shellopts 2.0.6 → 2.0.9
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/TODO +1 -0
- data/lib/shellopts/analyzer.rb +5 -2
- data/lib/shellopts/args.rb +21 -9
- data/lib/shellopts/formatter.rb +14 -17
- data/lib/shellopts/grammar.rb +8 -0
- data/lib/shellopts/interpreter.rb +1 -1
- data/lib/shellopts/lexer.rb +2 -2
- data/lib/shellopts/parser.rb +2 -9
- data/lib/shellopts/version.rb +1 -1
- data/shellopts.gemspec +7 -6
- metadata +6 -8
- data/.gitignore +0 -30
- data/.travis.yml +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9d576d24bd0aec0dd43a2a3645ede04751d80ae22a4c88e8f66ed53bbe7e405
|
4
|
+
data.tar.gz: 9027ac55689a345099f6515e5280808528603dfafe385219e6cce77d1c166d96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b44a4d95aa0585dd0ec31abccde4942c98ad712d9e3bdf9f0c0b6ead7333ff4c5b555ec5b45786a6f539388b2460c93d12f3755b2e80cbb81fd269c42a9b4955
|
7
|
+
data.tar.gz: 3c948a743d809df7d22bc142dcfa9aa4e943fed144004c4fbf5d1995c314f4aea3f91b032533222eed953e5344a45c55666339797e5ae2b1be262eea17071cd5
|
data/TODO
CHANGED
data/lib/shellopts/analyzer.rb
CHANGED
@@ -28,10 +28,13 @@ module ShellOpts
|
|
28
28
|
@options = option_groups.map(&:options).flatten
|
29
29
|
end
|
30
30
|
|
31
|
-
# Move options before first command
|
31
|
+
# Move options before first command or before explicit COMMAND section
|
32
32
|
def reorder_options
|
33
33
|
if commands.any?
|
34
|
-
|
34
|
+
i = children.find_index { |child|
|
35
|
+
child.is_a?(Command) || child.is_a?(Section) && child.name == "COMMAND"
|
36
|
+
}
|
37
|
+
if i
|
35
38
|
options, rest = children[i+1..-1].partition { |child| child.is_a?(OptionGroup) }
|
36
39
|
@children = children[0, i] + options + children[i..i] + rest
|
37
40
|
end
|
data/lib/shellopts/args.rb
CHANGED
@@ -2,21 +2,31 @@
|
|
2
2
|
module ShellOpts
|
3
3
|
# Specialization of Array for arguments lists. Args extends Array with a
|
4
4
|
# #extract and an #expect method to extract elements from the array. The
|
5
|
-
# methods raise a ShellOpts::
|
5
|
+
# methods raise a ShellOpts::Error exception in case of errors
|
6
6
|
#
|
7
7
|
class Args < Array
|
8
|
+
def initialize(*args, exception: false)
|
9
|
+
super(*args)
|
10
|
+
@exception = exception
|
11
|
+
end
|
12
|
+
|
13
|
+
# :call-seq:
|
14
|
+
# extract(count, message = nil)
|
15
|
+
# extract(range, message = nil)
|
16
|
+
#
|
8
17
|
# Remove and return elements from beginning of the array
|
9
18
|
#
|
10
19
|
# If +count_or_range+ is a number, that number of elements will be
|
11
20
|
# returned. If the count is one, a simple value is returned instead of an
|
12
21
|
# array. If the count is negative, the elements will be removed from the
|
13
22
|
# end of the array. If +count_or_range+ is a range, the number of elements
|
14
|
-
# returned will be in that range.
|
23
|
+
# returned will be in that range. Note that the range can't contain
|
24
|
+
# negative numbers
|
15
25
|
#
|
16
|
-
# #extract raise a ShellOpts::
|
26
|
+
# #extract raise a ShellOpts::Error exception if there's is not enough
|
17
27
|
# elements in the array to satisfy the request
|
18
28
|
#
|
19
|
-
def extract(count_or_range, message = nil)
|
29
|
+
def extract(count_or_range, message = nil)
|
20
30
|
case count_or_range
|
21
31
|
when Range
|
22
32
|
range = count_or_range
|
@@ -30,16 +40,16 @@ module ShellOpts
|
|
30
40
|
count.abs <= self.size or inoa(message)
|
31
41
|
start = count >= 0 ? 0 : size + count
|
32
42
|
r = slice!(start, count.abs)
|
33
|
-
r.size
|
43
|
+
r.size == 1 ? r.first : r
|
34
44
|
else
|
35
45
|
raise ArgumentError
|
36
46
|
end
|
37
47
|
end
|
38
48
|
|
39
49
|
# As #extract except it doesn't allow negative counts and that the array is
|
40
|
-
#
|
50
|
+
# expected to be emptied by the operation
|
41
51
|
#
|
42
|
-
# #expect raise a ShellOpts::
|
52
|
+
# #expect raise a ShellOpts::Error exception if the array is not emptied
|
43
53
|
# by the operation
|
44
54
|
#
|
45
55
|
def expect(count_or_range, message = nil)
|
@@ -54,8 +64,10 @@ module ShellOpts
|
|
54
64
|
end
|
55
65
|
|
56
66
|
private
|
57
|
-
def inoa(message = nil)
|
58
|
-
|
67
|
+
def inoa(message = nil)
|
68
|
+
message ||= "Illegal number of arguments"
|
69
|
+
raise Error, message if @exception
|
70
|
+
::ShellOpts.error(message)
|
59
71
|
end
|
60
72
|
end
|
61
73
|
end
|
data/lib/shellopts/formatter.rb
CHANGED
@@ -112,36 +112,33 @@ module ShellOpts
|
|
112
112
|
|
113
113
|
section = {
|
114
114
|
Paragraph => "DESCRIPTION",
|
115
|
-
OptionGroup => "
|
116
|
-
Command => "
|
115
|
+
OptionGroup => "OPTION",
|
116
|
+
Command => "COMMAND"
|
117
117
|
}
|
118
118
|
|
119
|
+
seen_sections = {}
|
119
120
|
newline = false # True if a newline should be printed before child
|
120
121
|
indent {
|
121
122
|
children.each { |child|
|
122
|
-
|
123
|
-
#
|
124
|
-
|
125
|
-
indent(-1).puts Ansi.bold child.name
|
126
|
-
section.delete_if { |_,v| v == child.name }
|
123
|
+
klass = child.is_a?(Section) ? section.key(child.name) : child.class
|
124
|
+
if s = section[klass] # Implicit section
|
125
|
+
section.delete(klass)
|
127
126
|
section.delete(Paragraph)
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
127
|
+
if klass <= OptionGroup
|
128
|
+
s = s + "S" if options.size > 1
|
129
|
+
elsif klass <= Command
|
130
|
+
s = s + "S" if commands.size > 1 || commands.first&.commands&.size != 0
|
131
|
+
end
|
132
|
+
puts
|
133
133
|
indent(-1).puts Ansi.bold s
|
134
|
-
section.delete(child.class)
|
135
|
-
section.delete(Paragraph)
|
136
134
|
newline = false
|
137
|
-
|
138
|
-
#
|
135
|
+
next if child.is_a?(Section)
|
136
|
+
else # Any other node adds a newline
|
139
137
|
puts if newline
|
140
138
|
newline = true
|
141
139
|
end
|
142
140
|
|
143
141
|
if child.is_a?(Command)
|
144
|
-
# prefix = child.parent != self ? nil : child.supercommand&.name
|
145
142
|
prefix = child.supercommand == self ? nil : child.supercommand&.name
|
146
143
|
child.puts_descr(prefix, brief: false, name: :path)
|
147
144
|
newline = true
|
data/lib/shellopts/grammar.rb
CHANGED
@@ -151,6 +151,10 @@ module ShellOpts
|
|
151
151
|
class OptionGroup < Node
|
152
152
|
alias_method :command, :parent
|
153
153
|
|
154
|
+
# Duck typing for compatibility with IdrNode (TODO: maybe just make
|
155
|
+
# OptionGroup an IdrNode and be over with it)
|
156
|
+
def name() options.first&.name end
|
157
|
+
|
154
158
|
# Array of options in declaration order
|
155
159
|
attr_reader :options
|
156
160
|
|
@@ -352,6 +356,10 @@ module ShellOpts
|
|
352
356
|
end
|
353
357
|
|
354
358
|
class Section < Node
|
359
|
+
def initialize(parent, token)
|
360
|
+
constrain token.source, *%w(DESCRIPTION OPTION COMMAND)
|
361
|
+
super
|
362
|
+
end
|
355
363
|
def name() token.source end
|
356
364
|
end
|
357
365
|
|
data/lib/shellopts/lexer.rb
CHANGED
@@ -45,7 +45,7 @@ module ShellOpts
|
|
45
45
|
# Match ArgDescr words (should be at least two characters long)
|
46
46
|
DESCR_RE = /^[^a-z]{2,}$/
|
47
47
|
|
48
|
-
SECTIONS = %w(DESCRIPTION OPTIONS COMMANDS)
|
48
|
+
SECTIONS = %w(DESCRIPTION OPTION OPTIONS COMMAND COMMANDS)
|
49
49
|
|
50
50
|
using Ext::Array::ShiftWhile
|
51
51
|
|
@@ -109,7 +109,7 @@ module ShellOpts
|
|
109
109
|
|
110
110
|
# Sections
|
111
111
|
elsif SECTIONS.include?(line.text)
|
112
|
-
@tokens << Token.new(:section, line.lineno, line.charno, line.text)
|
112
|
+
@tokens << Token.new(:section, line.lineno, line.charno, line.text.sub(/S$/, ""))
|
113
113
|
|
114
114
|
# Options, commands, usage, arguments, and briefs
|
115
115
|
elsif line =~ DECL_RE
|
data/lib/shellopts/parser.rb
CHANGED
@@ -132,7 +132,8 @@ module ShellOpts
|
|
132
132
|
|
133
133
|
option_token = Token.new(:option, 1, 1, "-h,help")
|
134
134
|
brief_token = Token.new(:brief, 1, 1, "Write help text and exit")
|
135
|
-
paragraph_token = Token.new(:text, 1, 1,
|
135
|
+
paragraph_token = Token.new(:text, 1, 1,
|
136
|
+
"-h prints a brief help text, --help prints a longer man-style description of the command")
|
136
137
|
group = OptionGroup.new(self, option_token)
|
137
138
|
option = Option.parse(group, option_token)
|
138
139
|
brief = Brief.parse(group, brief_token)
|
@@ -162,14 +163,6 @@ module ShellOpts
|
|
162
163
|
@nodes = {}
|
163
164
|
end
|
164
165
|
|
165
|
-
# def add_stdopts
|
166
|
-
# version_token = Token.new(:option, 1, 1, "--version")
|
167
|
-
# version_brief = Token.new(:brief, 1, 1, "Gryf gryf")
|
168
|
-
# group = Grammar::OptionGroup.new(@program, version_token)
|
169
|
-
# option = Grammar::Option.parse(group, version_token)
|
170
|
-
# brief = Grammr::Brief.parse(option, version_brief)
|
171
|
-
# end
|
172
|
-
|
173
166
|
def parse()
|
174
167
|
@program = Grammar::Program.parse(@tokens.shift)
|
175
168
|
oneline = @tokens.first.lineno == @tokens.last.lineno
|
data/lib/shellopts/version.rb
CHANGED
data/shellopts.gemspec
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "shellopts/version"
|
2
|
+
require_relative "lib/shellopts/version"
|
5
3
|
|
6
4
|
Gem::Specification.new do |spec|
|
7
5
|
spec.name = "shellopts"
|
@@ -15,15 +13,18 @@ Gem::Specification.new do |spec|
|
|
15
13
|
and has built-in help and error messages}
|
16
14
|
spec.homepage = "http://github.com/clrgit/shellopts"
|
17
15
|
|
18
|
-
spec.files
|
19
|
-
|
16
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
17
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
19
|
+
end
|
20
20
|
end
|
21
|
+
|
21
22
|
spec.bindir = "exe"
|
22
23
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
24
|
spec.require_paths = ["lib"]
|
24
25
|
|
25
26
|
spec.add_dependency "forward_to"
|
26
|
-
spec.add_dependency "constrain"
|
27
|
+
spec.add_dependency "constrain", "~> 0.5.1"
|
27
28
|
spec.add_dependency "ruby-terminfo"
|
28
29
|
spec.add_dependency "indented_io"
|
29
30
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shellopts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claus Rasmussen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03-
|
11
|
+
date: 2022-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: forward_to
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: constrain
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.5.1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.5.1
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: ruby-terminfo
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -132,10 +132,8 @@ executables: []
|
|
132
132
|
extensions: []
|
133
133
|
extra_rdoc_files: []
|
134
134
|
files:
|
135
|
-
- ".gitignore"
|
136
135
|
- ".rspec"
|
137
136
|
- ".ruby-version"
|
138
|
-
- ".travis.yml"
|
139
137
|
- Gemfile
|
140
138
|
- README.md
|
141
139
|
- Rakefile
|
data/.gitignore
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
/.bundle/
|
2
|
-
/.yardoc
|
3
|
-
/_yardoc/
|
4
|
-
/rdoc/
|
5
|
-
/pkg/
|
6
|
-
/spec/reports/
|
7
|
-
/tmp/
|
8
|
-
|
9
|
-
# rspec failure tracking
|
10
|
-
.rspec_status
|
11
|
-
|
12
|
-
# simplecov
|
13
|
-
/coverage/
|
14
|
-
|
15
|
-
# Ignore Gemfile.lock. See https://stackoverflow.com/questions/4151495/should-gemfile-lock-be-included-in-gitignore
|
16
|
-
/Gemfile.lock
|
17
|
-
|
18
|
-
# Ignore vim files
|
19
|
-
.*.swp
|
20
|
-
|
21
|
-
# Ignore t.* files
|
22
|
-
t
|
23
|
-
t.*
|
24
|
-
tt
|
25
|
-
tt.*
|
26
|
-
s
|
27
|
-
s.*
|
28
|
-
|
29
|
-
# Ignore temporary directory
|
30
|
-
/spec/tmpdir/
|