Class: Coolline::Menu

Inherits:
Object
  • Object
show all
Includes:
ANSI
Defined in:
lib/coolline/menu.rb

Overview

A menu allows to display some information on a rectangle below the cursor.

It displays a string or a list of strings until the user presses another key.

Constant Summary

Constants included from ANSI

ANSI::Code

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ANSI

#ansi_length, #ansi_print, #clear_screen, #erase_line, #go_to, #go_to_col, #go_to_next_line, #go_to_previous_line, #reset_color, #reset_line, #start_with_ansi_code?, #strip_ansi_codes

Constructor Details

#initialize(input, output) ⇒ Menu

Returns a new instance of Menu.



9
10
11
12
13
14
15
16
# File 'lib/coolline/menu.rb', line 9

def initialize(input, output)
  @input  = input
  @output = output

  @string = ""

  @last_line_count = 0
end

Instance Attribute Details

#stringString

Returns Information to be displayed.

Returns:

  • (String)

    Information to be displayed



19
20
21
# File 'lib/coolline/menu.rb', line 19

def string
  @string
end

Instance Method Details

#displayObject

Renders the menu below the current line.

This will ensure not to draw to much, so that the line currently being edited will always stay visible.

Once the menu is drawn, the cursor returns to the correct line.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/coolline/menu.rb', line 49

def display
  # An empty string shouldn't be treated like a 1-line string.
  return if @string.empty?

  height, width = @input.winsize

  lines = @string.lines.to_a

  lines[0, height - 1].each do |line|
    print "\n\r"
    ansi_print(line.chomp, 0, width)
  end
  reset_color

  [lines.size, height].min.times { go_to_previous_line }

  @last_line_count = [height - 1, lines.size].min
end

#eraseObject

Erases anything that had been written by the menu.

This allows to hide the menu once it is no longer relevant.

Notice it can only work by knowing how many lines the menu drew on the screen last time it was called, and assuming the terminal size didn’t change.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/coolline/menu.rb', line 75

def erase
  return if @last_line_count.zero?

  self.string = ""

  @last_line_count.times do
    go_to_next_line
    erase_line
  end
  reset_color

  @last_line_count.times { go_to_previous_line }

  @last_line_count = 0
end

#list=(items) ⇒ Object

Sets the menu’s string to a list of items, formatted in columns.

If some items are to wide to be showed, they will be excluded from the list.

Parameters:

  • items (Array<String>)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/coolline/menu.rb', line 27

def list=(items)
  height, width = @input.winsize

  items = items.reject { |s| ansi_length(s) > width }

  if items.empty?
    self.string = ""
  else
    col_width  = items.map { |s| ansi_length(s) }.max
    col_count  = width / col_width
    item_count = col_count * (height - 1)

    self.string = format_columns(items[0, item_count], col_count, col_width)
  end
end