class Chamomile::TextArea
Multi-line text editor with cursor navigation, word wrapping, and line numbers.
Constants
- DEFAULT_KEY_MAP
Attributes
Public Class Methods
Source
# 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
Public Instance Methods
Source
# File lib/chamomile/components/text_area.rb, line 37 def blur @focused = false self end
Source
# 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
Source
# File lib/chamomile/components/text_area.rb, line 96 def cursor_end @col = @lines[@row].length @last_char_offset = @col end
Source
# File lib/chamomile/components/text_area.rb, line 91 def cursor_start @col = 0 @last_char_offset = @col end
Source
# 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
Source
# 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
Source
# File lib/chamomile/components/text_area.rb, line 32 def focus @focused = true self end
Source
# 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
Also aliased as: update
Source
# 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
Source
# 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
Source
# File lib/chamomile/components/text_area.rb, line 61 def line_count @lines.length end
Source
# File lib/chamomile/components/text_area.rb, line 101 def move_to_begin @row = 0 @col = 0 @last_char_offset = 0 clamp_offset end
Source
# 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
Source
# 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
Source
# 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
Source
# File lib/chamomile/components/text_area.rb, line 163 def reset @lines = [""] @row = 0 @col = 0 @offset = 0 @last_char_offset = 0 end
Source
# File lib/chamomile/components/text_area.rb, line 46 def value @lines.join("\n") end
Source
# 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
Source
# 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
Source
# 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