rufio 1.1.0 → 1.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/CHANGELOG.md +34 -0
- data/README.md +74 -3
- data/README_ja.md +71 -2
- data/Rakefile +14 -1
- data/bin/rufio +31 -2
- data/docs/fast_zip_design_ja.md +167 -0
- data/info/help.md +2 -0
- data/info/keybindings.md +3 -1
- data/info/welcome.md +1 -1
- 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 +6 -1
- data/lib/rufio/command_history.rb +5 -2
- data/lib/rufio/command_mode.rb +40 -134
- data/lib/rufio/command_mode_ui.rb +4 -42
- data/lib/rufio/config.rb +88 -136
- data/lib/rufio/config_loader.rb +3 -11
- data/lib/rufio/dialog_renderer.rb +64 -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_preview.rb +46 -2
- data/lib/rufio/global_search.rb +121 -9
- data/lib/rufio/help_menu.rb +8 -2
- 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 +81 -115
- 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 +18 -20
- 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 +55 -294
- data/lib/rufio/text_utils.rb +26 -3
- data/lib/rufio/ui_renderer.rb +63 -40
- 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 +5 -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 +125 -3
- data/lib/rufio/native/rufio_zig.bundle +0 -0
data/lib/rufio/command_mode.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'open3'
|
|
4
|
+
require_relative 'script_runner'
|
|
4
5
|
|
|
5
6
|
module Rufio
|
|
6
7
|
# コマンドモード - DSLコマンドを実行するための統一インターフェース
|
|
@@ -37,14 +38,8 @@ module Rufio
|
|
|
37
38
|
# @param config_file [String] 設定ファイルのパス
|
|
38
39
|
# @param job_manager [JobManager] ジョブマネージャー
|
|
39
40
|
def setup_script_path_manager(config_file:, job_manager:)
|
|
40
|
-
@job_manager = job_manager
|
|
41
41
|
@script_path_manager = ScriptPathManager.new(config_file)
|
|
42
|
-
|
|
43
|
-
@script_runner = ScriptRunner.new(
|
|
44
|
-
script_paths: @script_path_manager.paths,
|
|
45
|
-
job_manager: job_manager,
|
|
46
|
-
command_logger: @background_executor&.command_logger
|
|
47
|
-
)
|
|
42
|
+
setup_script_runner(script_paths: @script_path_manager.paths, job_manager: job_manager)
|
|
48
43
|
end
|
|
49
44
|
|
|
50
45
|
# 閲覧中ディレクトリを更新
|
|
@@ -214,27 +209,28 @@ module Rufio
|
|
|
214
209
|
# コマンドが空の場合
|
|
215
210
|
return { success: false, error: "コマンドが指定されていません" } if shell_command.strip.empty?
|
|
216
211
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
stdout, stderr, status = Open3.capture3(shell_command)
|
|
220
|
-
|
|
221
|
-
result = {
|
|
222
|
-
success: status.success?,
|
|
223
|
-
output: stdout.strip,
|
|
224
|
-
stderr: stderr.strip
|
|
225
|
-
}
|
|
212
|
+
run_shell_capture(shell_command)
|
|
213
|
+
end
|
|
226
214
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
215
|
+
# Open3.capture3 によるコマンド実行と結果ハッシュの組み立て
|
|
216
|
+
def run_shell_capture(command, chdir: nil, not_found_label: "コマンド", error_label: "コマンド実行")
|
|
217
|
+
stdout, stderr, status = if chdir
|
|
218
|
+
Open3.capture3(command, chdir: chdir)
|
|
219
|
+
else
|
|
220
|
+
Open3.capture3(command)
|
|
221
|
+
end
|
|
231
222
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
223
|
+
result = {
|
|
224
|
+
success: status.success?,
|
|
225
|
+
output: stdout.strip,
|
|
226
|
+
stderr: stderr.strip
|
|
227
|
+
}
|
|
228
|
+
result[:error] = "コマンドが失敗しました (終了コード: #{status.exitstatus})" unless status.success?
|
|
229
|
+
result
|
|
230
|
+
rescue Errno::ENOENT => e
|
|
231
|
+
{ success: false, error: "#{not_found_label}が見つかりません: #{e.message}" }
|
|
232
|
+
rescue StandardError => e
|
|
233
|
+
{ success: false, error: "#{error_label}エラー: #{e.message}" }
|
|
238
234
|
end
|
|
239
235
|
|
|
240
236
|
# スクリプトを実行する(@プレフィックス用)
|
|
@@ -276,36 +272,17 @@ module Rufio
|
|
|
276
272
|
# @param args [String, nil] スクリプトに渡す引数
|
|
277
273
|
# @return [String, Hash] 実行結果メッセージ
|
|
278
274
|
def execute_local_script(script, working_dir, args = nil)
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
path: working_dir,
|
|
286
|
-
command: command
|
|
287
|
-
)
|
|
288
|
-
job.start
|
|
289
|
-
|
|
290
|
-
Thread.new do
|
|
291
|
-
execute_script_in_background(job, script, working_dir, command)
|
|
292
|
-
end
|
|
293
|
-
|
|
294
|
-
"🚀 ジョブを開始: #{script[:name]}"
|
|
295
|
-
else
|
|
296
|
-
# 同期実行
|
|
297
|
-
stdout, stderr, status = Open3.capture3(command, chdir: working_dir)
|
|
298
|
-
result = {
|
|
299
|
-
success: status.success?,
|
|
300
|
-
output: stdout.strip,
|
|
301
|
-
stderr: stderr.strip
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
# Logsに記録
|
|
305
|
-
log_execution("@#{script[:name]}", result)
|
|
275
|
+
runner = ScriptRunner.new(
|
|
276
|
+
script_paths: [], job_manager: @job_manager,
|
|
277
|
+
command_logger: @background_executor&.command_logger
|
|
278
|
+
)
|
|
279
|
+
result = runner.execute(script, working_dir: working_dir, args: args)
|
|
280
|
+
return "🚀 ジョブを開始: #{script[:name]}" if @job_manager
|
|
306
281
|
|
|
307
|
-
|
|
308
|
-
|
|
282
|
+
# CommandMode の表示用の戻り値は維持する。
|
|
283
|
+
result = { success: result[:success], output: result[:output].strip, stderr: result[:error].strip }
|
|
284
|
+
log_execution("@#{script[:name]}", result)
|
|
285
|
+
result
|
|
309
286
|
end
|
|
310
287
|
|
|
311
288
|
# 実行結果をCommandLoggerに記録
|
|
@@ -324,59 +301,6 @@ module Rufio
|
|
|
324
301
|
)
|
|
325
302
|
end
|
|
326
303
|
|
|
327
|
-
# スクリプトの実行コマンドを構築
|
|
328
|
-
# @param script [Hash] スクリプト情報
|
|
329
|
-
# @return [String] 実行コマンド
|
|
330
|
-
def build_script_command(script)
|
|
331
|
-
path = script[:path]
|
|
332
|
-
ext = File.extname(path).downcase
|
|
333
|
-
|
|
334
|
-
case ext
|
|
335
|
-
when '.rb'
|
|
336
|
-
"ruby #{path.shellescape}"
|
|
337
|
-
when '.py'
|
|
338
|
-
"python3 #{path.shellescape}"
|
|
339
|
-
when '.js'
|
|
340
|
-
"node #{path.shellescape}"
|
|
341
|
-
when '.ts'
|
|
342
|
-
"ts-node #{path.shellescape}"
|
|
343
|
-
when '.pl'
|
|
344
|
-
"perl #{path.shellescape}"
|
|
345
|
-
when '.ps1'
|
|
346
|
-
"pwsh #{path.shellescape}"
|
|
347
|
-
else
|
|
348
|
-
path.shellescape
|
|
349
|
-
end
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
# ローカルスクリプトをバックグラウンドで実行
|
|
353
|
-
def execute_script_in_background(job, script, working_dir, command)
|
|
354
|
-
stdout, stderr, status = Open3.capture3(command, chdir: working_dir)
|
|
355
|
-
|
|
356
|
-
job.append_log(stdout) unless stdout.empty?
|
|
357
|
-
job.append_log(stderr) unless stderr.empty?
|
|
358
|
-
|
|
359
|
-
if status.success?
|
|
360
|
-
job.complete(exit_code: status.exitstatus)
|
|
361
|
-
else
|
|
362
|
-
job.fail(exit_code: status.exitstatus)
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
# Logsに記録
|
|
366
|
-
log_execution("@#{script[:name]}", {
|
|
367
|
-
success: status.success?,
|
|
368
|
-
output: stdout.strip,
|
|
369
|
-
stderr: stderr.strip
|
|
370
|
-
})
|
|
371
|
-
|
|
372
|
-
@job_manager&.notify_completion(job)
|
|
373
|
-
rescue StandardError => e
|
|
374
|
-
job.append_log("Error: #{e.message}")
|
|
375
|
-
job.fail(exit_code: -1)
|
|
376
|
-
log_execution("@#{script[:name]}", { success: false, output: '', stderr: e.message })
|
|
377
|
-
@job_manager&.notify_completion(job)
|
|
378
|
-
end
|
|
379
|
-
|
|
380
304
|
# rakeタスクを実行する
|
|
381
305
|
# @param task_name [String] タスク名
|
|
382
306
|
# @param working_dir [String, nil] 作業ディレクトリ
|
|
@@ -393,32 +317,14 @@ module Rufio
|
|
|
393
317
|
working_dir ||= Dir.pwd
|
|
394
318
|
shell_command = "rake #{task_name.shellescape}"
|
|
395
319
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
unless status.success?
|
|
406
|
-
result[:error] = "コマンドが失敗しました (終了コード: #{status.exitstatus})"
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
# Logsに記録
|
|
410
|
-
log_execution("rake:#{task_name}", result)
|
|
411
|
-
|
|
412
|
-
result
|
|
413
|
-
rescue Errno::ENOENT => e
|
|
414
|
-
result = { success: false, error: "rakeが見つかりません: #{e.message}" }
|
|
415
|
-
log_execution("rake:#{task_name}", result)
|
|
416
|
-
result
|
|
417
|
-
rescue StandardError => e
|
|
418
|
-
result = { success: false, error: "rake実行エラー: #{e.message}" }
|
|
419
|
-
log_execution("rake:#{task_name}", result)
|
|
420
|
-
result
|
|
421
|
-
end
|
|
320
|
+
result = run_shell_capture(
|
|
321
|
+
shell_command,
|
|
322
|
+
chdir: working_dir,
|
|
323
|
+
not_found_label: "rake",
|
|
324
|
+
error_label: "rake実行"
|
|
325
|
+
)
|
|
326
|
+
log_execution("rake:#{task_name}", result)
|
|
327
|
+
result
|
|
422
328
|
end
|
|
423
329
|
|
|
424
330
|
# スクリプトパスからスクリプトを検索して実行を試みる
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'dialog_support'
|
|
4
|
+
|
|
3
5
|
require 'io/console'
|
|
4
6
|
|
|
5
7
|
module Rufio
|
|
6
8
|
# コマンドモードのUI - Tab補完とフローティングウィンドウでの結果表示
|
|
7
9
|
class CommandModeUI
|
|
10
|
+
include DialogSupport
|
|
11
|
+
|
|
8
12
|
def initialize(command_mode, dialog_renderer)
|
|
9
13
|
@command_mode = command_mode
|
|
10
14
|
@dialog_renderer = dialog_renderer
|
|
@@ -155,48 +159,6 @@ module Rufio
|
|
|
155
159
|
|
|
156
160
|
private
|
|
157
161
|
|
|
158
|
-
# オーバーレイダイアログを表示してキー入力を待つヘルパーメソッド
|
|
159
|
-
def show_overlay_dialog(title, content_lines, options = {}, &block)
|
|
160
|
-
# terminal_ui が利用可能で、screen と renderer が存在する場合のみオーバーレイを使用
|
|
161
|
-
use_overlay = @terminal_ui &&
|
|
162
|
-
@terminal_ui.respond_to?(:screen) &&
|
|
163
|
-
@terminal_ui.respond_to?(:renderer) &&
|
|
164
|
-
@terminal_ui.screen &&
|
|
165
|
-
@terminal_ui.renderer
|
|
166
|
-
|
|
167
|
-
if use_overlay
|
|
168
|
-
# オーバーレイを使用
|
|
169
|
-
@terminal_ui.show_overlay_dialog(title, content_lines, options, &block)
|
|
170
|
-
else
|
|
171
|
-
# フォールバック: 従来の方法
|
|
172
|
-
width = options[:width]
|
|
173
|
-
height = options[:height]
|
|
174
|
-
|
|
175
|
-
unless width && height
|
|
176
|
-
width, height = @dialog_renderer.calculate_dimensions(content_lines, {
|
|
177
|
-
title: title,
|
|
178
|
-
min_width: options[:min_width] || 40,
|
|
179
|
-
max_width: options[:max_width] || 80
|
|
180
|
-
})
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
x, y = @dialog_renderer.calculate_center(width, height)
|
|
184
|
-
|
|
185
|
-
@dialog_renderer.draw_floating_window(x, y, width, height, title, content_lines, {
|
|
186
|
-
border_color: options[:border_color] || "\e[37m",
|
|
187
|
-
title_color: options[:title_color] || "\e[1;33m",
|
|
188
|
-
content_color: options[:content_color] || "\e[37m"
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
key = block_given? ? yield : STDIN.getch
|
|
192
|
-
|
|
193
|
-
@dialog_renderer.clear_area(x, y, width, height)
|
|
194
|
-
@terminal_ui&.refresh_display
|
|
195
|
-
|
|
196
|
-
key
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
162
|
# 文字列配列の共通プレフィックスを見つける
|
|
201
163
|
# @param strings [Array<String>] 文字列配列
|
|
202
164
|
# @return [String] 共通プレフィックス
|
data/lib/rufio/config.rb
CHANGED
|
@@ -19,147 +19,92 @@ module Rufio
|
|
|
19
19
|
YAML_CONFIG_PATH = File.join(CONFIG_DIR, 'config.yml').freeze
|
|
20
20
|
LOCAL_YAML_PATH = './rufio.yml'
|
|
21
21
|
|
|
22
|
+
# Base English message definitions
|
|
23
|
+
BASE_MESSAGES = {
|
|
24
|
+
# Application messages
|
|
25
|
+
'app.interrupted' => 'rufio interrupted',
|
|
26
|
+
'app.error_occurred' => 'Error occurred',
|
|
27
|
+
'app.terminated' => 'rufio terminated',
|
|
28
|
+
|
|
29
|
+
# File operations
|
|
30
|
+
'file.not_found' => 'File not found',
|
|
31
|
+
'file.not_readable' => 'File not readable',
|
|
32
|
+
'file.read_error' => 'File read error',
|
|
33
|
+
'file.binary_file' => 'Binary file',
|
|
34
|
+
'file.cannot_preview' => 'Cannot preview',
|
|
35
|
+
'file.encoding_error' => 'Character encoding error - cannot read file',
|
|
36
|
+
'file.invalid_archive' => 'Invalid ZIP archive',
|
|
37
|
+
'file.preview_error' => 'Preview error',
|
|
38
|
+
'file.error_prefix' => 'Error',
|
|
39
|
+
|
|
40
|
+
# Keybind messages
|
|
41
|
+
'keybind.invalid_key' => 'invalid key',
|
|
42
|
+
'keybind.search_text' => 'Search text: ',
|
|
43
|
+
'keybind.no_matches' => 'No matches found.',
|
|
44
|
+
'keybind.press_any_key' => 'Press any key to continue...',
|
|
45
|
+
'keybind.input_filename' => 'Enter filename: ',
|
|
46
|
+
'keybind.input_dirname' => 'Enter directory name: ',
|
|
47
|
+
'keybind.invalid_filename' => 'Invalid filename (cannot contain / or \\)',
|
|
48
|
+
'keybind.invalid_dirname' => 'Invalid directory name (cannot contain / or \\)',
|
|
49
|
+
'keybind.file_exists' => 'File already exists',
|
|
50
|
+
'keybind.directory_exists' => 'Directory already exists',
|
|
51
|
+
'keybind.file_created' => 'File created',
|
|
52
|
+
'keybind.directory_created' => 'Directory created',
|
|
53
|
+
'keybind.creation_error' => 'Creation error',
|
|
54
|
+
|
|
55
|
+
# UI messages
|
|
56
|
+
'ui.operation_prompt' => 'Operation: ',
|
|
57
|
+
|
|
58
|
+
# Help text
|
|
59
|
+
'help.full' => 'j/k:move h:back l:enter o:open g/}:top/bottom G:global-search r:refresh f:filter s:search F:content a/A:create m/p/x:ops b:bookmark z:zoxide 1-9:goto q:quit',
|
|
60
|
+
'help.short' => 'j/k:move h:back l:enter o:open f:filter s:search b:bookmark z:zoxide 1-9:goto q:quit',
|
|
61
|
+
|
|
62
|
+
# Health check messages
|
|
63
|
+
'health.title' => 'rufio Health Check',
|
|
64
|
+
'health.ruby_version' => 'Ruby version',
|
|
65
|
+
'health.required_gems' => 'Required gems',
|
|
66
|
+
'health.fzf' => 'fzf (file search)',
|
|
67
|
+
'health.rga' => 'rga (content search)',
|
|
68
|
+
'health.zoxide' => 'zoxide (directory history)',
|
|
69
|
+
'health.bat' => 'bat (syntax highlight)',
|
|
70
|
+
'health.file_opener' => 'System file opener',
|
|
71
|
+
'health.summary' => 'Summary:',
|
|
72
|
+
'health.ok' => 'OK',
|
|
73
|
+
'health.warnings' => 'Warnings',
|
|
74
|
+
'health.errors' => 'Errors',
|
|
75
|
+
'health.all_passed' => 'All checks passed! rufio is ready to use.',
|
|
76
|
+
'health.critical_missing' => 'Some critical components are missing. rufio may not work properly.',
|
|
77
|
+
'health.optional_missing' => 'Some optional features are unavailable. Basic functionality will work.',
|
|
78
|
+
'health.all_gems_installed' => 'All required gems installed',
|
|
79
|
+
'health.missing_gems' => 'Missing gems',
|
|
80
|
+
'health.gem_install_instruction' => 'Run: gem install',
|
|
81
|
+
'health.tool_not_found' => 'not found',
|
|
82
|
+
'health.unknown_platform' => 'Unknown platform',
|
|
83
|
+
'health.file_open_may_not_work' => 'File opening may not work properly',
|
|
84
|
+
'health.macos_opener' => 'macOS file opener',
|
|
85
|
+
'health.linux_opener' => 'Linux file opener',
|
|
86
|
+
'health.windows_opener' => 'Windows file opener',
|
|
87
|
+
'health.install_brew' => 'Install: brew install',
|
|
88
|
+
'health.install_apt' => 'Install: apt install',
|
|
89
|
+
'health.install_guide' => 'Install: Check the installation guide for your platform',
|
|
90
|
+
'health.rga_releases' => 'Install: https://github.com/phiresky/ripgrep-all/releases',
|
|
91
|
+
'health.ruby_upgrade_needed' => 'Please upgrade Ruby to version 2.7.0 or higher'
|
|
92
|
+
}.freeze
|
|
93
|
+
|
|
22
94
|
# Multi-language message definitions
|
|
23
95
|
MESSAGES = {
|
|
24
|
-
'en' =>
|
|
25
|
-
|
|
26
|
-
'app.interrupted' => 'rufio interrupted',
|
|
27
|
-
'app.error_occurred' => 'Error occurred',
|
|
28
|
-
'app.terminated' => 'rufio terminated',
|
|
29
|
-
|
|
30
|
-
# File operations
|
|
31
|
-
'file.not_found' => 'File not found',
|
|
32
|
-
'file.not_readable' => 'File not readable',
|
|
33
|
-
'file.read_error' => 'File read error',
|
|
34
|
-
'file.binary_file' => 'Binary file',
|
|
35
|
-
'file.cannot_preview' => 'Cannot preview',
|
|
36
|
-
'file.encoding_error' => 'Character encoding error - cannot read file',
|
|
37
|
-
'file.preview_error' => 'Preview error',
|
|
38
|
-
'file.error_prefix' => 'Error',
|
|
39
|
-
|
|
40
|
-
# Keybind messages
|
|
41
|
-
'keybind.invalid_key' => 'invalid key',
|
|
42
|
-
'keybind.search_text' => 'Search text: ',
|
|
43
|
-
'keybind.no_matches' => 'No matches found.',
|
|
44
|
-
'keybind.press_any_key' => 'Press any key to continue...',
|
|
45
|
-
'keybind.input_filename' => 'Enter filename: ',
|
|
46
|
-
'keybind.input_dirname' => 'Enter directory name: ',
|
|
47
|
-
'keybind.invalid_filename' => 'Invalid filename (cannot contain / or \\)',
|
|
48
|
-
'keybind.invalid_dirname' => 'Invalid directory name (cannot contain / or \\)',
|
|
49
|
-
'keybind.file_exists' => 'File already exists',
|
|
50
|
-
'keybind.directory_exists' => 'Directory already exists',
|
|
51
|
-
'keybind.file_created' => 'File created',
|
|
52
|
-
'keybind.directory_created' => 'Directory created',
|
|
53
|
-
'keybind.creation_error' => 'Creation error',
|
|
54
|
-
|
|
55
|
-
# UI messages
|
|
56
|
-
'ui.operation_prompt' => 'Operation: ',
|
|
57
|
-
|
|
58
|
-
# Help text
|
|
59
|
-
'help.full' => 'j/k:move h:back l:enter o:open g/}:top/bottom G:global-search r:refresh f:filter s:search F:content a/A:create m/p/x:ops b:bookmark z:zoxide 1-9:goto q:quit',
|
|
60
|
-
'help.short' => 'j/k:move h:back l:enter o:open f:filter s:search b:bookmark z:zoxide 1-9:goto q:quit',
|
|
61
|
-
|
|
62
|
-
# Health check messages
|
|
63
|
-
'health.title' => 'rufio Health Check',
|
|
64
|
-
'health.ruby_version' => 'Ruby version',
|
|
65
|
-
'health.required_gems' => 'Required gems',
|
|
66
|
-
'health.fzf' => 'fzf (file search)',
|
|
67
|
-
'health.rga' => 'rga (content search)',
|
|
68
|
-
'health.zoxide' => 'zoxide (directory history)',
|
|
69
|
-
'health.bat' => 'bat (syntax highlight)',
|
|
70
|
-
'health.file_opener' => 'System file opener',
|
|
71
|
-
'health.summary' => 'Summary:',
|
|
72
|
-
'health.ok' => 'OK',
|
|
73
|
-
'health.warnings' => 'Warnings',
|
|
74
|
-
'health.errors' => 'Errors',
|
|
75
|
-
'health.all_passed' => 'All checks passed! rufio is ready to use.',
|
|
76
|
-
'health.critical_missing' => 'Some critical components are missing. rufio may not work properly.',
|
|
77
|
-
'health.optional_missing' => 'Some optional features are unavailable. Basic functionality will work.',
|
|
78
|
-
'health.all_gems_installed' => 'All required gems installed',
|
|
79
|
-
'health.missing_gems' => 'Missing gems',
|
|
80
|
-
'health.gem_install_instruction' => 'Run: gem install',
|
|
81
|
-
'health.tool_not_found' => 'not found',
|
|
82
|
-
'health.unknown_platform' => 'Unknown platform',
|
|
83
|
-
'health.file_open_may_not_work' => 'File opening may not work properly',
|
|
84
|
-
'health.macos_opener' => 'macOS file opener',
|
|
85
|
-
'health.linux_opener' => 'Linux file opener',
|
|
86
|
-
'health.windows_opener' => 'Windows file opener',
|
|
87
|
-
'health.install_brew' => 'Install: brew install',
|
|
88
|
-
'health.install_apt' => 'Install: apt install',
|
|
89
|
-
'health.install_guide' => 'Install: Check the installation guide for your platform',
|
|
90
|
-
'health.rga_releases' => 'Install: https://github.com/phiresky/ripgrep-all/releases',
|
|
91
|
-
'health.ruby_upgrade_needed' => 'Please upgrade Ruby to version 2.7.0 or higher'
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
'ja' => {
|
|
95
|
-
# Application messages
|
|
96
|
-
'app.interrupted' => 'rufio interrupted',
|
|
97
|
-
'app.error_occurred' => 'Error occurred',
|
|
98
|
-
'app.terminated' => 'rufio terminated',
|
|
99
|
-
|
|
100
|
-
# File operations
|
|
101
|
-
'file.not_found' => 'File not found',
|
|
102
|
-
'file.not_readable' => 'File not readable',
|
|
103
|
-
'file.read_error' => 'File read error',
|
|
104
|
-
'file.binary_file' => 'Binary file',
|
|
105
|
-
'file.cannot_preview' => 'Cannot preview',
|
|
96
|
+
'en' => BASE_MESSAGES,
|
|
97
|
+
'ja' => BASE_MESSAGES.merge(
|
|
106
98
|
'file.encoding_error' => 'Encoding error - cannot read file',
|
|
107
|
-
'file.preview_error' => 'Preview error',
|
|
108
|
-
'file.error_prefix' => 'Error',
|
|
109
|
-
|
|
110
|
-
# Keybind messages
|
|
111
99
|
'keybind.invalid_key' => 'Invalid key',
|
|
112
100
|
'keybind.search_text' => 'Search: ',
|
|
113
|
-
'keybind.no_matches' => 'No matches found.',
|
|
114
|
-
'keybind.press_any_key' => 'Press any key to continue...',
|
|
115
|
-
'keybind.input_filename' => 'Enter filename: ',
|
|
116
|
-
'keybind.input_dirname' => 'Enter directory name: ',
|
|
117
|
-
'keybind.invalid_filename' => 'Invalid filename (cannot contain / or \\)',
|
|
118
|
-
'keybind.invalid_dirname' => 'Invalid directory name (cannot contain / or \\)',
|
|
119
|
-
'keybind.file_exists' => 'File already exists',
|
|
120
|
-
'keybind.directory_exists' => 'Directory already exists',
|
|
121
|
-
'keybind.file_created' => 'File created',
|
|
122
|
-
'keybind.directory_created' => 'Directory created',
|
|
123
|
-
'keybind.creation_error' => 'Creation error',
|
|
124
|
-
|
|
125
|
-
# UI messages
|
|
126
|
-
'ui.operation_prompt' => 'Operation: ',
|
|
127
|
-
|
|
128
|
-
# Help text
|
|
129
101
|
'help.full' => 'j/k:move h:back l:enter o:open g/}:top/end G:global-search r:refresh f:filter s:search F:content a/A:create m/c/x:ops b:bookmark z:zoxide 1-9:jump q:quit',
|
|
130
102
|
'help.short' => 'j/k:move h:back l:enter o:open f:filter s:search b:bookmark z:zoxide 1-9:jump q:quit',
|
|
131
|
-
|
|
132
|
-
# Health check messages
|
|
133
|
-
'health.title' => 'rufio Health Check',
|
|
134
|
-
'health.ruby_version' => 'Ruby version',
|
|
135
|
-
'health.required_gems' => 'Required gems',
|
|
136
|
-
'health.fzf' => 'fzf (file search)',
|
|
137
|
-
'health.rga' => 'rga (content search)',
|
|
138
|
-
'health.zoxide' => 'zoxide (directory history)',
|
|
139
|
-
'health.bat' => 'bat (syntax highlight)',
|
|
140
|
-
'health.file_opener' => 'System file opener',
|
|
141
|
-
'health.summary' => 'Summary:',
|
|
142
|
-
'health.ok' => 'OK',
|
|
143
|
-
'health.warnings' => 'Warnings',
|
|
144
|
-
'health.errors' => 'Errors',
|
|
145
|
-
'health.all_passed' => 'All checks passed! rufio is ready to use.',
|
|
146
103
|
'health.critical_missing' => 'Critical components missing. rufio may not work properly.',
|
|
147
104
|
'health.optional_missing' => 'Optional features unavailable. Basic features will work.',
|
|
148
105
|
'health.all_gems_installed' => 'All required gems are installed',
|
|
149
|
-
'health.
|
|
150
|
-
|
|
151
|
-
'health.tool_not_found' => 'not found',
|
|
152
|
-
'health.unknown_platform' => 'Unknown platform',
|
|
153
|
-
'health.file_open_may_not_work' => 'File open may not work properly',
|
|
154
|
-
'health.macos_opener' => 'macOS file opener',
|
|
155
|
-
'health.linux_opener' => 'Linux file opener',
|
|
156
|
-
'health.windows_opener' => 'Windows file opener',
|
|
157
|
-
'health.install_brew' => 'Install: brew install',
|
|
158
|
-
'health.install_apt' => 'Install: apt install',
|
|
159
|
-
'health.install_guide' => 'Install: Check the installation guide for your platform',
|
|
160
|
-
'health.rga_releases' => 'Install: https://github.com/phiresky/ripgrep-all/releases',
|
|
161
|
-
'health.ruby_upgrade_needed' => 'Please upgrade Ruby to version 2.7.0 or higher'
|
|
162
|
-
}
|
|
106
|
+
'health.file_open_may_not_work' => 'File open may not work properly'
|
|
107
|
+
).freeze
|
|
163
108
|
}.freeze
|
|
164
109
|
|
|
165
110
|
class << self
|
|
@@ -272,14 +217,21 @@ module Rufio
|
|
|
272
217
|
return [] unless File.exist?(path)
|
|
273
218
|
|
|
274
219
|
yaml = YAML.safe_load(File.read(path), symbolize_names: true)
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
yaml.select { |b| b.is_a?(Hash) && b[:path] && b[:name] }
|
|
220
|
+
filter_valid_bookmarks(yaml)
|
|
278
221
|
rescue StandardError => e
|
|
279
222
|
warn "Failed to load bookmarks: #{e.message}"
|
|
280
223
|
[]
|
|
281
224
|
end
|
|
282
225
|
|
|
226
|
+
# 有効なブックマーク要素のみを抽出
|
|
227
|
+
# @param bookmarks [Array<Hash>] ブックマーク配列
|
|
228
|
+
# @return [Array<Hash>] フィルタ済みブックマーク配列
|
|
229
|
+
def filter_valid_bookmarks(bookmarks)
|
|
230
|
+
return [] unless bookmarks.is_a?(Array)
|
|
231
|
+
|
|
232
|
+
bookmarks.select { |b| b.is_a?(Hash) && b[:path] && b[:name] }
|
|
233
|
+
end
|
|
234
|
+
|
|
283
235
|
# ブックマークを保存
|
|
284
236
|
# @param path [String] YAMLファイルのパス
|
|
285
237
|
# @param bookmarks [Array<Hash>] ブックマーク配列
|
|
@@ -398,9 +350,9 @@ module Rufio
|
|
|
398
350
|
end
|
|
399
351
|
|
|
400
352
|
def detect_language
|
|
401
|
-
#
|
|
353
|
+
# RUFIO_LANG or BENIYA_LANG (legacy) environment variable takes precedence
|
|
402
354
|
# This ensures English is default unless explicitly requested
|
|
403
|
-
env_lang = ENV['BENIYA_LANG']
|
|
355
|
+
env_lang = ENV['RUFIO_LANG'] || ENV['BENIYA_LANG']
|
|
404
356
|
|
|
405
357
|
if env_lang && !env_lang.empty?
|
|
406
358
|
# Extract language code (e.g., 'ja_JP.UTF-8' -> 'ja')
|
data/lib/rufio/config_loader.rb
CHANGED
|
@@ -77,7 +77,8 @@ module Rufio
|
|
|
77
77
|
help: '?',
|
|
78
78
|
log_viewer: 'L',
|
|
79
79
|
command_mode: ':',
|
|
80
|
-
quit: 'q'
|
|
80
|
+
quit: 'q',
|
|
81
|
+
quit_cd: 'T'
|
|
81
82
|
}.freeze
|
|
82
83
|
end
|
|
83
84
|
|
|
@@ -282,17 +283,8 @@ module Rufio
|
|
|
282
283
|
Config.save_script_paths(SCRIPT_PATHS_YML, paths)
|
|
283
284
|
end
|
|
284
285
|
|
|
285
|
-
# YAMLファイルにセクションを保存(Config経由)
|
|
286
|
-
def save_to_yaml(key, value)
|
|
287
|
-
Config.save_yaml_config(YAML_CONFIG_PATH, key, value)
|
|
288
|
-
end
|
|
289
|
-
|
|
290
286
|
def filter_valid_bookmarks(bookmarks)
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
bookmarks.select do |b|
|
|
294
|
-
b.is_a?(Hash) && b[:path] && b[:name]
|
|
295
|
-
end
|
|
287
|
+
Config.filter_valid_bookmarks(bookmarks)
|
|
296
288
|
end
|
|
297
289
|
|
|
298
290
|
def load_config_file
|