arli 0.8.3 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +5 -4
- data/.travis.yml +16 -8
- data/README.md +235 -124
- data/Rakefile +1 -1
- data/arli.gemspec +1 -0
- data/exe/arli +1 -0
- data/lib/arli.rb +1 -1
- data/lib/arli/actions/action.rb +7 -33
- data/lib/arli/actions/unzip_file.rb +9 -6
- data/lib/arli/arli_file.rb +32 -28
- data/lib/arli/cli/app.rb +2 -3
- data/lib/arli/cli/command_finder.rb +2 -2
- data/lib/arli/cli/parser.rb +36 -9
- data/lib/arli/cli/parser_factory.rb +40 -38
- data/lib/arli/cli/runner.rb +0 -1
- data/lib/arli/commands/base.rb +2 -2
- data/lib/arli/commands/install.rb +49 -31
- data/lib/arli/commands/search.rb +40 -35
- data/lib/arli/configuration.rb +4 -3
- data/lib/arli/extensions.rb +6 -0
- data/lib/arli/helpers/inherited.rb +48 -0
- data/lib/arli/helpers/output.rb +187 -0
- data/lib/arli/library.rb +21 -2
- data/lib/arli/library/installer.rb +2 -2
- data/lib/arli/library/multi_version.rb +153 -0
- data/lib/arli/library/{proxy.rb → single_version.rb} +5 -20
- data/lib/arli/lock/file.rb +1 -2
- data/lib/arli/lock/formats/base.rb +8 -0
- data/lib/arli/lock/formats/cmake.rb +21 -5
- data/lib/arli/lock/formats/json.rb +2 -0
- data/lib/arli/lock/formats/text.rb +2 -0
- data/lib/arli/lock/formats/yaml.rb +3 -1
- data/lib/arli/version.rb +1 -1
- metadata +20 -5
- data/.rake_tasks~ +0 -8
- data/lib/arli/output.rb +0 -186
data/Rakefile
CHANGED
data/arli.gemspec
CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
|
31
31
|
spec.add_dependency 'arduino-library', '~> 0.5.4'
|
32
32
|
spec.add_dependency 'colored2'
|
33
|
+
spec.add_dependency 'awesome_print'
|
33
34
|
spec.add_dependency 'hashie'
|
34
35
|
spec.add_dependency 'dry-types'
|
35
36
|
spec.add_dependency 'dry-struct'
|
data/exe/arli
CHANGED
data/lib/arli.rb
CHANGED
data/lib/arli/actions/action.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
-
|
1
|
+
require 'arli/helpers/output'
|
2
|
+
require 'arli/helpers/inherited'
|
2
3
|
|
3
4
|
module Arli
|
4
5
|
module Actions
|
5
6
|
# Represents an abstract action related to the library
|
6
7
|
class Action
|
7
|
-
include Arli::Output
|
8
|
+
include Arli::Helpers::Output
|
9
|
+
|
10
|
+
include Arli::Helpers::Inherited
|
11
|
+
attr_assignable :check_command, :check_pattern, :description
|
8
12
|
|
9
13
|
extend Forwardable
|
10
14
|
def_delegators :@library,
|
@@ -15,37 +19,7 @@ module Arli
|
|
15
19
|
|
16
20
|
class << self
|
17
21
|
def inherited(base)
|
18
|
-
|
19
|
-
base.instance_eval do
|
20
|
-
class << self
|
21
|
-
attr_writer :check_command, :check_pattern, :description
|
22
|
-
|
23
|
-
def action_name
|
24
|
-
name.gsub(/.*::/, '').underscore.to_sym
|
25
|
-
end
|
26
|
-
|
27
|
-
def set_or_get(var_name, val = nil)
|
28
|
-
var = "@#{var_name}".to_sym
|
29
|
-
self.instance_variable_set(var, val) if val
|
30
|
-
self.instance_variable_get(var)
|
31
|
-
end
|
32
|
-
|
33
|
-
def check_pattern(val = nil)
|
34
|
-
set_or_get('check_pattern', val)
|
35
|
-
end
|
36
|
-
|
37
|
-
def check_command(val = nil)
|
38
|
-
set_or_get('check_command', val)
|
39
|
-
end
|
40
|
-
|
41
|
-
def description(val = nil)
|
42
|
-
set_or_get('description', val)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Add to the list of actions
|
48
|
-
::Arli::Actions.actions[base.action_name] = base
|
22
|
+
::Arli::Actions.actions[base.short_name] = base
|
49
23
|
end
|
50
24
|
end
|
51
25
|
|
@@ -12,12 +12,7 @@ module Arli
|
|
12
12
|
return if library.url !~ /\.zip$/i
|
13
13
|
|
14
14
|
download!
|
15
|
-
|
16
|
-
if File.exist?(zip_archive)
|
17
|
-
FileUtils.rm_rf(top_dir_inside_zip) if top_dir_inside_zip
|
18
|
-
unzip(zip_archive, '.')
|
19
|
-
FileUtils.move(top_dir_inside_zip, dir) if Dir.exist?(top_dir_inside_zip)
|
20
|
-
end
|
15
|
+
move_in_place!
|
21
16
|
rescue Exception => e
|
22
17
|
fuck
|
23
18
|
raise(e)
|
@@ -27,6 +22,14 @@ module Arli
|
|
27
22
|
|
28
23
|
private
|
29
24
|
|
25
|
+
def move_in_place!
|
26
|
+
if File.exist?(zip_archive)
|
27
|
+
FileUtils.rm_rf(top_dir_inside_zip) if top_dir_inside_zip
|
28
|
+
unzip(zip_archive, '.')
|
29
|
+
FileUtils.move(top_dir_inside_zip, dir) if Dir.exist?(top_dir_inside_zip)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
30
33
|
def delete_zip!
|
31
34
|
FileUtils.rm_f(zip_archive) if File.exist?(zip_archive)
|
32
35
|
end
|
data/lib/arli/arli_file.rb
CHANGED
@@ -3,24 +3,41 @@ require 'yaml'
|
|
3
3
|
require 'forwardable'
|
4
4
|
require 'arduino/library'
|
5
5
|
require 'hashie/mash'
|
6
|
+
require 'hashie/extensions/symbolize_keys'
|
7
|
+
require 'arli/library'
|
6
8
|
|
7
9
|
module Arli
|
8
10
|
class ArliFile
|
9
11
|
require 'arduino/library/include'
|
10
12
|
|
11
13
|
include Enumerable
|
12
|
-
extend Forwardable
|
13
14
|
|
15
|
+
extend Forwardable
|
14
16
|
def_delegators :@dependencies, *(Array.new.methods - Object.methods)
|
15
17
|
|
18
|
+
include ::Arli::Library
|
19
|
+
|
16
20
|
attr_accessor :dependencies,
|
17
21
|
:parsed_data,
|
18
|
-
:arlifile_path
|
22
|
+
:arlifile_path,
|
23
|
+
:config
|
19
24
|
|
20
25
|
def initialize(config: Arli.config, libraries: [])
|
21
|
-
self.
|
22
|
-
self.
|
23
|
-
|
26
|
+
self.config = config
|
27
|
+
self.arlifile_path = "#{config.arlifile.path}/#{config.arlifile.name}"
|
28
|
+
self.dependencies = read_dependencies(libraries)
|
29
|
+
|
30
|
+
self.config.libraries.temp_dir ||= Dir.mktmpdir
|
31
|
+
|
32
|
+
if parsed_data
|
33
|
+
if parsed_data.libraries_path
|
34
|
+
self.config.libraries.path = parsed_data.libraries_path
|
35
|
+
end
|
36
|
+
|
37
|
+
if parsed_data.lock_format
|
38
|
+
Arli.config.arlifile.lock_format = parsed_data.lock_format
|
39
|
+
end
|
40
|
+
end
|
24
41
|
end
|
25
42
|
|
26
43
|
alias libraries dependencies
|
@@ -43,26 +60,6 @@ module Arli
|
|
43
60
|
end
|
44
61
|
end
|
45
62
|
|
46
|
-
|
47
|
-
def library_model(lib)
|
48
|
-
return lib if lib.is_a?(::Arduino::Library::Model)
|
49
|
-
|
50
|
-
::Arduino::Library::Model.from(lib).tap do |model|
|
51
|
-
if model.nil?
|
52
|
-
lib_output = (lib && lib['name']) ? lib['name'] : lib.inspect
|
53
|
-
raise Arli::Errors::LibraryNotFound, 'Error: '.bold.red +
|
54
|
-
"Library #{lib_output.yellow} ".red + "was not found.\n\n".red +
|
55
|
-
%Q[ HINT: run #{"arli search 'name: /#{lib_output}/'".green}\n] +
|
56
|
-
%Q[ to find the exact name of the library you are trying\n] +
|
57
|
-
%Q[ to install. Alternatively, provide a url: field.\n]
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def make_lib(lib)
|
63
|
-
::Arli::Library::Proxy.new(library_model(lib))
|
64
|
-
end
|
65
|
-
|
66
63
|
def within_path(p, &_block)
|
67
64
|
FileUtils.mkpath(p) unless Dir.exist?(p)
|
68
65
|
Dir.chdir(p) do
|
@@ -72,7 +69,7 @@ module Arli
|
|
72
69
|
|
73
70
|
def read_dependencies(libraries)
|
74
71
|
if libraries && !libraries.empty?
|
75
|
-
libraries.map {
|
72
|
+
libraries.map {|lib| make_lib(lib)}
|
76
73
|
else
|
77
74
|
unless arlifile_path && File.exist?(arlifile_path)
|
78
75
|
raise(Arli::Errors::ArliFileNotFound,
|
@@ -83,8 +80,15 @@ module Arli
|
|
83
80
|
end
|
84
81
|
|
85
82
|
def parse_yaml_file
|
86
|
-
self.parsed_data = Hashie::Mash.new(
|
87
|
-
|
83
|
+
self.parsed_data = Hashie::Mash.new(
|
84
|
+
Hashie::Extensions::SymbolizeKeys.symbolize_keys(
|
85
|
+
::YAML.load(
|
86
|
+
::File.read(
|
87
|
+
self.arlifile_path)
|
88
|
+
)
|
89
|
+
)
|
90
|
+
)
|
91
|
+
parsed_data.dependencies.map {|lib| make_lib(lib)}
|
88
92
|
end
|
89
93
|
end
|
90
94
|
end
|
data/lib/arli/cli/app.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require 'optparse'
|
3
|
-
require 'colored2'
|
4
3
|
require 'tmpdir'
|
5
4
|
require_relative 'parser'
|
6
5
|
require_relative 'command_finder'
|
7
6
|
require_relative 'parser_factory'
|
8
7
|
require_relative '../commands'
|
9
|
-
|
8
|
+
require 'arli/helpers/output'
|
10
9
|
|
11
10
|
|
12
11
|
module Arli
|
13
12
|
module CLI
|
14
13
|
class App
|
15
|
-
include Arli::Output
|
14
|
+
include Arli::Helpers::Output
|
16
15
|
|
17
16
|
attr_accessor :argv, :config, :command
|
18
17
|
|
@@ -8,13 +8,13 @@ require_relative 'parser_factory'
|
|
8
8
|
require_relative '../commands'
|
9
9
|
require_relative '../commands/search'
|
10
10
|
require_relative '../commands/install'
|
11
|
-
|
11
|
+
require 'arli/helpers/output'
|
12
12
|
|
13
13
|
module Arli
|
14
14
|
module CLI
|
15
15
|
class CommandFinder
|
16
16
|
|
17
|
-
include Arli::Output
|
17
|
+
include Arli::Helpers::Output
|
18
18
|
|
19
19
|
attr_accessor :argv, :config, :command_name, :command
|
20
20
|
|
data/lib/arli/cli/parser.rb
CHANGED
@@ -69,15 +69,32 @@ module Arli
|
|
69
69
|
def option_search
|
70
70
|
on('-d', '--database URL',
|
71
71
|
'a JSON(.gz) file path or a URL of the library database.',
|
72
|
-
'Defaults to the Arduino-maintained database.') do |v|
|
72
|
+
'Defaults to the Arduino-maintained database.' + "\n\n") do |v|
|
73
73
|
config.database.path = v
|
74
74
|
end
|
75
75
|
|
76
76
|
on('-m', '--max NUMBER',
|
77
|
-
'if provided, limits the result set
|
78
|
-
'
|
77
|
+
'if provided, limits the result set using the ',
|
78
|
+
'total number of the unique library name matches.',
|
79
|
+
'Default is 0, which means no limit.' + "\n\n") do |v|
|
79
80
|
config.search.results.limit = v.to_i if v
|
80
81
|
end
|
82
|
+
|
83
|
+
formats = Arli::Library::MultiVersion.format_methods
|
84
|
+
|
85
|
+
on('-f', '--format FMT',
|
86
|
+
"Optional format of the search results.",
|
87
|
+
"The default is #{'short'.bold.yellow}. Available ",
|
88
|
+
"formats: #{formats.join(', ').bold.yellow}\n\n") do |v|
|
89
|
+
if formats.include?(v.downcase.to_sym)
|
90
|
+
config.search.results.output_format = v.downcase.to_sym
|
91
|
+
else
|
92
|
+
raise ::OptionParser::InvalidOption,
|
93
|
+
"#{v.yellow} is not a supported search result format"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
option_search_attributes
|
81
98
|
end
|
82
99
|
|
83
100
|
def option_if_exists
|
@@ -115,6 +132,17 @@ module Arli
|
|
115
132
|
end
|
116
133
|
end
|
117
134
|
|
135
|
+
def option_search_attributes
|
136
|
+
on('-A', '--print-attrs', 'prints full list of available library',
|
137
|
+
'attributes that can be used in search strings.', ' ') do
|
138
|
+
|
139
|
+
::Arli.config.help = true
|
140
|
+
output ''
|
141
|
+
header('Arduino Library Attributes:')
|
142
|
+
output " • " + Arduino::Library::Types::LIBRARY_PROPERTIES.keys.join("\n • ") + "\n\n"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
118
146
|
def header(string)
|
119
147
|
output "#{string.bold.magenta}:"
|
120
148
|
output
|
@@ -174,6 +202,7 @@ See #{Arli::Configuration::ARLI_COMMAND.blue + ' command '.green + '--help'.yell
|
|
174
202
|
on('-C', '--no-color',
|
175
203
|
'Disable any color output.') do |*|
|
176
204
|
Colored2.disable! # if $stdout.tty?
|
205
|
+
config.no_color = true
|
177
206
|
end
|
178
207
|
on('-D', '--debug',
|
179
208
|
'Print debugging info.') do |v|
|
@@ -183,10 +212,6 @@ See #{Arli::Configuration::ARLI_COMMAND.blue + ' command '.green + '--help'.yell
|
|
183
212
|
'Print exception stack traces.') do |v|
|
184
213
|
config.trace = v
|
185
214
|
end
|
186
|
-
# on('-n', '--dry-run',
|
187
|
-
# 'Only print actions, but do not do them.') do |v|
|
188
|
-
# config.trace = v
|
189
|
-
# end
|
190
215
|
on('-v', '--verbose',
|
191
216
|
'Print more information.') do |v|
|
192
217
|
config.verbose = true
|
@@ -209,7 +234,7 @@ See #{Arli::Configuration::ARLI_COMMAND.blue + ' command '.green + '--help'.yell
|
|
209
234
|
|
210
235
|
def output_command_description(command_name)
|
211
236
|
command_hash = factory.command_parsers[command_name]
|
212
|
-
indent
|
237
|
+
indent = ' '
|
213
238
|
|
214
239
|
if command_hash
|
215
240
|
if command_hash.description
|
@@ -218,7 +243,9 @@ See #{Arli::Configuration::ARLI_COMMAND.blue + ' command '.green + '--help'.yell
|
|
218
243
|
output indent + command_hash.sentence.bold
|
219
244
|
output ''
|
220
245
|
end
|
221
|
-
|
246
|
+
|
247
|
+
text = Array(command_hash[:description]).flatten.join(' ')
|
248
|
+
output text.reformat_wrapped(width = 70, indent_with = 8)
|
222
249
|
end
|
223
250
|
end
|
224
251
|
|
@@ -28,6 +28,7 @@ module Arli
|
|
28
28
|
@global ||= make_parser do |parser|
|
29
29
|
parser.banner = usage_line
|
30
30
|
parser.sep
|
31
|
+
parser.option_search_attributes
|
31
32
|
parser.option_help(commands: true)
|
32
33
|
end
|
33
34
|
end
|
@@ -36,32 +37,38 @@ module Arli
|
|
36
37
|
@command_parsers ||= {
|
37
38
|
search: Hashie::Mash.new(
|
38
39
|
{
|
39
|
-
sentence: 'Search standard Arduino Library Database with over 4K entries',
|
40
|
-
description: [
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
sentence: 'Search standard Arduino Library Database with over 4K entries ',
|
41
|
+
description: %Q[This command provides both the simple name-based search interface,
|
42
|
+
and the most sophisticated attribute-specific search using a downloaded,
|
43
|
+
and locally cached Public Arduino Database JSON file, maintained
|
44
|
+
by the Arduino Community. If you know of another database,
|
45
|
+
that's what the #{'--database'.blue} flag is for.
|
46
|
+
Note that you can print the list of available attributes by
|
47
|
+
running arli with #{'--print-attrs'.blue} flag.
|
48
|
+
],
|
45
49
|
examples: [
|
46
|
-
{ desc: '
|
47
|
-
cmd: 'arli search
|
50
|
+
{ desc: 'Finds any library with name matching a given string, case insensitively',
|
51
|
+
cmd: 'arli search audiozero' },
|
48
52
|
|
49
|
-
{ desc: '
|
50
|
-
cmd: %Q{arli search
|
53
|
+
{ desc: 'If the first character is "/", then the argument is assumed to be regex',
|
54
|
+
cmd: %Q{arli search /AudioZero$/ } },
|
51
55
|
|
52
|
-
{ desc: '
|
53
|
-
cmd: %Q{arli search
|
56
|
+
{ desc: 'If the first character is "=", then the rest is assumed to be exact name',
|
57
|
+
cmd: %Q{arli search =Time } },
|
54
58
|
|
55
|
-
{ desc: '
|
56
|
-
cmd: %Q{arli search 'name:
|
59
|
+
{ desc: 'Lets get a particular version of the library using another attribute',
|
60
|
+
cmd: %Q{arli search 'name: "AudioZero", version: "1.0.2"'} },
|
57
61
|
|
58
|
-
{ desc: '
|
59
|
-
cmd: %Q{arli search '
|
62
|
+
{ desc: 'Search using case insensitive search for the author',
|
63
|
+
cmd: %Q{arli search 'author: /adafruit/i'} },
|
64
|
+
|
65
|
+
{ desc: 'Finally, search for regex match for "WiFi" in a sentence or a paragraph',
|
66
|
+
cmd: %Q{arli search 'sentence: /wifi/i, paragraph: /wifi/i'} },
|
60
67
|
],
|
61
68
|
|
62
69
|
parser: -> (command_name) {
|
63
70
|
make_parser(command_name) do |parser|
|
64
|
-
parser.banner = usage_line 'search ' + '[
|
71
|
+
parser.banner = usage_line 'search ' + '[ -A | search-expression ] '.magenta
|
65
72
|
parser.option_search
|
66
73
|
parser.option_help(command_name: command_name)
|
67
74
|
end
|
@@ -71,15 +78,13 @@ module Arli
|
|
71
78
|
bundle: Hashie::Mash.new(
|
72
79
|
{
|
73
80
|
sentence: 'Installs all libraries specified in Arlifile',
|
74
|
-
description:
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
"your Arduino Library folder. Both the folder with the Arlifile, as well as the\n",
|
80
|
-
"destination library path folder can be changed with the command line flags.\n",
|
81
|
+
description: %Q[This command reads #{'Arlifile'.bold.green} (from the current folder, by default),
|
82
|
+
and then it installs all dependent libraries specified there, checking if
|
83
|
+
each already exists, and if not — downloading them, and installing them into
|
84
|
+
your Arduino Library folder. Both the folder with the Arlifile, as well as the
|
85
|
+
destination library path folder can be changed with the command line flags.
|
81
86
|
],
|
82
|
-
|
87
|
+
example: [
|
83
88
|
{ desc: 'Install all libs defined in Arlifile:',
|
84
89
|
cmd: 'arli bundle ' },
|
85
90
|
|
@@ -98,27 +103,24 @@ module Arli
|
|
98
103
|
install: Hashie::Mash.new(
|
99
104
|
{
|
100
105
|
sentence: 'Installs a single library either by searching, or url or local ZIP',
|
101
|
-
description: [
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
106
|
+
description: %Q[This command installs a single library into your library path
|
107
|
+
(which can be set with #{'--lib-path'.blue} flag).
|
108
|
+
Arli interpretes the third argument to #{'arli install'.bold.blue}
|
109
|
+
as either an exact library name, or a remote URL
|
110
|
+
(either ZIP or Git Repo). You can use #{'search'.bold.green} command
|
111
|
+
to first find the right library name, and then pass it to the install command.
|
107
112
|
],
|
108
113
|
examples: [
|
109
|
-
{ desc: 'Install the latest version of this library',
|
110
|
-
cmd: 'arli install "Adafruit GFX Library"' },
|
114
|
+
{ desc: 'Install the latest version of this library locally',
|
115
|
+
cmd: 'arli install "Adafruit GFX Library" -l ./libraries' },
|
111
116
|
|
112
117
|
{ desc: 'Install the library from a Github URL',
|
113
|
-
cmd: 'arli install https://github.com/jfturcot/SimpleTimer' }
|
114
|
-
|
115
|
-
{ desc: 'Install a local ZIP file',
|
116
|
-
cmd: 'arli install ~/Downloads/DHT-Library.zip' },
|
118
|
+
cmd: 'arli install https://github.com/jfturcot/SimpleTimer' }
|
117
119
|
],
|
118
120
|
|
119
121
|
parser: -> (command_name) {
|
120
122
|
make_parser(command_name) do |parser|
|
121
|
-
parser.banner = usage_line 'install' + ' [ "
|
123
|
+
parser.banner = usage_line 'install' + ' [ "Exact Library Name" | url ] '.magenta
|
122
124
|
parser.option_install
|
123
125
|
parser.option_help(command_name: command_name)
|
124
126
|
end
|