ruby-progress 1.3.4 → 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.
data/README.md CHANGED
@@ -2,32 +2,56 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/ruby-progress.svg)](https://badge.fury.io/rb/ruby-progress)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
- [![RSpec Tests](https://github.com/ttscoff/ruby-progress/actions/workflows/rspec.yml/badge.svg)](https://github.com/ttscoff/ruby-progress/actions/workflows/rspec.yml)
5
+ <!-- [![RSpec Tests](https://github.com/ttscoff/ruby-progress/actions/workflows/rspec.yml/badge.svg)](https://github.com/ttscoff/ruby-progress/actions/workflows/rspec.yml) -->
6
6
  [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%202.5.0-ruby.svg)](https://www.ruby-lang.org/)
7
- [![Coverage Status](https://img.shields.io/badge/coverage-55%25-yellow.svg)](#)
7
+ <!-- [![Coverage Status](https://img.shields.io/badge/coverage-31%25-yellow.svg)](#) -->
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
- - [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)
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
- ### Submitting jobs to a running daemon
105
+ ### Stopping a backgrounded progress indicator
82
106
 
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.
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
- Basic usage:
109
+ #### Job Control Subcommands
110
+
111
+ **Stop a running daemon:**
86
112
 
87
113
  ```bash
88
- # Enqueue a command to the default daemon PID
89
- prg job send --command "./deploy-step.sh"
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
- # 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"
120
+ # Send a stop signal with a completion message
121
+ prg job stop --daemon-name mytask --message "Deployment complete!"
93
122
 
94
- # Read command from stdin (useful in scripts)
95
- echo "bundle exec rake db:migrate" | prg job send --stdin --daemon-name mytask
123
+ # Send a stop signal with a checkmark
124
+ prg job stop --daemon-name mytask --message "Build successful" --checkmark
96
125
 
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
126
+ # Send a stop signal indicating an error
127
+ prg job stop --daemon-name mytask --message "Build failed" --error
99
128
  ```
100
129
 
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:
130
+ **Check daemon status:**
102
131
 
103
132
  ```bash
104
- # Send a simple 'advance' action (no value)
105
- prg job send --daemon-name demo --advance
133
+ # Check if a daemon is running
134
+ prg job status --daemon-name mytask
106
135
 
107
- # Send a 'percent' action with a numeric value
108
- prg job send --daemon-name demo --percent 42
136
+ # Check status using a PID file
137
+ prg job status --pid-file /tmp/ruby-progress/mytask.pid
138
+ ```
109
139
 
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
140
+ **Advance a progress indicator:**
114
141
 
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
119
- ```
142
+ ```bash
143
+ # Advance progress by 1 (for indicators that support it)
144
+ prg job advance --daemon-name mytask
120
145
 
121
- # Or use the generic action/value pair
122
- prg job send --daemon-name demo --action percent --value 42
146
+ # Advance by a specific amount
147
+ prg job advance --daemon-name mytask --amount 10
123
148
  ```
124
149
 
125
- Note about stopping named daemons:
150
+ **Backward Compatibility:**
126
151
 
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:
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
- # Stop a named fill worker with a success message
131
- prg fill --stop-id demo --stop-success 'Demo finished'
155
+ # This still works but shows a deprecation warning
156
+ prg job send --daemon-name mytask --message "Complete!"
132
157
  ```
133
158
 
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
159
+ Alternatively, you can use the built-in `--stop` flags on the progress commands:
143
160
 
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:
161
+ ```bash
162
+ # Stop a named daemon with a success message
163
+ prg worm --stop-id demo --stop-success 'Task completed'
157
164
 
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
- }
165
+ # Stop with an error message
166
+ prg worm --stop-id demo --stop-error 'Task failed'
166
167
  ```
167
168
 
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.
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
- 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:
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 backgrounds but does not fully detach
179
- prg worm --daemon-as demo --no-detach
174
+ # Start a named worm worker that runs in the background
175
+ prg worm --daemon-as demo
180
176
 
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
177
+ # Do some work in your script...
178
+ sleep 2
183
179
 
184
180
  # Stop the worker with a success message
185
- prg worm --stop-id demo --stop-success "Demo finished"
181
+ prg job stop --daemon-name demo --message "Demo finished" --checkmark
186
182
  ```
187
183
 
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.
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
- 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
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. Use when the user requests a non-detaching
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
- 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
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
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env sh
2
- # Example: start a worm daemon, send a job, wait for result, then stop.
2
+ # Example: start a worm in background mode, do some work, then stop it with a message.
3
3
  # This script assumes you're running from the project root and have a working
4
4
  # `bin/prg` script in the repository.
5
5
 
@@ -8,18 +8,16 @@ set -eu
8
8
  PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
9
9
  PRG_BIN="$PROJECT_ROOT/bin/prg"
10
10
 
11
- echo "Starting worm daemon (named 'example')..."
12
- # prg detaches in daemon mode so no & needed
13
- $PRG_BIN worm --daemon-as example --message "Example daemon"
11
+ echo "Starting worm in background mode (named 'example')..."
12
+ # Use --no-detach to keep it visible in the current terminal for demos
13
+ $PRG_BIN worm --daemon-as example --no-detach --message "Example running..." &
14
14
 
15
- sleep 0.2
15
+ sleep 0.5
16
16
 
17
- echo "Sending job and waiting for result..."
18
- $PRG_BIN job send --daemon-name example --command "echo hello; sleep 0.1" --wait --timeout 10
19
-
20
- sleep 0.1
17
+ echo "Doing some work..."
18
+ sleep 2
21
19
 
22
20
  echo "Stopping daemon with success message..."
23
- $PRG_BIN worm --stop-success "Example finished" --stop-checkmark --daemon-name example
21
+ $PRG_BIN job send --daemon-name example --message "Example finished" --checkmark
24
22
 
25
23
  echo "Done."
@@ -5,7 +5,7 @@ require 'optparse'
5
5
  module RubyProgress
6
6
  module FillCLI
7
7
  # Option parsing extracted to reduce module length in FillCLI
8
- # rubocop:disable Metrics/AbcSize, Metrics/BlockLength
8
+ # rubocop:disable Metrics/AbcSize
9
9
  module Options
10
10
  # rubocop :disable Metrics/MethodLength
11
11
  def self.parse_cli_options
@@ -146,10 +146,6 @@ module RubyProgress
146
146
  options[:daemon_name] = name
147
147
  end
148
148
 
149
- opts.on('--no-detach', 'When used with --daemon/--daemon-as: run background child but do not fully detach from the terminal') do
150
- options[:no_detach] = true
151
- end
152
-
153
149
  opts.on('--pid-file FILE', 'PID file location (default: /tmp/ruby-progress/fill.pid)') do |file|
154
150
  options[:pid_file] = file
155
151
  end
@@ -266,6 +262,6 @@ module RubyProgress
266
262
  opts.to_s
267
263
  end
268
264
  end
269
- # rubocop:enable Metrics/AbcSize, Metrics/BlockLength
265
+ # rubocop:enable Metrics/AbcSize
270
266
  end
271
267
  end