cli-dispatcher 1.2.4 → 1.2.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/lib/cli-dispatcher.rb +56 -14
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1b37219d472cc73b55f56047050b442e634de6b08c649dc617c12c0e812f220
|
4
|
+
data.tar.gz: 1cf08e0e3893984ef5d15c414d87b0889c3073dea6d7a6e8d7a6c6b12889d181
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 593cce73a3bd60c69bcad822f1dcb20579f482eec9454ce86bd9164da88ff0f536cebdd67fbf55695c88622e3c391ece18bff6a12e8ad18f094d2cabee45308c
|
7
|
+
data.tar.gz: da5e84b8318b15d2510ac1a04086a66bd8a53689bb2afb59a9afa4d893f3380554702ecebdc55f88805002a8e81f15377767711cc16f17bb33d386624ea08724
|
data/lib/cli-dispatcher.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
require 'texttools'
|
3
|
+
require 'reline'
|
4
|
+
require 'shellwords'
|
3
5
|
|
4
6
|
#
|
5
7
|
# Constructs a program that can operate a number of user-provided commands. To
|
@@ -31,12 +33,12 @@ class Dispatcher
|
|
31
33
|
# Reads ARGV and dispatches a command. If no arguments are given, an
|
32
34
|
# appropriate warning is issued and the program terminates.
|
33
35
|
#
|
34
|
-
def dispatch_argv
|
36
|
+
def dispatch_argv(default_interactive = false)
|
35
37
|
@option_parser ||= OptionParser.new
|
36
38
|
add_options(@option_parser)
|
37
39
|
@option_parser.banner = <<~EOF
|
38
|
-
Usage:
|
39
|
-
Run '
|
40
|
+
Usage: #{File.basename($0)} [options] command [arguments...]
|
41
|
+
Run '#{File.basename($0)} help' for a list of commands.
|
40
42
|
|
41
43
|
Options:
|
42
44
|
EOF
|
@@ -48,35 +50,39 @@ class Dispatcher
|
|
48
50
|
end
|
49
51
|
|
50
52
|
@option_parser.parse!
|
51
|
-
if ARGV.empty?
|
53
|
+
if !ARGV.empty?
|
54
|
+
exit dispatch(*ARGV) ? 0 : 1
|
55
|
+
elsif default_interactive
|
56
|
+
cmd_interactive
|
57
|
+
else
|
52
58
|
STDERR.puts(@option_parser)
|
53
59
|
exit 1
|
54
60
|
end
|
55
|
-
dispatch(*ARGV)
|
56
61
|
end
|
57
62
|
|
58
63
|
#
|
59
64
|
# Dispatches a single command with given arguments. If the command is not
|
60
|
-
# found, then issues a help warning.
|
65
|
+
# found, then issues a help warning. Returns true or false depending on
|
66
|
+
# whether the command executed successfully.
|
61
67
|
#
|
62
68
|
def dispatch(cmd, *args)
|
63
69
|
cmd_sym = "cmd_#{cmd}".to_sym
|
64
70
|
begin
|
65
71
|
if respond_to?(cmd_sym)
|
66
72
|
send(cmd_sym, *args)
|
73
|
+
return true
|
67
74
|
else
|
68
|
-
warn("
|
69
|
-
|
70
|
-
exit(1)
|
75
|
+
warn("Unknown command #{cmd_sym}. Run 'help' for a list of commands.")
|
76
|
+
return false
|
71
77
|
end
|
72
78
|
rescue ArgumentError
|
73
79
|
if $!.backtrace_locations.first.base_label == cmd_sym.to_s
|
74
|
-
warn("#{cmd}: wrong number of arguments")
|
80
|
+
warn("#{cmd}: wrong number of arguments.")
|
75
81
|
warn("Usage: #{signature_string(cmd)}")
|
76
|
-
exit(1)
|
77
82
|
else
|
78
|
-
raise
|
83
|
+
raise
|
79
84
|
end
|
85
|
+
return false
|
80
86
|
end
|
81
87
|
end
|
82
88
|
|
@@ -143,12 +149,48 @@ class Dispatcher
|
|
143
149
|
cmds.sort.each do |cmd|
|
144
150
|
warn(TextTools.line_break(
|
145
151
|
help_string(cmd, all: false),
|
146
|
-
prefix: " " *
|
147
|
-
first_prefix: cmd.ljust(
|
152
|
+
prefix: " " * 12,
|
153
|
+
first_prefix: cmd.ljust(11) + ' ',
|
148
154
|
))
|
149
155
|
end
|
150
156
|
end
|
151
157
|
|
158
|
+
def help_interactive
|
159
|
+
return "Start an interactive shell for entering commands."
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Runs the dispatcher in interactive mode, in which command lines are read
|
164
|
+
# from a prompt.
|
165
|
+
#
|
166
|
+
def cmd_interactive
|
167
|
+
stty_save = `stty -g`.chomp
|
168
|
+
loop do
|
169
|
+
begin
|
170
|
+
buf = Reline.readline(interactive_prompt, true)
|
171
|
+
exit unless buf
|
172
|
+
args = buf.shellsplit
|
173
|
+
next if args.empty?
|
174
|
+
exit if args.first == 'exit'
|
175
|
+
dispatch(*args)
|
176
|
+
rescue Interrupt
|
177
|
+
system("stty", stty_save)
|
178
|
+
exit
|
179
|
+
rescue
|
180
|
+
STDERR.puts $!.full_message
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# Returns the string for the interactive prompt. Subclasses can override this
|
187
|
+
# method to offer more detailed prompts.
|
188
|
+
#
|
189
|
+
def interactive_prompt
|
190
|
+
return "#{File.basename($0)}> "
|
191
|
+
end
|
192
|
+
|
193
|
+
|
152
194
|
#
|
153
195
|
# Adds commands relevant when this dispatcher uses Structured data inputs.
|
154
196
|
#
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cli-dispatcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Duan
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-10-02 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: |
|
13
13
|
Library for creating command-line programs that accept commands. Also
|
@@ -42,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: '0'
|
44
44
|
requirements: []
|
45
|
-
rubygems_version: 3.
|
45
|
+
rubygems_version: 3.7.2
|
46
46
|
specification_version: 4
|
47
47
|
summary: Command-line command dispatcher
|
48
48
|
test_files: []
|