rufio 0.10.0 → 0.20.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_v0.20.0.md +166 -0
- data/README.md +66 -14
- data/info/welcome.txt +21 -0
- data/lib/rufio/bookmark.rb +19 -3
- data/lib/rufio/bookmark_manager.rb +111 -13
- data/lib/rufio/config_loader.rb +15 -2
- data/lib/rufio/file_operations.rb +66 -0
- data/lib/rufio/file_preview.rb +1 -1
- data/lib/rufio/info_notice.rb +100 -0
- data/lib/rufio/keybind_handler.rb +434 -24
- data/lib/rufio/project_command.rb +147 -0
- data/lib/rufio/project_log.rb +68 -0
- data/lib/rufio/project_mode.rb +58 -0
- data/lib/rufio/terminal_ui.rb +552 -4
- data/lib/rufio/version.rb +1 -1
- data/lib/rufio.rb +5 -0
- metadata +7 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0b83ee6642477115c1a4590c5e0dd5194277eb5cc893e66fa8f59467a8768bec
|
|
4
|
+
data.tar.gz: 674b4c809669a17fcfc94a068e13a1524977cda466b610a75cd94f85995cbfbb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8e72520a40a2315b963d1c9a04f0071f35732696bbbf56d83a8d990025fb334fb6c834ec73bbe97b18fe27122c878771fc9710c33eda3293aa0dd0478946cd1e
|
|
7
|
+
data.tar.gz: 26089800c3bb70e4b63d698ffdb8c87c5f4827229769bddef6e18c76cfa78984e9dbbacdf7bf14de2c201396c390b714b89ec74a170fda157ea5a7297c7b0293
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Changelog v0.20.0 - Project Mode Enhancement & UI Unification
|
|
2
|
+
|
|
3
|
+
## [0.20.0] - 2025-12-28
|
|
4
|
+
|
|
5
|
+
### 🎨 Enhanced - Project Mode UI Overhaul
|
|
6
|
+
|
|
7
|
+
Complete UI unification between normal mode and project mode, with improved bookmark management and script execution capabilities.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
#### Script Directory Support
|
|
12
|
+
- **Auto-created scripts directory**: `~/.config/rufio/scripts`
|
|
13
|
+
- Automatically created on first run
|
|
14
|
+
- Configurable via `config.rb`
|
|
15
|
+
- Default location: `~/.config/rufio/scripts`
|
|
16
|
+
- **Ruby script execution**: Execute custom Ruby scripts from project mode
|
|
17
|
+
- List all `.rb` files in scripts directory
|
|
18
|
+
- Execute scripts with `:` command mode
|
|
19
|
+
- Sample `hello.rb` script included on initialization
|
|
20
|
+
- **`ProjectCommand#list_scripts`**: Returns list of available Ruby scripts
|
|
21
|
+
- **`ProjectCommand#execute_script`**: Executes selected script in project context
|
|
22
|
+
|
|
23
|
+
#### Bookmark Rename Feature
|
|
24
|
+
- **`r` key in project mode**: Rename bookmark with dialog
|
|
25
|
+
- **`Bookmark#rename(old_name, new_name)`**: Rename bookmark method
|
|
26
|
+
- Automatic name trimming (leading/trailing spaces)
|
|
27
|
+
- Duplicate name validation
|
|
28
|
+
- Same name check
|
|
29
|
+
- **Rename dialog**: Yellow-bordered input dialog
|
|
30
|
+
- Shows old name in title
|
|
31
|
+
- Input validation
|
|
32
|
+
- No result message (cleaner UX)
|
|
33
|
+
|
|
34
|
+
#### File Operations Enhancement
|
|
35
|
+
- **`r` key in normal mode**: Rename file/directory
|
|
36
|
+
- **`d` key in normal mode**: Delete file/directory with confirmation
|
|
37
|
+
- **`a` key**: Create file with dialog input (green border)
|
|
38
|
+
- **`A` key**: Create directory with dialog input (blue border)
|
|
39
|
+
- **`FileOperations#rename`**: Rename files and directories
|
|
40
|
+
- Path separator validation
|
|
41
|
+
- Empty name check
|
|
42
|
+
- Existence validation
|
|
43
|
+
- Conflict detection
|
|
44
|
+
|
|
45
|
+
#### Bookmark Management
|
|
46
|
+
- **`b` key in normal mode**: Direct bookmark addition
|
|
47
|
+
- Shows directory name in title
|
|
48
|
+
- Input dialog for bookmark name
|
|
49
|
+
- Duplicate path detection
|
|
50
|
+
- Green dialog for create operation
|
|
51
|
+
- **`r` key in project mode**: Rename bookmark at cursor
|
|
52
|
+
- **`d` key in project mode**: Delete bookmark at cursor
|
|
53
|
+
- **Unified operation dialogs**:
|
|
54
|
+
- Green: Create operations (file, directory, bookmark)
|
|
55
|
+
- Blue: Directory creation
|
|
56
|
+
- Yellow: Rename operations
|
|
57
|
+
- Red: Delete operations
|
|
58
|
+
|
|
59
|
+
### Changed
|
|
60
|
+
|
|
61
|
+
#### UI/UX Unification
|
|
62
|
+
- **Project mode selection UI** matches normal mode exactly
|
|
63
|
+
- Selection mark: `✓ ` (checkmark) instead of `*`
|
|
64
|
+
- Selected bookmark: Green background, black text (`\e[42m\e[30m`)
|
|
65
|
+
- Cursor position: Highlighted with selected color from config
|
|
66
|
+
- **Separator display**: Added `│` separator between left and right panes in project mode
|
|
67
|
+
- **Footer display**: Unified with normal mode
|
|
68
|
+
- Simple reverse video style (`\e[7m`)
|
|
69
|
+
- Compact help text: `SPACE:select l:logs ::cmd r:rename d:delete ESC:exit j/k:move`
|
|
70
|
+
- Log mode footer: `ESC:exit log j/k:move`
|
|
71
|
+
- **Right pane layout**: Matches normal mode with separator and content spacing
|
|
72
|
+
|
|
73
|
+
#### Bookmark Operations
|
|
74
|
+
- **Removed bookmark menu**: `b` key now directly adds bookmark
|
|
75
|
+
- **Cursor-based operations**: Rename/delete operate on cursor position
|
|
76
|
+
- No selection dialog needed
|
|
77
|
+
- Faster workflow (one less step)
|
|
78
|
+
- **Single selection model**: Simplified from multiple selection
|
|
79
|
+
- `SPACE` key selects bookmark as project
|
|
80
|
+
- Selected bookmark shown with checkmark
|
|
81
|
+
- Improved command mode compatibility
|
|
82
|
+
|
|
83
|
+
#### Dialog Consistency
|
|
84
|
+
- **All operations use dialogs**: No status line messages
|
|
85
|
+
- **Color coding by operation type**:
|
|
86
|
+
- Create: Green border
|
|
87
|
+
- Directory: Blue border
|
|
88
|
+
- Rename: Yellow border
|
|
89
|
+
- Delete: Red border
|
|
90
|
+
- **No result messages**: Cleaner UX after operations complete
|
|
91
|
+
- **Input dialogs**: Consistent `show_input_dialog` interface
|
|
92
|
+
|
|
93
|
+
### Technical Changes
|
|
94
|
+
|
|
95
|
+
#### Code Organization
|
|
96
|
+
- **`KeybindHandler#is_bookmark_selected?`**: Removed (simplified selection model)
|
|
97
|
+
- **`KeybindHandler#toggle_bookmark_selection`**: Replaced with `select_bookmark_in_project_mode`
|
|
98
|
+
- **`KeybindHandler#select_bookmark_in_project_mode`**: Single selection for project mode
|
|
99
|
+
- **`KeybindHandler#add_bookmark`**: Direct bookmark addition without menu
|
|
100
|
+
- **`KeybindHandler#rename_bookmark_in_project_mode`**: Cursor-based rename
|
|
101
|
+
- **`KeybindHandler#delete_bookmark_in_project_mode`**: Cursor-based delete
|
|
102
|
+
- **`TerminalUI#draw_bookmark_list`**: Updated to match normal mode UI
|
|
103
|
+
- **`TerminalUI#draw_bookmark_detail`**: Added separator display
|
|
104
|
+
- **`TerminalUI#draw_log_preview`**: Added separator display
|
|
105
|
+
- **`ProjectMode#clear_selection`**: Clear selected project
|
|
106
|
+
|
|
107
|
+
#### Configuration
|
|
108
|
+
- **`ConfigLoader.scripts_dir`**: New configuration option
|
|
109
|
+
- **`ConfigLoader.default_scripts_dir`**: Default scripts directory path
|
|
110
|
+
|
|
111
|
+
### Removed
|
|
112
|
+
|
|
113
|
+
- **Bookmark menu**: Removed multi-option bookmark menu
|
|
114
|
+
- `b` → `[A]dd` / `[L]ist` / `[R]emove` menu replaced with direct add
|
|
115
|
+
- Individual operations now mapped to dedicated keys
|
|
116
|
+
- **Multiple selection in project mode**: Simplified to single selection
|
|
117
|
+
- Removed `SelectionManager` integration for bookmarks
|
|
118
|
+
- Better command mode compatibility
|
|
119
|
+
- **Result message dialogs**: Removed after rename/delete operations
|
|
120
|
+
- Cleaner user experience
|
|
121
|
+
- Operations complete silently on success
|
|
122
|
+
|
|
123
|
+
### Key Bindings Summary
|
|
124
|
+
|
|
125
|
+
#### Normal Mode
|
|
126
|
+
- `b`: Add bookmark (direct, no menu)
|
|
127
|
+
- `r`: Rename file/directory
|
|
128
|
+
- `d`: Delete file/directory (with confirmation)
|
|
129
|
+
- `a`: Create file
|
|
130
|
+
- `A`: Create directory
|
|
131
|
+
|
|
132
|
+
#### Project Mode
|
|
133
|
+
- `SPACE`: Select bookmark as project
|
|
134
|
+
- `r`: Rename bookmark at cursor
|
|
135
|
+
- `d`: Delete bookmark at cursor
|
|
136
|
+
- `l`: View logs
|
|
137
|
+
- `:`: Command mode
|
|
138
|
+
- `ESC`: Exit project mode
|
|
139
|
+
|
|
140
|
+
### UI Color Scheme
|
|
141
|
+
|
|
142
|
+
- **Selection mark**: `✓ ` (green background, black text)
|
|
143
|
+
- **Cursor highlight**: Config-defined selected color
|
|
144
|
+
- **Create dialogs**: Green border (`\e[32m`)
|
|
145
|
+
- **Directory dialogs**: Blue border (`\e[34m`)
|
|
146
|
+
- **Rename dialogs**: Yellow border (`\e[33m`)
|
|
147
|
+
- **Delete dialogs**: Red border (`\e[31m`)
|
|
148
|
+
- **Footer**: Reverse video (`\e[7m`)
|
|
149
|
+
|
|
150
|
+
### Bug Fixes
|
|
151
|
+
|
|
152
|
+
- **Fixed private method error**: `is_bookmark_selected?` visibility issue resolved
|
|
153
|
+
- **Fixed command mode in project mode**: Single selection model prevents conflicts
|
|
154
|
+
- **Fixed separator display**: Added missing `│` separator in project mode
|
|
155
|
+
- **Fixed footer positioning**: Unified footer line calculation
|
|
156
|
+
|
|
157
|
+
### Migration Notes
|
|
158
|
+
|
|
159
|
+
- **Breaking change**: `b` key no longer shows menu, directly adds bookmark
|
|
160
|
+
- **Behavior change**: Bookmark operations are now cursor-based in project mode
|
|
161
|
+
- **UI change**: Selection marks changed from `*` to `✓ `
|
|
162
|
+
- Scripts directory will be auto-created at `~/.config/rufio/scripts` on first use
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
**Full Changelog**: [v0.19.0...v0.20.0](https://github.com/masisz/rufio/compare/v0.19.0...v0.20.0)
|
data/README.md
CHANGED
|
@@ -76,9 +76,11 @@ rufio --help # ヘルプメッセージを表示
|
|
|
76
76
|
| ---- | -------------------------------------------------- |
|
|
77
77
|
| `o` | 選択中のファイルを外部エディタで開く |
|
|
78
78
|
| `e` | 現在のディレクトリをファイルエクスプローラーで開く |
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
79
|
+
| `R` | ディレクトリ内容を更新 |
|
|
80
|
+
| `r` | ファイル・ディレクトリ名をリネーム |
|
|
81
|
+
| `d` | ファイル・ディレクトリを削除(確認ダイアログ付き) |
|
|
82
|
+
| `a` | 新しいファイルを作成(ダイアログ入力) |
|
|
83
|
+
| `A` | 新しいディレクトリを作成(ダイアログ入力) |
|
|
82
84
|
|
|
83
85
|
#### ファイル選択・操作
|
|
84
86
|
|
|
@@ -108,10 +110,11 @@ rufio --help # ヘルプメッセージを表示
|
|
|
108
110
|
|
|
109
111
|
#### ブックマーク機能
|
|
110
112
|
|
|
111
|
-
| キー | 機能
|
|
112
|
-
| --------- |
|
|
113
|
-
| `b` |
|
|
114
|
-
| `
|
|
113
|
+
| キー | 機能 |
|
|
114
|
+
| --------- | ------------------------------------ |
|
|
115
|
+
| `b` | 現在のディレクトリをブックマークに追加 |
|
|
116
|
+
| `p` | プロジェクトモードに入る |
|
|
117
|
+
| `1`-`9` | 対応する番号のブックマークに移動 |
|
|
115
118
|
|
|
116
119
|
#### zoxide連携機能
|
|
117
120
|
|
|
@@ -223,16 +226,30 @@ rufio起動時のディレクトリが**ベースディレクトリ**として
|
|
|
223
226
|
|
|
224
227
|
### ブックマーク機能の詳細
|
|
225
228
|
|
|
226
|
-
#### ブックマーク操作
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
229
|
+
#### ブックマーク操作
|
|
230
|
+
|
|
231
|
+
**通常モード:**
|
|
232
|
+
- **`b`キー**: 現在のディレクトリをブックマークに追加
|
|
233
|
+
- ディレクトリ名がタイトルに表示される
|
|
234
|
+
- ブックマーク名を入力して追加
|
|
235
|
+
- 重複パスは自動検出
|
|
236
|
+
- 緑色のダイアログで表示(作成操作)
|
|
237
|
+
|
|
238
|
+
**プロジェクトモード (`p`キー):**
|
|
239
|
+
- **`SPACE`キー**: ブックマークをプロジェクトとして選択
|
|
240
|
+
- 選択されたブックマークは✓マークと緑背景で表示
|
|
241
|
+
- **`r`キー**: カーソル位置のブックマークをリネーム
|
|
242
|
+
- 黄色のダイアログで入力
|
|
243
|
+
- 前後のスペースは自動削除
|
|
244
|
+
- **`d`キー**: カーソル位置のブックマークを削除
|
|
245
|
+
- 赤色の確認ダイアログ表示
|
|
246
|
+
- **`l`キー**: ログモードに入る
|
|
247
|
+
- **`:`キー**: コマンドモード起動
|
|
248
|
+
- **`ESC`キー**: プロジェクトモードを終了
|
|
232
249
|
|
|
233
250
|
#### 高速ナビゲーション (`1`-`9`)
|
|
234
251
|
|
|
235
|
-
-
|
|
252
|
+
- 数字キーでブックマークに直接ジャンプ
|
|
236
253
|
- 最大9個のブックマークをサポート
|
|
237
254
|
- ブックマーク情報は画面上部に表示
|
|
238
255
|
|
|
@@ -240,8 +257,43 @@ rufio起動時のディレクトリが**ベースディレクトリ**として
|
|
|
240
257
|
|
|
241
258
|
- ブックマーク情報は `~/.config/rufio/bookmarks.json` に自動保存
|
|
242
259
|
- rufio再起動後もブックマーク情報が保持される
|
|
260
|
+
- 名前の前後のスペースは自動削除されて保存される
|
|
243
261
|
- JSONファイルを直接編集することも可能
|
|
244
262
|
|
|
263
|
+
### プロジェクトモード機能の詳細
|
|
264
|
+
|
|
265
|
+
#### プロジェクトモード (`p`)
|
|
266
|
+
|
|
267
|
+
プロジェクトモードでは、ブックマークしたディレクトリをプロジェクトとして管理できます。
|
|
268
|
+
|
|
269
|
+
#### スクリプト実行機能
|
|
270
|
+
|
|
271
|
+
- **スクリプトディレクトリ**: `~/.config/rufio/scripts`
|
|
272
|
+
- 初回起動時に自動作成
|
|
273
|
+
- `config.rb`でカスタマイズ可能
|
|
274
|
+
- サンプルスクリプト `hello.rb` が含まれる
|
|
275
|
+
- **スクリプト実行**: `:`キーでコマンドモード起動
|
|
276
|
+
- `.rb`ファイルを一覧表示
|
|
277
|
+
- 選択したスクリプトを実行
|
|
278
|
+
- プロジェクトコンテキストで実行
|
|
279
|
+
|
|
280
|
+
#### UI表示
|
|
281
|
+
|
|
282
|
+
プロジェクトモードのUIは通常モードと統一されています:
|
|
283
|
+
|
|
284
|
+
- **選択マーク**: ✓(チェックマーク)で選択を表示
|
|
285
|
+
- **選択済みブックマーク**: 緑背景、黒文字で表示
|
|
286
|
+
- **カーソル位置**: 設定ファイルの選択色でハイライト
|
|
287
|
+
- **セパレータ**: 左右画面の間に`│`を表示
|
|
288
|
+
- **フッター**: 反転表示でキーバインドを表示
|
|
289
|
+
|
|
290
|
+
#### 操作色の統一
|
|
291
|
+
|
|
292
|
+
- **緑色ダイアログ**: 作成操作(ファイル、ディレクトリ、ブックマーク)
|
|
293
|
+
- **青色ダイアログ**: ディレクトリ作成
|
|
294
|
+
- **黄色ダイアログ**: リネーム操作
|
|
295
|
+
- **赤色ダイアログ**: 削除操作
|
|
296
|
+
|
|
245
297
|
### zoxide連携機能の詳細
|
|
246
298
|
|
|
247
299
|
#### zoxide履歴移動 (`z`)
|
data/info/welcome.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Welcome to rufio!
|
|
2
|
+
|
|
3
|
+
Thank you for using rufio - a terminal-based file manager.
|
|
4
|
+
|
|
5
|
+
Key Features:
|
|
6
|
+
- Vim-like keybindings (j/k/h/l for navigation)
|
|
7
|
+
- Real-time filtering (f key)
|
|
8
|
+
- Advanced search with fzf and rga
|
|
9
|
+
- Bookmark support (b key)
|
|
10
|
+
- Plugin system for extensibility
|
|
11
|
+
|
|
12
|
+
Quick Start:
|
|
13
|
+
j/k - Move up/down
|
|
14
|
+
h/l - Parent dir / Enter dir
|
|
15
|
+
f - Filter files
|
|
16
|
+
b - Bookmarks
|
|
17
|
+
: - Command mode
|
|
18
|
+
q - Quit
|
|
19
|
+
|
|
20
|
+
For more information, visit:
|
|
21
|
+
https://github.com/masisz/rufio
|
data/lib/rufio/bookmark.rb
CHANGED
|
@@ -15,12 +15,14 @@ module Rufio
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def add(path, name)
|
|
18
|
+
trimmed_name = name.strip
|
|
19
|
+
return false if trimmed_name.empty?
|
|
18
20
|
return false if @bookmarks.length >= MAX_BOOKMARKS
|
|
19
|
-
return false if exists_by_name?(
|
|
21
|
+
return false if exists_by_name?(trimmed_name)
|
|
20
22
|
return false if exists_by_path?(path)
|
|
21
23
|
return false unless Dir.exist?(path)
|
|
22
24
|
|
|
23
|
-
@bookmarks << { path: File.expand_path(path), name:
|
|
25
|
+
@bookmarks << { path: File.expand_path(path), name: trimmed_name }
|
|
24
26
|
save
|
|
25
27
|
true
|
|
26
28
|
end
|
|
@@ -28,7 +30,7 @@ module Rufio
|
|
|
28
30
|
def remove(name)
|
|
29
31
|
initial_length = @bookmarks.length
|
|
30
32
|
@bookmarks.reject! { |bookmark| bookmark[:name] == name }
|
|
31
|
-
|
|
33
|
+
|
|
32
34
|
if @bookmarks.length < initial_length
|
|
33
35
|
save
|
|
34
36
|
true
|
|
@@ -37,6 +39,20 @@ module Rufio
|
|
|
37
39
|
end
|
|
38
40
|
end
|
|
39
41
|
|
|
42
|
+
def rename(old_name, new_name)
|
|
43
|
+
trimmed_new_name = new_name.strip
|
|
44
|
+
return false if trimmed_new_name.empty?
|
|
45
|
+
return false if old_name == trimmed_new_name
|
|
46
|
+
return false if exists_by_name?(trimmed_new_name)
|
|
47
|
+
|
|
48
|
+
bookmark = @bookmarks.find { |b| b[:name] == old_name }
|
|
49
|
+
return false unless bookmark
|
|
50
|
+
|
|
51
|
+
bookmark[:name] = trimmed_new_name
|
|
52
|
+
save
|
|
53
|
+
true
|
|
54
|
+
end
|
|
55
|
+
|
|
40
56
|
def get_path(name)
|
|
41
57
|
bookmark = @bookmarks.find { |b| b[:name] == name }
|
|
42
58
|
bookmark&.[](:path)
|
|
@@ -22,7 +22,8 @@ module Rufio
|
|
|
22
22
|
'',
|
|
23
23
|
'[A]dd current directory to bookmarks',
|
|
24
24
|
'[L]ist bookmarks',
|
|
25
|
-
'[R]
|
|
25
|
+
'[R]ename bookmark',
|
|
26
|
+
'[D]elete bookmark',
|
|
26
27
|
'',
|
|
27
28
|
'Press 1-9 to go to bookmark directly',
|
|
28
29
|
'',
|
|
@@ -51,6 +52,9 @@ module Rufio
|
|
|
51
52
|
@dialog_renderer.clear_area(x, y, dialog_width, dialog_height)
|
|
52
53
|
return { action: :list }
|
|
53
54
|
when 'r'
|
|
55
|
+
@dialog_renderer.clear_area(x, y, dialog_width, dialog_height)
|
|
56
|
+
return { action: :rename }
|
|
57
|
+
when 'd'
|
|
54
58
|
@dialog_renderer.clear_area(x, y, dialog_width, dialog_height)
|
|
55
59
|
return { action: :remove }
|
|
56
60
|
when '1', '2', '3', '4', '5', '6', '7', '8', '9'
|
|
@@ -91,6 +95,81 @@ module Rufio
|
|
|
91
95
|
end
|
|
92
96
|
end
|
|
93
97
|
|
|
98
|
+
# Rename a bookmark interactively
|
|
99
|
+
# @return [Boolean] Success status
|
|
100
|
+
def rename_interactive
|
|
101
|
+
bookmarks = @bookmark.list
|
|
102
|
+
|
|
103
|
+
if bookmarks.empty?
|
|
104
|
+
show_result_dialog('No Bookmarks', 'No bookmarks found', :error)
|
|
105
|
+
return false
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
return false unless @dialog_renderer
|
|
109
|
+
|
|
110
|
+
# Build content lines for bookmark selection
|
|
111
|
+
content_lines = ['', 'Select bookmark to rename:', '']
|
|
112
|
+
bookmarks.each_with_index do |bookmark, index|
|
|
113
|
+
# Truncate path if too long
|
|
114
|
+
display_path = bookmark[:path]
|
|
115
|
+
if display_path.start_with?(Dir.home)
|
|
116
|
+
display_path = display_path.sub(Dir.home, '~')
|
|
117
|
+
end
|
|
118
|
+
if display_path.length > 35
|
|
119
|
+
display_path = "...#{display_path[-32..]}"
|
|
120
|
+
end
|
|
121
|
+
content_lines << " #{index + 1}. #{bookmark[:name]}"
|
|
122
|
+
content_lines << " #{display_path}"
|
|
123
|
+
end
|
|
124
|
+
content_lines << ''
|
|
125
|
+
content_lines << 'Press 1-9 to select, ESC to cancel'
|
|
126
|
+
|
|
127
|
+
title = 'Rename Bookmark'
|
|
128
|
+
width = 60
|
|
129
|
+
height = [content_lines.length + 4, 20].min
|
|
130
|
+
x, y = @dialog_renderer.calculate_center(width, height)
|
|
131
|
+
|
|
132
|
+
@dialog_renderer.draw_floating_window(x, y, width, height, title, content_lines, {
|
|
133
|
+
border_color: "\e[33m", # Yellow
|
|
134
|
+
title_color: "\e[1;33m", # Bold yellow
|
|
135
|
+
content_color: "\e[37m" # White
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
# Wait for selection
|
|
139
|
+
selected_number = nil
|
|
140
|
+
loop do
|
|
141
|
+
input = STDIN.getch.downcase
|
|
142
|
+
|
|
143
|
+
if input >= '1' && input <= '9'
|
|
144
|
+
number = input.to_i
|
|
145
|
+
if number > 0 && number <= bookmarks.length
|
|
146
|
+
selected_number = number
|
|
147
|
+
break
|
|
148
|
+
end
|
|
149
|
+
elsif input == "\e" # ESC
|
|
150
|
+
@dialog_renderer.clear_area(x, y, width, height)
|
|
151
|
+
return false
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
@dialog_renderer.clear_area(x, y, width, height)
|
|
156
|
+
|
|
157
|
+
# Get new name
|
|
158
|
+
bookmark_to_rename = bookmarks[selected_number - 1]
|
|
159
|
+
old_name = bookmark_to_rename[:name]
|
|
160
|
+
|
|
161
|
+
new_name = @dialog_renderer.show_input_dialog("Rename: #{old_name}", "Enter new name:", {
|
|
162
|
+
border_color: "\e[33m", # Yellow
|
|
163
|
+
title_color: "\e[1;33m", # Bold yellow
|
|
164
|
+
content_color: "\e[37m" # White
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
return false if new_name.nil? || new_name.empty?
|
|
168
|
+
|
|
169
|
+
# Rename bookmark
|
|
170
|
+
@bookmark.rename(old_name, new_name)
|
|
171
|
+
end
|
|
172
|
+
|
|
94
173
|
# Remove a bookmark interactively
|
|
95
174
|
# @return [Boolean] Success status
|
|
96
175
|
def remove_interactive
|
|
@@ -104,7 +183,7 @@ module Rufio
|
|
|
104
183
|
return false unless @dialog_renderer
|
|
105
184
|
|
|
106
185
|
# Build content lines for bookmark selection
|
|
107
|
-
content_lines = ['', 'Select bookmark to
|
|
186
|
+
content_lines = ['', 'Select bookmark to delete:', '']
|
|
108
187
|
bookmarks.each_with_index do |bookmark, index|
|
|
109
188
|
# Truncate path if too long
|
|
110
189
|
display_path = bookmark[:path]
|
|
@@ -120,7 +199,7 @@ module Rufio
|
|
|
120
199
|
content_lines << ''
|
|
121
200
|
content_lines << 'Press 1-9 to select, ESC to cancel'
|
|
122
201
|
|
|
123
|
-
title = '
|
|
202
|
+
title = 'Delete Bookmark'
|
|
124
203
|
width = 60
|
|
125
204
|
height = [content_lines.length + 4, 20].min
|
|
126
205
|
x, y = @dialog_renderer.calculate_center(width, height)
|
|
@@ -153,13 +232,7 @@ module Rufio
|
|
|
153
232
|
# Confirm deletion
|
|
154
233
|
bookmark_to_remove = bookmarks[selected_number - 1]
|
|
155
234
|
if show_remove_confirmation(bookmark_to_remove[:name])
|
|
156
|
-
|
|
157
|
-
show_result_dialog('Bookmark Removed', "Removed: #{bookmark_to_remove[:name]}", :success)
|
|
158
|
-
true
|
|
159
|
-
else
|
|
160
|
-
show_result_dialog('Remove Failed', 'Failed to remove bookmark', :error)
|
|
161
|
-
false
|
|
162
|
-
end
|
|
235
|
+
@bookmark.remove(bookmark_to_remove[:name])
|
|
163
236
|
else
|
|
164
237
|
false
|
|
165
238
|
end
|
|
@@ -262,6 +335,31 @@ module Rufio
|
|
|
262
335
|
@bookmark.remove(name)
|
|
263
336
|
end
|
|
264
337
|
|
|
338
|
+
# Get left pane display data for bookmarks
|
|
339
|
+
# @return [Array<String>] Formatted bookmark list
|
|
340
|
+
def get_left_pane_data
|
|
341
|
+
bookmarks = @bookmark.list
|
|
342
|
+
bookmarks.map.with_index(1) do |bookmark, index|
|
|
343
|
+
"#{index}. #{bookmark[:name]}"
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# Get right pane display data for a selected bookmark
|
|
348
|
+
# @param number [Integer] Bookmark number (1-based)
|
|
349
|
+
# @return [String] Bookmark details
|
|
350
|
+
def get_right_pane_data(number)
|
|
351
|
+
bookmark = @bookmark.find_by_number(number)
|
|
352
|
+
return '' unless bookmark
|
|
353
|
+
|
|
354
|
+
"Name: #{bookmark[:name]}\nPath: #{bookmark[:path]}"
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# Get bookmark count
|
|
358
|
+
# @return [Integer] Number of bookmarks
|
|
359
|
+
def count
|
|
360
|
+
@bookmark.list.length
|
|
361
|
+
end
|
|
362
|
+
|
|
265
363
|
private
|
|
266
364
|
|
|
267
365
|
# Show result dialog with success or error styling
|
|
@@ -309,14 +407,14 @@ module Rufio
|
|
|
309
407
|
|
|
310
408
|
content_lines = [
|
|
311
409
|
'',
|
|
312
|
-
"
|
|
410
|
+
"Delete bookmark '#{bookmark_name}'?",
|
|
313
411
|
'',
|
|
314
|
-
' [Y]es -
|
|
412
|
+
' [Y]es - Delete',
|
|
315
413
|
' [N]o - Cancel',
|
|
316
414
|
''
|
|
317
415
|
]
|
|
318
416
|
|
|
319
|
-
title = 'Confirm
|
|
417
|
+
title = 'Confirm Delete'
|
|
320
418
|
width = 50
|
|
321
419
|
height = content_lines.length + 4
|
|
322
420
|
x, y = @dialog_renderer.calculate_center(width, height)
|
data/lib/rufio/config_loader.rb
CHANGED
|
@@ -48,6 +48,14 @@ module Rufio
|
|
|
48
48
|
Config.message(key, **interpolations)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
|
+
def scripts_dir
|
|
52
|
+
load_config[:scripts_dir] || default_scripts_dir
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def default_scripts_dir
|
|
56
|
+
File.expand_path('~/.config/rufio/scripts')
|
|
57
|
+
end
|
|
58
|
+
|
|
51
59
|
private
|
|
52
60
|
|
|
53
61
|
def load_config_file
|
|
@@ -58,14 +66,19 @@ module Rufio
|
|
|
58
66
|
colors: Object.const_get(:COLORS),
|
|
59
67
|
keybinds: Object.const_get(:KEYBINDS)
|
|
60
68
|
}
|
|
61
|
-
|
|
69
|
+
|
|
62
70
|
# Load language setting if defined
|
|
63
71
|
if Object.const_defined?(:LANGUAGE)
|
|
64
72
|
language = Object.const_get(:LANGUAGE)
|
|
65
73
|
config[:language] = language
|
|
66
74
|
Config.current_language = language if Config.available_languages.include?(language.to_s)
|
|
67
75
|
end
|
|
68
|
-
|
|
76
|
+
|
|
77
|
+
# Load scripts directory if defined
|
|
78
|
+
if Object.const_defined?(:SCRIPTS_DIR)
|
|
79
|
+
config[:scripts_dir] = Object.const_get(:SCRIPTS_DIR)
|
|
80
|
+
end
|
|
81
|
+
|
|
69
82
|
config
|
|
70
83
|
rescue StandardError => e
|
|
71
84
|
warn "Failed to load config file: #{e.message}"
|
|
@@ -73,6 +73,72 @@ module Rufio
|
|
|
73
73
|
)
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
+
# Rename a file or directory
|
|
77
|
+
# @param directory [String] Directory path
|
|
78
|
+
# @param old_name [String] Current name
|
|
79
|
+
# @param new_name [String] New name
|
|
80
|
+
# @return [OperationResult]
|
|
81
|
+
def rename(directory, old_name, new_name)
|
|
82
|
+
# Validate new_name
|
|
83
|
+
if new_name.include?('/') || new_name.include?('\\')
|
|
84
|
+
return OperationResult.new(
|
|
85
|
+
success: false,
|
|
86
|
+
message: 'Invalid name: cannot contain path separators',
|
|
87
|
+
count: 0,
|
|
88
|
+
errors: []
|
|
89
|
+
)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
if new_name.strip.empty?
|
|
93
|
+
return OperationResult.new(
|
|
94
|
+
success: false,
|
|
95
|
+
message: 'Invalid name: cannot be empty',
|
|
96
|
+
count: 0,
|
|
97
|
+
errors: []
|
|
98
|
+
)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
old_path = File.join(directory, old_name)
|
|
102
|
+
new_path = File.join(directory, new_name)
|
|
103
|
+
|
|
104
|
+
# Check if old file exists
|
|
105
|
+
unless File.exist?(old_path)
|
|
106
|
+
return OperationResult.new(
|
|
107
|
+
success: false,
|
|
108
|
+
message: 'File not found',
|
|
109
|
+
count: 0,
|
|
110
|
+
errors: []
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Check if new name already exists
|
|
115
|
+
if File.exist?(new_path)
|
|
116
|
+
return OperationResult.new(
|
|
117
|
+
success: false,
|
|
118
|
+
message: 'File already exists with that name',
|
|
119
|
+
count: 0,
|
|
120
|
+
errors: []
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
begin
|
|
125
|
+
FileUtils.mv(old_path, new_path)
|
|
126
|
+
OperationResult.new(
|
|
127
|
+
success: true,
|
|
128
|
+
message: "Renamed: #{old_name} → #{new_name}",
|
|
129
|
+
count: 1,
|
|
130
|
+
errors: []
|
|
131
|
+
)
|
|
132
|
+
rescue StandardError => e
|
|
133
|
+
OperationResult.new(
|
|
134
|
+
success: false,
|
|
135
|
+
message: "Rename error: #{e.message}",
|
|
136
|
+
count: 0,
|
|
137
|
+
errors: [e.message]
|
|
138
|
+
)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
76
142
|
# Create a new file
|
|
77
143
|
# @param directory [String] Directory path
|
|
78
144
|
# @param filename [String] File name
|
data/lib/rufio/file_preview.rb
CHANGED