Class: Redwood::TextField

Inherits:
Object show all
Defined in:
lib/sup/textfield.rb

Overview

a fully-functional text field supporting completions, expansions, history–everything!

writing this fucking sucked. if you thought ncurses was some 1970s before-people-knew-how-to-program bullshit, wait till you see ncurses forms.

completion comments: 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.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTextField

Returns a new instance of TextField.



19
20
21
22
23
24
25
# File 'lib/sup/textfield.rb', line 19

def initialize
  @i = nil
  @history = []

  @completion_block = nil
  reset_completion_state
end

Instance Attribute Details

#completionsObject (readonly)

Returns the value of attribute completions.



28
29
30
# File 'lib/sup/textfield.rb', line 28

def completions
  @completions
end

Instance Method Details

#activate(window, y, x, width, question, default = nil, &block) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/sup/textfield.rb', line 32

def activate window, y, x, width, question, default=nil, &block
  @w, @y, @x, @width = window, y, x, width
  @question = question
  @completion_block = block
  @field = Ncurses::Form.new_field 1, @width - question.length, @y, @x + question.length, 0, 0
  if @field.respond_to? :opts_off
    @field.opts_off Ncurses::Form::O_STATIC
    @field.opts_off Ncurses::Form::O_BLANK
  end
  @form = Ncurses::Form.new_form [@field]
  @value = default || ''
  Ncurses::Form.post_form @form
  set_cursed_value @value
end

#deactivateObject



55
56
57
58
59
60
61
62
# File 'lib/sup/textfield.rb', line 55

def deactivate
  reset_completion_state
  @form.unpost_form
  @form.free_form
  @field.free_field
  @field = nil
  Ncurses.curs_set 0
end

#handle_input(c) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/sup/textfield.rb', line 64

def handle_input c
  ## short-circuit exit paths
  case c
  when Ncurses::KEY_ENTER # submit!
    @value = get_cursed_value
    @history.push @value unless @value =~ /^\s*$/
    @i = @history.size
    return false
  when Ncurses::KEY_CANCEL # cancel
    @value = nil
    return false
  when Ncurses::KEY_TAB # completion
    return true unless @completion_block
    if @completions.empty?
      v = get_cursed_value
      c = @completion_block.call v
      if c.size > 0
        @value = c.map { |full, short| full }.shared_prefix(true)
        set_cursed_value @value
        position_cursor
      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
  @value = nil

  d =
    case c
    when Ncurses::KEY_LEFT
      Ncurses::Form::REQ_PREV_CHAR
    when Ncurses::KEY_RIGHT
      Ncurses::Form::REQ_NEXT_CHAR
    when Ncurses::KEY_DC
      Ncurses::Form::REQ_DEL_CHAR
    when Ncurses::KEY_BACKSPACE, 127 # 127 is also a backspace keysym
      Ncurses::Form::REQ_DEL_PREV
    when ?\C-a.ord, Ncurses::KEY_HOME
      nop
      Ncurses::Form::REQ_BEG_FIELD
    when ?\C-e.ord, Ncurses::KEY_END
      Ncurses::Form::REQ_END_FIELD
    when ?\C-k.ord
      Ncurses::Form::REQ_CLR_EOF
    when ?\C-u.ord
      set_cursed_value cursed_value_after_point
      Ncurses::Form.form_driver @form, Ncurses::Form::REQ_END_FIELD
      nop
      Ncurses::Form::REQ_BEG_FIELD
    when ?\C-w.ord
      while action = remove_extra_space
        Ncurses::Form.form_driver @form, action
      end
      Ncurses::Form.form_driver @form, Ncurses::Form::REQ_PREV_CHAR
      Ncurses::Form.form_driver @form, Ncurses::Form::REQ_DEL_WORD
    when Ncurses::KEY_UP, Ncurses::KEY_DOWN
      unless !@i || @history.empty?
        value = get_cursed_value
        #debug "history before #{@history.inspect}"
        @i = @i + (c == Ncurses::KEY_UP ? -1 : 1)
        @i = 0 if @i < 0
        @i = @history.size if @i > @history.size
        @value = @history[@i] || ''
        #debug "history after #{@history.inspect}"
        set_cursed_value @value
        Ncurses::Form::REQ_END_FIELD
      end
    else
      c
    end

  Ncurses::Form.form_driver @form, d if d
  true
end

#position_cursorObject



47
48
49
50
51
52
53
# File 'lib/sup/textfield.rb', line 47

def position_cursor
  @w.attrset Colormap.color_for(:none)
  @w.mvaddstr @y, 0, @question
  Ncurses.curs_set 1
  Ncurses::Form.form_driver @form, Ncurses::Form::REQ_END_FIELD
  Ncurses::Form.form_driver @form, Ncurses::Form::REQ_NEXT_CHAR if @value && @value =~ / $/ # fucking RETARDED
end

#valueObject



30
# File 'lib/sup/textfield.rb', line 30

def value; @value || get_cursed_value end