ecic 0.0.1 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a76ed0b791619e00df7b26769de0149cd2c50bf7
4
- data.tar.gz: 32bdd099afd3603acb07f92e3d65059693b4308c
2
+ SHA256:
3
+ metadata.gz: 2941906c52685bf8cdd8dd3c988cb33d954917ce1af810b636a6d05a4a7858c9
4
+ data.tar.gz: e09506b75b7baaeb904179df7fa2eeb529d71e6084c1d9e150145b40d8ec1f2c
5
5
  SHA512:
6
- metadata.gz: 00fb2b177b7d849519218ad947caad8885ee6024beed10ea01945bb9aeac43557c3faf3205a7f3012a873a6910ddf3cd7b59b24887e15f5d93d626d20f06a4c3
7
- data.tar.gz: 6b9e3d628bb5982c30cabc505be385a80a4bf2fd3ba0e47d4f597c170ce75fc098afe88f340d8378d514dc7e509e158835e63cb3811dfd0f671b065adf07903f
6
+ metadata.gz: a6cf0330473f92ece3ae09d5448255502e354fce068eba417c9eb8e0c1dc79a1c21791bca6e440cce409f5f58faf2ac9fe1558aa69ba30d4fa742ae4d493487e
7
+ data.tar.gz: 7403f3d664272bd3bf5a25a6bbba9c534f212a9425f360f5c3f7531d3787452b7c6c2391e45aff9a908ed417a6ff6492dbe8f3315d1cd75ed66e710a4bc8dfb5
@@ -0,0 +1,7 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
+
6
+ ## [0.1.0]
7
+ - Initial release.
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in ecic.gemspec
3
+ # Specify your gem dependencies in ecic.gemspec
4
4
  gemspec
5
5
 
6
- gem 'thor'
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
@@ -1,37 +1,64 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ecic (0.1.4)
4
+ ecic (0.1.0)
5
+ activesupport
6
+ colorize
7
+ rake
8
+ thor
5
9
 
6
10
  GEM
7
11
  remote: https://rubygems.org/
8
12
  specs:
13
+ activesupport (5.1.4)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (~> 0.7)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ byebug (10.0.0)
19
+ codeclimate-test-reporter (1.0.8)
20
+ simplecov (<= 0.13)
21
+ colorize (0.8.1)
22
+ concurrent-ruby (1.0.5)
9
23
  diff-lcs (1.3)
10
- rake (10.5.0)
11
- rspec (3.8.0)
12
- rspec-core (~> 3.8.0)
13
- rspec-expectations (~> 3.8.0)
14
- rspec-mocks (~> 3.8.0)
15
- rspec-core (3.8.0)
16
- rspec-support (~> 3.8.0)
17
- rspec-expectations (3.8.1)
24
+ docile (1.1.5)
25
+ i18n (0.9.4)
26
+ concurrent-ruby (~> 1.0)
27
+ json (2.1.0)
28
+ minitest (5.11.3)
29
+ rake (12.3.0)
30
+ rspec (3.7.0)
31
+ rspec-core (~> 3.7.0)
32
+ rspec-expectations (~> 3.7.0)
33
+ rspec-mocks (~> 3.7.0)
34
+ rspec-core (3.7.1)
35
+ rspec-support (~> 3.7.0)
36
+ rspec-expectations (3.7.0)
18
37
  diff-lcs (>= 1.2.0, < 2.0)
19
- rspec-support (~> 3.8.0)
20
- rspec-mocks (3.8.0)
38
+ rspec-support (~> 3.7.0)
39
+ rspec-mocks (3.7.0)
21
40
  diff-lcs (>= 1.2.0, < 2.0)
22
- rspec-support (~> 3.8.0)
23
- rspec-support (3.8.0)
41
+ rspec-support (~> 3.7.0)
42
+ rspec-support (3.7.1)
43
+ simplecov (0.13.0)
44
+ docile (~> 1.1.0)
45
+ json (>= 1.8, < 3)
46
+ simplecov-html (~> 0.10.0)
47
+ simplecov-html (0.10.2)
24
48
  thor (0.20.0)
49
+ thread_safe (0.3.6)
50
+ tzinfo (1.2.5)
51
+ thread_safe (~> 0.1)
25
52
 
26
53
  PLATFORMS
27
54
  ruby
28
55
 
29
56
  DEPENDENCIES
30
- bundler (~> 1.13)
57
+ bundler
58
+ byebug
59
+ codeclimate-test-reporter
31
60
  ecic!
32
- rake (~> 10.0)
33
- rspec (~> 3.0)
34
- thor
61
+ rspec
35
62
 
36
63
  BUNDLED WITH
37
- 1.13.5
64
+ 1.16.1
@@ -0,0 +1,19 @@
1
+ guard "bundler", cmd: "bundle" do
2
+ watch("Gemfile")
3
+ watch(/^.+\.gemspec/)
4
+ end
5
+
6
+ guard :rspec, cmd: "bundle exec rspec" do
7
+ require "guard/rspec/dsl"
8
+ dsl = Guard::RSpec::Dsl.new(self)
9
+
10
+ # RSpec files
11
+ rspec = dsl.rspec
12
+ watch(rspec.spec_helper) { rspec.spec_dir }
13
+ watch(rspec.spec_support) { rspec.spec_dir }
14
+ watch(rspec.spec_files)
15
+
16
+ # Ruby files
17
+ ruby = dsl.ruby
18
+ dsl.watch_spec_files_for(ruby.lib_files)
19
+ end
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Easy IC : open-source, cross-platform framework for developing digital ASIC and FPGA designs
1
+ # Easy IC
2
2
 
3
3
  ## NOTE: this project has just been started. Hence, the description below is what will come in the future, but none of the features have been implemented yet.
4
4
 
@@ -183,4 +183,12 @@ To install the ECIC framework onto your local machine, run `bundle exec rake ins
183
183
  -->
184
184
  ## Contributing
185
185
 
186
+ 1. Fork it
187
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
188
+ 3. Commit your changes (`git commit -am "Add some feature"`)
189
+ 4. Push to the branch (`git push origin my-new-feature`)
190
+ 5. Create new Pull Request
191
+
186
192
  Bug reports and pull requests are welcome on GitHub at https://github.com/ic-factory/ecic.
193
+
194
+
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
3
 
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
4
  task :default => :spec
5
+
6
+ RSpec::Core::RakeTask.new
@@ -13,14 +13,18 @@ Gem::Specification.new do |spec|
13
13
  spec.description = %q{This gem allows you to easily create a new ASIC/FPGA project with a file structure and support tools that ensures consistency between your projects and gets you up to speed in no time. To create a new project simply type 'ecic new PATH'.}
14
14
  spec.homepage = "https://github.com/ic-factory/ecic"
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
- f.match(%r{^(test|spec|features)/})
18
- end
16
+ spec.files = `git ls-files`.split($/)
19
17
  spec.bindir = "exe"
20
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
20
  spec.require_paths = ["lib"]
22
21
 
23
- spec.add_development_dependency "bundler", "~> 1.13"
24
- spec.add_development_dependency "rake", "~> 10.0"
25
- spec.add_development_dependency "rspec", "~> 3.0"
22
+ spec.add_dependency "thor"
23
+ spec.add_dependency "colorize"
24
+ spec.add_dependency "rake"
25
+ spec.add_dependency "activesupport"
26
+
27
+ spec.add_development_dependency "bundler"
28
+ spec.add_development_dependency "byebug"
29
+ spec.add_development_dependency "rspec"
26
30
  end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Trap ^C
4
+ Signal.trap("INT") {
5
+ puts "\nCtrl-C detected. Exiting..."
6
+ sleep 1
7
+ exit
8
+ }
9
+
10
+ $:.unshift(File.expand_path("../../lib", __FILE__))
11
+ require "ecic"
12
+ require "ecic/cli"
13
+
14
+ Ecic::CLI.start(ARGV)
@@ -13,99 +13,14 @@
13
13
  # If the user tries to call the 'generate' command outside a project,
14
14
  # an error message must be returned stating that this command can only be called from within a project.
15
15
 
16
+ $:.unshift(File.expand_path("../", __FILE__))
16
17
  require "ecic/version"
17
18
 
18
19
  module Ecic
19
- require 'yaml'
20
- require 'thor'
21
- require 'thor/group'
22
- require "ecic/project_generator"
23
- require "ecic/library_generator"
24
-
25
- def self.help_text
26
- YAML.load(File.read(File.expand_path("../../config/locales/help.en.yaml", __FILE__)))['help']
27
- end
28
-
29
- #TBA: Make a function that returns the root folder for the project
30
- def self.root
31
- File.expand_path("./tfj2")
32
- end
33
-
34
- class Generate < Thor
35
- #--------------------------------------------------------------------------
36
- # TESTBENCH generator:
37
- #--------------------------------------------------------------------------
38
- class_option :verbose, :type => :boolean
39
-
40
- desc "testbench NAME", Ecic::help_text['generators']['testbench']['short']
41
- long_desc Ecic::help_text['generators']['testbench']['long']
42
- option :type, :banner => 'vhdl|sv|uvm', :required => true, :desc => 'Speficy the testbench type (VHDL, SystemVerilog or UVM)'
43
- option :just_print, :type => :boolean, :aliases => '-n', :desc => "Don't actually run any commands; just print them."
44
- def testbench(name)
45
- puts "Implement a generator for creating a new testbench"
46
- end
47
-
48
- desc "library NAME...", Ecic::help_text['generators']['library']['short']
49
- long_desc Ecic::help_text['generators']['library']['long']
50
- option :just_print, :type => :boolean, :aliases => '-n', :desc => "Don't actually run any commands; just print them."
51
- # def library(names)
52
- def library(lib_name)
53
- generator = LibraryGenerator.new
54
- generator.destination_root = Ecic::root
55
- # names.each do |lib_name|
56
- generator.library_name = lib_name
57
- generator.invoke_all
58
- # end
59
- end
60
-
61
- end
62
-
63
- class Cli < Thor
64
-
65
- check_unknown_options!
66
-
67
- #Make sure to return non-zero value if an error is thrown.
68
- def self.exit_on_failure?
69
- true
70
- end
71
-
72
- class << self
73
- def help(shell, subcommand = false)
74
- shell.say "Usage: ecic COMMAND [ARGS]"
75
- shell.say ""
76
- super
77
- shell.say "To get more help on a specific command, try 'ecic help [COMMAND]'"
78
- end
79
- end
80
-
81
- #--------------------------------------------------------------------------
82
- # VERSION command:
83
- #--------------------------------------------------------------------------
84
- desc 'version', 'Display version'
85
- map %w[-v --version] => :version
86
- def version
87
- say "#{VERSION}"
88
- end
89
-
90
- #--------------------------------------------------------------------------
91
- # NEW command:
92
- #--------------------------------------------------------------------------
93
- long_desc Ecic::help_text['new']['long']
94
- desc "new PATH", Ecic::help_text['new']['short']
95
- option :verbose, :type => :boolean
96
- def new(path)
97
- path = File.expand_path(path)
98
- puts "Generating a new project in #{path}"
99
- generator = ProjectGenerator.new
100
- generator.destination_root = path
101
- generator.invoke_all
102
- #TBA: invoke installation by eg. calling 'bundler install' from within the generate project folder
103
-
104
- end
105
-
106
- desc "generate SUBCOMMAND ...ARGS", Ecic::help_text['generate']['short']
107
- subcommand "generate", Generate
108
-
109
- end
110
-
20
+ autoload :Help, "ecic/help"
21
+ autoload :Command, "ecic/command"
22
+ autoload :CLI, "ecic/cli"
23
+ autoload :Generate, "ecic/generate"
24
+ autoload :Completion, "ecic/completion"
25
+ autoload :Completer, "ecic/completer"
111
26
  end
@@ -0,0 +1,69 @@
1
+ module Ecic
2
+ class CLI < Command
3
+
4
+ class << self
5
+ def help(shell, subcommand = false)
6
+ shell.say "Usage: ecic COMMAND [ARGS]"
7
+ shell.say ""
8
+ super
9
+ shell.say "To get more help on a specific command, try 'ecic help [COMMAND]'"
10
+ end
11
+ end
12
+
13
+ check_unknown_options!
14
+
15
+ #Make sure to return non-zero value if an error is thrown.
16
+ def self.exit_on_failure?
17
+ true
18
+ end
19
+
20
+ #TBA: Make a function that returns the root folder for the project
21
+ def self.root
22
+ File.expand_path("./tfj2")
23
+ end
24
+
25
+ # class_option :verbose, type: :boolean
26
+ # class_option :noop, type: :boolean
27
+
28
+ #--------------------------------------------------------------------------
29
+ # NEW command:
30
+ #--------------------------------------------------------------------------
31
+ long_desc Help.text(:new)
32
+ desc "new PATH", Help.short_text(:new)
33
+ option :verbose, :type => :boolean
34
+ def new(path)
35
+ path = File.expand_path(path)
36
+ puts "Generating a new project in #{path}"
37
+ generator = ProjectGenerator.new
38
+ generator.destination_root = path
39
+ generator.invoke_all
40
+ #TBA: invoke installation by eg. calling 'bundler install' from within the generate project folder
41
+ end
42
+
43
+ desc "generate SUBCOMMAND ...ARGS", "sub subcommands"
44
+ long_desc Help.text(:generate)
45
+ subcommand "generate", Generate
46
+
47
+ desc "completion *PARAMS", "Print words for auto-completion"
48
+ long_desc Help.text("completion")
49
+ def completion(*params)
50
+ Completer.new(CLI, *params).run
51
+ end
52
+
53
+ desc "completion_script", "Generate script that can be eval to setup auto-completion", hide: true
54
+ long_desc Help.text("completion_script")
55
+ def completion_script
56
+ Completer::Script.generate
57
+ end
58
+
59
+ desc 'version', 'Display version'
60
+ map %w[-v --version] => :version
61
+ def version
62
+ say "#{VERSION}"
63
+ end
64
+ end
65
+ end
66
+
67
+
68
+
69
+
@@ -0,0 +1,47 @@
1
+ require "thor"
2
+
3
+ # Override thor's long_desc identation behavior
4
+ # https://github.com/erikhuda/thor/issues/398
5
+ class Thor
6
+ module Shell
7
+ class Basic
8
+ def print_wrapped(message, options = {})
9
+ message = "\n#{message}" unless message[0] == "\n"
10
+ stdout.puts message
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ module Ecic
17
+ class Command < Thor
18
+ class << self
19
+ def dispatch(m, args, options, config)
20
+ # Allow calling for help via:
21
+ # ecic command help
22
+ # ecic command -h
23
+ # ecic command --help
24
+ # ecic command -D
25
+ #
26
+ # as well thor's normal way:
27
+ #
28
+ # ecic help command
29
+ help_flags = Thor::HELP_MAPPINGS + ["help"]
30
+ if args.length > 1 && !(args & help_flags).empty?
31
+ args -= help_flags
32
+ args.insert(-2, "help")
33
+ end
34
+
35
+ # ecic version
36
+ # ecic --version
37
+ # ecic -v
38
+ version_flags = ["--version", "-v"]
39
+ if args.length == 1 && !(args & version_flags).empty?
40
+ args = ["version"]
41
+ end
42
+
43
+ super
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,161 @@
1
+ =begin
2
+ Code Explanation:
3
+
4
+ There are 3 types of things to auto-complete:
5
+
6
+ 1. command: the command itself
7
+ 2. parameters: command parameters.
8
+ 3. options: command options
9
+
10
+ Here's an example:
11
+
12
+ mycli hello name --from me
13
+
14
+ * command: hello
15
+ * parameters: name
16
+ * option: --from
17
+
18
+ When command parameters are done processing, the remaining completion words will be options. We can tell that the command params are completed based on the method arity.
19
+
20
+ ## Arity
21
+
22
+ For example, say you had a method for a CLI command with the following form:
23
+
24
+ ufo scale service count --cluster development
25
+
26
+ It's equivalent ruby method:
27
+
28
+ scale(service, count) = has an arity of 2
29
+
30
+ So typing:
31
+
32
+ ufo scale service count [TAB] # there are 3 parameters including the "scale" command according to Thor's CLI processing.
33
+
34
+ So the completion should only show options, something like this:
35
+
36
+ --noop --verbose --cluster
37
+
38
+ ## Splat Arguments
39
+
40
+ When the ruby method has a splat argument, it's arity is negative. Here are some example methods and their arities.
41
+
42
+ ship(service) = 1
43
+ scale(service, count) = 2
44
+ ships(*services) = -1
45
+ foo(example, *rest) = -2
46
+
47
+ Fortunately, negative and positive arity values are processed the same way. So we take simply take the absolute value of the arity and process it the same.
48
+
49
+ Here are some test cases, hit TAB after typing the command:
50
+
51
+ ecic completion
52
+ ecic completion hello
53
+ ecic completion hello name
54
+ ecic completion hello name --
55
+ ecic completion hello name --noop
56
+
57
+ ecic completion
58
+ ecic completion sub:goodbye
59
+ ecic completion sub:goodbye name
60
+
61
+ ## Subcommands and Thor::Group Registered Commands
62
+
63
+ Sometimes the commands are not simple thor commands but are subcommands or Thor::Group commands. A good specific example is the ufo tool.
64
+
65
+ * regular command: ufo ship
66
+ * subcommand: ufo docker
67
+ * Thor::Group command: ufo init
68
+
69
+ Auto-completion accounts for each of these type of commands.
70
+ =end
71
+ module Ufo
72
+ class Completer
73
+ autoload :Script, 'ecic/completer/script'
74
+
75
+ def initialize(command_class, *params)
76
+ @params = params
77
+ @current_command = @params[0]
78
+ @command_class = command_class # CLI initiall
79
+ end
80
+
81
+ def run
82
+ if subcommand?(@current_command)
83
+ subcommand_class = @command_class.subcommand_classes[@current_command]
84
+ @params.shift # destructive
85
+ Completer.new(subcommand_class, *@params).run # recursively use subcommand
86
+ return
87
+ end
88
+
89
+ # full command has been found!
90
+ unless found?(@current_command)
91
+ puts all_commands
92
+ return
93
+ end
94
+
95
+ # will only get to here if command aws found (above)
96
+ arity = @command_class.instance_method(@current_command).arity.abs
97
+ if @params.size > arity or thor_group_command?
98
+ puts options_completion
99
+ else
100
+ puts params_completion
101
+ end
102
+ end
103
+
104
+ def subcommand?(command)
105
+ @command_class.subcommands.include?(command)
106
+ end
107
+
108
+ # hacky way to detect that command is a registered Thor::Group command
109
+ def thor_group_command?
110
+ command_params(raw=true) == [[:rest, :args]]
111
+ end
112
+
113
+ def found?(command)
114
+ public_methods = @command_class.public_instance_methods(false)
115
+ command && public_methods.include?(command.to_sym)
116
+ end
117
+
118
+ # all top-level commands
119
+ def all_commands
120
+ commands = @command_class.all_commands.reject do |k,v|
121
+ v.is_a?(Thor::HiddenCommand)
122
+ end
123
+ commands.keys
124
+ end
125
+
126
+ def command_params(raw=false)
127
+ params = @command_class.instance_method(@current_command).parameters
128
+ # Example:
129
+ # >> Sub.instance_method(:goodbye).parameters
130
+ # => [[:req, :name]]
131
+ # >>
132
+ raw ? params : params.map!(&:last)
133
+ end
134
+
135
+ def params_completion
136
+ offset = @params.size - 1
137
+ offset_params = command_params[offset..-1]
138
+ command_params[offset..-1].first
139
+ end
140
+
141
+ def options_completion
142
+ used = ARGV.select { |a| a.include?('--') } # so we can remove used options
143
+
144
+ method_options = @command_class.all_commands[@current_command].options.keys
145
+ class_options = @command_class.class_options.keys
146
+
147
+ all_options = method_options + class_options + ['help']
148
+
149
+ all_options.map! { |o| "--#{o.to_s.gsub('_','-')}" }
150
+ filtered_options = all_options - used
151
+ filtered_options.uniq
152
+ end
153
+
154
+ # Useful for debugging. Using puts messes up completion.
155
+ def log(msg)
156
+ File.open("/tmp/complete.log", "a") do |file|
157
+ file.puts(msg)
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,6 @@
1
+ class Ecic::Completer::Script
2
+ def self.generate
3
+ bash_script = File.expand_path("script.sh", File.dirname(__FILE__))
4
+ puts "source #{bash_script}"
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ _ecic() {
2
+ COMPREPLY=()
3
+ local word="${COMP_WORDS[COMP_CWORD]}"
4
+ local words=("${COMP_WORDS[@]}")
5
+ unset words[0]
6
+ local completion=$(ecic completion ${words[@]})
7
+ COMPREPLY=( $(compgen -W "$completion" -- "$word") )
8
+ }
9
+
10
+ complete -F _ecic ecic
@@ -0,0 +1,15 @@
1
+ module Ecic
2
+ class Completion < Command
3
+ desc "script", "generates script that can be eval to setup auto-completion"
4
+ long_desc Help.text("completion:script")
5
+ def script
6
+ Completer::Script.generate
7
+ end
8
+
9
+ desc "completions *PARAMS", "prints words for auto-completion"
10
+ long_desc Help.text("completion:list")
11
+ def list(*params)
12
+ Completer.new(*params).run
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ module Ecic
2
+ class Generate < Command
3
+
4
+ #--------------------------------------------------------------------------
5
+ # TESTBENCH generator:
6
+ #--------------------------------------------------------------------------
7
+ class_option :verbose, :type => :boolean
8
+
9
+ desc "testbench NAME", Help.short_text("generate:testbench")
10
+ long_desc Help.text("generate:testbench")
11
+ option :type, :banner => 'vhdl|sv|uvm', :required => true, :desc => 'Speficy the testbench type (VHDL, SystemVerilog or UVM)'
12
+ option :just_print, :type => :boolean, :aliases => '-n', :desc => "Don't actually run any commands; just print them."
13
+ def testbench(name)
14
+ puts "Implement a generator for creating a new testbench"
15
+ end
16
+
17
+ desc "library NAME...", Help.short_text("generate:library")
18
+ long_desc Help.text("generate:library")
19
+ option :just_print, :type => :boolean, :aliases => '-n', :desc => "Don't actually run any commands; just print them."
20
+ # def library(names)
21
+ def library(lib_name)
22
+ generator = LibraryGenerator.new
23
+ generator.destination_root = Ecic::root
24
+ # names.each do |lib_name|
25
+ generator.library_name = lib_name
26
+ generator.invoke_all
27
+ # end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ module Ecic::Help
2
+ class << self
3
+ def text(namespaced_command)
4
+ path = namespaced_command.to_s.gsub(':','/')
5
+ path = File.expand_path("../help/#{path}.md", __FILE__)
6
+ IO.read(path) if File.exist?(path)
7
+ end
8
+ def short_text(namespaced_command)
9
+ path = namespaced_command.to_s.gsub(':','/')
10
+ path = File.expand_path("../help/#{path}_short.md", __FILE__)
11
+ IO.read(path) if File.exist?(path)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ Example:
2
+
3
+ ecic completion
4
+
5
+ Prints words for TAB auto-completion.
6
+
7
+ Examples:
8
+
9
+ ecic completion
10
+ ecic completion hello
11
+ ecic completion hello name
12
+
13
+ To enable TAB auto-completion, add the following to your profile:
14
+
15
+ eval $(ecic completion script)
16
+
17
+ Auto-completion example usage:
18
+
19
+ ecic [TAB]
20
+ ecic generate [TAB]
21
+ ecic generate design [TAB]
22
+ ecic generate design --[TAB]
@@ -0,0 +1,3 @@
1
+ To use, add the following to your ~/.bashrc or ~/.profile
2
+
3
+ eval $(ecic completion script)
@@ -0,0 +1,4 @@
1
+ Examples:
2
+
3
+ ecic generate library
4
+ ecic generate library NAME
@@ -0,0 +1 @@
1
+ Generate new library
@@ -0,0 +1,4 @@
1
+ Examples:
2
+
3
+ ecic generate testbench
4
+ ecic generate testbench NAME
@@ -0,0 +1 @@
1
+ Generate new testbench
@@ -0,0 +1,3 @@
1
+ Examples:
2
+
3
+ ecic new my_project
@@ -0,0 +1 @@
1
+ Create new project
@@ -1,3 +1,3 @@
1
1
  module Ecic
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,38 @@
1
+ require "spec_helper"
2
+
3
+ describe Ecic::CLI do
4
+ before(:all) do
5
+ @args = "--from Tung"
6
+ end
7
+
8
+ describe "ecic" do
9
+ it "hello" do
10
+ out = execute("exe/ecic hello world #{@args}")
11
+ expect(out).to include("from: Tung\nHello world")
12
+ end
13
+
14
+ it "goodbye" do
15
+ out = execute("exe/ecic sub goodbye world #{@args}")
16
+ expect(out).to include("from: Tung\nGoodbye world")
17
+ end
18
+
19
+ commands = {
20
+ "hell" => "hello",
21
+ "hello" => "name",
22
+ "hello -" => "--from",
23
+ "hello name" => "--from",
24
+ "hello name --" => "--from",
25
+ "sub goodb" => "goodbye",
26
+ "sub goodbye" => "name",
27
+ "sub goodbye name" => "--from",
28
+ "sub goodbye name --" => "--from",
29
+ "sub goodbye name --from" => "--help",
30
+ }
31
+ commands.each do |command, expected_word|
32
+ it "completion #{command}" do
33
+ out = execute("exe/ecic completion #{command}")
34
+ expect(out).to include(expected_word) # only checking for one word for simplicity
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ ENV["TEST"] = "1"
2
+
3
+ # CodeClimate test coverage: https://docs.codeclimate.com/docs/configuring-test-coverage
4
+ # require 'simplecov'
5
+ # SimpleCov.start
6
+
7
+ require "pp"
8
+ require "byebug"
9
+ root = File.expand_path("../", File.dirname(__FILE__))
10
+ require "#{root}/lib/ecic"
11
+
12
+ module Helper
13
+ def execute(cmd)
14
+ puts "Running: #{cmd}" if show_command?
15
+ out = `#{cmd}`
16
+ puts out if show_command?
17
+ out
18
+ end
19
+
20
+ # Added SHOW_COMMAND because DEBUG is also used by other libraries like
21
+ # bundler and it shows its internal debugging logging also.
22
+ def show_command?
23
+ ENV['DEBUG'] || ENV['SHOW_COMMAND']
24
+ end
25
+ end
26
+
27
+ RSpec.configure do |c|
28
+ c.include Helper
29
+ end
metadata CHANGED
@@ -1,68 +1,128 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Torben Fox Jacobsen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-02 00:00:00.000000000 Z
11
+ date: 2018-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
13
69
  - !ruby/object:Gem::Dependency
14
70
  name: bundler
15
71
  requirement: !ruby/object:Gem::Requirement
16
72
  requirements:
17
- - - "~>"
73
+ - - ">="
18
74
  - !ruby/object:Gem::Version
19
- version: '1.13'
75
+ version: '0'
20
76
  type: :development
21
77
  prerelease: false
22
78
  version_requirements: !ruby/object:Gem::Requirement
23
79
  requirements:
24
- - - "~>"
80
+ - - ">="
25
81
  - !ruby/object:Gem::Version
26
- version: '1.13'
82
+ version: '0'
27
83
  - !ruby/object:Gem::Dependency
28
- name: rake
84
+ name: byebug
29
85
  requirement: !ruby/object:Gem::Requirement
30
86
  requirements:
31
- - - "~>"
87
+ - - ">="
32
88
  - !ruby/object:Gem::Version
33
- version: '10.0'
89
+ version: '0'
34
90
  type: :development
35
91
  prerelease: false
36
92
  version_requirements: !ruby/object:Gem::Requirement
37
93
  requirements:
38
- - - "~>"
94
+ - - ">="
39
95
  - !ruby/object:Gem::Version
40
- version: '10.0'
96
+ version: '0'
41
97
  - !ruby/object:Gem::Dependency
42
98
  name: rspec
43
99
  requirement: !ruby/object:Gem::Requirement
44
100
  requirements:
45
- - - "~>"
101
+ - - ">="
46
102
  - !ruby/object:Gem::Version
47
- version: '3.0'
103
+ version: '0'
48
104
  type: :development
49
105
  prerelease: false
50
106
  version_requirements: !ruby/object:Gem::Requirement
51
107
  requirements:
52
- - - "~>"
108
+ - - ">="
53
109
  - !ruby/object:Gem::Version
54
- version: '3.0'
110
+ version: '0'
55
111
  description: This gem allows you to easily create a new ASIC/FPGA project with a file
56
112
  structure and support tools that ensures consistency between your projects and gets
57
113
  you up to speed in no time. To create a new project simply type 'ecic new PATH'.
58
114
  email:
59
115
  - ecic@ic-factory.com
60
- executables: []
116
+ executables:
117
+ - ecic
61
118
  extensions: []
62
119
  extra_rdoc_files: []
63
120
  files:
121
+ - CHANGELOG.md
64
122
  - Gemfile
65
123
  - Gemfile.lock
124
+ - Guardfile
125
+ - LICENSE.txt
66
126
  - README.md
67
127
  - Rakefile
68
128
  - bin/console
@@ -71,12 +131,31 @@ files:
71
131
  - config/ecic.yaml
72
132
  - config/locales/help.en.yaml
73
133
  - ecic.gemspec
134
+ - exe/ecic
74
135
  - features_wishlist.md
75
136
  - lib/ecic.rb
137
+ - lib/ecic/cli.rb
138
+ - lib/ecic/command.rb
139
+ - lib/ecic/completer.rb
140
+ - lib/ecic/completer/script.rb
141
+ - lib/ecic/completer/script.sh
142
+ - lib/ecic/completion.rb
143
+ - lib/ecic/generate.rb
144
+ - lib/ecic/help.rb
145
+ - lib/ecic/help/completion.md
146
+ - lib/ecic/help/completion_script.md
147
+ - lib/ecic/help/generate/library.md
148
+ - lib/ecic/help/generate/library_short.md
149
+ - lib/ecic/help/generate/testbench.md
150
+ - lib/ecic/help/generate/testbench_short.md
151
+ - lib/ecic/help/new.md
152
+ - lib/ecic/help/new_short.md
76
153
  - lib/ecic/library_generator.rb
77
154
  - lib/ecic/project_generator.rb
78
155
  - lib/ecic/version.rb
79
156
  - notes.txt
157
+ - spec/lib/cli_spec.rb
158
+ - spec/spec_helper.rb
80
159
  - templates/project/Gemfile
81
160
  - templates/project/config/libraries.rb
82
161
  - templates/project/config/project.rb
@@ -103,9 +182,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
182
  version: '0'
104
183
  requirements: []
105
184
  rubyforge_project:
106
- rubygems_version: 2.6.7
185
+ rubygems_version: 2.7.7
107
186
  signing_key:
108
187
  specification_version: 4
109
188
  summary: 'Easy-IC : provides a framework for ASIC and FPGA projects that favors convention
110
189
  over configuration.'
111
- test_files: []
190
+ test_files:
191
+ - spec/lib/cli_spec.rb
192
+ - spec/spec_helper.rb