cli-kit 3.0.0 → 4.0.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 +5 -5
- data/.github/CODEOWNERS +1 -0
- data/.github/dependabot.yml +10 -0
- data/.github/probots.yml +2 -0
- data/.github/workflows/ruby.yml +32 -0
- data/.rubocop.yml +13 -15
- data/Gemfile +3 -2
- data/Gemfile.lock +35 -30
- data/README.md +102 -4
- data/Rakefile +27 -0
- data/TODO.md +5 -0
- data/bin/console +3 -3
- data/bin/test_gen +31 -0
- data/bin/testunit +2 -2
- data/cli-kit.gemspec +8 -7
- data/dev.yml +1 -1
- data/examples/README.md +21 -0
- data/examples/minimal/example.rb +22 -0
- data/examples/single-file/example.rb +71 -0
- data/examples/todo-list/README.md +1 -0
- data/gen/lib/gen/commands/help.rb +4 -4
- data/gen/lib/gen/generator.rb +12 -10
- data/gen/lib/gen.rb +5 -1
- data/gen/template/Gemfile +6 -0
- data/gen/template/bin/testunit +23 -0
- data/gen/template/bin/update-deps +2 -1
- data/gen/template/lib/__app__/commands/example.rb +0 -1
- data/gen/template/test/example_test.rb +17 -0
- data/gen/template/test/test_helper.rb +22 -0
- data/lib/cli/kit/base_command.rb +14 -8
- data/lib/cli/kit/command_registry.rb +1 -1
- data/lib/cli/kit/config.rb +39 -4
- data/lib/cli/kit/error_handler.rb +56 -36
- data/lib/cli/kit/executor.rb +39 -10
- data/lib/cli/kit/ini.rb +16 -7
- data/lib/cli/kit/logger.rb +82 -0
- data/lib/cli/kit/resolver.rb +2 -2
- data/lib/cli/kit/support/test_helper.rb +244 -0
- data/lib/cli/kit/support.rb +9 -0
- data/lib/cli/kit/system.rb +61 -22
- data/lib/cli/kit/util.rb +189 -0
- data/lib/cli/kit/version.rb +1 -1
- data/lib/cli/kit.rb +4 -1
- metadata +36 -20
- data/.travis.yml +0 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 523252459712e507c4579e244e6330eb3e8a5d8c71334d4e41553903ab651cd6
|
|
4
|
+
data.tar.gz: 459cb0a684e2890718d0cffdd74cd8540bd91a1995dfe1db593df9a189da20d7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8579924711573ce6338b52dc44c47ad40c12f925bbd6f3ad6cee5be9f44b2b4f315e6d272adc309788b0418ee6806567660f0386d7e91d9d09a524beeb0a4a1f
|
|
7
|
+
data.tar.gz: b5507292ba97fd6f13b83b6426e81e4500e0ef1480387164c936164b7593bf7daac98e39cbb835362f198c39e562f2d12adf92384365a9c99a7f0ed42c158a45
|
data/.github/CODEOWNERS
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@Shopify/dev-infra
|
data/.github/probots.yml
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Ruby
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
style:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
steps:
|
|
9
|
+
- uses: actions/checkout@v2
|
|
10
|
+
- name: Set up Ruby
|
|
11
|
+
uses: ruby/setup-ruby@v1
|
|
12
|
+
with:
|
|
13
|
+
ruby-version: '2.7'
|
|
14
|
+
bundler-cache: true
|
|
15
|
+
- name: Check style
|
|
16
|
+
run: bundle exec rake style
|
|
17
|
+
test:
|
|
18
|
+
strategy:
|
|
19
|
+
matrix:
|
|
20
|
+
os: [macos-latest, ubuntu-latest, windows-latest]
|
|
21
|
+
ruby-version: ['2.6', '2.7']
|
|
22
|
+
|
|
23
|
+
runs-on: ${{ matrix.os }}
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v2
|
|
26
|
+
- name: Set up Ruby
|
|
27
|
+
uses: ruby/setup-ruby@v1
|
|
28
|
+
with:
|
|
29
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
30
|
+
bundler-cache: true
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: bundle exec rake test
|
data/.rubocop.yml
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
-
|
|
1
|
+
inherit_gem:
|
|
2
|
+
rubocop-shopify: rubocop-cli.yml
|
|
3
3
|
|
|
4
4
|
AllCops:
|
|
5
|
-
Exclude:
|
|
6
|
-
|
|
5
|
+
Exclude:
|
|
6
|
+
- gen/template/**/*
|
|
7
|
+
- vendor/**/*
|
|
8
|
+
TargetRubyVersion: 2.5
|
|
7
9
|
|
|
8
|
-
Style/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Shopify/RubocopComments:
|
|
12
|
-
Enabled: false
|
|
10
|
+
Style/ClassAndModuleChildren:
|
|
11
|
+
Exclude:
|
|
12
|
+
- lib/cli/kit/support/test_helper.rb
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
Layout/IndentHeredoc:
|
|
14
|
+
Style/FrozenStringLiteralComment:
|
|
16
15
|
Enabled: false
|
|
17
16
|
|
|
18
17
|
# This doesn't take into account retrying from an exception
|
|
19
|
-
Lint/
|
|
18
|
+
Lint/SuppressedException:
|
|
20
19
|
Enabled: false
|
|
21
20
|
|
|
22
21
|
# allow String.new to create mutable strings
|
|
@@ -35,6 +34,5 @@ Style/RegexpLiteral:
|
|
|
35
34
|
Style/MultilineBlockChain:
|
|
36
35
|
Enabled: false
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Enabled: false
|
|
37
|
+
Style/StringLiterals:
|
|
38
|
+
EnforcedStyle: single_quotes
|
data/Gemfile
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
# NOTE: These are development-only dependencies
|
|
2
|
-
source
|
|
2
|
+
source 'https://rubygems.org'
|
|
3
3
|
|
|
4
4
|
gemspec
|
|
5
5
|
|
|
6
6
|
group :development, :test do
|
|
7
7
|
gem 'rubocop'
|
|
8
|
+
gem 'rubocop-shopify'
|
|
8
9
|
gem 'byebug'
|
|
9
10
|
gem 'method_source'
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
group :test do
|
|
13
|
-
gem 'mocha', require: false
|
|
14
|
+
gem 'mocha', '~> 1.13.0', require: false
|
|
14
15
|
gem 'minitest', '>= 5.0.0', require: false
|
|
15
16
|
gem 'minitest-reporters', require: false
|
|
16
17
|
end
|
data/Gemfile.lock
CHANGED
|
@@ -1,57 +1,62 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
cli-kit (
|
|
5
|
-
cli-ui (>= 1.1.
|
|
4
|
+
cli-kit (4.0.0)
|
|
5
|
+
cli-ui (>= 1.1.4)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
10
|
ansi (1.5.0)
|
|
11
|
-
ast (2.
|
|
12
|
-
builder (3.2.
|
|
13
|
-
byebug (
|
|
14
|
-
cli-ui (1.1
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
minitest (
|
|
18
|
-
minitest-reporters (1.1.14)
|
|
11
|
+
ast (2.4.2)
|
|
12
|
+
builder (3.2.4)
|
|
13
|
+
byebug (11.1.3)
|
|
14
|
+
cli-ui (1.5.1)
|
|
15
|
+
method_source (1.0.0)
|
|
16
|
+
minitest (5.14.4)
|
|
17
|
+
minitest-reporters (1.4.3)
|
|
19
18
|
ansi
|
|
20
19
|
builder
|
|
21
20
|
minitest (>= 5.0)
|
|
22
21
|
ruby-progressbar
|
|
23
|
-
mocha (1.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
rubocop (0.49.1)
|
|
22
|
+
mocha (1.13.0)
|
|
23
|
+
parallel (1.21.0)
|
|
24
|
+
parser (3.0.2.0)
|
|
25
|
+
ast (~> 2.4.1)
|
|
26
|
+
rainbow (3.0.0)
|
|
27
|
+
rake (13.0.6)
|
|
28
|
+
regexp_parser (2.1.1)
|
|
29
|
+
rexml (3.2.5)
|
|
30
|
+
rubocop (1.22.3)
|
|
33
31
|
parallel (~> 1.10)
|
|
34
|
-
parser (>=
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
parser (>= 3.0.0.0)
|
|
33
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
34
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
35
|
+
rexml
|
|
36
|
+
rubocop-ast (>= 1.12.0, < 2.0)
|
|
37
37
|
ruby-progressbar (~> 1.7)
|
|
38
|
-
unicode-display_width (
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
|
39
|
+
rubocop-ast (1.12.0)
|
|
40
|
+
parser (>= 3.0.1.1)
|
|
41
|
+
rubocop-shopify (2.3.0)
|
|
42
|
+
rubocop (~> 1.22)
|
|
43
|
+
ruby-progressbar (1.11.0)
|
|
44
|
+
unicode-display_width (2.1.0)
|
|
41
45
|
|
|
42
46
|
PLATFORMS
|
|
43
47
|
ruby
|
|
44
48
|
|
|
45
49
|
DEPENDENCIES
|
|
46
|
-
bundler (~> 1
|
|
50
|
+
bundler (~> 2.1)
|
|
47
51
|
byebug
|
|
48
52
|
cli-kit!
|
|
49
53
|
method_source
|
|
50
54
|
minitest (>= 5.0.0)
|
|
51
55
|
minitest-reporters
|
|
52
|
-
mocha
|
|
53
|
-
rake (~>
|
|
56
|
+
mocha (~> 1.13.0)
|
|
57
|
+
rake (~> 13.0)
|
|
54
58
|
rubocop
|
|
59
|
+
rubocop-shopify
|
|
55
60
|
|
|
56
61
|
BUNDLED WITH
|
|
57
|
-
|
|
62
|
+
2.2.24
|
data/README.md
CHANGED
|
@@ -11,8 +11,106 @@
|
|
|
11
11
|
to build a number of internal developer tools, along with
|
|
12
12
|
[cli-ui](https://github.com/shopify/cli-ui).
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## Getting Started
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
To begin creating your first `cli-kit` application, run:
|
|
17
|
+
```bash
|
|
18
|
+
gem install cli-kit
|
|
19
|
+
cli-kit new myproject
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Where `myproject` is the name of the application you wish to create. Then, you will be prompted to
|
|
23
|
+
select how the project consumes `cli-kit` and `cli-ui`. The available options are:
|
|
24
|
+
- Vendor (faster execution, more difficult to update dependencies)
|
|
25
|
+
- Bundler (slower execution, easier dependency management)
|
|
26
|
+
|
|
27
|
+
You're now ready to write your very first `cli-kit` application!
|
|
28
|
+
|
|
29
|
+
## How do `cli-kit` Applications Work?
|
|
30
|
+
|
|
31
|
+
The executable for your `cli-kit` app is stored in the "exe" directory. To execute the app, simply
|
|
32
|
+
run:
|
|
33
|
+
```bash
|
|
34
|
+
./exe/myproject
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Folder Structure
|
|
38
|
+
* `/exe/` - Location of the executables for your application.
|
|
39
|
+
* `/lib/` - Location of the resources for your app (modules, classes, helpers, etc).
|
|
40
|
+
* `myproject.rb` - This file is the starting point for where to look for all other files. It
|
|
41
|
+
configures autoload and autocall for the app.
|
|
42
|
+
* `myproject/` - Stores the various commands/entry points.
|
|
43
|
+
* `entry_point.rb` - This is the file that is first called from the executable. It handles
|
|
44
|
+
loading and commands.
|
|
45
|
+
* `commands.rb` - Registers the various commands that your application is able to handle.
|
|
46
|
+
* `commands/` - Stores Ruby files for each command (help, new, add, etc).
|
|
47
|
+
|
|
48
|
+
## Adding a New Command to your App
|
|
49
|
+
|
|
50
|
+
### Registering the Command
|
|
51
|
+
|
|
52
|
+
Let's say that you'd like your program to be able to handle a specific task, and you'd like to
|
|
53
|
+
_register_ a new handler for the command for that task, like `myproject add` to add 2 numbers, like
|
|
54
|
+
in a calculator app.
|
|
55
|
+
To do this, open `/lib/myproject/commands.rb`. Then, add a new line into the module, like this:
|
|
56
|
+
```ruby
|
|
57
|
+
register :Add, 'add', 'myproject/commands/add'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The format for this is `register :<CommandClass>, '<command-at-cli>', '<path/to/command.rb>'`
|
|
61
|
+
|
|
62
|
+
### Creating the Command Action
|
|
63
|
+
|
|
64
|
+
The action for a specific command is stored in its own Ruby file, in the `/lib/myproject/commands/`
|
|
65
|
+
directory. Here is an example of the `add` command in our previous to-do app example:
|
|
66
|
+
```ruby
|
|
67
|
+
require 'myproject'
|
|
68
|
+
|
|
69
|
+
module Myproject
|
|
70
|
+
module Commands
|
|
71
|
+
class Add < Myproject::Command
|
|
72
|
+
def call(args, _name)
|
|
73
|
+
# command action goes here
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.help
|
|
77
|
+
# help or instructions go here
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The `call(args, _name)` method is what actually runs when the `myproject add` command is executed.
|
|
86
|
+
|
|
87
|
+
- **Note:** The `args` parameter represents all the arguments the user has specified.
|
|
88
|
+
|
|
89
|
+
Let's say that you are trying to compute the sum of 2 numbers that the user has specified as
|
|
90
|
+
arguments. For example:
|
|
91
|
+
```ruby
|
|
92
|
+
def call(args, _name)
|
|
93
|
+
sum = args.map(&:to_i).inject(&:+)
|
|
94
|
+
puts sum
|
|
95
|
+
end
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Getting Help
|
|
99
|
+
|
|
100
|
+
Above, you'll notice that we also have a `self.help` method. This method is what runs when the user
|
|
101
|
+
has incorrectly used the command, or has requested help. For example:
|
|
102
|
+
```ruby
|
|
103
|
+
def self.help
|
|
104
|
+
"Print the sum of 2 numbers.\nUsage: {{command:#{Myproject::TOOL_NAME} add}} 5 7"
|
|
105
|
+
end
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## User Interfaces
|
|
109
|
+
|
|
110
|
+
`cli-kit` also features `cli-ui`, another gem from us here at Shopify, which allows for the use of
|
|
111
|
+
powerful command-line user interface elements. For more details on how to use `cli-ui`, visit the
|
|
112
|
+
[`cli-ui`](https://github.com/Shopify/cli-ui) repo.
|
|
113
|
+
|
|
114
|
+
## Examples
|
|
115
|
+
|
|
116
|
+
- [A Simple To-Do App](https://github.com/Shopify/cli-kit-example)
|
data/Rakefile
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
require 'rubocop/rake_task'
|
|
4
|
+
require 'bundler/gem_tasks'
|
|
5
|
+
|
|
6
|
+
TEST_ROOT = File.expand_path('../test', __FILE__)
|
|
7
|
+
|
|
8
|
+
Rake::TestTask.new do |t|
|
|
9
|
+
t.libs += ['test']
|
|
10
|
+
t.test_files = FileList[File.join(TEST_ROOT, '**', '*_test.rb')]
|
|
11
|
+
t.verbose = false
|
|
12
|
+
t.warning = false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
RuboCop::RakeTask.new(:style) do |t|
|
|
16
|
+
t.options = ['--display-cop-names']
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
task :test_gen_bundler do
|
|
20
|
+
sh 'DEPS=bundler bin/test_gen'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
task :test_gen_vendor do
|
|
24
|
+
sh 'DEPS=vendor bin/test_gen'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
task(default: [:test, :style, :test_gen_bundler, :test_gen_vendor])
|
data/TODO.md
ADDED
data/bin/console
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'cli/kit'
|
|
5
5
|
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
|
@@ -10,5 +10,5 @@ require "cli/kit"
|
|
|
10
10
|
# require "pry"
|
|
11
11
|
# Pry.start
|
|
12
12
|
|
|
13
|
-
require
|
|
13
|
+
require 'irb'
|
|
14
14
|
IRB.start(__FILE__)
|
data/bin/test_gen
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Make sure we're in the cli kit directory
|
|
5
|
+
CURR_DIR=$(dirname "$0")
|
|
6
|
+
cd $CURR_DIR
|
|
7
|
+
cd ../
|
|
8
|
+
|
|
9
|
+
# Clean up
|
|
10
|
+
function finish {
|
|
11
|
+
cd $CURR_DIR
|
|
12
|
+
cd ../../
|
|
13
|
+
rm -rf myapp
|
|
14
|
+
}
|
|
15
|
+
trap finish EXIT
|
|
16
|
+
|
|
17
|
+
# Generate app and move up a level to be at the same level as cli-kit
|
|
18
|
+
bundle exec ruby exe/cli-kit new myapp
|
|
19
|
+
mv myapp ../
|
|
20
|
+
cd ../myapp
|
|
21
|
+
|
|
22
|
+
# Test
|
|
23
|
+
if [[ $DEPS == 'bundler' ]]; then
|
|
24
|
+
bundle install
|
|
25
|
+
fi
|
|
26
|
+
bin/testunit
|
|
27
|
+
|
|
28
|
+
if [[ $DEPS == 'vendor' ]]; then
|
|
29
|
+
git clone https://github.com/Shopify/cli-ui.git ../cli-ui
|
|
30
|
+
bin/update-deps
|
|
31
|
+
fi
|
data/bin/testunit
CHANGED
|
@@ -9,12 +9,12 @@ CLI_TEST_ROOT = root + '/test'
|
|
|
9
9
|
$LOAD_PATH.unshift(CLI_TEST_ROOT)
|
|
10
10
|
|
|
11
11
|
def test_files
|
|
12
|
-
Dir.glob(CLI_TEST_ROOT +
|
|
12
|
+
Dir.glob(CLI_TEST_ROOT + '/**/*_test.rb')
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
if ARGV.empty?
|
|
16
16
|
test_files.each { |f| require(f) }
|
|
17
|
-
exit
|
|
17
|
+
exit(0)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# A list of files is presumed to be specified
|
data/cli-kit.gemspec
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
|
+
|
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
5
|
require 'cli/kit/version'
|
|
@@ -6,24 +7,24 @@ require 'cli/kit/version'
|
|
|
6
7
|
Gem::Specification.new do |spec|
|
|
7
8
|
spec.name = 'cli-kit'
|
|
8
9
|
spec.version = CLI::Kit::VERSION
|
|
9
|
-
spec.authors = ['Burke Libbey', '
|
|
10
|
-
spec.email = ['burke.libbey@shopify.com', '
|
|
10
|
+
spec.authors = ['Burke Libbey', 'Aaron Olson', 'Lisa Ugray']
|
|
11
|
+
spec.email = ['burke.libbey@shopify.com', 'aaron.olson@shopify.com', 'lisa.ugray@shopify.com']
|
|
11
12
|
|
|
12
13
|
spec.summary = 'Terminal UI framework extensions'
|
|
13
14
|
spec.description = 'Terminal UI framework extensions'
|
|
14
15
|
spec.homepage = 'https://github.com/shopify/cli-kit'
|
|
15
16
|
spec.license = 'MIT'
|
|
16
17
|
|
|
17
|
-
spec.files =
|
|
18
|
+
spec.files = %x(git ls-files -z).split("\x0").reject do |f|
|
|
18
19
|
f.match(%r{^(test|spec|features)/})
|
|
19
20
|
end
|
|
20
21
|
spec.bindir = 'exe'
|
|
21
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
22
23
|
spec.require_paths = ['lib']
|
|
23
24
|
|
|
24
|
-
spec.add_runtime_dependency
|
|
25
|
+
spec.add_runtime_dependency('cli-ui', '>= 1.1.4')
|
|
25
26
|
|
|
26
|
-
spec.add_development_dependency
|
|
27
|
-
spec.add_development_dependency
|
|
28
|
-
spec.add_development_dependency
|
|
27
|
+
spec.add_development_dependency('bundler', '~> 2.1')
|
|
28
|
+
spec.add_development_dependency('minitest', '~> 5.0')
|
|
29
|
+
spec.add_development_dependency('rake', '~> 13.0')
|
|
29
30
|
end
|
data/dev.yml
CHANGED
data/examples/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
**Note: If you're looking to bootstrap a new app, consider running `cli-kit new` instead of
|
|
4
|
+
copy/pasting one of these.**
|
|
5
|
+
|
|
6
|
+
## Full Example
|
|
7
|
+
|
|
8
|
+
The full example lives in its own repository at https://github.com/Shopify/cli-kit-example.
|
|
9
|
+
This is quite similar to the output of `cli-kit new`, but fleshed out a little bit more with
|
|
10
|
+
a couple of commands.
|
|
11
|
+
|
|
12
|
+
## Single-File starting point
|
|
13
|
+
|
|
14
|
+
Maybe it appeals to you to start from a single file and grow, rather than generating framework.
|
|
15
|
+
Check out the [`examples/single-file`](single-file) example.
|
|
16
|
+
|
|
17
|
+
## Minimal example
|
|
18
|
+
|
|
19
|
+
This example demonstrates the core of what `cli-kit` does very simply, but in general, shouldn't be
|
|
20
|
+
used for anything other than quick hacks. It leaves out a few best practices that help CLI apps
|
|
21
|
+
scale gracefully. Find it at [`examples/minimal`](minimal).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'cli/ui'
|
|
4
|
+
require 'cli/kit'
|
|
5
|
+
|
|
6
|
+
CLI::UI::StdoutRouter.enable
|
|
7
|
+
|
|
8
|
+
include(CLI::Kit)
|
|
9
|
+
|
|
10
|
+
registry = CommandRegistry.new(default: 'hello', contextual_resolver: nil)
|
|
11
|
+
registry.add(Class.new(BaseCommand) do
|
|
12
|
+
def call(_args, _name)
|
|
13
|
+
puts 'hello, world!'
|
|
14
|
+
end
|
|
15
|
+
end, 'hello')
|
|
16
|
+
|
|
17
|
+
executor = Executor.new(log_file: '/tmp/example.log')
|
|
18
|
+
error_handler = ErrorHandler.new(log_file: '/tmp/example.log', exception_reporter: nil)
|
|
19
|
+
resolver = Resolver.new(tool_name: 'example', command_registry: registry)
|
|
20
|
+
entry_point = ->(args) { executor.call(*resolver.call(args)) }
|
|
21
|
+
|
|
22
|
+
exit(error_handler.call { entry_point.call(ARGV.dup) }) if __FILE__ == $PROGRAM_NAME
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'cli/ui'
|
|
4
|
+
require 'cli/kit'
|
|
5
|
+
|
|
6
|
+
CLI::UI::StdoutRouter.enable
|
|
7
|
+
|
|
8
|
+
module Example
|
|
9
|
+
extend CLI::Kit::Autocall
|
|
10
|
+
|
|
11
|
+
TOOL_NAME = 'example'
|
|
12
|
+
ROOT = File.expand_path('../..', __FILE__)
|
|
13
|
+
LOG_FILE = '/tmp/example.log'
|
|
14
|
+
|
|
15
|
+
module Commands
|
|
16
|
+
extend CLI::Kit::Autocall
|
|
17
|
+
|
|
18
|
+
Registry = CLI::Kit::CommandRegistry.new(
|
|
19
|
+
default: 'hello',
|
|
20
|
+
contextual_resolver: nil
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def self.register(const, cmd, path = nil, &block)
|
|
24
|
+
path ? autoload(const, path) : autocall(const, &block)
|
|
25
|
+
Registry.add(->() { const_get(const) }, cmd)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# register(:Hello, 'hello', 'a/b/hello')
|
|
29
|
+
|
|
30
|
+
register(:Hello, 'hello') do
|
|
31
|
+
Class.new(Example::Command) do
|
|
32
|
+
def call(_args, _name)
|
|
33
|
+
puts 'hello, world!'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
autocall(:EntryPoint) do
|
|
40
|
+
Module.new do
|
|
41
|
+
def self.call(args)
|
|
42
|
+
cmd, command_name, args = Example::Resolver.call(args)
|
|
43
|
+
Example::Executor.call(cmd, command_name, args)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
autocall(:Config) { CLI::Kit::Config.new(tool_name: TOOL_NAME) }
|
|
49
|
+
autocall(:Command) { CLI::Kit::BaseCommand }
|
|
50
|
+
|
|
51
|
+
autocall(:Executor) { CLI::Kit::Executor.new(log_file: LOG_FILE) }
|
|
52
|
+
autocall(:Resolver) do
|
|
53
|
+
CLI::Kit::Resolver.new(
|
|
54
|
+
tool_name: TOOL_NAME,
|
|
55
|
+
command_registry: Example::Commands::Registry
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
autocall(:ErrorHandler) do
|
|
60
|
+
CLI::Kit::ErrorHandler.new(
|
|
61
|
+
log_file: LOG_FILE,
|
|
62
|
+
exception_reporter: nil
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if __FILE__ == $PROGRAM_NAME
|
|
68
|
+
exit(Example::ErrorHandler.call do
|
|
69
|
+
Example::EntryPoint.call(ARGV.dup)
|
|
70
|
+
end)
|
|
71
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Full example at https://github.com/Shopify/cli-kit-example
|
|
@@ -4,15 +4,15 @@ module Gen
|
|
|
4
4
|
module Commands
|
|
5
5
|
class Help < Gen::Command
|
|
6
6
|
def call(_args, _name)
|
|
7
|
-
puts CLI::UI.fmt(
|
|
8
|
-
puts
|
|
7
|
+
puts CLI::UI.fmt('{{bold:Available commands}}')
|
|
8
|
+
puts ''
|
|
9
9
|
|
|
10
10
|
Gen::Commands::Registry.resolved_commands.each do |name, klass|
|
|
11
11
|
puts CLI::UI.fmt("{{command:#{Gen::TOOL_NAME} #{name}}}")
|
|
12
|
-
if help = klass.help
|
|
12
|
+
if klass.respond_to?(:help) && (help = klass.help)
|
|
13
13
|
puts CLI::UI.fmt(help)
|
|
14
14
|
end
|
|
15
|
-
puts
|
|
15
|
+
puts ''
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
end
|
data/gen/lib/gen/generator.rb
CHANGED
|
@@ -18,21 +18,20 @@ module Gen
|
|
|
18
18
|
# false -> delete file
|
|
19
19
|
# string -> rename file before applying template substitutions
|
|
20
20
|
VENDOR_TRANSLATIONS = {
|
|
21
|
-
'Gemfile'
|
|
22
|
-
'exe/__app__-gems'
|
|
21
|
+
'Gemfile' => false,
|
|
22
|
+
'exe/__app__-gems' => false,
|
|
23
23
|
'exe/__app__-vendor' => 'exe/__app__',
|
|
24
|
-
'dev-gems.yml'
|
|
25
|
-
'dev-vendor.yml'
|
|
24
|
+
'dev-gems.yml' => false,
|
|
25
|
+
'dev-vendor.yml' => 'dev.yml',
|
|
26
26
|
}.freeze
|
|
27
27
|
private_constant :VENDOR_TRANSLATIONS
|
|
28
28
|
|
|
29
29
|
BUNDLER_TRANSLATIONS = {
|
|
30
|
-
'bin'
|
|
31
|
-
'
|
|
32
|
-
'exe/__app__-gems' => 'exe/__app__',
|
|
30
|
+
'bin/update-deps' => false,
|
|
31
|
+
'exe/__app__-gems' => 'exe/__app__',
|
|
33
32
|
'exe/__app__-vendor' => false,
|
|
34
|
-
'dev-gems.yml'
|
|
35
|
-
'dev-vendor.yml'
|
|
33
|
+
'dev-gems.yml' => 'dev.yml',
|
|
34
|
+
'dev-vendor.yml' => false,
|
|
36
35
|
}.freeze
|
|
37
36
|
private_constant :BUNDLER_TRANSLATIONS
|
|
38
37
|
|
|
@@ -59,6 +58,9 @@ module Gen
|
|
|
59
58
|
private
|
|
60
59
|
|
|
61
60
|
def ask_vendor?
|
|
61
|
+
return true if ENV['DEPS'] == 'vendor'
|
|
62
|
+
return false if ENV['DEPS'] == 'bundler'
|
|
63
|
+
|
|
62
64
|
vendor = nil
|
|
63
65
|
CLI::UI::Frame.open('Configuration') do
|
|
64
66
|
q = 'How would you like the application to consume {{command:cli-kit}} and {{command:cli-ui}}?'
|
|
@@ -114,7 +116,7 @@ module Gen
|
|
|
114
116
|
out, stat = Open3.capture2e('git', '-C', dir, 'clone', "https://github.com/shopify/#{repo}")
|
|
115
117
|
unless stat.success?
|
|
116
118
|
STDERR.puts(out)
|
|
117
|
-
error(
|
|
119
|
+
error('git clone failed')
|
|
118
120
|
end
|
|
119
121
|
end
|
|
120
122
|
|