Class: RuVim::KeyHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/ruvim/key_handler.rb

Constant Summary collapse

RICH_MODE_BLOCKED_COMMANDS =

Rich mode: delegates to normal mode key handling but blocks mutating operations.

%w[
  mode.insert mode.append mode.append_line_end mode.insert_nonblank
  mode.open_below mode.open_above
  buffer.delete_char buffer.delete_line buffer.delete_motion
  buffer.change_motion buffer.change_line
  buffer.paste_after buffer.paste_before
  buffer.replace_char
  buffer.visual_delete
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(editor:, dispatcher:, keymaps:, terminal:, screen:, completion:, stream_mixer:) ⇒ KeyHandler

Returns a new instance of KeyHandler.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/ruvim/key_handler.rb', line 18

def initialize(editor:, dispatcher:, keymaps:, terminal:, screen:, completion:, stream_mixer:)
  @editor = editor
  @dispatcher = dispatcher
  @keymaps = keymaps
  @terminal = terminal
  @screen = screen
  @completion = completion
  @stream_mixer = stream_mixer

  @pending_key_deadline = nil
  @pending_ambiguous_invocation = nil
  @pending_keys = nil
  @insert_start_location = nil
  @paste_batch = false

  # Pending state flags
  @operator_pending = nil
  @register_pending = false
  @mark_pending = false
  @jump_pending = nil
  @find_pending = nil
  @replace_pending = nil
  @macro_record_pending = false
  @macro_play_pending = false
  @visual_pending = nil
  @skip_record_for_current_key = false
  @last_macro_name = nil
  @macro_play_stack = nil
  @suspend_macro_recording_depth = nil

  # Dot repeat state
  @dot_change_capture_active = false
  @dot_change_capture_keys = nil
  @last_change_keys = nil
  @dot_replay_depth = nil
end

Instance Attribute Details

#paste_batchObject

Returns the value of attribute paste_batch.



16
17
18
# File 'lib/ruvim/key_handler.rb', line 16

def paste_batch
  @paste_batch
end

Instance Method Details

#escape_sequence_timeout_secondsObject



84
85
86
87
88
89
90
# File 'lib/ruvim/key_handler.rb', line 84

def escape_sequence_timeout_seconds
  ms = @editor.global_options["ttimeoutlen"].to_i
  ms = 50 if ms <= 0
  ms / 1000.0
rescue StandardError
  0.005
end

#handle(key) ⇒ Object

Returns true if redraw is needed



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
# File 'lib/ruvim/key_handler.rb', line 93

def handle(key)
  mode_before = @editor.mode
  clear_stale_message_before_key(key)
  @skip_record_for_current_key = false
  append_dot_change_capture_key(key)
  if key == :ctrl_z
    suspend_to_shell
    track_mode_transition(mode_before)
    return true
  end
  if key == :ctrl_c && @editor.mode != :normal
    handle_ctrl_c
    track_mode_transition(mode_before)
    record_macro_key_if_needed(key)
    return false
  end

  case @editor.mode
  when :hit_enter
    handle_hit_enter_key(key)
  when :insert
    handle_insert_key(key)
  when :command_line
    handle_command_line_key(key)
  when :visual_char, :visual_line, :visual_block
    handle_visual_key(key)
  when :rich
    handle_rich_key(key)
  else
    handle_normal_key(key)
  end
  track_mode_transition(mode_before)
  record_macro_key_if_needed(key)
  false
rescue RuVim::CommandError => e
  @editor.echo_error(e.message)
  false
end

#handle_editor_app_action(name, **kwargs) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/ruvim/key_handler.rb', line 132

def handle_editor_app_action(name, **kwargs)
  if @editor.rich_mode?
    case name
    when :normal_operator_start
      op = kwargs[:name] || kwargs["name"]
      return if op == :delete || op == :change
    when :normal_replace_pending_start, :normal_change_repeat
      return
    end
  end

  case name
  when :normal_register_pending_start
    start_register_pending
  when :normal_operator_start
    start_operator_pending(kwargs[:name] || kwargs["name"])
  when :normal_replace_pending_start
    start_replace_pending
  when :normal_find_pending_start
    start_find_pending((kwargs[:token] || kwargs["token"]).to_s)
  when :normal_find_repeat
    repeat_last_find(reverse: !!(kwargs[:reverse] || kwargs["reverse"]))
  when :normal_change_repeat
    repeat_last_change
  when :normal_macro_record_toggle
    toggle_macro_recording_or_start_pending
  when :normal_macro_play_pending_start
    start_macro_play_pending
  when :normal_mark_pending_start
    start_mark_pending
  when :normal_jump_pending_start
    start_jump_pending(
      linewise: !!(kwargs[:linewise] || kwargs["linewise"]),
      repeat_token: (kwargs[:repeat_token] || kwargs["repeat_token"]).to_s
    )
  when :follow_toggle
    @stream_mixer.ex_follow_toggle
  when :normal_ctrl_c
    handle_normal_ctrl_c
  else
    raise RuVim::CommandError, "Unknown app action: #{name}"
  end
end

#handle_idle_timeoutObject

Returns true if redraw is needed due to timeout/transient message handling



56
57
58
59
60
61
62
63
64
# File 'lib/ruvim/key_handler.rb', line 56

def handle_idle_timeout
  redraw = false
  if pending_key_timeout_expired?
    handle_pending_key_timeout
    redraw = true
  end
  redraw = true if @editor.clear_expired_transient_message!(now: monotonic_now)
  redraw
end

#handle_normal_ctrl_cObject



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/ruvim/key_handler.rb', line 176

def handle_normal_ctrl_c
  clear_pending_key_timeout
  @editor.pending_count = nil
  @pending_keys = []
  @operator_pending = nil
  @replace_pending = nil
  @register_pending = false
  @mark_pending = false
  @jump_pending = nil
  @macro_record_pending = false
  @macro_play_pending = false
  buf = @editor.current_buffer
  if buf && @stream_mixer.follow_active?(buf)
    @stream_mixer.stop_follow!(buf)
  else
    @editor.clear_message
  end
end

#loop_timeout_secondsObject



72
73
74
75
76
77
78
79
80
81
82
# File 'lib/ruvim/key_handler.rb', line 72

def loop_timeout_seconds
  now = monotonic_now
  timeouts = []
  if @pending_key_deadline
    timeouts << [@pending_key_deadline - now, 0.0].max
  end
  if (msg_to = @editor.transient_message_timeout_seconds(now:))
    timeouts << msg_to
  end
  timeouts.min
end

#pending_key_timeout_secondsObject



66
67
68
69
70
# File 'lib/ruvim/key_handler.rb', line 66

def pending_key_timeout_seconds
  return nil unless @pending_key_deadline

  [@pending_key_deadline - monotonic_now, 0.0].max
end