ruby-progress 1.3.2 → 1.3.5
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/.rubocop_todo.yml +37 -18
- data/CHANGELOG.md +64 -118
- data/DAEMON_MODE.md +127 -0
- data/Gemfile +9 -1
- data/Gemfile.lock +25 -18
- data/JOB_CLI_REFACTOR.md +67 -0
- data/README.md +90 -94
- data/bin/prg +10 -16
- data/demo_screencast.rb +130 -122
- data/examples/daemon_job_example.sh +8 -10
- data/lib/ruby-progress/cli/fill_options.rb +8 -6
- data/lib/ruby-progress/cli/job_cli.rb +170 -131
- data/lib/ruby-progress/cli/ripple_cli.rb +19 -56
- data/lib/ruby-progress/cli/ripple_options.rb +18 -3
- data/lib/ruby-progress/cli/twirl_cli.rb +3 -1
- data/lib/ruby-progress/cli/twirl_options.rb +4 -4
- data/lib/ruby-progress/cli/twirl_runner.rb +3 -37
- data/lib/ruby-progress/cli/worm_cli.rb +2 -50
- data/lib/ruby-progress/cli/worm_options.rb +4 -6
- data/lib/ruby-progress/cli/worm_runner.rb +16 -5
- data/lib/ruby-progress/daemon.rb +2 -64
- data/lib/ruby-progress/fill_cli.rb +4 -72
- data/lib/ruby-progress/output_capture.rb +174 -37
- data/lib/ruby-progress/utils.rb +11 -6
- data/lib/ruby-progress/version.rb +5 -5
- data/lib/ruby-progress/worm.rb +8 -61
- data/ruby-progress.gemspec +41 -0
- data/screencast +2497 -26
- data/screencast.svg +1 -0
- data/scripts/coverage_analysis.rb +49 -0
- data/test_daemon.sh +20 -0
- metadata +31 -11
data/JOB_CLI_REFACTOR.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Job CLI Refactoring Summary
|
|
2
|
+
|
|
3
|
+
## Changes Made
|
|
4
|
+
|
|
5
|
+
Restructured `prg job` to use proper subcommands instead of being hardcoded to only send stop signals.
|
|
6
|
+
|
|
7
|
+
### Before
|
|
8
|
+
```bash
|
|
9
|
+
prg job send --daemon-name mytask --message "Done!"
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### After
|
|
13
|
+
```bash
|
|
14
|
+
# Stop a daemon
|
|
15
|
+
prg job stop --daemon-name mytask --message "Done!"
|
|
16
|
+
|
|
17
|
+
# Check daemon status
|
|
18
|
+
prg job status --daemon-name mytask
|
|
19
|
+
|
|
20
|
+
# Advance a fill progress bar
|
|
21
|
+
prg job advance --daemon-name mybar --amount 10
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## New Subcommands
|
|
25
|
+
|
|
26
|
+
1. **`prg job stop`** - Stop a running progress indicator
|
|
27
|
+
- Options: `--daemon-name`, `--pid-file`, `--message`, `--checkmark`, `--error`
|
|
28
|
+
- Replaces the old `prg job send` command
|
|
29
|
+
|
|
30
|
+
2. **`prg job status`** - Check if a daemon is running
|
|
31
|
+
- Options: `--daemon-name`, `--pid-file`
|
|
32
|
+
- Shows PID and running status
|
|
33
|
+
|
|
34
|
+
3. **`prg job advance`** - Advance a fill progress bar
|
|
35
|
+
- Options: `--daemon-name`, `--pid-file`, `--amount`, `--total`
|
|
36
|
+
- Sends control message to update progress
|
|
37
|
+
- Uses USR2 signal to notify daemon
|
|
38
|
+
|
|
39
|
+
## Implementation Details
|
|
40
|
+
|
|
41
|
+
- **Main entry point**: `JobCLI.run(argv)` - dispatches to subcommands
|
|
42
|
+
- **Backward compatibility**: `prg job send` still works but shows deprecation warning
|
|
43
|
+
- **Control messages**: Uses JSON files (`.pid.msg`) to pass data to daemons
|
|
44
|
+
- **Signal handling**: USR2 for control messages, USR1/INT/TERM/HUP for stop
|
|
45
|
+
- **Silent operation**: No confirmation messages for script-friendly usage -
|
|
46
|
+
only daemon output is shown
|
|
47
|
+
|
|
48
|
+
## Files Modified
|
|
49
|
+
|
|
50
|
+
- `lib/ruby-progress/cli/job_cli.rb` - Complete rewrite with subcommands
|
|
51
|
+
- `bin/prg` - Updated to call `JobCLI.run` instead of `JobCLI.send`
|
|
52
|
+
- `DAEMON_MODE.md` - Updated documentation with new command syntax
|
|
53
|
+
|
|
54
|
+
## Testing
|
|
55
|
+
|
|
56
|
+
All three subcommands tested and working:
|
|
57
|
+
- ✅ `prg job stop` - Gracefully stops daemons
|
|
58
|
+
- ✅ `prg job status` - Shows daemon status
|
|
59
|
+
- ✅ `prg job send` - Backward compatibility with deprecation warning
|
|
60
|
+
- ⏳ `prg job advance` - Ready for implementation (requires daemon-side handling)
|
|
61
|
+
|
|
62
|
+
## Next Steps
|
|
63
|
+
|
|
64
|
+
To fully implement `job advance`, the fill daemon needs to:
|
|
65
|
+
1. Listen for USR2 signal
|
|
66
|
+
2. Read control message file on USR2
|
|
67
|
+
3. Parse JSON and update progress accordingly
|
data/README.md
CHANGED
|
@@ -2,32 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/rb/ruby-progress)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
[](https://github.com/ttscoff/ruby-progress/actions/workflows/rspec.yml)
|
|
5
|
+
<!-- [](https://github.com/ttscoff/ruby-progress/actions/workflows/rspec.yml) -->
|
|
6
6
|
[](https://www.ruby-lang.org/)
|
|
7
|
-
[](#) -->
|
|
8
8
|
|
|
9
9
|
This repository contains three different Ruby progress indicator projects: **Ripple**, **Worm**, and **Twirl**. All provide animated terminal progress indicators with different visual styles and features.
|
|
10
10
|
|
|
11
11
|
## Table of Contents
|
|
12
12
|
|
|
13
|
-
- [
|
|
14
|
-
- [
|
|
15
|
-
- [
|
|
16
|
-
- [
|
|
17
|
-
- [
|
|
18
|
-
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
21
|
-
- [
|
|
22
|
-
|
|
23
|
-
- [
|
|
24
|
-
- [
|
|
25
|
-
- [
|
|
26
|
-
- [
|
|
27
|
-
|
|
28
|
-
- [
|
|
29
|
-
- [
|
|
30
|
-
- [
|
|
13
|
+
- [Ruby Progress Indicators](#ruby-progress-indicators)
|
|
14
|
+
- [Table of Contents](#table-of-contents)
|
|
15
|
+
- [Unified Interface](#unified-interface)
|
|
16
|
+
- [Global Options](#global-options)
|
|
17
|
+
- [Stopping a backgrounded progress indicator](#stopping-a-backgrounded-progress-indicator)
|
|
18
|
+
- [Job Control Subcommands](#job-control-subcommands)
|
|
19
|
+
- [Example: background mode demo](#example-background-mode-demo)
|
|
20
|
+
- [Ripple](#ripple)
|
|
21
|
+
- [Ripple Features](#ripple-features)
|
|
22
|
+
- [Ripple Usage](#ripple-usage)
|
|
23
|
+
- [Ripple CLI examples](#ripple-cli-examples)
|
|
24
|
+
- [Ripple Command Line Options](#ripple-command-line-options)
|
|
25
|
+
- [Ripple Library Usage](#ripple-library-usage)
|
|
26
|
+
- [Twirl](#twirl)
|
|
27
|
+
- [Twirl Features](#twirl-features)
|
|
28
|
+
- [Twirl Usage](#twirl-usage)
|
|
29
|
+
- [Command Line](#command-line)
|
|
30
|
+
- [Twirl Command Line Options](#twirl-command-line-options)
|
|
31
|
+
- [Available Spinner Styles](#available-spinner-styles)
|
|
32
|
+
- [Worm](#worm)
|
|
33
|
+
- [Worm Features](#worm-features)
|
|
34
|
+
- [Worm Usage](#worm-usage)
|
|
35
|
+
- [Command Line](#command-line-1)
|
|
36
|
+
- [Daemon mode (background indicator)](#daemon-mode-background-indicator)
|
|
37
|
+
- [Worm Command Line Options](#worm-command-line-options)
|
|
38
|
+
- [Worm Library Usage](#worm-library-usage)
|
|
39
|
+
- [Animation Styles](#animation-styles)
|
|
40
|
+
- [Circles](#circles)
|
|
41
|
+
- [Blocks](#blocks)
|
|
42
|
+
- [Geometric](#geometric)
|
|
43
|
+
- [Custom Styles](#custom-styles)
|
|
44
|
+
- [Direction Control](#direction-control)
|
|
45
|
+
- [Requirements](#requirements)
|
|
46
|
+
- [Installation](#installation)
|
|
47
|
+
- [As a Gem (Recommended)](#as-a-gem-recommended)
|
|
48
|
+
- [From Source](#from-source)
|
|
49
|
+
- [Development](#development)
|
|
50
|
+
- [Universal Utilities](#universal-utilities)
|
|
51
|
+
- [Terminal Control](#terminal-control)
|
|
52
|
+
- [Completion Messages](#completion-messages)
|
|
53
|
+
- [Contributing](#contributing)
|
|
54
|
+
- [License](#license)
|
|
31
55
|
|
|
32
56
|
## Unified Interface
|
|
33
57
|
|
|
@@ -78,114 +102,86 @@ Notes:
|
|
|
78
102
|
- The indicator clears its line on shutdown and prints the final message to STDOUT.
|
|
79
103
|
- `--stop-pid` is still supported for backward compatibility, but `--stop [--pid-file FILE]` is preferred.
|
|
80
104
|
|
|
81
|
-
###
|
|
105
|
+
### Stopping a backgrounded progress indicator
|
|
82
106
|
|
|
83
|
-
When running a
|
|
107
|
+
When running a backgrounded progress indicator (for example `prg worm --daemon`), you can send control signals using the `prg job` command with subcommands.
|
|
84
108
|
|
|
85
|
-
|
|
109
|
+
#### Job Control Subcommands
|
|
110
|
+
|
|
111
|
+
**Stop a running daemon:**
|
|
86
112
|
|
|
87
113
|
```bash
|
|
88
|
-
#
|
|
89
|
-
prg job
|
|
114
|
+
# Send a stop signal to the default daemon
|
|
115
|
+
prg job stop
|
|
116
|
+
|
|
117
|
+
# Send a stop signal to a named daemon (uses /tmp/ruby-progress/<name>.pid)
|
|
118
|
+
prg job stop --daemon-name mytask
|
|
90
119
|
|
|
91
|
-
#
|
|
92
|
-
prg job
|
|
120
|
+
# Send a stop signal with a completion message
|
|
121
|
+
prg job stop --daemon-name mytask --message "Deployment complete!"
|
|
93
122
|
|
|
94
|
-
#
|
|
95
|
-
|
|
123
|
+
# Send a stop signal with a checkmark
|
|
124
|
+
prg job stop --daemon-name mytask --message "Build successful" --checkmark
|
|
96
125
|
|
|
97
|
-
#
|
|
98
|
-
prg job
|
|
126
|
+
# Send a stop signal indicating an error
|
|
127
|
+
prg job stop --daemon-name mytask --message "Build failed" --error
|
|
99
128
|
```
|
|
100
129
|
|
|
101
|
-
|
|
130
|
+
**Check daemon status:**
|
|
102
131
|
|
|
103
132
|
```bash
|
|
104
|
-
#
|
|
105
|
-
prg job
|
|
133
|
+
# Check if a daemon is running
|
|
134
|
+
prg job status --daemon-name mytask
|
|
106
135
|
|
|
107
|
-
#
|
|
108
|
-
prg job
|
|
136
|
+
# Check status using a PID file
|
|
137
|
+
prg job status --pid-file /tmp/ruby-progress/mytask.pid
|
|
138
|
+
```
|
|
109
139
|
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
# Start a named fill worker (non-detaching so animation remains visible)
|
|
113
|
-
prg fill --daemon-as demo --no-detach --output-lines 3 --output-position top
|
|
140
|
+
**Advance a progress indicator:**
|
|
114
141
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
prg job
|
|
118
|
-
prg job send --daemon-name demo --percent 100 --wait
|
|
119
|
-
```
|
|
142
|
+
```bash
|
|
143
|
+
# Advance progress by 1 (for indicators that support it)
|
|
144
|
+
prg job advance --daemon-name mytask
|
|
120
145
|
|
|
121
|
-
#
|
|
122
|
-
prg job
|
|
146
|
+
# Advance by a specific amount
|
|
147
|
+
prg job advance --daemon-name mytask --amount 10
|
|
123
148
|
```
|
|
124
149
|
|
|
125
|
-
|
|
150
|
+
**Backward Compatibility:**
|
|
126
151
|
|
|
127
|
-
|
|
152
|
+
The legacy `prg job send` command is still supported but deprecated. It functions identically to `prg job stop`:
|
|
128
153
|
|
|
129
154
|
```bash
|
|
130
|
-
#
|
|
131
|
-
prg
|
|
155
|
+
# This still works but shows a deprecation warning
|
|
156
|
+
prg job send --daemon-name mytask --message "Complete!"
|
|
132
157
|
```
|
|
133
158
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
- Jobs are written as JSON files into the daemon's job directory, which is derived from the daemon PID file. For example, a PID file `/tmp/ruby-progress/mytask.pid` maps to the job directory `/tmp/ruby-progress/mytask.jobs`.
|
|
137
|
-
- The CLI writes the job atomically by first writing a `*.json.tmp` temporary file and then renaming it to `*.json`.
|
|
138
|
-
- The daemon's job processor claims jobs atomically by renaming the job file to `*.processing`, writes a `*.processing.result` JSON file when finished, and moves processed jobs to `processed-*`.
|
|
139
|
-
|
|
140
|
-
This mechanism allows you to submit many commands to a single running indicator and have their output shown in reserved terminal rows while the animation continues.
|
|
141
|
-
|
|
142
|
-
## Job result schema
|
|
159
|
+
Alternatively, you can use the built-in `--stop` flags on the progress commands:
|
|
143
160
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
- `status` - `"done"` or `"error"`
|
|
148
|
-
- `time` - epoch seconds when the job finished (integer)
|
|
149
|
-
|
|
150
|
-
Depending on the job handler, additional keys may be present:
|
|
151
|
-
|
|
152
|
-
- `exit_status` - the numeric process exit status (integer or nil if unknown)
|
|
153
|
-
- `output` - a string with the last captured lines of output (if available)
|
|
154
|
-
- `error` - an error message when `status` is `error`
|
|
155
|
-
|
|
156
|
-
Example:
|
|
161
|
+
```bash
|
|
162
|
+
# Stop a named daemon with a success message
|
|
163
|
+
prg worm --stop-id demo --stop-success 'Task completed'
|
|
157
164
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
"id": "8a1f6c1e-4b7a-4f2c-b0a8-9e9f1c2f1a2b",
|
|
161
|
-
"status": "done",
|
|
162
|
-
"time": 1634044800,
|
|
163
|
-
"exit_status": 0,
|
|
164
|
-
"output": "Step 1 completed\nStep 2 completed"
|
|
165
|
-
}
|
|
165
|
+
# Stop with an error message
|
|
166
|
+
prg worm --stop-id demo --stop-error 'Task failed'
|
|
166
167
|
```
|
|
167
168
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
## Example: start a daemon and send a job (simple)
|
|
171
|
-
|
|
172
|
-
Below is an example script that demonstrates starting a worm daemon, sending a job, waiting for the result, and stopping the daemon.
|
|
173
|
-
---
|
|
169
|
+
## Example: background mode demo
|
|
174
170
|
|
|
175
|
-
|
|
171
|
+
Below is an example script that demonstrates starting a backgrounded progress indicator, doing work, and stopping it with a message.
|
|
176
172
|
|
|
177
173
|
```bash
|
|
178
|
-
# Start a named worm worker that
|
|
179
|
-
prg worm --daemon-as demo
|
|
174
|
+
# Start a named worm worker that runs in the background
|
|
175
|
+
prg worm --daemon-as demo
|
|
180
176
|
|
|
181
|
-
#
|
|
182
|
-
|
|
177
|
+
# Do some work in your script...
|
|
178
|
+
sleep 2
|
|
183
179
|
|
|
184
180
|
# Stop the worker with a success message
|
|
185
|
-
prg
|
|
181
|
+
prg job stop --daemon-name demo --message "Demo finished" --checkmark
|
|
186
182
|
```
|
|
187
183
|
|
|
188
|
-
Note
|
|
184
|
+
**Note:** Daemon mode automatically backgrounds the process using `Process.fork` and `Process.detach`, so you don't need to append `&`. The process detaches cleanly without shell job notifications.
|
|
189
185
|
|
|
190
186
|
## Ripple
|
|
191
187
|
|
data/bin/prg
CHANGED
|
@@ -24,14 +24,8 @@ module PrgCLI
|
|
|
24
24
|
# Handle `job` subcommands early
|
|
25
25
|
if ARGV[0] && ARGV[0].downcase == 'job'
|
|
26
26
|
ARGV.shift
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
when 'send'
|
|
30
|
-
JobCLI.send(ARGV)
|
|
31
|
-
else
|
|
32
|
-
puts 'job subcommands: send'
|
|
33
|
-
exit 1
|
|
34
|
-
end
|
|
27
|
+
JobCLI.run(ARGV)
|
|
28
|
+
exit
|
|
35
29
|
end
|
|
36
30
|
# Early scan: detect --ends flag and validate its argument before dispatching
|
|
37
31
|
if (i = ARGV.index('--ends')) && ARGV[i + 1]
|
|
@@ -151,16 +145,16 @@ module PrgCLI
|
|
|
151
145
|
# Spawn a background child but do NOT fully detach from the controlling
|
|
152
146
|
# terminal. This keeps the child attached to the same TTY so animations
|
|
153
147
|
# remain visible, while the parent exits immediately allowing the caller
|
|
154
|
-
# (shell or script) to continue.
|
|
155
|
-
# background worker (e.g. `--daemon-as NAME --no-detach`).
|
|
148
|
+
# (shell or script) to continue.
|
|
156
149
|
def self.backgroundize
|
|
157
150
|
pid = fork
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
#
|
|
151
|
+
if pid
|
|
152
|
+
# Parent: detach child and exit silently
|
|
153
|
+
Process.detach(pid)
|
|
154
|
+
exit(0)
|
|
155
|
+
end
|
|
156
|
+
# Child: create new process group but keep stdin/stdout/stderr
|
|
157
|
+
Process.setsid
|
|
164
158
|
end
|
|
165
159
|
|
|
166
160
|
# Attempt to stop processes for the given subcommand. Return true if any
|