ruby-progress 1.2.4 → 1.3.2
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 +26 -45
- data/CHANGELOG.md +38 -1
- data/Gemfile.lock +1 -1
- data/README.md +126 -133
- data/Rakefile +0 -3
- data/bin/prg +50 -0
- data/demo_screencast.rb +180 -36
- data/examples/daemon_job_example.sh +25 -0
- data/lib/ruby-progress/cli/fill_options.rb +73 -1
- data/lib/ruby-progress/cli/job_cli.rb +159 -0
- data/lib/ruby-progress/cli/ripple_cli.rb +88 -9
- data/lib/ruby-progress/cli/ripple_options.rb +22 -0
- data/lib/ruby-progress/cli/twirl_options.rb +30 -1
- data/lib/ruby-progress/cli/twirl_runner.rb +62 -5
- data/lib/ruby-progress/cli/twirl_spinner.rb +19 -2
- data/lib/ruby-progress/cli/worm_cli.rb +61 -19
- data/lib/ruby-progress/cli/worm_options.rb +32 -3
- data/lib/ruby-progress/cli/worm_runner.rb +37 -17
- data/lib/ruby-progress/daemon.rb +65 -0
- data/lib/ruby-progress/fill.rb +9 -3
- data/lib/ruby-progress/fill_cli.rb +189 -38
- data/lib/ruby-progress/output_capture.rb +136 -0
- data/lib/ruby-progress/ripple.rb +4 -2
- data/lib/ruby-progress/utils.rb +47 -26
- data/lib/ruby-progress/version.rb +6 -6
- data/lib/ruby-progress/worm.rb +8 -7
- data/screencast +26 -0
- metadata +5 -2
- data/ruby-progress.gemspec +0 -40
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c5a7ddc53059cb7f6d2b7bd1c066653058e1dbb281f4c23aa04229ce360a594
|
|
4
|
+
data.tar.gz: 0446a713142b93f16b9fe3e102c8a3c0db3194db17da25de7f1f7f31e5090907
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3cda8e32c95b8bd03d6c8549de1b3f4fc488f868cb028a554ddc44654428978bfd1db4178a1cb0a0a71c9a0c8ea46a1cc8da844c4026ef9b84ed45c1b43f4691
|
|
7
|
+
data.tar.gz: 39c31e85f87ea2201cbf3267fefedff1f4946f6bef9b1ee6178b8e1b5ecf8569a8391c20519582a1077bd6d352d229b01997ceedb358eeb049cf484c895028ed
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2025-10-
|
|
3
|
+
# on 2025-10-13 12:49:46 UTC using RuboCop version 1.75.7.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -22,11 +22,10 @@ Layout/TrailingEmptyLines:
|
|
|
22
22
|
Exclude:
|
|
23
23
|
- 'test_worm_flags.rb'
|
|
24
24
|
|
|
25
|
-
# Offense count:
|
|
25
|
+
# Offense count: 2
|
|
26
26
|
# Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
|
|
27
27
|
Lint/DuplicateBranch:
|
|
28
28
|
Exclude:
|
|
29
|
-
- 'bin/prg'
|
|
30
29
|
- 'lib/ruby-progress/utils.rb'
|
|
31
30
|
- 'lib/ruby-progress/worm.rb'
|
|
32
31
|
|
|
@@ -36,6 +35,12 @@ Lint/EmptyBlock:
|
|
|
36
35
|
Exclude:
|
|
37
36
|
- 'spec/worm_integration_spec.rb'
|
|
38
37
|
|
|
38
|
+
# Offense count: 1
|
|
39
|
+
# Configuration parameters: MaximumRangeSize.
|
|
40
|
+
Lint/MissingCopEnableDirective:
|
|
41
|
+
Exclude:
|
|
42
|
+
- 'lib/ruby-progress/fill_cli.rb'
|
|
43
|
+
|
|
39
44
|
# Offense count: 2
|
|
40
45
|
# This cop supports safe autocorrection (--autocorrect).
|
|
41
46
|
Lint/ScriptPermission:
|
|
@@ -43,63 +48,49 @@ Lint/ScriptPermission:
|
|
|
43
48
|
- 'demo_gem.rb'
|
|
44
49
|
- 'demo_worm_infinite.rb'
|
|
45
50
|
|
|
46
|
-
# Offense count:
|
|
47
|
-
Lint/SelfAssignment:
|
|
48
|
-
Exclude:
|
|
49
|
-
- 'lib/ruby-progress/ripple.rb'
|
|
50
|
-
|
|
51
|
-
# Offense count: 1
|
|
52
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
53
|
-
# Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
|
|
54
|
-
# NotImplementedExceptions: NotImplementedError
|
|
55
|
-
Lint/UnusedMethodArgument:
|
|
56
|
-
Exclude:
|
|
57
|
-
- 'lib/ruby-progress/worm.rb'
|
|
58
|
-
|
|
59
|
-
# Offense count: 23
|
|
51
|
+
# Offense count: 22
|
|
60
52
|
# This cop supports safe autocorrection (--autocorrect).
|
|
61
53
|
# Configuration parameters: AutoCorrect.
|
|
62
54
|
Lint/UselessAssignment:
|
|
63
55
|
Exclude:
|
|
64
56
|
- 'demo_gem.rb'
|
|
65
|
-
- 'lib/ruby-progress/worm.rb'
|
|
66
57
|
- 'spec/cli_integration_spec.rb'
|
|
67
58
|
|
|
68
|
-
# Offense count:
|
|
59
|
+
# Offense count: 52
|
|
69
60
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
|
70
61
|
Metrics/AbcSize:
|
|
71
|
-
Max:
|
|
62
|
+
Max: 122
|
|
72
63
|
|
|
73
|
-
# Offense count:
|
|
64
|
+
# Offense count: 49
|
|
74
65
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
75
66
|
# AllowedMethods: refine
|
|
76
67
|
Metrics/BlockLength:
|
|
77
|
-
Max:
|
|
68
|
+
Max: 111
|
|
78
69
|
|
|
79
|
-
# Offense count:
|
|
70
|
+
# Offense count: 4
|
|
80
71
|
# Configuration parameters: CountComments, CountAsOne.
|
|
81
72
|
Metrics/ClassLength:
|
|
82
|
-
Max:
|
|
73
|
+
Max: 268
|
|
83
74
|
|
|
84
|
-
# Offense count:
|
|
75
|
+
# Offense count: 30
|
|
85
76
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
86
77
|
Metrics/CyclomaticComplexity:
|
|
87
|
-
Max:
|
|
78
|
+
Max: 26
|
|
88
79
|
|
|
89
|
-
# Offense count:
|
|
80
|
+
# Offense count: 68
|
|
90
81
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
91
82
|
Metrics/MethodLength:
|
|
92
|
-
Max:
|
|
83
|
+
Max: 156
|
|
93
84
|
|
|
94
|
-
# Offense count:
|
|
85
|
+
# Offense count: 9
|
|
95
86
|
# Configuration parameters: CountComments, CountAsOne.
|
|
96
87
|
Metrics/ModuleLength:
|
|
97
|
-
Max:
|
|
88
|
+
Max: 285
|
|
98
89
|
|
|
99
|
-
# Offense count:
|
|
90
|
+
# Offense count: 31
|
|
100
91
|
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
101
92
|
Metrics/PerceivedComplexity:
|
|
102
|
-
Max:
|
|
93
|
+
Max: 27
|
|
103
94
|
|
|
104
95
|
# Offense count: 1
|
|
105
96
|
# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
|
@@ -110,7 +101,7 @@ Naming/FileName:
|
|
|
110
101
|
- 'Rakefile.rb'
|
|
111
102
|
- 'lib/ruby-progress.rb'
|
|
112
103
|
|
|
113
|
-
# Offense count:
|
|
104
|
+
# Offense count: 10
|
|
114
105
|
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
|
115
106
|
# SupportedStyles: snake_case, normalcase, non_integer
|
|
116
107
|
# AllowedIdentifiers: TLS1_1, TLS1_2, capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
|
|
@@ -127,15 +118,6 @@ Style/Documentation:
|
|
|
127
118
|
- 'lib/ruby-progress.rb'
|
|
128
119
|
- 'lib/ruby-progress/daemon.rb'
|
|
129
120
|
|
|
130
|
-
# Offense count: 4
|
|
131
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
132
|
-
# Configuration parameters: EnforcedStyle.
|
|
133
|
-
# SupportedStyles: allowed_in_returns, forbidden
|
|
134
|
-
Style/DoubleNegation:
|
|
135
|
-
Exclude:
|
|
136
|
-
- 'bin/prg'
|
|
137
|
-
- 'lib/ruby-progress/worm.rb'
|
|
138
|
-
|
|
139
121
|
# Offense count: 1
|
|
140
122
|
# This cop supports safe autocorrection (--autocorrect).
|
|
141
123
|
# Configuration parameters: AutoCorrect, EnforcedStyle, AllowComments.
|
|
@@ -167,14 +149,13 @@ Style/InfiniteLoop:
|
|
|
167
149
|
Exclude:
|
|
168
150
|
- 'lib/ruby-progress/ripple.rb'
|
|
169
151
|
|
|
170
|
-
# Offense count:
|
|
152
|
+
# Offense count: 1
|
|
171
153
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
172
154
|
# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns.
|
|
173
155
|
# SupportedStyles: predicate, comparison
|
|
174
156
|
Style/NumericPredicate:
|
|
175
157
|
Exclude:
|
|
176
158
|
- 'spec/**/*'
|
|
177
|
-
- 'bin/prg'
|
|
178
159
|
- 'lib/ruby-progress/ripple.rb'
|
|
179
160
|
|
|
180
161
|
# Offense count: 1
|
|
@@ -193,7 +174,7 @@ Style/StringLiterals:
|
|
|
193
174
|
Exclude:
|
|
194
175
|
- 'test_worm_flags.rb'
|
|
195
176
|
|
|
196
|
-
# Offense count:
|
|
177
|
+
# Offense count: 39
|
|
197
178
|
# This cop supports safe autocorrection (--autocorrect).
|
|
198
179
|
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
|
199
180
|
# URISchemes: http, https
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
# CHANGELOG
|
|
3
2
|
|
|
4
3
|
All notable changes to this project will be documented in this file.
|
|
@@ -6,6 +5,44 @@ All notable changes to this project will be documented in this file.
|
|
|
6
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
7
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
7
|
|
|
8
|
+
## 1.3.0 - 2025-10-12
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- PTY-based output capture: `RubyProgress::OutputCapture` now allows running commands under a PTY, keeps a rolling buffer of the last N lines for live redraw, and optionally writes the full streamed output to a `log_path` file.
|
|
13
|
+
- File-based daemon job queue: `RubyProgress::Daemon.process_jobs` implements atomic job enqueue/claim/processing with `.processing.result` metadata files and processed-archive behavior.
|
|
14
|
+
- `prg job send` CLI helper: atomically writes jobs to daemon job dirs and supports `--wait` to poll for results, `--daemon-name`, `--pid-file`, `--stdin`, and `--timeout`.
|
|
15
|
+
- Integration of job processing into Ripple/Twirl/Worm daemon modes so a running daemon can accept and display job output without interrupting animations.
|
|
16
|
+
- CLI options for output handling: `--output-position` and `--output-lines` to reserve terminal rows for captured output.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Job result files now merge any Hash returned by the job handler into the `.processing.result` JSON (e.g., `exit_status`, `output`, `log_path`).
|
|
21
|
+
|
|
22
|
+
### Tests
|
|
23
|
+
|
|
24
|
+
- Added unit and integration tests covering job enqueueing, processing, and result persistence.
|
|
25
|
+
|
|
26
|
+
### Release notes
|
|
27
|
+
|
|
28
|
+
- Merge commit: 99d9c39 (squash-merge of feature/output-handling)
|
|
29
|
+
|
|
30
|
+
## 1.3.2 - 2025-10-13
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- `fill` subcommand: added `-c, --command COMMAND` so the determinate progress bar can run and capture command output like the other subcommands. This includes `--output-lines` and `--output-position` support for reserving terminal rows during capture.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- Added `--stop-id NAME` shorthand for targeting named daemons (implies `--stop` and normalizes the name to the canonical PID filename). This is a small convenience used by the demo and scripts.
|
|
39
|
+
- Demo: updated `demo_screencast.rb` to call the local `bin/prg` when stopping the demo daemon to avoid conflicts with system-installed versions.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
- Bumped `FILL_VERSION` (patch) to reflect the new CLI behavior.
|
|
44
|
+
|
|
45
|
+
|
|
9
46
|
## 1.2.3 - 2025-10-11
|
|
10
47
|
|
|
11
48
|
### Added
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -8,6 +8,27 @@
|
|
|
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
|
+
## Table of Contents
|
|
12
|
+
|
|
13
|
+
- [Unified Interface](#unified-interface)
|
|
14
|
+
- [Submitting jobs to a running daemon](#submitting-jobs-to-a-running-daemon)
|
|
15
|
+
- [Job result schema](#job-result-schema)
|
|
16
|
+
- [Example: start a daemon and send a job (simple)](#example-start-a-daemon-and-send-a-job-simple)
|
|
17
|
+
- [Ripple](#ripple)
|
|
18
|
+
- [Ripple Features](#ripple-features)
|
|
19
|
+
- [Ripple Usage](#ripple-usage)
|
|
20
|
+
- [Twirl](#twirl)
|
|
21
|
+
- [Worm](#worm)
|
|
22
|
+
- [Daemon mode (background indicator)](#daemon-mode-background-indicator)
|
|
23
|
+
- [Requirements](#requirements)
|
|
24
|
+
- [Installation](#installation)
|
|
25
|
+
- [Universal Utilities](#universal-utilities)
|
|
26
|
+
- [Terminal Control](#terminal-control)
|
|
27
|
+
- [Completion Messages](#completion-messages)
|
|
28
|
+
- [Development](#development)
|
|
29
|
+
- [Contributing](#contributing)
|
|
30
|
+
- [License](#license)
|
|
31
|
+
|
|
11
32
|
## Unified Interface
|
|
12
33
|
|
|
13
34
|
The gem provides a unified `prg` command that supports all progress indicators through subcommands:
|
|
@@ -30,12 +51,12 @@ prg twirl --message "Working..." --style dots --speed fast
|
|
|
30
51
|
|
|
31
52
|
# Run fill directly (delegates to prg)
|
|
32
53
|
fill --report --percent 50
|
|
33
|
-
```
|
|
34
54
|
|
|
35
55
|
### With command execution
|
|
36
56
|
prg worm --command "sleep 5" --success "Completed!" --error "Failed!" --checkmark
|
|
37
57
|
prg ripple "Building..." --command "make build" --success "Build complete!" --stdout
|
|
38
58
|
prg twirl --command "npm install" --message "Installing packages" --style arc
|
|
59
|
+
prg fill --command "sleep 5" --success "Done!" --checkmark
|
|
39
60
|
|
|
40
61
|
### With start/end character decoration using --ends
|
|
41
62
|
prg ripple "Loading data" --ends "[]" --style rainbow
|
|
@@ -49,160 +70,123 @@ prg worm --message "Magic" --ends "🎯🎪" --style "custom=🟦🟨🟥"
|
|
|
49
70
|
### Global Options
|
|
50
71
|
|
|
51
72
|
- `prg --help` - Show main help
|
|
52
|
-
- `prg --version` - Show version info
|
|
53
|
-
- `prg --list-styles` - Show all available styles for all subcommands
|
|
54
|
-
- `prg <subcommand> --help` - Show specific subcommand help
|
|
55
73
|
|
|
56
|
-
|
|
74
|
+
Notes:
|
|
57
75
|
|
|
58
|
-
-
|
|
59
|
-
- `--
|
|
60
|
-
-
|
|
61
|
-
- `--
|
|
62
|
-
- `--error MESSAGE` - Error message on failure
|
|
63
|
-
- `--checkmark` - Show checkmarks (✅ success, 🛑 failure)
|
|
64
|
-
- `--stdout` - Output command results to STDOUT
|
|
65
|
-
- `--ends CHARS` - Start/end characters (even number of chars, split in half)
|
|
76
|
+
- The CLI detaches itself (double-fork); do not append `&`. This prevents shell job notifications like “job … has ended.” The command returns immediately.
|
|
77
|
+
- `--stop-success` and `--stop-error` are mutually exclusive; whichever you provide determines the success state and icon if `--stop-checkmark` is set.
|
|
78
|
+
- The indicator clears its line on shutdown and prints the final message to STDOUT.
|
|
79
|
+
- `--stop-pid` is still supported for backward compatibility, but `--stop [--pid-file FILE]` is preferred.
|
|
66
80
|
|
|
67
|
-
###
|
|
81
|
+
### Submitting jobs to a running daemon
|
|
68
82
|
|
|
69
|
-
|
|
83
|
+
When running a long-lived daemon (for example `prg worm --daemon`), you can submit additional commands to run and have their output displayed without disrupting the animation using the `prg job send` helper.
|
|
84
|
+
|
|
85
|
+
Basic usage:
|
|
70
86
|
|
|
71
87
|
```bash
|
|
72
|
-
|
|
73
|
-
prg
|
|
88
|
+
# Enqueue a command to the default daemon PID
|
|
89
|
+
prg job send --command "./deploy-step.sh"
|
|
74
90
|
|
|
75
|
-
|
|
76
|
-
prg
|
|
91
|
+
# Enqueue to a named daemon (creates /tmp/ruby-progress/<name>.pid)
|
|
92
|
+
prg job send --daemon-name mytask --command "rsync -av ./dist/ user@host:/srv/app"
|
|
77
93
|
|
|
78
|
-
|
|
94
|
+
# Read command from stdin (useful in scripts)
|
|
95
|
+
echo "bundle exec rake db:migrate" | prg job send --stdin --daemon-name mytask
|
|
79
96
|
|
|
80
|
-
|
|
81
|
-
prg
|
|
97
|
+
# Wait for the job result and print the job result JSON (default timeout 10s)
|
|
98
|
+
prg job send --daemon-name mytask --command "./deploy-step.sh" --wait --timeout 30
|
|
99
|
+
```
|
|
82
100
|
|
|
83
|
-
|
|
84
|
-
prg worm --stop-id mytask --stop-success "Task complete!" --stop-checkmark
|
|
101
|
+
You can also send control/action jobs (no shell command) to a running daemon. These are JSON payloads with an `action` key handled by the daemon's job processor. The helper supports a few common actions:
|
|
85
102
|
|
|
86
|
-
|
|
87
|
-
|
|
103
|
+
```bash
|
|
104
|
+
# Send a simple 'advance' action (no value)
|
|
105
|
+
prg job send --daemon-name demo --advance
|
|
106
|
+
|
|
107
|
+
# Send a 'percent' action with a numeric value
|
|
108
|
+
prg job send --daemon-name demo --percent 42
|
|
88
109
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
110
|
+
# Example using `fill` as a named daemon and sending percent updates
|
|
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
|
|
92
114
|
|
|
93
|
-
|
|
94
|
-
prg
|
|
95
|
-
prg
|
|
96
|
-
prg
|
|
115
|
+
# Send percent updates to the named worker
|
|
116
|
+
prg job send --daemon-name demo --percent 10 --wait
|
|
117
|
+
prg job send --daemon-name demo --percent 50 --wait
|
|
118
|
+
prg job send --daemon-name demo --percent 100 --wait
|
|
97
119
|
```
|
|
98
120
|
|
|
99
|
-
|
|
121
|
+
# Or use the generic action/value pair
|
|
122
|
+
prg job send --daemon-name demo --action percent --value 42
|
|
123
|
+
```
|
|
100
124
|
|
|
101
|
-
|
|
102
|
-
- `--stop-success` and `--stop-error` are mutually exclusive; whichever you provide determines the success state and icon if `--stop-checkmark` is set.
|
|
103
|
-
- The indicator clears its line on shutdown and prints the final message to STDOUT.
|
|
104
|
-
- `--stop-pid` is still supported for backward compatibility, but `--stop [--pid-file FILE]` is preferred.
|
|
105
|
-
o- [Ruby Progress Indicators](#ruby-progress-indicators)
|
|
106
|
-
- [Unified Interface](#unified-interface)
|
|
107
|
-
- [With command execution](#with-command-execution)
|
|
108
|
-
- [With start/end character decoration using --ends](#with-startend-character-decoration-using-ends)
|
|
109
|
-
- [Complex --ends patterns with emojis](#complex-ends-patterns-with-emojis)
|
|
110
|
-
- [Start in background (uses default PID file)](#start-in-background-uses-default-pid-file)
|
|
111
|
-
- [Start with a custom name (creates /tmp/ruby-progress/NAME.pid)](#start-with-a-custom-name-creates-tmpruby-progressnamepid)
|
|
112
|
-
- [... run your tasks ...](#-run-your-tasks-)
|
|
113
|
-
- [Stop with a success message and checkmark (--stop-success implies --stop)](#stop-with-a-success-message-and-checkmark-stop-success-implies-stop)
|
|
114
|
-
- [Stop a named daemon (--stop-id implies --stop)](#stop-a-named-daemon-stop-id-implies-stop)
|
|
115
|
-
- [Or stop with an error message and checkmark](#or-stop-with-an-error-message-and-checkmark)
|
|
116
|
-
- [Check status at any time](#check-status-at-any-time)
|
|
117
|
-
- [Use a completely custom PID file path](#use-a-completely-custom-pid-file-path)
|
|
118
|
-
- [Basic text animation](#basic-text-animation)
|
|
119
|
-
- [With style options](#with-style-options)
|
|
120
|
-
- [Multiple styles combined](#multiple-styles-combined)
|
|
121
|
-
- [Case transformation mode](#case-transformation-mode)
|
|
122
|
-
- [Run a command with progress animation](#run-a-command-with-progress-animation)
|
|
123
|
-
- [Simple progress block](#simple-progress-block)
|
|
124
|
-
- [With options](#with-options)
|
|
125
|
-
- [Basic spinner animation](#basic-spinner-animation)
|
|
126
|
-
- [With command execution](#with-command-execution)
|
|
127
|
-
- [Different spinner styles](#different-spinner-styles)
|
|
128
|
-
- [With success/error handling](#with-successerror-handling)
|
|
129
|
-
- [Daemon mode for background tasks](#daemon-mode-for-background-tasks)
|
|
130
|
-
- [... do other work ...](#-do-other-work-)
|
|
131
|
-
- [Run indefinitely without a command (like ripple)](#run-indefinitely-without-a-command-like-ripple)
|
|
132
|
-
- [Run a command with progress animation](#run-a-command-with-progress-animation)
|
|
133
|
-
- [Customize the animation](#customize-the-animation)
|
|
134
|
-
- [With custom error handling](#with-custom-error-handling)
|
|
135
|
-
- [With checkmarks for visual feedback](#with-checkmarks-for-visual-feedback)
|
|
136
|
-
- [Control animation direction (forward-only or bidirectional)](#control-animation-direction-forward-only-or-bidirectional)
|
|
137
|
-
- [Create custom animations with 3-character patterns](#create-custom-animations-with-3-character-patterns)
|
|
138
|
-
- [Add start/end characters around the animation](#add-startend-characters-around-the-animation)
|
|
139
|
-
- [Capture and display command output](#capture-and-display-command-output)
|
|
140
|
-
- [Combine checkmarks and stdout output](#combine-checkmarks-and-stdout-output)
|
|
141
|
-
- [Start in the background (default PID file: /tmp/ruby-progress/progress.pid)](#start-in-the-background-default-pid-file-tmpruby-progressprogresspid)
|
|
142
|
-
- [... run your tasks ...](#-run-your-tasks-)
|
|
143
|
-
- [Stop using the default PID file](#stop-using-the-default-pid-file)
|
|
144
|
-
- [Use a custom PID file](#use-a-custom-pid-file)
|
|
145
|
-
- [Stop using the matching custom PID file](#stop-using-the-matching-custom-pid-file)
|
|
146
|
-
- [Create and run animation with a block](#create-and-run-animation-with-a-block)
|
|
147
|
-
- [Your work here](#your-work-here)
|
|
148
|
-
- [With custom style and forward direction](#with-custom-style-and-forward-direction)
|
|
149
|
-
- [Or run with a command](#or-run-with-a-command)
|
|
150
|
-
- [ASCII characters](#ascii-characters)
|
|
151
|
-
- [Unicode characters](#unicode-characters)
|
|
152
|
-
- [Emojis (supports multi-byte characters)](#emojis-supports-multi-byte-characters)
|
|
153
|
-
- [Mixed ASCII and emoji](#mixed-ascii-and-emoji)
|
|
154
|
-
- [Cursor control](#cursor-control)
|
|
155
|
-
- [Basic completion message](#basic-completion-message)
|
|
156
|
-
- [With success/failure indication and checkmarks](#with-successfailure-indication-and-checkmarks)
|
|
157
|
-
- [Clear line and display completion (useful for replacing progress indicators)](#clear-line-and-display-completion-useful-for-replacing-progress-indicators)
|
|
125
|
+
Note about stopping named daemons:
|
|
158
126
|
|
|
159
|
-
|
|
127
|
+
You can target named daemons directly using the `--stop-id NAME` shorthand which implies `--stop` and targets the named daemon (it is normalized to the canonical daemon name used for the PID file). This is convenient for scripts and demos. Example:
|
|
160
128
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
- [Completion Messages](#completion-messages)
|
|
200
|
-
- [Contributing](#contributing)
|
|
201
|
-
- [License](#license)
|
|
129
|
+
```bash
|
|
130
|
+
# Stop a named fill worker with a success message
|
|
131
|
+
prg fill --stop-id demo --stop-success 'Demo finished'
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Behavior and file layout:
|
|
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
|
|
143
|
+
|
|
144
|
+
When a job is processed the daemon writes a small JSON result file next to the claimed job with the suffix `.processing.result` containing at least these keys:
|
|
145
|
+
|
|
146
|
+
- `id` - the job id (string)
|
|
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:
|
|
157
|
+
|
|
158
|
+
```json
|
|
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
|
+
}
|
|
166
|
+
```
|
|
202
167
|
|
|
168
|
+
This file is intended for short messages and small captured output snippets (the CLI captures the last N lines). If you need larger logs, write them to a persistent file from the command itself and include a reference in the job metadata.
|
|
203
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.
|
|
204
173
|
---
|
|
205
174
|
|
|
175
|
+
If you want the background worker to continue writing to the same terminal (so you can visually watch the animation while your script continues), use the non-detaching background mode:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Start a named worm worker that backgrounds but does not fully detach
|
|
179
|
+
prg worm --daemon-as demo --no-detach
|
|
180
|
+
|
|
181
|
+
# In the same script or a subsequent command, enqueue a job to that worker
|
|
182
|
+
prg job send --daemon-name demo --command "echo hello; sleep 1; echo done" --wait
|
|
183
|
+
|
|
184
|
+
# Stop the worker with a success message
|
|
185
|
+
prg worm --stop-id demo --stop-success "Demo finished"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Note: Non-detaching mode keeps the child process attached to the controlling TTY. That means both the worker and the invoking shell may write to the terminal and outputs can interleave.
|
|
189
|
+
|
|
206
190
|
## Ripple
|
|
207
191
|
|
|
208
192
|
Ripple is a sophisticated text animation library that creates ripple effects across text strings in the terminal. It supports various animation modes including bidirectional movement, and rainbow colors.
|
|
@@ -407,6 +391,15 @@ prg worm --message "Emoji ends" --ends "🎯🎪" --style "custom=🟦🟨🟥"
|
|
|
407
391
|
### Capture and display command output
|
|
408
392
|
prg worm --command "git status" --message "Checking status" --stdout
|
|
409
393
|
|
|
394
|
+
You can reserve terminal rows for captured command output so the animation doesn't interleave with the script output. Use:
|
|
395
|
+
|
|
396
|
+
- `--output-position POSITION` — `above` (default) or `below` the animation
|
|
397
|
+
- `--output-lines N` — how many terminal rows to reserve for captured output (default: 3)
|
|
398
|
+
|
|
399
|
+
Examples:
|
|
400
|
+
|
|
401
|
+
prg worm --command "git status" --stdout --output-position above --output-lines 4
|
|
402
|
+
|
|
410
403
|
### Combine checkmarks and stdout output
|
|
411
404
|
prg worm --command "echo 'Build output'" --success "Build complete!" --checkmark --stdout
|
|
412
405
|
```
|
data/Rakefile
CHANGED
|
@@ -108,7 +108,6 @@ namespace :markdown do
|
|
|
108
108
|
!!(line =~ /^\s*```|^\s*~~~/)
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
112
111
|
def format_markdown(content)
|
|
113
112
|
lines = content.split("\n", -1)
|
|
114
113
|
out = []
|
|
@@ -167,8 +166,6 @@ namespace :markdown do
|
|
|
167
166
|
out << '' if (last = out.last) && !last.empty?
|
|
168
167
|
out.join("\n")
|
|
169
168
|
end
|
|
170
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
171
|
-
|
|
172
169
|
desc 'Lint markdown (reports files that would be changed)'
|
|
173
170
|
task :lint do
|
|
174
171
|
changed = []
|
data/bin/prg
CHANGED
|
@@ -7,6 +7,7 @@ require 'optparse'
|
|
|
7
7
|
require 'json'
|
|
8
8
|
require 'English'
|
|
9
9
|
|
|
10
|
+
require_relative '../lib/ruby-progress/cli/job_cli'
|
|
10
11
|
# Load extracted per-subcommand CLI modules
|
|
11
12
|
require_relative '../lib/ruby-progress/cli/ripple_cli'
|
|
12
13
|
require_relative '../lib/ruby-progress/cli/worm_cli'
|
|
@@ -20,6 +21,18 @@ module PrgCLI
|
|
|
20
21
|
exit 1
|
|
21
22
|
end
|
|
22
23
|
|
|
24
|
+
# Handle `job` subcommands early
|
|
25
|
+
if ARGV[0] && ARGV[0].downcase == 'job'
|
|
26
|
+
ARGV.shift
|
|
27
|
+
sub = ARGV.shift
|
|
28
|
+
case sub
|
|
29
|
+
when 'send'
|
|
30
|
+
JobCLI.send(ARGV)
|
|
31
|
+
else
|
|
32
|
+
puts 'job subcommands: send'
|
|
33
|
+
exit 1
|
|
34
|
+
end
|
|
35
|
+
end
|
|
23
36
|
# Early scan: detect --ends flag and validate its argument before dispatching
|
|
24
37
|
if (i = ARGV.index('--ends')) && ARGV[i + 1]
|
|
25
38
|
ends_val = ARGV[i + 1]
|
|
@@ -113,6 +126,43 @@ module PrgCLI
|
|
|
113
126
|
puts '== fill =='
|
|
114
127
|
end
|
|
115
128
|
|
|
129
|
+
# Detach the current process into a background daemon. Uses Process.daemon
|
|
130
|
+
# when available, otherwise falls back to a basic fork/exit helper. This is
|
|
131
|
+
# intentionally simple for the test environment.
|
|
132
|
+
def self.daemonize
|
|
133
|
+
if Process.respond_to?(:daemon)
|
|
134
|
+
Process.daemon(true)
|
|
135
|
+
else
|
|
136
|
+
pid = fork
|
|
137
|
+
if pid
|
|
138
|
+
# parent exits so child can continue as daemon
|
|
139
|
+
exit(0)
|
|
140
|
+
else
|
|
141
|
+
# child: detach from controlling terminal
|
|
142
|
+
begin
|
|
143
|
+
Process.setsid
|
|
144
|
+
rescue StandardError
|
|
145
|
+
nil
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Spawn a background child but do NOT fully detach from the controlling
|
|
152
|
+
# terminal. This keeps the child attached to the same TTY so animations
|
|
153
|
+
# remain visible, while the parent exits immediately allowing the caller
|
|
154
|
+
# (shell or script) to continue. Use when the user requests a non-detaching
|
|
155
|
+
# background worker (e.g. `--daemon-as NAME --no-detach`).
|
|
156
|
+
def self.backgroundize
|
|
157
|
+
pid = fork
|
|
158
|
+
return unless pid
|
|
159
|
+
|
|
160
|
+
# parent: exit so the invoking shell/script continues
|
|
161
|
+
exit(0)
|
|
162
|
+
|
|
163
|
+
# child: continue without setsid/IO close so output remains on the TTY
|
|
164
|
+
end
|
|
165
|
+
|
|
116
166
|
# Attempt to stop processes for the given subcommand. Return true if any
|
|
117
167
|
# process was signaled/stopped; false otherwise. Keep quiet on missing
|
|
118
168
|
# processes to satisfy integration tests.
|