Class: GTK::Console::Prompt

Inherits:
Object show all
Defined in:
dragon/console_prompt.rb

Constant Summary collapse

WORD_LIMITER_CHARS =

? Can be changed, it was just taken from my editor settings :>

"`[email protected]#$%^&*-=+()[]{}\|;:'\",.<>/?_ \t\n\0".chars

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(font_style:, text_color:, console_text_width:) ⇒ Prompt

Returns a new instance of Prompt.


16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'dragon/console_prompt.rb', line 16

def initialize(font_style:, text_color:, console_text_width:)
  @prompt = '-> '
  @current_input_str = ''
  @font_style = font_style
  @text_color = text_color
  @cursor_color = Color.new [187, 21, 6]
  @console_text_width = console_text_width

  @cursor_position = 0
  update_cursor_position_px

  @last_autocomplete_prefix = nil
  @next_candidate_index = 0
end

Instance Attribute Details

#console_text_widthObject

Returns the value of attribute console_text_width


14
15
16
# File 'dragon/console_prompt.rb', line 14

def console_text_width
  @console_text_width
end

#current_input_strObject

Returns the value of attribute current_input_str


14
15
16
# File 'dragon/console_prompt.rb', line 14

def current_input_str
  @current_input_str
end

#font_styleObject

Returns the value of attribute font_style


14
15
16
# File 'dragon/console_prompt.rb', line 14

def font_style
  @font_style
end

#last_input_strObject

Returns the value of attribute last_input_str


14
15
16
# File 'dragon/console_prompt.rb', line 14

def last_input_str
  @last_input_str
end

#last_input_str_changedObject

Returns the value of attribute last_input_str_changed


14
15
16
# File 'dragon/console_prompt.rb', line 14

def last_input_str_changed
  @last_input_str_changed
end

Instance Method Details

#<<(str) ⇒ Object


41
42
43
44
45
46
47
# File 'dragon/console_prompt.rb', line 41

def <<(str)
  @current_input_str = @current_input_str[0...@cursor_position] + str + @current_input_str[@cursor_position..-1]
  @cursor_position += str.length
  update_cursor_position_px
  @current_input_changed_at = Kernel.global_tick_count
  reset_autocomplete
end

#autocompleteObject


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'dragon/console_prompt.rb', line 116

def autocomplete
  if !@last_autocomplete_prefix
    @last_autocomplete_prefix = calc_autocomplete_prefix

    puts "* AUTOCOMPLETE CANDIDATES: #{current_input_str}.."
    pretty_print_strings_as_table method_candidates(@last_autocomplete_prefix)
  else
    candidates = method_candidates(@last_autocomplete_prefix)
    return if candidates.empty?

    candidate = candidates[@next_candidate_index]
    candidate = candidate[0..-2] + " = " if candidate.end_with? '='
    @next_candidate_index += 1
    @next_candidate_index = 0 if @next_candidate_index >= candidates.length
    self.current_input_str = display_autocomplete_candidate(candidate)
    update_cursor_position_px
  end
rescue Exception => e
  puts "* BUG: Tab autocompletion failed. Let us know about this.\n#{e}"
end

#backspaceObject


49
50
51
52
53
54
55
56
# File 'dragon/console_prompt.rb', line 49

def backspace
  return if current_input_str.length.zero? || @cursor_position.zero?

  @current_input_str = @current_input_str[0...(@cursor_position - 1)] + @current_input_str[@cursor_position..-1]
  @cursor_position -= 1
  update_cursor_position_px
  reset_autocomplete
end

#clearObject


109
110
111
112
113
114
# File 'dragon/console_prompt.rb', line 109

def clear
  @current_input_str = ''
  @cursor_position = 0
  update_cursor_position_px
  reset_autocomplete
end

#deleteObject


58
59
60
61
62
63
# File 'dragon/console_prompt.rb', line 58

def delete
  return if current_input_str.length.zero? || @cursor_position == current_input_str.length

  @cursor_position += 1
  backspace
end

#move_cursor_endObject


104
105
106
107
# File 'dragon/console_prompt.rb', line 104

def move_cursor_end
  @cursor_position = str_len
  update_cursor_position_px
end

#move_cursor_homeObject


99
100
101
102
# File 'dragon/console_prompt.rb', line 99

def move_cursor_home
  @cursor_position = 0
  update_cursor_position_px
end

#move_cursor_leftObject


65
66
67
68
# File 'dragon/console_prompt.rb', line 65

def move_cursor_left
  @cursor_position -= 1 if @cursor_position > 0
  update_cursor_position_px
end

#move_cursor_left_wordObject


70
71
72
73
74
75
76
77
78
79
80
# File 'dragon/console_prompt.rb', line 70

def move_cursor_left_word
  return if @cursor_position.zero?

  new_pos = @cursor_position - 1
  (is_word_boundary? @current_input_str[new_pos]) ? 
      (new_pos -= 1 until !(is_word_boundary? @current_input_str[new_pos - 1]) || new_pos.zero?):
      (new_pos -= 1 until (is_word_boundary? @current_input_str[new_pos - 1]) || new_pos.zero?)

  @cursor_position = new_pos
  update_cursor_position_px
end

#move_cursor_rightObject


82
83
84
85
# File 'dragon/console_prompt.rb', line 82

def move_cursor_right
  @cursor_position += 1 if @cursor_position < current_input_str.length
  update_cursor_position_px
end

#move_cursor_right_wordObject


87
88
89
90
91
92
93
94
95
96
97
# File 'dragon/console_prompt.rb', line 87

def move_cursor_right_word
  return if @cursor_position.equal? str_len

  new_pos = @cursor_position + 1
  (is_word_boundary? @current_input_str[new_pos]) ?
      (new_pos += 1 until !(is_word_boundary? @current_input_str[new_pos]) || (new_pos.equal? str_len)):
      (new_pos += 1 until (is_word_boundary? @current_input_str[new_pos]) || (new_pos.equal? str_len))
  
  @cursor_position = new_pos
  update_cursor_position_px
end

#pretty_print_row(cells, string_width, cell_width, column_width, columns) ⇒ Object


168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'dragon/console_prompt.rb', line 168

def pretty_print_row cells, string_width, cell_width, column_width, columns
  # if the number of cells doesn't match the number of columns, then pad the array with empty values
  cells += (columns - cells.length).map { "" }

  # right align each cell value
  formated_row = "|" + cells.map do |c|
    "#{" " * (string_width.length - c.length) } #{c} |"
  end.join

  # remove separators between empty values
  formated_row = formated_row.gsub("  |  ", "     ")

  puts formated_row
end

#pretty_print_row_separator(string_width, cell_width, column_width, columns) ⇒ Object


183
184
185
186
187
188
189
# File 'dragon/console_prompt.rb', line 183

def pretty_print_row_separator string_width, cell_width, column_width, columns
  # this is a joint: +--------
  column_joint = "+#{"-" * cell_width}"

  # multiple joints create a row separator: +----+----+
  puts (column_joint * columns) + "+"
end

#pretty_print_strings_as_table(items) ⇒ Object


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
# File 'dragon/console_prompt.rb', line 137

def pretty_print_strings_as_table items
  if items.length == 0
    puts <<-S.strip
+--------+
| (none) |
+--------+
S
  else
    # figure out the largest string
    string_width = items.sort_by { |c| -c.to_s.length }.first

    # add spacing to each side of the string which represents the cell width
    cell_width = string_width.length + 2

    # add spacing to each side of the cell to represent the column width
    column_width = cell_width + 2

    # determine the max number of columns that can fit on the screen
    columns = @console_text_width.idiv column_width
    columns = items.length if items.length < columns

    # partition the original list of items into a string to be printed
    items.each_slice(columns).each_with_index do |cells, i|
      pretty_print_row_separator string_width, cell_width, column_width, columns
      pretty_print_row cells, string_width, cell_width, column_width, columns
    end

    pretty_print_row_separator string_width, cell_width, column_width, columns
  end
end

#render(args, x:, y:) ⇒ Object


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'dragon/console_prompt.rb', line 191

def render(args, x:, y:)
  args.outputs.reserved << font_style.label(x: x, y: y, text: "#{@prompt}#{current_input_str}", color: @text_color)
  args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 0.5,
                                                     y: y + 5,
                                                     x2: x + @cursor_position_px + 0.5,
                                                     y2: y + @font_style.letter_size.y + 5)

  args.outputs.reserved << (@cursor_color.to_h.merge x: x + @cursor_position_px + 1,
                                                     y: y + 5,
                                                     x2: x + @cursor_position_px + 1,
                                                     y2: y + @font_style.letter_size.y + 5)

  # debugging rectangle for string
  # args.outputs.reserved << (@cursor_color.to_h.merge x: x,
  #                                                    y: y + 5,
  #                                                    w: @cursor_position_px,
  #                                                    h: @font_style.letter_size.y).border
end

#tickObject


210
211
212
213
214
215
216
217
218
219
220
# File 'dragon/console_prompt.rb', line 210

def tick
  if (@current_input_changed_at) &&
     (@current_input_changed_at < Kernel.global_tick_count) &&
     (@last_input_str != @current_input_str)
    @last_input_str_changed = true
    @last_input_str = "#{@current_input_str}"
    @current_input_changed_at = nil
  else
    @last_input_str_changed = false
  end
end

#update_cursor_position_pxObject


31
32
33
# File 'dragon/console_prompt.rb', line 31

def update_cursor_position_px
  @cursor_position_px = ($gtk.calcstringbox (@prompt + @current_input_str[0...@cursor_position]), @font_style.size_enum, @font_style.font).x
end