runfile 0.12.0 → 1.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +109 -37
  3. data/bin/runn +5 -0
  4. data/examples/default-action/runfile +9 -0
  5. data/examples/default-action-2/runfile +11 -0
  6. data/examples/default-action-2/server.runfile +6 -0
  7. data/examples/different-name/runfile.rb +8 -0
  8. data/examples/example/runfile +10 -0
  9. data/examples/example-multiline/runfile +16 -0
  10. data/examples/execute/runfile +14 -0
  11. data/examples/execute/server.runfile +11 -0
  12. data/examples/full/runfile +24 -0
  13. data/examples/import/more_tasks/spec.runfile +8 -0
  14. data/examples/import/runfile +10 -0
  15. data/examples/import/tasks/server.runfile +14 -0
  16. data/examples/minimal/runfile +4 -0
  17. data/examples/multiple-runfiles/runfile +11 -0
  18. data/examples/multiple-runfiles/server.runfile +13 -0
  19. data/examples/named-only/deploy.runfile +7 -0
  20. data/examples/named-only/server.runfile +11 -0
  21. data/examples/naval-fate/runfile +47 -0
  22. data/examples/shortcut/runfile +31 -0
  23. data/lib/runfile/action.rb +40 -14
  24. data/lib/runfile/concerns/dsl.rb +116 -0
  25. data/lib/runfile/concerns/inspectable.rb +13 -0
  26. data/lib/runfile/concerns/renderable.rb +16 -0
  27. data/lib/runfile/entrypoint.rb +50 -0
  28. data/lib/runfile/exceptions.rb +13 -0
  29. data/lib/runfile/gem_finder.rb +29 -0
  30. data/lib/runfile/initiator.rb +87 -0
  31. data/lib/runfile/meta.rb +65 -0
  32. data/lib/runfile/runner.rb +10 -173
  33. data/lib/runfile/templates/runfile +13 -0
  34. data/lib/runfile/userfile.rb +103 -0
  35. data/lib/runfile/version.rb +2 -2
  36. data/lib/runfile/views/initiator.gtx +28 -0
  37. data/lib/runfile/views/userfile.gtx +93 -0
  38. data/lib/runfile.rb +13 -10
  39. metadata +98 -24
  40. data/bin/run +0 -10
  41. data/bin/run! +0 -16
  42. data/lib/runfile/compatibility.rb +0 -84
  43. data/lib/runfile/docopt_helper.rb +0 -128
  44. data/lib/runfile/dsl.rb +0 -90
  45. data/lib/runfile/refinements.rb +0 -22
  46. data/lib/runfile/runfile_helper.rb +0 -165
  47. data/lib/runfile/settings.rb +0 -34
  48. data/lib/runfile/setup.rb +0 -19
  49. data/lib/runfile/templates/Runfile +0 -16
  50. data/lib/runfile/terminal.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79a1c61423d09207b687d93f98035c5ca6b5e9d36f7b4acc12d93ccaa817c873
4
- data.tar.gz: 0d870a0f93a9add25113e8030a02ce99dd2ecb0ed8f42d5eddb69b520b998da0
3
+ metadata.gz: 5ae2a7aefd3a25703d232d70e6857aeafe467772582a96202d371bfca748e1f7
4
+ data.tar.gz: 32f39514ba7ffb8318c305278f55a397d2e686c7179cec0ff5899c5e6fd62871
5
5
  SHA512:
6
- metadata.gz: 387383e744bac9dbd8ab89598df2a3217a4fa58f120b60ab7c31bbbfec074ae3fee0512cdee002b740af3aa85a6cd930ddfeefbe1d14deec182ebf77d57c8ab6
7
- data.tar.gz: ca1b2962b157454842a0050cd3bf70826509362e7b18b9ebd2c1cc863480b0ac7f7556ad9e4fed27bad22b9c11238cf6b063e57e8b1d0459607fdb791c4ea1ae
6
+ metadata.gz: 289c29cf9119ce944bc46c1c6067299454396b143721b5b5b0b6b03553bca3c805743656a13cb8f4757a77022e4294152254124d7f6dfea4803879ac4289690d
7
+ data.tar.gz: 61afd4733813f4f3082765eae107295af324a446da8ccc5bc70959504c81aba0a161e286fc25ff0095b2fbff0c50b3a9fb76a8a21f992c6f5c620b1abd15b111
data/README.md CHANGED
@@ -20,85 +20,157 @@ Rake-inspired - Docopt inside
20
20
  to [Rake](https://github.com/ruby/rake), but with the full power of
21
21
  [Docopt](http://docopt.org/) command line options.
22
22
 
23
- You create a `Runfile`, and execute commands with
23
+ You create a `runfile`, and execute commands with
24
24
  `run command arguments -and --flags`.
25
25
 
26
+ Runfile is designed primarily for Ruby developers, but if you need to add a
27
+ command line "toolbelt" for your projects, you can use it regardless.
28
+
29
+ ## Pre-release Notice
30
+
31
+ Note that this README describes the not yet released 1.0.0 version.
32
+ See [runfile.dannyb.co](https://runfile.dannyb.co/) for the stable release
33
+ documentation.
34
+
35
+ During the pre-release phase, the `run` executable is called `runn` instead,
36
+ to allow running both the stable and pre-release version side by side.
37
+
38
+ ## Demo
39
+
26
40
  ![Runfile Demo](demo.svg "Runfile Demo")
27
41
 
42
+ ## Install
43
+
44
+ ```shell
45
+ $ gem install runfile --pre
46
+ ```
47
+
28
48
  ## Quick Start
29
49
 
30
50
  ```shell
31
- $ run new # create a new Runfile
51
+ $ run new # create a new runfile
32
52
  $ run --help # show the usage patterns
33
- $ vi Runfile # edit the Runfile
53
+ $ vi runfile # edit the runfile
34
54
  ```
35
55
 
36
-
37
56
  ## Example
38
57
 
39
- The most minimal `Runfile` looks like this:
58
+ A simple `runfile` looks like this. You can get this template by running `run
59
+ new` ()in a directory without other runfiles).
40
60
 
41
61
  ```ruby
42
- usage "greet <name>"
43
- action :greet do |args|
44
- puts "Hello #{args['<name>']}"
62
+ title 'Greeter'
63
+ summary 'A sample runfile'
64
+
65
+ usage 'hello [NAME --shout]'
66
+ help 'Say hello'
67
+ option '--shout, -s', 'Greet louder'
68
+ action 'hello' do |args|
69
+ name = args['NAME'] || 'You...'
70
+ message = "Hello #{name}"
71
+ message = "#{message.upcase}!" if args['--shout']
72
+
73
+ say "gu`#{message}`"
45
74
  end
46
75
  ```
47
76
 
48
77
  You can then run it by executing this command:
49
78
 
50
79
  ```shell
51
- $ run greet Luke
80
+ $ run hello Luke
52
81
  Hello Luke
53
82
  ```
54
83
 
55
- Executing `run` without parameters, will show the usage patterns:
84
+ It will behave in the same way you expect any standard command line interface to
85
+ behave,
56
86
 
57
87
  ```shell
88
+ # Show usage summary
58
89
  $ run
59
90
  Usage:
60
- run greet <name>
61
- run (-h|--help|--version)
62
- ```
91
+ run hello [NAME --shout]
92
+ run (--help | -h)
63
93
 
64
- Executing `run --help` will show the full help document (docopt)
65
-
66
- ```shell
94
+ # Show detailed help
67
95
  $ run --help
68
- Runfile 0.0.0
96
+ Greeter
97
+
98
+ A sample runfile
69
99
 
70
100
  Usage:
71
- run greet <name>
72
- run (-h|--help|--version)
101
+ run hello [NAME --shout]
102
+ run (--help | -h)
103
+
104
+ Commands:
105
+ hello
106
+ Say hello
73
107
 
74
108
  Options:
75
- -h --help
76
- Show this screen
109
+ --shout, -s
110
+ Greet louder
111
+
112
+ --help, -h
113
+ Show this message
114
+ ```
77
115
 
78
- --version
79
- Show version
116
+ ## Examples
117
+
118
+ You can learn almost everything there is to know about runfile from the
119
+ [examples](https://github.com/DannyBen/runfile/tree/master/examples#readme).
120
+
121
+ You can get any of these examples directly in your terminal by running:
122
+
123
+ ```shell
124
+ $ run example --help
80
125
  ```
81
126
 
82
127
  ## Documentation
83
128
 
84
- - [User Guide](https://runfile.dannyb.co/)
85
- - [Learn by Example](https://github.com/DannyBen/runfile/tree/master/examples#readme)
129
+ For a more formal documentation, see the [User Guide](https://runfile.dannyb.co/).
86
130
 
87
- ## Breaking changes in 0.12.0
131
+ Note that the current user guide is for the stable version 0.12.0.
88
132
 
89
- Note that version 0.12.0 removes several commands from the DSL.
90
- If you were using any of the Colsole commands (`say`, `resay`, etc.), or any of
91
- the `run`, `run_bg` commands, you will have to adjust your Runfile since they are
92
- no longer available.
133
+ ## Breaking Changes in 1.0.0
93
134
 
94
- For convenience, you can simply `require runfile/compatibility` at the top of
95
- your Runfile, to still have this functionality included.
135
+ If you are using a version earlier than 1.0, note that the upcoming release
136
+ 1.0.0 includes some breaking changes. You can read more about them in[this Pull
137
+ Request](https://github.com/DannyBen/runfile/pull/50).
96
138
 
97
- More info and alternative solutions in
98
- [this pull request](https://github.com/DannyBen/runfile/pull/46).
139
+ ### Upgrading to 1.0.0
99
140
 
100
- ## Contributing / Support
141
+ ### No more `.runfile.yml` config
142
+
143
+ If you have used the multi-runfile config file, this no longer exists.
144
+ Use a standard `runfile` instead, along with the `import` directive.
145
+
146
+ ### No more `action :global`
147
+
148
+ If you have used the `action :global do` notation, this is replaced with the
149
+ simpler use `action do` instead. Also, there is no more need for
150
+ empty `usage ''`, just delete it if you have it in your runfiles.
151
+
152
+ ### No more need for `trap(:INT)`
101
153
 
102
- If you experience any issue, have a question or a suggestion, or if you wish
103
- to contribute, feel free to [open an issue](https://github.com/DannyBen/runfile/issues).
154
+ If your old runfiles trap the `Interrupt` signal, there i no longer a need to
155
+ do so, as it is trapped by default.
156
+
157
+ ### Colsole is included
158
+
159
+ If your runfiles `required` and `include` Colsole, there is no longer a need to
160
+ do it. Colsole is bundled and available in actions.
161
+
162
+ ### Long flags before short flags
163
+
164
+ This is a cosmetic change for consistency. All generated output shows long flags
165
+ before short flags `--force, -f` instead of `-f, --force`. Update your custom
166
+ `usage` directives accordingly.
167
+
168
+ ### RunfileTasks
169
+
170
+ The `RunfileTasks` gem is not yet compatible. It will be later on.
171
+
172
+ ## Contributing / Support
104
173
 
174
+ If you experience any issue, have a question or a suggestion, or if you wish to
175
+ contribute, feel free to
176
+ [open an issue](https://github.com/DannyBen/runfile/issues).
data/bin/runn ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'runfile'
3
+
4
+ exit_code = Runfile::Entrypoint.new.run!
5
+ exit exit_code if exit_code.is_a? Integer
@@ -0,0 +1,9 @@
1
+ title 'Default action'
2
+ summary 'Defining an action without a name will execute immediately'
3
+
4
+ # $ run Hello : will execute this block instead of showing usage
5
+ # $ run : will still show usage since MESSAGE is a required argument
6
+ usage 'MESSAGE'
7
+ action do |args|
8
+ say "Action executed with #{args['MESSAGE']}"
9
+ end
@@ -0,0 +1,11 @@
1
+ title 'Default action and other actions'
2
+
3
+ # $ run : will execute this block instead of showing usage
4
+ action do
5
+ say 'Running DEFAULT action'
6
+ end
7
+
8
+ # $ run test
9
+ action :test do
10
+ say 'Running TEST action'
11
+ end
@@ -0,0 +1,6 @@
1
+ title 'Default action in a named file'
2
+
3
+ # $ run server
4
+ action do
5
+ say 'Starting server'
6
+ end
@@ -0,0 +1,8 @@
1
+ title 'Other name'
2
+ summary 'The main runfile can be named "runfile", "Runfile" or "runfile.rb"'
3
+
4
+ # $ run greet
5
+ # $ run g
6
+ action :greet, :g do
7
+ say 'GREET'
8
+ end
@@ -0,0 +1,10 @@
1
+ title 'Example with example'
2
+ summary 'Showing examples with --help'
3
+
4
+ usage 'build [--install]'
5
+ example 'run build'
6
+ example 'run build --install'
7
+ action 'build' do |args|
8
+ say 'Building'
9
+ say 'Installing' if args['--install']
10
+ end
@@ -0,0 +1,16 @@
1
+ title 'Example with a multiline examples'
2
+ summary 'Showing examples with --help'
3
+
4
+ example <<~EXAMPLES
5
+ nb`Build only`
6
+ $ run build
7
+
8
+ nb`Build and install`
9
+ $ run build --install
10
+ EXAMPLES
11
+
12
+ usage 'build [--install]'
13
+ action 'build' do |args|
14
+ say 'Building'
15
+ say 'Installing' if args['--install']
16
+ end
@@ -0,0 +1,14 @@
1
+ title 'Execute other actions'
2
+ summary 'Shows how to call other actions from within an action'
3
+
4
+ # $ run greet
5
+ # $ run g
6
+ action :greet, :g do |_args|
7
+ say 'GREET'
8
+ end
9
+
10
+ # $ run s
11
+ help 'Shortcut to nu`server start`'
12
+ action :s do
13
+ execute 'server start'
14
+ end
@@ -0,0 +1,11 @@
1
+ # $ run server start
2
+ # $ run server s
3
+ action :start, :s do
4
+ say 'START'
5
+ end
6
+
7
+ # $ run server stop
8
+ # $ run server st
9
+ action :stop, :st do
10
+ say 'STOP'
11
+ end
@@ -0,0 +1,24 @@
1
+ title 'Complete Runfile'
2
+ summary 'A runfile with all (most) features'
3
+ version '0.2.0'
4
+
5
+ help 'Say something'
6
+ usage '(say|s) MESSAGE [options]'
7
+ option '--color, -c CODE', 'One letter color code [default: g]'
8
+ option '--bold, -b', 'Show in bold'
9
+ param 'MESSAGE', 'Message to say'
10
+ env_var 'COLOR', 'Set color code (same as --color)'
11
+ example 'run say hello'
12
+ example 'run say hello -cr --bold'
13
+ action :say, :s do |args|
14
+ color = args['--color']
15
+ color += 'b' if args['--bold']
16
+ say "#{color}`Hello #{args['MESSAGE']}`"
17
+ end
18
+
19
+ usage 'ping [--red]'
20
+ help 'Respond with PONG'
21
+ option '--red, -r', 'PONG in red'
22
+ action :ping do |args|
23
+ say args['--red'] ? 'r`PONG`' : 'g`PONG`'
24
+ end
@@ -0,0 +1,8 @@
1
+ usage '[--continue --failed]'
2
+ option '--continue, -c', 'Continue testing'
3
+ option '--failed, -f', 'Retest failed specs'
4
+ action do |args|
5
+ say 'spec action'
6
+ p context
7
+ p args
8
+ end
@@ -0,0 +1,10 @@
1
+ title 'Importing other funfiles'
2
+ summary 'Reference other runfiles to blend them seamlessly as one command line interface'
3
+
4
+ import 'tasks/*'
5
+ import 'more_tasks/spec', anything: 'Context Values'
6
+
7
+ usage 'say MESSAGE'
8
+ action 'say' do |args|
9
+ say "in main runfile, with #{args['MESSAGE']}"
10
+ end
@@ -0,0 +1,14 @@
1
+ summary 'Server management commands'
2
+
3
+ action 'start' do |_args|
4
+ say "Context: #{context[:anything]}"
5
+ say 'g`Starting server`'
6
+ end
7
+
8
+ usage 'stop [--force]'
9
+ help 'Stop the server, with optional hard quit'
10
+ option '--force, -f', 'Force quit'
11
+ action 'stop' do |args|
12
+ say 'r`Stopping server`'
13
+ say 'rib` FORCE QUIT `' if args['--force']
14
+ end
@@ -0,0 +1,4 @@
1
+ # $ run greet : execute this block
2
+ action :greet do
3
+ say 'g`Hello World`'
4
+ end
@@ -0,0 +1,11 @@
1
+ title 'Multiple runfiles'
2
+ summary 'Named runfiles in this directory will be blended seamlessly'
3
+
4
+ help 'Say something'
5
+ usage 'say MESSAGE [options]'
6
+ option '--color, -c CODE', 'One letter color code [default: g]'
7
+ param 'MESSAGE', 'Message to say'
8
+ action :say do |args|
9
+ color = args['--color']
10
+ say "#{color}`Hello #{args['MESSAGE']}`"
11
+ end
@@ -0,0 +1,13 @@
1
+ summary 'Server management commands'
2
+
3
+ action 'start' do |_args|
4
+ say 'g`Starting server`'
5
+ end
6
+
7
+ usage 'stop [--force]'
8
+ help 'Stop the server, with optional hard quit'
9
+ option '--force, -f', 'Force quit'
10
+ action 'stop' do |args|
11
+ say 'r`Stopping server`'
12
+ say 'rib` FORCE QUIT `' if args['--force']
13
+ end
@@ -0,0 +1,7 @@
1
+ title 'Deployment commands'
2
+ summary 'With a default action'
3
+
4
+ # $ run deploy
5
+ action do
6
+ say 'deploy command'
7
+ end
@@ -0,0 +1,11 @@
1
+ title 'Server commands'
2
+
3
+ # $ run server stop
4
+ action :stop do
5
+ say 'stop server'
6
+ end
7
+
8
+ # $ run server start
9
+ action :start do
10
+ say 'start server'
11
+ end
@@ -0,0 +1,47 @@
1
+ title 'Naval Fate'
2
+ version '1.2.1'
3
+ summary <<~SUMMARY
4
+ Command line example adapted from Docopt's Naval Fate
5
+ Source bu`http://docopt.org/`
6
+ SUMMARY
7
+
8
+ usage 'new SHIPS...'
9
+ help 'Deploy one or more ships'
10
+ param 'SHIPS', 'One ore more ship names'
11
+ action :new do |args|
12
+ args['SHIPS'].each do |ship|
13
+ say "Deployed g`#{ship}`"
14
+ end
15
+ end
16
+
17
+ usage 'move SHIP X Y [--speed KN]'
18
+ help 'Move the given ship'
19
+ param 'SHIP', 'Ship name'
20
+ option '--speed, -s KN', 'Speed in knots [default: 20]'
21
+ action :move do |args|
22
+ ship = args['SHIP']
23
+ x = args['X']
24
+ y = args['Y']
25
+ speed = args['--speed']
26
+
27
+ say "Moving g`#{ship}` to b`#{x},#{y}` at m`#{speed}kn`"
28
+ end
29
+
30
+ usage 'mine (set | remove) X Y [--moored | --drifting]'
31
+ help 'Set or remove a mine'
32
+ option '--moored', 'Moored (anchored) mine'
33
+ option '--drifting', 'Drifting mine'
34
+ action :mine do |args|
35
+ action = args['set'] ? 'Setting' : 'Removing'
36
+ x = args['X']
37
+ y = args['Y']
38
+ type = if args['--moored']
39
+ 'moored'
40
+ elsif args['--drifting']
41
+ 'drifting'
42
+ else
43
+ 'bottom'
44
+ end
45
+
46
+ say "#{action} a #{type} mine at #{x},#{y}"
47
+ end
@@ -0,0 +1,31 @@
1
+ title 'Shortcut for an action'
2
+ summary 'Providing an alias shortcut for actions can be done in one of two ways'
3
+
4
+ # $ run greet :
5
+ # $ run g : will both execute this block
6
+ shortcut :g
7
+ action :greet do
8
+ say 'r`Greetings`'
9
+ end
10
+
11
+ # $ run salute
12
+ # $ run s --red
13
+ #
14
+ # Notice the explicit `usage` which is required when when parameters (--red)
15
+ # are needed. In this case, to support the shortcut you need to provide it
16
+ # as (salute | s)
17
+ usage '(salute | s) [--red]'
18
+ option '--red', 'In red'
19
+ shortcut :s
20
+ action :salute do |args|
21
+ color = args['--red'] ? 'r' : 'b'
22
+ say "#{color}`Salutations`"
23
+ end
24
+
25
+ # $ run toast
26
+ # $ run t
27
+ #
28
+ # Shortcut may also be provided as a second argument to the `action` directive
29
+ action :toast, :t do
30
+ say 'Toasts'
31
+ end
@@ -1,21 +1,47 @@
1
1
  module Runfile
2
-
3
- # The Action class represents a single Runfile action.
4
- # This object holds all the information needed to execute it and
5
- # show its help text (excluding the options, as they are considered
6
- # global throughout the application)
2
+ # Represents a single action inside a {Userfile} and executes its block
3
+ # on demand. Properties of this class are populated by the {DSL} module when
4
+ # running a {Userfile}.
7
5
  class Action
8
- attr :usage, :help
6
+ include Inspectable
7
+
8
+ attr_reader :name, :shortcut
9
+ attr_accessor :block, :help, :prefix
10
+
11
+ def run(args = {})
12
+ block.call args
13
+ end
14
+
15
+ def inspectable
16
+ { name: name, prefix: prefix, shortcut: shortcut }
17
+ end
18
+
19
+ def name=(value)
20
+ @name = value&.to_s
21
+ end
22
+
23
+ def shortcut=(value)
24
+ @shortcut = value&.to_s
25
+ end
26
+
27
+ def full_name
28
+ @full_name ||= if shortcut
29
+ "#{prefix} (#{name} | #{shortcut})".strip
30
+ else
31
+ "#{prefix} #{name}".strip
32
+ end
33
+ end
34
+
35
+ def names
36
+ name ? [name, shortcut].compact : ['(default)']
37
+ end
9
38
 
10
- def initialize(block, usage, help)
11
- @usage = usage
12
- @help = help
13
- @block = block
39
+ def implicit_usages
40
+ usages.empty? ? [full_name] : usages
14
41
  end
15
42
 
16
- # Call the provided block
17
- def execute(args)
18
- @block.yield args
43
+ def usages
44
+ @usages ||= []
19
45
  end
20
46
  end
21
- end
47
+ end