arli 0.5.1 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rake_tasks~ +8 -0
- data/README.md +122 -30
- data/Rakefile +24 -2
- data/arli.gemspec +4 -1
- data/exe/arli +2 -4
- data/lib/arli.rb +19 -21
- data/lib/arli/actions.rb +19 -0
- data/lib/arli/actions/action.rb +32 -0
- data/lib/arli/actions/backup.rb +30 -0
- data/lib/arli/actions/dir_name.rb +66 -0
- data/lib/arli/actions/git_repo.rb +43 -0
- data/lib/arli/actions/zip_file.rb +54 -0
- data/lib/arli/arli_file.rb +22 -37
- data/lib/arli/cli.rb +4 -190
- data/lib/arli/cli/app.rb +73 -0
- data/lib/arli/cli/command_finder.rb +72 -0
- data/lib/arli/{parser.rb → cli/parser.rb} +66 -56
- data/lib/arli/cli/parser_factory.rb +97 -0
- data/lib/arli/cli/runner.rb +40 -0
- data/lib/arli/commands.rb +8 -0
- data/lib/arli/commands/base.rb +23 -30
- data/lib/arli/commands/install.rb +14 -9
- data/lib/arli/commands/search.rb +35 -10
- data/lib/arli/configuration.rb +62 -0
- data/lib/arli/extensions.rb +9 -0
- data/lib/arli/installer.rb +30 -78
- data/lib/arli/library.rb +49 -0
- data/lib/arli/output.rb +94 -0
- data/lib/arli/version.rb +1 -1
- metadata +63 -8
- data/lib/arli/config.rb +0 -16
- data/lib/arli/installers/zip_file.rb +0 -61
- data/lib/arli/logger.rb +0 -13
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
require 'colored2'
|
5
|
+
|
6
|
+
require_relative 'parser'
|
7
|
+
require_relative 'parser_factory'
|
8
|
+
require_relative '../commands'
|
9
|
+
require_relative '../commands/search'
|
10
|
+
require_relative '../commands/install'
|
11
|
+
require_relative '../output'
|
12
|
+
|
13
|
+
module Arli
|
14
|
+
module CLI
|
15
|
+
class CommandFinder
|
16
|
+
|
17
|
+
include Arli::Output
|
18
|
+
|
19
|
+
attr_accessor :argv, :config, :command_name, :command
|
20
|
+
|
21
|
+
def initialize(argv, config: Arli.config)
|
22
|
+
self.config = config
|
23
|
+
self.argv = argv
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse!
|
27
|
+
self.command_name = detect_command
|
28
|
+
parse_command_arguments!(command_name)
|
29
|
+
unless Arli.config.help
|
30
|
+
self.command = instantiate_command
|
31
|
+
if self.command
|
32
|
+
config.runtime.command.instance = command
|
33
|
+
config.runtime.command.name = command_name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse_command_arguments!(cmd)
|
40
|
+
parser = factory.command_parser(cmd)
|
41
|
+
if parser
|
42
|
+
factory.parse_argv(parser, argv)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def instantiate_command
|
47
|
+
self.command_name = detect_command unless command_name
|
48
|
+
begin
|
49
|
+
name = command_name.to_s.capitalize.to_sym
|
50
|
+
command_class = ::Arli::Commands.const_get(name)
|
51
|
+
raise_invalid_arli_command!(command_name) unless command_class
|
52
|
+
command_class.new(config: config) if command_class
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def detect_command
|
57
|
+
return nil unless argv.first && argv.first !~ /^-.*$/
|
58
|
+
cmd = argv.shift.to_sym
|
59
|
+
if factory.valid_command?(cmd)
|
60
|
+
cmd
|
61
|
+
else
|
62
|
+
raise_invalid_arli_command!(cmd)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def factory
|
67
|
+
Arli::CLI::ParserFactory
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -1,21 +1,19 @@
|
|
1
|
-
require '
|
2
|
-
require 'arli/config'
|
3
|
-
require 'arli/version'
|
1
|
+
require 'arli/configuration'
|
4
2
|
|
5
3
|
module Arli
|
6
|
-
|
4
|
+
module CLI
|
7
5
|
class Parser < OptionParser
|
8
|
-
attr_accessor :output_lines, :command, :options, :arlifile
|
9
6
|
|
10
|
-
|
7
|
+
attr_accessor :output_lines,
|
8
|
+
:command,
|
9
|
+
:config
|
10
|
+
|
11
|
+
def initialize(config: Arli.config, command: nil)
|
11
12
|
super(nil, 22)
|
12
|
-
|
13
|
-
self.
|
14
|
-
self.
|
15
|
-
self.
|
16
|
-
options[:arli_dir] + '/' + Arli::Config::DEFAULT_FILENAME :
|
17
|
-
Arli::Config::DEFAULT_FILENAME
|
18
|
-
self.options[:arlifile] = arlifile
|
13
|
+
|
14
|
+
self.config = config
|
15
|
+
self.command = command
|
16
|
+
self.output_lines = ::Array.new
|
19
17
|
end
|
20
18
|
|
21
19
|
def sep(text = nil)
|
@@ -23,17 +21,18 @@ module Arli
|
|
23
21
|
end
|
24
22
|
|
25
23
|
def option_dependency_file
|
26
|
-
on('-
|
24
|
+
on('-a', '--arli-path PATH',
|
27
25
|
'Folder where ' + 'Arlifile'.green + ' is located,',
|
28
26
|
"Defaults to the current directory.\n\n") do |v|
|
29
|
-
|
27
|
+
config.arlifile.path = v
|
30
28
|
end
|
31
29
|
end
|
32
30
|
|
33
31
|
def option_lib_home
|
34
|
-
on('-l', '--
|
35
|
-
|
36
|
-
|
32
|
+
on('-l', '--libraries PATH',
|
33
|
+
'Local folder where libraries are installed',
|
34
|
+
"Defaults to #{Arli.default_library_path}\n\n") do |v|
|
35
|
+
config.libraries.path = v
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
@@ -41,12 +40,13 @@ module Arli
|
|
41
40
|
on('-d', '--database FILE/URL',
|
42
41
|
'a JSON file name, or a URL that contains the index',
|
43
42
|
'Defaults to the Arduino-maintained list') do |v|
|
44
|
-
|
43
|
+
config.database.path = v
|
45
44
|
end
|
45
|
+
|
46
46
|
on('-m', '--max NUMBER',
|
47
47
|
'if provided, limits the result set to this number',
|
48
48
|
'Defaults to 100') do |v|
|
49
|
-
|
49
|
+
config.search.results.limit = v.to_i if v
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -56,47 +56,37 @@ module Arli
|
|
56
56
|
'it will be overwritten or updated if possible.',
|
57
57
|
'Alternatively you can either ' + 'abort'.bold.blue + ' or ' + 'backup'.bold.blue
|
58
58
|
) do |v|
|
59
|
-
if v
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
59
|
+
if v == 'abort'
|
60
|
+
config.install.if_exists.abort = true
|
61
|
+
config.install.if_exists.overwrite = false
|
62
|
+
elsif v == 'backup'
|
63
|
+
config.install.if_exists.backup = true
|
64
64
|
end
|
65
65
|
end
|
66
66
|
sep ' '
|
67
67
|
end
|
68
68
|
|
69
69
|
def option_help(commands: false, command_name: nil)
|
70
|
-
|
71
|
-
|
72
|
-
options[:debug] = true
|
73
|
-
end
|
74
|
-
on('-t', '--trace',
|
75
|
-
'Print exception stack traces.') do |v|
|
76
|
-
options[:trace] = v
|
77
|
-
end
|
78
|
-
on('-v', '--verbose',
|
79
|
-
'Print more information.') do |v|
|
80
|
-
options[:verbose] = true
|
81
|
-
end
|
82
|
-
on('-V', '--version',
|
83
|
-
'Print current version and exit') do |v|
|
84
|
-
output 'Version: ' + Arli::VERSION
|
85
|
-
options[:help] = true
|
86
|
-
end
|
70
|
+
common_help_options
|
71
|
+
|
87
72
|
on('-h', '--help', 'prints this help') do
|
88
|
-
|
89
|
-
|
90
|
-
|
73
|
+
::Arli.config.help = true
|
74
|
+
|
75
|
+
command_hash = factory.command_parsers[command_name]
|
76
|
+
|
77
|
+
if command_hash && command_hash[:description]
|
78
|
+
output 'Description:'
|
79
|
+
output ' ' + command_hash[:description]
|
80
|
+
output ''
|
81
|
+
end
|
82
|
+
|
91
83
|
output_help
|
92
84
|
output_command_help if commands
|
93
85
|
|
94
|
-
if
|
86
|
+
if command_hash && command_hash[:example]
|
95
87
|
output 'Example:'
|
96
|
-
output '
|
88
|
+
output ' ' + command_hash[:example]
|
97
89
|
end
|
98
|
-
|
99
|
-
options[:help] = true
|
100
90
|
end
|
101
91
|
end
|
102
92
|
|
@@ -113,14 +103,14 @@ module Arli
|
|
113
103
|
end
|
114
104
|
|
115
105
|
def command_help
|
116
|
-
subtext = "Available Commands:\n"
|
117
106
|
|
118
|
-
|
119
|
-
|
107
|
+
subtext = "Available Commands:\n"
|
108
|
+
factory.command_parsers.each_pair do |command, config|
|
109
|
+
subtext << %Q/#{sprintf(' %-12s', command.to_s).green} — #{sprintf('%s', config[:description]).blue}\n/
|
120
110
|
end
|
121
111
|
subtext << <<-EOS
|
122
|
-
|
123
|
-
See #{
|
112
|
+
|
113
|
+
See #{Arli::Configuration::ARLI_COMMAND.blue + ' command '.green + '--help'.yellow} for more information on a specific command.
|
124
114
|
|
125
115
|
EOS
|
126
116
|
subtext
|
@@ -135,8 +125,28 @@ See #{COMMAND.blue + ' <command> '.green + '--help'.yellow} for more information
|
|
135
125
|
puts output.join("\n") unless output.empty?
|
136
126
|
end
|
137
127
|
|
138
|
-
def
|
139
|
-
::
|
128
|
+
def factory
|
129
|
+
Arli::CLI::ParserFactory
|
130
|
+
end
|
131
|
+
|
132
|
+
def common_help_options
|
133
|
+
on('-D', '--debug',
|
134
|
+
'Print debugging info.') do |v|
|
135
|
+
config.debug = true
|
136
|
+
end
|
137
|
+
on('-t', '--trace',
|
138
|
+
'Print exception stack traces.') do |v|
|
139
|
+
config.trace = v
|
140
|
+
end
|
141
|
+
on('-v', '--verbose',
|
142
|
+
'Print more information.') do |v|
|
143
|
+
config.verbose = true
|
144
|
+
end
|
145
|
+
on('-V', '--version',
|
146
|
+
'Print current version and exit') do |v|
|
147
|
+
puts 'Version: ' + Arli::VERSION
|
148
|
+
exit
|
149
|
+
end
|
140
150
|
end
|
141
151
|
end
|
142
152
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require_relative 'parser'
|
2
|
+
|
3
|
+
module Arli
|
4
|
+
module CLI
|
5
|
+
module ParserFactory
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def default_help
|
10
|
+
gp = global_parser
|
11
|
+
gp.parse!(%w(--help))
|
12
|
+
gp.print
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse_argv(parser, argv)
|
16
|
+
if parser
|
17
|
+
parser.parse!(argv)
|
18
|
+
parser.print
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_parser(command = nil, &block)
|
23
|
+
::Arli::CLI::Parser.new(command: command,
|
24
|
+
config: Arli.config, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def global_parser
|
28
|
+
@global ||= make_parser do |parser|
|
29
|
+
parser.banner = usage_line
|
30
|
+
parser.sep
|
31
|
+
parser.option_help(commands: true)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def command_parsers
|
36
|
+
@command_parsers ||= {
|
37
|
+
install: {
|
38
|
+
description: 'installs libraries defined in Arlifile',
|
39
|
+
parser: -> (command_name) {
|
40
|
+
make_parser(command_name) do |parser|
|
41
|
+
parser.banner = usage_line 'install'
|
42
|
+
parser.option_lib_home
|
43
|
+
parser.option_dependency_file
|
44
|
+
parser.option_abort_if_exists
|
45
|
+
parser.option_help(command_name: command_name)
|
46
|
+
end
|
47
|
+
} },
|
48
|
+
|
49
|
+
search: {
|
50
|
+
description: 'Flexible Search of the Arduino Library Database',
|
51
|
+
example: 'arli search '.green + %Q['name: /AudioZero/, version: "1.0.1"'].green,
|
52
|
+
parser: -> (command_name) {
|
53
|
+
make_parser(command_name) do |parser|
|
54
|
+
parser.banner = usage_line 'search ' + '[ name-match | expression ]'.magenta
|
55
|
+
parser.option_search
|
56
|
+
parser.option_help(command_name: command_name)
|
57
|
+
end
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def commands
|
64
|
+
command_parsers.keys
|
65
|
+
end
|
66
|
+
|
67
|
+
def valid_command?(command)
|
68
|
+
commands.include?(command)
|
69
|
+
end
|
70
|
+
|
71
|
+
def command_parser(cmd)
|
72
|
+
cmd_hash = command_parsers[cmd]
|
73
|
+
cmd_hash ? cmd_hash[:parser].call(cmd) : nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def global_usage(command)
|
77
|
+
"Usage:\n " + Arli::Configuration::ARLI_COMMAND.blue +
|
78
|
+
' [ options ] '.yellow + '[ ' + (command || 'command').green +
|
79
|
+
' [ options ] '.yellow + ' ]' + "\n"
|
80
|
+
end
|
81
|
+
|
82
|
+
def command_usage(command)
|
83
|
+
"Usage:\n " + Arli::Configuration::ARLI_COMMAND.blue + ' ' +
|
84
|
+
command.green +
|
85
|
+
' [options]'.yellow + "\n\n" +
|
86
|
+
'Command Options'
|
87
|
+
end
|
88
|
+
|
89
|
+
def usage_line(command = nil)
|
90
|
+
command ? command_usage(command) : global_usage(command)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'colored2'
|
2
|
+
require 'arli/cli/app'
|
3
|
+
require 'pp'
|
4
|
+
module Arli
|
5
|
+
module CLI
|
6
|
+
# For the reasons this file is the way it is, please refer to
|
7
|
+
# https://github.com/erikhuda/thor/wiki/Integrating-with-Aruba-In-Process-Runs
|
8
|
+
class Runner
|
9
|
+
def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = Kernel)
|
10
|
+
@argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute!
|
14
|
+
exit_code = begin
|
15
|
+
$stderr = @stderr
|
16
|
+
$stdin = @stdin
|
17
|
+
$stdout = @stdout
|
18
|
+
|
19
|
+
Arli::CLI::App.new(@argv).start
|
20
|
+
0
|
21
|
+
rescue StandardError => e
|
22
|
+
b = e.backtrace
|
23
|
+
@stderr.puts("#{b.shift.bold}:\n")
|
24
|
+
@stderr.puts("#{e.message.bold.red} (#{e.class.name.yellow})")
|
25
|
+
@stderr.puts(b.map { |s| "\tfrom #{s}" }.join("\n")).red
|
26
|
+
1
|
27
|
+
rescue SystemExit => e
|
28
|
+
e.status
|
29
|
+
ensure
|
30
|
+
$stderr = STDERR
|
31
|
+
$stdin = STDIN
|
32
|
+
$stdout = STDOUT
|
33
|
+
ap(Arli.config.to_hash, indent: 6, index: false) if Arli.config.debug
|
34
|
+
end
|
35
|
+
@kernel.exit(exit_code)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/arli/commands/base.rb
CHANGED
@@ -4,51 +4,44 @@ require 'open3'
|
|
4
4
|
require 'arli'
|
5
5
|
require 'arli/version'
|
6
6
|
require 'arli/errors'
|
7
|
+
require 'arli/output'
|
7
8
|
|
8
9
|
module Arli
|
9
10
|
module Commands
|
10
11
|
class Base
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
def initialize(options)
|
20
|
-
self.lib_path = options[:lib_home]
|
21
|
-
self.abort_if_exists = options[:abort_if_exists]
|
22
|
-
self.create_backup = options[:create_backup]
|
23
|
-
self.debug = options[:debug]
|
24
|
-
self.trace = options[:trace]
|
25
|
-
|
26
|
-
self.command = self.class.name.gsub(/.*::/, '').downcase.to_sym
|
12
|
+
include Arli::Output
|
13
|
+
|
14
|
+
attr_accessor :config, :name
|
15
|
+
|
16
|
+
def initialize(config: Arli.config)
|
17
|
+
self.config = config
|
18
|
+
FileUtils.mkdir_p(library_path) unless Dir.exist?(library_path)
|
27
19
|
setup
|
28
20
|
end
|
29
21
|
|
30
|
-
def
|
31
|
-
|
22
|
+
def run(*args)
|
23
|
+
raise ArgumentError, 'This method must be implemented in subclasses'
|
32
24
|
end
|
33
25
|
|
34
|
-
def
|
35
|
-
|
26
|
+
def runtime
|
27
|
+
config.runtime
|
36
28
|
end
|
37
29
|
|
38
|
-
def
|
39
|
-
|
40
|
-
if exception
|
41
|
-
puts
|
42
|
-
printf 'Exception: '.red + "\n#{exception.inspect.red}\n\n"
|
43
|
-
end
|
44
|
-
puts
|
30
|
+
def name
|
31
|
+
@name ||= self.class.name.gsub(/.*::/, '').downcase.to_sym
|
45
32
|
end
|
46
33
|
|
47
|
-
def
|
48
|
-
|
49
|
-
printf((header ? ' : ' : '') + msg + "\n") if msg
|
34
|
+
def library_path
|
35
|
+
config.libraries.path
|
50
36
|
end
|
51
37
|
|
38
|
+
def setup
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def params
|
43
|
+
|
44
|
+
end
|
52
45
|
end
|
53
46
|
end
|
54
47
|
end
|