arli 0.8.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -8,7 +8,7 @@ def shell(*args)
8
8
  end
9
9
 
10
10
  task :permissions do
11
- shell('rm -rf pkg/ tmp/' )
11
+ shell('rm -rf pkg/ tmp/ coverage/' )
12
12
  shell("chmod -v o+r,g+r * */* */*/* */*/*/* */*/*/*/* */*/*/*/*/*")
13
13
  shell("find . -type d -exec chmod o+x,g+x {} \\;")
14
14
  end
@@ -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
@@ -8,3 +8,4 @@ end
8
8
  require 'arli/cli/runner'
9
9
  Arli::CLI::Runner.new(ARGV.dup).execute!
10
10
 
11
+
@@ -1,5 +1,5 @@
1
1
  require 'arduino/library'
2
-
2
+ require 'arli/helpers/inherited'
3
3
  require 'arli/version'
4
4
  require 'arli/extensions'
5
5
  require 'arli/errors'
@@ -1,10 +1,14 @@
1
- require_relative '../output'
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
@@ -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.arlifile_path = "#{config.arlifile.path}/#{config.arlifile.name}"
22
- self.dependencies = read_dependencies(libraries)
23
- Arli.config.libraries.temp_dir ||= Dir.mktmpdir
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 { |lib| make_lib(lib) }
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(::YAML.load(::File.read(self.arlifile_path)))
87
- parsed_data.dependencies.map { |lib| make_lib(lib) }
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
@@ -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
- require_relative '../output'
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
- require_relative '../output'
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
 
@@ -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 to this number',
78
- 'Set to 0 to disable. Default is 100.') do |v|
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
- output indent + Array(command_hash[:description]).map(&:dark).join('').gsub(/\n/, "\n#{indent}")
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: ["This command provides both the simple name-based search interface,\n",
41
- "and the most sophisticated field-by-field search using a downloaded, \n",
42
- "and locally cached Public Arduino Database JSON file, maintained\n",
43
- "by Arduino and the Community. If you know of another database,\n",
44
- "that's what the --database flag is for."],
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: 'Search using the regular expression containing the name:',
47
- cmd: 'arli search AudioZero' },
50
+ { desc: 'Finds any library with name matching a given string, case insensitively',
51
+ cmd: 'arli search audiozero' },
48
52
 
49
- { desc: 'Same exact search as above, but using ruby hash syntax:',
50
- cmd: %Q{arli search 'name: /AudioZero/'} },
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: 'Lets get a particular version of the library',
53
- cmd: %Q{arli search 'name: "AudioZero", version: "1.0,2"'} },
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: 'Search using case insensitive name search, and :',
56
- cmd: %Q{arli search 'name: /adafruit/i'} },
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: 'Finally, search for the exact name match:',
59
- cmd: %Q{arli search '^Time$'} },
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 ' + '[ name | search-expression ]'.magenta
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
- "This command reads ", "Arlifile".bold.green, " (from the current folder, by default),\n",
77
- "and then it installs all dependent libraries specified there, checking if \n",
78
- "each already exists, and if not — downloading them, and installing them into\n",
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
- examples: [
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
- "This command installs a single library into your library path\n",
103
- "using the third argument to the command #{'arli install'.bold.white}\n".dark ,
104
- "which can be a library name, local ZIP file, or a remote URL \n",
105
- "(either ZIP or Git Repo)\n"
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' + ' [ "library name" | url | local-zip ] '.magenta
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