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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cli-dispatcher.rb +56 -14
  3. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f480b01f8af6a9af5c131e3e25081edd7e69fff4caf3daa22ea10efbc49b4f4
4
- data.tar.gz: 2eea3e4b6791f4babe182b56c15607b7fa5eb532106c00505fb26b8b0ee0f0d9
3
+ metadata.gz: b1b37219d472cc73b55f56047050b442e634de6b08c649dc617c12c0e812f220
4
+ data.tar.gz: 1cf08e0e3893984ef5d15c414d87b0889c3073dea6d7a6e8d7a6c6b12889d181
5
5
  SHA512:
6
- metadata.gz: b4ea432b818502f65c048a0911aef575b42ed17d2cff7e42f97382f5b3f6ce77e8cf52964f9ca43eb85b467c4f3a67bcc957a14d51b82b5fe37ff120524f03a9
7
- data.tar.gz: 9e5dbff959cc60f44ebadf445cb3257fea82403c2db4f053a7f241deb0f7a290cc5b5f02e3810e8ca48ba5ea16893765cfbe8e73c8b7f73b12c7462004b56ef7
6
+ metadata.gz: 593cce73a3bd60c69bcad822f1dcb20579f482eec9454ce86bd9164da88ff0f536cebdd67fbf55695c88622e3c391ece18bff6a12e8ad18f094d2cabee45308c
7
+ data.tar.gz: da5e84b8318b15d2510ac1a04086a66bd8a53689bb2afb59a9afa4d893f3380554702ecebdc55f88805002a8e81f15377767711cc16f17bb33d386624ea08724
@@ -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: #$0 [options] command [arguments...]
39
- Run '#$0 help' for a list of commands.
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("Usage: #$0 [options] command [arguments...]")
69
- warn("Run '#$0 help' for a list of commands.")
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: " " * 11,
147
- first_prefix: cmd.ljust(10) + ' ',
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
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-05-20 00:00:00.000000000 Z
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.6.9
45
+ rubygems_version: 3.7.2
46
46
  specification_version: 4
47
47
  summary: Command-line command dispatcher
48
48
  test_files: []