console_runner 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f8075476480adc8aea5a9508dca384fa66508a22
4
+ data.tar.gz: f58b9bedc8621e0ff85b83e918b3f64c2d8cb852
5
+ SHA512:
6
+ metadata.gz: a717dc7f2387a0549d984d571a9cedaa1eb2f45f1e4575ff639d3d7e61ca55ee8cc3aeca2e55478d69ad4d308d54c94bded243bae7d781bc6a5baa2270d0fa29
7
+ data.tar.gz: 162a8c1b729c4eb5c833cdcc1efee701d597ec8879875adc0f05f105f01d52faf6188aad67d739c4a491718e415262f64e73d118e39084f8782866a4067b3c58
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ repo_token: Zt5KZXhBj3awn9OS5Hy6pDuVEGSrWWSjT
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /vendor/
11
+ /.idea/
12
+ *.gem
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.5
5
+ before_install: gem install bundler -v 1.13.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in console_runner.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Yury Karpovich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # ConsoleRunner
2
+ [![Gem Version][GV img]][Gem Version]
3
+ [![Build Status][BS img]][Build Status]
4
+ [![Dependency Status][DS img]][Dependency Status]
5
+ [![Code Climate][CC img]][Code Climate]
6
+ [![Coverage Status][CS img]][Coverage Status]
7
+
8
+ This gem provides you an ability to run any Ruby method from command-line (no any code modifications required!!!).
9
+ One thing you need to do is to add an [YARD](http://yardoc.org/) tag annotation `@runnable`.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'console_runner'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install console_runner
26
+
27
+ ## Usage
28
+
29
+ TODO: Write usage instructions here
30
+
31
+ ## Development
32
+
33
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
34
+
35
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
36
+
37
+ ## Contributing
38
+
39
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yuri-karpovich/console_runner.
40
+
41
+
42
+ ## License
43
+
44
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
45
+
46
+
47
+ [Gem Version]: https://rubygems.org/gems/console_runner
48
+ [Build Status]: https://travis-ci.org/yuri-karpovich/console_runner
49
+ [travis pull requests]: https://travis-ci.org/yuri-karpovich/console_runner/pull_requests
50
+ [Dependency Status]: https://gemnasium.com/github.com/yuri-karpovich/console_runner
51
+ [Code Climate]: https://codeclimate.com/github/yuri-karpovich/console_runner
52
+ [Coverage Status]: https://coveralls.io/github/yuri-karpovich/console_runner
53
+
54
+ [GV img]: https://badge.fury.io/rb/console_runner.png
55
+ [BS img]: https://travis-ci.org/yuri-karpovich/console_runner.svg?branch=master
56
+ [DS img]: https://gemnasium.com/badges/github.com/yuri-karpovich/console_runner.svg
57
+ [CC img]: https://codeclimate.com/github/yuri-karpovich/console_runner.png
58
+ [CS img]: https://coveralls.io/repos/github/yuri-karpovich/console_runner/badge.svg
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "console_runner"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'console_runner/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'console_runner'
9
+ spec.version = ConsoleRunner::VERSION
10
+ spec.authors = ['Yury Karpovich']
11
+ spec.email = %w(spoonest@gmail.com yuri.karpovich@gmail.com)
12
+
13
+ spec.summary = 'Command-line runner for ruby code.'
14
+ spec.description = 'This gem provides you an ability to run any Ruby method ' \
15
+ 'from command-line (no any code modifications required!!!)'
16
+ spec.homepage = 'https://github.com/yuri-karpovich/console_runner'
17
+ spec.license = "MIT"
18
+
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
21
+ if spec.respond_to?(:metadata)
22
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
23
+ else
24
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
25
+ 'public gem pushes.'
26
+ end
27
+
28
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
29
+ f.match(%r{^(test|spec|features)/})
30
+ end
31
+ spec.bindir = 'exe'
32
+ spec.executables = ['c_run']
33
+ spec.require_paths = ['lib']
34
+
35
+ spec.add_development_dependency 'bundler', '~> 1.13'
36
+ spec.add_development_dependency 'rake', '~> 10.0'
37
+ spec.add_development_dependency 'minitest', '~> 5.0'
38
+ spec.add_development_dependency 'pry'
39
+ spec.add_development_dependency 'simplecov'
40
+ spec.add_development_dependency 'coveralls', '~> 0.8'
41
+ spec.add_dependency 'trollop', '~> 2.1'
42
+ spec.add_dependency 'yard', '~> 0.9'
43
+ spec.add_dependency 'colorize', '~> 0.8'
44
+ end
data/exe/c_run ADDED
@@ -0,0 +1,86 @@
1
+ # #!/usr/bin/env ruby
2
+ # require 'trollop'
3
+ #
4
+ #
5
+ # lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
6
+ # $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
7
+ # require '../lib/file_parser'
8
+ # require '../lib/cmd_parser'
9
+ # require '../lib/runner'
10
+ #
11
+ # file_path = ENV['DEBUG_FILE']
12
+ # file_path ||= File.realpath ARGV.shift
13
+ # file_parser = FileParser.new(file_path)
14
+ #
15
+ #
16
+ # runnable_classes = file_parser.list_classes(:runnable)
17
+ # raise "One runnable Class should be specified in file.
18
+ # Runnable class should be marked with @#{FileParser::RUNNABLE_TAG.to_s} tag" if runnable_classes.count != 1
19
+ #
20
+ # clazz = runnable_classes.first
21
+ # all_methods = file_parser.list_methods(:all, clazz)
22
+ # runnable_methods = file_parser.list_methods(:runnable, clazz)
23
+ # initialize_method = all_methods.find{|m| m.name == :initialize}
24
+ # run_method = all_methods.find{|m| m.name == :run}
25
+ #
26
+ #
27
+ # cmd_parser = CmdParser.new(runnable_methods, initialize_method)
28
+ # cmd = ARGV[0]
29
+ # action_method = runnable_methods.find { |m| m.name.to_s == cmd } # get the subcommand
30
+ # action_method ||= run_method
31
+ # cmd_parser.parse_method action_method
32
+ # raise "Cannot run #{cmd} command because method is nil" unless action_method
33
+ #
34
+ #
35
+ # puts "======================================================="
36
+ # puts "Global options:"
37
+ # puts cmd_parser.global_opts.map{|k,v| " #{k} = #{v}" }.join("\n")
38
+ # if initialize_method
39
+ # puts "INIT: #{initialize_method.name}"
40
+ # puts "INIT options:"
41
+ # puts cmd_parser.init_method.cmd_opts.map{|k,v| " #{k} = #{v}" }.join("\n")
42
+ # end
43
+ # puts "Subcommand: #{action_method.name}"
44
+ # puts "Subcommand options:"
45
+ # puts cmd_parser.method.cmd_opts.map{|k,v| " #{k} = #{v}" }.join("\n")
46
+ # puts "Remaining arguments: #{ARGV.inspect}" if ARGV != []
47
+ # puts "======================================================="
48
+ #
49
+ #
50
+ # Runner.run{
51
+ # require file_path
52
+ # class_full_name = clazz.title
53
+ # raise "#{class_full_name} is not defined" unless Module.const_defined?(class_full_name)
54
+ # klass_obj = Module.const_get(class_full_name)
55
+ # method_type = action_method.scope
56
+ # method_params = cmd_parser.method.params_array
57
+ #
58
+ # case method_type
59
+ # when :class
60
+ # klass_obj.send(action_method.name, *method_params)
61
+ # when :instance
62
+ # init_params = cmd_parser.init_method.params_array
63
+ # # TODO catch errors
64
+ # obj = klass_obj.new(*init_params)
65
+ # obj.send(action_method.name, *method_params)
66
+ # else
67
+ # raise "Unknown method type: #{method_type}"
68
+ # end
69
+ #
70
+ # }
71
+ #
72
+ #
73
+ #
74
+ #
75
+ #
76
+ #
77
+ #
78
+ #
79
+ #
80
+ #
81
+ # # raise "#{clazz.name}#initialize method should be specified" unless initialize_method
82
+ # #
83
+ # # raise "At least one method should be marked with @#{FileParser::RUNNABLE_TAG.to_s} tag.
84
+ # # Also you may specify #run method and it will be executed by default.
85
+ # # #run method don't need any code annotations as well." if runnable_methods.count == 0 unless run_method
86
+ #
data/exe/c_run.rb ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../test/simple_cov' if ENV['C_RUNNER_SCOV'].to_s == 'true'
4
+
5
+ lib = File.expand_path('../../lib', __FILE__)
6
+ $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
7
+ require 'console_runner'
data/lib/cmd_parser.rb ADDED
@@ -0,0 +1,223 @@
1
+ require 'trollop'
2
+
3
+ # Parses command line
4
+ class CmdParser
5
+
6
+ # Parses method code
7
+ class ParsedMethod
8
+ attr_reader :method, :name, :param_tags, :option_tags
9
+ attr_accessor :cmd_opts
10
+
11
+ def initialize(method)
12
+ @method = method
13
+ @name = @method.name
14
+ @parameters = @method.parameters
15
+ @param_tags = FileParser.select_param_tags @method
16
+ @option_tags = FileParser.select_option_tags @method
17
+ @cmd_opts = nil
18
+ end
19
+
20
+ def params_array
21
+ expected_params = @parameters.map(&:first).map.with_index { |p, i| [i, p] }.to_h
22
+ options_groups = {}
23
+ get_params = {}
24
+
25
+ expected_params.each do |index, name|
26
+ if options_group?(name)
27
+ options_groups[index] = name
28
+ get_params[index] = option_as_hash(name)
29
+ else
30
+ get_params[index] = @cmd_opts[name.to_sym]
31
+ end
32
+ end
33
+ get_params = get_params.to_a.sort_by { |a| a[0] }.reverse
34
+
35
+ stop_delete = false
36
+ get_params.delete_if do |a|
37
+ index = a[0]
38
+ value = a[1]
39
+ result = false
40
+
41
+ if options_groups[index]
42
+ result = value == {}
43
+ else
44
+ result = value == nil
45
+ end
46
+ stop_delete = true unless result
47
+ next if stop_delete
48
+ result
49
+ end
50
+
51
+ get_params.sort_by { |a| a[0] }.map { |a| a[1] }
52
+ end
53
+
54
+ def param_tags_names
55
+ param_tags.map { |t| t.name }
56
+ end
57
+
58
+ def option_tags_names
59
+ option_tags.map { |t| t.pair.name.gsub(':', '') }
60
+ end
61
+
62
+ def options_group?(param_name)
63
+ option_tags.any? { |t| t.name == param_name }
64
+ end
65
+
66
+ def default_params
67
+ @parameters.map do |array|
68
+ array.map do |a|
69
+ if a
70
+ ['"', "'"].include?(a[0]) && ['"', "'"].include?(a[-1]) ? a[1..-2] : a
71
+ else
72
+ a
73
+ end
74
+ end
75
+ end.to_h
76
+ end
77
+
78
+ private
79
+
80
+ def option_as_hash(options_group_name)
81
+ result = {}
82
+ option_tags.select { |t| t.name == options_group_name }.each do |t|
83
+ option_name = t.pair.name.gsub(':', '')
84
+ option_value = @cmd_opts[option_name.to_sym]
85
+ result[option_name] = option_value if option_value
86
+ end
87
+ result
88
+ end
89
+ end
90
+
91
+ attr_reader :global_opts, :method, :init_method
92
+
93
+ # Should be executed before ARGV.shift
94
+ def initialize(runnable_methods, init_method= nil)
95
+ clazz = runnable_methods.first.parent
96
+ sub_commands = runnable_methods.map { |m| m.name.to_s }
97
+ @parser = Trollop::Parser.new
98
+ @parser.banner(FileParser.select_runnable_tags(clazz).map { |t| (t.text + "\n") }.join("\n"))
99
+ @parser.stop_on sub_commands
100
+
101
+ if init_method
102
+ @init_method = ParsedMethod.new init_method
103
+ same_methods = @init_method.param_tags_names & @init_method.option_tags_names
104
+ raise "You have the same name for @param and @option attribute(s): #{same_methods.join(', ')}.
105
+ Use different names to `console_runner` be able to run #{@init_method.name} method." if same_methods.count > 0
106
+
107
+
108
+ @init_method.param_tags.each do |tag|
109
+ tag_name = tag.name
110
+ tag_text = tag.text
111
+ tag_type = tag.type
112
+ if tag_type == "Hash"
113
+ options = option_tags.select { |t| t.name == tag.name }
114
+ if options.count > 0
115
+ options.each do |option|
116
+ option_name = option.pair.name.gsub(':', '')
117
+ option_text = option.pair.text
118
+ option_type = option.pair.type
119
+ @parser.opt(option_name.to_sym, "(Ruby class: #{option_type}) " + option_text.to_s, type: CmdParser.parse_type(option_type))
120
+ end
121
+ else
122
+ @parser.opt(tag_name.to_sym, "(Ruby class: #{tag_type}) " + tag_text.to_s, type: CmdParser.parse_type(tag_type))
123
+ end
124
+ else
125
+ @parser.opt(tag_name.to_sym, "(Ruby class: #{tag_type}) " + tag_text.to_s, type: CmdParser.parse_type(tag_type))
126
+ end
127
+ end
128
+ end
129
+
130
+ @global_opts = Trollop::with_standard_exception_handling(@parser) do
131
+ begin
132
+ @parser.parse ARGV
133
+ rescue Trollop::CommandlineError => e
134
+ raise "You must provide one of available actions: #{sub_commands.join ', '}" unless sub_commands.include?(ARGV[0])
135
+ raise e
136
+ end
137
+ end
138
+
139
+ if @init_method
140
+ given_attrs = @global_opts.keys.select { |k| k.to_s.include? '_given' }.map { |k| k.to_s.gsub('_given', '').to_sym }
141
+ @init_method.cmd_opts = @global_opts.select { |k, v| given_attrs.include? k }
142
+ end
143
+ end
144
+
145
+
146
+ def parse_method(method)
147
+ ARGV.shift
148
+ @method = ParsedMethod.new method
149
+ same_methods = @method.param_tags_names & @method.option_tags_names
150
+ raise "You have the same name for @param and @option attribute(s): #{same_methods.join(', ')}.
151
+ Use different names to `console_runner` be able to run #{@method.name} method." if same_methods.count > 0
152
+ method_params_tags = @method.param_tags
153
+
154
+ method_params_tags.each do |tag|
155
+ tag_name = tag.name
156
+ tag_text = tag.text
157
+ tag_type = tag.type
158
+ if tag_type == "Hash"
159
+ options = @method.option_tags.select { |t| t.name == tag.name }
160
+ if options.count > 0
161
+ options.each do |option|
162
+ option_name = option.pair.name.gsub(':', '')
163
+ option_text = option.pair.text
164
+ option_type = option.pair.type
165
+ @parser.opt(option_name.to_sym, "(Ruby class: #{option_type}) " + option_text.to_s, type: CmdParser.parse_type(option_type))
166
+ end
167
+ else
168
+ @parser.opt(tag_name.to_sym, "(Ruby class: #{tag_type}) " + tag_text.to_s, type: CmdParser.parse_type(tag_type))
169
+ end
170
+ else
171
+ @parser.opt(tag_name.to_sym, "(Ruby class: #{tag_type}) " + tag_text.to_s, type: CmdParser.parse_type(tag_type))
172
+ end
173
+ end
174
+ cmd_opts = Trollop::with_standard_exception_handling @parser do
175
+ unless method_params_tags.count.zero?
176
+ raise Trollop::HelpNeeded if ARGV.empty?
177
+ end
178
+ # show help screen
179
+ @parser.parse ARGV
180
+ end
181
+ given_attrs = cmd_opts.keys.select { |k| k.to_s.include? '_given' }.map { |k| k.to_s.gsub('_given', '').to_sym }
182
+ @method.cmd_opts = cmd_opts.select { |k, v| given_attrs.include? k }
183
+ @method.default_params.each do |k, v|
184
+ @method.cmd_opts[k.to_sym] ||= v
185
+ end
186
+
187
+ method_params_tags.select { |t| t.tag_name == 'param' }.map(&:name).each do |required_param|
188
+ next if @method.options_group? required_param
189
+ unless @method.cmd_opts[required_param.to_sym]
190
+ raise "You must specify required parameter: #{required_param}"
191
+ end
192
+ end
193
+ end
194
+
195
+ def self.parse_type(yard_type)
196
+ case yard_type
197
+ when 'String'
198
+ :string
199
+ when 'Integer'
200
+ :int
201
+ when 'Fixnum'
202
+ :int
203
+ when 'Float'
204
+ :float
205
+ when 'Boolean'
206
+ :boolean
207
+ when 'Array(String)'
208
+ :strings
209
+ when 'Array(Integer)'
210
+ :ints
211
+ when 'Array(Fixnum)'
212
+ :ints
213
+ when 'Array(Float)'
214
+ :floats
215
+ when 'Array(Boolean)'
216
+ :booleans
217
+ else
218
+ raise "Unsupported YARD type: #{yard_type}"
219
+ end
220
+ end
221
+
222
+ end
223
+
@@ -0,0 +1,79 @@
1
+ module ConsoleRunner
2
+
3
+ require 'file_parser'
4
+ require 'cmd_parser'
5
+ require 'runner'
6
+
7
+ file_from_arg = ARGV.shift
8
+ raise ConsoleRunnerError, 'Specify file to be executed' unless file_from_arg
9
+ file_path ||= File.realpath file_from_arg
10
+ raise ConsoleRunnerError, "File doesn't exist: #{file_path}" unless File.exist? file_path
11
+ file_parser = FileParser.new(file_path)
12
+
13
+
14
+ runnable_classes = file_parser.list_classes(:runnable)
15
+ if runnable_classes.count != 1
16
+ raise ConsoleRunnerError, "One runnable Class should be specified in file.
17
+ Runnable class should be marked with @#{FileParser::RUNNABLE_TAG} tag"
18
+ end
19
+
20
+ clazz = runnable_classes.first
21
+ all_methods = file_parser.list_methods(:all, clazz)
22
+ runnable_methods = file_parser.list_methods(:runnable, clazz)
23
+ initialize_method = all_methods.find { |m| m.name == :initialize }
24
+ run_method = all_methods.find { |m| m.name == :run }
25
+
26
+
27
+ cmd = ARGV[0]
28
+ action_method = runnable_methods.find { |m| m.name.to_s == cmd } # get sub-command
29
+ action_method ||= run_method
30
+ cmd_parser = CmdParser.new(runnable_methods, initialize_method)
31
+ raise ConsoleRunnerError, "Cannot run! You haven't specify any method to run." unless action_method
32
+ cmd_parser.parse_method action_method
33
+
34
+
35
+ puts '======================================================='
36
+ puts 'Global options:'
37
+ puts cmd_parser.global_opts.map { |k, v| " #{k} = #{v}" }.join("\n")
38
+ if initialize_method
39
+ puts "INIT: #{initialize_method.name}"
40
+ puts 'INIT options:'
41
+ puts cmd_parser.init_method.cmd_opts.map { |k, v| " #{k} = #{v}" }.join("\n")
42
+ end
43
+ puts "Subcommand: #{action_method.name}"
44
+ puts 'Subcommand options:'
45
+ puts cmd_parser.method.cmd_opts.map { |k, v| " #{k} = #{v}" }.join("\n")
46
+ puts "Remaining arguments: #{ARGV.inspect}" if ARGV != []
47
+ puts '======================================================='
48
+
49
+
50
+ Runner.run {
51
+ require file_path
52
+ class_full_name = clazz.title
53
+ raise ConsoleRunnerError, "#{class_full_name} is not defined" unless Module.const_defined?(class_full_name)
54
+ klass_obj = Module.const_get(class_full_name)
55
+ method_type = action_method.scope
56
+ method_params = cmd_parser.method.params_array
57
+
58
+ case method_type
59
+ when :class
60
+ klass_obj.send(action_method.name, *method_params)
61
+ when :instance
62
+ init_params = cmd_parser.init_method.params_array
63
+ # TODO catch errors
64
+ obj = klass_obj.new(*init_params)
65
+ obj.send(action_method.name, *method_params)
66
+ else
67
+ raise ConsoleRunnerError, "Unknown method type: #{method_type}"
68
+ end
69
+
70
+ }
71
+
72
+
73
+ # raise ConsoleRunnerError, "#{clazz.name}#initialize method should be specified" unless initialize_method
74
+ #
75
+ # raise ConsoleRunnerError, "At least one method should be marked with @#{FileParser::RUNNABLE_TAG.to_s} tag.
76
+ # Also you may specify #run method and it will be executed by default.
77
+ # #run method don't need any code annotations as well." if runnable_methods.count == 0 unless run_method
78
+
79
+ end
@@ -0,0 +1,3 @@
1
+ module ConsoleRunner
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1 @@
1
+ class ConsoleRunnerError < Exception; end
@@ -0,0 +1,88 @@
1
+ require 'yard'
2
+ require 'console_runner/version'
3
+ require 'console_runner_error'
4
+
5
+ # Parses code in a file
6
+ class FileParser
7
+ attr_reader :all_objects
8
+
9
+ RUNNABLE_TAG = :runnable
10
+
11
+ # Parse file with #YARD::CLI::Stats
12
+ #
13
+ # @param [String] file_path path to the file to be parsed,
14
+ # @return[Array]
15
+ def initialize(file_path)
16
+ raise ConsoleRunnerError "Cannot find file #{file_path}" unless File.exist?(file_path)
17
+ code = YARD::CLI::Stats.new
18
+ code.run(file_path)
19
+ @all_objects = code.all_objects
20
+ end
21
+
22
+
23
+ # List methods
24
+ # @param [Symbol] scope :all - list all methods, :runnable - list only runnable methods
25
+ # @param [YARD::CodeObjects::ClassObject, nil] clazz list methods of specified class only
26
+ def list_methods(scope= :all, clazz = nil)
27
+ all_methods = @all_objects.select { |o| o.type == :method }
28
+ all_class_methods = []
29
+ all_class_methods = clazz.children.select { |m| m.class == YARD::CodeObjects::MethodObject } if clazz
30
+
31
+ case scope
32
+ when :all
33
+ if clazz
34
+ all_class_methods
35
+ else
36
+ all_methods
37
+ end
38
+ when RUNNABLE_TAG
39
+ if clazz
40
+ all_class_methods.select { |m| m.has_tag? RUNNABLE_TAG }
41
+ else
42
+ all_methods.select { |m| m.has_tag? RUNNABLE_TAG }
43
+ end
44
+ else
45
+ raise ":key can be :all or #{RUNNABLE_TAG}"
46
+ end
47
+ end
48
+
49
+ # List classes
50
+ # @param [Symbol] scope :all - list all classes, :runnable - list only runnable classes
51
+ def list_classes(scope= :all)
52
+ all_classes = @all_objects.select { |o| o.type == :class }
53
+ case scope
54
+ when :all
55
+ all_classes
56
+ when RUNNABLE_TAG
57
+ all_classes.select { |m| m.has_tag? RUNNABLE_TAG }
58
+ else
59
+ raise ':key can be :all or :runnable'
60
+ end
61
+ end
62
+
63
+ def self.select_runnable_tags(yard_object)
64
+ yard_object.tags.select { |t| t.tag_name == RUNNABLE_TAG.to_s }
65
+ end
66
+
67
+ def self.select_option_tags(yard_object)
68
+ yard_object.tags.select { |t| t.tag_name == 'option' }
69
+ end
70
+
71
+ def self.select_param_tags(yard_object)
72
+ yard_object.tags.select { |t| t.tag_name == 'param' }
73
+ end
74
+
75
+ end
76
+
77
+ # YARD::Tags::Library.define_tag "Run in Console", :runnable, :with_types_and_name
78
+ YARD::Tags::Library.define_tag 'Console Tool Description', FileParser::RUNNABLE_TAG
79
+
80
+ module YARD
81
+ module CLI
82
+ class Stats < Yardoc
83
+ def print_statistics; end
84
+
85
+ def print_undocumented_objects; end
86
+ end
87
+ end
88
+ end
data/lib/runner.rb ADDED
@@ -0,0 +1,21 @@
1
+ module Runner
2
+
3
+ def self.run &block
4
+ start_time = Time.now
5
+ puts "Start Time: #{start_time}"
6
+ Thread.current[:id] = 'main'
7
+
8
+ yield
9
+
10
+ trap 'SIGCHLD' do
11
+ loop do
12
+ pid = Process.waitpid(-1, Process::WNOHANG) rescue nil
13
+ break unless pid
14
+ end
15
+ end
16
+
17
+ finish_time = Time.now
18
+ puts "Finish Time: #{finish_time} (Duration: #{((finish_time - start_time) / 60).round(2) } minutes)"
19
+ end
20
+
21
+ end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: console_runner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Yury Karpovich
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-04-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: coveralls
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.8'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.8'
97
+ - !ruby/object:Gem::Dependency
98
+ name: trollop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.1'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: yard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.9'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.9'
125
+ - !ruby/object:Gem::Dependency
126
+ name: colorize
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.8'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.8'
139
+ description: This gem provides you an ability to run any Ruby method from command-line
140
+ (no any code modifications required!!!)
141
+ email:
142
+ - spoonest@gmail.com
143
+ - yuri.karpovich@gmail.com
144
+ executables:
145
+ - c_run
146
+ extensions: []
147
+ extra_rdoc_files: []
148
+ files:
149
+ - ".coveralls.yml"
150
+ - ".gitignore"
151
+ - ".travis.yml"
152
+ - Gemfile
153
+ - LICENSE.txt
154
+ - README.md
155
+ - Rakefile
156
+ - bin/console
157
+ - bin/setup
158
+ - console_runner.gemspec
159
+ - exe/c_run
160
+ - exe/c_run.rb
161
+ - lib/cmd_parser.rb
162
+ - lib/console_runner.rb
163
+ - lib/console_runner/version.rb
164
+ - lib/console_runner_error.rb
165
+ - lib/file_parser.rb
166
+ - lib/runner.rb
167
+ homepage: https://github.com/yuri-karpovich/console_runner
168
+ licenses:
169
+ - MIT
170
+ metadata:
171
+ allowed_push_host: https://rubygems.org
172
+ post_install_message:
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ requirements: []
187
+ rubyforge_project:
188
+ rubygems_version: 2.4.5.1
189
+ signing_key:
190
+ specification_version: 4
191
+ summary: Command-line runner for ruby code.
192
+ test_files: []