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
@@ -11,26 +11,26 @@ module Fatty
11
11
  def id = :prompt
12
12
 
13
13
  def initialize(initial: "", prompt: "> ", title: "Prompt", message: nil, kind: nil,
14
- history_ctx: nil, history_path: :default)
15
- super(keymap: Keymaps.emacs, views: [])
14
+ history_ctx: nil, history_path: :default, history: nil, save_history: true)
15
+ super(keymap: Keymaps.emacs)
16
16
  @title = title&.to_s
17
17
  @message = message&.to_s
18
18
  @kind = kind&.to_sym
19
-
20
- @history = Fatty::History.for_path(history_path)
19
+ @save_history = !!save_history
20
+ @history = history || Fatty::History.for_path(history_path)
21
21
  @field = Fatty::InputField.new(
22
22
  prompt: prompt,
23
- history: @history,
24
23
  history_kind: :prompt,
24
+ history: @history,
25
25
  history_ctx: history_ctx,
26
26
  )
27
27
  @field.buffer.replace(initial.to_s)
28
-
28
+ @field.buffer.bol
29
29
  @win = nil
30
30
  end
31
31
 
32
32
  #########################################################################################
33
- # Framework and Session Hooks
33
+ # Session Protocol
34
34
  #########################################################################################
35
35
 
36
36
  def init(terminal:)
@@ -39,11 +39,27 @@ module Fatty
39
39
  []
40
40
  end
41
41
 
42
- def keymap_contexts
43
- [:prompt, :text, :terminal]
42
+ def update(command)
43
+ commands =
44
+ case command.action
45
+ when :key
46
+ ev = command.payload.fetch(:event)
47
+ action, args = resolve_action(ev)
48
+ if action
49
+ normalize_action_result(apply_action(action, args, event: ev))
50
+ else
51
+ []
52
+ end
53
+ when :terminal_paste
54
+ field.act_on(:paste, command.payload.fetch(:text, ""), env: action_env(event: nil))
55
+ []
56
+ else
57
+ []
58
+ end
59
+ Array(commands)
44
60
  end
45
61
 
46
- def view(screen:, renderer:)
62
+ def view
47
63
  return unless @win
48
64
 
49
65
  renderer.render_prompt_popup(session: self)
@@ -55,20 +71,26 @@ module Fatty
55
71
 
56
72
  action_on :session
57
73
 
58
- desc "Accept prompt input"
59
74
  action :prompt_accept do
60
- text = @field.accept_line.to_s
75
+ text = @field.accept_line(save_history: @save_history).to_s
76
+
61
77
  [
62
- [:terminal, :send_modal_owner, [:cmd, :prompt_result, { kind: @kind, text: text }]],
63
- [:terminal, :pop_modal],
78
+ Command.terminal(
79
+ :send_modal_owner,
80
+ command: Command.session(:self, :prompt_result, kind: @kind, text: text),
81
+ ),
82
+ Command.terminal(:pop_modal),
64
83
  ]
65
84
  end
66
85
 
67
86
  desc "Cancel prompt input"
68
87
  action :prompt_cancel do
69
88
  [
70
- [:terminal, :send_modal_owner, [:cmd, :prompt_cancelled, prompt_payload]],
71
- [:terminal, :pop_modal],
89
+ Command.terminal(
90
+ :send_modal_owner,
91
+ command: Command.session(:self, :prompt_cancelled, **prompt_payload),
92
+ ),
93
+ Command.terminal(:pop_modal),
72
94
  ]
73
95
  end
74
96
 
@@ -82,16 +104,38 @@ module Fatty
82
104
  end
83
105
  end
84
106
 
85
- def handle_action(action, args, event:)
86
- env = action_env(event: event)
107
+ #########################################################################################
108
+ # Other public API methods
109
+ #########################################################################################
87
110
 
88
- result =
89
- with_virtual_suffix_sync do
90
- @field.act_on(action, *args, env: env)
91
- end
92
- result.is_a?(Array) ? result : []
111
+ def state
112
+ [
113
+ title.to_s.dup.freeze,
114
+ message.to_s.dup.freeze,
115
+ field.prompt_text.to_s.dup.freeze,
116
+ field.buffer.text.to_s.dup.freeze,
117
+ field.buffer.cursor,
118
+ field.buffer.virtual_suffix.to_s.dup.freeze,
119
+ renderer.screen.rows,
120
+ renderer.screen.cols,
121
+ ]
122
+ end
123
+
124
+ private
125
+
126
+ # simplecov:disable
127
+
128
+ def keymap_contexts
129
+ [:prompt, :text, :terminal]
130
+ end
131
+
132
+ def apply_action(action, args, event:)
133
+ env = action_env(event: event)
134
+ with_virtual_suffix_sync do
135
+ @field.act_on(action, *args, env: env)
136
+ end
93
137
  rescue ActionError => e
94
- Fatty.error("PromptSession#handle_action: ActionError #{e.message}", tag: :session)
138
+ Fatty.error("PromptSession#apply_action: ActionError #{e.message}", tag: :session)
95
139
  []
96
140
  end
97
141
 
@@ -135,8 +179,6 @@ module Fatty
135
179
  result
136
180
  end
137
181
 
138
- private
139
-
140
182
  def prompt_payload
141
183
  {
142
184
  kind: @kind,
@@ -10,34 +10,49 @@ module Fatty
10
10
  DEFAULT_SEARCH_HISTORY_MAX = 200
11
11
 
12
12
  def initialize(direction: :backward, regex: false, history: nil, prefix: nil)
13
- super(keymap: Keymaps.emacs, views: [])
14
-
13
+ super(keymap: Keymaps.emacs)
15
14
  @direction = direction.to_sym
16
15
  @regex = !!regex
17
-
18
16
  prompt = search_prompt(direction: @direction, regex: @regex)
19
-
17
+ search_session = self
20
18
  @field = Fatty::InputField.new(
21
19
  prompt: prompt,
22
20
  history: history,
23
- history_kind: -> { @regex ? :search_regex : :search_string },
21
+ history_kind: -> { search_session.regex ? :search_regex : :search_string },
22
+ history_ctx: -> { { kind: :search, regex: search_session.regex } },
24
23
  )
25
24
  text = prefix.to_s
26
25
  @field.buffer.replace(text) unless text.empty?
27
26
  end
28
27
 
29
28
  #########################################################################################
30
- # Framework and Session Hooks
29
+ # Session Prototcol
31
30
  #########################################################################################
32
31
 
33
- def keymap_contexts
34
- [:search, :text, :terminal]
32
+ def update(command)
33
+ commands =
34
+ case command.action
35
+ when :terminal_paste
36
+ field.act_on(:paste, command.payload.fetch(:text, ""), env: action_env(event: nil))
37
+ []
38
+ when :key
39
+ ev = command.payload.fetch(:event)
40
+ action, args = resolve_action(ev)
41
+ if action
42
+ normalize_action_result(apply_action(action, args, event: ev))
43
+ else
44
+ []
45
+ end
46
+ else
47
+ []
48
+ end
49
+ Array(commands)
35
50
  end
36
51
 
37
- def view(screen:, renderer:)
52
+ def view
38
53
  row = screen.output_rect.rows - 1
39
54
 
40
- ::Curses.curs_set(1)
55
+ renderer.show_cursor
41
56
  renderer.render_pager_field(
42
57
  @field,
43
58
  row: row,
@@ -75,34 +90,42 @@ module Fatty
75
90
  step_search(:backward)
76
91
  end
77
92
 
78
- def handle_action(action, args, event:)
79
- env = ActionEnvironment.new(
80
- session: self,
81
- counter: counter,
82
- event: event,
83
- buffer: @field.buffer,
84
- field: @field,
85
- )
93
+ private
94
+
95
+ # simplecov:disable
96
+
97
+ def keymap_contexts
98
+ [:search, :text, :terminal]
99
+ end
86
100
 
101
+ def apply_action(action, args, event:)
102
+ env = action_env(event)
87
103
  if Fatty::Actions.lookup(action)&.fetch(:on) == :session
88
104
  Fatty::Actions.call(action, env, *args)
89
105
  else
90
106
  @field.act_on(action, *args, env: env)
107
+ @field.sync_virtual_suffix!
91
108
  end
92
109
  rescue Fatty::ActionError
93
110
  []
94
111
  end
95
112
 
113
+ def action_env(event)
114
+ ActionEnvironment.new(
115
+ session: self,
116
+ counter: counter,
117
+ event: event,
118
+ buffer: @field.buffer,
119
+ field: @field,
120
+ )
121
+ end
122
+
96
123
  def toggle_regex
97
124
  @regex = !@regex
98
125
  @field.prompt = search_prompt(direction: @direction, regex: @regex)
99
126
  []
100
127
  end
101
128
 
102
- def cancel!
103
- [[:terminal, :pop_modal]]
104
- end
105
-
106
129
  def search_prompt(direction:, regex:)
107
130
  label =
108
131
  if regex
@@ -116,21 +139,46 @@ module Fatty
116
139
  dir + label
117
140
  end
118
141
 
142
+ def cancel!
143
+ [
144
+ Command.terminal(
145
+ :send_modal_owner,
146
+ command: Command.session(:focused, :pager_search_cancel),
147
+ ),
148
+ Command.terminal(:pop_modal),
149
+ ]
150
+ end
151
+
119
152
  def search_accept
120
153
  pattern = @field.accept_line.to_s
121
-
122
- cmds = []
123
- cmds << [
124
- :terminal,
125
- :send_modal_owner,
126
- [:cmd, :pager_search_set, { pattern: pattern, direction: direction, regex: regex }]
154
+ [
155
+ Command.terminal(
156
+ :send_modal_owner,
157
+ command: Command.session(
158
+ :focused,
159
+ :pager_search_set,
160
+ pattern: pattern,
161
+ direction: direction,
162
+ regex: regex,
163
+ ),
164
+ ),
165
+ Command.terminal(:pop_modal),
127
166
  ]
128
- cmds << [:terminal, :pop_modal]
129
- cmds
130
167
  end
131
168
 
132
169
  def step_search(dir)
133
- [[:terminal, :send_modal_owner, [:cmd, :pager_search_step, { direction: dir }]]]
170
+ [
171
+ Command.terminal(
172
+ :send_modal_owner,
173
+ command: Command.session(
174
+ :focused,
175
+ :pager_search_step,
176
+ pattern: @field.buffer.text.to_s,
177
+ regex: regex,
178
+ direction: dir,
179
+ ),
180
+ ),
181
+ ]
134
182
  end
135
183
  end
136
184
  end