rufio 1.1.0 → 1.4.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 +50 -0
- data/README.md +26 -297
- data/README_ja.md +24 -261
- data/Rakefile +14 -1
- data/bin/rufio +31 -2
- data/docs/fast_zip_design_ja.md +167 -0
- data/docs/guide.md +410 -0
- data/docs/guide_ja.md +410 -0
- data/info/help.md +54 -17
- data/info/keybindings.md +50 -22
- data/info/welcome.md +14 -5
- data/lib/rufio/application.rb +12 -1
- data/lib/rufio/archive_controller.rb +211 -0
- data/lib/rufio/background_command_executor.rb +9 -0
- data/lib/rufio/background_status.rb +49 -0
- data/lib/rufio/bookmark_controller.rb +38 -121
- data/lib/rufio/bookmark_manager.rb +77 -331
- data/lib/rufio/command_completion.rb +28 -2
- data/lib/rufio/command_history.rb +5 -2
- data/lib/rufio/command_mode.rb +60 -134
- data/lib/rufio/command_mode_ui.rb +4 -42
- data/lib/rufio/config.rb +88 -136
- data/lib/rufio/config_loader.rb +4 -11
- data/lib/rufio/dialog_renderer.rb +90 -152
- data/lib/rufio/dialog_support.rb +69 -0
- data/lib/rufio/document_text_extractor.rb +167 -0
- data/lib/rufio/file_operation_controller.rb +49 -222
- data/lib/rufio/file_operations.rb +28 -6
- data/lib/rufio/file_preview.rb +46 -2
- data/lib/rufio/global_search.rb +125 -13
- data/lib/rufio/help_menu.rb +19 -7
- data/lib/rufio/interpreter_resolver.rb +6 -11
- data/lib/rufio/job_manager.rb +2 -5
- data/lib/rufio/key_input.rb +77 -0
- data/lib/rufio/keybind_handler.rb +83 -116
- data/lib/rufio/local_script_scanner.rb +6 -18
- data/lib/rufio/native/aarch64-linux-gnu/librufio_zig.so +0 -0
- data/lib/rufio/native/aarch64-linux-musl/librufio_zig.so +0 -0
- data/lib/rufio/native/aarch64-macos/librufio_zig.dylib +0 -0
- data/lib/rufio/native/aarch64-windows/rufio_zig.dll +0 -0
- data/lib/rufio/native/x86_64-linux-gnu/librufio_zig.so +0 -0
- data/lib/rufio/native/x86_64-linux-musl/librufio_zig.so +0 -0
- data/lib/rufio/native/x86_64-macos/librufio_zig.dylib +0 -0
- data/lib/rufio/native/x86_64-windows/rufio_zig.dll +0 -0
- data/lib/rufio/native_content_search.rb +153 -0
- data/lib/rufio/native_scanner.rb +13 -68
- data/lib/rufio/native_scanner_zig.rb +106 -56
- data/lib/rufio/native_zip.rb +121 -0
- data/lib/rufio/navigation_controller.rb +20 -26
- data/lib/rufio/path_jump.rb +55 -0
- data/lib/rufio/screen.rb +2 -12
- data/lib/rufio/script_executor.rb +6 -73
- data/lib/rufio/script_file.rb +44 -0
- data/lib/rufio/script_path_manager.rb +9 -43
- data/lib/rufio/script_runner.rb +13 -50
- data/lib/rufio/search_controller.rb +1 -1
- data/lib/rufio/shell_command_completion.rb +1 -5
- data/lib/rufio/shell_init.rb +90 -0
- data/lib/rufio/task_status.rb +5 -1
- data/lib/rufio/terminal_ui.rb +84 -298
- data/lib/rufio/text_utils.rb +26 -3
- data/lib/rufio/ui_renderer.rb +73 -45
- data/lib/rufio/version.rb +1 -1
- data/lib/rufio/zip_archive.rb +314 -0
- data/lib/rufio/zip_extractor.rb +346 -0
- data/lib/rufio/zip_writer.rb +268 -0
- data/lib/rufio/zoxide_integration.rb +5 -43
- data/lib/rufio.rb +6 -0
- data/lib_zig/rufio_native/Makefile +54 -17
- data/lib_zig/rufio_native/bench.sh +36 -0
- data/lib_zig/rufio_native/build.zig +32 -35
- data/lib_zig/rufio_native/src/cli.zig +99 -0
- data/lib_zig/rufio_native/src/main.zig +187 -83
- data/lib_zig/rufio_native/src/os.zig +889 -0
- data/lib_zig/rufio_native/src/search.zig +919 -0
- data/lib_zig/rufio_native/src/search_test.zig +88 -0
- data/lib_zig/rufio_native/src/zip.zig +482 -0
- metadata +128 -3
- data/lib/rufio/native/rufio_zig.bundle +0 -0
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'dialog_support'
|
|
4
|
+
|
|
3
5
|
module Rufio
|
|
4
6
|
# ブックマーク・zoxide・スクリプトパス専用コントローラ
|
|
5
7
|
# KeybindHandler からブックマーク系・zoxide・スクリプトパス系メソッドを分離し、単一責任原則に準拠
|
|
6
8
|
class BookmarkController
|
|
9
|
+
include DialogSupport
|
|
10
|
+
|
|
7
11
|
def initialize(directory_listing, bookmark_manager, dialog_renderer, nav_controller,
|
|
8
12
|
script_path_manager, notification_manager, zoxide_integration)
|
|
9
13
|
@directory_listing = directory_listing
|
|
@@ -78,8 +82,6 @@ module Rufio
|
|
|
78
82
|
end
|
|
79
83
|
|
|
80
84
|
def show_bookmark_menu
|
|
81
|
-
current_path = @directory_listing&.current_path || Dir.pwd
|
|
82
|
-
|
|
83
85
|
menu_items = [
|
|
84
86
|
'1. Add current dir to bookmarks',
|
|
85
87
|
'2. Add to script paths',
|
|
@@ -154,56 +156,14 @@ module Rufio
|
|
|
154
156
|
# 存在しないパスのブックマークはスキップする
|
|
155
157
|
# @return [Integer, nil] 新しいブックマークインデックス、またはnil
|
|
156
158
|
def goto_next_bookmark
|
|
157
|
-
|
|
158
|
-
return nil unless bookmarks&.any?
|
|
159
|
-
|
|
160
|
-
current_path = @directory_listing.current_path
|
|
161
|
-
current_position = bookmarks.find_index { |bm| bm[:path] == current_path }
|
|
162
|
-
start_idx = if current_position
|
|
163
|
-
(current_position + 1) % bookmarks.length
|
|
164
|
-
elsif @last_bookmark_idx
|
|
165
|
-
(@last_bookmark_idx + 1) % bookmarks.length
|
|
166
|
-
else
|
|
167
|
-
0
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
bookmarks.length.times do |i|
|
|
171
|
-
idx = (start_idx + i) % bookmarks.length
|
|
172
|
-
next unless Dir.exist?(bookmarks[idx][:path])
|
|
173
|
-
|
|
174
|
-
@last_bookmark_idx = idx
|
|
175
|
-
navigate_to_directory(bookmarks[idx][:path])
|
|
176
|
-
return @last_bookmark_idx
|
|
177
|
-
end
|
|
178
|
-
nil
|
|
159
|
+
cycle_bookmark(1)
|
|
179
160
|
end
|
|
180
161
|
|
|
181
162
|
# 前のブックマークに移動(Shift+Tabキー)
|
|
182
163
|
# 存在しないパスのブックマークはスキップする
|
|
183
164
|
# @return [Integer, nil] 新しいブックマークインデックス、またはnil
|
|
184
165
|
def goto_prev_bookmark
|
|
185
|
-
|
|
186
|
-
return nil unless bookmarks&.any?
|
|
187
|
-
|
|
188
|
-
current_path = @directory_listing.current_path
|
|
189
|
-
current_position = bookmarks.find_index { |bm| bm[:path] == current_path }
|
|
190
|
-
start_idx = if current_position
|
|
191
|
-
(current_position - 1 + bookmarks.length) % bookmarks.length
|
|
192
|
-
elsif @last_bookmark_idx
|
|
193
|
-
(@last_bookmark_idx - 1 + bookmarks.length) % bookmarks.length
|
|
194
|
-
else
|
|
195
|
-
bookmarks.length - 1
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
bookmarks.length.times do |i|
|
|
199
|
-
idx = (start_idx - i + bookmarks.length) % bookmarks.length
|
|
200
|
-
next unless Dir.exist?(bookmarks[idx][:path])
|
|
201
|
-
|
|
202
|
-
@last_bookmark_idx = idx
|
|
203
|
-
navigate_to_directory(bookmarks[idx][:path])
|
|
204
|
-
return @last_bookmark_idx
|
|
205
|
-
end
|
|
206
|
-
nil
|
|
166
|
+
cycle_bookmark(-1)
|
|
207
167
|
end
|
|
208
168
|
|
|
209
169
|
# ============================
|
|
@@ -262,8 +222,6 @@ module Rufio
|
|
|
262
222
|
end
|
|
263
223
|
|
|
264
224
|
selected_index = 0
|
|
265
|
-
screen = @terminal_ui&.screen
|
|
266
|
-
renderer = @terminal_ui&.renderer
|
|
267
225
|
|
|
268
226
|
loop do
|
|
269
227
|
menu_items = paths.each_with_index.map do |path, i|
|
|
@@ -277,30 +235,13 @@ module Rufio
|
|
|
277
235
|
width = 50
|
|
278
236
|
height = content_lines.length + 4
|
|
279
237
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
})
|
|
288
|
-
renderer.render(screen)
|
|
289
|
-
|
|
290
|
-
key = STDIN.getch
|
|
291
|
-
screen.disable_overlay
|
|
292
|
-
renderer.render(screen)
|
|
293
|
-
else
|
|
294
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
295
|
-
@dialog_renderer.draw_floating_window(x, y, width, height, title, content_lines, {
|
|
296
|
-
border_color: "\e[35m",
|
|
297
|
-
title_color: "\e[1;35m",
|
|
298
|
-
content_color: "\e[37m"
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
key = STDIN.getch
|
|
302
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
303
|
-
end
|
|
238
|
+
key = show_overlay_dialog(title, content_lines, {
|
|
239
|
+
width: width,
|
|
240
|
+
height: height,
|
|
241
|
+
border_color: "\e[35m",
|
|
242
|
+
title_color: "\e[1;35m",
|
|
243
|
+
content_color: "\e[37m"
|
|
244
|
+
})
|
|
304
245
|
|
|
305
246
|
case key
|
|
306
247
|
when 'j'
|
|
@@ -358,59 +299,38 @@ module Rufio
|
|
|
358
299
|
# ============================
|
|
359
300
|
|
|
360
301
|
def navigate_to_directory(path)
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
result = @directory_listing.navigate_to_path(path)
|
|
364
|
-
if result
|
|
365
|
-
@nav_controller.select_index(0)
|
|
366
|
-
@nav_controller.clear_filter_mode
|
|
367
|
-
true
|
|
368
|
-
else
|
|
369
|
-
false
|
|
370
|
-
end
|
|
302
|
+
@nav_controller.navigate_to_directory(path)
|
|
371
303
|
end
|
|
372
304
|
|
|
373
305
|
private
|
|
374
306
|
|
|
375
|
-
def
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
@terminal_ui.respond_to?(:renderer) &&
|
|
379
|
-
@terminal_ui.screen &&
|
|
380
|
-
@terminal_ui.renderer
|
|
381
|
-
|
|
382
|
-
if use_overlay
|
|
383
|
-
@terminal_ui.show_overlay_dialog(title, content_lines, options, &block)
|
|
384
|
-
else
|
|
385
|
-
width = options[:width]
|
|
386
|
-
height = options[:height]
|
|
387
|
-
|
|
388
|
-
unless width && height
|
|
389
|
-
width, height = @dialog_renderer.calculate_dimensions(content_lines, {
|
|
390
|
-
title: title,
|
|
391
|
-
min_width: options[:min_width] || 40,
|
|
392
|
-
max_width: options[:max_width] || 80
|
|
393
|
-
})
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
397
|
-
|
|
398
|
-
@dialog_renderer.draw_floating_window(x, y, width, height, title, content_lines, {
|
|
399
|
-
border_color: options[:border_color] || "\e[37m",
|
|
400
|
-
title_color: options[:title_color] || "\e[1;33m",
|
|
401
|
-
content_color: options[:content_color] || "\e[37m"
|
|
402
|
-
})
|
|
403
|
-
|
|
404
|
-
key = block_given? ? yield : STDIN.getch
|
|
307
|
+
def cycle_bookmark(step)
|
|
308
|
+
bookmarks = @bookmark_manager.list
|
|
309
|
+
return nil unless bookmarks&.any?
|
|
405
310
|
|
|
406
|
-
|
|
407
|
-
|
|
311
|
+
len = bookmarks.length
|
|
312
|
+
current_path = @directory_listing.current_path
|
|
313
|
+
current_position = bookmarks.find_index { |bm| bm[:path] == current_path }
|
|
314
|
+
start_idx = if current_position
|
|
315
|
+
(current_position + step + len) % len
|
|
316
|
+
elsif @last_bookmark_idx
|
|
317
|
+
(@last_bookmark_idx + step + len) % len
|
|
318
|
+
else
|
|
319
|
+
step > 0 ? 0 : len - 1
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
len.times do |i|
|
|
323
|
+
idx = (start_idx + (i * step) + len) % len
|
|
324
|
+
next unless Dir.exist?(bookmarks[idx][:path])
|
|
408
325
|
|
|
409
|
-
|
|
326
|
+
@last_bookmark_idx = idx
|
|
327
|
+
navigate_to_directory(bookmarks[idx][:path])
|
|
328
|
+
return @last_bookmark_idx
|
|
410
329
|
end
|
|
330
|
+
nil
|
|
411
331
|
end
|
|
412
332
|
|
|
413
|
-
def show_notification(title,
|
|
333
|
+
def show_notification(title, _message, type)
|
|
414
334
|
return unless @notification_manager
|
|
415
335
|
|
|
416
336
|
@notification_manager.add(title, type, duration: 3, exit_code: nil)
|
|
@@ -424,16 +344,13 @@ module Rufio
|
|
|
424
344
|
|
|
425
345
|
def wait_for_keypress
|
|
426
346
|
print ConfigLoader.message('keybind.press_any_key') || 'Press any key to continue...'
|
|
427
|
-
|
|
347
|
+
KeyInput.getch
|
|
428
348
|
end
|
|
429
349
|
|
|
430
350
|
def truncate_path(path, max_length)
|
|
431
351
|
return path if path.length <= max_length
|
|
432
352
|
|
|
433
|
-
|
|
434
|
-
return display_path if display_path.length <= max_length
|
|
435
|
-
|
|
436
|
-
"...#{display_path[-(max_length - 3)..]}"
|
|
353
|
+
TextUtils.shorten_path_from_end(path, max_length, tilde: true)
|
|
437
354
|
end
|
|
438
355
|
end
|
|
439
356
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'dialog_support'
|
|
4
|
+
require_relative 'text_utils'
|
|
3
5
|
require_relative 'bookmark'
|
|
4
6
|
require_relative 'bookmark_storage'
|
|
5
7
|
require_relative 'config_loader'
|
|
@@ -7,6 +9,8 @@ require_relative 'config_loader'
|
|
|
7
9
|
module Rufio
|
|
8
10
|
# Manages bookmark operations with interactive UI
|
|
9
11
|
class BookmarkManager
|
|
12
|
+
include DialogSupport
|
|
13
|
+
|
|
10
14
|
def initialize(bookmark = nil, dialog_renderer = nil)
|
|
11
15
|
@bookmark = bookmark || create_default_bookmark
|
|
12
16
|
@dialog_renderer = dialog_renderer
|
|
@@ -31,159 +35,29 @@ module Rufio
|
|
|
31
35
|
|
|
32
36
|
public
|
|
33
37
|
|
|
34
|
-
#
|
|
35
|
-
# @
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
'[A]dd current directory to bookmarks',
|
|
44
|
-
'[L]ist bookmarks',
|
|
45
|
-
'[R]ename bookmark',
|
|
46
|
-
'[D]elete bookmark',
|
|
47
|
-
'',
|
|
48
|
-
'Press 1-9 to go to bookmark directly',
|
|
49
|
-
'',
|
|
50
|
-
'Press any other key to cancel'
|
|
51
|
-
]
|
|
52
|
-
|
|
53
|
-
dialog_width = 45
|
|
54
|
-
dialog_height = 4 + content_lines.length
|
|
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
|
|
89
|
-
end
|
|
90
|
-
nil
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
result
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# Add a bookmark interactively
|
|
97
|
-
# @param path [String] Path to bookmark
|
|
98
|
-
# @return [Boolean] Success status
|
|
99
|
-
def add_interactive(path)
|
|
100
|
-
return false unless @dialog_renderer
|
|
101
|
-
|
|
102
|
-
# Show floating input dialog
|
|
103
|
-
title = 'Add Bookmark'
|
|
104
|
-
prompt = 'Enter bookmark name:'
|
|
105
|
-
name = @dialog_renderer.show_input_dialog(title, prompt, {
|
|
106
|
-
border_color: "\e[34m", # Blue
|
|
107
|
-
title_color: "\e[1;34m", # Bold blue
|
|
108
|
-
content_color: "\e[37m" # White
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
return false if name.nil? || name.empty?
|
|
112
|
-
|
|
113
|
-
# Add bookmark (name is already trimmed in show_input_dialog)
|
|
114
|
-
if @bookmark.add(path, name)
|
|
115
|
-
show_result_dialog('Bookmark Added', "Added: #{name}", :success)
|
|
116
|
-
true
|
|
117
|
-
else
|
|
118
|
-
show_result_dialog('Add Failed', 'Failed to add bookmark', :error)
|
|
119
|
-
false
|
|
120
|
-
end
|
|
38
|
+
# List all bookmarks interactively
|
|
39
|
+
# @return [Hash, nil] Selected bookmark path or nil
|
|
40
|
+
def list_interactive
|
|
41
|
+
select_bookmark_from_dialog(
|
|
42
|
+
title: 'Bookmarks',
|
|
43
|
+
header: 'Select a bookmark:',
|
|
44
|
+
border_color: "\e[34m",
|
|
45
|
+
title_color: "\e[1;34m"
|
|
46
|
+
)
|
|
121
47
|
end
|
|
122
48
|
|
|
123
49
|
# Rename a bookmark interactively
|
|
124
50
|
# @return [Boolean] Success status
|
|
125
51
|
def rename_interactive
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
# Build content lines for bookmark selection
|
|
136
|
-
content_lines = ['', 'Select bookmark to rename:', '']
|
|
137
|
-
bookmarks.each_with_index do |bookmark, index|
|
|
138
|
-
# Truncate path if too long
|
|
139
|
-
display_path = bookmark[:path]
|
|
140
|
-
if display_path.start_with?(Dir.home)
|
|
141
|
-
display_path = display_path.sub(Dir.home, '~')
|
|
142
|
-
end
|
|
143
|
-
if display_path.length > 35
|
|
144
|
-
display_path = "...#{display_path[-32..]}"
|
|
145
|
-
end
|
|
146
|
-
content_lines << " #{index + 1}. #{bookmark[:name]}"
|
|
147
|
-
content_lines << " #{display_path}"
|
|
148
|
-
end
|
|
149
|
-
content_lines << ''
|
|
150
|
-
content_lines << 'Press 1-9 to select, ESC to cancel'
|
|
151
|
-
|
|
152
|
-
title = 'Rename Bookmark'
|
|
153
|
-
width = 60
|
|
154
|
-
height = [content_lines.length + 4, 20].min
|
|
155
|
-
|
|
156
|
-
# Wait for selection
|
|
157
|
-
selected_number = nil
|
|
158
|
-
show_overlay_dialog(title, content_lines, {
|
|
159
|
-
width: width,
|
|
160
|
-
height: height,
|
|
161
|
-
border_color: "\e[33m", # Yellow
|
|
162
|
-
title_color: "\e[1;33m", # Bold yellow
|
|
163
|
-
content_color: "\e[37m" # White
|
|
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
|
|
175
|
-
break
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
nil
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
return false unless selected_number
|
|
182
|
-
|
|
183
|
-
# Get new name
|
|
184
|
-
bookmark_to_rename = bookmarks[selected_number - 1]
|
|
185
|
-
old_name = bookmark_to_rename[:name]
|
|
186
|
-
|
|
52
|
+
selected = select_bookmark_from_dialog(
|
|
53
|
+
title: 'Rename Bookmark',
|
|
54
|
+
header: 'Select bookmark to rename:',
|
|
55
|
+
border_color: "\e[33m",
|
|
56
|
+
title_color: "\e[1;33m"
|
|
57
|
+
)
|
|
58
|
+
return false unless selected
|
|
59
|
+
|
|
60
|
+
old_name = selected[:name]
|
|
187
61
|
new_name = @dialog_renderer.show_input_dialog("Rename: #{old_name}", "Enter new name:", {
|
|
188
62
|
border_color: "\e[33m", # Yellow
|
|
189
63
|
title_color: "\e[1;33m", # Bold yellow
|
|
@@ -192,140 +66,27 @@ module Rufio
|
|
|
192
66
|
|
|
193
67
|
return false if new_name.nil? || new_name.empty?
|
|
194
68
|
|
|
195
|
-
# Rename bookmark
|
|
196
69
|
@bookmark.rename(old_name, new_name)
|
|
197
70
|
end
|
|
198
71
|
|
|
199
72
|
# Remove a bookmark interactively
|
|
200
73
|
# @return [Boolean] Success status
|
|
201
74
|
def remove_interactive
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
content_lines = ['', 'Select bookmark to delete:', '']
|
|
213
|
-
bookmarks.each_with_index do |bookmark, index|
|
|
214
|
-
# Truncate path if too long
|
|
215
|
-
display_path = bookmark[:path]
|
|
216
|
-
if display_path.start_with?(Dir.home)
|
|
217
|
-
display_path = display_path.sub(Dir.home, '~')
|
|
218
|
-
end
|
|
219
|
-
if display_path.length > 35
|
|
220
|
-
display_path = "...#{display_path[-32..]}"
|
|
221
|
-
end
|
|
222
|
-
content_lines << " #{index + 1}. #{bookmark[:name]}"
|
|
223
|
-
content_lines << " #{display_path}"
|
|
224
|
-
end
|
|
225
|
-
content_lines << ''
|
|
226
|
-
content_lines << 'Press 1-9 to select, ESC to cancel'
|
|
227
|
-
|
|
228
|
-
title = 'Delete Bookmark'
|
|
229
|
-
width = 60
|
|
230
|
-
height = [content_lines.length + 4, 20].min
|
|
231
|
-
|
|
232
|
-
# Wait for selection
|
|
233
|
-
selected_number = nil
|
|
234
|
-
show_overlay_dialog(title, content_lines, {
|
|
235
|
-
width: width,
|
|
236
|
-
height: height,
|
|
237
|
-
border_color: "\e[31m", # Red (warning)
|
|
238
|
-
title_color: "\e[1;31m", # Bold red
|
|
239
|
-
content_color: "\e[37m" # White
|
|
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
|
|
251
|
-
break
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
nil
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
return false unless selected_number
|
|
258
|
-
|
|
259
|
-
# Confirm deletion
|
|
260
|
-
bookmark_to_remove = bookmarks[selected_number - 1]
|
|
261
|
-
if show_remove_confirmation(bookmark_to_remove[:name])
|
|
262
|
-
@bookmark.remove(bookmark_to_remove[:name])
|
|
75
|
+
selected = select_bookmark_from_dialog(
|
|
76
|
+
title: 'Delete Bookmark',
|
|
77
|
+
header: 'Select bookmark to delete:',
|
|
78
|
+
border_color: "\e[31m",
|
|
79
|
+
title_color: "\e[1;31m"
|
|
80
|
+
)
|
|
81
|
+
return false unless selected
|
|
82
|
+
|
|
83
|
+
if show_remove_confirmation(selected[:name])
|
|
84
|
+
@bookmark.remove(selected[:name])
|
|
263
85
|
else
|
|
264
86
|
false
|
|
265
87
|
end
|
|
266
88
|
end
|
|
267
89
|
|
|
268
|
-
# List all bookmarks interactively
|
|
269
|
-
# @return [Hash, nil] Selected bookmark path or nil
|
|
270
|
-
def list_interactive
|
|
271
|
-
bookmarks = @bookmark.list
|
|
272
|
-
|
|
273
|
-
if bookmarks.empty?
|
|
274
|
-
show_result_dialog('No Bookmarks', 'No bookmarks found', :error)
|
|
275
|
-
return nil
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
return nil unless @dialog_renderer
|
|
279
|
-
|
|
280
|
-
# Build content lines
|
|
281
|
-
content_lines = ['', 'Select a bookmark:','']
|
|
282
|
-
bookmarks.each_with_index do |bookmark, index|
|
|
283
|
-
# Truncate path if too long
|
|
284
|
-
display_path = bookmark[:path]
|
|
285
|
-
if display_path.start_with?(Dir.home)
|
|
286
|
-
display_path = display_path.sub(Dir.home, '~')
|
|
287
|
-
end
|
|
288
|
-
if display_path.length > 35
|
|
289
|
-
display_path = "...#{display_path[-32..]}"
|
|
290
|
-
end
|
|
291
|
-
content_lines << " #{index + 1}. #{bookmark[:name]}"
|
|
292
|
-
content_lines << " #{display_path}"
|
|
293
|
-
end
|
|
294
|
-
content_lines << ''
|
|
295
|
-
content_lines << 'Press 1-9 to select, ESC to cancel'
|
|
296
|
-
|
|
297
|
-
title = 'Bookmarks'
|
|
298
|
-
width = 60
|
|
299
|
-
height = [content_lines.length + 4, 20].min
|
|
300
|
-
|
|
301
|
-
# Wait for selection
|
|
302
|
-
selected_bookmark = nil
|
|
303
|
-
show_overlay_dialog(title, content_lines, {
|
|
304
|
-
width: width,
|
|
305
|
-
height: height,
|
|
306
|
-
border_color: "\e[34m", # Blue
|
|
307
|
-
title_color: "\e[1;34m", # Bold blue
|
|
308
|
-
content_color: "\e[37m" # White
|
|
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
|
|
320
|
-
break
|
|
321
|
-
end
|
|
322
|
-
end
|
|
323
|
-
nil
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
selected_bookmark
|
|
327
|
-
end
|
|
328
|
-
|
|
329
90
|
# Get bookmark by number
|
|
330
91
|
# @param number [Integer] Bookmark number (1-9)
|
|
331
92
|
# @return [Hash, nil] Bookmark hash with :path and :name
|
|
@@ -390,46 +151,53 @@ module Rufio
|
|
|
390
151
|
|
|
391
152
|
private
|
|
392
153
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
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
|
|
154
|
+
def select_bookmark_from_dialog(title:, header:, border_color:, title_color:)
|
|
155
|
+
bookmarks = @bookmark.list
|
|
156
|
+
|
|
157
|
+
if bookmarks.empty?
|
|
158
|
+
show_result_dialog('No Bookmarks', 'No bookmarks found', :error)
|
|
159
|
+
return nil
|
|
160
|
+
end
|
|
417
161
|
|
|
418
|
-
|
|
162
|
+
return nil unless @dialog_renderer
|
|
419
163
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
}
|
|
164
|
+
content_lines = ['', header, '']
|
|
165
|
+
bookmarks.each_with_index do |bookmark, index|
|
|
166
|
+
display_path = TextUtils.shorten_path_from_end(bookmark[:path], 35, tilde: true)
|
|
167
|
+
content_lines << " #{index + 1}. #{bookmark[:name]}"
|
|
168
|
+
content_lines << " #{display_path}"
|
|
169
|
+
end
|
|
170
|
+
content_lines << ''
|
|
171
|
+
content_lines << 'Press 1-9 to select, ESC to cancel'
|
|
425
172
|
|
|
426
|
-
|
|
173
|
+
width = 60
|
|
174
|
+
height = [content_lines.length + 4, 20].min
|
|
427
175
|
|
|
428
|
-
|
|
429
|
-
|
|
176
|
+
selected_bookmark = nil
|
|
177
|
+
show_overlay_dialog(title, content_lines, {
|
|
178
|
+
width: width,
|
|
179
|
+
height: height,
|
|
180
|
+
border_color: border_color,
|
|
181
|
+
title_color: title_color,
|
|
182
|
+
content_color: "\e[37m"
|
|
183
|
+
}) do
|
|
184
|
+
loop do
|
|
185
|
+
input = KeyInput.getch.downcase
|
|
430
186
|
|
|
431
|
-
|
|
187
|
+
if input >= '1' && input <= '9'
|
|
188
|
+
number = input.to_i
|
|
189
|
+
if number > 0 && number <= bookmarks.length
|
|
190
|
+
selected_bookmark = bookmarks[number - 1]
|
|
191
|
+
break
|
|
192
|
+
end
|
|
193
|
+
elsif input == "\e"
|
|
194
|
+
break
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
nil
|
|
432
198
|
end
|
|
199
|
+
|
|
200
|
+
selected_bookmark
|
|
433
201
|
end
|
|
434
202
|
|
|
435
203
|
# Show result dialog with success or error styling
|
|
@@ -483,35 +251,13 @@ module Rufio
|
|
|
483
251
|
''
|
|
484
252
|
]
|
|
485
253
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
# Wait for confirmation
|
|
491
|
-
confirmed = false
|
|
492
|
-
show_overlay_dialog(title, content_lines, {
|
|
493
|
-
width: width,
|
|
494
|
-
height: height,
|
|
254
|
+
confirm_dialog('Confirm Delete', content_lines, {
|
|
255
|
+
width: 50,
|
|
256
|
+
height: content_lines.length + 4,
|
|
495
257
|
border_color: "\e[33m", # Yellow (warning)
|
|
496
258
|
title_color: "\e[1;33m", # Bold yellow
|
|
497
259
|
content_color: "\e[37m" # White
|
|
498
|
-
})
|
|
499
|
-
loop do
|
|
500
|
-
input = STDIN.getch.downcase
|
|
501
|
-
|
|
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
|
|
510
|
-
end
|
|
511
|
-
nil
|
|
512
|
-
end
|
|
513
|
-
|
|
514
|
-
confirmed
|
|
260
|
+
})
|
|
515
261
|
end
|
|
516
262
|
end
|
|
517
263
|
end
|