runfile 0.12.0 → 1.0.0.rc2

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.
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