Class: Chamomile::TextArea
- Inherits:
-
Object
- Object
- Chamomile::TextArea
- Defined in:
- lib/chamomile/components/text_area.rb,
lib/chamomile/components/text_area/key_map.rb
Overview
Multi-line text editor with cursor navigation, word wrapping, and line numbers.
Constant Summary collapse
- DEFAULT_KEY_MAP =
KeyBinding.normalize({ character_forward: [[:right, []], ["f", [:ctrl]]], character_backward: [[:left, []], ["b", [:ctrl]]], word_forward: [[:right, [:alt]], [:right, [:ctrl]], ["f", [:alt]]], word_backward: [[:left, [:alt]], [:left, [:ctrl]], ["b", [:alt]]], delete_word_backward: [[:backspace, [:alt]], ["w", [:ctrl]]], delete_word_forward: [[:delete, [:alt]], ["d", [:alt]]], delete_after_cursor: [["k", [:ctrl]]], delete_before_cursor: [["u", [:ctrl]]], delete_char_backward: [[:backspace, []], ["h", [:ctrl]]], delete_char_forward: [[:delete, []], ["d", [:ctrl]]], line_start: [[:home, []], ["a", [:ctrl]]], line_end: [[:end_key, []], ["e", [:ctrl]]], line_up: [[:up, []]], line_down: [[:down, []]], new_line: [[:enter, []]], input_begin: [[:home, [:ctrl]]], input_end: [[:end_key, [:ctrl]]], page_up: [[:page_up, []]], page_down: [[:page_down, []]], })
Instance Attribute Summary collapse
-
#char_limit ⇒ Object
Returns the value of attribute char_limit.
-
#col ⇒ Object
readonly
Returns the value of attribute col.
-
#end_of_buffer_char ⇒ Object
Returns the value of attribute end_of_buffer_char.
-
#height ⇒ Object
Returns the value of attribute height.
-
#key_map ⇒ Object
Returns the value of attribute key_map.
-
#max_height ⇒ Object
Returns the value of attribute max_height.
-
#max_width ⇒ Object
Returns the value of attribute max_width.
-
#placeholder ⇒ Object
Returns the value of attribute placeholder.
-
#prompt ⇒ Object
Returns the value of attribute prompt.
-
#row ⇒ Object
readonly
Returns the value of attribute row.
-
#show_line_numbers ⇒ Object
Returns the value of attribute show_line_numbers.
-
#width ⇒ Object
Returns the value of attribute width.
Instance Method Summary collapse
- #blur ⇒ Object
- #cursor_down ⇒ Object
- #cursor_end ⇒ Object
- #cursor_start ⇒ Object
- #cursor_up ⇒ Object
- #display_height ⇒ Object
- #focus ⇒ Object
- #focused? ⇒ Boolean
- #handle(msg) ⇒ Object (also: #update)
-
#initialize(width: 40, height: 6, key_map: DEFAULT_KEY_MAP, prompt: "", placeholder: "", char_limit: 0, show_line_numbers: false, end_of_buffer_char: "~") ⇒ TextArea
constructor
A new instance of TextArea.
- #insert_rune(c) ⇒ Object
- #insert_string(s) ⇒ Object
- #length ⇒ Object
- #line_count ⇒ Object
- #move_to_begin ⇒ Object
- #move_to_end ⇒ Object
- #page_down ⇒ Object
- #page_up ⇒ Object
- #reset ⇒ Object
- #value ⇒ Object
- #value=(s) ⇒ Object
- #view ⇒ Object
- #word ⇒ Object
Constructor Details
#initialize(width: 40, height: 6, key_map: DEFAULT_KEY_MAP, prompt: "", placeholder: "", char_limit: 0, show_line_numbers: false, end_of_buffer_char: "~") ⇒ TextArea
Returns a new instance of TextArea.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/chamomile/components/text_area.rb', line 11 def initialize(width: 40, height: 6, key_map: DEFAULT_KEY_MAP, prompt: "", placeholder: "", char_limit: 0, show_line_numbers: false, end_of_buffer_char: "~") @width = width @height = height @key_map = key_map @prompt = prompt @placeholder = placeholder @char_limit = char_limit @show_line_numbers = show_line_numbers @end_of_buffer_char = end_of_buffer_char @max_height = 0 @max_width = 0 @lines = [""] @row = 0 @col = 0 @offset = 0 @focused = false @last_char_offset = 0 end |
Instance Attribute Details
#char_limit ⇒ Object
Returns the value of attribute char_limit.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def char_limit @char_limit end |
#col ⇒ Object (readonly)
Returns the value of attribute col.
6 7 8 |
# File 'lib/chamomile/components/text_area.rb', line 6 def col @col end |
#end_of_buffer_char ⇒ Object
Returns the value of attribute end_of_buffer_char.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def end_of_buffer_char @end_of_buffer_char end |
#height ⇒ Object
Returns the value of attribute height.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def height @height end |
#key_map ⇒ Object
Returns the value of attribute key_map.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def key_map @key_map end |
#max_height ⇒ Object
Returns the value of attribute max_height.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def max_height @max_height end |
#max_width ⇒ Object
Returns the value of attribute max_width.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def max_width @max_width end |
#placeholder ⇒ Object
Returns the value of attribute placeholder.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def placeholder @placeholder end |
#prompt ⇒ Object
Returns the value of attribute prompt.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def prompt @prompt end |
#row ⇒ Object (readonly)
Returns the value of attribute row.
6 7 8 |
# File 'lib/chamomile/components/text_area.rb', line 6 def row @row end |
#show_line_numbers ⇒ Object
Returns the value of attribute show_line_numbers.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def show_line_numbers @show_line_numbers end |
#width ⇒ Object
Returns the value of attribute width.
7 8 9 |
# File 'lib/chamomile/components/text_area.rb', line 7 def width @width end |
Instance Method Details
#blur ⇒ Object
37 38 39 40 |
# File 'lib/chamomile/components/text_area.rb', line 37 def blur @focused = false self end |
#cursor_down ⇒ Object
83 84 85 86 87 88 89 |
# File 'lib/chamomile/components/text_area.rb', line 83 def cursor_down return if @row >= @lines.length - 1 @row += 1 @col = [@last_char_offset, @lines[@row].length].min clamp_offset end |
#cursor_end ⇒ Object
96 97 98 99 |
# File 'lib/chamomile/components/text_area.rb', line 96 def cursor_end @col = @lines[@row].length @last_char_offset = @col end |
#cursor_start ⇒ Object
91 92 93 94 |
# File 'lib/chamomile/components/text_area.rb', line 91 def cursor_start @col = 0 @last_char_offset = @col end |
#cursor_up ⇒ Object
75 76 77 78 79 80 81 |
# File 'lib/chamomile/components/text_area.rb', line 75 def cursor_up return if @row.zero? @row -= 1 @col = [@last_char_offset, @lines[@row].length].min clamp_offset end |
#display_height ⇒ Object
69 70 71 72 73 |
# File 'lib/chamomile/components/text_area.rb', line 69 def display_height return @height unless @max_height.positive? [@lines.length, @height].max.clamp(@height, @max_height) end |
#focus ⇒ Object
32 33 34 35 |
# File 'lib/chamomile/components/text_area.rb', line 32 def focus @focused = true self end |
#focused? ⇒ Boolean
42 43 44 |
# File 'lib/chamomile/components/text_area.rb', line 42 def focused? @focused end |
#handle(msg) ⇒ Object Also known as: update
171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/chamomile/components/text_area.rb', line 171 def handle(msg) return unless @focused case msg when Chamomile::KeyEvent handle_key(msg) when Chamomile::PasteEvent handle_paste(msg) end nil end |
#insert_rune(c) ⇒ Object
152 153 154 155 156 157 158 159 160 161 |
# File 'lib/chamomile/components/text_area.rb', line 152 def insert_rune(c) return if c == "\n" return if @char_limit.positive? && length >= @char_limit line = @lines[@row] @lines[@row] = line[0, @col].to_s + c + line[@col..].to_s @col += 1 @last_char_offset = @col end |
#insert_string(s) ⇒ Object
142 143 144 145 146 147 148 149 150 |
# File 'lib/chamomile/components/text_area.rb', line 142 def insert_string(s) s.each_char do |c| if c == "\n" split_line else insert_rune(c) end end end |
#length ⇒ Object
65 66 67 |
# File 'lib/chamomile/components/text_area.rb', line 65 def length value.length end |
#line_count ⇒ Object
61 62 63 |
# File 'lib/chamomile/components/text_area.rb', line 61 def line_count @lines.length end |
#move_to_begin ⇒ Object
101 102 103 104 105 106 |
# File 'lib/chamomile/components/text_area.rb', line 101 def move_to_begin @row = 0 @col = 0 @last_char_offset = 0 clamp_offset end |
#move_to_end ⇒ Object
108 109 110 111 112 113 |
# File 'lib/chamomile/components/text_area.rb', line 108 def move_to_end @row = @lines.length - 1 @col = @lines[@row].length @last_char_offset = @col clamp_offset end |
#page_down ⇒ Object
122 123 124 125 126 127 |
# File 'lib/chamomile/components/text_area.rb', line 122 def page_down rows = display_height @row = [@row + rows, @lines.length - 1].min @col = [@last_char_offset, @lines[@row].length].min clamp_offset end |
#page_up ⇒ Object
115 116 117 118 119 120 |
# File 'lib/chamomile/components/text_area.rb', line 115 def page_up rows = display_height @row = [@row - rows, 0].max @col = [@last_char_offset, @lines[@row].length].min clamp_offset end |
#reset ⇒ Object
163 164 165 166 167 168 169 |
# File 'lib/chamomile/components/text_area.rb', line 163 def reset @lines = [""] @row = 0 @col = 0 @offset = 0 @last_char_offset = 0 end |
#value ⇒ Object
46 47 48 |
# File 'lib/chamomile/components/text_area.rb', line 46 def value @lines.join("\n") end |
#value=(s) ⇒ Object
50 51 52 53 54 55 56 57 58 59 |
# File 'lib/chamomile/components/text_area.rb', line 50 def value=(s) s = s.to_s s = s[0, @char_limit] if @char_limit.positive? && s.length > @char_limit @lines = s.split("\n", -1) @lines = [""] if @lines.empty? @row = @row.clamp(0, @lines.length - 1) @col = @col.clamp(0, @lines[@row].length) @last_char_offset = @col clamp_offset end |
#view ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/chamomile/components/text_area.rb', line 186 def view return "#{@prompt}#{@placeholder}" if @lines == [""] && !@placeholder.empty? && !@focused view_h = display_height visible_lines = @lines[@offset, view_h] || [] rendered = visible_lines.each_with_index.map do |line, i| actual_row = @offset + i render_line(line, actual_row) end # Pad with end-of-buffer chars while rendered.length < view_h prefix = @show_line_numbers ? "#{" " * gutter_width} " : "" rendered << "#{@prompt}#{prefix}#{@end_of_buffer_char}" end rendered.join("\n") end |
#word ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/chamomile/components/text_area.rb', line 129 def word line = @lines[@row] return "" if line.empty? || @col >= line.length || line[@col] =~ /\s/ left = @col left -= 1 while left.positive? && line[left - 1] =~ /\S/ right = @col right += 1 while right < line.length && line[right] =~ /\S/ line[left...right] end |