ruby-progress 1.3.5 → 1.3.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a22fcfc5ae8ffc222ac1f19f4d7b5295f9205c8ae95bce7ec8be8884e076f578
4
- data.tar.gz: f96675ec9f6bcc1e6dd905763b45ea776bbf3f78f57629fc50a2cac4a13d22b2
3
+ metadata.gz: ed28989b5200a0ba018f976c1b7b90b8077916959633a5e2ea576de25bb6ddb5
4
+ data.tar.gz: f5c0ddea618bad931125e8f3195162e3cae7405c583fe27da5759d0febf30fa1
5
5
  SHA512:
6
- metadata.gz: 4a61a58643c367f94645d5f3fded92473c44f72ee17553f47f89e27403780cbb3c7bb0fb3a3b36876be8928162434cd28aa847ef6e2ec488ec115c64f06bee2e
7
- data.tar.gz: 9a7eda5a91f80ea1be162bb6bd250da3134f0567fa1c47f6c9e782f6aa80e16ed379e60da48a1ebd59f44dcb80a50cc92467ed9ec42be7196ceb973be66113fb
6
+ metadata.gz: 6722478a39177ac8c8618035abbd0b155afc275eb53120c7c89ff9f7a0c2194a02313efb5cf19ec59205d5f8002435edbef41c7cf5590f7e5f30ad00fa10f02d
7
+ data.tar.gz: 861feef40116e9c4a5f1c18e2455032a286c9c38fd7bccca19d24c1438b2554be90db4b5c820421b87301b4f21a3527a9bb17095c35140cf4ddddd0d8551539a
data/CHANGELOG.md CHANGED
@@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.7] - 2025-10-22
9
+
10
+ ### Fixed
11
+
12
+ - PTY command spawning now executes via the user's login shell to support shell aliases/functions and ensure PATH customizations are honored.
13
+ - Uses `ENV['SHELL']` when available (fallback `/bin/sh`).
14
+ - `bash`/`zsh`/`sh`: `-lc` is used; `fish`: `-l -c` is used.
15
+ - Resolves `Errno::ENOENT` when running commands like `-c 'r fast'` under `--stdout-live`.
16
+
17
+ ### Changed
18
+
19
+ - Refactored output capture internals:
20
+ - Introduced `RubyProgress::ShellExec.build_shell_argv` for shell argv construction.
21
+ - Extracted terminal reservation to `RubyProgress::OutputUI.reserve_space`.
22
+ - Reduced method complexity and addressed linter warnings without behavior changes.
23
+
24
+ ## [1.3.6] - 2025-10-15
25
+
26
+ ### Fixed
27
+
28
+ - **Interrupt handling**: Fixed Twirl and Worm CLIs to exit cleanly on Ctrl+C (SIGINT) without displaying backtraces
29
+ - Added top-level `trap('INT')` handlers to both `twirl_cli.rb` and `worm_cli.rb`
30
+ - Added `rescue Interrupt` clauses to Twirl runner methods for graceful cleanup
31
+ - All four progress indicators (Ripple, Worm, Twirl, Fill) now have consistent interrupt handling
32
+ - Properly clean up (show cursor, clear line) and exit with code 130 on interrupt
33
+
8
34
  ## [1.3.5] - 2025-10-15
9
35
 
10
36
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-progress (1.3.5)
4
+ ruby-progress (1.3.7)
5
5
  tty-cursor (~> 0.7)
6
6
  tty-screen (~> 0.8)
7
7
 
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%202.5.0-ruby.svg)](https://www.ruby-lang.org/)
7
7
  <!-- [![Coverage Status](https://img.shields.io/badge/coverage-31%25-yellow.svg)](#) -->
8
8
 
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.
9
+ This repository contains a collection of Ruby progress indicator projects: **Ripple**, **Worm**, **Twirl**, and **Fill**. All provide animated terminal progress indicators with different visual styles and features.
10
10
 
11
11
  ## Table of Contents
12
12
 
data/blog-post.md CHANGED
@@ -1,39 +1,154 @@
1
1
  ---
2
- title: "More CLI Progress Indicators: The ruby-progress Gem"
3
- date: 2025-10-10
2
+ title: "Ruby Progress Indicators for Modern CLI Tools"
3
+ date: 2025-10-15 11:00
4
4
  categories: [Ruby, CLI, Development Tools]
5
- tags: [ruby, cli, progress, animation, terminal]
5
+ tags: [ruby, cli, progress, animation, terminal, daemon]
6
6
  ---
7
+ I've been playing around with progress bars in the terminal, and I think I've
8
+ created something genuinely useful.
7
9
 
8
- [ripple]: https://brettterpstra.com/2025/06/30/ripple-an-indeterminate-progress-indicator/
10
+ Yes, I know there are multiple options
11
+ already available for this, but I wanted something specific: a Ruby library that
12
+ could be used for command-line scripting, with CLI executables that made it easy
13
+ to use when scripting in *any* language --- not just Ruby.
9
14
 
10
- # More CLI Progress Indicators: The ruby-progress Gem
15
+ The result is `ruby-progress`, a gem that provides four different animated
16
+ progress indicators, each with its own visual style and use cases.
11
17
 
12
- The `ruby-progress` gem expands my previous work on [Ripple], adding 2 more indicator types and a new daemon mode to make it more useful in non-Ruby shell scripts.
18
+ > If you're scripting in Ruby, I do highly recommend the TTY tools from [Piotr Murach](piotrmurach),
19
+ such as [tty-progress](https://github.com/piotrmurach/tty-progressbar/). Piotr's
20
+ TTY tools are much more elegant with a better Ruby API. `ruby-progress` is
21
+ designed more for use in other shell scripts than it is for detailed Ruby
22
+ scripting.
23
+ {:.tip}
13
24
 
14
- ## What is ruby-progress?
25
+ {% gif /uploads/2025/10/ruby-progress.mp4 %}
15
26
 
16
- Ruby-progress provides animated progress indicators for command-line applications. Unlike traditional progress bars showing completion percentage, this gem focuses on continuous animations (indeterminate) that indicate activity - perfect for tasks with unpredictable completion times.
27
+ ## The Four Progress Indicators
17
28
 
18
- Three animation styles are available:
29
+ Ripple
30
+ : creates a wave-like effect across text, with the characters rippling
31
+ through different visual states. It supports rainbow colors, inverse
32
+ highlighting, and case transformations. Perfect for text-heavy operations where
33
+ you want something more dynamic than a simple spinner.
19
34
 
20
- - **Ripple**: Wave-like effect across text
21
- - **Worm**: Moving dot pattern that crawls across the screen
22
- - **Twirl**: Classic spinning indicators with various symbols
35
+ Worm
36
+ : displays a moving dot pattern that crawls across the screen using
37
+ Unicode characters. It includes multiple styles (circles, blocks, geometric
38
+ shapes) and can move in any direction. Great for file operations, network
39
+ transfers, or any continuous background task.
23
40
 
24
- ## Quick Start
41
+ Twirl
42
+ : provides classic spinning indicators with over 35 different spinner
43
+ styles --- from simple dots to complex geometric patterns. It's the most
44
+ traditional of the four, but with way more visual variety than typical spinners.
45
+
46
+ Fill : is the only determinate indicator in the bunch --- an actual progress bar
47
+ that shows completion percentage. It can be controlled via command execution or
48
+ updated programmatically through daemon control messages.
49
+
50
+ ## Installation and Quick Start
51
+
52
+ Installation is straightforward:
25
53
 
26
54
  ```bash
27
- # Install
28
55
  gem install ruby-progress
56
+ ```
57
+
58
+ All four indicators are available through a unified `prg` command:
29
59
 
60
+ ```bash
30
61
  # Basic usage
31
- ripple "Processing files..."
32
- worm --message "Loading..." --speed fast
33
- twirl --spinner dots
62
+ prg ripple "Processing files..."
63
+ prg worm --message "Loading..." --style blocks
64
+ prg twirl --message "Working..." --style dots --speed fast
65
+ prg fill --total 100 --report
66
+
67
+ # With command execution
68
+ prg ripple "Building..." --command "make build" --success "Build complete!" --checkmark
69
+ ```
70
+
71
+ You can also use the individual commands directly: `ripple`, `worm`, `twirl`, and `fill`.
72
+
73
+ ## The Killer Feature: Daemon Mode
74
+
75
+ Here's where things get interesting. All four indicators support daemon mode,
76
+ which lets you run a progress indicator in the background while your scripts
77
+ execute other commands. This is useful for complex workflows.
78
+
79
+ ```bash
80
+ # Start a background spinner
81
+ prg worm --daemon-as deployment --message "Deploying application..."
82
+
83
+ # Execute your actual deployment steps
84
+ git push production main
85
+ kubectl apply -f manifests/
86
+ ./run-migrations.sh
87
+
88
+ # Stop the spinner with a success message
89
+ prg job stop --daemon-name deployment --message "Deployment complete!" --checkmark
90
+ ```
91
+
92
+ The daemon mode uses `Process.fork` and `Process.detach`, so there are no shell
93
+ job notifications cluttering your output. The progress indicator runs cleanly in
94
+ the background, providing visual feedback without interfering with your script's
95
+ execution.
96
+
97
+ ### Keeping Output Clean
98
+
99
+ One of the challenges with daemon mode is preventing command output from
100
+ disrupting the animation. By default, when you run a progress indicator in
101
+ daemon mode, any STDOUT or STDERR output from commands executed in your script
102
+ will appear on the terminal and potentially mess up the animation display.
103
+
104
+ Ruby-progress handles this intelligently. When running in daemon mode, the
105
+ animation continues on its dedicated line while your commands execute. However,
106
+ if you want to see the output from those commands, you have options:
107
+
108
+ ```bash
109
+ # Run command with animation, show output after completion
110
+ prg ripple "Building..." --command "make build" --stdout
111
+
112
+ # Stream output live while animation runs (reserves terminal rows)
113
+ prg worm "Installing..." --command "npm install" --stdout-live --output-lines 5
114
+
115
+ # Run daemon and manually capture output from your script commands
116
+ prg worm --daemon-as build --message "Building..."
117
+ make build > /tmp/build.log 2>&1
118
+ prg job stop --daemon-name build --message "Build complete!" --checkmark
119
+ cat /tmp/build.log
120
+ ```
121
+
122
+ The `--stdout-live` flag is particularly useful --- it reserves a section of the
123
+ terminal to display live command output while the animation continues above or
124
+ below it. You control how many lines to reserve with `--output-lines` and where
125
+ they appear with `--output-position` (above or below the animation).
126
+
127
+ ### Job Control Commands
128
+
129
+ The `prg job` command provides subcommands for controlling background indicators:
130
+
131
+ - `prg job stop` --- Stop a running daemon with an optional message
132
+ - `prg job status` --- Check if a daemon is running and show its PID
133
+ - `prg job advance` --- Update a fill progress bar by a specific amount
134
+
135
+ ```bash
136
+ # Check if a daemon is running
137
+ prg job status --daemon-name mytask
138
+
139
+ # Advance a progress bar remotely
140
+ prg fill --daemon-as progress --total 100
141
+ prg job advance --daemon-name progress --amount 10
142
+
143
+ # Stop with error state
144
+ prg job stop --daemon-name mytask --message "Build failed!" --error
34
145
  ```
35
146
 
36
- ## Ruby Integration
147
+ {% paywall "Library and advanced usage" %}
148
+
149
+ ## Ruby Library Usage
150
+
151
+ While the CLI is great for shell scripting, the Ruby API is just as elegant:
37
152
 
38
153
  ```ruby
39
154
  require 'ruby-progress'
@@ -44,131 +159,108 @@ RubyProgress::Ripple.progress("Processing files...") do
44
159
  upload_results
45
160
  end
46
161
 
47
- # Manual control
162
+ # Manual control for complex scenarios
48
163
  worm = RubyProgress::Worm.new(
49
164
  message: "Custom task",
50
165
  style: 'blocks',
51
166
  speed: 'medium'
52
167
  )
53
168
 
54
- worm.animate { heavy_computation }
55
- ```
169
+ worm.animate do
170
+ heavy_computation
171
+ more_work
172
+ end
56
173
 
57
- ## Daemon Mode - The Killer Feature
174
+ # Command execution with error handling
175
+ RubyProgress::Twirl.new(
176
+ command: "bundle install",
177
+ message: "Installing gems...",
178
+ success: "Dependencies installed!",
179
+ error: "Installation failed",
180
+ checkmark: true
181
+ ).run_with_command
182
+ ```
58
183
 
59
- Run progress indicators in the background while your scripts execute:
184
+ ## Advanced Features Worth Knowing
60
185
 
61
- ```bash
62
- # Start background indicator
63
- worm --daemon --pid-file /tmp/progress.pid --message "Deploying..."
186
+ ### Custom Styling and Icons
64
187
 
65
- # Run your actual work
66
- ./deploy.sh
67
- kubectl apply -f manifests/
188
+ All indicators support custom success and error icons:
68
189
 
69
- # Stop with success message
70
- worm --stop /tmp/progress.pid --message "Deploy complete!" --checkmark
190
+ ```bash
191
+ prg ripple "Deploying..." \
192
+ --command "./deploy.sh" \
193
+ --success "All systems go!" \
194
+ --error "Houston, we have a problem" \
195
+ --success-icon "🚀" \
196
+ --error-icon "💥" \
197
+ --checkmark
71
198
  ```
72
199
 
73
- This is incredibly useful for complex deployment scripts where you want continuous visual feedback without interrupting the main process.
74
-
75
- There's a unified binary called `prg` that takes the three types as subcommands, e.g. `prg twirl --checkmark`. You can use any of them either way.
200
+ ### Visual Customization
76
201
 
77
- ## Advanced Features
202
+ Ripple supports rainbow colors and multiple composable styles:
78
203
 
79
- ### Error Handling
80
- ```ruby
81
- RubyProgress::Ripple.progress("Risky operation") do
82
- might_fail_operation
83
- rescue StandardError => e
84
- # Automatically stops and shows error state
85
- puts "Failed: #{e.message}"
86
- end
204
+ ```bash
205
+ prg ripple "Processing" --style rainbow,inverse,caps
87
206
  ```
88
207
 
89
- ### Command Integration
90
- ```ruby
91
- # Execute shell commands with progress
92
- RubyProgress::Worm.new(
93
- command: "pg_dump mydb > backup.sql",
94
- success: "Backup complete!",
95
- error: "Backup failed"
96
- ).run_with_command
97
- ```
208
+ Worm has directional control and custom character sets:
98
209
 
99
- ### Visual Customization
100
- ```ruby
101
- # Rainbow colors and custom styling
102
- RubyProgress::Ripple.progress("Colorful task",
103
- rainbow: true,
104
- speed: :fast,
105
- format: :forward_only
106
- ) do
107
- process_with_style
108
- end
210
+ ```bash
211
+ prg worm --direction rtl --style "custom=🟦🟨🟥"
109
212
  ```
110
213
 
111
- ## Real-World Examples
214
+ ### Start/End Character Decoration
112
215
 
113
- ### Deployment Script
216
+ The `--ends` flag lets you wrap your progress indicator with decorative characters:
114
217
 
115
218
  ```bash
116
- #!/bin/bash
117
- worm --daemon-as deploy --message "Deploying..." &
219
+ prg worm --message "Magic" --ends "🎯🎪" --style blocks
220
+ prg ripple "Loading data" --ends "[]" --style rainbow
221
+ ```
118
222
 
119
- git push production main
120
- kubectl rollout status deployment/app
223
+ ### Output Capture
121
224
 
122
- worm --stop-id deploy --stop-success "Success!" --checkmark
123
- ```
225
+ When running commands, you can capture and display output:
124
226
 
125
- ### Data Processing
126
- ```ruby
127
- def import_large_csv(file)
128
- RubyProgress::Ripple.progress("Importing #{File.basename(file)}...") do
129
- CSV.foreach(file, headers: true) { |row| User.create!(row.to_h) }
130
- end
131
- end
132
- ```
227
+ ```bash
228
+ # Show command output after completion
229
+ prg ripple "Building..." --command "make build" --stdout
133
230
 
134
- ### Rake Tasks
135
- ```ruby
136
- task :backup do
137
- RubyProgress::Worm.new(
138
- command: "tar -czf backup.tar.gz app/",
139
- success: "Backup created successfully!"
140
- ).run_with_command
141
- end
231
+ # Display live output with reserved terminal rows
232
+ prg worm --command "npm install" --output-lines 5 --output-position above
142
233
  ```
234
+ {% endpaywall %}
235
+
236
+ ## Real-World Use Cases
237
+
238
+ **Deployment Scripts**: Show continuous progress during multi-step deployments
239
+ without blocking command output.
240
+
241
+ **Data Processing**: Provide visual feedback during long-running data imports or
242
+ transformations.
143
243
 
144
- ## Why ruby-progress?
244
+ **Build Systems**: Integrate into Rake or Make tasks to show progress during compilation.
145
245
 
146
- - **Simple API**: Works in Ruby code and shell scripts
147
- - **Visual Appeal**: Engaging animations beyond basic spinners
148
- - **Unique Daemon Mode**: Background progress indicators
149
- - **Production Ready**: 84.55% test coverage, 113 test examples, zero failures
150
- - **Cross-Platform**: Linux, macOS, Windows support
151
- - **Reliable**: Comprehensive error handling and edge case coverage
246
+ **CI/CD Pipelines**: Add visual indicators to pipeline scripts for better monitoring.
152
247
 
153
- ## Installation & First Steps
248
+ **System Administration**: Show progress during backups, database dumps, or file
249
+ synchronization.
154
250
 
155
- 1. **Install**: `gem install ruby-progress`
156
- 2. **Test CLI**: `ripple "Hello World!"`
157
- 3. **Try in Ruby**:
158
- ```ruby
159
- require 'ruby-progress'
160
- RubyProgress::Ripple.progress("Testing...") { sleep 2 }
161
- ```
251
+ ## Try It Out
162
252
 
163
- ## Conclusion
253
+ The easiest way to get started:
164
254
 
165
- Ruby-progress transforms boring CLI applications into engaging user experiences. Whether building deployment scripts, data processing tools, or utility commands, it provides the visual feedback users expect from modern command-line tools.
255
+ {% iterm "gem install ruby-progress" %}
166
256
 
167
- The daemon mode alone makes it worth trying - no other progress library offers this level of flexibility for complex workflows.
257
+ {% iterm "prg ripple 'Hello, World!'" %}
168
258
 
169
- **Links:**
170
- - [GitHub](https://github.com/ttscoff/ruby-progress)
171
- - [RubyGems](https://rubygems.org/gems/ruby-progress)
172
- - [Latest Release](https://github.com/ttscoff/ruby-progress/releases/latest)
259
+ Or check out the [GitHub repository](https://github.com/ttscoff/ruby-progress)
260
+ for full documentation, examples, and the complete API reference. The README
261
+ includes detailed guides for each indicator type and advanced usage patterns.
173
262
 
174
- *Make your CLI tools feel alive with ruby-progress!*
263
+ The gem is also available on
264
+ [RubyGems](https://rubygems.org/gems/ruby-progress), and the latest release
265
+ includes significant improvements to daemon mode handling and job control
266
+ commands.
@@ -8,6 +8,9 @@ module RubyProgress
8
8
  # rubocop:disable Metrics/AbcSize
9
9
  module Options
10
10
  # rubocop :disable Metrics/MethodLength
11
+ # Parse CLI options for the fill subcommand.
12
+ #
13
+ # @return [Hash] parsed options keyed by symbols
11
14
  def self.parse_cli_options
12
15
  options = {
13
16
  style: :blocks,
@@ -6,6 +6,9 @@ require 'json'
6
6
  module RippleCLI
7
7
  # Option parsing extracted to its own file to reduce module size of RippleCLI.
8
8
  module Options
9
+ # Parse CLI options for the ripple subcommand.
10
+ #
11
+ # @return [Hash] parsed options keyed by symbols
9
12
  def self.parse_cli_options
10
13
  options = {
11
14
  speed: :medium,
@@ -7,7 +7,22 @@ require_relative 'twirl_runner'
7
7
 
8
8
  # Twirl CLI (extracted from bin/prg)
9
9
  module TwirlCLI
10
+ # CLI dispatcher for the Twirl spinner indicator. Parses options and
11
+ # dispatches to runtime helpers in TwirlRunner or controls daemons via
12
+ # RubyProgress::Daemon.
13
+ #
14
+ # Public methods:
15
+ # - .run
16
+ # - .resolve_pid_file
17
+ # - .parse_cli_options
18
+ #
19
+ # @return [void]
10
20
  def self.run
21
+ trap('INT') do
22
+ RubyProgress::Utils.show_cursor
23
+ exit
24
+ end
25
+
11
26
  options = TwirlCLI::Options.parse_cli_options
12
27
 
13
28
  if options[:status]
@@ -38,6 +53,11 @@ module TwirlCLI
38
53
  end
39
54
 
40
55
  # runtime methods moved to TwirlRunner
56
+ # Resolve the pid file path used for named/unnamed daemons.
57
+ #
58
+ # @param options [Hash]
59
+ # @param name_key [Symbol]
60
+ # @return [String]
41
61
  def self.resolve_pid_file(options, name_key)
42
62
  return options[:pid_file] if options[:pid_file]
43
63
 
@@ -9,6 +9,9 @@ module TwirlCLI
9
9
  # Keeps the CLI option definitions extracted from the main dispatcher
10
10
  # so the `TwirlCLI` module stays small and focused on dispatching.
11
11
  module Options
12
+ # Parse CLI options for the twirl subcommand.
13
+ #
14
+ # @return [Hash] parsed options keyed by symbols
12
15
  def self.parse_cli_options
13
16
  options = {
14
17
  output_position: :above,
@@ -12,6 +12,12 @@ require_relative '../output_capture'
12
12
  # indefinitely, or launching in daemon mode) and were extracted to
13
13
  # reduce module size and improve testability.
14
14
  module TwirlRunner
15
+ # Runtime helper: run the provided command while showing a twirl spinner.
16
+ # Captures output via RubyProgress::OutputCapture when appropriate and
17
+ # prints final completion messages according to options.
18
+ #
19
+ # @param options [Hash] CLI options parsed from TwirlCLI::Options
20
+ # @return [void] exits with appropriate status code (0 success, 1 failure)
15
21
  def self.run_with_command(options)
16
22
  message = options[:message]
17
23
  captured_output = nil
@@ -46,6 +52,11 @@ module TwirlRunner
46
52
 
47
53
  spinner_thread.kill
48
54
  RubyProgress::Utils.clear_line
55
+ rescue Interrupt
56
+ spinner_thread&.kill
57
+ RubyProgress::Utils.clear_line
58
+ RubyProgress::Utils.show_cursor
59
+ exit 130
49
60
  ensure
50
61
  RubyProgress::Utils.show_cursor
51
62
  end
@@ -67,6 +78,10 @@ module TwirlRunner
67
78
  exit success ? 0 : 1
68
79
  end
69
80
 
81
+ # Run the spinner indefinitely until interrupted (SIGINT).
82
+ #
83
+ # @param options [Hash] CLI options used to configure the spinner
84
+ # @return [void] exits 130 on interrupt
70
85
  def self.run_indefinitely(options)
71
86
  message = options[:message]
72
87
  spinner = TwirlSpinner.new(message, options)
@@ -74,6 +89,10 @@ module TwirlRunner
74
89
  begin
75
90
  RubyProgress::Utils.hide_cursor
76
91
  loop { spinner.animate }
92
+ rescue Interrupt
93
+ RubyProgress::Utils.clear_line
94
+ RubyProgress::Utils.show_cursor
95
+ exit 130
77
96
  ensure
78
97
  RubyProgress::Utils.show_cursor
79
98
  if options[:success] || options[:checkmark]
@@ -87,6 +106,11 @@ module TwirlRunner
87
106
  end
88
107
  end
89
108
 
109
+ # Run the spinner in daemon mode. Writes a pid file and listens for
110
+ # control messages via the daemon control message file.
111
+ #
112
+ # @param options [Hash]
113
+ # @return [void]
90
114
  def self.run_daemon_mode(options)
91
115
  pid_file = resolve_pid_file(options, :daemon_name)
92
116
  FileUtils.mkdir_p(File.dirname(pid_file))
@@ -141,6 +165,11 @@ module TwirlRunner
141
165
  end
142
166
  end
143
167
 
168
+ # Resolve pid file helper used by run_daemon_mode and CLI.
169
+ #
170
+ # @param options [Hash]
171
+ # @param name_key [Symbol]
172
+ # @return [String]
144
173
  def self.resolve_pid_file(options, name_key)
145
174
  return options[:pid_file] if options[:pid_file]
146
175
 
@@ -6,6 +6,25 @@ require_relative 'worm_options'
6
6
 
7
7
  # Enhanced Worm CLI (extracted from bin/prg)
8
8
  module WormCLI
9
+ # CLI dispatcher for the Worm indicator.
10
+ #
11
+ # Responsibilities:
12
+ # - parse CLI options (delegates to WormCLI::Options)
13
+ # - handle daemonization, status, and stop commands via RubyProgress::Daemon
14
+ # - launch the appropriate runtime mode (command-run, indefinite, daemon)
15
+ #
16
+ # Public methods:
17
+ # - .run
18
+ # - .resolve_pid_file
19
+ # - .run_daemon_mode
20
+
21
+ # Determine the pid file path from options. If options specify a custom
22
+ # :pid_file, return it. If a named daemon key is present, use
23
+ # /tmp/ruby-progress/<name>.pid. Otherwise fall back to the default.
24
+ #
25
+ # @param options [Hash] parsed CLI options
26
+ # @param name_key [Symbol] key used for named daemons (default :daemon_name)
27
+ # @return [String] path to the pid file
9
28
  def self.resolve_pid_file(options, name_key = :daemon_name)
10
29
  return options[:pid_file] if options[:pid_file]
11
30
 
@@ -14,7 +33,16 @@ module WormCLI
14
33
  RubyProgress::Daemon.default_pid_file
15
34
  end
16
35
 
36
+ # Entrypoint for the Worm CLI. Parses options and dispatches to status,
37
+ # stop, daemon, or runtime modes. Ensures the cursor is restored on Ctrl+C.
38
+ #
39
+ # @return [void] exits with appropriate exit codes for status/stop modes.
17
40
  def self.run
41
+ trap('INT') do
42
+ RubyProgress::Utils.show_cursor
43
+ exit
44
+ end
45
+
18
46
  options = WormCLI::Options.parse_cli_options
19
47
 
20
48
  if options[:status]
@@ -48,6 +76,11 @@ module WormCLI
48
76
  end
49
77
  end
50
78
 
79
+ # Launch the worm indicator in daemon mode writing a pid file and
80
+ # monitoring for control messages. Ensures pid file is removed on exit.
81
+ #
82
+ # @param options [Hash] parsed CLI options used to configure the Worm instance
83
+ # @return [void]
51
84
  def self.run_daemon_mode(options)
52
85
  pid_file = resolve_pid_file(options, :daemon_name)
53
86
  FileUtils.mkdir_p(File.dirname(pid_file))
@@ -8,6 +8,9 @@ module WormCLI
8
8
  # Keeps the CLI option definitions for `prg worm` extracted from
9
9
  # the main dispatcher to keep the CLI module small and focused.
10
10
  module Options
11
+ # Parse CLI options for the worm subcommand.
12
+ #
13
+ # @return [Hash] parsed options keyed by symbols
11
14
  def self.parse_cli_options
12
15
  options = {
13
16
  output_position: :above,