chamomile-petals 0.1.1 → 0.2.0
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.
- checksums.yaml +4 -4
- data/lib/petals/cursor.rb +3 -1
- data/lib/petals/file_picker.rb +6 -4
- data/lib/petals/help.rb +3 -1
- data/lib/petals/key_binding.rb +2 -2
- data/lib/petals/list.rb +4 -2
- data/lib/petals/paginator.rb +4 -2
- data/lib/petals/progress.rb +3 -1
- data/lib/petals/spinner.rb +3 -1
- data/lib/petals/stopwatch.rb +3 -1
- data/lib/petals/table.rb +53 -4
- data/lib/petals/text_area.rb +5 -3
- data/lib/petals/text_input.rb +7 -5
- data/lib/petals/timer.rb +3 -1
- data/lib/petals/version.rb +1 -1
- data/lib/petals/viewport.rb +23 -9
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b0e639488f319cee4214dadaf0a18d780c364f1e2dd0eb105ad8a02396c10476
|
|
4
|
+
data.tar.gz: 312869e2b9d7f6e1cbeb10a88144adbd576ff53979e4aa6c3668846614e5d9d2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 83bd46a6443068228e48ac8084480044cb6656376120f9ed096ad803887d8c50bfe103143c988bb628576a2d58d20a93aaab5f448f1f2c7a6d19b98aa020150e
|
|
7
|
+
data.tar.gz: d8f90b12a4a67f5a07e04870b83f004fff7d385de2face4bd4fb7008e0be3e906c2f9ce8fb1bedc469ea3be0003585964e39e53f912696148743b41eb4b7ff5e
|
data/lib/petals/cursor.rb
CHANGED
|
@@ -74,7 +74,7 @@ module Petals
|
|
|
74
74
|
}
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
def
|
|
77
|
+
def handle(msg)
|
|
78
78
|
return unless msg.is_a?(CursorBlinkMsg)
|
|
79
79
|
return unless @mode == MODE_BLINK && @focused
|
|
80
80
|
return unless msg.id == @id && msg.tag == @tag
|
|
@@ -84,6 +84,8 @@ module Petals
|
|
|
84
84
|
blink_cmd
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
alias update handle
|
|
88
|
+
|
|
87
89
|
def view
|
|
88
90
|
return @char if @mode == MODE_HIDE
|
|
89
91
|
return @char if @blinked
|
data/lib/petals/file_picker.rb
CHANGED
|
@@ -52,7 +52,7 @@ module Petals
|
|
|
52
52
|
read_dir_cmd(@current_directory)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
def
|
|
55
|
+
def handle(msg)
|
|
56
56
|
case msg
|
|
57
57
|
when FilePickerReadDirMsg
|
|
58
58
|
return unless msg.id == @id
|
|
@@ -61,11 +61,13 @@ module Petals
|
|
|
61
61
|
@cursor = @cursor.clamp(0, [entries_size - 1, 0].max)
|
|
62
62
|
clamp_offset
|
|
63
63
|
nil
|
|
64
|
-
when Chamomile::
|
|
64
|
+
when Chamomile::KeyEvent
|
|
65
65
|
handle_key(msg)
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
+
alias update handle
|
|
70
|
+
|
|
69
71
|
def view
|
|
70
72
|
return " (empty)" if @entries.empty?
|
|
71
73
|
|
|
@@ -93,7 +95,7 @@ module Petals
|
|
|
93
95
|
end
|
|
94
96
|
|
|
95
97
|
def did_select_file?(msg)
|
|
96
|
-
return [false, nil] unless msg.is_a?(Chamomile::
|
|
98
|
+
return [false, nil] unless msg.is_a?(Chamomile::KeyEvent)
|
|
97
99
|
|
|
98
100
|
if @selected_path
|
|
99
101
|
path = @selected_path
|
|
@@ -105,7 +107,7 @@ module Petals
|
|
|
105
107
|
end
|
|
106
108
|
|
|
107
109
|
def did_select_disabled_file?(msg)
|
|
108
|
-
return [false, nil] unless msg.is_a?(Chamomile::
|
|
110
|
+
return [false, nil] unless msg.is_a?(Chamomile::KeyEvent)
|
|
109
111
|
|
|
110
112
|
if @disabled_selected_path
|
|
111
113
|
path = @disabled_selected_path
|
data/lib/petals/help.rb
CHANGED
data/lib/petals/key_binding.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Petals
|
|
4
|
-
# Utilities for matching
|
|
4
|
+
# Utilities for matching KeyEvent against normalized key maps.
|
|
5
5
|
module KeyBinding
|
|
6
6
|
# Normalize a key map so mod arrays are sorted and frozen.
|
|
7
7
|
# Call once at definition time to avoid per-keystroke allocations.
|
|
@@ -14,7 +14,7 @@ module Petals
|
|
|
14
14
|
end.freeze
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
# Check if a
|
|
17
|
+
# Check if a KeyEvent matches any binding for a named action.
|
|
18
18
|
# Expects a normalized key map (from .normalize) for best performance.
|
|
19
19
|
def self.key_matches?(msg, key_map, action)
|
|
20
20
|
return false unless msg.is_a?(Chamomile::KeyMsg)
|
data/lib/petals/list.rb
CHANGED
|
@@ -212,9 +212,9 @@ module Petals
|
|
|
212
212
|
@spinner_visible
|
|
213
213
|
end
|
|
214
214
|
|
|
215
|
-
def
|
|
215
|
+
def handle(msg)
|
|
216
216
|
case msg
|
|
217
|
-
when Chamomile::
|
|
217
|
+
when Chamomile::KeyEvent
|
|
218
218
|
handle_key(msg)
|
|
219
219
|
when SpinnerTickMsg
|
|
220
220
|
@spinner.update(msg)
|
|
@@ -230,6 +230,8 @@ module Petals
|
|
|
230
230
|
end
|
|
231
231
|
end
|
|
232
232
|
|
|
233
|
+
alias update handle
|
|
234
|
+
|
|
233
235
|
def view
|
|
234
236
|
sections = []
|
|
235
237
|
|
data/lib/petals/paginator.rb
CHANGED
|
@@ -72,9 +72,9 @@ module Petals
|
|
|
72
72
|
|
|
73
73
|
# Elm protocol
|
|
74
74
|
|
|
75
|
-
def
|
|
75
|
+
def handle(msg)
|
|
76
76
|
case msg
|
|
77
|
-
when Chamomile::
|
|
77
|
+
when Chamomile::KeyEvent
|
|
78
78
|
if KeyBinding.key_matches?(msg, @key_map, :prev_page)
|
|
79
79
|
prev_page
|
|
80
80
|
elsif KeyBinding.key_matches?(msg, @key_map, :next_page)
|
|
@@ -85,6 +85,8 @@ module Petals
|
|
|
85
85
|
nil
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
alias update handle
|
|
89
|
+
|
|
88
90
|
def view
|
|
89
91
|
case @type
|
|
90
92
|
when TYPE_ARABIC
|
data/lib/petals/progress.rb
CHANGED
|
@@ -79,7 +79,7 @@ module Petals
|
|
|
79
79
|
@animating
|
|
80
80
|
end
|
|
81
81
|
|
|
82
|
-
def
|
|
82
|
+
def handle(msg)
|
|
83
83
|
return unless msg.is_a?(ProgressFrameMsg)
|
|
84
84
|
return unless msg.id == @id && msg.tag == @tag
|
|
85
85
|
|
|
@@ -101,6 +101,8 @@ module Petals
|
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
+
alias update handle
|
|
105
|
+
|
|
104
106
|
def view
|
|
105
107
|
render_bar(@percent)
|
|
106
108
|
end
|
data/lib/petals/spinner.rb
CHANGED
|
@@ -42,7 +42,7 @@ module Petals
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
# Advance frame if msg is a matching SpinnerTickMsg; return cmd or nil.
|
|
45
|
-
def
|
|
45
|
+
def handle(msg)
|
|
46
46
|
return unless msg.is_a?(SpinnerTickMsg)
|
|
47
47
|
return unless msg.id == @id && msg.tag == @tag
|
|
48
48
|
|
|
@@ -51,6 +51,8 @@ module Petals
|
|
|
51
51
|
tick_cmd
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
alias update handle
|
|
55
|
+
|
|
54
56
|
# Current frame string.
|
|
55
57
|
def view
|
|
56
58
|
@spinner_type.frames[@frame]
|
data/lib/petals/stopwatch.rb
CHANGED
|
@@ -64,7 +64,7 @@ module Petals
|
|
|
64
64
|
@running
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
def
|
|
67
|
+
def handle(msg)
|
|
68
68
|
return unless msg.is_a?(StopwatchTickMsg)
|
|
69
69
|
return unless msg.id == @id && msg.tag == @tag
|
|
70
70
|
|
|
@@ -73,6 +73,8 @@ module Petals
|
|
|
73
73
|
tick_cmd
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
+
alias update handle
|
|
77
|
+
|
|
76
78
|
def view
|
|
77
79
|
total = @elapsed.ceil.to_i
|
|
78
80
|
hours = total / 3600
|
data/lib/petals/table.rb
CHANGED
|
@@ -8,14 +8,33 @@ module Petals
|
|
|
8
8
|
attr_accessor :columns, :key_map, :height
|
|
9
9
|
attr_reader :cursor, :rows
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
# Accepts columns as keyword arg or via block DSL.
|
|
12
|
+
#
|
|
13
|
+
# # Keyword form (original)
|
|
14
|
+
# Table.new(columns: [Column.new(title: "Name", width: 20)], rows: rows)
|
|
15
|
+
#
|
|
16
|
+
# # Block DSL form (new)
|
|
17
|
+
# Table.new(rows: rows) do |t|
|
|
18
|
+
# t.column "Name", width: 20
|
|
19
|
+
# t.column "Size", width: 10
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# # Hash form (new)
|
|
23
|
+
# Table.new(columns: [{ title: "Name", width: 20 }], rows: rows)
|
|
24
|
+
def initialize(columns: [], rows: [], height: 10, key_map: DEFAULT_KEY_MAP, &block)
|
|
25
|
+
@columns = normalize_columns(columns)
|
|
13
26
|
@rows = rows
|
|
14
27
|
@height = height
|
|
15
28
|
@key_map = key_map
|
|
16
29
|
@cursor = 0
|
|
17
30
|
@offset = 0
|
|
18
31
|
@focused = false
|
|
32
|
+
|
|
33
|
+
if block
|
|
34
|
+
builder = ColumnBuilder.new
|
|
35
|
+
block.call(builder)
|
|
36
|
+
@columns = builder.columns unless builder.columns.empty?
|
|
37
|
+
end
|
|
19
38
|
end
|
|
20
39
|
|
|
21
40
|
def rows=(rows)
|
|
@@ -69,17 +88,21 @@ module Petals
|
|
|
69
88
|
@focused
|
|
70
89
|
end
|
|
71
90
|
|
|
72
|
-
|
|
91
|
+
# Handle an incoming event.
|
|
92
|
+
def handle(msg)
|
|
73
93
|
return unless @focused
|
|
74
94
|
|
|
75
95
|
case msg
|
|
76
|
-
when Chamomile::
|
|
96
|
+
when Chamomile::KeyEvent
|
|
77
97
|
handle_key(msg)
|
|
78
98
|
end
|
|
79
99
|
|
|
80
100
|
nil
|
|
81
101
|
end
|
|
82
102
|
|
|
103
|
+
# Backward compat alias
|
|
104
|
+
alias update handle
|
|
105
|
+
|
|
83
106
|
def view
|
|
84
107
|
header = render_header
|
|
85
108
|
separator = render_separator
|
|
@@ -88,8 +111,34 @@ module Petals
|
|
|
88
111
|
[header, separator, body].compact.join("\n")
|
|
89
112
|
end
|
|
90
113
|
|
|
114
|
+
# DSL builder for column definitions.
|
|
115
|
+
class ColumnBuilder
|
|
116
|
+
attr_reader :columns
|
|
117
|
+
|
|
118
|
+
def initialize
|
|
119
|
+
@columns = []
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def column(title, width: 20)
|
|
123
|
+
@columns << Column.new(title: title, width: width)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
91
127
|
private
|
|
92
128
|
|
|
129
|
+
def normalize_columns(columns)
|
|
130
|
+
columns.map do |col|
|
|
131
|
+
case col
|
|
132
|
+
when Column
|
|
133
|
+
col
|
|
134
|
+
when Hash
|
|
135
|
+
Column.new(title: col[:title], width: col[:width] || 20)
|
|
136
|
+
else
|
|
137
|
+
col
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
93
142
|
def row_count
|
|
94
143
|
@rows.length
|
|
95
144
|
end
|
data/lib/petals/text_area.rb
CHANGED
|
@@ -168,19 +168,21 @@ module Petals
|
|
|
168
168
|
@last_char_offset = 0
|
|
169
169
|
end
|
|
170
170
|
|
|
171
|
-
def
|
|
171
|
+
def handle(msg)
|
|
172
172
|
return unless @focused
|
|
173
173
|
|
|
174
174
|
case msg
|
|
175
|
-
when Chamomile::
|
|
175
|
+
when Chamomile::KeyEvent
|
|
176
176
|
handle_key(msg)
|
|
177
|
-
when Chamomile::
|
|
177
|
+
when Chamomile::PasteEvent
|
|
178
178
|
handle_paste(msg)
|
|
179
179
|
end
|
|
180
180
|
|
|
181
181
|
nil
|
|
182
182
|
end
|
|
183
183
|
|
|
184
|
+
alias update handle
|
|
185
|
+
|
|
184
186
|
def view
|
|
185
187
|
return "#{@prompt}#{@placeholder}" if @lines == [""] && !@placeholder.empty? && !@focused
|
|
186
188
|
|
data/lib/petals/text_input.rb
CHANGED
|
@@ -65,21 +65,23 @@ module Petals
|
|
|
65
65
|
recalc_offset
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
#
|
|
69
|
-
|
|
70
|
-
def update(msg)
|
|
68
|
+
# Handle an incoming event. Primary API — replaces the old `update` name.
|
|
69
|
+
def handle(msg)
|
|
71
70
|
return unless @focused
|
|
72
71
|
|
|
73
72
|
case msg
|
|
74
|
-
when Chamomile::
|
|
73
|
+
when Chamomile::KeyEvent
|
|
75
74
|
handle_key(msg)
|
|
76
|
-
when Chamomile::
|
|
75
|
+
when Chamomile::PasteEvent
|
|
77
76
|
handle_paste(msg)
|
|
78
77
|
end
|
|
79
78
|
|
|
80
79
|
nil
|
|
81
80
|
end
|
|
82
81
|
|
|
82
|
+
# Backward compat alias
|
|
83
|
+
alias update handle
|
|
84
|
+
|
|
83
85
|
def view
|
|
84
86
|
return "#{@prompt}#{@placeholder}" if @value.empty? && !@placeholder.empty? && !@focused
|
|
85
87
|
|
data/lib/petals/timer.rb
CHANGED
|
@@ -70,7 +70,7 @@ module Petals
|
|
|
70
70
|
@remaining <= 0
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
def
|
|
73
|
+
def handle(msg)
|
|
74
74
|
case msg
|
|
75
75
|
when TimerTickMsg
|
|
76
76
|
return unless msg.id == @id && msg.tag == @tag
|
|
@@ -87,6 +87,8 @@ module Petals
|
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
+
alias update handle
|
|
91
|
+
|
|
90
92
|
def view
|
|
91
93
|
total = @remaining.ceil.to_i
|
|
92
94
|
total = 0 if total.negative?
|
data/lib/petals/version.rb
CHANGED
data/lib/petals/viewport.rb
CHANGED
|
@@ -18,24 +18,36 @@ module Petals
|
|
|
18
18
|
@soft_wrap = false
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def
|
|
21
|
+
def width=(new_width)
|
|
22
22
|
@width = new_width
|
|
23
23
|
clamp_offset
|
|
24
24
|
@x_offset = @x_offset.clamp(0, [max_horizontal_scroll, 0].max) unless @soft_wrap
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
# Backward compat alias
|
|
28
|
+
alias set_width width=
|
|
29
|
+
|
|
30
|
+
def height=(new_height)
|
|
28
31
|
@height = new_height
|
|
29
32
|
clamp_offset
|
|
30
33
|
end
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
# Backward compat alias
|
|
36
|
+
alias set_height height=
|
|
37
|
+
|
|
38
|
+
def content=(s)
|
|
39
|
+
@lines = s.to_s.split("\n", -1)
|
|
34
40
|
clamp_offset
|
|
35
41
|
@x_offset = @x_offset.clamp(0, [max_horizontal_scroll, 0].max) unless @soft_wrap
|
|
36
42
|
self
|
|
37
43
|
end
|
|
38
44
|
|
|
45
|
+
# Backward compat — preserves the return-self convention
|
|
46
|
+
def set_content(s)
|
|
47
|
+
self.content = s
|
|
48
|
+
self
|
|
49
|
+
end
|
|
50
|
+
|
|
39
51
|
def content
|
|
40
52
|
@lines.join("\n")
|
|
41
53
|
end
|
|
@@ -138,19 +150,21 @@ module Petals
|
|
|
138
150
|
self
|
|
139
151
|
end
|
|
140
152
|
|
|
141
|
-
#
|
|
142
|
-
|
|
143
|
-
def update(msg)
|
|
153
|
+
# Handle an incoming event.
|
|
154
|
+
def handle(msg)
|
|
144
155
|
case msg
|
|
145
|
-
when Chamomile::
|
|
156
|
+
when Chamomile::KeyEvent
|
|
146
157
|
handle_key(msg)
|
|
147
|
-
when Chamomile::
|
|
158
|
+
when Chamomile::MouseEvent
|
|
148
159
|
handle_mouse(msg)
|
|
149
160
|
end
|
|
150
161
|
|
|
151
162
|
nil
|
|
152
163
|
end
|
|
153
164
|
|
|
165
|
+
# Backward compat alias
|
|
166
|
+
alias update handle
|
|
167
|
+
|
|
154
168
|
def view
|
|
155
169
|
if @soft_wrap
|
|
156
170
|
render_soft_wrap
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chamomile-petals
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jack Killilea
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-03-
|
|
11
|
+
date: 2026-03-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: chamomile
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0.
|
|
19
|
+
version: '0.2'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0.
|
|
26
|
+
version: '0.2'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rspec
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|