]> git.cworth.org Git - sup/blob - lib/sup/textfield.rb
L now prompts for label rather than immediately spawning label-select-mode
[sup] / lib / sup / textfield.rb
1 require 'curses'
2
3 module Redwood
4
5 ## a fully-functional text field supporting completions, expansions,
6 ## history--everything!
7 ##
8 ## completion is done emacs-style, and mostly depends on outside
9 ## support, as we merely signal the existence of a new set of
10 ## completions to show (#new_completions?)  or that the current list
11 ## of completions should be rolled if they're too large to fill the
12 ## screen (#roll_completions?).
13 ##
14 ## in sup, completion support is implemented through BufferManager#ask
15 ## and CompletionMode.
16 class TextField
17   def initialize window, y, x, width
18     @w, @x, @y = window, x, y
19     @width = width
20     @i = nil
21     @history = []
22
23     @completion_block = nil
24     reset_completion_state
25   end
26
27   bool_reader :new_completions, :roll_completions
28   attr_reader :completions
29
30   ## when the user presses enter, we store the value in @value and
31   ## clean up all the ncurses cruft. before @value is set, we can
32   ## get the current value from ncurses.
33   def value; @field ? get_cur_value : @value end
34
35   def activate question, default=nil, &block
36     @question = question
37     @value = nil
38     @completion_block = block
39     @field = Ncurses::Form.new_field 1, @width - question.length,
40                                      @y, @x + question.length, 0, 0
41     @form = Ncurses::Form.new_form [@field]
42
43     @history[@i = @history.size] = default || ""
44     Ncurses::Form.post_form @form
45     set_cur_value @history[@i]
46   end
47
48   def position_cursor
49     @w.attrset Colormap.color_for(:none)
50     @w.mvaddstr @y, 0, @question
51     Ncurses.curs_set 1
52     Ncurses::Form.form_driver @form, Ncurses::Form::REQ_END_FIELD
53     Ncurses::Form.form_driver @form, Ncurses::Form::REQ_NEXT_CHAR if @history[@i] =~ / $/ # fucking RETARDED!!!!
54   end
55
56   def deactivate
57     reset_completion_state
58     @form.unpost_form
59     @form.free_form
60     @field.free_field
61     @field = nil
62     Ncurses.curs_set 0
63   end
64
65   def handle_input c
66     ## short-circuit exit paths
67     case c
68     when Ncurses::KEY_ENTER # submit!
69       @value = @history[@i] = get_cur_value
70       return false
71     when Ncurses::KEY_CANCEL # cancel
72       @history.delete_at @i
73       @i = @history.empty? ? nil : (@i - 1) % @history.size 
74       @value = nil
75       return false
76     when Ncurses::KEY_TAB # completion
77       return true unless @completion_block
78       if @completions.empty?
79         v = get_cur_value
80         c = @completion_block.call v
81         if c.size > 0
82           set_cur_value c.map { |full, short| full }.shared_prefix
83         end
84         if c.size > 1
85           @completions = c
86           @new_completions = true
87           @roll_completions = false
88         end
89       else
90         @new_completions = false
91         @roll_completions = true
92       end
93       return true
94     end
95
96     reset_completion_state
97
98     d =
99       case c
100       when Ncurses::KEY_LEFT
101         Ncurses::Form::REQ_PREV_CHAR
102       when Ncurses::KEY_RIGHT
103         Ncurses::Form::REQ_NEXT_CHAR
104       when Ncurses::KEY_BACKSPACE
105         Ncurses::Form::REQ_DEL_PREV
106       when ?\001
107         Ncurses::Form::REQ_BEG_FIELD
108       when ?\005
109         Ncurses::Form::REQ_END_FIELD
110       when Ncurses::KEY_UP
111         @history[@i] = @field.field_buffer 0
112         @i = (@i - 1) % @history.size
113         set_cur_value @history[@i]
114       when Ncurses::KEY_DOWN
115         @history[@i] = @field.field_buffer 0
116         @i = (@i + 1) % @history.size
117         set_cur_value @history[@i]
118       else
119         c
120       end
121
122     Ncurses::Form.form_driver @form, d
123     true
124   end
125
126 private
127
128   def reset_completion_state
129     @completions = []
130     @new_completions = @roll_completions = @clear_completions = false
131   end
132
133   ## ncurses inanity wrapper
134   def get_cur_value
135     Ncurses::Form.form_driver @form, Ncurses::Form::REQ_VALIDATION
136     @field.field_buffer(0).gsub(/^\s+|\s+$/, "").gsub(/\s+/, " ")
137   end
138   
139   ## ncurses inanity wrapper
140   def set_cur_value v
141     @field.set_field_buffer 0, v
142     Ncurses::Form.form_driver @form, Ncurses::Form::REQ_END_FIELD
143   end
144
145 end
146 end