rufio 0.63.0 → 0.64.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/CHANGELOG.md +31 -0
- data/lib/rufio/bookmark_manager.rb +159 -103
- data/lib/rufio/command_mode_ui.rb +56 -15
- data/lib/rufio/dialog_renderer.rb +67 -0
- data/lib/rufio/keybind_handler.rb +215 -174
- data/lib/rufio/screen.rb +113 -5
- data/lib/rufio/terminal_ui.rb +137 -72
- data/lib/rufio/text_utils.rb +4 -2
- data/lib/rufio/version.rb +1 -1
- data/lib/rufio/zoxide_integration.rb +97 -48
- data/lib/rufio.rb +50 -49
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a25103ee7f5bae19e38110e69a2eeb2ca66eb0b781dba23d271ceafb22933087
|
|
4
|
+
data.tar.gz: ecc2574678d47565dbc8ad0f0797c7b59a13a2e04cf70f5a5ee21013e089ef98
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9e9e60071f2ac2ef3c6ac141a6ae04dd38b0fd9545655f2e24f2a42f14ca8767c905a8cd556898b4c9aee629c0e6153ee8a03f7bae4c3bc5d3a6bbc644a6c3d0
|
|
7
|
+
data.tar.gz: 3b0be66f3ecd1d6d65152375e3ae1659ee8f0a4bf90e87475e3fed088a3427d3ab09143b0f2287dd642e8b47737fbc99787e7f26a6b8ff3710da5eeed27d1432
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.64.0] - 2026-02-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Screen Overlay Layer**: ダイアログ描画用のオーバーレイレイヤーをScreenクラスに追加
|
|
14
|
+
- `enable_overlay` / `disable_overlay` / `clear_overlay` / `overlay_enabled?`
|
|
15
|
+
- `put_overlay` / `put_overlay_string` でオーバーレイレイヤーに描画
|
|
16
|
+
- `row()` メソッドがオーバーレイとベースレイヤーを自動合成
|
|
17
|
+
- オーバーレイ無効化時にdirty行を自動マーク(再描画保証)
|
|
18
|
+
- **`show_overlay_dialog` ヘルパーメソッド**: TerminalUI, KeybindHandler, BookmarkManager, CommandModeUI, ZoxideIntegration に統一的なオーバーレイダイアログ表示メソッドを追加
|
|
19
|
+
- `terminal_ui` が利用可能な場合はオーバーレイを使用、なければ従来の直接描画にフォールバック
|
|
20
|
+
- **`draw_floating_window_to_overlay`**: DialogRendererにオーバーレイレイヤーへのフローティングウィンドウ描画メソッドを追加
|
|
21
|
+
- **Screen Overlay テスト**: `test/test_screen_overlay.rb` を追加
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- **ダイアログ描画のバッファベース化**: 全ダイアログ表示をScreenオーバーレイ経由に変更
|
|
25
|
+
- BookmarkManager: ブックマークメニュー、一覧、リネーム、削除、確認ダイアログ
|
|
26
|
+
- KeybindHandler: 削除確認、コピー/移動確認、終了確認、スクリプトパス管理、ブックマーク操作結果
|
|
27
|
+
- CommandModeUI: コマンド実行結果表示
|
|
28
|
+
- ZoxideIntegration: 履歴なしメッセージ、履歴選択ダイアログ
|
|
29
|
+
- TerminalUI: ヘルプダイアログ、お知らせ表示、プラグイン読み込みエラー
|
|
30
|
+
- **コマンドモードのオーバーレイ化**: 直接描画(Screenバッファ外)からオーバーレイベースのバッファ描画に変更
|
|
31
|
+
- `draw_command_mode_to_overlay` メソッドでメインループ内のバッファ描画に統合
|
|
32
|
+
- **Box Drawing文字の幅修正**: `TextUtils.char_width` で罫線文字(U+2500-U+257F)を幅1として扱うように修正(ターミナルでの実際の表示幅に合わせた)
|
|
33
|
+
- **コードスタイル統一**: `lib/rufio.rb` の `require_relative` をダブルクォートからシングルクォートに統一
|
|
34
|
+
- **`set_terminal_ui` の伝播**: KeybindHandler経由でBookmarkManager, ZoxideIntegrationにも `terminal_ui` を設定
|
|
35
|
+
- **TerminalUI**: `screen` と `renderer` の `attr_reader` を公開
|
|
36
|
+
|
|
37
|
+
### Technical Details
|
|
38
|
+
- **新規ファイル**: `test/test_screen_overlay.rb`
|
|
39
|
+
- **変更ファイル**: `lib/rufio.rb`, `lib/rufio/screen.rb`, `lib/rufio/dialog_renderer.rb`, `lib/rufio/terminal_ui.rb`, `lib/rufio/keybind_handler.rb`, `lib/rufio/bookmark_manager.rb`, `lib/rufio/command_mode_ui.rb`, `lib/rufio/text_utils.rb`, `lib/rufio/zoxide_integration.rb`
|
|
40
|
+
|
|
10
41
|
## [0.63.0] - 2026-02-01
|
|
11
42
|
|
|
12
43
|
### Added
|
|
@@ -10,6 +10,12 @@ module Rufio
|
|
|
10
10
|
def initialize(bookmark = nil, dialog_renderer = nil)
|
|
11
11
|
@bookmark = bookmark || create_default_bookmark
|
|
12
12
|
@dialog_renderer = dialog_renderer
|
|
13
|
+
@terminal_ui = nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# terminal_ui を設定
|
|
17
|
+
def set_terminal_ui(terminal_ui)
|
|
18
|
+
@terminal_ui = terminal_ui
|
|
13
19
|
end
|
|
14
20
|
|
|
15
21
|
private
|
|
@@ -46,40 +52,45 @@ module Rufio
|
|
|
46
52
|
|
|
47
53
|
dialog_width = 45
|
|
48
54
|
dialog_height = 4 + content_lines.length
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
55
|
+
|
|
56
|
+
result = { action: :cancel }
|
|
57
|
+
show_overlay_dialog(title, content_lines, {
|
|
58
|
+
width: dialog_width,
|
|
59
|
+
height: dialog_height,
|
|
60
|
+
border_color: "\e[34m", # Blue
|
|
61
|
+
title_color: "\e[1;34m", # Bold blue
|
|
62
|
+
content_color: "\e[37m" # White
|
|
63
|
+
}) do
|
|
64
|
+
# Wait for key input
|
|
65
|
+
loop do
|
|
66
|
+
input = STDIN.getch.downcase
|
|
67
|
+
|
|
68
|
+
case input
|
|
69
|
+
when 'a'
|
|
70
|
+
result = { action: :add, path: current_path }
|
|
71
|
+
break
|
|
72
|
+
when 'l'
|
|
73
|
+
result = { action: :list }
|
|
74
|
+
break
|
|
75
|
+
when 'r'
|
|
76
|
+
result = { action: :rename }
|
|
77
|
+
break
|
|
78
|
+
when 'd'
|
|
79
|
+
result = { action: :remove }
|
|
80
|
+
break
|
|
81
|
+
when '1', '2', '3', '4', '5', '6', '7', '8', '9'
|
|
82
|
+
result = { action: :navigate, number: input.to_i }
|
|
83
|
+
break
|
|
84
|
+
else
|
|
85
|
+
# Cancel
|
|
86
|
+
result = { action: :cancel }
|
|
87
|
+
break
|
|
88
|
+
end
|
|
81
89
|
end
|
|
90
|
+
nil
|
|
82
91
|
end
|
|
92
|
+
|
|
93
|
+
result
|
|
83
94
|
end
|
|
84
95
|
|
|
85
96
|
# Add a bookmark interactively
|
|
@@ -141,32 +152,33 @@ module Rufio
|
|
|
141
152
|
title = 'Rename Bookmark'
|
|
142
153
|
width = 60
|
|
143
154
|
height = [content_lines.length + 4, 20].min
|
|
144
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
145
155
|
|
|
146
|
-
|
|
156
|
+
# Wait for selection
|
|
157
|
+
selected_number = nil
|
|
158
|
+
show_overlay_dialog(title, content_lines, {
|
|
159
|
+
width: width,
|
|
160
|
+
height: height,
|
|
147
161
|
border_color: "\e[33m", # Yellow
|
|
148
162
|
title_color: "\e[1;33m", # Bold yellow
|
|
149
163
|
content_color: "\e[37m" # White
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
164
|
+
}) do
|
|
165
|
+
loop do
|
|
166
|
+
input = STDIN.getch.downcase
|
|
167
|
+
|
|
168
|
+
if input >= '1' && input <= '9'
|
|
169
|
+
number = input.to_i
|
|
170
|
+
if number > 0 && number <= bookmarks.length
|
|
171
|
+
selected_number = number
|
|
172
|
+
break
|
|
173
|
+
end
|
|
174
|
+
elsif input == "\e" # ESC
|
|
161
175
|
break
|
|
162
176
|
end
|
|
163
|
-
elsif input == "\e" # ESC
|
|
164
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
165
|
-
return false
|
|
166
177
|
end
|
|
178
|
+
nil
|
|
167
179
|
end
|
|
168
180
|
|
|
169
|
-
|
|
181
|
+
return false unless selected_number
|
|
170
182
|
|
|
171
183
|
# Get new name
|
|
172
184
|
bookmark_to_rename = bookmarks[selected_number - 1]
|
|
@@ -216,32 +228,33 @@ module Rufio
|
|
|
216
228
|
title = 'Delete Bookmark'
|
|
217
229
|
width = 60
|
|
218
230
|
height = [content_lines.length + 4, 20].min
|
|
219
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
220
231
|
|
|
221
|
-
|
|
232
|
+
# Wait for selection
|
|
233
|
+
selected_number = nil
|
|
234
|
+
show_overlay_dialog(title, content_lines, {
|
|
235
|
+
width: width,
|
|
236
|
+
height: height,
|
|
222
237
|
border_color: "\e[31m", # Red (warning)
|
|
223
238
|
title_color: "\e[1;31m", # Bold red
|
|
224
239
|
content_color: "\e[37m" # White
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
240
|
+
}) do
|
|
241
|
+
loop do
|
|
242
|
+
input = STDIN.getch.downcase
|
|
243
|
+
|
|
244
|
+
if input >= '1' && input <= '9'
|
|
245
|
+
number = input.to_i
|
|
246
|
+
if number > 0 && number <= bookmarks.length
|
|
247
|
+
selected_number = number
|
|
248
|
+
break
|
|
249
|
+
end
|
|
250
|
+
elsif input == "\e" # ESC
|
|
236
251
|
break
|
|
237
252
|
end
|
|
238
|
-
elsif input == "\e" # ESC
|
|
239
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
240
|
-
return false
|
|
241
253
|
end
|
|
254
|
+
nil
|
|
242
255
|
end
|
|
243
256
|
|
|
244
|
-
|
|
257
|
+
return false unless selected_number
|
|
245
258
|
|
|
246
259
|
# Confirm deletion
|
|
247
260
|
bookmark_to_remove = bookmarks[selected_number - 1]
|
|
@@ -284,31 +297,32 @@ module Rufio
|
|
|
284
297
|
title = 'Bookmarks'
|
|
285
298
|
width = 60
|
|
286
299
|
height = [content_lines.length + 4, 20].min
|
|
287
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
288
300
|
|
|
289
|
-
|
|
301
|
+
# Wait for selection
|
|
302
|
+
selected_bookmark = nil
|
|
303
|
+
show_overlay_dialog(title, content_lines, {
|
|
304
|
+
width: width,
|
|
305
|
+
height: height,
|
|
290
306
|
border_color: "\e[34m", # Blue
|
|
291
307
|
title_color: "\e[1;34m", # Bold blue
|
|
292
308
|
content_color: "\e[37m" # White
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
309
|
+
}) do
|
|
310
|
+
loop do
|
|
311
|
+
input = STDIN.getch.downcase
|
|
312
|
+
|
|
313
|
+
if input >= '1' && input <= '9'
|
|
314
|
+
number = input.to_i
|
|
315
|
+
if number > 0 && number <= bookmarks.length
|
|
316
|
+
selected_bookmark = bookmarks[number - 1]
|
|
317
|
+
break
|
|
318
|
+
end
|
|
319
|
+
elsif input == "\e" # ESC
|
|
304
320
|
break
|
|
305
321
|
end
|
|
306
|
-
elsif input == "\e" # ESC
|
|
307
|
-
break
|
|
308
322
|
end
|
|
323
|
+
nil
|
|
309
324
|
end
|
|
310
325
|
|
|
311
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
312
326
|
selected_bookmark
|
|
313
327
|
end
|
|
314
328
|
|
|
@@ -376,6 +390,48 @@ module Rufio
|
|
|
376
390
|
|
|
377
391
|
private
|
|
378
392
|
|
|
393
|
+
# オーバーレイダイアログを表示してキー入力を待つヘルパーメソッド
|
|
394
|
+
def show_overlay_dialog(title, content_lines, options = {}, &block)
|
|
395
|
+
# terminal_ui が利用可能で、screen と renderer が存在する場合のみオーバーレイを使用
|
|
396
|
+
use_overlay = @terminal_ui &&
|
|
397
|
+
@terminal_ui.respond_to?(:screen) &&
|
|
398
|
+
@terminal_ui.respond_to?(:renderer) &&
|
|
399
|
+
@terminal_ui.screen &&
|
|
400
|
+
@terminal_ui.renderer
|
|
401
|
+
|
|
402
|
+
if use_overlay
|
|
403
|
+
# オーバーレイを使用
|
|
404
|
+
@terminal_ui.show_overlay_dialog(title, content_lines, options, &block)
|
|
405
|
+
else
|
|
406
|
+
# フォールバック: 従来の方法
|
|
407
|
+
width = options[:width]
|
|
408
|
+
height = options[:height]
|
|
409
|
+
|
|
410
|
+
unless width && height
|
|
411
|
+
width, height = @dialog_renderer.calculate_dimensions(content_lines, {
|
|
412
|
+
title: title,
|
|
413
|
+
min_width: options[:min_width] || 40,
|
|
414
|
+
max_width: options[:max_width] || 80
|
|
415
|
+
})
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
x, y = @dialog_renderer.calculate_center(width, height)
|
|
419
|
+
|
|
420
|
+
@dialog_renderer.draw_floating_window(x, y, width, height, title, content_lines, {
|
|
421
|
+
border_color: options[:border_color] || "\e[37m",
|
|
422
|
+
title_color: options[:title_color] || "\e[1;33m",
|
|
423
|
+
content_color: options[:content_color] || "\e[37m"
|
|
424
|
+
})
|
|
425
|
+
|
|
426
|
+
key = block_given? ? yield : STDIN.getch
|
|
427
|
+
|
|
428
|
+
@dialog_renderer.clear_area(x, y, width, height)
|
|
429
|
+
@terminal_ui&.refresh_display
|
|
430
|
+
|
|
431
|
+
key
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
379
435
|
# Show result dialog with success or error styling
|
|
380
436
|
# @param title [String] Dialog title
|
|
381
437
|
# @param message [String] Result message
|
|
@@ -401,16 +457,15 @@ module Rufio
|
|
|
401
457
|
|
|
402
458
|
width = 50
|
|
403
459
|
height = 6
|
|
404
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
405
460
|
|
|
406
|
-
|
|
461
|
+
# オーバーレイダイアログを表示
|
|
462
|
+
show_overlay_dialog(title, content_lines, {
|
|
463
|
+
width: width,
|
|
464
|
+
height: height,
|
|
407
465
|
border_color: border_color,
|
|
408
466
|
title_color: title_color,
|
|
409
467
|
content_color: "\e[37m"
|
|
410
468
|
})
|
|
411
|
-
|
|
412
|
-
STDIN.getch
|
|
413
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
414
469
|
end
|
|
415
470
|
|
|
416
471
|
# Show confirmation dialog for bookmark removal
|
|
@@ -431,30 +486,31 @@ module Rufio
|
|
|
431
486
|
title = 'Confirm Delete'
|
|
432
487
|
width = 50
|
|
433
488
|
height = content_lines.length + 4
|
|
434
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
435
489
|
|
|
436
|
-
|
|
490
|
+
# Wait for confirmation
|
|
491
|
+
confirmed = false
|
|
492
|
+
show_overlay_dialog(title, content_lines, {
|
|
493
|
+
width: width,
|
|
494
|
+
height: height,
|
|
437
495
|
border_color: "\e[33m", # Yellow (warning)
|
|
438
496
|
title_color: "\e[1;33m", # Bold yellow
|
|
439
497
|
content_color: "\e[37m" # White
|
|
440
|
-
})
|
|
498
|
+
}) do
|
|
499
|
+
loop do
|
|
500
|
+
input = STDIN.getch.downcase
|
|
441
501
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
break
|
|
451
|
-
when 'n', "\e" # n or ESC
|
|
452
|
-
confirmed = false
|
|
453
|
-
break
|
|
502
|
+
case input
|
|
503
|
+
when 'y'
|
|
504
|
+
confirmed = true
|
|
505
|
+
break
|
|
506
|
+
when 'n', "\e" # n or ESC
|
|
507
|
+
confirmed = false
|
|
508
|
+
break
|
|
509
|
+
end
|
|
454
510
|
end
|
|
511
|
+
nil
|
|
455
512
|
end
|
|
456
513
|
|
|
457
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
458
514
|
confirmed
|
|
459
515
|
end
|
|
460
516
|
end
|
|
@@ -8,10 +8,16 @@ module Rufio
|
|
|
8
8
|
def initialize(command_mode, dialog_renderer)
|
|
9
9
|
@command_mode = command_mode
|
|
10
10
|
@dialog_renderer = dialog_renderer
|
|
11
|
+
@terminal_ui = nil
|
|
11
12
|
# 最後に表示したウィンドウの位置とサイズを保存
|
|
12
13
|
@last_window = nil
|
|
13
14
|
end
|
|
14
15
|
|
|
16
|
+
# terminal_ui を設定
|
|
17
|
+
def set_terminal_ui(terminal_ui)
|
|
18
|
+
@terminal_ui = terminal_ui
|
|
19
|
+
end
|
|
20
|
+
|
|
15
21
|
# 入力文字列に対する補完候補を取得
|
|
16
22
|
# @param input [String] 現在の入力文字列
|
|
17
23
|
# @return [Array<String>] 補完候補の配列
|
|
@@ -124,21 +130,14 @@ module Rufio
|
|
|
124
130
|
max_width: 100
|
|
125
131
|
})
|
|
126
132
|
|
|
127
|
-
#
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
# キー入力を待つ
|
|
138
|
-
STDIN.getch
|
|
139
|
-
|
|
140
|
-
# ウィンドウをクリア
|
|
141
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
133
|
+
# オーバーレイダイアログを表示
|
|
134
|
+
show_overlay_dialog(title, content_lines, {
|
|
135
|
+
width: width,
|
|
136
|
+
height: height,
|
|
137
|
+
border_color: border_color,
|
|
138
|
+
title_color: title_color,
|
|
139
|
+
content_color: content_color
|
|
140
|
+
})
|
|
142
141
|
end
|
|
143
142
|
|
|
144
143
|
# コマンド入力プロンプトをクリア
|
|
@@ -156,6 +155,48 @@ module Rufio
|
|
|
156
155
|
|
|
157
156
|
private
|
|
158
157
|
|
|
158
|
+
# オーバーレイダイアログを表示してキー入力を待つヘルパーメソッド
|
|
159
|
+
def show_overlay_dialog(title, content_lines, options = {}, &block)
|
|
160
|
+
# terminal_ui が利用可能で、screen と renderer が存在する場合のみオーバーレイを使用
|
|
161
|
+
use_overlay = @terminal_ui &&
|
|
162
|
+
@terminal_ui.respond_to?(:screen) &&
|
|
163
|
+
@terminal_ui.respond_to?(:renderer) &&
|
|
164
|
+
@terminal_ui.screen &&
|
|
165
|
+
@terminal_ui.renderer
|
|
166
|
+
|
|
167
|
+
if use_overlay
|
|
168
|
+
# オーバーレイを使用
|
|
169
|
+
@terminal_ui.show_overlay_dialog(title, content_lines, options, &block)
|
|
170
|
+
else
|
|
171
|
+
# フォールバック: 従来の方法
|
|
172
|
+
width = options[:width]
|
|
173
|
+
height = options[:height]
|
|
174
|
+
|
|
175
|
+
unless width && height
|
|
176
|
+
width, height = @dialog_renderer.calculate_dimensions(content_lines, {
|
|
177
|
+
title: title,
|
|
178
|
+
min_width: options[:min_width] || 40,
|
|
179
|
+
max_width: options[:max_width] || 80
|
|
180
|
+
})
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
x, y = @dialog_renderer.calculate_center(width, height)
|
|
184
|
+
|
|
185
|
+
@dialog_renderer.draw_floating_window(x, y, width, height, title, content_lines, {
|
|
186
|
+
border_color: options[:border_color] || "\e[37m",
|
|
187
|
+
title_color: options[:title_color] || "\e[1;33m",
|
|
188
|
+
content_color: options[:content_color] || "\e[37m"
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
key = block_given? ? yield : STDIN.getch
|
|
192
|
+
|
|
193
|
+
@dialog_renderer.clear_area(x, y, width, height)
|
|
194
|
+
@terminal_ui&.refresh_display
|
|
195
|
+
|
|
196
|
+
key
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
159
200
|
# 文字列配列の共通プレフィックスを見つける
|
|
160
201
|
# @param strings [Array<String>] 文字列配列
|
|
161
202
|
# @return [String] 共通プレフィックス
|
|
@@ -75,6 +75,73 @@ module Rufio
|
|
|
75
75
|
screen.put_string(x, bottom_y, "└#{'─' * (width - 2)}┘", fg: border_color)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
+
# オーバーレイレイヤーにフローティングウィンドウを描画
|
|
79
|
+
# @param screen [Screen] Screen buffer with overlay enabled
|
|
80
|
+
# @param x [Integer] X position (column)
|
|
81
|
+
# @param y [Integer] Y position (row)
|
|
82
|
+
# @param width [Integer] Window width
|
|
83
|
+
# @param height [Integer] Window height
|
|
84
|
+
# @param title [String, nil] Window title (optional)
|
|
85
|
+
# @param content_lines [Array<String>] Content lines to display
|
|
86
|
+
# @param options [Hash] Customization options
|
|
87
|
+
def draw_floating_window_to_overlay(screen, x, y, width, height, title, content_lines, options = {})
|
|
88
|
+
# オーバーレイが有効でない場合は有効化
|
|
89
|
+
screen.enable_overlay unless screen.overlay_enabled?
|
|
90
|
+
|
|
91
|
+
border_color = options[:border_color] || "\e[37m"
|
|
92
|
+
title_color = options[:title_color] || "\e[1;33m"
|
|
93
|
+
content_color = options[:content_color] || "\e[37m"
|
|
94
|
+
|
|
95
|
+
# Draw top border
|
|
96
|
+
screen.put_overlay_string(x, y, "┌#{'─' * (width - 2)}┐", fg: border_color)
|
|
97
|
+
|
|
98
|
+
# Draw title line if title exists
|
|
99
|
+
if title
|
|
100
|
+
title_width = TextUtils.display_width(title)
|
|
101
|
+
title_padding = (width - 2 - title_width) / 2
|
|
102
|
+
padded_title = ' ' * title_padding + title
|
|
103
|
+
title_line = TextUtils.pad_string_to_width(padded_title, width - 2)
|
|
104
|
+
|
|
105
|
+
screen.put_overlay(x, y + 1, '│', fg: border_color)
|
|
106
|
+
screen.put_overlay_string(x + 1, y + 1, title_line, fg: title_color)
|
|
107
|
+
screen.put_overlay(x + width - 1, y + 1, '│', fg: border_color)
|
|
108
|
+
|
|
109
|
+
# Draw title separator
|
|
110
|
+
screen.put_overlay_string(x, y + 2, "├#{'─' * (width - 2)}┤", fg: border_color)
|
|
111
|
+
content_start_y = y + 3
|
|
112
|
+
else
|
|
113
|
+
content_start_y = y + 1
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Draw content lines
|
|
117
|
+
content_height = title ? height - 4 : height - 2
|
|
118
|
+
content_lines.each_with_index do |line, index|
|
|
119
|
+
break if index >= content_height
|
|
120
|
+
|
|
121
|
+
line_y = content_start_y + index
|
|
122
|
+
line_content = TextUtils.pad_string_to_width(line, width - 2)
|
|
123
|
+
|
|
124
|
+
screen.put_overlay(x, line_y, '│', fg: border_color)
|
|
125
|
+
screen.put_overlay_string(x + 1, line_y, line_content, fg: content_color)
|
|
126
|
+
screen.put_overlay(x + width - 1, line_y, '│', fg: border_color)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Fill remaining lines with empty space
|
|
130
|
+
remaining_lines = content_height - content_lines.length
|
|
131
|
+
remaining_lines.times do |i|
|
|
132
|
+
line_y = content_start_y + content_lines.length + i
|
|
133
|
+
empty_line = ' ' * (width - 2)
|
|
134
|
+
|
|
135
|
+
screen.put_overlay(x, line_y, '│', fg: border_color)
|
|
136
|
+
screen.put_overlay_string(x + 1, line_y, empty_line)
|
|
137
|
+
screen.put_overlay(x + width - 1, line_y, '│', fg: border_color)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Draw bottom border
|
|
141
|
+
bottom_y = y + height - 1
|
|
142
|
+
screen.put_overlay_string(x, bottom_y, "└#{'─' * (width - 2)}┘", fg: border_color)
|
|
143
|
+
end
|
|
144
|
+
|
|
78
145
|
# Draw a floating window with title, content, and customizable colors
|
|
79
146
|
# @param x [Integer] X position (column)
|
|
80
147
|
# @param y [Integer] Y position (row)
|