rufio 0.65.0 → 0.71.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 +48 -0
- data/README.md +14 -1
- data/info/help.md +68 -21
- data/info/keybindings.md +39 -23
- data/info/welcome.md +27 -11
- data/lib/rufio/command_completion.rb +23 -6
- data/lib/rufio/command_mode.rb +212 -14
- data/lib/rufio/keybind_handler.rb +8 -3
- data/lib/rufio/local_script_scanner.rb +92 -0
- data/lib/rufio/rakefile_parser.rb +77 -0
- data/lib/rufio/script_runner.rb +21 -4
- data/lib/rufio/selection_manager.rb +6 -0
- data/lib/rufio/terminal_ui.rb +16 -5
- data/lib/rufio/version.rb +1 -1
- data/lib/rufio.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b269821deb0be4866afdc75e58a1369de3448324cee49e6c4f7e68febbae9fff
|
|
4
|
+
data.tar.gz: 835570061c06d6a5adc439d2dfb67c62313fccf101cdb6fb068976f5d72d5607
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8ba615e62db5874737085807f29825e92c3447a094aeb7349c77b8d0adab4e39fc2ce4bfe40fa53f354b23057e81a29077a7177a6f31379cf140ff876bd2bbc7
|
|
7
|
+
data.tar.gz: b8ac577e995fb0a1cbc7776246f3443e2d137914a84fa94b02b013a3bca5f9124b30b42b03cb6fedbe8bb5d33fcadfbea4d9622023b446df5abb5288871bf978
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.71.0] - 2026-02-16
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Script Arguments**: Pass arguments to scripts via command mode (e.g., `@retag.sh v0.70.0`)
|
|
14
|
+
- Supports both ScriptRunner and LocalScriptScanner
|
|
15
|
+
- **Script/Rake Execution Logging**: Log execution results of `@script` and `rake:task` commands to CommandLogger
|
|
16
|
+
- Covers both synchronous and background execution
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- **Selection across directories**: Clear selection state when navigating to a different directory
|
|
20
|
+
- **Help/Log viewer entries**: Exclude `..` entry in help mode and log viewer mode
|
|
21
|
+
|
|
22
|
+
## [0.70.0] - 2026-02-14
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- **Local Script Scanning**: Automatically detect script files (`.sh`, `.rb`, `.py`, `.pl`, `.js`, `.ts`, `.ps1`) in the currently browsed directory
|
|
26
|
+
- Displayed and executable as `@script.sh` format in command mode
|
|
27
|
+
- Falls back to local scripts when not found in registered script paths
|
|
28
|
+
- Cached per directory with automatic invalidation on directory change
|
|
29
|
+
- **Rakefile Task Execution**: Parse Rakefile to extract task names and execute them
|
|
30
|
+
- `rake:task_name` format in command mode (e.g., `:rake:test`, `:rake:build`)
|
|
31
|
+
- Supports `Rakefile`, `rakefile`, `Rakefile.rb`
|
|
32
|
+
- Recognizes symbol, string, and hash-style task definitions
|
|
33
|
+
- **Rake Task Tab Completion**: Full Tab completion support for rake tasks
|
|
34
|
+
- `rake:` prefix triggers task-specific completion
|
|
35
|
+
- Partial input (`r`, `rak`, `rake`) also suggests matching `rake:xxx` commands
|
|
36
|
+
- Common prefix completion (e.g., `rak` → `rake:`)
|
|
37
|
+
- **New classes**: `LocalScriptScanner`, `RakefileParser`
|
|
38
|
+
- **New tests**: `test_local_script_scanner.rb` (16 tests), `test_rakefile_parser.rb` (19 tests), `test_command_mode_local.rb` (11 tests), `test_command_completion_local.rb` (13 tests), `test_overlay_clearing.rb` (2 tests)
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
- **Floating window border remnants**: Fixed old dialog borders remaining when switching between overlay dialogs (e.g., command prompt → completion list)
|
|
42
|
+
- Added `@screen.clear_overlay` in `show_overlay_dialog` before drawing new dialog
|
|
43
|
+
- Added overlay clearing before each frame's `draw_command_mode_to_overlay` in main loop
|
|
44
|
+
- **CommandResult display artifact**: Fixed command window top border remaining visible when showing command execution results
|
|
45
|
+
- Root cause: `execute_command` called legacy `draw_screen` (direct terminal print) which has a coordinate offset from the overlay-based rendering system
|
|
46
|
+
- Removed `draw_screen` call from `execute_command`, letting the main loop handle re-rendering via the buffer system
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
- **CommandMode**: Added `update_browsing_directory` method, `rake:` routing, local script fallback
|
|
50
|
+
- **CommandCompletion**: Added rake task and local script completion integration
|
|
51
|
+
- **TerminalUI**: `activate_command_mode` now notifies `CommandMode` of current browsing directory
|
|
52
|
+
|
|
53
|
+
### Technical Details
|
|
54
|
+
- **New files**: `lib/rufio/local_script_scanner.rb`, `lib/rufio/rakefile_parser.rb`, 5 test files
|
|
55
|
+
- **Modified files**: `lib/rufio.rb`, `lib/rufio/command_mode.rb`, `lib/rufio/command_completion.rb`, `lib/rufio/terminal_ui.rb`
|
|
56
|
+
- **Test coverage**: 821 runs, 2816 assertions, 0 failures
|
|
57
|
+
|
|
10
58
|
## [0.65.0] - 2026-02-14
|
|
11
59
|
|
|
12
60
|
### Changed
|
data/README.md
CHANGED
|
@@ -145,8 +145,18 @@ Press `:` to enter command mode and execute various commands.
|
|
|
145
145
|
```
|
|
146
146
|
:@build # @ prefix triggers script completion
|
|
147
147
|
:@deploy.rb # Execute registered script
|
|
148
|
+
:@local.sh # Scripts in current directory are also available
|
|
148
149
|
```
|
|
149
150
|
|
|
151
|
+
### Rake Task Execution
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
:rake:test # Execute rake task
|
|
155
|
+
:rake:build # Tab completion supported
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Rakefile in the current directory is automatically parsed. Supports `Rakefile`, `rakefile`, `Rakefile.rb`.
|
|
159
|
+
|
|
150
160
|
### Shell Commands
|
|
151
161
|
|
|
152
162
|
```
|
|
@@ -182,8 +192,11 @@ Press `B` → `3` to open the script path management menu:
|
|
|
182
192
|
|-----------|----------|
|
|
183
193
|
| `.rb` | Ruby |
|
|
184
194
|
| `.py` | Python |
|
|
185
|
-
| `.ps1` | PowerShell |
|
|
186
195
|
| `.sh` | Shell (bash/zsh) |
|
|
196
|
+
| `.js` | JavaScript (Node.js) |
|
|
197
|
+
| `.ts` | TypeScript (ts-node/deno) |
|
|
198
|
+
| `.pl` | Perl |
|
|
199
|
+
| `.ps1` | PowerShell |
|
|
187
200
|
|
|
188
201
|
## DSL Commands
|
|
189
202
|
|
data/info/help.md
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
# rufio Help
|
|
2
2
|
|
|
3
|
-
**rufio** is a terminal-based file manager
|
|
3
|
+
**rufio** is a terminal-based file manager and tool runtime environment.
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
7
7
|
- [Basic Operations](#basic-operations)
|
|
8
|
-
- [Navigation](#navigation)
|
|
9
8
|
- [File Operations](#file-operations)
|
|
10
9
|
- [File Selection & Bulk Operations](#file-selection--bulk-operations)
|
|
11
10
|
- [Filtering & Search](#filtering--search)
|
|
12
|
-
- [Bookmarks](#bookmarks)
|
|
13
|
-
- [
|
|
11
|
+
- [Bookmarks & Navigation](#bookmarks--navigation)
|
|
12
|
+
- [Command Mode](#command-mode)
|
|
13
|
+
- [Tool Runtime](#tool-runtime)
|
|
14
|
+
- [Mode Switching](#mode-switching)
|
|
14
15
|
|
|
15
16
|
---
|
|
16
17
|
|
|
@@ -20,10 +21,10 @@
|
|
|
20
21
|
|
|
21
22
|
| Key | Action |
|
|
22
23
|
|-----|--------|
|
|
23
|
-
| `j` or
|
|
24
|
-
| `k` or
|
|
25
|
-
| `h` or
|
|
26
|
-
| `l`, `Enter`, or
|
|
24
|
+
| `j` or `Down` | Move down one item |
|
|
25
|
+
| `k` or `Up` | Move up one item |
|
|
26
|
+
| `h` or `Left` | Go to parent directory |
|
|
27
|
+
| `l`, `Enter`, or `Right` | Enter directory / Open file |
|
|
27
28
|
| `g` | Jump to top of list |
|
|
28
29
|
| `G` | Jump to bottom of list |
|
|
29
30
|
|
|
@@ -61,33 +62,78 @@
|
|
|
61
62
|
- Press `Enter` to apply filter and exit filter mode
|
|
62
63
|
- Press `ESC` to cancel and clear filter
|
|
63
64
|
|
|
64
|
-
### Bookmarks
|
|
65
|
+
### Bookmarks & Navigation
|
|
65
66
|
|
|
66
67
|
| Key | Action |
|
|
67
68
|
|-----|--------|
|
|
68
69
|
| `b` | Add current directory to bookmarks |
|
|
70
|
+
| `B` | Bookmark menu (view/add/remove/script paths) |
|
|
69
71
|
| `0` | Jump to startup directory |
|
|
70
72
|
| `1-9` | Jump to bookmark 1-9 |
|
|
71
|
-
| `
|
|
73
|
+
| `z` | Navigate using zoxide history |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Command Mode
|
|
78
|
+
|
|
79
|
+
Press `:` to enter command mode. Available prefixes:
|
|
80
|
+
|
|
81
|
+
| Prefix | Function | Example |
|
|
82
|
+
|--------|----------|---------|
|
|
83
|
+
| `@` | Execute script | `:@build.sh` |
|
|
84
|
+
| `rake:` | Execute rake task | `:rake:test` |
|
|
85
|
+
| `!` | Shell command | `:!git status` |
|
|
86
|
+
| (none) | Built-in command | `:hello` |
|
|
72
87
|
|
|
73
|
-
|
|
74
|
-
- Browse all bookmarks with normal navigation keys
|
|
75
|
-
- Press `Space` to select a bookmark and jump to it
|
|
76
|
-
- Press `ESC` to exit project mode
|
|
88
|
+
### Features
|
|
77
89
|
|
|
78
|
-
|
|
90
|
+
- **Tab completion**: Press `Tab` to auto-complete commands, scripts, and rake tasks
|
|
91
|
+
- **Command history**: Use `Up/Down` arrows to navigate previous commands
|
|
92
|
+
- **Local scripts**: Scripts in the current directory are automatically available with `@` prefix
|
|
93
|
+
- **Rakefile parsing**: Tasks from `Rakefile` in the current directory are available as `rake:task_name`
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Tool Runtime
|
|
79
98
|
|
|
80
99
|
| Key | Action |
|
|
81
100
|
|-----|--------|
|
|
82
|
-
| `z` | Navigate using zoxide history |
|
|
83
101
|
| `:` | Enter command mode |
|
|
84
|
-
|
|
|
85
|
-
| `
|
|
86
|
-
|
|
102
|
+
| `J` | Job mode (view background jobs) |
|
|
103
|
+
| `L` | View execution logs |
|
|
104
|
+
|
|
105
|
+
### Script Path Management
|
|
106
|
+
|
|
107
|
+
Press `B` then select script path management to:
|
|
108
|
+
- View registered script directories
|
|
109
|
+
- Add/remove script paths
|
|
110
|
+
- Jump to script directories
|
|
111
|
+
|
|
112
|
+
### Supported Script Types
|
|
113
|
+
|
|
114
|
+
| Extension | Language |
|
|
115
|
+
|-----------|----------|
|
|
116
|
+
| `.rb` | Ruby |
|
|
117
|
+
| `.py` | Python |
|
|
118
|
+
| `.sh` | Shell (bash/zsh) |
|
|
119
|
+
| `.js` | JavaScript |
|
|
120
|
+
| `.ts` | TypeScript |
|
|
121
|
+
| `.pl` | Perl |
|
|
122
|
+
| `.ps1` | PowerShell |
|
|
87
123
|
|
|
88
124
|
---
|
|
89
125
|
|
|
90
|
-
##
|
|
126
|
+
## Mode Switching
|
|
127
|
+
|
|
128
|
+
| Key | Action |
|
|
129
|
+
|-----|--------|
|
|
130
|
+
| `Tab` | Switch mode: Files -> Logs -> Jobs -> Help |
|
|
131
|
+
| `Shift+Tab` | Switch mode (reverse) |
|
|
132
|
+
| `?` | Enter help mode (this mode) |
|
|
133
|
+
| `ESC` | Exit current mode |
|
|
134
|
+
| `q` | Quit rufio |
|
|
135
|
+
|
|
136
|
+
### Help Mode
|
|
91
137
|
|
|
92
138
|
You are currently in **Help Mode**. In this mode:
|
|
93
139
|
|
|
@@ -104,7 +150,8 @@ You are currently in **Help Mode**. In this mode:
|
|
|
104
150
|
2. **Bulk operations**: Select multiple files with `Space`, then use `m/c/x`
|
|
105
151
|
3. **Filter + Search**: Use `f` for real-time filtering, `s` for fuzzy search
|
|
106
152
|
4. **Bookmarks**: Save frequently used directories with `b`, access with `1-9`
|
|
107
|
-
5. **
|
|
153
|
+
5. **Rake tasks**: If your project has a Rakefile, use `:rake:` with Tab completion
|
|
154
|
+
6. **Background jobs**: Long-running commands execute in background, view with `J`
|
|
108
155
|
|
|
109
156
|
---
|
|
110
157
|
|
data/info/keybindings.md
CHANGED
|
@@ -6,10 +6,10 @@ Complete reference of all keyboard shortcuts in **rufio**.
|
|
|
6
6
|
|
|
7
7
|
| Key | Action |
|
|
8
8
|
|-----|--------|
|
|
9
|
-
| `j` /
|
|
10
|
-
| `k` /
|
|
11
|
-
| `h` /
|
|
12
|
-
| `l` /
|
|
9
|
+
| `j` / `Down` | Move down |
|
|
10
|
+
| `k` / `Up` | Move up |
|
|
11
|
+
| `h` / `Left` | Go to parent directory |
|
|
12
|
+
| `l` / `Right` / `Enter` | Enter directory or open file |
|
|
13
13
|
| `g` | Jump to top of list |
|
|
14
14
|
| `G` | Jump to bottom of list |
|
|
15
15
|
|
|
@@ -42,31 +42,32 @@ Complete reference of all keyboard shortcuts in **rufio**.
|
|
|
42
42
|
| `s` | Search file names with fzf |
|
|
43
43
|
| `F` | Search file contents with rga |
|
|
44
44
|
|
|
45
|
-
## Bookmarks
|
|
45
|
+
## Bookmarks & Navigation
|
|
46
46
|
|
|
47
47
|
| Key | Action |
|
|
48
48
|
|-----|--------|
|
|
49
49
|
| `b` | Add current directory to bookmarks |
|
|
50
|
+
| `B` | Bookmark menu (view/add/remove/script paths) |
|
|
50
51
|
| `0` | Jump to startup directory |
|
|
51
|
-
| `1` | Jump to bookmark 1 |
|
|
52
|
-
| `
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
| `5` | Jump to bookmark 5 |
|
|
56
|
-
| `6` | Jump to bookmark 6 |
|
|
57
|
-
| `7` | Jump to bookmark 7 |
|
|
58
|
-
| `8` | Jump to bookmark 8 |
|
|
59
|
-
| `9` | Jump to bookmark 9 |
|
|
60
|
-
| `p` | Enter project mode (browse all bookmarks) |
|
|
61
|
-
|
|
62
|
-
## Other
|
|
52
|
+
| `1-9` | Jump to bookmark 1-9 |
|
|
53
|
+
| `z` | Navigate using zoxide history |
|
|
54
|
+
|
|
55
|
+
## Command Mode & Tool Runtime
|
|
63
56
|
|
|
64
57
|
| Key | Action |
|
|
65
58
|
|-----|--------|
|
|
66
|
-
| `z` | Navigate using zoxide history |
|
|
67
59
|
| `:` | Enter command mode |
|
|
60
|
+
| `J` | Job mode (view background jobs) |
|
|
61
|
+
| `L` | View execution logs |
|
|
62
|
+
|
|
63
|
+
## Mode Switching
|
|
64
|
+
|
|
65
|
+
| Key | Action |
|
|
66
|
+
|-----|--------|
|
|
67
|
+
| `Tab` | Switch mode: Files -> Logs -> Jobs -> Help |
|
|
68
|
+
| `Shift+Tab` | Switch mode (reverse direction) |
|
|
68
69
|
| `?` | Enter help mode |
|
|
69
|
-
| `ESC` | Exit current mode (help/filter/
|
|
70
|
+
| `ESC` | Exit current mode (help/filter/command) |
|
|
70
71
|
| `q` | Quit rufio |
|
|
71
72
|
|
|
72
73
|
---
|
|
@@ -79,15 +80,28 @@ Complete reference of all keyboard shortcuts in **rufio**.
|
|
|
79
80
|
- **Enter**: Apply filter and exit filter mode
|
|
80
81
|
- **ESC**: Cancel filter and exit filter mode
|
|
81
82
|
|
|
82
|
-
###
|
|
83
|
-
- **
|
|
84
|
-
- **
|
|
85
|
-
- **
|
|
83
|
+
### Command Mode
|
|
84
|
+
- **Any character**: Add to command input
|
|
85
|
+
- **Tab**: Auto-complete (scripts, rake tasks, commands)
|
|
86
|
+
- **Up/Down**: Navigate command history
|
|
87
|
+
- **Enter**: Execute command
|
|
88
|
+
- **Backspace**: Remove last character
|
|
89
|
+
- **ESC**: Cancel and exit command mode
|
|
90
|
+
|
|
91
|
+
### Command Mode Prefixes
|
|
92
|
+
- `@script` - Execute a registered or local script
|
|
93
|
+
- `rake:task` - Execute a Rakefile task
|
|
94
|
+
- `!command` - Execute a shell command
|
|
95
|
+
- `command` - Execute a built-in or plugin command
|
|
86
96
|
|
|
87
97
|
### Help Mode
|
|
88
98
|
- **j/k/h/l**: Navigate help files
|
|
89
99
|
- **ESC**: Exit help mode and return to previous directory
|
|
90
100
|
|
|
101
|
+
### Job Mode
|
|
102
|
+
- **j/k**: Navigate through jobs
|
|
103
|
+
- **ESC**: Exit job mode
|
|
104
|
+
|
|
91
105
|
---
|
|
92
106
|
|
|
93
107
|
## Tips
|
|
@@ -96,6 +110,8 @@ Complete reference of all keyboard shortcuts in **rufio**.
|
|
|
96
110
|
- **Selection**: Use `Space` to mark multiple files, then operate on all at once
|
|
97
111
|
- **Quick access**: Number keys `1-9` provide instant access to bookmarks
|
|
98
112
|
- **Filtering**: Press `f` and start typing for real-time filtering
|
|
113
|
+
- **Rake tasks**: Type `:rake:` then `Tab` to see available tasks
|
|
114
|
+
- **Local scripts**: Scripts in the current directory are auto-detected with `@` prefix
|
|
99
115
|
|
|
100
116
|
---
|
|
101
117
|
|
data/info/welcome.md
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
# Welcome to rufio!
|
|
1
|
+
# Welcome to rufio!
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Runtime Unified Flow I/O Operator**
|
|
4
|
+
|
|
5
|
+
A TUI file manager that executes and coordinates tools and scripts from files.
|
|
4
6
|
|
|
5
7
|
## Key Features
|
|
6
8
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
9
|
+
- **Tool Runtime** - Execute scripts and rake tasks from command mode
|
|
10
|
+
- **Vim-like Keybindings** - Navigate with `j/k/h/l` keys
|
|
11
|
+
- **Real-time Filtering** - Press `f` to filter files instantly
|
|
12
|
+
- **Advanced Search** - Use `fzf` for file names and `rga` for content search
|
|
13
|
+
- **Bookmark Support** - Quick access to favorite directories
|
|
14
|
+
- **Job Management** - Run commands in the background
|
|
15
|
+
- **Plugin System** - Extend functionality with custom plugins
|
|
13
16
|
|
|
14
17
|
## Quick Start
|
|
15
18
|
|
|
@@ -18,12 +21,25 @@ Thank you for using **rufio** - a terminal-based file manager inspired by [Yazi]
|
|
|
18
21
|
| `j/k` | Move down/up |
|
|
19
22
|
| `h/l` | Go to parent / Enter directory |
|
|
20
23
|
| `f` | Filter files |
|
|
24
|
+
| `s` | Search with fzf |
|
|
21
25
|
| `b` | Add bookmark |
|
|
22
|
-
| `
|
|
23
|
-
|
|
|
26
|
+
| `B` | Bookmark menu |
|
|
27
|
+
| `z` | zoxide history |
|
|
24
28
|
| `:` | Command mode |
|
|
29
|
+
| `J` | Job mode |
|
|
30
|
+
| `?` | Help mode |
|
|
31
|
+
| `Tab` | Switch mode (Files / Logs / Jobs / Help) |
|
|
25
32
|
| `q` | Quit |
|
|
26
33
|
|
|
34
|
+
## Command Mode
|
|
35
|
+
|
|
36
|
+
Press `:` to enter command mode:
|
|
37
|
+
|
|
38
|
+
- `@script.sh` - Execute a script
|
|
39
|
+
- `rake:test` - Execute a rake task
|
|
40
|
+
- `!git status` - Run a shell command
|
|
41
|
+
- `Tab` - Auto-complete commands
|
|
42
|
+
|
|
27
43
|
## Getting Help
|
|
28
44
|
|
|
29
45
|
Press `?` to enter **Help Mode** where you can browse all documentation files.
|
|
@@ -37,4 +53,4 @@ Visit the GitHub repository for detailed documentation:
|
|
|
37
53
|
|
|
38
54
|
---
|
|
39
55
|
|
|
40
|
-
*Happy file managing
|
|
56
|
+
*Happy file managing!*
|
|
@@ -16,9 +16,11 @@ module Rufio
|
|
|
16
16
|
# @param input [String] 入力されたテキスト
|
|
17
17
|
# @return [Array<String>] 補完候補のリスト
|
|
18
18
|
def complete(input)
|
|
19
|
-
#
|
|
19
|
+
# 入力が空の場合は内部コマンド + スクリプト + rakeタスクを返す
|
|
20
20
|
if input.nil? || input.strip.empty?
|
|
21
|
-
return @command_mode.available_commands.map(&:to_s) +
|
|
21
|
+
return @command_mode.available_commands.map(&:to_s) +
|
|
22
|
+
script_candidates('') +
|
|
23
|
+
rake_candidates('')
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
# シェルコマンド補完(!で始まる場合)
|
|
@@ -31,13 +33,23 @@ module Rufio
|
|
|
31
33
|
return @command_mode.complete_script(input.strip)
|
|
32
34
|
end
|
|
33
35
|
|
|
34
|
-
#
|
|
36
|
+
# rakeタスク補完(rake:で始まる場合)
|
|
37
|
+
if input.strip.start_with?('rake:')
|
|
38
|
+
prefix = input.strip[5..-1]
|
|
39
|
+
return @command_mode.complete_rake_task(prefix)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# 通常のコマンド補完(内部コマンド + rakeタスク)
|
|
35
43
|
available_commands = @command_mode.available_commands.map(&:to_s)
|
|
36
44
|
input_lower = input.downcase
|
|
37
45
|
candidates = available_commands.select do |command|
|
|
38
46
|
command.downcase.start_with?(input_lower)
|
|
39
47
|
end
|
|
40
48
|
|
|
49
|
+
# rakeタスクも候補に追加("r", "ra", "rak", "rake" 等にマッチ)
|
|
50
|
+
rake_tasks = rake_candidates('')
|
|
51
|
+
candidates += rake_tasks.select { |task| task.downcase.start_with?(input_lower) }
|
|
52
|
+
|
|
41
53
|
candidates
|
|
42
54
|
end
|
|
43
55
|
|
|
@@ -67,15 +79,20 @@ module Rufio
|
|
|
67
79
|
|
|
68
80
|
private
|
|
69
81
|
|
|
70
|
-
#
|
|
82
|
+
# スクリプト候補を取得(ScriptRunner + ローカルスクリプト)
|
|
71
83
|
# @param prefix [String] 入力中の文字列
|
|
72
84
|
# @return [Array<String>] スクリプト候補(@付き)
|
|
73
85
|
def script_candidates(prefix)
|
|
74
|
-
return [] unless @command_mode&.script_runner
|
|
75
|
-
|
|
76
86
|
@command_mode.complete_script("@#{prefix}")
|
|
77
87
|
end
|
|
78
88
|
|
|
89
|
+
# rakeタスク候補を取得
|
|
90
|
+
# @param prefix [String] 入力中の文字列
|
|
91
|
+
# @return [Array<String>] rakeタスク候補(rake:付き)
|
|
92
|
+
def rake_candidates(prefix)
|
|
93
|
+
@command_mode.complete_rake_task(prefix)
|
|
94
|
+
end
|
|
95
|
+
|
|
79
96
|
# シェルコマンドの補完
|
|
80
97
|
# @param input [String] ! で始まる入力
|
|
81
98
|
# @return [Array<String>] 補完候補のリスト
|
data/lib/rufio/command_mode.rb
CHANGED
|
@@ -15,6 +15,8 @@ module Rufio
|
|
|
15
15
|
@script_runner = nil
|
|
16
16
|
@script_path_manager = nil
|
|
17
17
|
@job_manager = nil
|
|
18
|
+
@local_script_scanner = LocalScriptScanner.new
|
|
19
|
+
@rakefile_parser = RakefileParser.new
|
|
18
20
|
load_builtin_commands
|
|
19
21
|
load_dsl_commands
|
|
20
22
|
end
|
|
@@ -26,7 +28,8 @@ module Rufio
|
|
|
26
28
|
@job_manager = job_manager
|
|
27
29
|
@script_runner = ScriptRunner.new(
|
|
28
30
|
script_paths: script_paths,
|
|
29
|
-
job_manager: job_manager
|
|
31
|
+
job_manager: job_manager,
|
|
32
|
+
command_logger: @background_executor&.command_logger
|
|
30
33
|
)
|
|
31
34
|
end
|
|
32
35
|
|
|
@@ -39,10 +42,18 @@ module Rufio
|
|
|
39
42
|
# ScriptRunnerも設定(ScriptPathManagerのパスを使用)
|
|
40
43
|
@script_runner = ScriptRunner.new(
|
|
41
44
|
script_paths: @script_path_manager.paths,
|
|
42
|
-
job_manager: job_manager
|
|
45
|
+
job_manager: job_manager,
|
|
46
|
+
command_logger: @background_executor&.command_logger
|
|
43
47
|
)
|
|
44
48
|
end
|
|
45
49
|
|
|
50
|
+
# 閲覧中ディレクトリを更新
|
|
51
|
+
# @param directory [String] 現在の閲覧ディレクトリ
|
|
52
|
+
def update_browsing_directory(directory)
|
|
53
|
+
@local_script_scanner.update_directory(directory)
|
|
54
|
+
@rakefile_parser.update_directory(directory)
|
|
55
|
+
end
|
|
56
|
+
|
|
46
57
|
# コマンドを実行する
|
|
47
58
|
# @param command_string [String] コマンド文字列
|
|
48
59
|
# @param working_dir [String, nil] 作業ディレクトリ(スクリプト実行時に使用)
|
|
@@ -55,6 +66,12 @@ module Rufio
|
|
|
55
66
|
return execute_script(command_string.strip[1..-1], working_dir)
|
|
56
67
|
end
|
|
57
68
|
|
|
69
|
+
# rakeタスク実行 (rake: で始まる場合)
|
|
70
|
+
if command_string.strip.start_with?('rake:')
|
|
71
|
+
task_name = command_string.strip[5..-1]
|
|
72
|
+
return execute_rake_task(task_name, working_dir)
|
|
73
|
+
end
|
|
74
|
+
|
|
58
75
|
# シェルコマンドの実行 (! で始まる場合)
|
|
59
76
|
if command_string.strip.start_with?('!')
|
|
60
77
|
shell_command = command_string.strip[1..-1]
|
|
@@ -132,11 +149,28 @@ module Rufio
|
|
|
132
149
|
# @param prefix [String] 入力中の文字列(@を含む)
|
|
133
150
|
# @return [Array<String>] 補完候補(@付き)
|
|
134
151
|
def complete_script(prefix)
|
|
135
|
-
return [] unless @script_runner
|
|
136
|
-
|
|
137
152
|
# @を除去して検索
|
|
138
153
|
search_prefix = prefix.sub(/^@/, '')
|
|
139
|
-
|
|
154
|
+
|
|
155
|
+
candidates = []
|
|
156
|
+
|
|
157
|
+
# ScriptRunnerからの候補
|
|
158
|
+
if @script_runner
|
|
159
|
+
candidates += @script_runner.complete(search_prefix)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# ローカルスクリプトからの候補
|
|
163
|
+
candidates += @local_script_scanner.complete(search_prefix)
|
|
164
|
+
|
|
165
|
+
# 重複排除してソート、@付きで返す
|
|
166
|
+
candidates.uniq.sort.map { |name| "@#{name}" }
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# rakeタスク名を補完する
|
|
170
|
+
# @param prefix [String] 入力中の文字列(rake:を含まない)
|
|
171
|
+
# @return [Array<String>] 補完候補(rake:付き)
|
|
172
|
+
def complete_rake_task(prefix)
|
|
173
|
+
@rakefile_parser.complete(prefix).map { |name| "rake:#{name}" }
|
|
140
174
|
end
|
|
141
175
|
|
|
142
176
|
private
|
|
@@ -204,22 +238,186 @@ module Rufio
|
|
|
204
238
|
end
|
|
205
239
|
|
|
206
240
|
# スクリプトを実行する(@プレフィックス用)
|
|
207
|
-
#
|
|
241
|
+
# ScriptRunner → LocalScriptScanner の順にフォールバック
|
|
242
|
+
# @param script_input [String] スクリプト名(引数を含む場合あり)
|
|
208
243
|
# @param working_dir [String, nil] 作業ディレクトリ
|
|
209
244
|
# @return [String] 実行結果メッセージ
|
|
210
|
-
def execute_script(
|
|
211
|
-
|
|
212
|
-
|
|
245
|
+
def execute_script(script_input, working_dir)
|
|
246
|
+
working_dir ||= Dir.pwd
|
|
247
|
+
|
|
248
|
+
# スクリプト名と引数を分離(例: "retag.sh v0.70.0" → name="retag.sh", args="v0.70.0")
|
|
249
|
+
parts = script_input.split(' ', 2)
|
|
250
|
+
script_name = parts[0]
|
|
251
|
+
script_args = parts[1]
|
|
252
|
+
|
|
253
|
+
# ScriptRunnerで検索
|
|
254
|
+
if @script_runner
|
|
255
|
+
job = @script_runner.run(script_name, working_dir: working_dir, args: script_args)
|
|
256
|
+
return "🚀 ジョブを開始: #{script_name}" if job
|
|
213
257
|
end
|
|
214
258
|
|
|
215
|
-
|
|
259
|
+
# LocalScriptScannerにフォールバック
|
|
260
|
+
local_script = @local_script_scanner.find_script(script_name)
|
|
261
|
+
if local_script
|
|
262
|
+
return execute_local_script(local_script, working_dir, script_args)
|
|
263
|
+
end
|
|
216
264
|
|
|
217
|
-
|
|
265
|
+
# どちらにも見つからない
|
|
266
|
+
if @script_runner
|
|
267
|
+
"⚠️ スクリプトが見つかりません: #{script_name}"
|
|
268
|
+
else
|
|
269
|
+
"⚠️ スクリプトランナーが設定されていません"
|
|
270
|
+
end
|
|
271
|
+
end
|
|
218
272
|
|
|
219
|
-
|
|
220
|
-
|
|
273
|
+
# ローカルスクリプトを実行する
|
|
274
|
+
# @param script [Hash] スクリプト情報 { name:, path:, dir: }
|
|
275
|
+
# @param working_dir [String] 作業ディレクトリ
|
|
276
|
+
# @param args [String, nil] スクリプトに渡す引数
|
|
277
|
+
# @return [String, Hash] 実行結果メッセージ
|
|
278
|
+
def execute_local_script(script, working_dir, args = nil)
|
|
279
|
+
command = build_script_command(script)
|
|
280
|
+
command = "#{command} #{args}" if args && !args.empty?
|
|
281
|
+
|
|
282
|
+
if @job_manager
|
|
283
|
+
job = @job_manager.add_job(
|
|
284
|
+
name: script[:name],
|
|
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]}"
|
|
221
295
|
else
|
|
222
|
-
|
|
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)
|
|
306
|
+
|
|
307
|
+
result
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# 実行結果をCommandLoggerに記録
|
|
312
|
+
# @param command_name [String] コマンド名
|
|
313
|
+
# @param result [Hash] 実行結果 { success:, output:, stderr:, error: }
|
|
314
|
+
def log_execution(command_name, result)
|
|
315
|
+
logger = @background_executor&.command_logger
|
|
316
|
+
return unless logger
|
|
317
|
+
|
|
318
|
+
output = [result[:output], result[:stderr]].compact.reject(&:empty?).join("\n")
|
|
319
|
+
logger.log(
|
|
320
|
+
command_name,
|
|
321
|
+
output,
|
|
322
|
+
success: result[:success],
|
|
323
|
+
error: result[:error]
|
|
324
|
+
)
|
|
325
|
+
end
|
|
326
|
+
|
|
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
|
+
# rakeタスクを実行する
|
|
381
|
+
# @param task_name [String] タスク名
|
|
382
|
+
# @param working_dir [String, nil] 作業ディレクトリ
|
|
383
|
+
# @return [String, Hash] 実行結果
|
|
384
|
+
def execute_rake_task(task_name, working_dir)
|
|
385
|
+
unless @rakefile_parser.rakefile_exists?
|
|
386
|
+
return "⚠️ Rakefileが見つかりません"
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
unless @rakefile_parser.tasks.include?(task_name)
|
|
390
|
+
return "⚠️ rakeタスクが見つかりません: #{task_name}"
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
working_dir ||= Dir.pwd
|
|
394
|
+
shell_command = "rake #{task_name.shellescape}"
|
|
395
|
+
|
|
396
|
+
begin
|
|
397
|
+
stdout, stderr, status = Open3.capture3(shell_command, chdir: working_dir)
|
|
398
|
+
|
|
399
|
+
result = {
|
|
400
|
+
success: status.success?,
|
|
401
|
+
output: stdout.strip,
|
|
402
|
+
stderr: stderr.strip
|
|
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
|
|
223
421
|
end
|
|
224
422
|
end
|
|
225
423
|
|
|
@@ -218,10 +218,15 @@ module Rufio
|
|
|
218
218
|
end
|
|
219
219
|
|
|
220
220
|
def get_active_entries
|
|
221
|
-
if @filter_manager.filter_active?
|
|
222
|
-
|
|
221
|
+
entries = if @filter_manager.filter_active?
|
|
222
|
+
@filter_manager.filtered_entries
|
|
223
|
+
else
|
|
224
|
+
@directory_listing&.list_entries || []
|
|
225
|
+
end
|
|
226
|
+
if @in_help_mode || @in_log_viewer_mode
|
|
227
|
+
entries.reject { |e| e[:name] == '..' }
|
|
223
228
|
else
|
|
224
|
-
|
|
229
|
+
entries
|
|
225
230
|
end
|
|
226
231
|
end
|
|
227
232
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rufio
|
|
4
|
+
# 閲覧中ディレクトリのスクリプトファイルを検出するスキャナー
|
|
5
|
+
# カレントディレクトリ直下のスクリプトファイル(.sh, .rb, .py等)を検出し、
|
|
6
|
+
# コマンドモードから @script.sh 形式で実行可能にする
|
|
7
|
+
class LocalScriptScanner
|
|
8
|
+
# サポートするスクリプト拡張子
|
|
9
|
+
SUPPORTED_EXTENSIONS = %w[.sh .rb .py .pl .js .ts .ps1].freeze
|
|
10
|
+
|
|
11
|
+
# @param directory [String, nil] スキャン対象ディレクトリ
|
|
12
|
+
def initialize(directory = nil)
|
|
13
|
+
@directory = directory
|
|
14
|
+
@scripts_cache = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# ディレクトリ変更時にキャッシュを無効化
|
|
18
|
+
# @param directory [String] 新しいディレクトリ
|
|
19
|
+
def update_directory(directory)
|
|
20
|
+
return if @directory == directory
|
|
21
|
+
|
|
22
|
+
@directory = directory
|
|
23
|
+
@scripts_cache = nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# 利用可能なスクリプト一覧を取得
|
|
27
|
+
# @return [Array<Hash>] スクリプト情報の配列 [{ name:, path:, dir: }, ...]
|
|
28
|
+
def available_scripts
|
|
29
|
+
@scripts_cache ||= scan_scripts
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# 名前でスクリプトを検索
|
|
33
|
+
# @param name [String] スクリプト名(拡張子あり/なし)
|
|
34
|
+
# @return [Hash, nil] スクリプト情報 { name:, path:, dir: } または nil
|
|
35
|
+
def find_script(name)
|
|
36
|
+
# 完全一致を優先
|
|
37
|
+
script = available_scripts.find { |s| s[:name] == name }
|
|
38
|
+
return script if script
|
|
39
|
+
|
|
40
|
+
# 拡張子なしで検索
|
|
41
|
+
SUPPORTED_EXTENSIONS.each do |ext|
|
|
42
|
+
script = available_scripts.find { |s| s[:name] == "#{name}#{ext}" }
|
|
43
|
+
return script if script
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Tab補完候補を取得
|
|
50
|
+
# @param prefix [String] 入力中の文字列
|
|
51
|
+
# @return [Array<String>] 補完候補のスクリプト名
|
|
52
|
+
def complete(prefix)
|
|
53
|
+
available_scripts
|
|
54
|
+
.map { |s| s[:name] }
|
|
55
|
+
.select { |name| name.start_with?(prefix) }
|
|
56
|
+
.sort
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
# ディレクトリをスキャンしてスクリプトファイルを収集
|
|
62
|
+
# @return [Array<Hash>] スクリプト情報の配列
|
|
63
|
+
def scan_scripts
|
|
64
|
+
return [] unless @directory && Dir.exist?(@directory)
|
|
65
|
+
|
|
66
|
+
scripts = []
|
|
67
|
+
|
|
68
|
+
Dir.foreach(@directory) do |entry|
|
|
69
|
+
next if entry.start_with?('.')
|
|
70
|
+
path = File.join(@directory, entry)
|
|
71
|
+
next unless File.file?(path)
|
|
72
|
+
next unless script_file?(entry)
|
|
73
|
+
|
|
74
|
+
scripts << {
|
|
75
|
+
name: entry,
|
|
76
|
+
path: path,
|
|
77
|
+
dir: @directory
|
|
78
|
+
}
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
scripts.sort_by { |s| s[:name] }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# スクリプトファイルかどうかを判定
|
|
85
|
+
# @param filename [String] ファイル名
|
|
86
|
+
# @return [Boolean]
|
|
87
|
+
def script_file?(filename)
|
|
88
|
+
ext = File.extname(filename).downcase
|
|
89
|
+
SUPPORTED_EXTENSIONS.include?(ext)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rufio
|
|
4
|
+
# Rakefileをパースしてタスク名を抽出するパーサー
|
|
5
|
+
# 正規表現ベースでtask定義を検出し、コマンドモードから
|
|
6
|
+
# rake:task_name 形式で実行可能にする
|
|
7
|
+
class RakefileParser
|
|
8
|
+
RAKEFILE_NAMES = %w[Rakefile rakefile Rakefile.rb].freeze
|
|
9
|
+
TASK_PATTERN = /^\s*task\s+[:'"]?(\w+)/.freeze
|
|
10
|
+
|
|
11
|
+
# @param directory [String, nil] スキャン対象ディレクトリ
|
|
12
|
+
def initialize(directory = nil)
|
|
13
|
+
@directory = directory
|
|
14
|
+
@tasks_cache = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# ディレクトリ変更時にキャッシュを無効化
|
|
18
|
+
# @param directory [String] 新しいディレクトリ
|
|
19
|
+
def update_directory(directory)
|
|
20
|
+
return if @directory == directory
|
|
21
|
+
|
|
22
|
+
@directory = directory
|
|
23
|
+
@tasks_cache = nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Rakefileが存在するかどうか
|
|
27
|
+
# @return [Boolean]
|
|
28
|
+
def rakefile_exists?
|
|
29
|
+
!!find_rakefile
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Rakefileからタスク名を抽出
|
|
33
|
+
# @return [Array<String>] タスク名の配列(ソート済み・ユニーク)
|
|
34
|
+
def tasks
|
|
35
|
+
@tasks_cache ||= parse_tasks
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Tab補完候補を取得
|
|
39
|
+
# @param prefix [String] 入力中の文字列
|
|
40
|
+
# @return [Array<String>] 補完候補のタスク名
|
|
41
|
+
def complete(prefix)
|
|
42
|
+
tasks.select { |name| name.start_with?(prefix) }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Rakefileのパスを検索
|
|
48
|
+
# @return [String, nil] Rakefileのパス、見つからない場合nil
|
|
49
|
+
def find_rakefile
|
|
50
|
+
return nil unless @directory && Dir.exist?(@directory)
|
|
51
|
+
|
|
52
|
+
RAKEFILE_NAMES.each do |name|
|
|
53
|
+
path = File.join(@directory, name)
|
|
54
|
+
return path if File.file?(path)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Rakefileをパースしてタスク名を抽出
|
|
61
|
+
# @return [Array<String>] タスク名の配列
|
|
62
|
+
def parse_tasks
|
|
63
|
+
rakefile = find_rakefile
|
|
64
|
+
return [] unless rakefile
|
|
65
|
+
|
|
66
|
+
content = File.read(rakefile)
|
|
67
|
+
task_names = []
|
|
68
|
+
|
|
69
|
+
content.each_line do |line|
|
|
70
|
+
match = line.match(TASK_PATTERN)
|
|
71
|
+
task_names << match[1] if match
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
task_names.uniq.sort
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
data/lib/rufio/script_runner.rb
CHANGED
|
@@ -11,9 +11,11 @@ module Rufio
|
|
|
11
11
|
|
|
12
12
|
# @param script_paths [Array<String>] スクリプトを検索するディレクトリのリスト
|
|
13
13
|
# @param job_manager [JobManager, nil] ジョブマネージャー(nilの場合は同期実行)
|
|
14
|
-
|
|
14
|
+
# @param command_logger [CommandLogger, nil] コマンドロガー
|
|
15
|
+
def initialize(script_paths:, job_manager: nil, command_logger: nil)
|
|
15
16
|
@script_paths = script_paths.map { |p| File.expand_path(p) }
|
|
16
17
|
@job_manager = job_manager
|
|
18
|
+
@command_logger = command_logger
|
|
17
19
|
@scripts_cache = nil
|
|
18
20
|
end
|
|
19
21
|
|
|
@@ -54,15 +56,16 @@ module Rufio
|
|
|
54
56
|
# スクリプトをジョブとして実行
|
|
55
57
|
# @param name [String] スクリプト名
|
|
56
58
|
# @param working_dir [String] 作業ディレクトリ
|
|
59
|
+
# @param args [String, nil] スクリプトに渡す引数
|
|
57
60
|
# @param selected_file [String, nil] 選択中のファイル
|
|
58
61
|
# @param selected_dir [String, nil] 選択中のディレクトリ
|
|
59
62
|
# @return [TaskStatus, nil] 作成されたジョブ、またはスクリプトが見つからない場合nil
|
|
60
|
-
def run(name, working_dir:, selected_file: nil, selected_dir: nil)
|
|
63
|
+
def run(name, working_dir:, args: nil, selected_file: nil, selected_dir: nil)
|
|
61
64
|
script = find_script(name)
|
|
62
65
|
return nil unless script
|
|
63
66
|
|
|
64
67
|
env = build_environment(working_dir, selected_file, selected_dir)
|
|
65
|
-
execute_script(script, working_dir, env)
|
|
68
|
+
execute_script(script, working_dir, env, args)
|
|
66
69
|
end
|
|
67
70
|
|
|
68
71
|
# キャッシュをクリア
|
|
@@ -130,9 +133,11 @@ module Rufio
|
|
|
130
133
|
# @param script [Hash] スクリプト情報
|
|
131
134
|
# @param working_dir [String] 作業ディレクトリ
|
|
132
135
|
# @param env [Hash] 環境変数
|
|
136
|
+
# @param args [String, nil] スクリプトに渡す引数
|
|
133
137
|
# @return [TaskStatus] 作成されたジョブ
|
|
134
|
-
def execute_script(script, working_dir, env = {})
|
|
138
|
+
def execute_script(script, working_dir, env = {}, args = nil)
|
|
135
139
|
command = build_command(script)
|
|
140
|
+
command = "#{command} #{args}" if args && !args.empty?
|
|
136
141
|
|
|
137
142
|
if @job_manager
|
|
138
143
|
# ジョブマネージャーにジョブを追加
|
|
@@ -205,12 +210,24 @@ module Rufio
|
|
|
205
210
|
job.fail(exit_code: status.exitstatus)
|
|
206
211
|
end
|
|
207
212
|
|
|
213
|
+
# CommandLoggerに記録
|
|
214
|
+
log_to_command_logger(job.name, stdout, stderr, status.success?)
|
|
215
|
+
|
|
208
216
|
# 通知を送信
|
|
209
217
|
@job_manager&.notify_completion(job)
|
|
210
218
|
rescue StandardError => e
|
|
211
219
|
job.append_log("Error: #{e.message}")
|
|
212
220
|
job.fail(exit_code: -1)
|
|
221
|
+
log_to_command_logger(job.name, '', e.message, false)
|
|
213
222
|
@job_manager&.notify_completion(job)
|
|
214
223
|
end
|
|
224
|
+
|
|
225
|
+
# CommandLoggerに実行結果を記録
|
|
226
|
+
def log_to_command_logger(name, stdout, stderr, success)
|
|
227
|
+
return unless @command_logger
|
|
228
|
+
|
|
229
|
+
output = [stdout, stderr].compact.map(&:strip).reject(&:empty?).join("\n")
|
|
230
|
+
@command_logger.log("@#{name}", output, success: success)
|
|
231
|
+
end
|
|
215
232
|
end
|
|
216
233
|
end
|
|
@@ -17,6 +17,12 @@ module Rufio
|
|
|
17
17
|
def toggle_selection(entry, current_directory = nil)
|
|
18
18
|
return false unless entry
|
|
19
19
|
|
|
20
|
+
# 異なるディレクトリで選択した場合、古い選択をクリアしてリセット
|
|
21
|
+
if current_directory && @source_directory && current_directory != @source_directory
|
|
22
|
+
@selected_items.clear
|
|
23
|
+
@source_directory = nil
|
|
24
|
+
end
|
|
25
|
+
|
|
20
26
|
if @selected_items.include?(entry[:name])
|
|
21
27
|
@selected_items.delete(entry[:name])
|
|
22
28
|
# Clear source_directory if no items are selected
|
data/lib/rufio/terminal_ui.rb
CHANGED
|
@@ -216,6 +216,7 @@ module Rufio
|
|
|
216
216
|
last_frame_time = Time.now
|
|
217
217
|
current_fps = 0.0
|
|
218
218
|
last_fps_update = Time.now
|
|
219
|
+
@last_displayed_fps = 0.0
|
|
219
220
|
|
|
220
221
|
# 再描画フラグ
|
|
221
222
|
needs_redraw = false
|
|
@@ -237,8 +238,11 @@ module Rufio
|
|
|
237
238
|
last_fps_update = start
|
|
238
239
|
end
|
|
239
240
|
|
|
240
|
-
#
|
|
241
|
-
|
|
241
|
+
# FPS表示の更新タイミングで再描画(1秒ごと)
|
|
242
|
+
if current_fps != @last_displayed_fps
|
|
243
|
+
@last_displayed_fps = current_fps
|
|
244
|
+
needs_redraw = true
|
|
245
|
+
end
|
|
242
246
|
end
|
|
243
247
|
|
|
244
248
|
# UPDATE phase - ノンブロッキング入力処理
|
|
@@ -305,6 +309,8 @@ module Rufio
|
|
|
305
309
|
|
|
306
310
|
# コマンドモードがアクティブな場合はオーバーレイにダイアログを描画
|
|
307
311
|
if @command_mode_active
|
|
312
|
+
# 前回のオーバーレイ残留を防ぐためクリアしてから描画
|
|
313
|
+
@screen.clear_overlay if @screen.overlay_enabled?
|
|
308
314
|
draw_command_mode_to_overlay
|
|
309
315
|
else
|
|
310
316
|
# コマンドモードでない場合はオーバーレイをクリア
|
|
@@ -1370,6 +1376,9 @@ module Rufio
|
|
|
1370
1376
|
def activate_command_mode
|
|
1371
1377
|
@command_mode_active = true
|
|
1372
1378
|
@command_input = ""
|
|
1379
|
+
# 閲覧中ディレクトリをコマンドモードに通知(ローカルスクリプト・Rakefileの検出用)
|
|
1380
|
+
browsing_dir = @directory_listing&.current_path || Dir.pwd
|
|
1381
|
+
@command_mode.update_browsing_directory(browsing_dir)
|
|
1373
1382
|
end
|
|
1374
1383
|
|
|
1375
1384
|
# コマンドモードを終了
|
|
@@ -1476,8 +1485,9 @@ module Rufio
|
|
|
1476
1485
|
@command_mode_ui.show_result(result)
|
|
1477
1486
|
end
|
|
1478
1487
|
|
|
1479
|
-
#
|
|
1480
|
-
draw_screen
|
|
1488
|
+
# メインループの次フレームで再描画される(draw_screenは使わない)
|
|
1489
|
+
# draw_screen(レガシー直接出力)はバッファベースのオーバーレイと座標系が異なるため、
|
|
1490
|
+
# 使用するとコマンドプロンプトの枠線が残る不具合が発生する
|
|
1481
1491
|
end
|
|
1482
1492
|
|
|
1483
1493
|
# Tab補完を処理
|
|
@@ -1697,8 +1707,9 @@ module Rufio
|
|
|
1697
1707
|
def show_overlay_dialog(title, content_lines, options = {}, &block)
|
|
1698
1708
|
return nil unless @screen && @renderer
|
|
1699
1709
|
|
|
1700
|
-
#
|
|
1710
|
+
# オーバーレイを有効化し、前回のダイアログ残留を除去
|
|
1701
1711
|
@screen.enable_overlay
|
|
1712
|
+
@screen.clear_overlay
|
|
1702
1713
|
|
|
1703
1714
|
# ウィンドウサイズを計算
|
|
1704
1715
|
if options[:width] && options[:height]
|
data/lib/rufio/version.rb
CHANGED
data/lib/rufio.rb
CHANGED
|
@@ -53,6 +53,8 @@ require_relative 'rufio/job_mode'
|
|
|
53
53
|
require_relative 'rufio/script_runner'
|
|
54
54
|
require_relative 'rufio/script_path_manager'
|
|
55
55
|
require_relative 'rufio/script_config_loader'
|
|
56
|
+
require_relative 'rufio/local_script_scanner'
|
|
57
|
+
require_relative 'rufio/rakefile_parser'
|
|
56
58
|
|
|
57
59
|
module Rufio
|
|
58
60
|
class Error < StandardError; end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rufio
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.71.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- masisz
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: io-console
|
|
@@ -175,12 +175,14 @@ files:
|
|
|
175
175
|
- lib/rufio/job_manager.rb
|
|
176
176
|
- lib/rufio/job_mode.rb
|
|
177
177
|
- lib/rufio/keybind_handler.rb
|
|
178
|
+
- lib/rufio/local_script_scanner.rb
|
|
178
179
|
- lib/rufio/logger.rb
|
|
179
180
|
- lib/rufio/native/rufio_zig.bundle
|
|
180
181
|
- lib/rufio/native_scanner.rb
|
|
181
182
|
- lib/rufio/native_scanner_zig.rb
|
|
182
183
|
- lib/rufio/notification_manager.rb
|
|
183
184
|
- lib/rufio/parallel_scanner.rb
|
|
185
|
+
- lib/rufio/rakefile_parser.rb
|
|
184
186
|
- lib/rufio/renderer.rb
|
|
185
187
|
- lib/rufio/screen.rb
|
|
186
188
|
- lib/rufio/script_config_loader.rb
|