class Diakonos::Readline

Attributes

input[R]

Public Class Methods

new( list_manager:, keystroke_processor:, testing: false, window:, start_pos:, options: {}, &block ) click to toggle source

completion_array is the array of strings that tab completion can use The block returns true if a refresh is needed? @param options :initial_text, :completion_array, :history, :do_complete, :on_dirs

# File lib/diakonos/readline.rb, line 10
def initialize(
  list_manager:,
  keystroke_processor:,
  testing: false,
  window:,
  start_pos:,
  options: {},
  &block
)
  @list_manager = list_manager
  @keystroke_processor = keystroke_processor
  @testing = testing
  @window = window
  @start_pos = start_pos
  @window.setpos( 0, start_pos )
  @initial_text = options[ :initial_text ] || ''
  @completion_array = options[ :completion_array ]
  @list_filename = @list_manager.list_filename

  @history = options[ :history ] || []
  @history << @initial_text
  @history_index = [ @history.length - 1, 0 ].max

  @do_complete = options[ :do_complete ] || ::Diakonos::DONT_COMPLETE
  @on_dirs = options[ :on_dirs ] || :go_into_dirs
  @numbered_list = options[ :numbered_list ]

  @block = block

  # ---

  @input = @initial_text.dup
  if ! @input.empty?
    call_block
  end

  @icurx = @window.curx
  @icury = @window.cury
  @view_y = 0
  if ! @testing
    @window.addstr @initial_text
  end
  @input_cursor = @initial_text.length
  @opened_list_file = false

  if @do_complete
    complete_input
  end
end

Public Instance Methods

abort() click to toggle source
# File lib/diakonos/readline/functions.rb, line 5
def abort
  @input = nil
  @done = true
end
accept( item ) click to toggle source
# File lib/diakonos/readline/functions.rb, line 10
def accept( item )
  if item && @on_dirs == :go_into_dirs && File.directory?( item )
    complete_input
  else
    @done = true
  end
end
backspace() click to toggle source
# File lib/diakonos/readline/functions.rb, line 18
def backspace
  if cursor_left
    delete
  end
end
call_block() click to toggle source
# File lib/diakonos/readline.rb, line 67
def call_block
  if @block
    @block.call( @input )
    @window.refresh
  end
end
complete_input() click to toggle source
# File lib/diakonos/readline.rb, line 146
def complete_input
  if @completion_array && @input.length > 0
    len = @input.length
    matches = @completion_array.find_all { |el| el[ 0...len ] == @input && len <= el.length }
  else
    path = File.expand_path( @input || '.' )
    if FileTest.directory? path
      path << '/'
    end
    matches = Dir.glob( ( path + "*" ).gsub( /\*\*/, "*" ) )
    if @on_dirs == :accept_dirs
      matches = matches.select { |m| File.directory? m }
    end
  end
  matches.sort!

  if matches.length == 1
    @input = matches[ 0 ]
    cursor_write_input
    File.open( @list_filename, "w" ) do |f|
      if @completion_array.nil?
        f.puts "(unique)"
      else
        f.puts @input
      end
    end
    if @completion_array.nil? && FileTest.directory?( @input )
      @input << "/"
      cursor_write_input
      if @on_dirs != :accept_dirs
        complete_input
      end
    end
  elsif matches.length > 1
    common = matches[ 0 ]
    File.open( @list_filename, "w" ) do |f|
      i = nil
      matches.each do |match|
        f.print match
        if FileTest.directory?( match )
          f.print '/'
        end
        f.puts

        if match[ 0 ] != common[ 0 ]
          common = nil
          break
        end

        up_to = [ common.length - 1, match.length - 1 ].min
        i = 1
        while ( i <= up_to ) && ( match[ 0..i ] == common[ 0..i ] )
          i += 1
        end
        common = common[ 0...i ]
      end
    end
    if common.nil?
      File.open( @list_filename, "w" ) do |f|
        f.puts "(no matches)"
      end
    else
      @input = common
      cursor_write_input
    end
  else
    File.open( @list_filename, "w" ) do |f|
      f.puts "(no matches)"
    end
  end
  @list_manager.open_list_buffer
  @window.setpos( @window.cury, @window.curx )
end
cursor_bol() click to toggle source
# File lib/diakonos/readline/functions.rb, line 24
def cursor_bol
  @input_cursor = 0
  sync
end
cursor_eol() click to toggle source
# File lib/diakonos/readline/functions.rb, line 29
def cursor_eol
  @input_cursor = @input.length
  sync
end
cursor_left() click to toggle source
# File lib/diakonos/readline/functions.rb, line 34
def cursor_left
  return false  if @input_cursor < 1
  @input_cursor -= 1
  sync
  true
end
cursor_right() click to toggle source
# File lib/diakonos/readline/functions.rb, line 41
def cursor_right
  return  if @input_cursor >= @input.length
  @input_cursor += 1
  sync
end
cursor_write_input() click to toggle source

Redisplays the input text starting at the start of the user input area, positioning the cursor at the end of the text.

# File lib/diakonos/readline.rb, line 138
def cursor_write_input
  if @input
    @input_cursor = @input.length
    @window.setpos( @window.cury, @icurx + @input.length )
    redraw_input
  end
end
delete() click to toggle source
# File lib/diakonos/readline/functions.rb, line 47
def delete
  return  if @input_cursor >= @input.length
  @input = @input[ 0...@input_cursor ] + @input[ (@input_cursor + 1)..-1 ]
  sync
end
delete_line() click to toggle source
# File lib/diakonos/readline/functions.rb, line 53
def delete_line
  @input = ""
  sync
end
delete_word() click to toggle source
# File lib/diakonos/readline/functions.rb, line 58
def delete_word
  head = @input[ 0...@input_cursor ]
  chopped = head.sub( /\w+\W*$/, '' )
  @input = chopped + @input[ @input_cursor..-1 ]
  @input_cursor -= head.length - chopped.length
  sync
end
done?() click to toggle source
# File lib/diakonos/readline.rb, line 81
def done?
  @done
end
finish() click to toggle source
# File lib/diakonos/readline.rb, line 85
def finish
  @done = true
end
get_input() click to toggle source
# File lib/diakonos/readline.rb, line 60
def get_input
  while ! done?
    @keystroke_processor.process_keystroke(Array.new, 'input')
  end
  input
end
history_down() click to toggle source
# File lib/diakonos/readline/functions.rb, line 73
def history_down
  return  if @history_index > @history.length - 2
  @history[ @history_index ] = @input
  @history_index += 1
  @input = @history[ @history_index ]
end
history_up() click to toggle source
# File lib/diakonos/readline/functions.rb, line 66
def history_up
  return  if @history_index < 1
  @history[ @history_index ] = @input
  @history_index -= 1
  @input = @history[ @history_index ]
end
list_sync( line ) click to toggle source
# File lib/diakonos/readline.rb, line 89
def list_sync( line )
  return  if line.nil?
  set_input line
  cursor_write_input
end
numbered_list?() click to toggle source
# File lib/diakonos/readline.rb, line 95
def numbered_list?
  @numbered_list
end
paste( s ) click to toggle source
# File lib/diakonos/readline.rb, line 116
def paste( s )
  @input = @input[ 0...@input_cursor ] + s + @input[ @input_cursor..-1 ]
  @input_cursor += s.length
  sync
end
redraw_input() click to toggle source
# File lib/diakonos/readline.rb, line 122
def redraw_input
  input = @input[ @view_y...(@view_y + Curses::cols) ]

  curx = @window.curx
  cury = @window.cury
  @window.setpos( @icury, @icurx )
  @window.addstr "%-#{ Curses::cols - curx }s%s" % [
    input,
    " " * [ ( Curses::cols - input.length ), 0 ].max
  ]
  @window.setpos( cury, curx )
  @window.refresh
end
set_input( input = '' ) click to toggle source
# File lib/diakonos/readline.rb, line 74
def set_input( input = '' )
  if numbered_list? && input =~ /^\w  /
    input = input[ 3..-1 ]
  end
  @input = input
end
sync() click to toggle source
# File lib/diakonos/readline.rb, line 99
def sync
  if @input_cursor > @input.length
    @input_cursor = @input.length
  elsif @input_cursor < @view_y
    @view_y = @input_cursor
  end

  diff = ( @input_cursor - @view_y ) + 1 - ( Curses::cols - @start_pos )
  if diff > 0
    @view_y += diff
  end

  @window.setpos( @window.cury, @start_pos + @input_cursor - @view_y )
  redraw_input
  call_block
end