Class: Fatty::InputField
- Inherits:
-
Object
- Object
- Fatty::InputField
- Includes:
- Actionable
- Defined in:
- lib/fatty/input_field.rb
Overview
The =InputField= class is a thin controller around an InputBuffer that adds:
- A prompt (text shown before the editable buffer)
- Optional command history integration (previous/next)
- A small set of "editor actions" intended to be bound to keys
=InputField= intentionally does *not* perform terminal I/O or rendering.
Higher-level UI components (e.g., Terminal/Screen/widgets) are responsible
for:
- Decoding keys and dispatching actions
- Translating buffer/cursor state into screen coordinates
- Drawing the prompt + buffer text and placing the cursor
Word-motion and word-deletion semantics are delegated to InputBuffer so
the definition of "word" can be configured in one place (via
=InputBuffer='s word_char_re).
Instance Attribute Summary collapse
-
#buffer ⇒ Object
readonly
Returns the value of attribute buffer.
-
#history ⇒ Object
readonly
Returns the value of attribute history.
-
#prompt ⇒ Object
Returns the value of attribute prompt.
Instance Method Summary collapse
- #act_on(action, *args, env: nil, **kwargs) ⇒ Object
- #autosuggestion ⇒ Object
- #complete!(direction: 1) ⇒ Object
-
#cursor_x ⇒ Object
Visual cursor X position in the window.
- #cycle_completion!(direction: 1) ⇒ Object
-
#empty? ⇒ Boolean
:category: Queries.
-
#initialize(prompt: ">", buffer: nil, completion_proc: nil, history: nil, history_kind: :command, history_ctx: nil) ⇒ InputField
constructor
A new instance of InputField.
- #path_completion_candidates ⇒ Object
- #path_completion_candidates_for(prefix) ⇒ Object
- #popup_completion_candidates ⇒ Object
- #popup_completion_path? ⇒ Boolean
- #popup_completion_query ⇒ Object
- #popup_completion_range ⇒ Object
- #prompt_text ⇒ Object
- #reset_completion_state! ⇒ Object
- #state ⇒ Object
- #sync_virtual_suffix! ⇒ Object
-
#to_s ⇒ Object
(also: #inspect)
:category: Inspect.
Methods included from Actionable
Constructor Details
#initialize(prompt: ">", buffer: nil, completion_proc: nil, history: nil, history_kind: :command, history_ctx: nil) ⇒ InputField
Returns a new instance of InputField.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/fatty/input_field.rb', line 29 def initialize( prompt: ">", buffer: nil, completion_proc: nil, history: nil, history_kind: :command, history_ctx: nil ) @prompt = Prompt.ensure(prompt) @history = history @history_kind = history_kind @history_ctx = history_ctx @completion_proc = completion_proc @completion_state = nil @buffer = if buffer buffer else cfg = Fatty::Config.config word_char_re = cfg.dig(:word_char_re) || Fatty::InputBuffer::DEFAULT_WORD_CHAR_RE Fatty::InputBuffer.new(word_char_re: word_char_re) end end |
Instance Attribute Details
#buffer ⇒ Object (readonly)
Returns the value of attribute buffer.
27 28 29 |
# File 'lib/fatty/input_field.rb', line 27 def buffer @buffer end |
#history ⇒ Object (readonly)
Returns the value of attribute history.
27 28 29 |
# File 'lib/fatty/input_field.rb', line 27 def history @history end |
#prompt ⇒ Object
Returns the value of attribute prompt.
27 28 29 |
# File 'lib/fatty/input_field.rb', line 27 def prompt @prompt end |
Instance Method Details
#act_on(action, *args, env: nil, **kwargs) ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/fatty/input_field.rb', line 211 def act_on(action, *args, env: nil, **kwargs) return unless action reset_history_cursor_for(action) if Fatty::Actions.registered?(action) if env Fatty::Actions.call(action, env, *args, **kwargs) else defn = Fatty::Actions.lookup(action) target = case defn[:on] when :buffer then buffer else raise Fatty::ActionError, "Cannot dispatch #{action} without env for target #{defn[:on].inspect}" end target.public_send(defn[:method], *args, **kwargs) end else raise Fatty::ActionError, "Unknown action: #{action}" end end |
#autosuggestion ⇒ Object
116 117 118 119 120 121 122 123 124 |
# File 'lib/fatty/input_field.rb', line 116 def autosuggestion active = active_completion_autosuggestion return active if active text = buffer.text.to_s return if text.empty? autosuggestion_candidates.first end |
#complete!(direction: 1) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/fatty/input_field.rb', line 126 def complete!(direction: 1) candidates = tab_completion_candidates common_prefix = common_completion_prefix(candidates) if candidates.length == 1 accept_completion_line(candidates.first) elsif direction.positive? && common_prefix && common_prefix.length > buffer.text.length accept_completion_line(common_prefix) else cycle_completion!(direction: direction) end end |
#cursor_x ⇒ Object
Visual cursor X position in the window
239 240 241 242 |
# File 'lib/fatty/input_field.rb', line 239 def cursor_x before_cursor = buffer.text.to_s[0...buffer.cursor].to_s prompt_width + Fatty::Ansi.visible_length(before_cursor) end |
#cycle_completion!(direction: 1) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/fatty/input_field.rb', line 141 def cycle_completion!(direction: 1) text = buffer.text.to_s candidates = tab_completion_candidates result = nil if candidates.empty? reset_completion_state! elsif same_completion_state?(base: text, candidates: candidates) @completion_state[:index] = (@completion_state[:index] + direction) % @completion_state[:candidates].length result = @completion_state[:candidates][@completion_state[:index]] else @completion_state = { base: text, candidates: candidates, index: 0, } result = @completion_state[:candidates].first end sync_virtual_suffix! result end |
#empty? ⇒ Boolean
:category: Queries
63 64 65 |
# File 'lib/fatty/input_field.rb', line 63 def empty? buffer.text == "" end |
#path_completion_candidates ⇒ Object
174 175 176 177 178 179 |
# File 'lib/fatty/input_field.rb', line 174 def path_completion_candidates prefix = path_completion_prefix return [] if prefix.nil? || prefix.empty? rendered_path_candidates(prefix) end |
#path_completion_candidates_for(prefix) ⇒ Object
181 182 183 184 185 |
# File 'lib/fatty/input_field.rb', line 181 def path_completion_candidates_for(prefix) return [] if prefix.nil? || prefix.empty? rendered_path_candidates(prefix) end |
#popup_completion_candidates ⇒ Object
165 166 167 168 169 170 171 172 |
# File 'lib/fatty/input_field.rb', line 165 def popup_completion_candidates path_prefix = popup_path_completion_prefix if path_prefix path = rendered_path_candidates(path_prefix) return path if path.any? end autosuggestion_candidates(base: buffer.text.to_s[0...buffer.cursor]) end |
#popup_completion_path? ⇒ Boolean
199 200 201 |
# File 'lib/fatty/input_field.rb', line 199 def popup_completion_path? !!popup_path_completion_prefix end |
#popup_completion_query ⇒ Object
195 196 197 |
# File 'lib/fatty/input_field.rb', line 195 def popup_completion_query path_completion_prefix || buffer.completion_prefix end |
#popup_completion_range ⇒ Object
187 188 189 190 191 192 193 |
# File 'lib/fatty/input_field.rb', line 187 def popup_completion_range if popup_path_completion_prefix path_completion_range else 0...buffer.text.length end end |
#prompt_text ⇒ Object
234 235 236 |
# File 'lib/fatty/input_field.rb', line 234 def prompt_text prompt.text end |
#reset_completion_state! ⇒ Object
203 204 205 |
# File 'lib/fatty/input_field.rb', line 203 def reset_completion_state! @completion_state = nil end |
#state ⇒ Object
67 68 69 70 71 72 73 74 75 76 |
# File 'lib/fatty/input_field.rb', line 67 def state [ prompt_text.to_s.dup.freeze, buffer.text.to_s.dup.freeze, buffer.cursor, buffer.virtual_suffix.to_s.dup.freeze, buffer.region_active?, buffer.region_range, ] end |
#sync_virtual_suffix! ⇒ Object
207 208 209 |
# File 'lib/fatty/input_field.rb', line 207 def sync_virtual_suffix! buffer.virtual_suffix = autosuggestion_suffix end |
#to_s ⇒ Object Also known as: inspect
:category: Inspect
56 57 58 |
# File 'lib/fatty/input_field.rb', line 56 def to_s "<InputField:#{object_id}> Prompt => #{prompt} Buffer => #{buffer}" end |