3 ## a fully-functional text field supporting completions, expansions,
4 ## history--everything!
6 ## writing this fucking sucked. if you thought ncurses was some 1970s
7 ## before-people-knew-how-to-program bullshit, wait till you see
10 ## completion comments: completion is done emacs-style, and mostly
11 ## depends on outside support, as we merely signal the existence of a
12 ## new set of completions to show (#new_completions?) or that the
13 ## current list of completions should be rolled if they're too large
14 ## to fill the screen (#roll_completions?).
16 ## in sup, completion support is implemented through BufferManager#ask
17 ## and CompletionMode.
23 @completion_block = nil
24 reset_completion_state
27 bool_reader :new_completions, :roll_completions
28 attr_reader :completions
30 def value; @value || get_cursed_value end
32 def activate window, y, x, width, question, default=nil, &block
33 @w, @y, @x, @width = window, y, x, width
35 @completion_block = block
36 @field = Ncurses::Form.new_field 1, @width - question.length, @y, @x + question.length, 0, 0
37 @form = Ncurses::Form.new_form [@field]
39 Ncurses::Form.post_form @form
40 set_cursed_value default if default
44 @w.attrset Colormap.color_for(:none)
45 @w.mvaddstr @y, 0, @question
47 Ncurses::Form.form_driver @form, Ncurses::Form::REQ_END_FIELD
48 Ncurses::Form.form_driver @form, Ncurses::Form::REQ_NEXT_CHAR if @value && @value =~ / $/ # fucking RETARDED
52 reset_completion_state
61 ## short-circuit exit paths
63 when Ncurses::KEY_ENTER # submit!
64 @value = get_cursed_value
65 @history.push @value unless @value =~ /^\s*$/
67 when Ncurses::KEY_CANCEL # cancel
70 when Ncurses::KEY_TAB # completion
71 return true unless @completion_block
72 if @completions.empty?
74 c = @completion_block.call v
76 @value = c.map { |full, short| full }.shared_prefix(true)
77 set_cursed_value @value
82 @new_completions = true
83 @roll_completions = false
86 @new_completions = false
87 @roll_completions = true
92 reset_completion_state
97 when Ncurses::KEY_LEFT
98 Ncurses::Form::REQ_PREV_CHAR
99 when Ncurses::KEY_RIGHT
100 Ncurses::Form::REQ_NEXT_CHAR
102 Ncurses::Form::REQ_DEL_CHAR
103 when Ncurses::KEY_BACKSPACE
104 Ncurses::Form::REQ_DEL_PREV
106 Ncurses::Form::REQ_BEG_FIELD
108 Ncurses::Form::REQ_END_FIELD
110 Ncurses::Form::REQ_CLR_EOF
111 when Ncurses::KEY_UP, Ncurses::KEY_DOWN
112 unless @history.empty?
113 value = get_cursed_value
115 #Redwood::log "history before #{@history.inspect}"
116 @history[@i] = value #unless value =~ /^\s*$/
117 @i = (@i + (c == Ncurses::KEY_UP ? -1 : 1)) % @history.size
118 @value = @history[@i]
119 #Redwood::log "history after #{@history.inspect}"
120 set_cursed_value @value
121 Ncurses::Form::REQ_END_FIELD
127 Ncurses::Form.form_driver @form, d if d
133 def reset_completion_state
135 @new_completions = @roll_completions = @clear_completions = false
138 ## ncurses inanity wrapper
140 ## DO NOT READ THIS CODE. YOU WILL GO MAD.
142 return nil unless @field
145 Ncurses::Form.form_driver @form, Ncurses::Form::REQ_VALIDATION
146 v = @field.field_buffer(0).gsub(/^\s+|\s+$/, "")
148 ## cursor <= end of text
149 if x - @question.length - v.length <= 0
151 else # trailing spaces
152 v + (" " * (x - @question.length - v.length))
156 def set_cursed_value v
157 @field.set_field_buffer 0, v