bubbletea 0.0.1 → 0.1.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/LICENSE.txt +21 -0
- data/README.md +241 -16
- data/bubbletea.gemspec +39 -0
- data/ext/bubbletea/extconf.rb +64 -0
- data/ext/bubbletea/extension.c +59 -0
- data/ext/bubbletea/extension.h +22 -0
- data/ext/bubbletea/program.c +251 -0
- data/go/bubbletea.go +98 -0
- data/go/go.mod +16 -0
- data/go/go.sum +15 -0
- data/go/input.go +158 -0
- data/go/keys.go +466 -0
- data/go/renderer.go +204 -0
- data/go/terminal.go +277 -0
- data/lib/bubbletea/commands.rb +126 -0
- data/lib/bubbletea/messages.rb +248 -0
- data/lib/bubbletea/model.rb +62 -0
- data/lib/bubbletea/runner.rb +376 -0
- data/lib/bubbletea/version.rb +1 -1
- data/lib/bubbletea.rb +12 -1
- metadata +43 -15
- data/CHANGELOG.md +0 -5
- data/CODE_OF_CONDUCT.md +0 -132
- data/Rakefile +0 -12
- data/sig/bubbletea.rbs +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: acdee3b175481f16d4a4080472a633b4c80efa7c5042c75441f01827b58840dd
|
|
4
|
+
data.tar.gz: 1b8b37c756c887225add359144efac1810d162ce187ebcdbe0e07c2b90076648
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c93f2b40dd0fa39d0567ea57ea59c757d4cfbf378f59ceabe8f1ec621b869b4e3734749cfc0e2e812b7b8135e9aa2ad71c0dd21f0da1004ab21831edc81f3f34
|
|
7
|
+
data.tar.gz: 567a50b78e99970ed2f2b0678f78602c7fc8efa7c578d5918dfbe65c9bad5fa87021167d0ae210d5b7289d237926bbfac7e67f17054f583be93b20913ec10656
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Marco Roth
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,39 +1,264 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>Bubbletea for Ruby</h1>
|
|
3
|
+
<h4>A powerful TUI framework for Ruby.</h4>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<p>
|
|
6
|
+
<a href="https://rubygems.org/gems/bubbletea"><img alt="Gem Version" src="https://img.shields.io/gem/v/bubbletea"></a>
|
|
7
|
+
<a href="https://github.com/marcoroth/bubbletea-ruby/blob/main/LICENSE.txt"><img alt="License" src="https://img.shields.io/github/license/marcoroth/bubbletea-ruby"></a>
|
|
8
|
+
</p>
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
<p>Ruby bindings for <a href="https://github.com/charmbracelet/bubbletea">charmbracelet/bubbletea</a>.<br/>Build beautiful, interactive terminal applications using the Elm Architecture in Ruby.</p>
|
|
11
|
+
</div>
|
|
6
12
|
|
|
7
13
|
## Installation
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
**Add to your Gemfile:**
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
17
|
+
```ruby
|
|
18
|
+
gem "bubbletea"
|
|
15
19
|
```
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
**Or install directly:**
|
|
18
22
|
|
|
19
23
|
```bash
|
|
20
|
-
gem install
|
|
24
|
+
gem install bubbletea
|
|
21
25
|
```
|
|
22
26
|
|
|
23
27
|
## Usage
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
### The Elm Architecture
|
|
30
|
+
|
|
31
|
+
Bubbletea implements the Elm Architecture pattern with three core methods:
|
|
32
|
+
|
|
33
|
+
| Method | Description |
|
|
34
|
+
|--------|-------------|
|
|
35
|
+
| `init` | Returns `[model, command]` - initial state and optional startup command |
|
|
36
|
+
| `update(message)` | Returns `[model, command]` - handles messages and updates state |
|
|
37
|
+
| `view` | Returns `String` - renders the current state to the terminal |
|
|
38
|
+
|
|
39
|
+
### Basic Example
|
|
40
|
+
|
|
41
|
+
**A simple counter:**
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
require "bubbletea"
|
|
45
|
+
|
|
46
|
+
class Counter
|
|
47
|
+
include Bubbletea::Model
|
|
48
|
+
|
|
49
|
+
def initialize
|
|
50
|
+
@count = 0
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def init
|
|
54
|
+
[self, nil]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def update(message)
|
|
58
|
+
case message
|
|
59
|
+
when Bubbletea::KeyMessage
|
|
60
|
+
case message.to_s
|
|
61
|
+
when "q", "ctrl+c"
|
|
62
|
+
[self, Bubbletea.quit]
|
|
63
|
+
when "up", "k"
|
|
64
|
+
@count += 1
|
|
65
|
+
[self, nil]
|
|
66
|
+
when "down", "j"
|
|
67
|
+
@count -= 1
|
|
68
|
+
[self, nil]
|
|
69
|
+
else
|
|
70
|
+
[self, nil]
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
[self, nil]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def view
|
|
78
|
+
"Count: #{@count}\n\nPress up/down to change, q to quit"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
Bubbletea.run(Counter.new)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Messages
|
|
86
|
+
|
|
87
|
+
Messages are events that trigger updates to your model:
|
|
88
|
+
|
|
89
|
+
| Message | Description |
|
|
90
|
+
|---------|-------------|
|
|
91
|
+
| `KeyMessage` | Keyboard input with key type, runes, and modifiers |
|
|
92
|
+
| `MouseMessage` | Mouse events with position, button, and action |
|
|
93
|
+
| `WindowSizeMessage` | Terminal resize events with width and height |
|
|
94
|
+
| `FocusMessage` | Terminal gained focus |
|
|
95
|
+
| `BlurMessage` | Terminal lost focus |
|
|
96
|
+
|
|
97
|
+
**Handling key messages:**
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
def update(message)
|
|
101
|
+
case message
|
|
102
|
+
when Bubbletea::KeyMessage
|
|
103
|
+
case message.to_s
|
|
104
|
+
when "q", "ctrl+c", "esc"
|
|
105
|
+
[self, Bubbletea.quit]
|
|
106
|
+
when "up", "k"
|
|
107
|
+
# handle up
|
|
108
|
+
when "down", "j"
|
|
109
|
+
# handle down
|
|
110
|
+
when "enter"
|
|
111
|
+
# handle enter
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Key message helpers:**
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
message.enter? # true if Enter key
|
|
121
|
+
message.backspace? # true if Backspace
|
|
122
|
+
message.tab? # true if Tab
|
|
123
|
+
message.esc? # true if Escape
|
|
124
|
+
message.space? # true if Space
|
|
125
|
+
message.ctrl? # true if Ctrl modifier
|
|
126
|
+
message.up? # true if Up arrow
|
|
127
|
+
message.down? # true if Down arrow
|
|
128
|
+
message.left? # true if Left arrow
|
|
129
|
+
message.right? # true if Right arrow
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Commands
|
|
133
|
+
|
|
134
|
+
Commands trigger side effects and return messages:
|
|
135
|
+
|
|
136
|
+
| Command | Description |
|
|
137
|
+
|---------|-------------|
|
|
138
|
+
| `Bubbletea.quit` | Exit the program |
|
|
139
|
+
| `Bubbletea.tick(duration) { message }` | Schedule a message after delay |
|
|
140
|
+
| `Bubbletea.batch(cmd1, cmd2, ...)` | Run multiple commands together |
|
|
141
|
+
| `Bubbletea.sequence(cmd1, cmd2, ...)` | Run commands in sequence |
|
|
142
|
+
| `Bubbletea.send_message(message)` | Send a message immediately |
|
|
143
|
+
| `Bubbletea.enter_alt_screen` | Switch to alternate screen buffer |
|
|
144
|
+
| `Bubbletea.exit_alt_screen` | Return to normal screen buffer |
|
|
145
|
+
| `Bubbletea.set_window_title(title)` | Set terminal window title |
|
|
146
|
+
|
|
147
|
+
**Using tick for animations:**
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
class TickMessage < Bubbletea::Message; end
|
|
151
|
+
|
|
152
|
+
def init
|
|
153
|
+
[self, schedule_tick]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def update(message)
|
|
157
|
+
case message
|
|
158
|
+
when TickMessage
|
|
159
|
+
@frame = (@frame + 1) % FRAMES.length
|
|
160
|
+
[self, schedule_tick]
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def schedule_tick
|
|
165
|
+
Bubbletea.tick(0.1) { TickMessage.new }
|
|
166
|
+
end
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Run Options
|
|
170
|
+
|
|
171
|
+
| Option | Description |
|
|
172
|
+
|--------|-------------|
|
|
173
|
+
| `alt_screen` | Use alternate screen buffer (fullscreen mode) |
|
|
174
|
+
| `mouse_cell_motion` | Enable mouse click tracking |
|
|
175
|
+
| `mouse_all_motion` | Enable all mouse movement tracking |
|
|
176
|
+
| `bracketed_paste` | Enable bracketed paste mode |
|
|
177
|
+
| `report_focus` | Report terminal focus/blur events |
|
|
178
|
+
| `fps` | Target frames per second (default: 60) |
|
|
179
|
+
|
|
180
|
+
**Run with options:**
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
Bubbletea.run(MyModel.new,
|
|
184
|
+
alt_screen: true,
|
|
185
|
+
mouse_all_motion: true,
|
|
186
|
+
report_focus: true
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Styling with Lipgloss
|
|
191
|
+
|
|
192
|
+
Bubbletea works great with [Lipgloss](https://github.com/marcoroth/lipgloss-ruby) for styling:
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
require "bubbletea"
|
|
196
|
+
require "lipgloss"
|
|
197
|
+
|
|
198
|
+
class StyledApp
|
|
199
|
+
include Bubbletea::Model
|
|
200
|
+
|
|
201
|
+
def initialize
|
|
202
|
+
@title_style = Lipgloss::Style.new
|
|
203
|
+
.bold(true)
|
|
204
|
+
.foreground("212")
|
|
205
|
+
|
|
206
|
+
@help_style = Lipgloss::Style.new
|
|
207
|
+
.foreground("241")
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def view
|
|
211
|
+
lines = []
|
|
212
|
+
lines << @title_style.render("My App")
|
|
213
|
+
lines << ""
|
|
214
|
+
lines << @help_style.render("Press q to quit")
|
|
215
|
+
lines.join("\n")
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
```
|
|
26
219
|
|
|
27
220
|
## Development
|
|
28
221
|
|
|
29
|
-
|
|
222
|
+
**Requirements:**
|
|
223
|
+
- Go 1.23+
|
|
224
|
+
- Ruby 3.2+
|
|
225
|
+
|
|
226
|
+
**Install dependencies:**
|
|
30
227
|
|
|
31
|
-
|
|
228
|
+
```bash
|
|
229
|
+
bundle install
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Build the Go library and compile the extension:**
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
bundle exec rake compile
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Run tests:**
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
bundle exec rake test
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Run demos:**
|
|
245
|
+
|
|
246
|
+
The `demo/` directory contains many working examples:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
demo/counter
|
|
250
|
+
demo/spinner
|
|
251
|
+
demo/test_runner
|
|
252
|
+
```
|
|
32
253
|
|
|
33
254
|
## Contributing
|
|
34
255
|
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/marcoroth/bubbletea.
|
|
256
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/marcoroth/bubbletea-ruby.
|
|
257
|
+
|
|
258
|
+
## License
|
|
259
|
+
|
|
260
|
+
The gem is available as open source under the terms of the MIT License.
|
|
36
261
|
|
|
37
|
-
##
|
|
262
|
+
## Acknowledgments
|
|
38
263
|
|
|
39
|
-
|
|
264
|
+
This gem wraps [charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea), part of the excellent [Charm](https://charm.sh) ecosystem.
|
data/bubbletea.gemspec
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/bubbletea/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "bubbletea"
|
|
7
|
+
spec.version = Bubbletea::VERSION
|
|
8
|
+
spec.authors = ["Marco Roth"]
|
|
9
|
+
spec.email = ["marco.roth@intergga.ch"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Ruby wrapper for Charm's bubbletea. A powerful TUI framework."
|
|
12
|
+
spec.description = "Build beautiful, interactive terminal applications using the Elm Architecture in Ruby."
|
|
13
|
+
spec.homepage = "https://github.com/marcoroth/bubbletea-ruby"
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
spec.required_ruby_version = ">= 3.2.0"
|
|
16
|
+
|
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
18
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
|
19
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/releases"
|
|
20
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
21
|
+
|
|
22
|
+
spec.files = Dir[
|
|
23
|
+
"bubbletea.gemspec",
|
|
24
|
+
"LICENSE.txt",
|
|
25
|
+
"README.md",
|
|
26
|
+
"CHANGELOG.md",
|
|
27
|
+
"lib/**/*.rb",
|
|
28
|
+
"ext/**/*.{c,h,rb}",
|
|
29
|
+
"go/**/*.{go,mod,sum}",
|
|
30
|
+
"go/build/**/*"
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
spec.bindir = "exe"
|
|
34
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
35
|
+
spec.require_paths = ["lib"]
|
|
36
|
+
spec.extensions = ["ext/bubbletea/extconf.rb"]
|
|
37
|
+
|
|
38
|
+
spec.add_dependency "lipgloss", "~> 0.1"
|
|
39
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "mkmf"
|
|
4
|
+
|
|
5
|
+
extension_name = "bubbletea"
|
|
6
|
+
|
|
7
|
+
def detect_platform
|
|
8
|
+
cpu = RbConfig::CONFIG["host_cpu"]
|
|
9
|
+
os = RbConfig::CONFIG["host_os"]
|
|
10
|
+
|
|
11
|
+
arch = case cpu
|
|
12
|
+
when /aarch64|arm64/ then "arm64"
|
|
13
|
+
when /x86_64|amd64/ then "amd64"
|
|
14
|
+
when /arm/ then "arm"
|
|
15
|
+
when /i[3-6]86/ then "386"
|
|
16
|
+
else cpu
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
goos = case os
|
|
20
|
+
when /darwin/ then "darwin"
|
|
21
|
+
when /mswin|mingw/ then "windows"
|
|
22
|
+
else "linux"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
"#{goos}_#{arch}"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
platform = detect_platform
|
|
29
|
+
go_lib_dir = File.expand_path("../../go/build/#{platform}", __dir__)
|
|
30
|
+
|
|
31
|
+
puts "Looking for Go library in: #{go_lib_dir}"
|
|
32
|
+
|
|
33
|
+
unless File.exist?(File.join(go_lib_dir, "libbubbletea.a"))
|
|
34
|
+
abort <<~ERROR
|
|
35
|
+
Could not find libbubbletea.a for platform #{platform}
|
|
36
|
+
|
|
37
|
+
Please build the Go archive first:
|
|
38
|
+
cd go && go build -buildmode=c-archive -o build/#{platform}/libbubbletea.a .
|
|
39
|
+
|
|
40
|
+
Or run:
|
|
41
|
+
bundle exec rake go:build
|
|
42
|
+
ERROR
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
$LDFLAGS << " -L#{go_lib_dir}"
|
|
46
|
+
$INCFLAGS << " -I#{go_lib_dir}"
|
|
47
|
+
|
|
48
|
+
$LOCAL_LIBS << " #{go_lib_dir}/libbubbletea.a"
|
|
49
|
+
|
|
50
|
+
case RbConfig::CONFIG["host_os"]
|
|
51
|
+
when /darwin/
|
|
52
|
+
$LDFLAGS << " -framework CoreFoundation -framework Security -framework SystemConfiguration"
|
|
53
|
+
$LDFLAGS << " -lresolv"
|
|
54
|
+
when /linux/
|
|
55
|
+
$LDFLAGS << " -lpthread -lm -ldl"
|
|
56
|
+
$LDFLAGS << " -lresolv" if find_library("resolv", "res_query")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
$srcs = [
|
|
60
|
+
"extension.c",
|
|
61
|
+
"program.c",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
create_makefile("#{extension_name}/#{extension_name}")
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#include "extension.h"
|
|
2
|
+
|
|
3
|
+
VALUE mBubbletea;
|
|
4
|
+
VALUE cProgram;
|
|
5
|
+
|
|
6
|
+
static VALUE bubbletea_upstream_version_rb(VALUE self) {
|
|
7
|
+
char *version = tea_upstream_version();
|
|
8
|
+
VALUE rb_version = rb_utf8_str_new_cstr(version);
|
|
9
|
+
|
|
10
|
+
tea_free(version);
|
|
11
|
+
|
|
12
|
+
return rb_version;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static VALUE bubbletea_version_rb(VALUE self) {
|
|
16
|
+
VALUE gem_version = rb_const_get(self, rb_intern("VERSION"));
|
|
17
|
+
VALUE upstream_version = bubbletea_upstream_version_rb(self);
|
|
18
|
+
VALUE format_string = rb_utf8_str_new_cstr("bubbletea v%s (upstream charmbracelet/x/ansi %s) [Go native extension]");
|
|
19
|
+
|
|
20
|
+
return rb_funcall(rb_mKernel, rb_intern("sprintf"), 3, format_string, gem_version, upstream_version);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static VALUE bubbletea_is_tty_rb(VALUE self) {
|
|
24
|
+
return tea_terminal_is_tty() ? Qtrue : Qfalse;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static VALUE bubbletea_clear_screen_rb(VALUE self) {
|
|
28
|
+
tea_terminal_clear_screen();
|
|
29
|
+
return Qnil;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static VALUE bubbletea_set_window_title_rb(VALUE self, VALUE title) {
|
|
33
|
+
Check_Type(title, T_STRING);
|
|
34
|
+
tea_terminal_set_window_title(StringValueCStr(title));
|
|
35
|
+
return Qnil;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static VALUE bubbletea_get_key_name_rb(VALUE self, VALUE key_type) {
|
|
39
|
+
Check_Type(key_type, T_FIXNUM);
|
|
40
|
+
char *name = tea_get_key_name(FIX2INT(key_type));
|
|
41
|
+
VALUE rb_name = rb_utf8_str_new_cstr(name);
|
|
42
|
+
free(name);
|
|
43
|
+
return rb_name;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
__attribute__((__visibility__("default"))) void Init_bubbletea(void) {
|
|
47
|
+
rb_require("json");
|
|
48
|
+
|
|
49
|
+
mBubbletea = rb_define_module("Bubbletea");
|
|
50
|
+
|
|
51
|
+
Init_bubbletea_program();
|
|
52
|
+
|
|
53
|
+
rb_define_singleton_method(mBubbletea, "upstream_version", bubbletea_upstream_version_rb, 0);
|
|
54
|
+
rb_define_singleton_method(mBubbletea, "version", bubbletea_version_rb, 0);
|
|
55
|
+
rb_define_singleton_method(mBubbletea, "tty?", bubbletea_is_tty_rb, 0);
|
|
56
|
+
rb_define_singleton_method(mBubbletea, "clear_screen", bubbletea_clear_screen_rb, 0);
|
|
57
|
+
rb_define_singleton_method(mBubbletea, "_set_window_title", bubbletea_set_window_title_rb, 1);
|
|
58
|
+
rb_define_singleton_method(mBubbletea, "get_key_name", bubbletea_get_key_name_rb, 1);
|
|
59
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#ifndef BUBBLETEA_EXTENSION_H
|
|
2
|
+
#define BUBBLETEA_EXTENSION_H
|
|
3
|
+
|
|
4
|
+
#include <ruby.h>
|
|
5
|
+
#include "libbubbletea.h"
|
|
6
|
+
|
|
7
|
+
extern VALUE mBubbletea;
|
|
8
|
+
extern VALUE cProgram;
|
|
9
|
+
|
|
10
|
+
extern const rb_data_type_t program_type;
|
|
11
|
+
|
|
12
|
+
typedef struct {
|
|
13
|
+
unsigned long long handle;
|
|
14
|
+
} bubbletea_program_t;
|
|
15
|
+
|
|
16
|
+
#define GET_PROGRAM(self, program) \
|
|
17
|
+
bubbletea_program_t *program; \
|
|
18
|
+
TypedData_Get_Struct(self, bubbletea_program_t, &program_type, program)
|
|
19
|
+
|
|
20
|
+
void Init_bubbletea_program(void);
|
|
21
|
+
|
|
22
|
+
#endif
|