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
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'task_status'
|
|
4
|
+
|
|
5
|
+
module Rufio
|
|
6
|
+
# 複数のジョブを管理するクラス
|
|
7
|
+
# ジョブの追加、状態追跡、通知連携を行う
|
|
8
|
+
class JobManager
|
|
9
|
+
attr_reader :jobs
|
|
10
|
+
|
|
11
|
+
def initialize(notification_manager: nil)
|
|
12
|
+
@jobs = []
|
|
13
|
+
@notification_manager = notification_manager
|
|
14
|
+
@next_id = 1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# ジョブを追加
|
|
18
|
+
# @param name [String] ジョブ名
|
|
19
|
+
# @param path [String] 実行ディレクトリ
|
|
20
|
+
# @param command [String] 実行コマンド
|
|
21
|
+
# @return [TaskStatus] 作成されたジョブ
|
|
22
|
+
def add_job(name:, path:, command:)
|
|
23
|
+
job = TaskStatus.new(
|
|
24
|
+
id: @next_id,
|
|
25
|
+
name: name,
|
|
26
|
+
path: path
|
|
27
|
+
)
|
|
28
|
+
# commandを保存(TaskStatusに追加)
|
|
29
|
+
job.instance_variable_set(:@command, command)
|
|
30
|
+
job.define_singleton_method(:command) { @command }
|
|
31
|
+
|
|
32
|
+
@jobs << job
|
|
33
|
+
@next_id += 1
|
|
34
|
+
job
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# IDでジョブを検索
|
|
38
|
+
# @param id [Integer] ジョブID
|
|
39
|
+
# @return [TaskStatus, nil]
|
|
40
|
+
def find_job(id)
|
|
41
|
+
@jobs.find { |job| job.id == id }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# ジョブ数を取得
|
|
45
|
+
# @return [Integer]
|
|
46
|
+
def job_count
|
|
47
|
+
@jobs.size
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# 実行中のジョブ数
|
|
51
|
+
# @return [Integer]
|
|
52
|
+
def running_count
|
|
53
|
+
@jobs.count(&:running?)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# 完了したジョブ数
|
|
57
|
+
# @return [Integer]
|
|
58
|
+
def completed_count
|
|
59
|
+
@jobs.count(&:completed?)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# 失敗したジョブ数
|
|
63
|
+
# @return [Integer]
|
|
64
|
+
def failed_count
|
|
65
|
+
@jobs.count(&:failed?)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# ステータスサマリーを取得
|
|
69
|
+
# @return [Hash] { total:, running:, done:, failed: }
|
|
70
|
+
def status_summary
|
|
71
|
+
{
|
|
72
|
+
total: @jobs.size,
|
|
73
|
+
running: running_count,
|
|
74
|
+
done: completed_count,
|
|
75
|
+
failed: failed_count
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# ジョブをキャンセル
|
|
80
|
+
# @param id [Integer] ジョブID
|
|
81
|
+
# @return [Boolean] キャンセル成功かどうか
|
|
82
|
+
def cancel_job(id)
|
|
83
|
+
job = find_job(id)
|
|
84
|
+
return false unless job
|
|
85
|
+
|
|
86
|
+
job.cancel
|
|
87
|
+
true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# 完了したジョブをクリア
|
|
91
|
+
def clear_completed
|
|
92
|
+
@jobs.reject! { |job| job.completed? || job.cancelled? }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# ステータスバー用のテキストを生成
|
|
96
|
+
# @return [String] "3 jobs: 2 running, 1 done" のような形式
|
|
97
|
+
def status_bar_text
|
|
98
|
+
summary = status_summary
|
|
99
|
+
"#{summary[:total]} jobs: #{summary[:running]} running, #{summary[:done]} done"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# ジョブがあるかどうか
|
|
103
|
+
# @return [Boolean]
|
|
104
|
+
def has_jobs?
|
|
105
|
+
!@jobs.empty?
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# 実行中のジョブがあるかどうか
|
|
109
|
+
# @return [Boolean]
|
|
110
|
+
def any_running?
|
|
111
|
+
@jobs.any?(&:running?)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# ジョブ完了時の通知を送信(NotificationManagerと連携)
|
|
115
|
+
# @param job [TaskStatus] 完了したジョブ
|
|
116
|
+
def notify_completion(job)
|
|
117
|
+
return unless @notification_manager
|
|
118
|
+
|
|
119
|
+
type = job.completed? ? :success : :error
|
|
120
|
+
@notification_manager.add(
|
|
121
|
+
job.name,
|
|
122
|
+
type,
|
|
123
|
+
duration: job.duration || 0,
|
|
124
|
+
exit_code: job.exit_code
|
|
125
|
+
)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rufio
|
|
4
|
+
# ジョブモードのUI管理クラス
|
|
5
|
+
# ジョブ一覧の表示、選択、操作を行う
|
|
6
|
+
class JobMode
|
|
7
|
+
attr_reader :selected_index
|
|
8
|
+
|
|
9
|
+
def initialize(job_manager:)
|
|
10
|
+
@job_manager = job_manager
|
|
11
|
+
@active = false
|
|
12
|
+
@selected_index = 0
|
|
13
|
+
@log_mode = false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# ジョブモードを有効化
|
|
17
|
+
def activate
|
|
18
|
+
@active = true
|
|
19
|
+
@selected_index = 0
|
|
20
|
+
@log_mode = false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# ジョブモードを無効化
|
|
24
|
+
def deactivate
|
|
25
|
+
@active = false
|
|
26
|
+
@log_mode = false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# ジョブモードが有効かどうか
|
|
30
|
+
# @return [Boolean]
|
|
31
|
+
def active?
|
|
32
|
+
@active
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# ログモードが有効かどうか
|
|
36
|
+
# @return [Boolean]
|
|
37
|
+
def log_mode?
|
|
38
|
+
@log_mode
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# ログモードに入る
|
|
42
|
+
def enter_log_mode
|
|
43
|
+
@log_mode = true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# ログモードを終了
|
|
47
|
+
def exit_log_mode
|
|
48
|
+
@log_mode = false
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# 下に移動
|
|
52
|
+
def move_down
|
|
53
|
+
max_index = [@job_manager.job_count - 1, 0].max
|
|
54
|
+
@selected_index = [@selected_index + 1, max_index].min
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# 上に移動
|
|
58
|
+
def move_up
|
|
59
|
+
@selected_index = [@selected_index - 1, 0].max
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# 先頭に移動
|
|
63
|
+
def move_to_top
|
|
64
|
+
@selected_index = 0
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# 末尾に移動
|
|
68
|
+
def move_to_bottom
|
|
69
|
+
@selected_index = [@job_manager.job_count - 1, 0].max
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# 選択中のジョブを取得
|
|
73
|
+
# @return [TaskStatus, nil]
|
|
74
|
+
def selected_job
|
|
75
|
+
return nil if @job_manager.jobs.empty?
|
|
76
|
+
|
|
77
|
+
@job_manager.jobs[@selected_index]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# 選択中のジョブをキャンセル
|
|
81
|
+
# @return [Boolean]
|
|
82
|
+
def cancel_selected_job
|
|
83
|
+
job = selected_job
|
|
84
|
+
return false unless job
|
|
85
|
+
|
|
86
|
+
@job_manager.cancel_job(job.id)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# キー入力を処理
|
|
90
|
+
# @param key [String] 入力されたキー
|
|
91
|
+
# @return [Boolean, Symbol] 処理結果
|
|
92
|
+
def handle_key(key)
|
|
93
|
+
# ログモード中の処理
|
|
94
|
+
if @log_mode
|
|
95
|
+
return handle_log_mode_key(key)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
case key
|
|
99
|
+
when 'j'
|
|
100
|
+
move_down
|
|
101
|
+
true
|
|
102
|
+
when 'k'
|
|
103
|
+
move_up
|
|
104
|
+
true
|
|
105
|
+
when 'g'
|
|
106
|
+
move_to_top
|
|
107
|
+
true
|
|
108
|
+
when 'G'
|
|
109
|
+
move_to_bottom
|
|
110
|
+
true
|
|
111
|
+
when 'x'
|
|
112
|
+
cancel_selected_job
|
|
113
|
+
true
|
|
114
|
+
when ' ' # Space
|
|
115
|
+
enter_log_mode if selected_job
|
|
116
|
+
:show_log
|
|
117
|
+
when "\e" # Escape
|
|
118
|
+
deactivate
|
|
119
|
+
:exit
|
|
120
|
+
else
|
|
121
|
+
false
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
private
|
|
126
|
+
|
|
127
|
+
# ログモード中のキー処理
|
|
128
|
+
# @param key [String] 入力されたキー
|
|
129
|
+
# @return [Boolean, Symbol]
|
|
130
|
+
def handle_log_mode_key(key)
|
|
131
|
+
case key
|
|
132
|
+
when "\e" # Escape
|
|
133
|
+
exit_log_mode
|
|
134
|
+
true
|
|
135
|
+
when 'j'
|
|
136
|
+
# ログのスクロール(将来実装)
|
|
137
|
+
true
|
|
138
|
+
when 'k'
|
|
139
|
+
# ログのスクロール(将来実装)
|
|
140
|
+
true
|
|
141
|
+
else
|
|
142
|
+
false
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|