beniya 0.2.0 → 0.3.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/README.md +50 -1
- data/README_EN.md +50 -1
- data/lib/beniya/application.rb +1 -0
- data/lib/beniya/file_preview.rb +23 -3
- data/lib/beniya/keybind_handler.rb +150 -3
- data/lib/beniya/terminal_ui.rb +54 -8
- data/lib/beniya/version.rb +1 -1
- 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: 2e937b12eb5f1aa3425c8dd832cb7bd11396dfd86b6e232de58fe771c3da47a2
|
4
|
+
data.tar.gz: 1c41f33e6419d9458c778e8d7937472ad29e4f6d49ffcca12f1e78fac07f16ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 272779c673aa653ffeada51b3f46ff4da876d2107310fd79460d1f3a50eae6690dd60d3c21fb9f9ff21ab6914e5baab7ac96c54cb273c68c0b4859d95cb66077
|
7
|
+
data.tar.gz: 4bf52e383efe9457ec8e0b46b90a5b0742eddd48a222197d83de6e374942cefb92df4c802cd40bb3b047c6e4180311e87a326fd1eabfb453f9b5bac3938d8dd6
|
data/README.md
CHANGED
@@ -13,7 +13,9 @@ beniyaは、Yaziにインスパイアされたターミナル上で動作する
|
|
13
13
|
- **軽量でシンプル**: Rubyで書かれた軽量なファイルマネージャー
|
14
14
|
- **直感的な操作**: Vimライクなキーバインド
|
15
15
|
- **ファイルプレビュー**: テキストファイルの内容をその場で確認
|
16
|
-
-
|
16
|
+
- **ファイル選択・操作**: 複数ファイルの選択、移動、コピー、削除が可能
|
17
|
+
- **ベースディレクトリ操作**: 起動ディレクトリへの一括ファイル移動・コピー
|
18
|
+
- **リアルタイムフィルター**: sキーでファイル名の絞り込み表示
|
17
19
|
- **高度な検索機能**: fzfとrgaを使った強力な検索
|
18
20
|
- **マルチプラットフォーム**: macOS、Linux、Windowsで動作
|
19
21
|
- **外部エディタ連携**: お気に入りのエディタでファイルを開く
|
@@ -77,6 +79,15 @@ beniya --help # ヘルプメッセージを表示
|
|
77
79
|
| `a` | 新しいファイルを作成 |
|
78
80
|
| `A` | 新しいディレクトリを作成 |
|
79
81
|
|
82
|
+
#### ファイル選択・操作
|
83
|
+
|
84
|
+
| キー | 機能 |
|
85
|
+
| ------- | ---------------------------------------------------- |
|
86
|
+
| `Space` | ファイル・ディレクトリを選択・選択解除(複数選択可) |
|
87
|
+
| `m` | 選択したアイテムをベースディレクトリに移動 |
|
88
|
+
| `p` | 選択したアイテムをベースディレクトリにコピー |
|
89
|
+
| `x` | 選択したアイテムを削除 |
|
90
|
+
|
80
91
|
#### リアルタイムフィルター機能
|
81
92
|
|
82
93
|
| キー | 機能 |
|
@@ -100,6 +111,44 @@ beniya --help # ヘルプメッセージを表示
|
|
100
111
|
| ---- | ------------ |
|
101
112
|
| `q` | beniyaを終了 |
|
102
113
|
|
114
|
+
### ファイル選択・操作機能の詳細
|
115
|
+
|
116
|
+
#### ファイル・ディレクトリ選択 (`Space`)
|
117
|
+
|
118
|
+
- **選択・選択解除**: `Space`キーでファイルやディレクトリを選択・選択解除
|
119
|
+
- **複数選択**: 複数のファイルやディレクトリを同時に選択可能
|
120
|
+
- **視覚的表示**: 選択されたアイテムは✓マークと緑色の背景で表示
|
121
|
+
- **選択状態の表示**: 画面上部2行目に選択中のアイテム数が表示
|
122
|
+
|
123
|
+
#### ベースディレクトリ操作
|
124
|
+
|
125
|
+
beniya起動時のディレクトリが**ベースディレクトリ**として設定され、選択したファイルの移動・コピー先となります。
|
126
|
+
|
127
|
+
| 操作 | キー | 機能 |
|
128
|
+
| -------- | ---- | ---------------------------------------- |
|
129
|
+
| **移動** | `m` | 選択したアイテムをベースディレクトリに移動 |
|
130
|
+
| **コピー** | `p` | 選択したアイテムをベースディレクトリにコピー |
|
131
|
+
| **削除** | `x` | 選択したアイテムを削除 |
|
132
|
+
|
133
|
+
#### 操作の流れ
|
134
|
+
|
135
|
+
```
|
136
|
+
1. Space → ファイル・ディレクトリを選択(複数選択可)
|
137
|
+
2. 操作キーを選択:
|
138
|
+
- m → ベースディレクトリに移動
|
139
|
+
- p → ベースディレクトリにコピー
|
140
|
+
- x → 削除
|
141
|
+
3. y/n → 確認ダイアログで実行/キャンセル
|
142
|
+
4. 結果表示 → 処理結果を確認
|
143
|
+
```
|
144
|
+
|
145
|
+
#### 安全機能
|
146
|
+
|
147
|
+
- **確認ダイアログ**: 移動・コピー・削除前に必ず確認
|
148
|
+
- **重複チェック**: 同名ファイルがある場合は自動でスキップ
|
149
|
+
- **エラーハンドリング**: 権限不足などのエラーに適切に対応
|
150
|
+
- **操作ログ**: 処理結果を詳細に表示
|
151
|
+
|
103
152
|
### フィルター機能の詳細
|
104
153
|
|
105
154
|
#### リアルタイムフィルター (`s`)
|
data/README_EN.md
CHANGED
@@ -13,7 +13,9 @@ beniya is a terminal-based file manager inspired by Yazi. It's implemented in Ru
|
|
13
13
|
- **Lightweight & Simple**: A lightweight file manager written in Ruby
|
14
14
|
- **Intuitive Operation**: Vim-like key bindings
|
15
15
|
- **File Preview**: View text file contents on the fly
|
16
|
-
- **
|
16
|
+
- **File Selection & Operations**: Select multiple files, move, copy, and delete
|
17
|
+
- **Base Directory Operations**: Batch file operations to startup directory
|
18
|
+
- **Real-time Filter**: Filter files by name using s key
|
17
19
|
- **Advanced Search**: Powerful search using fzf and rga
|
18
20
|
- **Multi-platform**: Runs on macOS, Linux, and Windows
|
19
21
|
- **External Editor Integration**: Open files with your favorite editor
|
@@ -77,6 +79,15 @@ beniya --help # Show help message
|
|
77
79
|
| `a` | Create new file |
|
78
80
|
| `A` | Create new directory |
|
79
81
|
|
82
|
+
#### File Selection & Operations
|
83
|
+
|
84
|
+
| Key | Function |
|
85
|
+
| ------- | ------------------------------------------- |
|
86
|
+
| `Space` | Select/deselect files and directories |
|
87
|
+
| `m` | Move selected items to base directory |
|
88
|
+
| `p` | Copy selected items to base directory |
|
89
|
+
| `x` | Delete selected items |
|
90
|
+
|
80
91
|
#### Real-time Filter
|
81
92
|
|
82
93
|
| Key | Function |
|
@@ -100,6 +111,44 @@ beniya --help # Show help message
|
|
100
111
|
| --- | ----------- |
|
101
112
|
| `q` | Quit beniya |
|
102
113
|
|
114
|
+
### File Selection & Operations
|
115
|
+
|
116
|
+
#### File and Directory Selection (`Space`)
|
117
|
+
|
118
|
+
- **Select/Deselect**: Use `Space` key to select or deselect files and directories
|
119
|
+
- **Multiple Selection**: Select multiple files and directories simultaneously
|
120
|
+
- **Visual Display**: Selected items are marked with ✓ and highlighted in green
|
121
|
+
- **Selection Counter**: The number of selected items is shown on the second line of the screen
|
122
|
+
|
123
|
+
#### Base Directory Operations
|
124
|
+
|
125
|
+
The directory where beniya starts becomes the **base directory**, which serves as the destination for move and copy operations.
|
126
|
+
|
127
|
+
| Operation | Key | Function |
|
128
|
+
| --------- | --- | --------------------------------------- |
|
129
|
+
| **Move** | `m` | Move selected items to base directory |
|
130
|
+
| **Copy** | `p` | Copy selected items to base directory |
|
131
|
+
| **Delete** | `x` | Delete selected items |
|
132
|
+
|
133
|
+
#### Operation Workflow
|
134
|
+
|
135
|
+
```
|
136
|
+
1. Space → Select files/directories (multiple selection possible)
|
137
|
+
2. Choose operation key:
|
138
|
+
- m → Move to base directory
|
139
|
+
- p → Copy to base directory
|
140
|
+
- x → Delete
|
141
|
+
3. y/n → Confirm or cancel in confirmation dialog
|
142
|
+
4. Result Display → Review operation results
|
143
|
+
```
|
144
|
+
|
145
|
+
#### Safety Features
|
146
|
+
|
147
|
+
- **Confirmation Dialog**: Always confirm before move/copy/delete operations
|
148
|
+
- **Duplicate Check**: Automatically skip files with same names
|
149
|
+
- **Error Handling**: Proper handling of permission errors and other issues
|
150
|
+
- **Operation Log**: Detailed display of operation results
|
151
|
+
|
103
152
|
### Filter Feature
|
104
153
|
|
105
154
|
#### Real-time Filter (`s`)
|
data/lib/beniya/application.rb
CHANGED
data/lib/beniya/file_preview.rb
CHANGED
@@ -19,8 +19,8 @@ module Beniya
|
|
19
19
|
|
20
20
|
begin
|
21
21
|
# binary file detection
|
22
|
-
sample = File.
|
23
|
-
return binary_response if binary_file?(sample)
|
22
|
+
sample = File.binread(file_path, [file_size, 512].min)
|
23
|
+
return binary_response(file_path) if binary_file?(sample)
|
24
24
|
|
25
25
|
# process as text file
|
26
26
|
lines = read_text_file(file_path, max_lines)
|
@@ -124,6 +124,14 @@ module Beniya
|
|
124
124
|
{ type: "code", language: "markdown" }
|
125
125
|
when ".txt", ".log"
|
126
126
|
{ type: "text", language: nil }
|
127
|
+
when ".zip", ".tar", ".gz", ".bz2", ".xz", ".7z"
|
128
|
+
{ type: "archive", language: nil }
|
129
|
+
when ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg"
|
130
|
+
{ type: "image", language: nil }
|
131
|
+
when ".pdf"
|
132
|
+
{ type: "document", language: nil }
|
133
|
+
when ".exe", ".dmg", ".deb", ".rpm"
|
134
|
+
{ type: "executable", language: nil }
|
127
135
|
else
|
128
136
|
{ type: "text", language: nil }
|
129
137
|
end
|
@@ -147,7 +155,19 @@ module Beniya
|
|
147
155
|
}
|
148
156
|
end
|
149
157
|
|
150
|
-
def binary_response
|
158
|
+
def binary_response(file_path = nil)
|
159
|
+
file_size = file_path ? File.size(file_path) : 0
|
160
|
+
modified_time = file_path ? File.mtime(file_path) : Time.now
|
161
|
+
|
162
|
+
{
|
163
|
+
type: "binary",
|
164
|
+
message: "#{ConfigLoader.message('file.binary_file')} - #{ConfigLoader.message('file.cannot_preview')}",
|
165
|
+
lines: ["(#{ConfigLoader.message('file.binary_file')})"],
|
166
|
+
size: file_size,
|
167
|
+
modified: modified_time,
|
168
|
+
encoding: "binary"
|
169
|
+
}
|
170
|
+
rescue => e
|
151
171
|
{
|
152
172
|
type: "binary",
|
153
173
|
message: "#{ConfigLoader.message('file.binary_file')} - #{ConfigLoader.message('file.cannot_preview')}",
|
@@ -13,6 +13,8 @@ module Beniya
|
|
13
13
|
@filter_query = ""
|
14
14
|
@filtered_entries = []
|
15
15
|
@original_entries = []
|
16
|
+
@selected_items = []
|
17
|
+
@base_directory = nil
|
16
18
|
end
|
17
19
|
|
18
20
|
def set_directory_listing(directory_listing)
|
@@ -24,6 +26,18 @@ module Beniya
|
|
24
26
|
@terminal_ui = terminal_ui
|
25
27
|
end
|
26
28
|
|
29
|
+
def set_base_directory(base_dir)
|
30
|
+
@base_directory = File.expand_path(base_dir)
|
31
|
+
end
|
32
|
+
|
33
|
+
def selected_items
|
34
|
+
@selected_items.dup
|
35
|
+
end
|
36
|
+
|
37
|
+
def is_selected?(entry_name)
|
38
|
+
@selected_items.include?(entry_name)
|
39
|
+
end
|
40
|
+
|
27
41
|
def handle_key(key)
|
28
42
|
return false unless @directory_listing
|
29
43
|
|
@@ -60,8 +74,8 @@ module Beniya
|
|
60
74
|
# 新規フィルターモード開始
|
61
75
|
start_filter_mode
|
62
76
|
end
|
63
|
-
when ' ' # Space -
|
64
|
-
|
77
|
+
when ' ' # Space - toggle selection
|
78
|
+
toggle_selection
|
65
79
|
when "\e" # ESC
|
66
80
|
if !@filter_query.empty?
|
67
81
|
# フィルタが設定されている場合はクリア
|
@@ -82,6 +96,12 @@ module Beniya
|
|
82
96
|
create_file
|
83
97
|
when 'A' # A
|
84
98
|
create_directory
|
99
|
+
when 'm' # m - move selected files to base directory
|
100
|
+
move_selected_to_base
|
101
|
+
when 'p' # p - copy selected files to base directory
|
102
|
+
copy_selected_to_base
|
103
|
+
when 'x' # x - delete selected files
|
104
|
+
delete_selected_files
|
85
105
|
else
|
86
106
|
false # #{ConfigLoader.message('keybind.invalid_key')}
|
87
107
|
end
|
@@ -435,5 +455,132 @@ module Beniya
|
|
435
455
|
false
|
436
456
|
end
|
437
457
|
end
|
458
|
+
|
459
|
+
def toggle_selection
|
460
|
+
entry = current_entry
|
461
|
+
return false unless entry
|
462
|
+
|
463
|
+
if @selected_items.include?(entry[:name])
|
464
|
+
@selected_items.delete(entry[:name])
|
465
|
+
else
|
466
|
+
@selected_items << entry[:name]
|
467
|
+
end
|
468
|
+
true
|
469
|
+
end
|
470
|
+
|
471
|
+
def move_selected_to_base
|
472
|
+
return false if @selected_items.empty? || @base_directory.nil?
|
473
|
+
|
474
|
+
if show_confirmation_dialog("移動", @selected_items.length)
|
475
|
+
perform_file_operation(:move, @selected_items, @base_directory)
|
476
|
+
else
|
477
|
+
false
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
def copy_selected_to_base
|
482
|
+
return false if @selected_items.empty? || @base_directory.nil?
|
483
|
+
|
484
|
+
if show_confirmation_dialog("コピー", @selected_items.length)
|
485
|
+
perform_file_operation(:copy, @selected_items, @base_directory)
|
486
|
+
else
|
487
|
+
false
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
def show_confirmation_dialog(operation, count)
|
492
|
+
print "\n#{count}個のアイテムを#{operation}しますか? (y/n): "
|
493
|
+
response = STDIN.gets.chomp.downcase
|
494
|
+
response == 'y' || response == 'yes'
|
495
|
+
end
|
496
|
+
|
497
|
+
def perform_file_operation(operation, items, destination)
|
498
|
+
success_count = 0
|
499
|
+
current_path = @directory_listing&.current_path || Dir.pwd
|
500
|
+
|
501
|
+
items.each do |item_name|
|
502
|
+
source_path = File.join(current_path, item_name)
|
503
|
+
dest_path = File.join(destination, item_name)
|
504
|
+
|
505
|
+
begin
|
506
|
+
case operation
|
507
|
+
when :move
|
508
|
+
if File.exist?(dest_path)
|
509
|
+
puts "\n#{item_name} は既に移動先に存在します。スキップします。"
|
510
|
+
next
|
511
|
+
end
|
512
|
+
FileUtils.mv(source_path, dest_path)
|
513
|
+
when :copy
|
514
|
+
if File.exist?(dest_path)
|
515
|
+
puts "\n#{item_name} は既に移動先に存在します。スキップします。"
|
516
|
+
next
|
517
|
+
end
|
518
|
+
if File.directory?(source_path)
|
519
|
+
FileUtils.cp_r(source_path, dest_path)
|
520
|
+
else
|
521
|
+
FileUtils.cp(source_path, dest_path)
|
522
|
+
end
|
523
|
+
end
|
524
|
+
success_count += 1
|
525
|
+
rescue => e
|
526
|
+
puts "\n#{item_name} の#{operation == :move ? '移動' : 'コピー'}に失敗: #{e.message}"
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
# 操作完了後の処理
|
531
|
+
@selected_items.clear
|
532
|
+
@directory_listing.refresh if @directory_listing
|
533
|
+
|
534
|
+
puts "\n#{success_count}個のアイテムを#{operation == :move ? '移動' : 'コピー'}しました。"
|
535
|
+
print "何かキーを押してください..."
|
536
|
+
STDIN.getch
|
537
|
+
true
|
538
|
+
end
|
539
|
+
|
540
|
+
def delete_selected_files
|
541
|
+
return false if @selected_items.empty?
|
542
|
+
|
543
|
+
if show_delete_confirmation(@selected_items.length)
|
544
|
+
perform_delete_operation(@selected_items)
|
545
|
+
else
|
546
|
+
false
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
550
|
+
def show_delete_confirmation(count)
|
551
|
+
print "\n#{count}個のアイテムを削除しますか? (y/n): "
|
552
|
+
response = STDIN.gets.chomp.downcase
|
553
|
+
response == 'y' || response == 'yes'
|
554
|
+
end
|
555
|
+
|
556
|
+
def perform_delete_operation(items)
|
557
|
+
success_count = 0
|
558
|
+
current_path = @directory_listing&.current_path || Dir.pwd
|
559
|
+
|
560
|
+
items.each do |item_name|
|
561
|
+
item_path = File.join(current_path, item_name)
|
562
|
+
|
563
|
+
begin
|
564
|
+
if File.directory?(item_path)
|
565
|
+
FileUtils.rm_rf(item_path)
|
566
|
+
else
|
567
|
+
FileUtils.rm(item_path)
|
568
|
+
end
|
569
|
+
success_count += 1
|
570
|
+
puts "\n#{item_name} を削除しました。"
|
571
|
+
rescue => e
|
572
|
+
puts "\n#{item_name} の削除に失敗: #{e.message}"
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
# 削除完了後の処理
|
577
|
+
@selected_items.clear
|
578
|
+
@directory_listing.refresh if @directory_listing
|
579
|
+
|
580
|
+
puts "\n#{success_count}個のアイテムを削除しました。"
|
581
|
+
print "何かキーを押してください..."
|
582
|
+
STDIN.getch
|
583
|
+
true
|
584
|
+
end
|
438
585
|
end
|
439
|
-
end
|
586
|
+
end
|
data/lib/beniya/terminal_ui.rb
CHANGED
@@ -75,15 +75,16 @@ module Beniya
|
|
75
75
|
# move cursor to top of screen (don't clear)
|
76
76
|
print "\e[H"
|
77
77
|
|
78
|
-
# header
|
78
|
+
# header (2 lines)
|
79
79
|
draw_header
|
80
|
+
draw_base_directory_info
|
80
81
|
|
81
82
|
# main content (left: directory list, right: preview)
|
82
83
|
entries = get_display_entries
|
83
84
|
selected_entry = entries[@keybind_handler.current_index]
|
84
85
|
|
85
|
-
# calculate height with footer margin
|
86
|
-
content_height = @screen_height -
|
86
|
+
# calculate height with header (2 lines) and footer margin
|
87
|
+
content_height = @screen_height - 4 # ヘッダー(2行)とフッター分を除く
|
87
88
|
left_width = @screen_width / 2
|
88
89
|
right_width = @screen_width - left_width
|
89
90
|
|
@@ -125,13 +126,50 @@ module Beniya
|
|
125
126
|
puts "\e[7m#{header.ljust(@screen_width)}\e[0m" # reverse display
|
126
127
|
end
|
127
128
|
|
129
|
+
def draw_base_directory_info
|
130
|
+
# 強制的に表示 - デバッグ用に安全チェックを緩和
|
131
|
+
if @keybind_handler && @keybind_handler.instance_variable_get(:@base_directory)
|
132
|
+
base_dir = @keybind_handler.instance_variable_get(:@base_directory)
|
133
|
+
selected_count = @keybind_handler.selected_items.length
|
134
|
+
base_info = "📋 ベースディレクトリ: #{base_dir}"
|
135
|
+
|
136
|
+
# 選択されたアイテム数を表示
|
137
|
+
if selected_count > 0
|
138
|
+
base_info += " | 選択中: #{selected_count}個"
|
139
|
+
end
|
140
|
+
else
|
141
|
+
# keybind_handlerがない場合、またはbase_directoryが設定されていない場合
|
142
|
+
base_info = "📋 ベースディレクトリ: #{Dir.pwd}"
|
143
|
+
end
|
144
|
+
|
145
|
+
# 長すぎる場合は省略
|
146
|
+
if base_info.length > @screen_width - 2
|
147
|
+
if base_info.include?(" | 選択中:")
|
148
|
+
selected_part = base_info.split(" | 選択中:").last
|
149
|
+
available_length = @screen_width - 20 - " | 選択中:#{selected_part}".length
|
150
|
+
else
|
151
|
+
available_length = @screen_width - 20
|
152
|
+
end
|
153
|
+
|
154
|
+
if available_length > 10
|
155
|
+
# パスの最後の部分を表示
|
156
|
+
dir_part = base_info.split(": ").last.split(" | ").first
|
157
|
+
short_base_dir = "...#{dir_part[-available_length..-1]}"
|
158
|
+
base_info = base_info.gsub(dir_part, short_base_dir)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# 2行目に確実に表示
|
163
|
+
print "\e[2;1H\e[44m\e[37m#{base_info.ljust(@screen_width)}\e[0m"
|
164
|
+
end
|
165
|
+
|
128
166
|
def draw_directory_list(entries, width, height)
|
129
167
|
start_index = [@keybind_handler.current_index - height / 2, 0].max
|
130
168
|
[start_index + height - 1, entries.length - 1].min
|
131
169
|
|
132
170
|
(0...height).each do |i|
|
133
171
|
entry_index = start_index + i
|
134
|
-
line_num = i +
|
172
|
+
line_num = i + 3 # skip header (2 lines)
|
135
173
|
|
136
174
|
print "\e[#{line_num};1H" # set cursor position
|
137
175
|
|
@@ -155,16 +193,19 @@ module Beniya
|
|
155
193
|
# 左ペイン専用の安全な幅を計算(右ペインにはみ出さないよう)
|
156
194
|
safe_width = [width - 1, @screen_width / 2 - 1].min
|
157
195
|
|
196
|
+
# 選択マークの追加
|
197
|
+
selection_mark = @keybind_handler.is_selected?(entry[:name]) ? "✓ " : " "
|
198
|
+
|
158
199
|
# ファイル名(必要に応じて切り詰め)
|
159
200
|
name = entry[:name]
|
160
|
-
max_name_length = safe_width -
|
201
|
+
max_name_length = safe_width - 12 # アイコン、選択マーク、サイズ情報分を除く
|
161
202
|
name = name[0...max_name_length - 3] + '...' if max_name_length > 0 && name.length > max_name_length
|
162
203
|
|
163
204
|
# サイズ情報
|
164
205
|
size_info = format_size(entry[:size])
|
165
206
|
|
166
207
|
# 行の内容を構築(安全な幅内で)
|
167
|
-
content_without_size = "#{icon} #{name}"
|
208
|
+
content_without_size = "#{selection_mark}#{icon} #{name}"
|
168
209
|
available_for_content = safe_width - size_info.length
|
169
210
|
|
170
211
|
line_content = if available_for_content > 0
|
@@ -180,7 +221,12 @@ module Beniya
|
|
180
221
|
selected_color = ColorHelper.color_to_selected_ansi(ConfigLoader.colors[:selected])
|
181
222
|
print "#{selected_color}#{line_content}#{ColorHelper.reset}"
|
182
223
|
else
|
183
|
-
|
224
|
+
# 選択されたアイテムは異なる色で表示
|
225
|
+
if @keybind_handler.is_selected?(entry[:name])
|
226
|
+
print "\e[42m\e[30m#{line_content}\e[0m" # 緑背景、黒文字
|
227
|
+
else
|
228
|
+
print "#{color}#{line_content}#{ColorHelper.reset}"
|
229
|
+
end
|
184
230
|
end
|
185
231
|
end
|
186
232
|
|
@@ -226,7 +272,7 @@ module Beniya
|
|
226
272
|
|
227
273
|
def draw_file_preview(selected_entry, width, height, left_offset)
|
228
274
|
(0...height).each do |i|
|
229
|
-
line_num = i + 2
|
275
|
+
line_num = i + 3 # skip header (2 lines)
|
230
276
|
# カーソル位置を左パネルの右端に設定
|
231
277
|
cursor_position = left_offset + 1
|
232
278
|
|
data/lib/beniya/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beniya
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- masisz
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-09-06 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: io-console
|