arli 0.5.1 → 0.6.1

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.
@@ -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 'arduino/library'
2
- require 'arli/config'
3
- require 'arli/version'
1
+ require 'arli/configuration'
4
2
 
5
3
  module Arli
6
- class CLI
4
+ module CLI
7
5
  class Parser < OptionParser
8
- attr_accessor :output_lines, :command, :options, :arlifile
9
6
 
10
- def initialize(command = nil)
7
+ attr_accessor :output_lines,
8
+ :command,
9
+ :config
10
+
11
+ def initialize(config: Arli.config, command: nil)
11
12
  super(nil, 22)
12
- self.output_lines = ::Array.new
13
- self.command = command
14
- self.options = ::Hashie::Mash.new
15
- self.arlifile = options[:arli_dir] ?
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('-p', '--arli-path PATH',
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
- options[:arli_dir] = v
27
+ config.arlifile.path = v
30
28
  end
31
29
  end
32
30
 
33
31
  def option_lib_home
34
- on('-l', '--libs PATH', 'Local folder where libraries are installed',
35
- "Defaults to #{default_library_path}\n\n") do |v|
36
- options[:lib_home] = v
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
- options[:database] = v
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
- options[:limit] = v.to_i if v
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 =~ /abort/i
60
- options[:abort_if_exists] = true
61
- elsif v =~ /backup/
62
- options[:create_backup] = true
63
- elsif v =~ /replace/
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
- on('-D', '--debug',
71
- 'Print debugging info.') do |v|
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
- output 'Description:' if command_name
89
- output ' ' * 4 + command_name[:description].green if command_name
90
- output ''
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 command_name && command_name[:example]
86
+ if command_hash && command_hash[:example]
95
87
  output 'Example:'
96
- output ' ' * 4 + command_name[:example]
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
- ::Arli::CLI.commands.each_pair do |command, config|
119
- subtext << %Q/#{sprintf(' %-12s', command.to_s).green} : #{sprintf('%s', config[:description]).yellow}\n/
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 #{COMMAND.blue + ' <command> '.green + '--help'.yellow} for more information on a specific command.
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 default_library_path
139
- ::Arli.config.library_path.gsub(%r(#{ENV['HOME']}), '~').blue
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
@@ -0,0 +1,8 @@
1
+ module Arli
2
+ module Commands
3
+ end
4
+ end
5
+
6
+ require_relative 'commands/base'
7
+ require_relative 'commands/search'
8
+ require_relative 'commands/install'
@@ -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
- attr_accessor :lib_path,
12
- :arlifile,
13
- :abort_if_exists,
14
- :create_backup,
15
- :command,
16
- :debug,
17
- :trace
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 name
31
- self.class.name.gsub(/.*::/, '').downcase
22
+ def run(*args)
23
+ raise ArgumentError, 'This method must be implemented in subclasses'
32
24
  end
33
25
 
34
- def setup
35
- FileUtils.mkdir_p(lib_path)
26
+ def runtime
27
+ config.runtime
36
28
  end
37
29
 
38
- def error(msg, exception = nil)
39
- printf 'Runtime Error: '.red + "\n#{msg}\n" if msg
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 info(msg, header = nil)
48
- printf('%-20s', header.blue) if header
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