simple-cli 0.2.28 → 0.3.0

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: ba16419e4dc2f0fe2dc47fe0a5cb29a6de15a57d2b221ef3aa8c3ed7455c0556
4
- data.tar.gz: 6293877fe62faaaf2718745c94ebb1ea798e1500330f75095c0363f151047fe4
3
+ metadata.gz: 1fdfd698a5315891e4d5dd96e5d3ce07fc075d17d5ced10eb06a9cb5733b4a8a
4
+ data.tar.gz: 9000f43f3dfceb572aae61b8907216c3dd7c9c4c468374587f56d5c433d84ecd
5
5
  SHA512:
6
- metadata.gz: 1dc54fc73aa56d28485023047df277663cdf0b0edeaacde994c772fd908934e7994bf84d4f9e216cc55573df2b3ad128d800ab217f268dfdbee731fd48e0db93
7
- data.tar.gz: b9ee91e8c0aae8d0586b90dcbebe7476d9c34338ecc45bbdd08a685548f539c519db6412e99de13a65acac5538d0c151fe2dd76b9c3966126d1c91b910ada533
6
+ metadata.gz: 82f219944dc7ffecac5cae4975749732a6741ee676f5ffd8b4ca862c48717d20a56dfc363dbf7c486e5cb9d48ba376eecb67a7185557547da7824bd201fd524f
7
+ data.tar.gz: ee581a7eb68e35c9cc8a2560538f709a1c9ce8a90457338c14ef9446875563f6e9f9f4012844c5ada1f96486ef0945e9917cdda0434972b078c9dc22c5f2c9d1
@@ -1,8 +1,24 @@
1
1
  module Simple::CLI::Adapter
2
- def run!(*args)
3
- args = ARGV if args.empty?
4
-
5
- Simple::CLI::Runner.run(self, *args)
2
+ # Run a Simple::CLI application
3
+ #
4
+ # This is usually called with as either
5
+ #
6
+ # - Application::CLI.run!: runs the Application's CLI with subcommand support.
7
+ #
8
+ # or
9
+ #
10
+ # - Application::CLI.run!("main"): runs the Application's CLI without subcommand support.
11
+ #
12
+ def run!(main_command = nil)
13
+ runner = Simple::CLI::Runner.new(self)
14
+
15
+ if main_command && (ARGV.include?("--help") || ARGV.include?("-h"))
16
+ runner.help(main_command)
17
+ elsif main_command
18
+ runner.run(main_command, *ARGV)
19
+ else
20
+ runner.run(*ARGV)
21
+ end
6
22
  end
7
23
 
8
24
  def logger=(logger)
@@ -56,6 +56,11 @@ module Simple::CLI::Logger::ColoredLogger
56
56
  log :error, *args, &block
57
57
  end
58
58
 
59
+ def fatal(*args, &block)
60
+ log :error, *args, &block
61
+ exit 1
62
+ end
63
+
59
64
  def success(*args, &block)
60
65
  log :success, *args, &block
61
66
  end
@@ -118,25 +123,10 @@ module Simple::CLI::Logger::ColoredLogger
118
123
  STDERR.puts msg
119
124
  end
120
125
 
121
- # [TODO] The heuristic used to determine the caller is not perfect.
122
- # Maybe we'll find a better solution; but for now this has to do.
126
+ # The heuristic used to determine the caller is not perfect, but should
127
+ # do well in most cases.
123
128
  def source_from_caller
124
- source = caller.find do |loc|
125
- # skip this gem
126
- next false if loc =~ /\/lib\/simple\/cli\//
127
-
128
- # skip forwardable from Ruby stdlib
129
- next false if loc =~ /\/forwardable.rb\:/
130
-
131
- # skip simple-sql
132
- next false if loc =~ /\/lib\/simple\/sql\b/
133
-
134
- # skip lib/postjob/queue/postgres/checked_sql.rb
135
- next false if loc =~ %r{lib/postjob/queue/postgres/checked_sql.rb}
136
-
137
- true
138
- end
139
-
129
+ source = caller.find { |loc| loc !~ /simple-cli.*\/lib\/simple\/cli/ }
140
130
  source ||= caller[2]
141
131
  source = source[(wd.length + 1)..-1] if source.start_with?(wd)
142
132
  source
@@ -43,7 +43,7 @@ class Simple::CLI::Runner::CommandHelp
43
43
  end
44
44
 
45
45
  # A help string constructed from the commands method signature.
46
- def interface(binary_name, command_name)
46
+ def interface(binary_name, command_name, include_subcommand: false)
47
47
  args = @method_parameters_ex.map do |mode, name|
48
48
  case mode
49
49
  when :req then "<#{name}>"
@@ -66,7 +66,8 @@ class Simple::CLI::Runner::CommandHelp
66
66
  end
67
67
  end.compact
68
68
 
69
- help = "#{binary_name} #{command_to_string(command_name)}"
69
+ help = "#{binary_name}"
70
+ help << " #{command_to_string(command_name)}" if include_subcommand
70
71
  help << " #{options.join(' ')}" unless options.empty?
71
72
  help << " #{args.join(' ')}" unless args.empty?
72
73
  help
@@ -8,13 +8,10 @@ class Simple::CLI::Runner
8
8
  end
9
9
 
10
10
  require_relative "runner/command_help"
11
- require_relative "runner/autocompletion"
12
11
 
13
12
  # A Runner object manages running a CLI application module with a set
14
13
  # of string arguments (usually taken from ARGV)
15
14
  class Simple::CLI::Runner
16
- include Autocompletion
17
-
18
15
  def self.run(app, *args)
19
16
  new(app).run(*args)
20
17
  end
@@ -34,6 +31,14 @@ class Simple::CLI::Runner
34
31
 
35
32
  attr_accessor :subcommand
36
33
 
34
+ def help(command)
35
+ if command
36
+ run "help", command
37
+ else
38
+ run "help"
39
+ end
40
+ end
41
+
37
42
  def run(*args)
38
43
  extract_default_flags!(args)
39
44
 
@@ -43,10 +48,6 @@ class Simple::CLI::Runner
43
48
 
44
49
  if command == :help
45
50
  do_help!(*args)
46
- elsif command == :autocomplete
47
- autocomplete(*args)
48
- elsif command == :autocomplete_bash
49
- autocomplete_bash(*args)
50
51
  elsif commands.include?(command)
51
52
  self.subcommand = command
52
53
  @instance.run! command, *args_with_options(args)
@@ -57,6 +58,10 @@ class Simple::CLI::Runner
57
58
  on_exception(e)
58
59
  end
59
60
 
61
+ def has_subcommands?
62
+ commands.length > 1
63
+ end
64
+
60
65
  def do_help!(subcommand = nil)
61
66
  if !subcommand
62
67
  help!
@@ -72,8 +77,19 @@ class Simple::CLI::Runner
72
77
  #{help_for_command(subcommand)}
73
78
 
74
79
  #{edoc.full}
75
- MSG
80
+ MSG
76
81
 
82
+ unless has_subcommands?
83
+
84
+ STDERR.puts <<~MSG
85
+
86
+ Default options include:
87
+
88
+ #{binary_name} [ --help | -h ] ... print this help
89
+ #{binary_name} [ --verbose | -v ] ... run on DEBUG log level
90
+ #{binary_name} [ --quiet | -q ] ... run on WARN log level
91
+ MSG
92
+ end
77
93
  exit 1
78
94
  end
79
95
 
@@ -133,13 +149,8 @@ class Simple::CLI::Runner
133
149
  end
134
150
 
135
151
  def help_for_command(sym)
136
- if sym == "autocomplete"
137
- autocomplete_help
138
- return
139
- end
140
-
141
152
  cmd = string_to_command(sym)
142
- CommandHelp.new(@app, cmd).interface(binary_name, cmd)
153
+ CommandHelp.new(@app, cmd).interface(binary_name, cmd, include_subcommand: has_subcommands?)
143
154
  end
144
155
 
145
156
  def binary_name
@@ -194,7 +205,6 @@ class Simple::CLI::Runner
194
205
 
195
206
  print_help_line.call "#{binary_name} help [ subcommand ]", "print help on a specific subcommand"
196
207
  print_help_line.call "#{binary_name} help -v", "show help for internal commands as well"
197
- print_help_line.call "#{binary_name} help autocomplete", "print information on autocompletion."
198
208
 
199
209
  STDERR.puts "\n"
200
210
 
@@ -1,5 +1,5 @@
1
1
  module Simple
2
2
  module CLI
3
- VERSION = "0.2.28"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.28
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - radiospiel
8
8
  - mediapeers GmbH
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-07-15 00:00:00.000000000 Z
12
+ date: 2019-11-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -75,13 +75,9 @@ extra_rdoc_files: []
75
75
  files:
76
76
  - ".gitignore"
77
77
  - ".rubocop.yml"
78
- - ".ruby-version"
79
78
  - Gemfile
80
- - README.md
81
79
  - Rakefile
82
80
  - bin/rake
83
- - doc/examples/ex1/ex1
84
- - doc/examples/ex1/ex1.rb
85
81
  - lib/simple-cli.rb
86
82
  - lib/simple/cli.rb
87
83
  - lib/simple/cli/adapter.rb
@@ -91,7 +87,6 @@ files:
91
87
  - lib/simple/cli/logger/colored_logger.rb
92
88
  - lib/simple/cli/pp.rb
93
89
  - lib/simple/cli/runner.rb
94
- - lib/simple/cli/runner/autocompletion.rb
95
90
  - lib/simple/cli/runner/command_help.rb
96
91
  - lib/simple/cli/runner/module_ex.rb
97
92
  - lib/simple/cli/version.rb
@@ -103,7 +98,7 @@ files:
103
98
  homepage: http://github.com/radiospiel/simple-cli
104
99
  licenses: []
105
100
  metadata: {}
106
- post_install_message:
101
+ post_install_message:
107
102
  rdoc_options: []
108
103
  require_paths:
109
104
  - lib
@@ -118,8 +113,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
113
  - !ruby/object:Gem::Version
119
114
  version: '0'
120
115
  requirements: []
121
- rubygems_version: 3.1.4
122
- signing_key:
116
+ rubygems_version: 3.0.4
117
+ signing_key:
123
118
  specification_version: 4
124
119
  summary: Simple CLI builder for ruby
125
120
  test_files:
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 2.7.2
data/README.md DELETED
@@ -1,32 +0,0 @@
1
- # simple-cli
2
-
3
- Building Ruby CLIs with easy.
4
-
5
- ## Philosophy
6
-
7
- Building a command line could be much easier than what ruby provides with its standard library. In general, between the invocation of a tool from the command line and the actual running of whatever code the user intends to run really should disappear.
8
-
9
- Ideally a developer would only have to build the implementation of whatever logic should be provided by the tool; everything else - parsing arguments, calling the tool's implementation, printing help - should happen automatically.
10
-
11
- This is roughly what sinmple-sql provides.
12
-
13
- ## On versions
14
-
15
- `simple-cli` is still on a 0.x.x version, and, generally, a 0.x.y version is not compatible with a 0.x+1.y version.
16
-
17
- These are the follow
18
-
19
- - The 0.2.x versions are tracked in the [`stable`](https://github.com/radiospiel/simple-cli/tree/stable) branch
20
- - The 0.3.x versions are tracked in the [`master`](https://github.com/radiospiel/simple-cli/tree/stable) branch
21
-
22
- ## Basic features
23
-
24
- - build command line features in a number of modules;
25
- - public methods in these modules provide a subcommand for the CLI;
26
- - `"_"` in the method name are being mapped to `":"` in the CLI;
27
- - CLI provides a help subcommand. help texts are derived from the methods over a subcommand implementation:
28
- - The first line determines the "short help" message, to be included in the `$CMD help` command list;
29
- - The remaining lines determines the full help message, to be included in the `$CMD help subcommand` message.
30
-
31
- ## Example
32
-
data/doc/examples/ex1/ex1 DELETED
@@ -1,2 +0,0 @@
1
- #!/bin/sh
2
- exec $0.rb "$@"
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'bundler/inline'
3
-
4
- gemfile do
5
- source 'https://rubygems.org'
6
- gem "simple-cli", '~> 0.2', path: "../../.."
7
- end
8
-
9
- module Ex1; end
10
- module Ex1::CLI
11
- include Simple::CLI
12
-
13
- # Command without arguments
14
- #
15
- # Example:
16
- #
17
- # ./ex1 hello:world
18
- #
19
- def hello_world
20
- puts "Hello from #{__FILE__}"
21
- end
22
-
23
- # Command with arguments
24
- #
25
- # This implements a command with arguments
26
- #
27
- # Examples:
28
- #
29
- # ./ex1 hello --name=user "what's up"
30
- #
31
- def hello(message, name: nil)
32
- if name
33
- puts "Hello #{name}: #{message}!"
34
- else
35
- puts "Hello, #{message}!"
36
- end
37
- end
38
- end
39
-
40
- Ex1::CLI.run!(*ARGV)
@@ -1,91 +0,0 @@
1
- module Simple::CLI::Runner::Autocompletion
2
- CommandHelp = Simple::CLI::Runner::CommandHelp
3
-
4
- def autocomplete(subcommand = nil, cur = nil)
5
- puts completions(subcommand, cur).join("\n")
6
- end
7
-
8
- def completions(subcommand = nil, cur = nil)
9
- if !cur
10
- autocomplete_subcommands(subcommand)
11
- else
12
- autocomplete_subcommand_options(subcommand, cur)
13
- end
14
- end
15
-
16
- def filter_completions(completions, prefix:)
17
- completions.select do |completion|
18
- !prefix || completion.start_with?(prefix)
19
- end
20
- end
21
-
22
- def autocomplete_subcommands(cur)
23
- commands = self.commands.map { |cmd| cmd.to_s.tr("_", ":") }
24
- commands << "help"
25
- completions = filter_completions commands, prefix: cur
26
- if completions == [cur]
27
- autocomplete_subcommand_options(cur, nil)
28
- else
29
- completions
30
- end
31
- end
32
-
33
- DEFAULT_OPTIONS = %w(--verbose -v --quiet -q)
34
-
35
- def autocomplete_subcommand_options(subcommand, cur)
36
- if subcommand == "help"
37
- completions = commands.map(&:to_s).map { |s| s.tr("_", ":") } + ["autocomplete"]
38
- filter_completions completions, prefix: cur
39
- elsif cur && cur[0, 1] == "-"
40
- completions = CommandHelp.option_names(@app, string_to_command(subcommand))
41
- completions += DEFAULT_OPTIONS
42
-
43
- filter_completions completions, prefix: cur
44
- else
45
- Dir.glob "#{cur}*"
46
- end
47
- end
48
-
49
- def autocomplete_help
50
- STDERR.puts <<~DOC
51
- #{binary_name} supports autocompletion. To enable autocompletion please run
52
-
53
- eval "$(#{$0} autocomplete:bash)"
54
- DOC
55
-
56
- exit 1
57
- end
58
-
59
- def autocomplete_bash
60
- puts AUTOCOMPLETE_SHELL_CODE.gsub(/{{BINARY}}/, binary_name)
61
- end
62
-
63
- # The shell function function is executed in the current shell environment.
64
- # When it is executed,
65
- #
66
- # - $1 is the name of the command whose arguments are being completed,
67
- # - $2 is the word being completed, and
68
- # - $3 is the word preceding the word being completed
69
- #
70
- # When it finishes, the possible completions are retrieved from the value of the COMPREPLY array variable.
71
- #
72
- # see https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html
73
- #
74
- AUTOCOMPLETE_SHELL_CODE = <<~BASH
75
- _{{BINARY}}()
76
- {
77
- local cmd=$1
78
- local cur=$2
79
-
80
- if [[ $COMP_CWORD == 1 ]]; then
81
- COMPREPLY=( $("$cmd" autocomplete "$cur" ))
82
- else
83
- local subcommand=${COMP_WORDS[1]}
84
- COMPREPLY=( $("$cmd" autocomplete "$subcommand" "$cur" ))
85
- fi
86
-
87
- return 0
88
- }
89
- complete -F _{{BINARY}} {{BINARY}}
90
- BASH
91
- end