rufio 0.41.0 → 0.60.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 +26 -0
- data/README.md +96 -194
- data/bin/rufio +0 -3
- data/docs/CHANGELOG_v0.50.0.md +128 -0
- data/examples/config.yml +8 -0
- data/lib/rufio/builtin_commands.rb +34 -0
- data/lib/rufio/command_completion.rb +20 -5
- data/lib/rufio/command_mode.rb +157 -46
- data/lib/rufio/config_loader.rb +37 -0
- data/lib/rufio/dsl_command.rb +120 -0
- data/lib/rufio/dsl_command_loader.rb +177 -0
- data/lib/rufio/interpreter_resolver.rb +79 -0
- data/lib/rufio/job_manager.rb +128 -0
- data/lib/rufio/job_mode.rb +146 -0
- data/lib/rufio/keybind_handler.rb +243 -232
- data/lib/rufio/notification_manager.rb +77 -0
- data/lib/rufio/script_config_loader.rb +101 -0
- data/lib/rufio/script_executor.rb +253 -0
- data/lib/rufio/script_path_manager.rb +386 -0
- data/lib/rufio/script_runner.rb +216 -0
- data/lib/rufio/task_status.rb +118 -0
- data/lib/rufio/terminal_ui.rb +181 -495
- data/lib/rufio/version.rb +1 -1
- data/lib/rufio.rb +15 -11
- data/scripts/test_jobs/build_simulation.sh +29 -0
- data/scripts/test_jobs/deploy_simulation.sh +37 -0
- data/scripts/test_jobs/quick.sh +11 -0
- data/scripts/test_jobs/random_result.sh +23 -0
- data/scripts/test_jobs/slow_fail.sh +10 -0
- data/scripts/test_jobs/slow_success.sh +10 -0
- data/scripts/test_jobs/very_slow.sh +19 -0
- metadata +23 -13
- data/docs/file-preview-optimization-analysis.md +0 -759
- data/docs/file-preview-performance-issue-FIXED.md +0 -547
- data/lib/rufio/plugin.rb +0 -89
- data/lib/rufio/plugin_config.rb +0 -59
- data/lib/rufio/plugin_manager.rb +0 -84
- data/lib/rufio/plugins/file_operations.rb +0 -44
- data/lib/rufio/plugins/hello.rb +0 -30
- data/lib/rufio/plugins/stop.rb +0 -32
- data/lib/rufio/project_command.rb +0 -147
- data/lib/rufio/project_log.rb +0 -68
- data/lib/rufio/project_mode.rb +0 -58
data/lib/rufio/plugin_manager.rb
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rufio
|
|
4
|
-
# プラグインを管理するクラス
|
|
5
|
-
class PluginManager
|
|
6
|
-
class << self
|
|
7
|
-
# 登録済みプラグインクラスのリスト
|
|
8
|
-
def plugins
|
|
9
|
-
@plugins ||= []
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# プラグインを登録する
|
|
13
|
-
def register(plugin_class)
|
|
14
|
-
@plugins ||= []
|
|
15
|
-
@plugins << plugin_class unless @plugins.include?(plugin_class)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# 全プラグインを読み込む(本体同梱 + ユーザープラグイン)
|
|
19
|
-
def load_all
|
|
20
|
-
load_builtin_plugins
|
|
21
|
-
load_user_plugins
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# 有効なプラグインインスタンスのリストを取得
|
|
25
|
-
def enabled_plugins
|
|
26
|
-
return @enabled_plugins if @enabled_plugins
|
|
27
|
-
|
|
28
|
-
@enabled_plugins = []
|
|
29
|
-
|
|
30
|
-
plugins.each do |plugin_class|
|
|
31
|
-
# プラグイン名を取得(クラス名から推測)
|
|
32
|
-
plugin_name = plugin_class.name.split('::').last
|
|
33
|
-
|
|
34
|
-
# PluginConfigで有効かチェック
|
|
35
|
-
next unless PluginConfig.plugin_enabled?(plugin_name)
|
|
36
|
-
|
|
37
|
-
# プラグインのインスタンスを作成
|
|
38
|
-
begin
|
|
39
|
-
plugin_instance = plugin_class.new
|
|
40
|
-
@enabled_plugins << plugin_instance
|
|
41
|
-
rescue Plugin::DependencyError => e
|
|
42
|
-
warn "⚠️ #{e.message}"
|
|
43
|
-
# プラグインは無効化されるが、rufioは起動継続
|
|
44
|
-
rescue StandardError => e
|
|
45
|
-
warn "⚠️ Failed to load plugin #{plugin_name}: #{e.message}"
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
@enabled_plugins
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
private
|
|
53
|
-
|
|
54
|
-
# 本体同梱プラグインを読み込む
|
|
55
|
-
def load_builtin_plugins
|
|
56
|
-
# plugin_manager.rbは/lib/rufio/にあるので、pluginsディレクトリは同じディレクトリ内
|
|
57
|
-
builtin_plugins_dir = File.join(__dir__, 'plugins')
|
|
58
|
-
return unless Dir.exist?(builtin_plugins_dir)
|
|
59
|
-
|
|
60
|
-
Dir.glob(File.join(builtin_plugins_dir, '*.rb')).sort.each do |file|
|
|
61
|
-
begin
|
|
62
|
-
require file
|
|
63
|
-
rescue StandardError => e
|
|
64
|
-
warn "⚠️ Failed to load builtin plugin #{File.basename(file)}: #{e.message}"
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# ユーザープラグインを読み込む
|
|
70
|
-
def load_user_plugins
|
|
71
|
-
user_plugins_dir = File.expand_path('~/.rufio/plugins')
|
|
72
|
-
return unless Dir.exist?(user_plugins_dir)
|
|
73
|
-
|
|
74
|
-
Dir.glob(File.join(user_plugins_dir, '*.rb')).sort.each do |file|
|
|
75
|
-
begin
|
|
76
|
-
require file
|
|
77
|
-
rescue SyntaxError, StandardError => e
|
|
78
|
-
warn "⚠️ Failed to load user plugin #{File.basename(file)}: #{e.message}"
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
end
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rufio
|
|
4
|
-
module Plugins
|
|
5
|
-
# 基本的なファイル操作を提供するプラグイン
|
|
6
|
-
class FileOperations < Plugin
|
|
7
|
-
def name
|
|
8
|
-
"FileOperations"
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def description
|
|
12
|
-
"基本的なファイル操作(コピー、移動、削除)"
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def commands
|
|
16
|
-
{
|
|
17
|
-
copy: method(:copy),
|
|
18
|
-
move: method(:move),
|
|
19
|
-
delete: method(:delete)
|
|
20
|
-
}
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
# ファイルコピー(スタブ実装)
|
|
26
|
-
def copy
|
|
27
|
-
# 実装は将来追加
|
|
28
|
-
nil
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# ファイル移動(スタブ実装)
|
|
32
|
-
def move
|
|
33
|
-
# 実装は将来追加
|
|
34
|
-
nil
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# ファイル削除(スタブ実装)
|
|
38
|
-
def delete
|
|
39
|
-
# 実装は将来追加
|
|
40
|
-
nil
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
data/lib/rufio/plugins/hello.rb
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rufio
|
|
4
|
-
module Plugins
|
|
5
|
-
# Hello コマンドを提供するプラグイン
|
|
6
|
-
# Rubyコードで挨拶を返す簡単な例
|
|
7
|
-
class Hello < Plugin
|
|
8
|
-
def name
|
|
9
|
-
"Hello"
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def description
|
|
13
|
-
"Rubyで実装された挨拶コマンドの例"
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def commands
|
|
17
|
-
{
|
|
18
|
-
hello: method(:say_hello)
|
|
19
|
-
}
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
# 挨拶メッセージを返す
|
|
25
|
-
def say_hello
|
|
26
|
-
"Hello, World! 🌍\n\nこのコマンドはRubyで実装されています。"
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
data/lib/rufio/plugins/stop.rb
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rufio
|
|
4
|
-
module Plugins
|
|
5
|
-
# Hello コマンドを提供するプラグイン
|
|
6
|
-
# Rubyコードで挨拶を返す簡単な例
|
|
7
|
-
class Stop < Plugin
|
|
8
|
-
def name
|
|
9
|
-
'Stop'
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def description
|
|
13
|
-
'Rubyで実装された挨拶コマンドの例'
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def commands
|
|
17
|
-
{
|
|
18
|
-
stop: method(:say_hello)
|
|
19
|
-
}
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
# 挨拶メッセージを返す
|
|
25
|
-
def say_hello
|
|
26
|
-
'stop 5seconds'
|
|
27
|
-
sleep 5
|
|
28
|
-
'done'
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'open3'
|
|
4
|
-
require 'fileutils'
|
|
5
|
-
require 'shellwords'
|
|
6
|
-
|
|
7
|
-
module Rufio
|
|
8
|
-
# プロジェクトコマンド - 登録されたコマンドを実行する
|
|
9
|
-
class ProjectCommand
|
|
10
|
-
def initialize(log_dir, scripts_dir = nil)
|
|
11
|
-
@log_dir = log_dir
|
|
12
|
-
@scripts_dir = scripts_dir || ConfigLoader.scripts_dir
|
|
13
|
-
@registered_commands = {}
|
|
14
|
-
|
|
15
|
-
# スクリプトディレクトリが存在しなければ作成
|
|
16
|
-
ensure_scripts_directory
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# コマンドを実行する
|
|
20
|
-
# @param command [String] 実行するコマンド
|
|
21
|
-
# @param working_dir [String] 作業ディレクトリ
|
|
22
|
-
# @return [Hash] 実行結果 { success: Boolean, output: String, error: String }
|
|
23
|
-
def execute(command, working_dir)
|
|
24
|
-
begin
|
|
25
|
-
stdout, stderr, status = Open3.capture3(command, chdir: working_dir)
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
success: status.success?,
|
|
29
|
-
output: stdout,
|
|
30
|
-
error: stderr
|
|
31
|
-
}
|
|
32
|
-
rescue StandardError => e
|
|
33
|
-
{
|
|
34
|
-
success: false,
|
|
35
|
-
output: '',
|
|
36
|
-
error: "Command not found or failed to execute: #{e.message}"
|
|
37
|
-
}
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# 登録されたコマンドを実行する
|
|
42
|
-
# @param command_name [String] コマンド名
|
|
43
|
-
# @param working_dir [String] 作業ディレクトリ
|
|
44
|
-
# @return [Hash] 実行結果
|
|
45
|
-
def execute_registered(command_name, working_dir)
|
|
46
|
-
unless @registered_commands.key?(command_name)
|
|
47
|
-
return {
|
|
48
|
-
success: false,
|
|
49
|
-
output: '',
|
|
50
|
-
error: "Command '#{command_name}' not found in registered commands"
|
|
51
|
-
}
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
command = @registered_commands[command_name]
|
|
55
|
-
execute(command, working_dir)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# コマンドを登録する
|
|
59
|
-
# @param name [String] コマンド名
|
|
60
|
-
# @param command [String] コマンド文字列
|
|
61
|
-
def register(name, command)
|
|
62
|
-
@registered_commands[name] = command
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# 登録されているコマンドの一覧を取得
|
|
66
|
-
# @return [Array<String>] コマンド名の配列
|
|
67
|
-
def list_registered_commands
|
|
68
|
-
@registered_commands.keys
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# 左画面用の表示データを取得
|
|
72
|
-
# @return [Array<String>] コマンド名の配列
|
|
73
|
-
def get_left_pane_data
|
|
74
|
-
@registered_commands.keys.map.with_index(1) do |name, index|
|
|
75
|
-
"#{index}. #{name}"
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# スクリプトディレクトリ内のRubyスクリプト一覧を取得
|
|
80
|
-
# @return [Array<String>] スクリプトファイル名の配列
|
|
81
|
-
def list_scripts
|
|
82
|
-
return [] unless Dir.exist?(@scripts_dir)
|
|
83
|
-
|
|
84
|
-
Dir.glob(File.join(@scripts_dir, '*.rb')).map do |path|
|
|
85
|
-
File.basename(path)
|
|
86
|
-
end.sort
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# スクリプトを実行する
|
|
90
|
-
# @param script_name [String] スクリプトファイル名
|
|
91
|
-
# @param working_dir [String] 作業ディレクトリ
|
|
92
|
-
# @return [Hash] 実行結果
|
|
93
|
-
def execute_script(script_name, working_dir)
|
|
94
|
-
script_path = File.join(@scripts_dir, script_name)
|
|
95
|
-
|
|
96
|
-
unless File.exist?(script_path)
|
|
97
|
-
return {
|
|
98
|
-
success: false,
|
|
99
|
-
output: '',
|
|
100
|
-
error: "Script not found: #{script_name}"
|
|
101
|
-
}
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Rubyスクリプトとして実行
|
|
105
|
-
execute("ruby #{script_path.shellescape}", working_dir)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
# スクリプトディレクトリのパスを取得
|
|
109
|
-
# @return [String] スクリプトディレクトリのパス
|
|
110
|
-
def scripts_dir
|
|
111
|
-
@scripts_dir
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
private
|
|
115
|
-
|
|
116
|
-
# スクリプトディレクトリを確保する
|
|
117
|
-
def ensure_scripts_directory
|
|
118
|
-
return if Dir.exist?(@scripts_dir)
|
|
119
|
-
|
|
120
|
-
FileUtils.mkdir_p(@scripts_dir)
|
|
121
|
-
|
|
122
|
-
# サンプルスクリプトを作成
|
|
123
|
-
create_sample_script
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# サンプルスクリプトを作成
|
|
127
|
-
def create_sample_script
|
|
128
|
-
sample_script = File.join(@scripts_dir, 'hello.rb')
|
|
129
|
-
return if File.exist?(sample_script)
|
|
130
|
-
|
|
131
|
-
File.write(sample_script, <<~RUBY)
|
|
132
|
-
#!/usr/bin/env ruby
|
|
133
|
-
# Sample script for rufio project mode
|
|
134
|
-
# This script will be executed in the selected project directory
|
|
135
|
-
|
|
136
|
-
puts "Hello from rufio script!"
|
|
137
|
-
puts "Current directory: \#{Dir.pwd}"
|
|
138
|
-
puts "Files in directory:"
|
|
139
|
-
Dir.glob('*').each do |file|
|
|
140
|
-
puts " - \#{file}"
|
|
141
|
-
end
|
|
142
|
-
RUBY
|
|
143
|
-
|
|
144
|
-
File.chmod(0755, sample_script)
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
end
|
data/lib/rufio/project_log.rb
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'fileutils'
|
|
4
|
-
require 'time'
|
|
5
|
-
|
|
6
|
-
module Rufio
|
|
7
|
-
# プロジェクトログ - コマンド実行ログを管理する
|
|
8
|
-
class ProjectLog
|
|
9
|
-
def initialize(log_dir)
|
|
10
|
-
@log_dir = log_dir
|
|
11
|
-
FileUtils.mkdir_p(@log_dir) unless Dir.exist?(@log_dir)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# ログを保存する
|
|
15
|
-
# @param project_name [String] プロジェクト名
|
|
16
|
-
# @param command [String] 実行したコマンド
|
|
17
|
-
# @param output [String] コマンドの出力
|
|
18
|
-
# @return [String] 保存したログファイルのパス
|
|
19
|
-
def save(project_name, command, output)
|
|
20
|
-
timestamp = Time.now.strftime('%Y%m%d_%H%M%S')
|
|
21
|
-
log_filename = "#{project_name}_#{timestamp}.log"
|
|
22
|
-
log_path = File.join(@log_dir, log_filename)
|
|
23
|
-
|
|
24
|
-
log_content = <<~LOG
|
|
25
|
-
Project: #{project_name}
|
|
26
|
-
Command: #{command}
|
|
27
|
-
Timestamp: #{Time.now}
|
|
28
|
-
|
|
29
|
-
Output:
|
|
30
|
-
#{output}
|
|
31
|
-
LOG
|
|
32
|
-
|
|
33
|
-
File.write(log_path, log_content)
|
|
34
|
-
log_path
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# ログディレクトリに移動する
|
|
38
|
-
# @return [Hash] ログディレクトリ情報
|
|
39
|
-
def navigate_to_log_dir
|
|
40
|
-
{
|
|
41
|
-
path: @log_dir
|
|
42
|
-
}
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# ログファイルの一覧を取得(新しい順)
|
|
46
|
-
# @return [Array<String>] ログファイル名の配列
|
|
47
|
-
def list_log_files
|
|
48
|
-
log_files = Dir.glob(File.join(@log_dir, '*.log'))
|
|
49
|
-
|
|
50
|
-
# ファイルの更新時刻でソート(新しい順)
|
|
51
|
-
log_files.sort_by { |f| -File.mtime(f).to_i }
|
|
52
|
-
.map { |f| File.basename(f) }
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# ログファイルのプレビューを取得
|
|
56
|
-
# @param filename [String] ログファイル名
|
|
57
|
-
# @return [String] ログファイルの内容
|
|
58
|
-
def preview(filename)
|
|
59
|
-
log_path = File.join(@log_dir, filename)
|
|
60
|
-
|
|
61
|
-
return '' unless File.exist?(log_path)
|
|
62
|
-
|
|
63
|
-
File.read(log_path)
|
|
64
|
-
rescue StandardError
|
|
65
|
-
''
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
data/lib/rufio/project_mode.rb
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Rufio
|
|
4
|
-
# プロジェクトモード - ブックマークしたプロジェクトの管理とコマンド実行
|
|
5
|
-
class ProjectMode
|
|
6
|
-
attr_reader :selected_path, :selected_name
|
|
7
|
-
|
|
8
|
-
def initialize(bookmark, log_dir)
|
|
9
|
-
@bookmark = bookmark
|
|
10
|
-
@log_dir = log_dir
|
|
11
|
-
@active = false
|
|
12
|
-
@selected_path = nil
|
|
13
|
-
@selected_name = nil
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# プロジェクトモードをアクティブにする
|
|
17
|
-
def activate
|
|
18
|
-
@active = true
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# プロジェクトモードを非アクティブにする
|
|
22
|
-
def deactivate
|
|
23
|
-
@active = false
|
|
24
|
-
@selected_path = nil
|
|
25
|
-
@selected_name = nil
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# プロジェクトモードがアクティブかどうか
|
|
29
|
-
def active?
|
|
30
|
-
@active
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# ブックマーク一覧を取得
|
|
34
|
-
def list_bookmarks
|
|
35
|
-
return [] unless @active
|
|
36
|
-
|
|
37
|
-
@bookmark.list
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# ブックマークを番号で選択
|
|
41
|
-
def select_bookmark(number)
|
|
42
|
-
return false unless @active
|
|
43
|
-
|
|
44
|
-
bookmark = @bookmark.find_by_number(number)
|
|
45
|
-
return false unless bookmark
|
|
46
|
-
|
|
47
|
-
@selected_path = bookmark[:path]
|
|
48
|
-
@selected_name = bookmark[:name]
|
|
49
|
-
true
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# 選択をクリア
|
|
53
|
-
def clear_selection
|
|
54
|
-
@selected_path = nil
|
|
55
|
-
@selected_name = nil
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|