charming 0.1.2 → 0.1.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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/lib/charming/application.rb +3 -3
  3. data/lib/charming/controller/class_methods.rb +2 -2
  4. data/lib/charming/controller/command_palette.rb +2 -2
  5. data/lib/charming/controller/rendering.rb +2 -2
  6. data/lib/charming/controller/session_state.rb +1 -1
  7. data/lib/charming/generators/component_generator.rb +1 -1
  8. data/lib/charming/generators/templates/app/application.template +1 -1
  9. data/lib/charming/generators/templates/app/layout.template +3 -6
  10. data/lib/charming/generators/templates/app/view.template +1 -1
  11. data/lib/charming/generators/templates/component/component.rb.template +1 -1
  12. data/lib/charming/generators/templates/screen/view.rb.template +1 -1
  13. data/lib/charming/generators/templates/view/view.rb.template +1 -1
  14. data/lib/charming/internal/renderer/differential.rb +13 -5
  15. data/lib/charming/internal/terminal/tty_backend.rb +22 -2
  16. data/lib/charming/presentation/component.rb +3 -5
  17. data/lib/charming/presentation/components/activity_indicator.rb +173 -134
  18. data/lib/charming/presentation/components/command_palette.rb +94 -96
  19. data/lib/charming/presentation/components/command_palette_modal.rb +33 -0
  20. data/lib/charming/presentation/components/empty_state.rb +47 -49
  21. data/lib/charming/presentation/components/form/builder.rb +52 -54
  22. data/lib/charming/presentation/components/form/confirm.rb +49 -51
  23. data/lib/charming/presentation/components/form/field.rb +94 -96
  24. data/lib/charming/presentation/components/form/input.rb +53 -55
  25. data/lib/charming/presentation/components/form/note.rb +27 -29
  26. data/lib/charming/presentation/components/form/select.rb +84 -86
  27. data/lib/charming/presentation/components/form/textarea.rb +67 -69
  28. data/lib/charming/presentation/components/form.rb +120 -122
  29. data/lib/charming/presentation/components/keyboard_handler.rb +41 -43
  30. data/lib/charming/presentation/components/list.rb +123 -125
  31. data/lib/charming/presentation/components/markdown.rb +21 -23
  32. data/lib/charming/presentation/components/modal.rb +46 -48
  33. data/lib/charming/presentation/components/progressbar.rb +51 -53
  34. data/lib/charming/presentation/components/spinner.rb +40 -42
  35. data/lib/charming/presentation/components/table.rb +109 -111
  36. data/lib/charming/presentation/components/text_area.rb +219 -221
  37. data/lib/charming/presentation/components/text_input.rb +120 -122
  38. data/lib/charming/presentation/components/viewport.rb +218 -220
  39. data/lib/charming/presentation/layout/builder.rb +64 -66
  40. data/lib/charming/presentation/layout/overlay.rb +48 -50
  41. data/lib/charming/presentation/layout/pane.rb +122 -118
  42. data/lib/charming/presentation/layout/rect.rb +14 -16
  43. data/lib/charming/presentation/layout/screen_layout.rb +40 -42
  44. data/lib/charming/presentation/layout/split.rb +101 -103
  45. data/lib/charming/presentation/layout.rb +28 -30
  46. data/lib/charming/presentation/markdown/block_renderers.rb +94 -96
  47. data/lib/charming/presentation/markdown/inline_renderers.rb +52 -54
  48. data/lib/charming/presentation/markdown/render_context.rb +12 -14
  49. data/lib/charming/presentation/markdown/renderer.rb +84 -86
  50. data/lib/charming/presentation/markdown/syntax_highlighter.rb +57 -59
  51. data/lib/charming/presentation/markdown.rb +4 -6
  52. data/lib/charming/presentation/template_view.rb +22 -24
  53. data/lib/charming/presentation/templates/erb_handler.rb +4 -6
  54. data/lib/charming/presentation/templates.rb +47 -49
  55. data/lib/charming/presentation/ui/ansi_codes.rb +66 -68
  56. data/lib/charming/presentation/ui/ansi_slicer.rb +67 -69
  57. data/lib/charming/presentation/ui/border.rb +24 -26
  58. data/lib/charming/presentation/ui/border_painter.rb +37 -39
  59. data/lib/charming/presentation/ui/canvas.rb +59 -61
  60. data/lib/charming/presentation/ui/style.rb +173 -175
  61. data/lib/charming/presentation/ui/theme.rb +133 -135
  62. data/lib/charming/presentation/ui/width.rb +12 -14
  63. data/lib/charming/presentation/ui.rb +69 -71
  64. data/lib/charming/presentation/view.rb +103 -105
  65. data/lib/charming/runtime.rb +23 -10
  66. data/lib/charming/version.rb +1 -1
  67. data/lib/charming.rb +3 -2
  68. metadata +2 -1
@@ -1,128 +1,126 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Charming
4
- module Presentation
5
- module Components
6
- # TextInput is a single-line text editor component. Supports printable character insertion,
7
- # cursor movement (left/right/home/end), and deletion (backspace/delete). The component
8
- # exposes its `value` and `cursor` positions as reader methods; when an explicit `width:`
9
- # is given, the rendered output is padded to that width via a UI::Style.
10
- class TextInput < Component
11
- include KeyboardHandler
12
-
13
- # Maps editing keys (left/right/home/end/backspace/delete) to the instance
14
- # methods they dispatch via KeyboardHandler. Each symbol key (e.g., :left)
15
- # maps to a method (e.g., :move_left) that adjusts cursor position or text content.
16
- KEY_ACTIONS = {
17
- left: :move_left,
18
- right: :move_right,
19
- home: :move_home,
20
- end: :move_end,
21
- backspace: :delete_before_cursor,
22
- delete: :delete_at_cursor
23
- }.freeze
24
-
25
- # The current input string and the byte offset of the cursor within it.
26
- attr_reader :value, :cursor
27
-
28
- # *value* is the initial text. *placeholder* is shown when the value is empty.
29
- # *width* optionally constrains the rendered output width; *cursor* defaults to the end.
30
- def initialize(value: "", placeholder: "", width: nil, cursor: nil)
31
- super()
32
- @value = value.dup
33
- @placeholder = placeholder
34
- @width = width
35
- @cursor = cursor || @value.length
36
- clamp_position
37
- end
38
-
39
- # Handles key events. Inserts printable characters, otherwise dispatches via KEY_ACTIONS.
40
- # Returns :handled when the event was consumed, nil otherwise.
41
- def handle_key(event)
42
- return :handled if character_event?(event) && insert(event.char)
43
-
44
- super
45
- end
46
-
47
- # Renders the value with a cursor marker. When *width* was given at construction, the
48
- # output is padded to that width via the configured style.
49
- def render
50
- rendered = render_value
51
- @width ? style.width(@width).render(rendered) : rendered
52
- end
53
-
54
- private
55
-
56
- attr_reader :placeholder
57
-
58
- # True when *event* carries a single printable character that should be inserted.
59
- def character_event?(event)
60
- event.respond_to?(:char) && event.char && event.char.length == 1 && printable?(event.char)
61
- end
62
-
63
- # True when *char* is not a control character (and therefore safe to insert).
64
- def printable?(char)
65
- !char.match?(/[[:cntrl:]]/)
66
- end
67
-
68
- # Inserts *char* at the cursor and advances the cursor by its byte length.
69
- def insert(char)
70
- @value = value[0...cursor] + char + value[cursor..]
71
- @cursor += char.length
72
- end
73
-
74
- # Moves the cursor one position left, when possible.
75
- def move_left
76
- @cursor -= 1 if cursor.positive?
77
- end
78
-
79
- # Moves the cursor one position right, when possible.
80
- def move_right
81
- @cursor += 1 if cursor < value.length
82
- end
83
-
84
- # Moves the cursor to the start of the value.
85
- def move_home
86
- @cursor = 0
87
- end
88
-
89
- # Moves the cursor to the end of the value.
90
- def move_end
91
- @cursor = value.length
92
- end
93
-
94
- # Deletes the character before the cursor (backspace behavior).
95
- def delete_before_cursor
96
- return if cursor.zero?
97
-
98
- @value = value[0...(cursor - 1)] + value[cursor..]
99
- @cursor -= 1
100
- end
101
-
102
- # Deletes the character at the cursor (delete-key behavior).
103
- def delete_at_cursor
104
- return if cursor >= value.length
105
-
106
- @value = value[0...cursor] + value[(cursor + 1)..]
107
- end
108
-
109
- # Renders the value with a "|" cursor marker at the current position. When the value is
110
- # empty, the placeholder is rendered instead, preceded by the cursor marker.
111
- def render_value
112
- return cursor_marker + placeholder if value.empty?
113
-
114
- value[0...cursor] + cursor_marker + value[cursor..]
115
- end
116
-
117
- # The literal character used to mark the cursor position in `render`.
118
- def cursor_marker
119
- "|"
120
- end
121
-
122
- # Clamps the cursor to the valid range `[0, value.length]`.
123
- def clamp_position
124
- @cursor = cursor.clamp(0, value.length)
125
- end
4
+ module Components
5
+ # TextInput is a single-line text editor component. Supports printable character insertion,
6
+ # cursor movement (left/right/home/end), and deletion (backspace/delete). The component
7
+ # exposes its `value` and `cursor` positions as reader methods; when an explicit `width:`
8
+ # is given, the rendered output is padded to that width via a UI::Style.
9
+ class TextInput < Component
10
+ include KeyboardHandler
11
+
12
+ # Maps editing keys (left/right/home/end/backspace/delete) to the instance
13
+ # methods they dispatch via KeyboardHandler. Each symbol key (e.g., :left)
14
+ # maps to a method (e.g., :move_left) that adjusts cursor position or text content.
15
+ KEY_ACTIONS = {
16
+ left: :move_left,
17
+ right: :move_right,
18
+ home: :move_home,
19
+ end: :move_end,
20
+ backspace: :delete_before_cursor,
21
+ delete: :delete_at_cursor
22
+ }.freeze
23
+
24
+ # The current input string and the byte offset of the cursor within it.
25
+ attr_reader :value, :cursor
26
+
27
+ # *value* is the initial text. *placeholder* is shown when the value is empty.
28
+ # *width* optionally constrains the rendered output width; *cursor* defaults to the end.
29
+ def initialize(value: "", placeholder: "", width: nil, cursor: nil)
30
+ super()
31
+ @value = value.dup
32
+ @placeholder = placeholder
33
+ @width = width
34
+ @cursor = cursor || @value.length
35
+ clamp_position
36
+ end
37
+
38
+ # Handles key events. Inserts printable characters, otherwise dispatches via KEY_ACTIONS.
39
+ # Returns :handled when the event was consumed, nil otherwise.
40
+ def handle_key(event)
41
+ return :handled if character_event?(event) && insert(event.char)
42
+
43
+ super
44
+ end
45
+
46
+ # Renders the value with a cursor marker. When *width* was given at construction, the
47
+ # output is padded to that width via the configured style.
48
+ def render
49
+ rendered = render_value
50
+ @width ? style.width(@width).render(rendered) : rendered
51
+ end
52
+
53
+ private
54
+
55
+ attr_reader :placeholder
56
+
57
+ # True when *event* carries a single printable character that should be inserted.
58
+ def character_event?(event)
59
+ event.respond_to?(:char) && event.char && event.char.length == 1 && printable?(event.char)
60
+ end
61
+
62
+ # True when *char* is not a control character (and therefore safe to insert).
63
+ def printable?(char)
64
+ !char.match?(/[[:cntrl:]]/)
65
+ end
66
+
67
+ # Inserts *char* at the cursor and advances the cursor by its byte length.
68
+ def insert(char)
69
+ @value = value[0...cursor] + char + value[cursor..]
70
+ @cursor += char.length
71
+ end
72
+
73
+ # Moves the cursor one position left, when possible.
74
+ def move_left
75
+ @cursor -= 1 if cursor.positive?
76
+ end
77
+
78
+ # Moves the cursor one position right, when possible.
79
+ def move_right
80
+ @cursor += 1 if cursor < value.length
81
+ end
82
+
83
+ # Moves the cursor to the start of the value.
84
+ def move_home
85
+ @cursor = 0
86
+ end
87
+
88
+ # Moves the cursor to the end of the value.
89
+ def move_end
90
+ @cursor = value.length
91
+ end
92
+
93
+ # Deletes the character before the cursor (backspace behavior).
94
+ def delete_before_cursor
95
+ return if cursor.zero?
96
+
97
+ @value = value[0...(cursor - 1)] + value[cursor..]
98
+ @cursor -= 1
99
+ end
100
+
101
+ # Deletes the character at the cursor (delete-key behavior).
102
+ def delete_at_cursor
103
+ return if cursor >= value.length
104
+
105
+ @value = value[0...cursor] + value[(cursor + 1)..]
106
+ end
107
+
108
+ # Renders the value with a "|" cursor marker at the current position. When the value is
109
+ # empty, the placeholder is rendered instead, preceded by the cursor marker.
110
+ def render_value
111
+ return cursor_marker + placeholder if value.empty?
112
+
113
+ value[0...cursor] + cursor_marker + value[cursor..]
114
+ end
115
+
116
+ # The literal character used to mark the cursor position in `render`.
117
+ def cursor_marker
118
+ "|"
119
+ end
120
+
121
+ # Clamps the cursor to the valid range `[0, value.length]`.
122
+ def clamp_position
123
+ @cursor = cursor.clamp(0, value.length)
126
124
  end
127
125
  end
128
126
  end