rufio 0.60.0 → 0.62.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 +56 -0
- data/README.md +221 -590
- data/README_ja.md +331 -0
- data/examples/bookmarks.yml +14 -0
- data/examples/config.rb +68 -0
- data/examples/script_paths.yml +11 -0
- data/lib/rufio/application.rb +1 -1
- data/lib/rufio/bookmark.rb +6 -30
- data/lib/rufio/bookmark_manager.rb +15 -1
- data/lib/rufio/bookmark_storage.rb +149 -0
- data/lib/rufio/command_mode.rb +4 -4
- data/lib/rufio/command_mode_ui.rb +8 -8
- data/lib/rufio/config.rb +268 -54
- data/lib/rufio/config_loader.rb +149 -26
- data/lib/rufio/keybind_handler.rb +14 -9
- data/lib/rufio/script_config_loader.rb +27 -12
- data/lib/rufio/script_path_manager.rb +50 -89
- data/lib/rufio/terminal_ui.rb +2 -2
- data/lib/rufio/version.rb +1 -1
- data/lib/rufio.rb +1 -0
- metadata +10 -17
- data/README_EN.md +0 -610
- data/config_example.rb +0 -88
- data/examples/config.yml +0 -8
- data/scripts/test_jobs/build_simulation.sh +0 -29
- data/scripts/test_jobs/deploy_simulation.sh +0 -37
- data/scripts/test_jobs/quick.sh +0 -11
- data/scripts/test_jobs/random_result.sh +0 -23
- data/scripts/test_jobs/slow_fail.sh +0 -10
- data/scripts/test_jobs/slow_success.sh +0 -10
- data/scripts/test_jobs/very_slow.sh +0 -19
- data/test_delete/test1.txt +0 -1
- data/test_delete/test2.txt +0 -1
|
@@ -47,13 +47,13 @@ module Rufio
|
|
|
47
47
|
# @param suggestions [Array<String>] 補完候補(オプション)
|
|
48
48
|
def show_input_prompt(input, suggestions = [])
|
|
49
49
|
# タイトル
|
|
50
|
-
title = "
|
|
50
|
+
title = "Command Mode"
|
|
51
51
|
|
|
52
|
-
#
|
|
52
|
+
# Build content lines
|
|
53
53
|
content_lines = [""]
|
|
54
|
-
content_lines << "#{input}_" #
|
|
54
|
+
content_lines << "#{input}_" # Show cursor as _
|
|
55
55
|
content_lines << ""
|
|
56
|
-
content_lines << "Tab:
|
|
56
|
+
content_lines << "Tab: Complete | Enter: Execute | ESC: Cancel"
|
|
57
57
|
|
|
58
58
|
# ウィンドウの色設定(青)
|
|
59
59
|
border_color = "\e[34m" # Blue
|
|
@@ -94,7 +94,7 @@ module Rufio
|
|
|
94
94
|
else
|
|
95
95
|
# 文字列形式の結果(従来の動作)
|
|
96
96
|
result_text = result
|
|
97
|
-
is_error = result.include?("⚠️") || result.include?("
|
|
97
|
+
is_error = result.include?("⚠️") || result.include?("Error")
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
# 結果を行に分割
|
|
@@ -112,7 +112,7 @@ module Rufio
|
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
# ウィンドウタイトル
|
|
115
|
-
title = "
|
|
115
|
+
title = "Command Result"
|
|
116
116
|
|
|
117
117
|
# コンテンツ行を構築
|
|
118
118
|
content_lines = [""] + result_lines + ["", "Press any key to close"]
|
|
@@ -207,9 +207,9 @@ module Rufio
|
|
|
207
207
|
# 何も出力がない場合
|
|
208
208
|
if lines.empty?
|
|
209
209
|
if result[:success]
|
|
210
|
-
lines << "
|
|
210
|
+
lines << "Command executed successfully"
|
|
211
211
|
else
|
|
212
|
-
lines << "
|
|
212
|
+
lines << "Command failed"
|
|
213
213
|
end
|
|
214
214
|
end
|
|
215
215
|
|
data/lib/rufio/config.rb
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require 'fileutils'
|
|
5
|
+
|
|
3
6
|
module Rufio
|
|
4
7
|
class Config
|
|
5
8
|
# Default language settings
|
|
6
9
|
DEFAULT_LANGUAGE = 'en'
|
|
7
10
|
AVAILABLE_LANGUAGES = %w[en ja].freeze
|
|
8
11
|
|
|
12
|
+
# 設定ディレクトリとファイルパス
|
|
13
|
+
CONFIG_DIR = File.expand_path('~/.config/rufio').freeze
|
|
14
|
+
CONFIG_RB_PATH = File.join(CONFIG_DIR, 'config.rb').freeze
|
|
15
|
+
SCRIPT_PATHS_YML = File.join(CONFIG_DIR, 'script_paths.yml').freeze
|
|
16
|
+
BOOKMARKS_YML = File.join(CONFIG_DIR, 'bookmarks.yml').freeze
|
|
17
|
+
|
|
18
|
+
# 後方互換性のためのパス(非推奨)
|
|
19
|
+
YAML_CONFIG_PATH = File.join(CONFIG_DIR, 'config.yml').freeze
|
|
20
|
+
LOCAL_YAML_PATH = './rufio.yml'
|
|
21
|
+
|
|
9
22
|
# Multi-language message definitions
|
|
10
23
|
MESSAGES = {
|
|
11
24
|
'en' => {
|
|
@@ -79,71 +92,71 @@ module Rufio
|
|
|
79
92
|
|
|
80
93
|
'ja' => {
|
|
81
94
|
# Application messages
|
|
82
|
-
'app.interrupted' => 'rufio
|
|
83
|
-
'app.error_occurred' => '
|
|
84
|
-
'app.terminated' => 'rufio
|
|
95
|
+
'app.interrupted' => 'rufio interrupted',
|
|
96
|
+
'app.error_occurred' => 'Error occurred',
|
|
97
|
+
'app.terminated' => 'rufio terminated',
|
|
85
98
|
|
|
86
99
|
# File operations
|
|
87
|
-
'file.not_found' => '
|
|
88
|
-
'file.not_readable' => '
|
|
89
|
-
'file.read_error' => '
|
|
90
|
-
'file.binary_file' => '
|
|
91
|
-
'file.cannot_preview' => '
|
|
92
|
-
'file.encoding_error' => '
|
|
93
|
-
'file.preview_error' => '
|
|
94
|
-
'file.error_prefix' => '
|
|
100
|
+
'file.not_found' => 'File not found',
|
|
101
|
+
'file.not_readable' => 'File not readable',
|
|
102
|
+
'file.read_error' => 'File read error',
|
|
103
|
+
'file.binary_file' => 'Binary file',
|
|
104
|
+
'file.cannot_preview' => 'Cannot preview',
|
|
105
|
+
'file.encoding_error' => 'Encoding error - cannot read file',
|
|
106
|
+
'file.preview_error' => 'Preview error',
|
|
107
|
+
'file.error_prefix' => 'Error',
|
|
95
108
|
|
|
96
109
|
# Keybind messages
|
|
97
|
-
'keybind.invalid_key' => '
|
|
98
|
-
'keybind.search_text' => '
|
|
99
|
-
'keybind.no_matches' => '
|
|
100
|
-
'keybind.press_any_key' => '
|
|
101
|
-
'keybind.input_filename' => '
|
|
102
|
-
'keybind.input_dirname' => '
|
|
103
|
-
'keybind.invalid_filename' => '
|
|
104
|
-
'keybind.invalid_dirname' => '
|
|
105
|
-
'keybind.file_exists' => '
|
|
106
|
-
'keybind.directory_exists' => '
|
|
107
|
-
'keybind.file_created' => '
|
|
108
|
-
'keybind.directory_created' => '
|
|
109
|
-
'keybind.creation_error' => '
|
|
110
|
+
'keybind.invalid_key' => 'Invalid key',
|
|
111
|
+
'keybind.search_text' => 'Search: ',
|
|
112
|
+
'keybind.no_matches' => 'No matches found.',
|
|
113
|
+
'keybind.press_any_key' => 'Press any key to continue...',
|
|
114
|
+
'keybind.input_filename' => 'Enter filename: ',
|
|
115
|
+
'keybind.input_dirname' => 'Enter directory name: ',
|
|
116
|
+
'keybind.invalid_filename' => 'Invalid filename (cannot contain / or \\)',
|
|
117
|
+
'keybind.invalid_dirname' => 'Invalid directory name (cannot contain / or \\)',
|
|
118
|
+
'keybind.file_exists' => 'File already exists',
|
|
119
|
+
'keybind.directory_exists' => 'Directory already exists',
|
|
120
|
+
'keybind.file_created' => 'File created',
|
|
121
|
+
'keybind.directory_created' => 'Directory created',
|
|
122
|
+
'keybind.creation_error' => 'Creation error',
|
|
110
123
|
|
|
111
124
|
# UI messages
|
|
112
|
-
'ui.operation_prompt' => '
|
|
125
|
+
'ui.operation_prompt' => 'Operation: ',
|
|
113
126
|
|
|
114
127
|
# Help text
|
|
115
|
-
'help.full' => 'j/k
|
|
116
|
-
'help.short' => 'j/k
|
|
128
|
+
'help.full' => 'j/k:move h:back l:enter o:open g/G:top/end r:refresh f:filter s:search F:content a/A:create m/c/x:ops b:bookmark z:zoxide 1-9:jump q:quit',
|
|
129
|
+
'help.short' => 'j/k:move h:back l:enter o:open f:filter s:search b:bookmark z:zoxide 1-9:jump q:quit',
|
|
117
130
|
|
|
118
131
|
# Health check messages
|
|
119
|
-
'health.title' => 'rufio
|
|
120
|
-
'health.ruby_version' => 'Ruby
|
|
121
|
-
'health.required_gems' => '
|
|
122
|
-
'health.fzf' => 'fzf (
|
|
123
|
-
'health.rga' => 'rga (
|
|
124
|
-
'health.zoxide' => 'zoxide (
|
|
125
|
-
'health.file_opener' => '
|
|
126
|
-
'health.summary' => '
|
|
132
|
+
'health.title' => 'rufio Health Check',
|
|
133
|
+
'health.ruby_version' => 'Ruby version',
|
|
134
|
+
'health.required_gems' => 'Required gems',
|
|
135
|
+
'health.fzf' => 'fzf (file search)',
|
|
136
|
+
'health.rga' => 'rga (content search)',
|
|
137
|
+
'health.zoxide' => 'zoxide (directory history)',
|
|
138
|
+
'health.file_opener' => 'System file opener',
|
|
139
|
+
'health.summary' => 'Summary:',
|
|
127
140
|
'health.ok' => 'OK',
|
|
128
|
-
'health.warnings' => '
|
|
129
|
-
'health.errors' => '
|
|
130
|
-
'health.all_passed' => '
|
|
131
|
-
'health.critical_missing' => '
|
|
132
|
-
'health.optional_missing' => '
|
|
133
|
-
'health.all_gems_installed' => '
|
|
134
|
-
'health.missing_gems' => '
|
|
135
|
-
'health.gem_install_instruction' => '
|
|
136
|
-
'health.tool_not_found' => '
|
|
137
|
-
'health.unknown_platform' => '
|
|
138
|
-
'health.file_open_may_not_work' => '
|
|
139
|
-
'health.macos_opener' => 'macOS
|
|
140
|
-
'health.linux_opener' => 'Linux
|
|
141
|
-
'health.windows_opener' => 'Windows
|
|
142
|
-
'health.install_brew' => '
|
|
143
|
-
'health.install_apt' => '
|
|
144
|
-
'health.install_guide' => '
|
|
145
|
-
'health.rga_releases' => '
|
|
146
|
-
'health.ruby_upgrade_needed' => 'Ruby
|
|
141
|
+
'health.warnings' => 'Warnings',
|
|
142
|
+
'health.errors' => 'Errors',
|
|
143
|
+
'health.all_passed' => 'All checks passed! rufio is ready to use.',
|
|
144
|
+
'health.critical_missing' => 'Critical components missing. rufio may not work properly.',
|
|
145
|
+
'health.optional_missing' => 'Optional features unavailable. Basic features will work.',
|
|
146
|
+
'health.all_gems_installed' => 'All required gems are installed',
|
|
147
|
+
'health.missing_gems' => 'Missing gems',
|
|
148
|
+
'health.gem_install_instruction' => 'Run: gem install',
|
|
149
|
+
'health.tool_not_found' => 'not found',
|
|
150
|
+
'health.unknown_platform' => 'Unknown platform',
|
|
151
|
+
'health.file_open_may_not_work' => 'File open may not work properly',
|
|
152
|
+
'health.macos_opener' => 'macOS file opener',
|
|
153
|
+
'health.linux_opener' => 'Linux file opener',
|
|
154
|
+
'health.windows_opener' => 'Windows file opener',
|
|
155
|
+
'health.install_brew' => 'Install: brew install',
|
|
156
|
+
'health.install_apt' => 'Install: apt install',
|
|
157
|
+
'health.install_guide' => 'Check installation guide for your platform',
|
|
158
|
+
'health.rga_releases' => 'Install: https://github.com/phiresky/ripgrep-all/releases',
|
|
159
|
+
'health.ruby_upgrade_needed' => 'Please upgrade Ruby to version 2.7.0 or higher'
|
|
147
160
|
}
|
|
148
161
|
}.freeze
|
|
149
162
|
|
|
@@ -179,8 +192,209 @@ module Rufio
|
|
|
179
192
|
@current_language = nil
|
|
180
193
|
end
|
|
181
194
|
|
|
195
|
+
# YAML設定を取得(キャッシュあり)
|
|
196
|
+
# @return [Hash] YAML設定
|
|
197
|
+
def yaml_config
|
|
198
|
+
@yaml_config ||= load_yaml_config(YAML_CONFIG_PATH)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# YAML設定をリロード
|
|
202
|
+
def reload_yaml_config!
|
|
203
|
+
@yaml_config = nil
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# 全設定をリセット
|
|
207
|
+
def reset_config!
|
|
208
|
+
@yaml_config = nil
|
|
209
|
+
@script_paths = nil
|
|
210
|
+
@bookmarks = nil
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# ========================================
|
|
214
|
+
# script_paths.yml の操作
|
|
215
|
+
# ========================================
|
|
216
|
+
|
|
217
|
+
# スクリプトパスを読み込む
|
|
218
|
+
# @param path [String] YAMLファイルのパス
|
|
219
|
+
# @return [Array<String>] 展開済みのパス配列
|
|
220
|
+
def load_script_paths(path = SCRIPT_PATHS_YML)
|
|
221
|
+
return [] unless File.exist?(path)
|
|
222
|
+
|
|
223
|
+
yaml = YAML.safe_load(File.read(path))
|
|
224
|
+
return [] unless yaml.is_a?(Array)
|
|
225
|
+
|
|
226
|
+
yaml.map { |p| File.expand_path(p) }
|
|
227
|
+
rescue StandardError => e
|
|
228
|
+
warn "Failed to load script paths: #{e.message}"
|
|
229
|
+
[]
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# スクリプトパスを保存
|
|
233
|
+
# @param path [String] YAMLファイルのパス
|
|
234
|
+
# @param paths [Array<String>] パス配列
|
|
235
|
+
def save_script_paths(path, paths)
|
|
236
|
+
ensure_config_directory(path)
|
|
237
|
+
File.write(path, YAML.dump(paths))
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# スクリプトパスを追加
|
|
241
|
+
# @param path [String] YAMLファイルのパス
|
|
242
|
+
# @param new_path [String] 追加するパス
|
|
243
|
+
def add_script_path(path, new_path)
|
|
244
|
+
paths = load_script_paths(path)
|
|
245
|
+
expanded = File.expand_path(new_path)
|
|
246
|
+
return if paths.include?(expanded)
|
|
247
|
+
|
|
248
|
+
paths << expanded
|
|
249
|
+
save_script_paths(path, paths)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# スクリプトパスを削除
|
|
253
|
+
# @param path [String] YAMLファイルのパス
|
|
254
|
+
# @param remove_path [String] 削除するパス
|
|
255
|
+
def remove_script_path(path, remove_path)
|
|
256
|
+
paths = load_script_paths(path)
|
|
257
|
+
expanded = File.expand_path(remove_path)
|
|
258
|
+
paths.delete(expanded)
|
|
259
|
+
save_script_paths(path, paths)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# ========================================
|
|
263
|
+
# bookmarks.yml の操作
|
|
264
|
+
# ========================================
|
|
265
|
+
|
|
266
|
+
# ブックマークを読み込む
|
|
267
|
+
# @param path [String] YAMLファイルのパス
|
|
268
|
+
# @return [Array<Hash>] ブックマーク配列
|
|
269
|
+
def load_bookmarks_from_yml(path = BOOKMARKS_YML)
|
|
270
|
+
return [] unless File.exist?(path)
|
|
271
|
+
|
|
272
|
+
yaml = YAML.safe_load(File.read(path), symbolize_names: true)
|
|
273
|
+
return [] unless yaml.is_a?(Array)
|
|
274
|
+
|
|
275
|
+
yaml.select { |b| b.is_a?(Hash) && b[:path] && b[:name] }
|
|
276
|
+
rescue StandardError => e
|
|
277
|
+
warn "Failed to load bookmarks: #{e.message}"
|
|
278
|
+
[]
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# ブックマークを保存
|
|
282
|
+
# @param path [String] YAMLファイルのパス
|
|
283
|
+
# @param bookmarks [Array<Hash>] ブックマーク配列
|
|
284
|
+
def save_bookmarks_to_yml(path, bookmarks)
|
|
285
|
+
ensure_config_directory(path)
|
|
286
|
+
data = bookmarks.map { |b| { 'path' => b[:path], 'name' => b[:name] } }
|
|
287
|
+
File.write(path, YAML.dump(data))
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# ブックマークを追加
|
|
291
|
+
# @param path [String] YAMLファイルのパス
|
|
292
|
+
# @param bookmark_path [String] ブックマークするパス
|
|
293
|
+
# @param name [String] ブックマーク名
|
|
294
|
+
def add_bookmark(path, bookmark_path, name)
|
|
295
|
+
bookmarks = load_bookmarks_from_yml(path)
|
|
296
|
+
bookmarks << { path: bookmark_path, name: name }
|
|
297
|
+
save_bookmarks_to_yml(path, bookmarks)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# ブックマークを削除
|
|
301
|
+
# @param path [String] YAMLファイルのパス
|
|
302
|
+
# @param name [String] 削除するブックマーク名
|
|
303
|
+
def remove_bookmark(path, name)
|
|
304
|
+
bookmarks = load_bookmarks_from_yml(path)
|
|
305
|
+
bookmarks.reject! { |b| b[:name] == name }
|
|
306
|
+
save_bookmarks_to_yml(path, bookmarks)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# ========================================
|
|
310
|
+
# config.rb (DSL) の操作
|
|
311
|
+
# ========================================
|
|
312
|
+
|
|
313
|
+
# config.rb を読み込む
|
|
314
|
+
# @param path [String] config.rb のパス
|
|
315
|
+
def load_config_rb(path = CONFIG_RB_PATH)
|
|
316
|
+
return unless File.exist?(path)
|
|
317
|
+
|
|
318
|
+
load path
|
|
319
|
+
rescue StandardError => e
|
|
320
|
+
warn "Failed to load config.rb: #{e.message}"
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# ========================================
|
|
324
|
+
# マイグレーション
|
|
325
|
+
# ========================================
|
|
326
|
+
|
|
327
|
+
# 古い config.yml から新形式にマイグレーション
|
|
328
|
+
# @param old_config_yml [String] 古い config.yml のパス
|
|
329
|
+
# @param script_paths_yml [String] 新しい script_paths.yml のパス
|
|
330
|
+
# @param bookmarks_yml [String] 新しい bookmarks.yml のパス
|
|
331
|
+
def migrate_from_config_yml(old_config_yml, script_paths_yml, bookmarks_yml)
|
|
332
|
+
return unless File.exist?(old_config_yml)
|
|
333
|
+
|
|
334
|
+
old_config = load_yaml_config(old_config_yml)
|
|
335
|
+
|
|
336
|
+
# script_paths のマイグレーション
|
|
337
|
+
if old_config[:script_paths].is_a?(Array) && !old_config[:script_paths].empty?
|
|
338
|
+
save_script_paths(script_paths_yml, old_config[:script_paths])
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# bookmarks のマイグレーション
|
|
342
|
+
if old_config[:bookmarks].is_a?(Array) && !old_config[:bookmarks].empty?
|
|
343
|
+
save_bookmarks_to_yml(bookmarks_yml, old_config[:bookmarks])
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# YAML設定ファイルを読み込む
|
|
348
|
+
# @param path [String] 設定ファイルのパス
|
|
349
|
+
# @return [Hash] 設定内容(シンボルキー)
|
|
350
|
+
def load_yaml_config(path)
|
|
351
|
+
return {} unless File.exist?(path)
|
|
352
|
+
|
|
353
|
+
yaml = YAML.safe_load(File.read(path), symbolize_names: true)
|
|
354
|
+
yaml || {}
|
|
355
|
+
rescue StandardError => e
|
|
356
|
+
warn "Failed to load YAML config: #{e.message}"
|
|
357
|
+
{}
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# YAML設定ファイルにセクションを保存
|
|
361
|
+
# @param path [String] 設定ファイルのパス
|
|
362
|
+
# @param key [Symbol, String] 保存するキー
|
|
363
|
+
# @param value [Object] 保存する値
|
|
364
|
+
def save_yaml_config(path, key, value)
|
|
365
|
+
ensure_config_directory(path)
|
|
366
|
+
|
|
367
|
+
existing = if File.exist?(path)
|
|
368
|
+
YAML.safe_load(File.read(path), symbolize_names: true) || {}
|
|
369
|
+
else
|
|
370
|
+
{}
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
existing[key.to_sym] = value
|
|
374
|
+
File.write(path, YAML.dump(stringify_keys(existing)))
|
|
375
|
+
reload_yaml_config! if path == YAML_CONFIG_PATH
|
|
376
|
+
end
|
|
377
|
+
|
|
182
378
|
private
|
|
183
379
|
|
|
380
|
+
def ensure_config_directory(path)
|
|
381
|
+
dir = File.dirname(path)
|
|
382
|
+
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def stringify_keys(hash)
|
|
386
|
+
hash.transform_keys(&:to_s).transform_values do |value|
|
|
387
|
+
case value
|
|
388
|
+
when Hash
|
|
389
|
+
stringify_keys(value)
|
|
390
|
+
when Array
|
|
391
|
+
value.map { |v| v.is_a?(Hash) ? stringify_keys(v) : v }
|
|
392
|
+
else
|
|
393
|
+
value
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
|
|
184
398
|
def detect_language
|
|
185
399
|
# Only BENIYA_LANG environment variable takes precedence
|
|
186
400
|
# This ensures English is default unless explicitly requested
|
data/lib/rufio/config_loader.rb
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'yaml'
|
|
4
|
+
require 'json'
|
|
4
5
|
require_relative 'config'
|
|
5
6
|
|
|
6
7
|
module Rufio
|
|
7
8
|
class ConfigLoader
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
# 新しいパス定数(Configから取得)
|
|
10
|
+
CONFIG_PATH = Config::CONFIG_RB_PATH
|
|
11
|
+
SCRIPT_PATHS_YML = Config::SCRIPT_PATHS_YML
|
|
12
|
+
BOOKMARKS_YML = Config::BOOKMARKS_YML
|
|
13
|
+
|
|
14
|
+
# 後方互換性のためのパス(非推奨)
|
|
15
|
+
YAML_CONFIG_PATH = Config::YAML_CONFIG_PATH
|
|
16
|
+
LOCAL_YAML_PATH = Config::LOCAL_YAML_PATH
|
|
10
17
|
|
|
11
18
|
class << self
|
|
12
19
|
def load_config
|
|
@@ -19,6 +26,7 @@ module Rufio
|
|
|
19
26
|
|
|
20
27
|
def reload_config!
|
|
21
28
|
@config = nil
|
|
29
|
+
@script_paths = nil
|
|
22
30
|
load_config
|
|
23
31
|
end
|
|
24
32
|
|
|
@@ -40,7 +48,6 @@ module Rufio
|
|
|
40
48
|
|
|
41
49
|
def set_language(lang)
|
|
42
50
|
Config.current_language = lang
|
|
43
|
-
# Update config if it's user-defined
|
|
44
51
|
if @config
|
|
45
52
|
@config[:language] = lang
|
|
46
53
|
end
|
|
@@ -62,12 +69,10 @@ module Rufio
|
|
|
62
69
|
load_config[:command_history_size] || 1000
|
|
63
70
|
end
|
|
64
71
|
|
|
65
|
-
#
|
|
72
|
+
# スクリプトパスの配列を取得(ローカル > ユーザー設定の優先順位でマージ)
|
|
66
73
|
# @return [Array<String>] 展開済みのスクリプトパス
|
|
67
74
|
def script_paths
|
|
68
|
-
|
|
69
|
-
paths = yaml_config[:script_paths] || default_script_paths
|
|
70
|
-
expand_script_paths(paths)
|
|
75
|
+
@script_paths ||= load_merged_script_paths
|
|
71
76
|
end
|
|
72
77
|
|
|
73
78
|
# デフォルトのスクリプトパス
|
|
@@ -83,44 +88,159 @@ module Rufio
|
|
|
83
88
|
paths.map { |p| File.expand_path(p) }
|
|
84
89
|
end
|
|
85
90
|
|
|
86
|
-
#
|
|
91
|
+
# スクリプトパスを追加
|
|
92
|
+
# @param path [String] 追加するパス
|
|
93
|
+
# @return [Boolean] 追加成功したか
|
|
94
|
+
def add_script_path(path)
|
|
95
|
+
expanded = File.expand_path(path)
|
|
96
|
+
current = script_paths
|
|
97
|
+
return false if current.include?(expanded)
|
|
98
|
+
|
|
99
|
+
save_script_paths_to_yaml(current + [expanded])
|
|
100
|
+
@script_paths = nil
|
|
101
|
+
true
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# スクリプトパスを削除
|
|
105
|
+
# @param path [String] 削除するパス
|
|
106
|
+
# @return [Boolean] 削除成功したか
|
|
107
|
+
def remove_script_path(path)
|
|
108
|
+
expanded = File.expand_path(path)
|
|
109
|
+
current = script_paths
|
|
110
|
+
return false unless current.include?(expanded)
|
|
111
|
+
|
|
112
|
+
save_script_paths_to_yaml(current - [expanded])
|
|
113
|
+
@script_paths = nil
|
|
114
|
+
true
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# YAML設定ファイルを読み込む(Config経由)
|
|
87
118
|
# @param path [String, nil] 設定ファイルのパス(nilの場合はデフォルト)
|
|
88
119
|
# @return [Hash] 設定内容
|
|
89
120
|
def load_yaml_config(path = nil)
|
|
90
121
|
config_path = path || YAML_CONFIG_PATH
|
|
91
|
-
|
|
122
|
+
Config.load_yaml_config(config_path)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# ブックマークを読み込む(新形式: bookmarks.yml)
|
|
126
|
+
# @return [Array<Hash>] ブックマークの配列
|
|
127
|
+
def load_bookmarks
|
|
128
|
+
# 新形式を優先
|
|
129
|
+
bookmarks = Config.load_bookmarks_from_yml(BOOKMARKS_YML)
|
|
130
|
+
return bookmarks unless bookmarks.empty?
|
|
131
|
+
|
|
132
|
+
# 後方互換: 古いconfig.ymlから読み込み
|
|
133
|
+
yaml_config = load_yaml_config
|
|
134
|
+
filter_valid_bookmarks(yaml_config[:bookmarks] || [])
|
|
135
|
+
end
|
|
92
136
|
|
|
93
|
-
|
|
94
|
-
|
|
137
|
+
# ブックマークを保存(新形式: bookmarks.yml)
|
|
138
|
+
# @param bookmarks [Array<Hash>] ブックマークの配列
|
|
139
|
+
# @return [Boolean] 保存成功したか
|
|
140
|
+
def save_bookmarks(bookmarks)
|
|
141
|
+
Config.save_bookmarks_to_yml(BOOKMARKS_YML, bookmarks)
|
|
142
|
+
true
|
|
95
143
|
rescue StandardError => e
|
|
96
|
-
warn "Failed to
|
|
97
|
-
|
|
144
|
+
warn "Failed to save bookmarks: #{e.message}"
|
|
145
|
+
false
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# ブックマークストレージを取得
|
|
149
|
+
# @return [YamlBookmarkStorage] ブックマークストレージ
|
|
150
|
+
def bookmark_storage
|
|
151
|
+
@bookmark_storage ||= YamlBookmarkStorage.new(BOOKMARKS_YML)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# 古いconfig.ymlからのマイグレーション
|
|
155
|
+
def migrate_bookmarks_if_needed
|
|
156
|
+
# 新形式が存在する場合はスキップ
|
|
157
|
+
return if File.exist?(BOOKMARKS_YML)
|
|
158
|
+
return unless File.exist?(YAML_CONFIG_PATH)
|
|
159
|
+
|
|
160
|
+
Config.migrate_from_config_yml(YAML_CONFIG_PATH, SCRIPT_PATHS_YML, BOOKMARKS_YML)
|
|
98
161
|
end
|
|
99
162
|
|
|
100
163
|
private
|
|
101
164
|
|
|
165
|
+
# マージされたスクリプトパスを読み込む
|
|
166
|
+
# @return [Array<String>] マージされたスクリプトパス
|
|
167
|
+
def load_merged_script_paths
|
|
168
|
+
paths = []
|
|
169
|
+
seen = Set.new
|
|
170
|
+
|
|
171
|
+
# ローカル設定(優先)
|
|
172
|
+
if File.exist?(LOCAL_YAML_PATH)
|
|
173
|
+
local_config = load_yaml_config(LOCAL_YAML_PATH)
|
|
174
|
+
local_paths = local_config[:script_paths] || []
|
|
175
|
+
add_unique_paths(paths, seen, expand_script_paths(local_paths))
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# 新形式: script_paths.yml から読み込み
|
|
179
|
+
script_paths_from_yml = Config.load_script_paths(SCRIPT_PATHS_YML)
|
|
180
|
+
add_unique_paths(paths, seen, script_paths_from_yml)
|
|
181
|
+
|
|
182
|
+
# 後方互換: 古いconfig.ymlから読み込み
|
|
183
|
+
if paths.empty?
|
|
184
|
+
user_config = load_yaml_config
|
|
185
|
+
user_paths = user_config[:script_paths] || []
|
|
186
|
+
add_unique_paths(paths, seen, expand_script_paths(user_paths))
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# デフォルトパス(何も設定されていない場合)
|
|
190
|
+
if paths.empty?
|
|
191
|
+
add_unique_paths(paths, seen, default_script_paths)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
paths
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# ユニークなパスを追加
|
|
198
|
+
def add_unique_paths(paths, seen, new_paths)
|
|
199
|
+
new_paths.each do |path|
|
|
200
|
+
expanded = File.expand_path(path)
|
|
201
|
+
next if seen.include?(expanded)
|
|
202
|
+
|
|
203
|
+
seen.add(expanded)
|
|
204
|
+
paths << expanded
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# スクリプトパスをYAMLに保存(新形式: script_paths.yml)
|
|
209
|
+
def save_script_paths_to_yaml(paths)
|
|
210
|
+
Config.save_script_paths(SCRIPT_PATHS_YML, paths)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# YAMLファイルにセクションを保存(Config経由)
|
|
214
|
+
def save_to_yaml(key, value)
|
|
215
|
+
Config.save_yaml_config(YAML_CONFIG_PATH, key, value)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def filter_valid_bookmarks(bookmarks)
|
|
219
|
+
return [] unless bookmarks.is_a?(Array)
|
|
220
|
+
|
|
221
|
+
bookmarks.select do |b|
|
|
222
|
+
b.is_a?(Hash) && b[:path] && b[:name]
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
102
226
|
def load_config_file
|
|
103
|
-
# 設定ファイルを実行してグローバル定数を定義
|
|
104
227
|
load CONFIG_PATH
|
|
105
228
|
config = {
|
|
106
|
-
applications:
|
|
107
|
-
colors:
|
|
108
|
-
keybinds:
|
|
229
|
+
applications: safe_const_get(:APPLICATIONS, default_config[:applications]),
|
|
230
|
+
colors: safe_const_get(:COLORS, default_config[:colors]),
|
|
231
|
+
keybinds: safe_const_get(:KEYBINDS, default_config[:keybinds])
|
|
109
232
|
}
|
|
110
233
|
|
|
111
|
-
# Load language setting if defined
|
|
112
234
|
if Object.const_defined?(:LANGUAGE)
|
|
113
235
|
language = Object.const_get(:LANGUAGE)
|
|
114
236
|
config[:language] = language
|
|
115
237
|
Config.current_language = language if Config.available_languages.include?(language.to_s)
|
|
116
238
|
end
|
|
117
239
|
|
|
118
|
-
# Load scripts directory if defined
|
|
119
240
|
if Object.const_defined?(:SCRIPTS_DIR)
|
|
120
241
|
config[:scripts_dir] = Object.const_get(:SCRIPTS_DIR)
|
|
121
242
|
end
|
|
122
243
|
|
|
123
|
-
# Load command history size if defined
|
|
124
244
|
if Object.const_defined?(:COMMAND_HISTORY_SIZE)
|
|
125
245
|
config[:command_history_size] = Object.const_get(:COMMAND_HISTORY_SIZE)
|
|
126
246
|
end
|
|
@@ -132,6 +252,10 @@ module Rufio
|
|
|
132
252
|
default_config
|
|
133
253
|
end
|
|
134
254
|
|
|
255
|
+
def safe_const_get(name, default)
|
|
256
|
+
Object.const_defined?(name) ? Object.const_get(name) : default
|
|
257
|
+
end
|
|
258
|
+
|
|
135
259
|
def default_config
|
|
136
260
|
{
|
|
137
261
|
applications: {
|
|
@@ -143,11 +267,11 @@ module Rufio
|
|
|
143
267
|
:default => 'open'
|
|
144
268
|
},
|
|
145
269
|
colors: {
|
|
146
|
-
directory: { hsl: [220, 80, 60] },
|
|
147
|
-
file: { hsl: [0, 0, 90] },
|
|
148
|
-
executable: { hsl: [120, 70, 50] },
|
|
149
|
-
selected: { hsl: [50, 90, 70] },
|
|
150
|
-
preview: { hsl: [180, 60, 65] }
|
|
270
|
+
directory: { hsl: [220, 80, 60] },
|
|
271
|
+
file: { hsl: [0, 0, 90] },
|
|
272
|
+
executable: { hsl: [120, 70, 50] },
|
|
273
|
+
selected: { hsl: [50, 90, 70] },
|
|
274
|
+
preview: { hsl: [180, 60, 65] }
|
|
151
275
|
},
|
|
152
276
|
keybinds: {
|
|
153
277
|
quit: %w[q ESC],
|
|
@@ -166,4 +290,3 @@ module Rufio
|
|
|
166
290
|
end
|
|
167
291
|
end
|
|
168
292
|
end
|
|
169
|
-
|