runfile 0.12.0.pre.rc1 → 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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +112 -28
  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 +96 -21
  40. data/bin/run +0 -10
  41. data/bin/run! +0 -16
  42. data/lib/runfile/docopt_helper.rb +0 -128
  43. data/lib/runfile/dsl.rb +0 -90
  44. data/lib/runfile/refinements.rb +0 -22
  45. data/lib/runfile/runfile_helper.rb +0 -165
  46. data/lib/runfile/settings.rb +0 -34
  47. data/lib/runfile/setup.rb +0 -19
  48. data/lib/runfile/templates/Runfile +0 -16
  49. data/lib/runfile/terminal.rb +0 -32
@@ -0,0 +1,111 @@
1
+ require 'shellwords'
2
+
3
+ module Runfile
4
+ # Represents a single runfile.
5
+ class Userfile
6
+ include Renderable
7
+ include Inspectable
8
+ include DSL
9
+
10
+ attr_reader :code, :name, :path
11
+ attr_writer :context
12
+ alias action_prefix name
13
+
14
+ class << self
15
+ def load_file(path)
16
+ if masterfile? path
17
+ name = nil
18
+ else
19
+ name = File.basename path, '.runfile'
20
+ path = "#{path}.runfile" unless path.end_with? '.runfile'
21
+ end
22
+
23
+ code = File.read path
24
+ new code, name: name, path: path
25
+ end
26
+
27
+ def masterfile?(path)
28
+ Meta::MASTERFILE_NAMES.include? path
29
+ end
30
+ end
31
+
32
+ def initialize(code = nil, name: nil, path: nil)
33
+ @code = code
34
+ @name = name
35
+ @path = path
36
+
37
+ return unless @code
38
+
39
+ if path
40
+ instance_eval @code, @path
41
+ else
42
+ instance_eval @code
43
+ end
44
+ end
45
+
46
+ def inspectable
47
+ { name: name, path: path }
48
+ end
49
+
50
+ def run(argv = [])
51
+ found_delegate = delegate argv[0]
52
+ if found_delegate
53
+ found_delegate.run argv
54
+ else
55
+ run_local argv
56
+ end
57
+ end
58
+
59
+ def context
60
+ @context ||= {}
61
+ end
62
+
63
+ def implicit_title
64
+ title || name
65
+ end
66
+
67
+ # Returns an array of actions that have help defined
68
+ def commands
69
+ actions.values.select(&:help)
70
+ end
71
+
72
+ def delegates
73
+ @delegates ||= (name ? {} : meta.external_files)
74
+ end
75
+
76
+ private
77
+
78
+ def find_action(args)
79
+ acts = actions.values
80
+ acts.find { |a| args[a.name] } ||
81
+ acts.find { |a| args[a.shortcut] } ||
82
+ acts.find { |a| args[a.prefix] } ||
83
+ actions[:default]
84
+ end
85
+
86
+ def run_local(argv)
87
+ Runner.run docopt, argv: argv, version: version do |args|
88
+ action = find_action(args)
89
+ raise ActionNotFound, 'Cannot find action. Is it properly defined?' unless action
90
+
91
+ action.run args
92
+ end
93
+ end
94
+
95
+ def delegate(name)
96
+ return nil unless delegates.has_key? name
97
+
98
+ result = delegates[name]
99
+ result.context = contexts[name]
100
+ result
101
+ end
102
+
103
+ def meta
104
+ @meta ||= Meta.new
105
+ end
106
+
107
+ def docopt
108
+ @docopt ||= render 'userfile', context: self
109
+ end
110
+ end
111
+ end
@@ -1,3 +1,3 @@
1
1
  module Runfile
2
- VERSION = "0.12.0-rc1"
3
- end
2
+ VERSION = '1.0.0.rc1'
3
+ end
@@ -0,0 +1,28 @@
1
+ > Runfile
2
+ >
3
+ > Local command line for your projects
4
+ >
5
+ > Usage:
6
+ > run new
7
+ > run example [NAME]
8
+ > run --help | -h
9
+ > run --version
10
+ >
11
+ > Commands:
12
+ > nb`new`
13
+ > Create a new runfile in the current directory
14
+ >
15
+ > nb`example`
16
+ > Copy one of the examples to the current directory
17
+ > Run without arguments to see the list of examples
18
+ >
19
+ > Options:
20
+ > --help, -h
21
+ > Show this message
22
+ >
23
+ > --version
24
+ > Show version number
25
+ >
26
+ > Documentation:
27
+ > bu`https://runfile.dannyb.co`
28
+ >
@@ -0,0 +1,93 @@
1
+ if implicit_title
2
+ = implicit_title
3
+ >
4
+ end
5
+
6
+ if summary
7
+ = implicit_title ? word_wrap(" #{summary}") : word_wrap(summary)
8
+ >
9
+ end
10
+
11
+ > Usage:
12
+ actions.each do |name, action|
13
+ action.implicit_usages.each do |usage|
14
+ = " run #{usage}".rstrip
15
+ end
16
+ end
17
+
18
+ delegates.keys.each do |name|
19
+ = " run #{name}"
20
+ end
21
+
22
+ if delegates.any?
23
+ > run [COMMAND] (--help | -h)
24
+ elsif name
25
+ > run {{ name }} (--help | -h)
26
+ else
27
+ > run (--help | -h)
28
+ end
29
+
30
+ if version
31
+ > run --version
32
+ end
33
+ >
34
+
35
+ if commands.any? || delegates.any?
36
+ > Commands:
37
+ commands.each do |action|
38
+ = " nb`#{action.names.join(', ')}`"
39
+ = word_wrap " #{action.help}"
40
+ >
41
+ end
42
+
43
+ delegates.each do |name, userfile|
44
+ summary = userfile.summary || userfile.title ||
45
+ "Run nu`run #{name} --help` for more information"
46
+
47
+ = " nb`#{name}`"
48
+ = word_wrap " #{summary}"
49
+ >
50
+ end
51
+ end
52
+
53
+ if params.any?
54
+ > Parameters:
55
+ params.each do |name, help|
56
+ = " #{name}"
57
+ = word_wrap " #{help}"
58
+ >
59
+ end
60
+ end
61
+
62
+ > Options:
63
+ options.each do |name, help|
64
+ = " #{name}"
65
+ = word_wrap " #{help}"
66
+ >
67
+ end
68
+ > --help, -h
69
+ > Show this message
70
+ >
71
+ if version
72
+ > --version
73
+ > Show version number
74
+ >
75
+ end
76
+
77
+ if env_vars.any?
78
+ > Environment Variables:
79
+ env_vars.each do |name, help|
80
+ = " #{name}"
81
+ = word_wrap " #{help}"
82
+ end
83
+ >
84
+ end
85
+
86
+
87
+ if examples.any?
88
+ > Examples:
89
+ examples.each do |text|
90
+ = word_wrap " #{text}"
91
+ end
92
+ >
93
+ end
data/lib/runfile.rb CHANGED
@@ -1,10 +1,13 @@
1
- require 'runfile/version'
2
- require 'runfile/terminal'
3
- require 'runfile/refinements'
4
- require 'runfile/settings'
5
- require 'runfile/setup'
6
- require 'runfile/docopt_helper'
7
- require 'runfile/runfile_helper'
8
- require 'runfile/action'
9
- require 'runfile/runner'
10
- require 'runfile/dsl'
1
+ require 'gtx'
2
+ require 'docopt'
3
+ require 'colsole'
4
+ require 'requires'
5
+
6
+ requires 'runfile/exceptions'
7
+ requires 'runfile/concerns'
8
+ requires 'runfile'
9
+
10
+ if ENV['BYEBUG']
11
+ require 'byebug'
12
+ require 'lp'
13
+ end
metadata CHANGED
@@ -1,53 +1,127 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: runfile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0.pre.rc1
4
+ version: 1.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-28 00:00:00.000000000 Z
11
+ date: 2023-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colsole
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.8.2
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.8.2
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
13
33
  - !ruby/object:Gem::Dependency
14
34
  name: docopt
15
35
  requirement: !ruby/object:Gem::Requirement
16
36
  requirements:
17
37
  - - "~>"
18
38
  - !ruby/object:Gem::Version
19
- version: '0.5'
39
+ version: '0.6'
20
40
  type: :runtime
21
41
  prerelease: false
22
42
  version_requirements: !ruby/object:Gem::Requirement
23
43
  requirements:
24
44
  - - "~>"
25
45
  - !ruby/object:Gem::Version
26
- version: '0.5'
27
- description: Build command line applications per project with ease. Rake-inspired,
28
- Docopt inside.
46
+ version: '0.6'
47
+ - !ruby/object:Gem::Dependency
48
+ name: gtx
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.1'
61
+ - !ruby/object:Gem::Dependency
62
+ name: requires
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0.2'
68
+ - - "<"
69
+ - !ruby/object:Gem::Version
70
+ version: '2.0'
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0.2'
78
+ - - "<"
79
+ - !ruby/object:Gem::Version
80
+ version: '2.0'
81
+ description: Build expressive command line utilities for your projects.
29
82
  email: db@dannyben.com
30
83
  executables:
31
- - run
32
- - run!
84
+ - runn
33
85
  extensions: []
34
86
  extra_rdoc_files: []
35
87
  files:
36
88
  - README.md
37
- - bin/run
38
- - bin/run!
89
+ - bin/runn
90
+ - examples/default-action-2/runfile
91
+ - examples/default-action-2/server.runfile
92
+ - examples/default-action/runfile
93
+ - examples/different-name/runfile.rb
94
+ - examples/example-multiline/runfile
95
+ - examples/example/runfile
96
+ - examples/execute/runfile
97
+ - examples/execute/server.runfile
98
+ - examples/full/runfile
99
+ - examples/import/more_tasks/spec.runfile
100
+ - examples/import/runfile
101
+ - examples/import/tasks/server.runfile
102
+ - examples/minimal/runfile
103
+ - examples/multiple-runfiles/runfile
104
+ - examples/multiple-runfiles/server.runfile
105
+ - examples/named-only/deploy.runfile
106
+ - examples/named-only/server.runfile
107
+ - examples/naval-fate/runfile
108
+ - examples/shortcut/runfile
39
109
  - lib/runfile.rb
40
110
  - lib/runfile/action.rb
41
- - lib/runfile/docopt_helper.rb
42
- - lib/runfile/dsl.rb
43
- - lib/runfile/refinements.rb
44
- - lib/runfile/runfile_helper.rb
111
+ - lib/runfile/concerns/dsl.rb
112
+ - lib/runfile/concerns/inspectable.rb
113
+ - lib/runfile/concerns/renderable.rb
114
+ - lib/runfile/entrypoint.rb
115
+ - lib/runfile/exceptions.rb
116
+ - lib/runfile/gem_finder.rb
117
+ - lib/runfile/initiator.rb
118
+ - lib/runfile/meta.rb
45
119
  - lib/runfile/runner.rb
46
- - lib/runfile/settings.rb
47
- - lib/runfile/setup.rb
48
- - lib/runfile/templates/Runfile
49
- - lib/runfile/terminal.rb
120
+ - lib/runfile/templates/runfile
121
+ - lib/runfile/userfile.rb
50
122
  - lib/runfile/version.rb
123
+ - lib/runfile/views/initiator.gtx
124
+ - lib/runfile/views/userfile.gtx
51
125
  homepage: https://github.com/DannyBen/runfile
52
126
  licenses:
53
127
  - MIT
@@ -56,6 +130,7 @@ metadata:
56
130
  changelog_uri: https://github.com/DannyBen/runfile/blob/master/CHANGELOG.md
57
131
  source_code_uri: https://github.com/DannyBen/runfile
58
132
  bug_tracker_uri: https://github.com/DannyBen/runfile/issues
133
+ rubygems_mfa_required: 'true'
59
134
  post_install_message:
60
135
  rdoc_options: []
61
136
  require_paths:
@@ -64,15 +139,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
64
139
  requirements:
65
140
  - - ">="
66
141
  - !ruby/object:Gem::Version
67
- version: 2.4.0
142
+ version: '2.7'
68
143
  required_rubygems_version: !ruby/object:Gem::Requirement
69
144
  requirements:
70
145
  - - ">"
71
146
  - !ruby/object:Gem::Version
72
147
  version: 1.3.1
73
148
  requirements: []
74
- rubygems_version: 3.2.25
149
+ rubygems_version: 3.4.5
75
150
  signing_key:
76
151
  specification_version: 4
77
- summary: If Rake and Docopt had a baby
152
+ summary: Local command line for your projects
78
153
  test_files: []
data/bin/run DELETED
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'runfile'
4
-
5
- # for dev
6
- # require File.dirname(__FILE__) + "/../lib/runfile"
7
-
8
- include Runfile::DSL
9
-
10
- Runfile::Runner.instance.execute ARGV
data/bin/run! DELETED
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- # This is needed in cases when you are running "run!" from a folder
4
- # that contains a Gemfile on a machine with RVM.
5
- # It will disable attempting to run in the current context
6
- # Source: https://rvm.io/integration/bundler
7
- ENV['NOEXEC_DISABLE'] = '1'
8
-
9
- require 'runfile'
10
-
11
- # for dev
12
- # require File.dirname(__FILE__) + "/../lib/runfile"
13
-
14
- include Runfile::DSL
15
-
16
- Runfile::Runner.instance.execute ARGV, false
@@ -1,128 +0,0 @@
1
- require 'docopt'
2
-
3
- module Runfile
4
- # The DocoptHelper class handles the dynamic generation of the
5
- # docopt document and the docopt part of the execution (meaning,
6
- # to call Docopt so it returns the parsed arguments or halts with
7
- # usage message).
8
- class DocoptHelper
9
- using Refinements
10
-
11
- # The constructor expects to an object that responds to all the
12
- # textual details needed to generate a docopt document (name, version,
13
- # summary, options) and an array of Action objects.
14
- # The superspace argument will be the name of runfile, in case we
15
- # are running a named.runfile. It is only needed to generate the
16
- # proper `run superspace (-h|--help|--version)` line
17
- def initialize(options)
18
- @superspace = options.superspace
19
- @name = options.name
20
- @version = options.version
21
- @summary = options.summary
22
- @actions = options.actions
23
- @options = options.options
24
- @params = options.params
25
- @env_vars = options.env_vars
26
- @examples = options.examples
27
- end
28
-
29
- # Generate a document based on all the actions, help messages
30
- # and options we have collected from the Runfile DSL.
31
- def docopt
32
- width = Terminal.width
33
- doc = []
34
- doc << (@version ? "#{@name} #{@version}" : "#{@name}")
35
- doc << "#{@summary}" if @summary
36
- doc += docopt_usage
37
- doc += docopt_commands width
38
- doc += docopt_options width
39
- doc += docopt_params width
40
- doc += docopt_env_vars width
41
- doc += docopt_examples width
42
- doc.join "\n"
43
- end
44
-
45
- # Return all docopt lines for the 'Usage' section
46
- def docopt_usage
47
- doc = ["\nUsage:"];
48
- @actions.each do |_name, action|
49
- doc << " run #{action.usage}" unless action.usage == false
50
- end
51
- basic_flags = @version ? "(-h|--help|--version)" : "(-h|--help)"
52
- if @superspace
53
- doc << " run #{@superspace} #{basic_flags}\n"
54
- else
55
- doc << " run #{basic_flags}\n"
56
- end
57
- doc
58
- end
59
-
60
- # Return all docopt lines for the 'Commands' section
61
- def docopt_commands(width)
62
- doc = []
63
- caption_printed = false
64
- @actions.each do |_name, action|
65
- action.help or next
66
- doc << "Commands:" unless caption_printed
67
- caption_printed = true
68
- helpline = " #{action.help}"
69
- wrapped = helpline.word_wrap width
70
- doc << " #{action.usage}\n#{wrapped}\n" unless action.usage == false
71
- end
72
- doc
73
- end
74
-
75
- # Return all docopt lines for the various 'Options' sections
76
- def docopt_options(width)
77
- @options['Options'] = {} unless @options['Options']
78
- @options['Options']['-h --help'] = 'Show this screen'
79
- @options['Options']['--version'] = 'Show version number' if @version
80
- section_block @options, width
81
- end
82
-
83
- # Return all docopt params for 'Params' section
84
- def docopt_params(width)
85
- section_block @params, width
86
- end
87
-
88
- # Return all docopt params for 'Environment Variables' section
89
- def docopt_env_vars(width)
90
- section_block @env_vars, width
91
- end
92
-
93
- # Return all docopt lines for the 'Examples' section
94
- def docopt_examples(width)
95
- return [] if @examples.empty?
96
-
97
- doc = ["Examples:"]
98
- base_command = @superspace ? "run #{@superspace}" : "run"
99
- @examples.each do |command|
100
- helpline = " #{base_command} #{command}"
101
- wrapped = helpline.word_wrap width
102
- doc << "#{wrapped}"
103
- end
104
- doc
105
- end
106
-
107
- # Return a generic block containing scope section (e.g. "Options"),
108
- # followed by key value paragraphs.
109
- def section_block(definitions, width)
110
- doc = []
111
- definitions.each do |scope, values|
112
- doc << "#{scope}:"
113
- values.each do |label, text|
114
- helpline = " #{text}"
115
- wrapped = helpline.word_wrap width
116
- doc << " #{label}\n#{wrapped}\n"
117
- end
118
- end
119
- doc
120
- end
121
-
122
- # Call the docopt handler, which will either return a parsed
123
- # arguments list, or halt execution and show usage.
124
- def args(argv)
125
- Docopt.docopt(docopt, version: @version, argv:argv)
126
- end
127
- end
128
- end
data/lib/runfile/dsl.rb DELETED
@@ -1,90 +0,0 @@
1
- # This file defines all the commands supported in a Runfile.
2
- # All commands are immediately handed over to the Runner instance
3
- # for handling.
4
-
5
- module Runfile
6
- module DSL
7
- private
8
-
9
- # Set the name of your Runfile program
10
- # title 'My Runfile'
11
- def title(name)
12
- Runner.instance.name = name
13
- end
14
-
15
- # Set the version of your Runfile program
16
- # version '0.1.0'
17
- def version(ver)
18
- Runner.instance.version = ver
19
- end
20
-
21
- # Set the one line summary of your Runfile program
22
- # summary 'Utilities for my server'
23
- def summary(text)
24
- Runner.instance.summary = text
25
- end
26
-
27
- # Set the usage pattern for the next action
28
- # usage 'server [--background]'
29
- def usage(text)
30
- Runner.instance.last_usage = text
31
- end
32
-
33
- # Set the help message for the next action
34
- # help 'Starts the server in the foreground or background'
35
- def help(text)
36
- Runner.instance.last_help = text
37
- end
38
-
39
- # Add an option/flag to the next action (can be called multiple
40
- # times)
41
- # option '-b --background', 'Start in the background'
42
- def option(flag, text, scope=nil)
43
- Runner.instance.add_option flag, text, scope
44
- end
45
-
46
- # Add a parameter (can be called multiple times)
47
- # param 'FOLDER', 'Folder to copy'
48
- def param(name, text, scope=nil)
49
- Runner.instance.add_param name, text, scope
50
- end
51
-
52
- # Set an environment variable (can be called multiple times)
53
- # env_var 'USER', 'Set the user (same as --user)'
54
- def env_var(name, text, scope = nil)
55
- Runner.instance.add_env_var name, text, scope
56
- end
57
-
58
- # Set an example command (can be called multiple times)
59
- # example 'server --background'
60
- def example(text)
61
- Runner.instance.add_example text
62
- end
63
-
64
- # Define the action
65
- # action :server do |args|
66
- # run 'rails server'
67
- # end
68
- def action(name, altname=nil, &block)
69
- Runner.instance.add_action name, altname, &block
70
- end
71
-
72
- # Define a new command namespace
73
- # command 'server'
74
- # # ... define actions here
75
- # endcommand
76
- def command(name=nil)
77
- Runner.instance.namespace = name
78
- end
79
-
80
- # Cross-call another action
81
- # execute 'other_action'
82
- def execute(command_string)
83
- Runner.instance.cross_call command_string
84
- end
85
-
86
- # Also allow to use 'endcommand' instead of 'command' to end
87
- # a command namespace definition
88
- alias_method :endcommand, :command
89
- end
90
- end