Module: NattyUI::Features

Included in:
NattyUI, Element
Defined in:
lib/natty-ui/features.rb

Overview

These are all supported features by NattyUI or any other sub- element like #section, #message, #task, ...

Any printed text can contain BBCode-like embedded ANSI attributes which will be used when the output terminal supports attributes and colors.

Printing Methods collapse

Sub-Elements collapse

User Interaction collapse

Utilities collapse

Instance Method Details

#await(yes: 'Enter', no: 'Esc') ⇒ true, ... #await(yes: 'Enter', no: 'Esc') {|temp| ... } ⇒ true, ...

Wait for user input.

Examples:

Wait until user wants to coninue

ui.await { ui.puts '[faint][\\Press ENTER to continue...][/faint]' }

Ask yes/no-question

ui.await(yes: %w[j o t s y d Enter], no: %w[n Esc]) do
  ui.puts 'Do you like NayttUI?'
end
# => true, for user's YES
# => false, for user's NO
# Info:
# The keys will work for Afrikaans, Dutch, English, French, German,
# Italian, Polish, Portuguese, Romanian, Spanish and Swedish.

Overloads:

  • #await(yes: 'Enter', no: 'Esc') {|temp| ... } ⇒ true, ...

    Yield Parameters:

    • temp (Temporary)

      temporary displayed section (section will be erased after input)

Parameters:

  • yes (String, Enumerable<String>) (defaults to: 'Enter')

    key code/s a user can input to return positive result

  • no (String, Enumerable<String>) (defaults to: 'Esc')

    key code/s a user can input to return negative resault

Returns:

  • (true, false)

    whether the user inputs a positive result

  • (nil)

    in error case



802
803
804
805
806
807
808
# File 'lib/natty-ui/features.rb', line 802

def await(yes: 'Enter', no: 'Esc')
  return __await(yes, no) unless block_given?
  temporary do |temp|
    yield(temp)
    __await(yes, no)
  end
end

#choice(*choices, abortable: false) ⇒ Integer? #choice(*choices, abortable: false) {|temp| ... } ⇒ Integer? #choice(**choices, abortable: false) ⇒ Object? #choice(**choices, abortable: false) {|temp| ... } ⇒ Object?

Allows the user to select an option from a selection. The selected option is returned.

Overloads:

  • #choice(*choices, abortable: false) ⇒ Integer?

    Parameters:

    • choices (#to_s)

      one or more alternatives to select from

    • abortable (true, false) (defaults to: false)

      whether the user is allowed to abort with 'Esc' or 'Ctrl+c'

    Returns:

    • (Integer)

      index of selected choice

    • (nil)

      when user aborted the selection

  • #choice(*choices, abortable: false) {|temp| ... } ⇒ Integer?

    Examples:

    Request a fruit

    ui.choice('Apple', 'Banana', 'Orange') { ui.puts 'What do you prefer?' }
    # => 0, when user likes apples
    # => 1, when bananas are user's favorite
    # => 2, when user is a oranges lover
    

    Parameters:

    • choices (#to_s)

      one or more alternatives to select from

    • abortable (true, false) (defaults to: false)

      whether the user is allowed to abort with 'Esc' or 'Ctrl+c'

    Yield Parameters:

    • temp (Temporary)

      temporary displayed section (section will be erased after input)

    Returns:

    • (Integer)

      index of selected choice

    • (nil)

      when user aborted the selection

  • #choice(**choices, abortable: false) ⇒ Object?

    Parameters:

    • choices (#to_s)

      one or more alternatives to select from

    • abortable (true, false) (defaults to: false)

      whether the user is allowed to abort with 'Esc' or 'Ctrl+c'

    • selected (#to_s, nil)

      optionally pre-selected option

    Returns:

    • (Object)

      key for selected choice

    • (nil)

      when user aborted the selection

  • #choice(**choices, abortable: false) {|temp| ... } ⇒ Object?

    Examples:

    Request a preference

    ui.choice(
      k: 'Kitty',
      i: 'iTerm2',
      g: 'Ghostty',
      t: 'Tabby',
      r: 'Rio',
      abortable: true
    ) { ui.puts 'Which terminal emulator do you like?' }
    # => whether the user selected: :k, :i, :g, :t, :r
    # => nil, when the user aborted
    

    Parameters:

    • choices (#to_s)

      one or more alternatives to select from

    • abortable (true, false) (defaults to: false)

      whether the user is allowed to abort with 'Esc' or 'Ctrl+c'

    • selected (Integer)

      pre-selected option index

    Yield Parameters:

    • temp (Temporary)

      temporary displayed section (section will be erased after input)

    Returns:

    • (Object)

      key for selected choice

    • (nil)

      when user aborted the selection



884
885
886
887
888
889
890
891
892
893
# File 'lib/natty-ui/features.rb', line 884

def choice(*choices, abortable: false, selected: nil, **kwchoices, &block)
  return if choices.empty? && kwchoices.empty?
  choice =
    if Terminal.ansi?
      Choice.new(self, choices, kwchoices, abortable, selected)
    else
      DumbChoice.new(self, choices, kwchoices, abortable)
    end
  __with(choice) { choice.select(&block) }
end

#cols(*columns, **attributes) {|row| ... } ⇒ Features

Print text in columns. This is a shorthand to define a Table with a single row.

Parameters:

  • columns (#to_s)

    two or more convertible objects to print side by side

  • attributes ({Symbol => Object})

    attributes for the table and default attributes for table cells

Options Hash (**attributes):

  • :width (Integer) — default: nil

    width of a column, see Attributes::Width

  • :border (Symbol) — default: nil

    kind of border, see Table::Attributes

  • :border_style (Enumerable<Symbol>) — default: nil

    style of border, see Table::Attributes

  • :border_around (true, false) — default: false

    whether the table should have a border around, see Table::Attributes

  • :position (:left, :right, :centered) — default: false

    where to align the table, see Table::Attributes

Yield Parameters:

  • row (Table::Row)

    helper to define the row layout

Returns:



401
402
403
404
405
406
407
408
409
# File 'lib/natty-ui/features.rb', line 401

def cols(*columns, **attributes)
  tab_att, att = Utils.split_table_attr(attributes)
  table(**tab_att) do |table|
    table.add do |row|
      columns.each { row.add(_1, **att) }
      yield(row) if block_given?
    end
  end
end

#div(*text, **attributes) ⇒ Features

Print a text division with attributes. This is a shorthand to define a Table with a single cell.

Parameters:

  • attributes ({Symbol => Object})

    attributes for the division

  • text (#to_s)

    one or more convertible objects to print line by line

Options Hash (**attributes):

  • :align (:left, :right, :centered) — default: :left

    text alignment, see Attributes::Align

  • :padding (Integer, Enumerable<Integer>) — default: nil

    text padding, see Attributes::Padding

  • :style (Enumerable<Symbol>) — default: nil

    text style, see Attributes::Style

  • :width (Integer) — default: nil

    width of the cell, see Attributes::Width

  • :border (Symbol) — default: nil

    kind of border, see Table::Attributes

  • :border_style (Enumerable<Symbol>) — default: nil

    style of border, see Table::Attributes

  • :border_around (true, false) — default: false

    whether the table should have a border around, see Table::Attributes

  • :position (:left, :right, :centered) — default: false

    where to align the table, see Table::Attributes

Returns:



432
433
434
435
436
437
# File 'lib/natty-ui/features.rb', line 432

def div(*text, **attributes)
  return self if text.empty?
  tab_att, att = Utils.split_table_attr(attributes)
  tab_att[:border_around] = true
  table(**tab_att) { |table| table.add { _1.add(*text, **att) } }
end

#error(title, *text) {|section| ... } ⇒ Object Also known as: err

Create a visually separated section marked as an error with a title for the output of text elements.

Parameters:

  • title (#to_s)

    title to print as section head

  • text (#to_s)

    convertible objects to print line by line

Yield Parameters:

Returns:

  • (Object)

    the result of the given block

See Also:



712
# File 'lib/natty-ui/features.rb', line 712

def error(title, *text, &block) = __tsec(:error, title, text, &block)

#failed(title, *text) {|section| ... } ⇒ Object

Create a visually separated section marked as a failure with a title for the output of text elements.

Parameters:

  • title (#to_s)

    title to print as section head

  • text (#to_s)

    convertible objects to print line by line

Yield Parameters:

Returns:

  • (Object)

    the result of the given block

See Also:



719
# File 'lib/natty-ui/features.rb', line 719

def failed(title, *text, &block) = __tsec(:failed, title, text, &block)

#framed(*text, align: :left, border: :default, border_style: nil) {|frame| ... } ⇒ Object

Create a framed section.

Parameters:

  • align (:left, :right, :centered) (defaults to: :left)

    text alignment, see Attributes::Align

  • border (Symbol) (defaults to: :default)

    kind of border, see Attributes::Border

  • border_style (Enumerable<Symbol>) (defaults to: nil)

    style of border, see Attributes::BorderStyle

  • text (#to_s)

    convertible objects to print line by line

Yield Parameters:

  • frame (Framed)

    itself

Returns:

  • (Object)

    the result of the given block



737
738
739
740
741
742
743
744
745
746
747
748
# File 'lib/natty-ui/features.rb', line 737

def framed(*text, align: :left, border: :default, border_style: nil, &block)
  __with(
    Framed.new(
      self,
      Utils.align(align),
      Theme.current.border(border),
      Utils.style(border_style),
      text
    ),
    &block
  )
end

#h1(*text) ⇒ Features

Print given text as a H1 #heading.

Parameters:

  • text (#to_s)

    one or more convertible objects to print line by line

Returns:



256
# File 'lib/natty-ui/features.rb', line 256

def h1(*text) = heading(1, *text)

#h2(*text) ⇒ Features

Print given text as a H2 #heading.

Parameters:

  • text (#to_s)

    one or more convertible objects to print line by line

Returns:



263
# File 'lib/natty-ui/features.rb', line 263

def h2(*text) = heading(2, *text)

#h3(*text) ⇒ Features

Print given text as a H3 #heading.

Parameters:

  • text (#to_s)

    one or more convertible objects to print line by line

Returns:



270
# File 'lib/natty-ui/features.rb', line 270

def h3(*text) = heading(3, *text)

#h4(*text) ⇒ Features

Print given text as a H4 #heading.

Parameters:

  • text (#to_s)

    one or more convertible objects to print line by line

Returns:



277
# File 'lib/natty-ui/features.rb', line 277

def h4(*text) = heading(4, *text)

#h5(*text) ⇒ Features

Print given text as a H5 #heading.

Parameters:

  • text (#to_s)

    one or more convertible objects to print line by line

Returns:



284
# File 'lib/natty-ui/features.rb', line 284

def h5(*text) = heading(5, *text)

#h6(*text) ⇒ Features

Print given text as a H6 #heading.

Parameters:

  • text (#to_s)

    one or more convertible objects to print line by line

Returns:



291
# File 'lib/natty-ui/features.rb', line 291

def h6(*text) = heading(6, *text)

#hbars(values, min: nil, max: nil, normalize: false, text: true, width: :auto, style: nil, text_style: nil) ⇒ Features

Dump given values as horizontal bars.

Examples:

Draw green bars

ui.hbars 1..10, style: :green

Draw bars in half sreen width

ui.hbars 1..10, style: :blue, width: 0.5

Parameters:

  • values (#to_a, Array<Numeric>)

    values to print

  • min (#to_f) (defaults to: nil)

    start value

  • max (#to_f) (defaults to: nil)

    end value

  • normalize (true, false) (defaults to: false)

    whether the values should be normalized

  • text (true, false) (defaults to: true)

    whether the values should be printed too

  • width (:auto, :min, Integer) (defaults to: :auto)

    with of each bar

  • style (Symbol, Array<Symbol>, nil) (defaults to: nil)

    bar drawing style

  • text_style (Symbol, Array<Symbol>, nil) (defaults to: nil)

    text style

Returns:

Raises:

  • (ArgumentError)

    if any value is negative



499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
# File 'lib/natty-ui/features.rb', line 499

def hbars(
  values,
  min: nil,
  max: nil,
  normalize: false,
  text: true,
  width: :auto,
  style: nil,
  text_style: nil
)
  return self if (values = values.to_a).empty?
  if values.any?(&:negative?)
    raise(ArgumentError, 'values can not be negative')
  end
  style = text_style = nil unless Terminal.ansi?
  renderer = HBarsRenderer.new(values, min, max)
  renderer.with_text(text_style) if text
  puts(*renderer.lines(Utils.as_size(3..columns, width), style, normalize))
end

#heading(level, *text) ⇒ Features

Print given text as a heading.

There are specific shortcuts for heading levels: #h1, #h2, #h3, #h4, #h5, #h6.

Examples:

Print a level 1 heading

ui.heading(1, 'This is a H1 heading element')
# => ╴╶╴╶─═══ This is a H1 heading element ═══─╴╶╴╶

Parameters:

  • level (#to_i)

    heading level, one of 1..6

  • text (#to_s)

    one or more convertible objects to print line by line

Returns:



238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/natty-ui/features.rb', line 238

def heading(level, *text)
  prefix, suffix = Theme.current.heading(level)
  puts(
    *text,
    max_width: columns,
    prefix: prefix,
    prefix_width: prefix.width,
    suffix: suffix,
    suffix_width: suffix.width,
    align: :centered
  )
end

#hr(type = :default) ⇒ Features

Print a horizontal rule.

Examples:

Print double line

ui.hr :double

Parameters:

  • type (Symbol) (defaults to: :default)

    border type

Returns:



302
303
304
305
306
# File 'lib/natty-ui/features.rb', line 302

def hr(type = :default)
  theme = Theme.current
  bc = theme.border(type)[10]
  puts("#{theme.heading_sytle}#{bc * columns}")
end

#information(title, *text) {|section| ... } ⇒ Object Also known as: info

Create a visually separated section marked as informational with a title for the output of text elements.

Parameters:

  • title (#to_s)

    title to print as section head

  • text (#to_s)

    convertible objects to print line by line

Yield Parameters:

Returns:

  • (Object)

    the result of the given block

See Also:



696
697
698
# File 'lib/natty-ui/features.rb', line 696

def information(title, *text, &block)
  __tsec(:information, title, text, &block)
end

#ls(*items, compact: true, glyph: nil) ⇒ Features

Print given items as list (like 'ls' command).

Each list item will optionally be decorated with the given glyph as:

  • Integer as the start value for a numbered list
  • Symbol as the start symbol
  • :hex to create a hexadecimal numbered list
  • any text as prefix

Examples:

Print all Ruby files as a numbered list

ui.ls Dir['*/**/*.rb'], glyph: 1

Print all Ruby files as a bullet point list (with green bullets)

ui.ls Dir['*/**/*.rb'], glyph: '[green]•[/fg]'

Parameters:

  • items (#to_s)

    one or more convertible objects to list

  • compact (true, false) (defaults to: true)

    whether the compact display format should be used

  • glyph (Integer, :hex, Symbol, #to_s) (defaults to: nil)

    glyph to be used as prefix

Returns:



341
342
343
344
345
# File 'lib/natty-ui/features.rb', line 341

def ls(*items, compact: true, glyph: nil)
  return self if items.empty?
  renderer = compact ? CompactLSRenderer : LSRenderer
  puts(*renderer.lines(items, glyph, columns))
end

#mark(*text, mark: :default, **options) ⇒ Features

Print given text with a decoration mark.

Parameters:

  • mark (Symbol, #to_s) (defaults to: :default)

    marker type

  • text (#to_s)

    one or more convertible objects to print line by line

Returns:



177
178
179
180
181
182
# File 'lib/natty-ui/features.rb', line 177

def mark(*text, mark: :default, **options)
  mark = Theme.current.mark(mark)
  options[:first_line_prefix] = mark
  options[:first_line_prefix_width] = mark.width
  puts(*text, **options)
end

#message(title, *text) {|section| ... } ⇒ Object Also known as: msg

Create a visually separated section with a title for the output of text elements.

Parameters:

  • title (#to_s)

    title to print as section head

  • text (#to_s)

    convertible objects to print line by line

Yield Parameters:

Returns:

  • (Object)

    the result of the given block

See Also:



689
# File 'lib/natty-ui/features.rb', line 689

def message(title, *text, &block) = __sec(:message, title, text, &block)

#options(abortable: false, selected: nil, **choices) {|temp| ... } ⇒ {#to_s => [true,false]}?

Allows the user to select from several options. All options are returned with their selection status.

Parameters:

  • choices ({#to_s => [true,false]})

    Hash of options and their selection state

  • abortable (true, false) (defaults to: false)

    whether the user is allowed to abort with 'Esc' or 'Ctrl+c'

  • selected (#to_s, nil) (defaults to: nil)

    optionally pre-selected key

Yield Parameters:

  • temp (Temporary)

    temporary displayed section (section will be erased after input)

Returns:

  • ({#to_s => [true,false]})

    Hash of options and their selection state

  • (nil)

    when user aborted the selection



912
913
914
915
916
917
918
919
920
921
# File 'lib/natty-ui/features.rb', line 912

def options(abortable: false, selected: nil, **choices, &block)
  return {} if choices.empty?
  options =
    if Terminal.ansi?
      Options.new(self, choices, abortable, selected)
    else
      DumbOptions.new(self, choices, abortable, selected)
    end
  __with(options) { options.select(&block) }
end

#pin(*text, mark: nil, **options) ⇒ Features

Print given text as lines like #puts. Used in elements with temporary output like #task the text will be kept ("pinned").

It can optionally have a decoration marker in first line like #mark.

Examples:

Print two lines decorated as information which are pinned

ui.task 'Do something important' do |task|
  # ...
  task.pin("This is text", "which is pinned", mark: :information)
  # ...
end
# => ✓ Do something important
# =>   𝒊 This is text
# =>     which is pinned.

Parameters:

  • text (#to_s)

    one or more convertible objects to print line by line

  • options ({Symbol => Object})
  • mark (Symbol, #to_s) (defaults to: nil)

    marker type

Options Hash (**options):

  • :align (:left, :right, :centered) — default: :left

    text alignment

  • :eol (true, false) — default: true

    whether to respect newline characters

Returns:



204
205
206
# File 'lib/natty-ui/features.rb', line 204

def pin(*text, mark: nil, **options)
  mark(*text, mark: mark, pin: true, **options)
end

#progress(title, max: nil, pin: false) ⇒ ProgressHelper #progress(title, max: nil, pin: false) {|progress| ... } ⇒ Object

Dynamically display a task progress. When a max parameter is given the progress will be displayed as a progress bar below the title. Otherwise the progress is displayed just by accumulating dots.

Examples:

Display a progress bar

ui.progress('Download file', max: 1024) do |progress|
  while progress.value < progress.max
    # just to simulate the download
    sleep(0.1)
    bytes_read = rand(10..128)

    # here we actualize the progress
    progress.value += bytes_read
  end
end

Display simple progress

progress = ui.progress 'Check some stuff'
10.times do
  # simulate some work
  sleep 0.1

  # here we actualize the progress
  progress.step
end
progress.ok 'Stuff checked ok'

Overloads:

  • #progress(title, max: nil, pin: false) ⇒ ProgressHelper

    Returns itself.

    Parameters:

    • title (#to_s)

      title text to display

    • max (#to_f) (defaults to: nil)

      expected maximum value

    • pin (true, false) (defaults to: false)

      whether the final progress state should be "pinned" to parent element

    Returns:

  • #progress(title, max: nil, pin: false) {|progress| ... } ⇒ Object

    Returns the result of the given block.

    Parameters:

    • title (#to_s)

      title text

    • max (#to_f) (defaults to: nil)

      expected maximum value

    • pin (true, false) (defaults to: false)

      whether the final progress state should be "pinned" to parent element

    Yield Parameters:

    Returns:

    • (Object)

      the result of the given block



571
572
573
574
575
576
577
578
579
# File 'lib/natty-ui/features.rb', line 571

def progress(title, max: nil, pin: false, &block)
  progress =
    if Terminal.ansi?
      Progress.new(self, title, max, pin)
    else
      DumbProgress.new(self, title, max)
    end
  block ? __with(progress, &block) : progress
end

#puts(*text, **options) ⇒ Features

Print given text as lines.

Examples:

Print two lines text, right aligned

ui.puts "Two lines", "of nice text", align: :right
# =>    Two lines
# => of nice text

Print two lines text, with a prefix

ui.puts "Two lines", "of nice text", prefix: ': '
# => : Two lines
# => : of nice text

Parameters:

  • text (#to_s)

    one or more convertible objects to print line by line

  • options ({Symbol => Object})

Options Hash (**options):

  • :align (:left, :right, :centered) — default: :left

    text alignment

  • :eol (true, false) — default: true

    whether to respect newline characters

Returns:

See Also:



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/natty-ui/features.rb', line 39

def puts(*text, **options)
  if options.empty?
    bbcode = true
    max_width = Terminal.columns
  else
    bbcode = true if (bbcode = options[:bbcode]).nil?
    ignore_newline = options[:eol] == false || options[:ignore_newline]

    if (max_width = options[:max_width]).nil?
      return self if (max_width = Terminal.columns).zero?
    elsif max_width < 1
      if max_width > 0
        max_width *= Terminal.columns
      elsif max_width < 0
        max_width += Terminal.columns
      else
        return self
      end
    end

    prefix_width =
      if (prefix = options[:prefix])
        prefix = Ansi.bbcode(prefix) if bbcode
        options[:prefix_width] || Text.width(prefix, bbcode: false)
      else
        0
      end

    if (first_line = options[:first_line_prefix])
      first_line = Ansi.bbcode(first_line) if bbcode
      first_line_width =
        options[:first_line_prefix_width] ||
          Text.width(first_line, bbcode: false)

      if prefix_width < first_line_width
        prefix_next = "#{prefix}#{' ' * (first_line_width - prefix_width)}"
        prefix = first_line
        prefix_width = first_line_width
      else
        prefix_next = prefix
        prefix =
          if first_line_width < prefix_width
            first_line + (' ' * (prefix_width - first_line_width))
          else
            first_line
          end
      end
    end

    max_width -= prefix_width

    if (suffix = options[:suffix])
      suffix = Ansi.bbcode(suffix) if bbcode
      max_width -=
        options[:suffix_width] || Text.width(suffix, bbcode: false)
    end
  end

  return self if max_width <= 0

  lines =
    Text.each_line_with_size(
      *text,
      limit: max_width,
      bbcode: bbcode,
      ansi: Terminal.ansi?,
      ignore_newline: ignore_newline
    )
  tail = options[:tail] and lines = lines.to_a.last(tail)
  @__eol ||= Terminal.ansi? ? "\e[m\n" : "\n"

  if (align = options[:align]).nil?
    lines.each do |line, _|
      Terminal.print(prefix, line, suffix, @__eol, bbcode: false)
      @lines_written += 1
      prefix, prefix_next = prefix_next, nil if prefix_next
    end
    return self
  end

  unless options[:expand]
    lines = lines.to_a
    max_width = lines.max_by(&:last).last
  end

  case align
  when :right
    lines.each do |line, width|
      Terminal.print(
        prefix,
        ' ' * (max_width - width),
        line,
        suffix,
        @__eol,
        bbcode: false
      )
      @lines_written += 1
      prefix, prefix_next = prefix_next, nil if prefix_next
    end
  when :centered
    lines.each do |line, width|
      space = max_width - width
      Terminal.print(
        prefix,
        ' ' * (lw = space / 2),
        line,
        ' ' * (space - lw),
        suffix,
        @__eol,
        bbcode: false
      )
      @lines_written += 1
      prefix, prefix_next = prefix_next, nil if prefix_next
    end
  else
    lines.each do |line, width|
      Terminal.print(
        prefix,
        line,
        ' ' * (max_width - width),
        suffix,
        @__eol,
        bbcode: false
      )
      @lines_written += 1
      prefix, prefix_next = prefix_next, nil if prefix_next
    end
  end
  self
end

#quote(*text) ⇒ Features

Print given text as a quotation.

Parameters:

  • text (#to_s)

    one or more convertible objects to print line by line

Returns:



213
214
215
216
217
218
219
220
221
222
# File 'lib/natty-ui/features.rb', line 213

def quote(*text)
  width = columns * 0.75
  quote = Theme.current.mark(:quote)
  puts(
    *text,
    prefix: quote,
    prefix_width: quote.width,
    max_width: width < 20 ? nil : width.round
  )
end

#run(*cmd, preserve_spaces: false, max_lines: 10, **options) ⇒ [Process::Status, Array<String>, Array<String>]?

Execute a shell program and return output. Limit the lines displayed.

Examples:

Capture output and error

status, out, err = ui.run('ls ./ && ls ./this_does_not_exist')
# => #<Process::Status: pid 25562 exit 1>
# => [...] # the output of first `ls`
# => ["ls: ./this_does_not_exist: No such file or directory"]

Parameters:

  • cmd (String)

    command and optional arguments

  • preserve_spaces (true, false) (defaults to: false)

    whether the spaces and tabs of the output should be preserve

  • max_lines (Integer) (defaults to: 10)

    limit of displayed lines

  • options (Hash)

    executions options

Returns:

  • ([Process::Status, Array<String>, Array<String>])

    process status, output and error output when command was executed

  • (nil)

    in error case (like command not found)

See Also:



630
631
632
633
634
635
636
637
638
639
640
# File 'lib/natty-ui/features.rb', line 630

def run(*cmd, preserve_spaces: false, max_lines: 10, **options)
  result =
    ShellRenderer.run(
      self,
      cmd,
      options,
      preserve_spaces,
      max_lines.clamp(1, Terminal.rows)
    )
  result if result[0]
end

#section(*text) {|section| ... } ⇒ Object

Create a visually separated section for the output of text elements. Like any other Element sections support all NattyUI::Features.

Examples:

ui.section do |section|
  section.h1 'About Sections'
  section.space
  section.puts 'Sections are areas of text elements.'
  section.puts 'You can use any other feature inside such an area.'
end
# => ╭────╶╶╶
# => │ ╴╶╴╶─═══ About Sections ═══─╴╶╴╶
# => │
# => │ Sections are areas of text elements.
# => │ You can use any other feature inside such an area.
# => ╰──── ─╶╶╶

Parameters:

  • text (#to_s)

    convertible objects to print line by line

Yield Parameters:

Returns:

  • (Object)

    the result of the given block



675
# File 'lib/natty-ui/features.rb', line 675

def section(*text, &block) = __sec(:default, nil, text, &block)

#select(*choices, abortable: false, selected: nil) {|temp| ... } ⇒ Array<#to_s>?

Allows the user to select from several options. The selected options are returned.

Examples:

Select a terminal

ui.select %w[Kitty iTerm2 Ghostty Tabby Rio] do
 ui.puts '[i]Which terminal applications did you already tested?[/i]'
end

Parameters:

  • choices (Array<#to_s>)

    selectable options

  • abortable (true, false) (defaults to: false)

    whether the user is allowed to abort with 'Esc' or 'Ctrl+c'

  • selected (Integer, :all, nil) (defaults to: nil)

    optionally pre-selected option index or :all to pre-select all items

Yield Parameters:

  • temp (Temporary)

    temporary displayed section (section will be erased after input)

Returns:

  • (Array<#to_s>)

    selected options

  • (nil)

    when user aborted the selection



944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
# File 'lib/natty-ui/features.rb', line 944

def select(*choices, abortable: false, selected: nil, &block)
  return [] if choices.empty?
  choices = choices[0] if choices.size == 1 && choices[0].is_a?(Enumerable)
  if selected == :all
    sel = true
  elsif selected
    selected = choices[selected.to_i]
  end
  options(
    abortable: abortable,
    selected: selected,
    **choices.to_h { [_1, sel] },
    &block
  ).filter_map { |key, selected| key if selected }
end

#sh(*cmd, preserve_spaces: false, **options) ⇒ Process::Status?

Execute a program.

Examples:

Execute a simple command

ui.sh 'ls'

Execute a command wih arguments

ret = ui.sh('curl', '--version')
raise('Curl not found') unless ret&.success?

Execute shell commands

ui.sh "mkdir 'test' && cd 'test'"

Execute a command with environment variables

ui.sh({'ENV' => 'test'}, 'rails')

Parameters:

  • cmd (String)

    command and optional arguments

  • preserve_spaces (true, false) (defaults to: false)

    whether the spaces and tabs of the output should be preserve

  • options (Hash)

    executions options

Returns:

  • (Process::Status)

    when command was executed

  • (nil)

    in error case (like command not found)

See Also:



605
606
607
# File 'lib/natty-ui/features.rb', line 605

def sh(*cmd, preserve_spaces: false, **options)
  ShellRenderer.sh(self, cmd, options, preserve_spaces)
end

#space(count = 1) ⇒ Features

Print one or more space lines.

Parameters:

  • count (#to_i) (defaults to: 1)

    lines to print

Returns:



314
315
316
# File 'lib/natty-ui/features.rb', line 314

def space(count = 1)
  (count = count.to_i).positive? ? puts("\n" * count) : self
end

#table(**attributes) {|table| ... } ⇒ Features

Generate and print a table. See Table for much more details about table generation.

Examples:

Draw a very simple 3x4 table with complete borders

ui.table(border: :default, border_around: true, padding: [0, 1]) do |table|
  table.add 1, 2, 3, 4
  table.add 5, 6, 7, 8
  table.add 9, 10, 11, 12
end

Parameters:

  • attributes ({Symbol => Object})

    attributes for the table and default attributes for table cells

Options Hash (**attributes):

  • :border (Symbol) — default: nil

    kind of border, see Table::Attributes

  • :border_style (Enumerable<Symbol>) — default: nil

    style of border, see Table::Attributes

  • :border_around (true, false) — default: false

    whether the table should have a border around, see Table::Attributes

  • :position (:left, :right, :centered) — default: false

    where to align the table, see Table::Attributes

Yield Parameters:

  • table (Table)

    helper to define the table layout

Returns:



376
377
378
379
380
381
382
383
384
# File 'lib/natty-ui/features.rb', line 376

def table(**attributes)
  return self unless block_given?
  yield(table = Table.new(**attributes))
  puts(
    *TableRenderer[table, columns],
    align: table.attributes.position,
    expand: true
  )
end

#task(title, *text, pin: false) {|task| ... } ⇒ Object

Generate a task section.

Parameters:

  • title (#to_s)

    task title text

  • pin (true, false) (defaults to: false)

    whether to keep text "pinned"

  • text (#to_s)

    convertible objects to print line by line

Yield Parameters:

  • task (Task)

    itself

Returns:

  • (Object)

    the result of the given block



760
761
762
# File 'lib/natty-ui/features.rb', line 760

def task(title, *text, pin: false, &block)
  __with(Task.new(self, title, text, pin), &block)
end

#temporary {|temp| ... } ⇒ Object

Display some temporary content. The content displayed in the block will be erased after the block ends.

Examples:

Show tempoary information

ui.temporary do
  ui.info 'Information', 'This text will disappear when you pressed ENTER.'
  ui.await
end

Yield Parameters:

Returns:

  • (Object)

    the result of the given block



984
# File 'lib/natty-ui/features.rb', line 984

def temporary(&block) = __with(Temporary.new(self), &block)

#vbars(values, normalize: false, height: 10, bar_width: :auto, style: nil) ⇒ Features

Dump given values as vertical bars.

Examples:

Draw green bars

ui.vbars 1..10, style: :green

Draw very big bars

ui.vbars 1..10, bar_width: 5, height: 20

Parameters:

  • values (#to_a, Array<Numeric>)

    values to print

  • normalize (true, false) (defaults to: false)

    whether the values should be normalized

  • height (Integer) (defaults to: 10)

    output height

  • bar_width (:auto, :min, Integer) (defaults to: :auto)

    with of each bar

  • style (Symbol, Array<Symbol>, nil) (defaults to: nil)

    drawing style

Returns:

Raises:

  • (ArgumentError)

    if any value is negative



456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
# File 'lib/natty-ui/features.rb', line 456

def vbars(
  values,
  normalize: false,
  height: 10,
  bar_width: :auto,
  style: nil
)
  return self if (values = values.to_a).empty?
  if values.any?(&:negative?)
    raise(ArgumentError, 'values can not be negative')
  end
  puts(
    *VBarsRenderer.lines(
      values,
      columns,
      height,
      normalize,
      bar_width,
      Terminal.ansi? ? style : nil
    )
  )
end

#warning(title, *text) {|section| ... } ⇒ Object Also known as: warn

Create a visually separated section marked as a warning with a title for the output of text elements.

Parameters:

  • title (#to_s)

    title to print as section head

  • text (#to_s)

    convertible objects to print line by line

Yield Parameters:

Returns:

  • (Object)

    the result of the given block

See Also:



705
# File 'lib/natty-ui/features.rb', line 705

def warning(title, *text, &block) = __tsec(:warning, title, text, &block)