lib/sup/textfield.rb in sup-0.0.8 vs lib/sup/textfield.rb in sup-0.1

- old
+ new

@@ -1,29 +1,50 @@ require 'curses' module Redwood +## a fully-functional text field supporting completions, expansions, +## history--everything! +## +## completion is done emacs-style, and mostly depends on outside +## support, as we merely signal the existence of a new set of +## completions to show (#new_completions?) or that the current list +## of completions should be rolled if they're too large to fill the +## screen (#roll_completions?). +## +## in sup, completion support is implemented through BufferManager#ask +## and CompletionMode. class TextField - attr_reader :value - def initialize window, y, x, width @w, @x, @y = window, x, y @width = width @i = nil @history = [] + + @completion_block = nil + reset_completion_state end - def activate question, default=nil + bool_reader :new_completions, :roll_completions + attr_reader :completions + + ## when the user presses enter, we store the value in @value and + ## clean up all the ncurses cruft. before @value is set, we can + ## get the current value from ncurses. + def value; @field ? get_cur_value : @value end + + def activate question, default=nil, &block @question = question @value = nil + @completion_block = block @field = Ncurses::Form.new_field 1, @width - question.length, @y, @x + question.length, 0, 0 @form = Ncurses::Form.new_form [@field] @history[@i = @history.size] = default || "" Ncurses::Form.post_form @form - @field.set_field_buffer 0, @history[@i] + set_cur_value @history[@i] end def position_cursor @w.attrset Colormap.color_for(:none) @w.mvaddstr @y, 0, @question @@ -31,28 +52,51 @@ Ncurses::Form.form_driver @form, Ncurses::Form::REQ_END_FIELD Ncurses::Form.form_driver @form, Ncurses::Form::REQ_NEXT_CHAR if @history[@i] =~ / $/ # fucking RETARDED!!!! end def deactivate + reset_completion_state @form.unpost_form @form.free_form @field.free_field + @field = nil Ncurses.curs_set 0 end def handle_input c - if c == 10 # Ncurses::KEY_ENTER - Ncurses::Form.form_driver @form, Ncurses::Form::REQ_VALIDATION - @value = @history[@i] = @field.field_buffer(0).gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ") + ## short-circuit exit paths + case c + when Ncurses::KEY_ENTER # submit! + @value = @history[@i] = get_cur_value return false - elsif c == Ncurses::KEY_CANCEL + when Ncurses::KEY_CANCEL # cancel @history.delete_at @i @i = @history.empty? ? nil : (@i - 1) % @history.size @value = nil return false + when Ncurses::KEY_TAB # completion + return true unless @completion_block + if @completions.empty? + v = get_cur_value + c = @completion_block.call v + if c.size > 0 + set_cur_value c.map { |full, short| full }.shared_prefix + end + if c.size > 1 + @completions = c + @new_completions = true + @roll_completions = false + end + else + @new_completions = false + @roll_completions = true + end + return true end + reset_completion_state + d = case c when Ncurses::KEY_LEFT Ncurses::Form::REQ_PREV_CHAR when Ncurses::KEY_RIGHT @@ -62,23 +106,41 @@ when ?\001 Ncurses::Form::REQ_BEG_FIELD when ?\005 Ncurses::Form::REQ_END_FIELD when Ncurses::KEY_UP - @history[@i] = @field.field_buffer(0) + @history[@i] = @field.field_buffer 0 @i = (@i - 1) % @history.size - @field.set_field_buffer 0, @history[@i] + set_cur_value @history[@i] when Ncurses::KEY_DOWN - @history[@i] = @field.field_buffer(0) + @history[@i] = @field.field_buffer 0 @i = (@i + 1) % @history.size - @field.set_field_buffer 0, @history[@i] + set_cur_value @history[@i] else c end Ncurses::Form.form_driver @form, d - Ncurses.refresh - true end + +private + + def reset_completion_state + @completions = [] + @new_completions = @roll_completions = @clear_completions = false + end + + ## ncurses inanity wrapper + def get_cur_value + Ncurses::Form.form_driver @form, Ncurses::Form::REQ_VALIDATION + @field.field_buffer(0).gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ") + end + + ## ncurses inanity wrapper + def set_cur_value v + @field.set_field_buffer 0, v + Ncurses::Form.form_driver @form, Ncurses::Form::REQ_END_FIELD + end + end end