rufio 0.63.0 → 0.65.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 +52 -16
- 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/script_path_manager.rb +3 -3
- data/lib/rufio/script_runner.rb +1 -1
- data/lib/rufio/terminal_ui.rb +145 -80
- 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
|
@@ -75,7 +75,7 @@ module Rufio
|
|
|
75
75
|
@paths.each do |path|
|
|
76
76
|
next unless Dir.exist?(path)
|
|
77
77
|
|
|
78
|
-
Dir.glob(File.join(path, '*')).each do |file|
|
|
78
|
+
Dir.glob(File.join(path, '**', '*')).each do |file|
|
|
79
79
|
next unless File.file?(file)
|
|
80
80
|
|
|
81
81
|
basename = File.basename(file)
|
|
@@ -240,7 +240,7 @@ module Rufio
|
|
|
240
240
|
@paths.each do |path|
|
|
241
241
|
next unless Dir.exist?(path)
|
|
242
242
|
|
|
243
|
-
Dir.glob(File.join(path, '*')).each do |file|
|
|
243
|
+
Dir.glob(File.join(path, '**', '*')).each do |file|
|
|
244
244
|
next unless File.file?(file)
|
|
245
245
|
|
|
246
246
|
file_basename = File.basename(file)
|
|
@@ -276,7 +276,7 @@ module Rufio
|
|
|
276
276
|
@paths.each do |path|
|
|
277
277
|
next unless Dir.exist?(path)
|
|
278
278
|
|
|
279
|
-
Dir.glob(File.join(path, '*')).each do |file|
|
|
279
|
+
Dir.glob(File.join(path, '**', '*')).each do |file|
|
|
280
280
|
next unless File.file?(file)
|
|
281
281
|
|
|
282
282
|
file_basename = File.basename(file)
|
data/lib/rufio/script_runner.rb
CHANGED
data/lib/rufio/terminal_ui.rb
CHANGED
|
@@ -87,6 +87,9 @@ module Rufio
|
|
|
87
87
|
@keybind_handler.set_directory_listing(@directory_listing)
|
|
88
88
|
@keybind_handler.set_terminal_ui(self)
|
|
89
89
|
|
|
90
|
+
# command_mode_ui にも terminal_ui を設定
|
|
91
|
+
@command_mode_ui.set_terminal_ui(self)
|
|
92
|
+
|
|
90
93
|
# コマンドモードにバックグラウンドエグゼキュータを設定
|
|
91
94
|
@command_mode.background_executor = @background_executor if @background_executor
|
|
92
95
|
|
|
@@ -300,7 +303,15 @@ module Rufio
|
|
|
300
303
|
draw_screen_to_buffer(@screen, nil, current_fps)
|
|
301
304
|
end
|
|
302
305
|
|
|
303
|
-
#
|
|
306
|
+
# コマンドモードがアクティブな場合はオーバーレイにダイアログを描画
|
|
307
|
+
if @command_mode_active
|
|
308
|
+
draw_command_mode_to_overlay
|
|
309
|
+
else
|
|
310
|
+
# コマンドモードでない場合はオーバーレイをクリア
|
|
311
|
+
@screen.clear_overlay if @screen.overlay_enabled?
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# 差分レンダリング(dirty rowsのみ、オーバーレイを含む)
|
|
304
315
|
@renderer.render(@screen)
|
|
305
316
|
|
|
306
317
|
# 描画後にカーソルを画面外に移動
|
|
@@ -311,12 +322,6 @@ module Rufio
|
|
|
311
322
|
needs_redraw = false
|
|
312
323
|
end
|
|
313
324
|
|
|
314
|
-
# コマンドモードがアクティブな場合はフローティングウィンドウを表示
|
|
315
|
-
# Phase 4: 暫定的に直接描画(Screenバッファ外)
|
|
316
|
-
if @command_mode_active
|
|
317
|
-
@command_mode_ui.show_input_prompt(@command_input)
|
|
318
|
-
end
|
|
319
|
-
|
|
320
325
|
# SLEEP phase - CPU使用率削減のため適切にスリープ
|
|
321
326
|
elapsed = Time.now - start
|
|
322
327
|
sleep_time = [min_sleep_interval - elapsed, 0].max
|
|
@@ -508,7 +513,7 @@ module Rufio
|
|
|
508
513
|
# Phase 3: Screenバッファにヘッダーを描画
|
|
509
514
|
def draw_header_to_buffer(screen, y)
|
|
510
515
|
current_path = @directory_listing.current_path
|
|
511
|
-
header = "💎 rufio - #{current_path}"
|
|
516
|
+
header = "💎 rufio v#{VERSION} - #{current_path}"
|
|
512
517
|
|
|
513
518
|
# Add help mode indicator if in help mode
|
|
514
519
|
if @keybind_handler.help_mode?
|
|
@@ -527,14 +532,14 @@ module Rufio
|
|
|
527
532
|
# prioritize showing help mode indicator
|
|
528
533
|
help_text = " [Help Mode - Press ESC to exit]"
|
|
529
534
|
base_length = @screen_width - help_text.length - FILTER_TEXT_RESERVED
|
|
530
|
-
header = "💎 rufio - ...#{current_path[-base_length..-1]}#{help_text}"
|
|
535
|
+
header = "💎 rufio v#{VERSION} - ...#{current_path[-base_length..-1]}#{help_text}"
|
|
531
536
|
elsif @keybind_handler.filter_active?
|
|
532
537
|
# prioritize showing filter when active
|
|
533
538
|
filter_text = " [Filter: #{@keybind_handler.filter_query}]"
|
|
534
539
|
base_length = @screen_width - filter_text.length - FILTER_TEXT_RESERVED
|
|
535
|
-
header = "💎 rufio - ...#{current_path[-base_length..-1]}#{filter_text}"
|
|
540
|
+
header = "💎 rufio v#{VERSION} - ...#{current_path[-base_length..-1]}#{filter_text}"
|
|
536
541
|
else
|
|
537
|
-
header = "💎 rufio - ...#{current_path[-(@screen_width - FILTER_TEXT_RESERVED)..-1]}"
|
|
542
|
+
header = "💎 rufio v#{VERSION} - ...#{current_path[-(@screen_width - FILTER_TEXT_RESERVED)..-1]}"
|
|
538
543
|
end
|
|
539
544
|
end
|
|
540
545
|
|
|
@@ -601,7 +606,7 @@ module Rufio
|
|
|
601
606
|
|
|
602
607
|
def draw_header
|
|
603
608
|
current_path = @directory_listing.current_path
|
|
604
|
-
header = "💎 rufio - #{current_path}"
|
|
609
|
+
header = "💎 rufio v#{VERSION} - #{current_path}"
|
|
605
610
|
|
|
606
611
|
# Add help mode indicator if in help mode
|
|
607
612
|
if @keybind_handler.help_mode?
|
|
@@ -620,14 +625,14 @@ module Rufio
|
|
|
620
625
|
# prioritize showing help mode indicator
|
|
621
626
|
help_text = " [Help Mode - Press ESC to exit]"
|
|
622
627
|
base_length = @screen_width - help_text.length - FILTER_TEXT_RESERVED
|
|
623
|
-
header = "💎 rufio - ...#{current_path[-base_length..-1]}#{help_text}"
|
|
628
|
+
header = "💎 rufio v#{VERSION} - ...#{current_path[-base_length..-1]}#{help_text}"
|
|
624
629
|
elsif @keybind_handler.filter_active?
|
|
625
630
|
# prioritize showing filter when active
|
|
626
631
|
filter_text = " [Filter: #{@keybind_handler.filter_query}]"
|
|
627
632
|
base_length = @screen_width - filter_text.length - FILTER_TEXT_RESERVED
|
|
628
|
-
header = "💎 rufio - ...#{current_path[-base_length..-1]}#{filter_text}"
|
|
633
|
+
header = "💎 rufio v#{VERSION} - ...#{current_path[-base_length..-1]}#{filter_text}"
|
|
629
634
|
else
|
|
630
|
-
header = "💎 rufio - ...#{current_path[-(@screen_width - FILTER_TEXT_RESERVED)..-1]}"
|
|
635
|
+
header = "💎 rufio v#{VERSION} - ...#{current_path[-(@screen_width - FILTER_TEXT_RESERVED)..-1]}"
|
|
631
636
|
end
|
|
632
637
|
end
|
|
633
638
|
|
|
@@ -1230,6 +1235,11 @@ module Rufio
|
|
|
1230
1235
|
# キーバインドハンドラーに処理を委譲
|
|
1231
1236
|
result = @keybind_handler.handle_key(input) if input
|
|
1232
1237
|
|
|
1238
|
+
# 外部ターミナルアプリ(vim等)から戻った後は画面全体を再描画
|
|
1239
|
+
if result == :needs_refresh
|
|
1240
|
+
refresh_display
|
|
1241
|
+
end
|
|
1242
|
+
|
|
1233
1243
|
# 終了処理(qキーのみ、確認ダイアログの結果を確認)
|
|
1234
1244
|
if input == 'q' && result == true
|
|
1235
1245
|
@running = false
|
|
@@ -1294,6 +1304,11 @@ module Rufio
|
|
|
1294
1304
|
# キーバインドハンドラーに処理を委譲
|
|
1295
1305
|
result = @keybind_handler.handle_key(input)
|
|
1296
1306
|
|
|
1307
|
+
# 外部ターミナルアプリ(vim等)から戻った後は画面全体を再描画
|
|
1308
|
+
if result == :needs_refresh
|
|
1309
|
+
refresh_display
|
|
1310
|
+
end
|
|
1311
|
+
|
|
1297
1312
|
# 終了処理(qキーのみ、確認ダイアログの結果を確認)
|
|
1298
1313
|
if input == 'q' && result == true
|
|
1299
1314
|
@running = false
|
|
@@ -1361,6 +1376,42 @@ module Rufio
|
|
|
1361
1376
|
def deactivate_command_mode
|
|
1362
1377
|
@command_mode_active = false
|
|
1363
1378
|
@command_input = ""
|
|
1379
|
+
# オーバーレイをクリア
|
|
1380
|
+
@screen&.clear_overlay if @screen&.overlay_enabled?
|
|
1381
|
+
end
|
|
1382
|
+
|
|
1383
|
+
# コマンドモードダイアログをオーバーレイに描画
|
|
1384
|
+
def draw_command_mode_to_overlay
|
|
1385
|
+
return unless @screen
|
|
1386
|
+
|
|
1387
|
+
title = "Command Mode"
|
|
1388
|
+
content_lines = [
|
|
1389
|
+
"",
|
|
1390
|
+
"#{@command_input}_", # カーソル表示
|
|
1391
|
+
"",
|
|
1392
|
+
"Tab: Complete | Enter: Execute | ESC: Cancel"
|
|
1393
|
+
]
|
|
1394
|
+
|
|
1395
|
+
border_color = "\e[34m" # Blue
|
|
1396
|
+
title_color = "\e[1;34m" # Bold blue
|
|
1397
|
+
content_color = "\e[37m" # White
|
|
1398
|
+
|
|
1399
|
+
# ウィンドウサイズを計算
|
|
1400
|
+
width, height = @dialog_renderer.calculate_dimensions(content_lines, {
|
|
1401
|
+
title: title,
|
|
1402
|
+
min_width: 50,
|
|
1403
|
+
max_width: 80
|
|
1404
|
+
})
|
|
1405
|
+
|
|
1406
|
+
# 中央位置を計算
|
|
1407
|
+
x, y = @dialog_renderer.calculate_center(width, height)
|
|
1408
|
+
|
|
1409
|
+
# オーバーレイにダイアログを描画
|
|
1410
|
+
@dialog_renderer.draw_floating_window_to_overlay(@screen, x, y, width, height, title, content_lines, {
|
|
1411
|
+
border_color: border_color,
|
|
1412
|
+
title_color: title_color,
|
|
1413
|
+
content_color: content_color
|
|
1414
|
+
})
|
|
1364
1415
|
end
|
|
1365
1416
|
|
|
1366
1417
|
# コマンドモードがアクティブかどうか
|
|
@@ -1475,36 +1526,14 @@ module Rufio
|
|
|
1475
1526
|
content_lines << ""
|
|
1476
1527
|
content_lines << "Press any key to continue..."
|
|
1477
1528
|
|
|
1478
|
-
#
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
min_width: 40,
|
|
1487
|
-
max_width: 80
|
|
1488
|
-
})
|
|
1489
|
-
|
|
1490
|
-
# 中央位置を計算
|
|
1491
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
1492
|
-
|
|
1493
|
-
# フローティングウィンドウを描画
|
|
1494
|
-
@dialog_renderer.draw_floating_window(x, y, width, height, title, content_lines, {
|
|
1495
|
-
border_color: border_color,
|
|
1496
|
-
title_color: title_color,
|
|
1497
|
-
content_color: content_color
|
|
1498
|
-
})
|
|
1499
|
-
|
|
1500
|
-
# キー入力を待つ
|
|
1501
|
-
STDIN.getch
|
|
1502
|
-
|
|
1503
|
-
# ウィンドウをクリア
|
|
1504
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
1505
|
-
|
|
1506
|
-
# 画面を再描画
|
|
1507
|
-
draw_screen
|
|
1529
|
+
# オーバーレイダイアログを表示
|
|
1530
|
+
show_overlay_dialog(title, content_lines, {
|
|
1531
|
+
min_width: 40,
|
|
1532
|
+
max_width: 80,
|
|
1533
|
+
border_color: "\e[33m", # Yellow
|
|
1534
|
+
title_color: "\e[1;33m", # Bold yellow
|
|
1535
|
+
content_color: "\e[37m" # White
|
|
1536
|
+
})
|
|
1508
1537
|
end
|
|
1509
1538
|
|
|
1510
1539
|
# Show info notices from the info directory if any are unread
|
|
@@ -1527,36 +1556,18 @@ module Rufio
|
|
|
1527
1556
|
# Calculate height based on content length
|
|
1528
1557
|
content_length = notice[:content].length
|
|
1529
1558
|
height = [content_length + 4, @screen_height - 4].min # +4 for borders and title
|
|
1530
|
-
x = (@screen_width - width) / 2
|
|
1531
|
-
y = (@screen_height - height) / 2
|
|
1532
|
-
|
|
1533
|
-
# Display the notice window
|
|
1534
|
-
@dialog_renderer.draw_floating_window(
|
|
1535
|
-
x, y, width, height,
|
|
1536
|
-
notice[:title],
|
|
1537
|
-
notice[:content],
|
|
1538
|
-
{
|
|
1539
|
-
border_color: "\e[36m", # Cyan
|
|
1540
|
-
title_color: "\e[1;36m", # Bold cyan
|
|
1541
|
-
content_color: "\e[37m" # White
|
|
1542
|
-
}
|
|
1543
|
-
)
|
|
1544
1559
|
|
|
1545
|
-
#
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1560
|
+
# オーバーレイダイアログを表示
|
|
1561
|
+
show_overlay_dialog(notice[:title], notice[:content], {
|
|
1562
|
+
width: width,
|
|
1563
|
+
height: height,
|
|
1564
|
+
border_color: "\e[36m", # Cyan
|
|
1565
|
+
title_color: "\e[1;36m", # Bold cyan
|
|
1566
|
+
content_color: "\e[37m" # White
|
|
1567
|
+
})
|
|
1551
1568
|
|
|
1552
1569
|
# Mark as shown
|
|
1553
1570
|
info_notice.mark_as_shown(notice[:file])
|
|
1554
|
-
|
|
1555
|
-
# Clear the notice window
|
|
1556
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
1557
|
-
|
|
1558
|
-
# Redraw the screen
|
|
1559
|
-
draw_screen
|
|
1560
1571
|
end
|
|
1561
1572
|
|
|
1562
1573
|
# ログモードに入る(廃止済み: 空のメソッド)
|
|
@@ -1670,6 +1681,65 @@ module Rufio
|
|
|
1670
1681
|
end
|
|
1671
1682
|
end
|
|
1672
1683
|
|
|
1684
|
+
# オーバーレイダイアログを表示してキー入力を待つヘルパーメソッド
|
|
1685
|
+
# @param title [String] ダイアログタイトル
|
|
1686
|
+
# @param content_lines [Array<String>] コンテンツ行
|
|
1687
|
+
# @param options [Hash] オプション
|
|
1688
|
+
# @option options [String] :border_color ボーダー色
|
|
1689
|
+
# @option options [String] :title_color タイトル色
|
|
1690
|
+
# @option options [String] :content_color コンテンツ色
|
|
1691
|
+
# @option options [Integer] :width 幅(省略時は自動計算)
|
|
1692
|
+
# @option options [Integer] :height 高さ(省略時は自動計算)
|
|
1693
|
+
# @option options [Integer] :min_width 最小幅
|
|
1694
|
+
# @option options [Integer] :max_width 最大幅
|
|
1695
|
+
# @yield キー入力処理(ブロックが与えられた場合)
|
|
1696
|
+
# @return [String] 入力されたキー
|
|
1697
|
+
def show_overlay_dialog(title, content_lines, options = {}, &block)
|
|
1698
|
+
return nil unless @screen && @renderer
|
|
1699
|
+
|
|
1700
|
+
# オーバーレイを有効化
|
|
1701
|
+
@screen.enable_overlay
|
|
1702
|
+
|
|
1703
|
+
# ウィンドウサイズを計算
|
|
1704
|
+
if options[:width] && options[:height]
|
|
1705
|
+
width = options[:width]
|
|
1706
|
+
height = options[:height]
|
|
1707
|
+
else
|
|
1708
|
+
width, height = @dialog_renderer.calculate_dimensions(content_lines, {
|
|
1709
|
+
title: title,
|
|
1710
|
+
min_width: options[:min_width] || 40,
|
|
1711
|
+
max_width: options[:max_width] || 80
|
|
1712
|
+
})
|
|
1713
|
+
end
|
|
1714
|
+
|
|
1715
|
+
# 中央位置を計算
|
|
1716
|
+
x, y = @dialog_renderer.calculate_center(width, height)
|
|
1717
|
+
|
|
1718
|
+
# オーバーレイにダイアログを描画
|
|
1719
|
+
@dialog_renderer.draw_floating_window_to_overlay(@screen, x, y, width, height, title, content_lines, {
|
|
1720
|
+
border_color: options[:border_color] || "\e[37m",
|
|
1721
|
+
title_color: options[:title_color] || "\e[1;33m",
|
|
1722
|
+
content_color: options[:content_color] || "\e[37m"
|
|
1723
|
+
})
|
|
1724
|
+
|
|
1725
|
+
# レンダリング
|
|
1726
|
+
@renderer.render(@screen)
|
|
1727
|
+
|
|
1728
|
+
# キー入力を待つ
|
|
1729
|
+
key = block_given? ? yield : STDIN.getch
|
|
1730
|
+
|
|
1731
|
+
# オーバーレイを無効化
|
|
1732
|
+
@screen.disable_overlay
|
|
1733
|
+
|
|
1734
|
+
# 画面を再描画
|
|
1735
|
+
@renderer.render(@screen)
|
|
1736
|
+
|
|
1737
|
+
key
|
|
1738
|
+
end
|
|
1739
|
+
|
|
1740
|
+
# Screen と Renderer のアクセサ(他のクラスから利用可能に)
|
|
1741
|
+
attr_reader :screen, :renderer
|
|
1742
|
+
|
|
1673
1743
|
# ヘルプダイアログを表示
|
|
1674
1744
|
def show_help_dialog
|
|
1675
1745
|
content_lines = [
|
|
@@ -1716,20 +1786,15 @@ module Rufio
|
|
|
1716
1786
|
|
|
1717
1787
|
width = 60
|
|
1718
1788
|
height = [content_lines.length + 4, @screen_height - 4].min
|
|
1719
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
1720
1789
|
|
|
1721
|
-
|
|
1790
|
+
# オーバーレイダイアログを表示
|
|
1791
|
+
show_overlay_dialog('rufio - Help', content_lines, {
|
|
1792
|
+
width: width,
|
|
1793
|
+
height: height,
|
|
1722
1794
|
border_color: "\e[36m", # Cyan
|
|
1723
1795
|
title_color: "\e[1;36m", # Bold cyan
|
|
1724
1796
|
content_color: "\e[37m" # White
|
|
1725
1797
|
})
|
|
1726
|
-
|
|
1727
|
-
require 'io/console'
|
|
1728
|
-
IO.console.getch
|
|
1729
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
1730
|
-
|
|
1731
|
-
# 画面を再描画
|
|
1732
|
-
refresh_display
|
|
1733
1798
|
end
|
|
1734
1799
|
|
|
1735
1800
|
end
|
data/lib/rufio/text_utils.rb
CHANGED
|
@@ -25,8 +25,10 @@ module Rufio
|
|
|
25
25
|
def char_width(char)
|
|
26
26
|
@char_width_cache[char] ||= begin
|
|
27
27
|
case char
|
|
28
|
-
when /[\
|
|
29
|
-
|
|
28
|
+
when /[\u2500-\u257F]/
|
|
29
|
+
HALFWIDTH_CHAR_WIDTH # Box Drawing characters (罫線文字) - ターミナルでは幅1
|
|
30
|
+
when /[\u3000-\u303F\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FAF\uFF00-\uFFEF\u2580-\u259F]/
|
|
31
|
+
FULLWIDTH_CHAR_WIDTH # Japanese characters (hiragana, katakana, kanji, full-width symbols, block elements)
|
|
30
32
|
when /[\u0020-\u007E]/
|
|
31
33
|
HALFWIDTH_CHAR_WIDTH # ASCII characters
|
|
32
34
|
else
|
data/lib/rufio/version.rb
CHANGED
|
@@ -11,6 +11,12 @@ module Rufio
|
|
|
11
11
|
|
|
12
12
|
def initialize(dialog_renderer = nil)
|
|
13
13
|
@dialog_renderer = dialog_renderer
|
|
14
|
+
@terminal_ui = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# terminal_ui を設定
|
|
18
|
+
def set_terminal_ui(terminal_ui)
|
|
19
|
+
@terminal_ui = terminal_ui
|
|
14
20
|
end
|
|
15
21
|
|
|
16
22
|
# Check if zoxide is available
|
|
@@ -82,6 +88,48 @@ module Rufio
|
|
|
82
88
|
|
|
83
89
|
private
|
|
84
90
|
|
|
91
|
+
# オーバーレイダイアログを表示してキー入力を待つヘルパーメソッド
|
|
92
|
+
def show_overlay_dialog(title, content_lines, options = {}, &block)
|
|
93
|
+
# terminal_ui が利用可能で、screen と renderer が存在する場合のみオーバーレイを使用
|
|
94
|
+
use_overlay = @terminal_ui &&
|
|
95
|
+
@terminal_ui.respond_to?(:screen) &&
|
|
96
|
+
@terminal_ui.respond_to?(:renderer) &&
|
|
97
|
+
@terminal_ui.screen &&
|
|
98
|
+
@terminal_ui.renderer
|
|
99
|
+
|
|
100
|
+
if use_overlay
|
|
101
|
+
# オーバーレイを使用
|
|
102
|
+
@terminal_ui.show_overlay_dialog(title, content_lines, options, &block)
|
|
103
|
+
else
|
|
104
|
+
# フォールバック: 従来の方法
|
|
105
|
+
width = options[:width]
|
|
106
|
+
height = options[:height]
|
|
107
|
+
|
|
108
|
+
unless width && height
|
|
109
|
+
width, height = @dialog_renderer.calculate_dimensions(content_lines, {
|
|
110
|
+
title: title,
|
|
111
|
+
min_width: options[:min_width] || 40,
|
|
112
|
+
max_width: options[:max_width] || 80
|
|
113
|
+
})
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
x, y = @dialog_renderer.calculate_center(width, height)
|
|
117
|
+
|
|
118
|
+
@dialog_renderer.draw_floating_window(x, y, width, height, title, content_lines, {
|
|
119
|
+
border_color: options[:border_color] || "\e[37m",
|
|
120
|
+
title_color: options[:title_color] || "\e[1;33m",
|
|
121
|
+
content_color: options[:content_color] || "\e[37m"
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
key = block_given? ? yield : STDIN.getch
|
|
125
|
+
|
|
126
|
+
@dialog_renderer.clear_area(x, y, width, height)
|
|
127
|
+
@terminal_ui&.refresh_display
|
|
128
|
+
|
|
129
|
+
key
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
85
133
|
# Show message when no history is available
|
|
86
134
|
def show_no_history_message
|
|
87
135
|
return unless @dialog_renderer
|
|
@@ -99,16 +147,15 @@ module Rufio
|
|
|
99
147
|
|
|
100
148
|
dialog_width = DIALOG_WIDTH
|
|
101
149
|
dialog_height = DIALOG_BORDER_HEIGHT + content_lines.length
|
|
102
|
-
x, y = @dialog_renderer.calculate_center(dialog_width, dialog_height)
|
|
103
|
-
|
|
104
|
-
@dialog_renderer.draw_floating_window(x, y, dialog_width, dialog_height, title, content_lines, {
|
|
105
|
-
border_color: "\e[33m", # Yellow
|
|
106
|
-
title_color: "\e[1;33m", # Bold yellow
|
|
107
|
-
content_color: "\e[37m" # White
|
|
108
|
-
})
|
|
109
150
|
|
|
110
|
-
|
|
111
|
-
|
|
151
|
+
# オーバーレイダイアログを表示
|
|
152
|
+
show_overlay_dialog(title, content_lines, {
|
|
153
|
+
width: dialog_width,
|
|
154
|
+
height: dialog_height,
|
|
155
|
+
border_color: "\e[33m", # Yellow
|
|
156
|
+
title_color: "\e[1;33m", # Bold yellow
|
|
157
|
+
content_color: "\e[37m" # White
|
|
158
|
+
})
|
|
112
159
|
end
|
|
113
160
|
|
|
114
161
|
# Select from zoxide history
|
|
@@ -137,52 +184,54 @@ module Rufio
|
|
|
137
184
|
|
|
138
185
|
dialog_width = 70
|
|
139
186
|
dialog_height = [4 + content_lines.length, 25].min
|
|
140
|
-
x, y = @dialog_renderer.calculate_center(dialog_width, dialog_height)
|
|
141
|
-
|
|
142
|
-
@dialog_renderer.draw_floating_window(x, y, dialog_width, dialog_height, title, content_lines, {
|
|
143
|
-
border_color: "\e[36m", # Cyan
|
|
144
|
-
title_color: "\e[1;36m", # Bold cyan
|
|
145
|
-
content_color: "\e[37m" # White
|
|
146
|
-
})
|
|
147
187
|
|
|
148
188
|
# Number input mode
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
189
|
+
selected_path = nil
|
|
190
|
+
show_overlay_dialog(title, content_lines, {
|
|
191
|
+
width: dialog_width,
|
|
192
|
+
height: dialog_height,
|
|
193
|
+
border_color: "\e[36m", # Cyan
|
|
194
|
+
title_color: "\e[1;36m", # Bold cyan
|
|
195
|
+
content_color: "\e[37m" # White
|
|
196
|
+
}) do
|
|
197
|
+
input_buffer = ''
|
|
198
|
+
|
|
199
|
+
loop do
|
|
200
|
+
char = STDIN.getch
|
|
201
|
+
|
|
202
|
+
case char
|
|
203
|
+
when "\e", "\x03" # ESC, Ctrl+C
|
|
204
|
+
break
|
|
205
|
+
when "\r", "\n" # Enter
|
|
206
|
+
unless input_buffer.empty?
|
|
207
|
+
number = input_buffer.to_i
|
|
208
|
+
if number > 0 && number <= display_history.length
|
|
209
|
+
selected_path = display_history[number - 1][:path]
|
|
210
|
+
break
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
# Invalid input, ask again
|
|
214
|
+
input_buffer = ''
|
|
215
|
+
when "\u007f", "\b" # Backspace
|
|
216
|
+
input_buffer = input_buffer[0...-1] unless input_buffer.empty?
|
|
217
|
+
when /[0-9]/
|
|
218
|
+
input_buffer += char
|
|
219
|
+
# Max 2 digits
|
|
220
|
+
input_buffer = input_buffer[-2..-1] if input_buffer.length > 2
|
|
221
|
+
|
|
222
|
+
# If number is within range, select immediately
|
|
160
223
|
number = input_buffer.to_i
|
|
161
|
-
if number > 0 && number <= display_history.length
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
224
|
+
if number > 0 && number <= display_history.length &&
|
|
225
|
+
(number >= 10 || input_buffer.length == 1)
|
|
226
|
+
selected_path = display_history[number - 1][:path]
|
|
227
|
+
break
|
|
165
228
|
end
|
|
166
229
|
end
|
|
167
|
-
# Invalid input, ask again
|
|
168
|
-
input_buffer = ''
|
|
169
|
-
when "\u007f", "\b" # Backspace
|
|
170
|
-
input_buffer = input_buffer[0...-1] unless input_buffer.empty?
|
|
171
|
-
when /[0-9]/
|
|
172
|
-
input_buffer += char
|
|
173
|
-
# Max 2 digits
|
|
174
|
-
input_buffer = input_buffer[-2..-1] if input_buffer.length > 2
|
|
175
|
-
|
|
176
|
-
# If number is within range, select immediately
|
|
177
|
-
number = input_buffer.to_i
|
|
178
|
-
if number > 0 && number <= display_history.length &&
|
|
179
|
-
(number >= 10 || input_buffer.length == 1)
|
|
180
|
-
selected_entry = display_history[number - 1]
|
|
181
|
-
@dialog_renderer.clear_area(x, y, dialog_width, dialog_height)
|
|
182
|
-
return selected_entry[:path]
|
|
183
|
-
end
|
|
184
230
|
end
|
|
231
|
+
nil
|
|
185
232
|
end
|
|
233
|
+
|
|
234
|
+
selected_path
|
|
186
235
|
end
|
|
187
236
|
end
|
|
188
237
|
end
|