runfile 0.12.0 → 1.0.0.rc1

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 +108 -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 +7 -0
  14. data/examples/import/runfile +10 -0
  15. data/examples/import/tasks/server.runfile +13 -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 +132 -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 +111 -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: b399f5dddc730408a835c29507af0b23d80be1ce6452c90d0c26d0d0acc577e7
4
+ data.tar.gz: 27211f7110e22ca49317d893952d7af82bdd774879782335185f0421e74f864b
5
5
  SHA512:
6
- metadata.gz: 387383e744bac9dbd8ab89598df2a3217a4fa58f120b60ab7c31bbbfec074ae3fee0512cdee002b740af3aa85a6cd930ddfeefbe1d14deec182ebf77d57c8ab6
7
- data.tar.gz: ca1b2962b157454842a0050cd3bf70826509362e7b18b9ebd2c1cc863480b0ac7f7556ad9e4fed27bad22b9c11238cf6b063e57e8b1d0459607fdb791c4ea1ae
6
+ metadata.gz: eaf0546be8eed23eeb6af18789a83e4b4eaa5514b044b41efb7a7a401da8465986a05bfcc5ec0930b0292edf4ea1830d2c78d0014808b59d5cf2f7c25fd3eb6d
7
+ data.tar.gz: 7eb9ba751139e0a83106cf7a5c0ff933b51ebba6cdbd63ee32f7ddf34be249b9804f6fb007e303cb3e225cb3cedf04ed9418a7e6856cb94165208ee3e5e672c2
data/README.md CHANGED
@@ -20,85 +20,156 @@ 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 https://bashly.dannyb.co/ for the stable release documentation.
33
+
34
+ During the pre-release phase, the `run` executable is called `runn` instead,
35
+ to allow running both the stable and pre-release version side by side.
36
+
37
+ ## Demo
38
+
26
39
  ![Runfile Demo](demo.svg "Runfile Demo")
27
40
 
41
+ ## Install
42
+
43
+ ```shell
44
+ $ gem install runfile --pre
45
+ ```
46
+
28
47
  ## Quick Start
29
48
 
30
49
  ```shell
31
- $ run new # create a new Runfile
50
+ $ run new # create a new runfile
32
51
  $ run --help # show the usage patterns
33
- $ vi Runfile # edit the Runfile
52
+ $ vi runfile # edit the runfile
34
53
  ```
35
54
 
36
-
37
55
  ## Example
38
56
 
39
- The most minimal `Runfile` looks like this:
57
+ A simple `runfile` looks like this. You can get this template by running `run
58
+ new` ()in a directory without other runfiles).
40
59
 
41
60
  ```ruby
42
- usage "greet <name>"
43
- action :greet do |args|
44
- puts "Hello #{args['<name>']}"
61
+ title 'Greeter'
62
+ summary 'A sample runfile'
63
+
64
+ usage 'hello [NAME --shout]'
65
+ help 'Say hello'
66
+ option '--shout, -s', 'Greet louder'
67
+ action 'hello' do |args|
68
+ name = args['NAME'] || 'You...'
69
+ message = "Hello #{name}"
70
+ message = "#{message.upcase}!" if args['--shout']
71
+
72
+ say "gu`#{message}`"
45
73
  end
46
74
  ```
47
75
 
48
76
  You can then run it by executing this command:
49
77
 
50
78
  ```shell
51
- $ run greet Luke
79
+ $ run hello Luke
52
80
  Hello Luke
53
81
  ```
54
82
 
55
- Executing `run` without parameters, will show the usage patterns:
83
+ It will behave in the same way you expect any standard command line interface to
84
+ behave,
56
85
 
57
86
  ```shell
87
+ # Show usage summary
58
88
  $ run
59
89
  Usage:
60
- run greet <name>
61
- run (-h|--help|--version)
62
- ```
90
+ run hello [NAME --shout]
91
+ run (--help | -h)
63
92
 
64
- Executing `run --help` will show the full help document (docopt)
65
-
66
- ```shell
93
+ # Show detailed help
67
94
  $ run --help
68
- Runfile 0.0.0
95
+ Greeter
96
+
97
+ A sample runfile
69
98
 
70
99
  Usage:
71
- run greet <name>
72
- run (-h|--help|--version)
100
+ run hello [NAME --shout]
101
+ run (--help | -h)
102
+
103
+ Commands:
104
+ hello
105
+ Say hello
73
106
 
74
107
  Options:
75
- -h --help
76
- Show this screen
108
+ --shout, -s
109
+ Greet louder
110
+
111
+ --help, -h
112
+ Show this message
113
+ ```
77
114
 
78
- --version
79
- Show version
115
+ ## Examples
116
+
117
+ You can learn almost everything there is to know about runfile from the
118
+ [examples](https://github.com/DannyBen/runfile/tree/master/examples#readme).
119
+
120
+ You can get any of these examples directly in your terminal by running:
121
+
122
+ ```shell
123
+ $ run example --help
80
124
  ```
81
125
 
82
126
  ## Documentation
83
127
 
84
- - [User Guide](https://runfile.dannyb.co/)
85
- - [Learn by Example](https://github.com/DannyBen/runfile/tree/master/examples#readme)
128
+ For a more formal documentation, see the [User Guide](https://runfile.dannyb.co/).
86
129
 
87
- ## Breaking changes in 0.12.0
130
+ Note that the current user guide is for the stable version 0.12.0.
88
131
 
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.
132
+ ## Breaking Changes in 1.0.0
93
133
 
94
- For convenience, you can simply `require runfile/compatibility` at the top of
95
- your Runfile, to still have this functionality included.
134
+ If you are using a version earlier than 1.0, note that the upcoming release
135
+ 1.0.0 includes some breaking changes. You can read more about them in[this Pull
136
+ Request](https://github.com/DannyBen/runfile/pull/50).
96
137
 
97
- More info and alternative solutions in
98
- [this pull request](https://github.com/DannyBen/runfile/pull/46).
138
+ ### Upgrading to 1.0.0
99
139
 
100
- ## Contributing / Support
140
+ ### No more `.runfile.yml` config
141
+
142
+ If you have used the multi-runfile config file, this no longer exists.
143
+ Use a standard `runfile` instead, along with the `import` directive.
144
+
145
+ ### No more `action :global`
146
+
147
+ If you have used the `action :global do` notation, this is replaced with the
148
+ simpler use `action do` instead. Also, there is no more need for
149
+ empty `usage ''`, just delete it if you have it in your runfiles.
150
+
151
+ ### No more need for `trap(:INT)`
101
152
 
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).
153
+ If your old runfiles trap the `Interrupt` signal, there i no longer a need to
154
+ do so, as it is trapped by default.
155
+
156
+ ### Colsole is included
157
+
158
+ If your runfiles `required` and `include` Colsole, there is no longer a need to
159
+ do it. Colsole is bundled and available in actions.
160
+
161
+ ### Long flags before short flags
162
+
163
+ This is a cosmetic change for consistency. All generated output shows long flags
164
+ before short flags `--force, -f` instead of `-f, --force`. Update your custom
165
+ `usage` directives accordingly.
166
+
167
+ ### RunfileTasks
168
+
169
+ The `RunfileTasks` gem is not yet compatible. It will be later on.
170
+
171
+ ## Contributing / Support
104
172
 
173
+ If you experience any issue, have a question or a suggestion, or if you wish to
174
+ contribute, feel free to
175
+ [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,7 @@
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 args
7
+ 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'
6
+
7
+ usage 'say MESSAGE'
8
+ action 'say' do |args|
9
+ say "in main runfile, with #{args['MESSAGE']}"
10
+ 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,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