class TTY::Reader::Line
Shim Helper
Constants
- DEFAULT_WORD_BREAK_CHARACTERS
The word break characters list used by shell
Attributes
The current cursor position witin the text @api public
The line mode @api public
The prompt displayed before input @api public
The word separator pattern for splitting the text
@return [Regexp]
@api public
The editable text @api public
Public Class Methods
Create a Line
instance
@api private
# File lib/greenhat/tty/line.rb, line 52 def initialize(text = '', prompt: '', separator: nil) @text = text.dup @prompt = prompt.dup break_chars = DEFAULT_WORD_BREAK_CHARACTERS.chars @separator = separator || Regexp.union(break_chars) @cursor = [0, @text.length].max @mode = :edit yield self if block_given? end
Strip ANSI characters from the text
@param [String] text
@return [String]
@api public
# File lib/greenhat/tty/line.rb, line 22 def self.sanitize(text) text.dup.gsub(ANSI_MATCHER, '') end
Public Instance Methods
Add char and move cursor
@api public
# File lib/greenhat/tty/line.rb, line 267 def <<(char) @text << char @cursor += 1 end
Read character
@api public
# File lib/greenhat/tty/line.rb, line 193 def [](i) @text[i] end
Insert characters inside a line. When the lines exceeds maximum length, an extra space is added to accomodate index.
@param [Integer] i
the index to insert at
@param [String] chars
the characters to insert
@example
text = "aaa" line[5]= "b" => "aaa b"
@api public
# File lib/greenhat/tty/line.rb, line 160 def []=(i, chars) edit_mode if i.is_a?(Range) @text[i] = chars @cursor += chars.length return end if i <= 0 before_text = '' after_text = @text.dup elsif i > @text.length - 1 # insert outside of line input before_text = @text.dup after_text = "\s" * (i - @text.length) @cursor += after_text.length else before_text = @text[0..i - 1].dup after_text = @text[i..-1].dup end @text = if i > @text.length - 1 before_text + after_text + chars else before_text + chars + after_text end @cursor = i + chars.length end
Remove char from the line at current position
@api public
# File lib/greenhat/tty/line.rb, line 275 def delete(n = 1) @text.slice!(@cursor, n) end
Enable edit mode
@return [Boolean]
@public
# File lib/greenhat/tty/line.rb, line 77 def edit_mode @mode = :edit end
Check if line is in edit mode
@return [Boolean]
@public
# File lib/greenhat/tty/line.rb, line 68 def editing? @mode == :edit end
Check if cursor reached end of the line
@return [Boolean]
@api public
# File lib/greenhat/tty/line.rb, line 113 def end? @cursor == @text.length end
No Tabs
# File lib/greenhat/tty/custom_line.rb, line 24 def insert(chars) self[@cursor] = chars unless ["\t", "\e[Z"].include?(chars) end
Move line position to the left by n chars
@api public
# File lib/greenhat/tty/line.rb, line 120 def left(n = 1) @cursor = [0, @cursor - n].max end
Move cursor to end position
@api public
# File lib/greenhat/tty/line.rb, line 141 def move_to_end @cursor = @text.length # put cursor outside of text end
Move cursor to beginning position
@api public
# File lib/greenhat/tty/line.rb, line 134 def move_to_start @cursor = 0 end
# File lib/greenhat/tty/custom_line.rb, line 5 def move_word_left loop do # Don't go past beginning break if @cursor.zero? left 1 break if self[@cursor].blank? end end
# File lib/greenhat/tty/custom_line.rb, line 16 def move_word_right loop do right 1 break if self[@cursor].blank? end end
Prompt size
@api public
# File lib/greenhat/tty/line.rb, line 301 def prompt_size p = self.class.sanitize(@prompt).split(/\r?\n/) # return the length of each line + screen width for every line past the first # which accounts for multi-line prompts p.join.length + ((p.length - 1) * TTY::Screen.width) end
Find a range of characters under the cursor based on the word separator
@param [Integer] from
the start index
@param [Symbol] before
whether to start search before or after break character
@return [Range]
@api public
# File lib/greenhat/tty/line.rb, line 220 def range(from: @cursor, before: true) # move back or forward by one character when at a word boundary if word_boundary? from = before ? from - 1 : from + 1 end # find start position start_pos = @text.rindex(separator, from) || 0 start_pos += 1 unless start_pos.zero? # find end position end_pos = @text.index(separator, start_pos) || text_size end_pos -= 1 unless @text.empty? start_pos..end_pos end
Remove char from the line in front of the cursor
@param [Integer] n
the number of chars to remove
@api public
# File lib/greenhat/tty/line.rb, line 285 def remove(n = 1) left(n) @text.slice!(@cursor, n) end
Replace current line with new text
@param [String] text
@api public
# File lib/greenhat/tty/line.rb, line 251 def replace(text) @text = text @cursor = @text.length # put cursor outside of text replace_mode end
Enable replace mode
@return [Boolean]
@public
# File lib/greenhat/tty/line.rb, line 95 def replace_mode @mode = :replace end
Check if line is in replace mode
@return [Boolean]
@public
# File lib/greenhat/tty/line.rb, line 86 def replacing? @mode == :replace end
Move line position to the right by n chars
@api public
# File lib/greenhat/tty/line.rb, line 127 def right(n = 1) @cursor = [@text.length, @cursor + n].min end
Full line size with prompt
@api public
# File lib/greenhat/tty/line.rb, line 318 def size prompt_size + text_size end
Check if cursor reached beginning of the line
@return [Boolean]
@api public
# File lib/greenhat/tty/line.rb, line 104 def start? @cursor.zero? end
Text size
@api public
# File lib/greenhat/tty/line.rb, line 311 def text_size self.class.sanitize(@text).size end
Full line with prompt as string
@api public
# File lib/greenhat/tty/line.rb, line 293 def to_s "#{@prompt}#{@text}" end
Find a word under the cursor based on the word separator
@param [Boolean] before
whether to start searching before or after a break character
@return [String]
@api public
# File lib/greenhat/tty/line.rb, line 205 def word(before: true) @text[range(before: before)] end
Check if cursor is at a word boundary
@return [Boolean]
@api private
# File lib/greenhat/tty/line.rb, line 242 def word_boundary? @text[@cursor] =~ separator end