simple-cli 0.2.28 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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