fatty 0.99.0 → 0.99.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.org +11 -29
  3. data/README.md +2207 -18
  4. data/README.org +2066 -104
  5. data/exe/fatty +236 -93
  6. data/help/help.md +233 -0
  7. data/lib/fatty/action.rb +3 -7
  8. data/lib/fatty/actionable.rb +2 -0
  9. data/lib/fatty/alert.rb +65 -39
  10. data/lib/fatty/ansi/renderer.rb +26 -6
  11. data/lib/fatty/ansi.rb +1 -0
  12. data/lib/fatty/api/alert.rb +15 -0
  13. data/lib/fatty/api/choose.rb +145 -0
  14. data/lib/fatty/api/environment.rb +12 -0
  15. data/lib/fatty/api/keytest.rb +11 -0
  16. data/lib/fatty/api/menu.rb +104 -0
  17. data/lib/fatty/api/output.rb +55 -0
  18. data/lib/fatty/api/progress.rb +24 -0
  19. data/lib/fatty/api/prompt.rb +77 -0
  20. data/lib/fatty/api/status.rb +55 -0
  21. data/lib/fatty/api.rb +38 -0
  22. data/lib/fatty/callback_environment.rb +74 -0
  23. data/lib/fatty/colors/color.rb +366 -232
  24. data/lib/fatty/colors/pairs.rb +2 -0
  25. data/lib/fatty/command.rb +78 -0
  26. data/lib/fatty/config.rb +227 -39
  27. data/lib/fatty/config_files/config.yml +4 -12
  28. data/lib/fatty/config_files/keydefs.yml +13 -23
  29. data/lib/fatty/config_files/themes/capuchin_monk.yml +140 -0
  30. data/lib/fatty/config_files/themes/catppuccin_latte.yml +140 -0
  31. data/lib/fatty/config_files/themes/catppuccin_mocha.yml +140 -0
  32. data/lib/fatty/config_files/themes/cyberpunk.yml +141 -0
  33. data/lib/fatty/config_files/themes/dracula.yml +140 -0
  34. data/lib/fatty/config_files/themes/everforest_dark.yml +140 -0
  35. data/lib/fatty/config_files/themes/gruvbox_dark.yml +140 -0
  36. data/lib/fatty/config_files/themes/gruvbox_light.yml +140 -0
  37. data/lib/fatty/config_files/themes/mono.yml +119 -47
  38. data/lib/fatty/config_files/themes/monokai.yml +140 -0
  39. data/lib/fatty/config_files/themes/nordic.yml +1 -0
  40. data/lib/fatty/config_files/themes/onedark.yml +140 -0
  41. data/lib/fatty/config_files/themes/solarized_dark.yml +1 -0
  42. data/lib/fatty/config_files/themes/solarized_light.yml +140 -0
  43. data/lib/fatty/config_files/themes/terminal.yml +67 -0
  44. data/lib/fatty/config_files/themes/tokyo_night.yml +140 -0
  45. data/lib/fatty/config_files/themes/wordperfect.yml +80 -9
  46. data/lib/fatty/core_ext/hash.rb +19 -0
  47. data/lib/fatty/core_ext/string.rb +19 -12
  48. data/lib/fatty/core_ext.rb +1 -0
  49. data/lib/fatty/curses/context.rb +86 -84
  50. data/lib/fatty/curses/event_source.rb +128 -40
  51. data/lib/fatty/curses/key_decoder.rb +77 -11
  52. data/lib/fatty/env.rb +21 -20
  53. data/lib/fatty/help.rb +1 -29
  54. data/lib/fatty/history/entry.rb +2 -0
  55. data/lib/fatty/history.rb +17 -14
  56. data/lib/fatty/input_buffer.rb +71 -47
  57. data/lib/fatty/input_field.rb +216 -149
  58. data/lib/fatty/key_event.rb +67 -66
  59. data/lib/fatty/key_map.rb +54 -16
  60. data/lib/fatty/keymaps/emacs.rb +40 -6
  61. data/lib/fatty/log_formats/json.rb +2 -0
  62. data/lib/fatty/log_formats/text.rb +2 -0
  63. data/lib/fatty/logger.rb +7 -2
  64. data/lib/fatty/markdown/ansi_renderer.rb +75 -6
  65. data/lib/fatty/markdown/render.rb +2 -3
  66. data/lib/fatty/mouse_event.rb +142 -2
  67. data/lib/fatty/output_buffer.rb +2 -0
  68. data/lib/fatty/pager.rb +158 -47
  69. data/lib/fatty/progress.rb +417 -0
  70. data/lib/fatty/renderer/curses.rb +340 -184
  71. data/lib/fatty/renderer/truecolor.rb +266 -163
  72. data/lib/fatty/renderer.rb +115 -97
  73. data/lib/fatty/screen.rb +2 -0
  74. data/lib/fatty/session/alert_session.rb +39 -21
  75. data/lib/fatty/session/isearch_session.rb +92 -38
  76. data/lib/fatty/session/keytest_session.rb +105 -85
  77. data/lib/fatty/session/modal_session.rb +38 -1
  78. data/lib/fatty/session/output_session.rb +472 -21
  79. data/lib/fatty/session/popup_session.rb +251 -134
  80. data/lib/fatty/session/prompt_session.rb +68 -26
  81. data/lib/fatty/session/search_session.rb +79 -31
  82. data/lib/fatty/session/shell_session.rb +383 -368
  83. data/lib/fatty/session/status_session.rb +167 -0
  84. data/lib/fatty/session.rb +95 -95
  85. data/lib/fatty/terminal/popup_owner.rb +14 -11
  86. data/lib/fatty/terminal.rb +515 -813
  87. data/lib/fatty/themes/loader.rb +4 -2
  88. data/lib/fatty/themes/manager.rb +4 -0
  89. data/lib/fatty/themes/registry.rb +2 -0
  90. data/lib/fatty/themes/resolver.rb +175 -162
  91. data/lib/fatty/version.rb +1 -1
  92. data/lib/fatty/viewport.rb +8 -1
  93. data/lib/fatty.rb +35 -7
  94. metadata +42 -40
  95. data/.envrc +0 -2
  96. data/.simplecov +0 -23
  97. data/.yardopts +0 -4
  98. data/CHANGELOG.md +0 -34
  99. data/Rakefile +0 -15
  100. data/TODO.org +0 -163
  101. data/examples/markdown/native-markdown.md +0 -370
  102. data/examples/markdown/ox-gfm-markdown.md +0 -373
  103. data/examples/markdown/ox-gfm-markdown.org +0 -376
  104. data/fatty.gemspec +0 -42
  105. data/lib/fatty/accept_env.rb +0 -32
  106. data/lib/fatty/config_files/help.md +0 -120
  107. data/lib/fatty/config_files/help.org +0 -124
  108. data/lib/fatty/config_files/themes/wordperfect_light.yml +0 -77
  109. data/lib/fatty/menu_env.rb +0 -22
  110. data/lib/fatty/session/input_session.rb +0 -99
  111. data/lib/fatty/sessions.rb +0 -14
  112. data/lib/fatty/terminal/progress.rb +0 -374
  113. data/lib/fatty/view/alert_view.rb +0 -14
  114. data/lib/fatty/view/cursor_view.rb +0 -18
  115. data/lib/fatty/view/input_view.rb +0 -9
  116. data/lib/fatty/view/output_view.rb +0 -9
  117. data/lib/fatty/view/status_view.rb +0 -14
  118. data/lib/fatty/view.rb +0 -33
  119. data/lib/fatty/views.rb +0 -9
  120. data/sig/fatty.rbs +0 -4
@@ -37,7 +37,7 @@ module Fatty
37
37
  POPUP_SELECTED_GUTTER = "▶ "
38
38
  POPUP_UNSELECTED_GUTTER = " "
39
39
 
40
- attr_reader :screen, :palette, :context
40
+ attr_reader :screen, :palette, :context, :theme_version
41
41
 
42
42
  def initialize(screen:, palette:, context:)
43
43
  @screen = screen
@@ -49,12 +49,14 @@ module Fatty
49
49
  @last_popup_state = nil
50
50
  @last_prompt_popup_state = nil
51
51
  @last_pager_field_state = nil
52
+ @theme_version = 0
52
53
  end
53
54
 
54
55
  attr_writer :screen
55
56
 
56
57
  def apply_theme!(theme)
57
58
  Fatty::Themes::Manager.set(theme)
59
+ @theme_version += 1
58
60
  theme_spec = Fatty::Themes::Manager.roles(Fatty::Themes::Manager.current) || {}
59
61
  @palette = Fatty::Colors::Palette.compile(theme_spec, available_colors: available_colors)
60
62
 
@@ -75,6 +77,14 @@ module Fatty
75
77
  raise NotImplementedError, "#{self.class} must implement #render_input_field"
76
78
  end
77
79
 
80
+ def clear_input_field(...)
81
+ raise NotImplementedError, "#{self.class} must implement #clear_input_field"
82
+ end
83
+
84
+ def restore_cursor(...)
85
+ raise NotImplementedError, "#{self.class} must implement #restore_cursor"
86
+ end
87
+
78
88
  def render_pager_field(...)
79
89
  raise NotImplementedError, "#{self.class} must implement #render_pager_field"
80
90
  end
@@ -98,10 +108,23 @@ module Fatty
98
108
  @last_status_state = nil
99
109
  @last_pager_field_state = nil
100
110
  @last_popup_state = nil
111
+ @last_prompt_popup_state = nil
112
+ end
113
+
114
+ def hide_cursor
115
+ end
116
+
117
+ def show_cursor
101
118
  end
102
119
 
103
120
  protected
104
121
 
122
+ # simplecov:disable
123
+
124
+ def alert_role(role)
125
+ :"alert_#{role}"
126
+ end
127
+
105
128
  def available_colors
106
129
  nil
107
130
  end
@@ -110,74 +133,37 @@ module Fatty
110
133
  nil
111
134
  end
112
135
 
113
- def alert_state(alert)
114
- [
115
- alert&.message.dup.freeze,
116
- alert&.role,
117
- alert&.details,
118
- screen.alert_rect.row,
119
- screen.alert_rect.cols,
120
- ]
136
+ def alert_state(session)
137
+ session.state
121
138
  end
122
139
 
123
- def status_state(text, role)
124
- [
125
- renderable_segments(text, role: role).map { |segment|
126
- [
127
- segment[:text].to_s.dup.freeze,
128
- segment[:role],
129
- segment[:style],
130
- ].freeze
131
- }.freeze,
132
- role,
133
- screen.status_rect.row,
134
- screen.status_rect.rows,
135
- screen.status_rect.cols,
136
- ]
140
+ def status_state(session)
141
+ session.state
137
142
  end
138
143
 
139
144
  def popup_state(session)
140
145
  [
141
146
  popup_border,
142
- session.title.to_s.dup.freeze,
143
- session.message.to_s.dup.freeze,
144
- session.displayed.map { |item| item.to_s.dup.freeze }.freeze,
145
- session.selected,
146
- session.field.buffer.text.to_s.dup.freeze,
147
- session.field.buffer.cursor,
148
- session.field.buffer.virtual_suffix.to_s.dup.freeze,
149
- session.selected_labels.map { |label| label.to_s.dup.freeze }.sort.freeze,
150
- session.counts&.dup&.freeze,
151
- screen.rows,
152
- screen.cols,
147
+ session.state
153
148
  ]
154
149
  end
155
150
 
156
151
  def prompt_popup_state(session)
157
152
  [
158
153
  popup_border,
159
- session.title.to_s.dup.freeze,
160
- session.message.to_s.dup.freeze,
161
- session.field.prompt_text.to_s.dup.freeze,
162
- session.field.buffer.text.to_s.dup.freeze,
163
- session.field.buffer.cursor,
164
- session.field.buffer.virtual_suffix.to_s.dup.freeze,
165
- screen.rows,
166
- screen.cols,
154
+ session.state
167
155
  ]
168
156
  end
169
157
 
170
- def output_state(viewport:, lines:, highlights:)
171
- {
172
- top: viewport.top,
173
- height: viewport.height,
174
- width: viewport.respond_to?(:width) ? viewport.width : screen.output_rect.cols,
175
- col: viewport.respond_to?(:col) ? viewport.col : 0,
176
- lines: lines.map { |line| line.to_s.dup.freeze }.freeze,
177
- highlights: normalized_highlights_state(highlights),
178
- output_rows: screen.output_rect.rows,
179
- output_cols: screen.output_rect.cols,
180
- }.freeze
158
+ def output_state(session, viewport: session.viewport)
159
+ session.state(viewport: viewport)
160
+ end
161
+
162
+ def input_field_state(input_field)
163
+ [
164
+ input_field.state,
165
+ theme_version
166
+ ]
181
167
  end
182
168
 
183
169
  def pager_field_state(field, row:, role:)
@@ -201,20 +187,43 @@ module Fatty
201
187
  }.join
202
188
  end
203
189
 
204
- def status_render_lines(text, width:, max_rows:)
205
- width = [width.to_i, 1].max
206
- max_rows = [max_rows.to_i, 1].max
207
-
208
- lines =
209
- renderable_text(text)
210
- .to_s
211
- .lines
212
- .flat_map do |line|
213
- wrap_status_line(line.chomp, width: width)
190
+ def status_segment_lines(status_session)
191
+ segments = renderable_segments(
192
+ status_session.text,
193
+ role: status_session.role,
194
+ )
195
+ segment_lines(segments, width: screen.status_rect.cols)
196
+ .last(screen.status_rect.rows)
197
+ end
198
+
199
+ def segment_lines(segments, width:)
200
+ lines = [[]]
201
+ col = 0
202
+ segments.each do |segment|
203
+ text = segment[:text].to_s
204
+ text.each_line do |raw|
205
+ rest = raw.chomp
206
+ until rest.empty?
207
+ remaining = width - col
208
+ if remaining <= 0
209
+ lines << []
210
+ col = 0
211
+ remaining = width
212
+ end
213
+ piece = Fatty::Ansi.truncate_visible(rest, remaining)
214
+ break if piece.empty?
215
+
216
+ lines.last << segment.merge(text: piece)
217
+ col += Fatty::Ansi.visible_length(piece)
218
+ rest = rest[piece.length..].to_s
219
+ end
220
+ if raw.end_with?("\n")
221
+ lines << []
222
+ col = 0
223
+ end
224
+ end
214
225
  end
215
-
216
- lines = [""] if lines.empty?
217
- lines.last(max_rows)
226
+ lines
218
227
  end
219
228
 
220
229
  def wrap_status_line(line, width:)
@@ -234,18 +243,35 @@ module Fatty
234
243
  end
235
244
 
236
245
  def renderable_segments(value, role:)
237
- renderable_parts(value).map do |part|
238
- if part.is_a?(Hash) && part.key?(:text)
246
+ renderable_parts(value).flat_map do |part|
247
+ part_role =
248
+ if part.is_a?(Hash) && part.key?(:text)
249
+ part[:role] || role
250
+ else
251
+ role
252
+ end
253
+
254
+ text =
255
+ if part.is_a?(Hash) && part.key?(:text)
256
+ part[:text].to_s
257
+ else
258
+ part.to_s
259
+ end
260
+
261
+ if part.is_a?(Hash) && part[:style]
239
262
  {
240
- text: part[:text].to_s,
241
- role: part[:role] || role,
263
+ text: text,
264
+ role: part_role,
242
265
  style: part[:style],
243
- }.compact
244
- else
245
- {
246
- text: part.to_s,
247
- role: role,
248
266
  }
267
+ else
268
+ Fatty::Ansi.segment(text).map do |segment_text, style|
269
+ {
270
+ text: segment_text,
271
+ role: part_role,
272
+ style: style,
273
+ }
274
+ end
249
275
  end
250
276
  end
251
277
  end
@@ -254,19 +280,6 @@ module Fatty
254
280
  value.is_a?(Array) ? value : [value]
255
281
  end
256
282
 
257
- def input_field_state(field)
258
- [
259
- field.prompt_text.to_s.dup.freeze,
260
- field.buffer.text.to_s.dup.freeze,
261
- field.buffer.cursor,
262
- field.buffer.virtual_suffix.to_s.dup.freeze,
263
- field.buffer.region_active?,
264
- field.buffer.region_range,
265
- screen.input_rect.row,
266
- screen.input_rect.cols,
267
- ]
268
- end
269
-
270
283
  def popup_counts_text(session)
271
284
  counts = session.counts
272
285
 
@@ -327,12 +340,12 @@ module Fatty
327
340
  highlights.each_with_object({}) do |(line_no, ranges), out|
328
341
  out[line_no] =
329
342
  Array(ranges).map do |r|
330
- if r.is_a?(Hash)
331
- [r[:from].to_i, r[:to].to_i, (r[:role] || :primary).to_sym]
332
- else
333
- [r[0].to_i, r[1].to_i, (r[2] || :primary).to_sym]
343
+ if r.is_a?(Hash)
344
+ [r[:from].to_i, r[:to].to_i, (r[:role] || :primary).to_sym]
345
+ else
346
+ [r[0].to_i, r[1].to_i, (r[2] || :primary).to_sym]
347
+ end
334
348
  end
335
- end
336
349
  end
337
350
  end
338
351
 
@@ -343,9 +356,7 @@ module Fatty
343
356
  def deep_state(value)
344
357
  case value
345
358
  when Hash
346
- value.to_h do |key, val|
347
- [deep_state(key), deep_state(val)]
348
- end.freeze
359
+ value.to_h { |key, val| [deep_state(key), deep_state(val)] }.freeze
349
360
  when Array
350
361
  value.map { |item| deep_state(item) }.freeze
351
362
  when String
@@ -384,7 +395,14 @@ module Fatty
384
395
  def field_segments(field, base_role:, suggestion_role: :input_suggestion, region_role: :region)
385
396
  buf = field.buffer
386
397
  text = buf.text.to_s
387
- segments = [{ text: field.prompt_text.to_s, role: base_role }]
398
+ segments =
399
+ Fatty::Ansi.segment(field.prompt_text.to_s).map do |prompt_text, style|
400
+ {
401
+ text: prompt_text,
402
+ role: base_role,
403
+ style: style,
404
+ }
405
+ end
388
406
 
389
407
  region =
390
408
  if buf.respond_to?(:region_range)
data/lib/fatty/screen.rb CHANGED
@@ -42,6 +42,8 @@ module Fatty
42
42
 
43
43
  private
44
44
 
45
+ # simplecov:disable
46
+
45
47
  # Default layout:
46
48
  # - status: 1 row above input (when it has content)
47
49
  # - input: 1 row above alert
@@ -2,37 +2,56 @@
2
2
 
3
3
  module Fatty
4
4
  # A pinned, non-interactive overlay session responsible for rendering alerts.
5
- #
6
- # It is intentionally dumb:
7
- # - Terminal does not special-case alerts
8
- # - other sessions emit commands like:
9
- # [:send, :alert, :show, { level:, message: }]
10
- # [:send, :alert, :clear, {}]
11
5
  class AlertSession < Session
12
6
  attr_reader :current
13
7
 
14
- def initialize
15
- super(views: [Fatty::AlertView.new(z: 1_000)])
8
+ def initialize(id: nil)
9
+ super
16
10
  @current = nil
17
11
  end
18
12
 
19
- def id
20
- :alert
21
- end
22
-
23
- private
13
+ #########################################################################################
14
+ # Session Protocol
15
+ #########################################################################################
24
16
 
25
- def update_cmd(name, payload)
26
- payload ||= {}
27
- case name
17
+ def update(command)
18
+ Fatty.debug("AlertSession#update: action: #{command.action} alert: #{command.payload[:alert].inspect}")
19
+ case command.action
28
20
  when :show
29
- show_from_payload(payload)
21
+ show_from_payload(command.payload[:alert] || command.payload)
30
22
  when :clear
31
23
  @current = nil unless @current&.sticky?
32
24
  end
33
25
  []
34
26
  end
35
27
 
28
+ def view
29
+ renderer.render_alert(self)
30
+ end
31
+
32
+ def state
33
+ [
34
+ current&.text.dup.freeze,
35
+ current&.role,
36
+ current&.details,
37
+ renderer.screen.alert_rect.row,
38
+ renderer.screen.alert_rect.cols,
39
+ renderer.theme_version
40
+ ]
41
+ end
42
+
43
+ private
44
+
45
+ # simplecov:disable
46
+
47
+ def clear
48
+ @current = nil
49
+ end
50
+
51
+ def visible?
52
+ !!current
53
+ end
54
+
36
55
  def show_from_payload(payload)
37
56
  return if payload.nil?
38
57
 
@@ -41,12 +60,11 @@ module Fatty
41
60
  return
42
61
  end
43
62
 
44
- level = (payload[:level] || :info).to_sym
45
- message = (payload[:message] || payload[:text]).to_s
63
+ role = (payload[:role] || :info).to_sym
64
+ text = payload[:text].to_s
46
65
  details = payload[:details]
47
66
  sticky = !!payload[:sticky]
48
-
49
- @current = Fatty::Alert.new(level: level, message: message, details: details, sticky: sticky)
67
+ @current = Fatty::Alert.new(role: role, text: text, details: details, sticky: sticky)
50
68
  end
51
69
  end
52
70
  end
@@ -4,7 +4,7 @@ module Fatty
4
4
  class ISearchSession < Session
5
5
  action_on :session
6
6
 
7
- attr_reader :field, :direction
7
+ attr_reader :field, :direction, :last_pattern
8
8
 
9
9
  def id = :isearch
10
10
 
@@ -12,33 +12,58 @@ module Fatty
12
12
  DEFAULT_ISEARCH_HISTORY_MAX = 200
13
13
 
14
14
  def initialize(direction: :forward, last_pattern: nil, history: nil)
15
- super(keymap: Keymaps.emacs, views: [])
16
-
15
+ super(keymap: Keymaps.emacs)
17
16
  @direction = direction.to_sym
18
17
  @failed = false
19
18
  @last_text = nil
20
19
  @last_pattern = last_pattern.to_s
21
-
22
20
  @field = Fatty::InputField.new(
23
21
  prompt: Prompt.new { isearch_prompt },
24
22
  history: history,
25
23
  history_kind: :search_string,
26
- # ? history_ctx: -> { { session: "pager_isearch" } },
24
+ history_ctx: { kind: :search, regex: false },
27
25
  )
28
26
  end
29
27
 
30
28
  #########################################################################################
31
- # Framework and Session Hooks
29
+ # Session Protocol
32
30
  #########################################################################################
33
31
 
34
- def keymap_contexts
35
- [:isearch, :text, :terminal]
36
- end
37
-
38
- def view(screen:, renderer:)
32
+ def update(command)
33
+ log_update(command)
34
+ commands =
35
+ case command.action
36
+ when :key
37
+ ev = command.payload.fetch(:event)
38
+ action, args = resolve_action(ev)
39
+ if action
40
+ apply_action(action, args, event: ev)
41
+ else
42
+ []
43
+ end
44
+ when :terminal_paste
45
+ env = action_env(event: nil)
46
+ @field.act_on(
47
+ :paste,
48
+ command.payload.fetch(:text, ""),
49
+ env: env,
50
+ )
51
+ @field.sync_virtual_suffix!
52
+ maybe_preview!
53
+ when :isearch_set_failed
54
+ @failed = !!command.payload[:failed]
55
+ @field.prompt = isearch_prompt
56
+ []
57
+ else
58
+ []
59
+ end
60
+ Array(commands)
61
+ end
62
+
63
+ def view
39
64
  row = screen.output_rect.rows - 1
40
65
 
41
- ::Curses.curs_set(1)
66
+ renderer.show_cursor
42
67
  renderer.render_pager_field(@field, row: row, role: :search_input)
43
68
  renderer.restore_output_cursor(@field, row: row)
44
69
  end
@@ -69,14 +94,10 @@ module Fatty
69
94
 
70
95
  private
71
96
 
72
- def update_cmd(name, payload)
73
- cmds = []
74
- case name
75
- when :isearch_set_failed
76
- @failed = !!payload[:failed]
77
- @field.prompt = isearch_prompt
78
- end
79
- cmds
97
+ # simplecov:disable
98
+
99
+ def keymap_contexts
100
+ [:isearch, :text, :terminal]
80
101
  end
81
102
 
82
103
  def action_env(event:)
@@ -89,13 +110,14 @@ module Fatty
89
110
  )
90
111
  end
91
112
 
92
- def handle_action(action, args, event:)
113
+ def apply_action(action, args, event:)
93
114
  env = action_env(event: event)
94
115
 
95
116
  if Fatty::Actions.lookup(action)&.fetch(:on) == :session
96
117
  Fatty::Actions.call(action, env, *args)
97
118
  else
98
119
  @field.act_on(action, *args, env: env)
120
+ @field.sync_virtual_suffix!
99
121
  maybe_preview!
100
122
  end
101
123
  rescue Fatty::ActionError
@@ -110,30 +132,58 @@ module Fatty
110
132
 
111
133
  def accept!
112
134
  pattern = @field.accept_line.to_s
113
- cmds = []
114
- cmds << [:terminal, :send_modal_owner, [:cmd, :pager_isearch_commit, { pattern: pattern, direction: @direction }]]
115
- cmds << [:terminal, :pop_modal]
116
- cmds
135
+ [
136
+ Command.terminal(
137
+ :send_modal_owner,
138
+ command: Command.session(
139
+ :focused,
140
+ :pager_isearch_commit,
141
+ pattern: pattern,
142
+ direction: @direction,
143
+ ),
144
+ ),
145
+ Command.terminal(:pop_modal),
146
+ ]
117
147
  end
118
148
 
119
149
  def cancel!
120
- [[:terminal, :send_modal_owner, [:cmd, :pager_isearch_cancel, {}]], [:terminal, :pop_modal]]
150
+ [
151
+ Command.terminal(
152
+ :send_modal_owner,
153
+ command: Command.session(:focused, :pager_isearch_cancel),
154
+ ),
155
+ Command.terminal(:pop_modal),
156
+ ]
121
157
  end
122
158
 
123
159
  def step_next!
124
160
  @direction = :forward
125
- cmds = []
126
- cmds.concat(prefill_last_pattern_if_empty!)
127
- cmds << [:terminal, :send_modal_owner, [:cmd, :pager_isearch_step, { direction: @direction }]]
128
- cmds
161
+
162
+ prefill_last_pattern_if_empty! + [
163
+ Command.terminal(
164
+ :send_modal_owner,
165
+ command: Command.session(
166
+ :focused,
167
+ :pager_isearch_step,
168
+ direction: @direction,
169
+ ),
170
+ ),
171
+ ]
129
172
  end
130
173
 
131
174
  def step_prev!
132
175
  @direction = :backward
133
- cmds = []
134
- cmds.concat(prefill_last_pattern_if_empty!)
135
- cmds << [:terminal, :send_modal_owner, [:cmd, :pager_isearch_step, { direction: @direction }]]
136
- cmds
176
+
177
+ prefill_last_pattern_if_empty! + [
178
+ Command.terminal(
179
+ :send_modal_owner,
180
+ command: Command.session(
181
+ :focused,
182
+ :pager_isearch_step,
183
+ direction: @direction,
184
+ ),
185
+ ),
186
+ ]
137
187
  end
138
188
 
139
189
  def prefill_last_pattern_if_empty!
@@ -161,11 +211,15 @@ module Fatty
161
211
 
162
212
  @last_text = text.dup
163
213
  [
164
- [
165
- :terminal,
214
+ Command.terminal(
166
215
  :send_modal_owner,
167
- [:cmd, :pager_isearch_update, { pattern: text, direction: @direction }],
168
- ]
216
+ command: Command.session(
217
+ :focused,
218
+ :pager_isearch_update,
219
+ pattern: text,
220
+ direction: @direction,
221
+ ),
222
+ ),
169
223
  ]
170
224
  end
171
225
  end