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.
- checksums.yaml +4 -4
- data/README.md +108 -37
- data/bin/runn +5 -0
- data/examples/default-action/runfile +9 -0
- data/examples/default-action-2/runfile +11 -0
- data/examples/default-action-2/server.runfile +6 -0
- data/examples/different-name/runfile.rb +8 -0
- data/examples/example/runfile +10 -0
- data/examples/example-multiline/runfile +16 -0
- data/examples/execute/runfile +14 -0
- data/examples/execute/server.runfile +11 -0
- data/examples/full/runfile +24 -0
- data/examples/import/more_tasks/spec.runfile +7 -0
- data/examples/import/runfile +10 -0
- data/examples/import/tasks/server.runfile +13 -0
- data/examples/minimal/runfile +4 -0
- data/examples/multiple-runfiles/runfile +11 -0
- data/examples/multiple-runfiles/server.runfile +13 -0
- data/examples/named-only/deploy.runfile +7 -0
- data/examples/named-only/server.runfile +11 -0
- data/examples/naval-fate/runfile +47 -0
- data/examples/shortcut/runfile +31 -0
- data/lib/runfile/action.rb +40 -14
- data/lib/runfile/concerns/dsl.rb +132 -0
- data/lib/runfile/concerns/inspectable.rb +13 -0
- data/lib/runfile/concerns/renderable.rb +16 -0
- data/lib/runfile/entrypoint.rb +50 -0
- data/lib/runfile/exceptions.rb +13 -0
- data/lib/runfile/gem_finder.rb +29 -0
- data/lib/runfile/initiator.rb +87 -0
- data/lib/runfile/meta.rb +65 -0
- data/lib/runfile/runner.rb +10 -173
- data/lib/runfile/templates/runfile +13 -0
- data/lib/runfile/userfile.rb +111 -0
- data/lib/runfile/version.rb +2 -2
- data/lib/runfile/views/initiator.gtx +28 -0
- data/lib/runfile/views/userfile.gtx +93 -0
- data/lib/runfile.rb +13 -10
- metadata +98 -24
- data/bin/run +0 -10
- data/bin/run! +0 -16
- data/lib/runfile/compatibility.rb +0 -84
- data/lib/runfile/docopt_helper.rb +0 -128
- data/lib/runfile/dsl.rb +0 -90
- data/lib/runfile/refinements.rb +0 -22
- data/lib/runfile/runfile_helper.rb +0 -165
- data/lib/runfile/settings.rb +0 -34
- data/lib/runfile/setup.rb +0 -19
- data/lib/runfile/templates/Runfile +0 -16
- data/lib/runfile/terminal.rb +0 -32
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
|
data/lib/runfile/refinements.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
module Runfile
|
2
|
-
module Refinements
|
3
|
-
refine String do
|
4
|
-
def word_wrap(length = nil)
|
5
|
-
text = self
|
6
|
-
|
7
|
-
length ||= Terminal.width
|
8
|
-
lead = text[/^\s*/]
|
9
|
-
text.strip!
|
10
|
-
length -= lead.length
|
11
|
-
text.split("\n").collect! do |line|
|
12
|
-
if line.length > length
|
13
|
-
line.gsub!(/([^\s]{#{length}})([^\s$])/, "\\1 \\2")
|
14
|
-
line.gsub(/(.{1,#{length}})(\s+|$)/, "#{lead}\\1\n").rstrip
|
15
|
-
else
|
16
|
-
"#{lead}#{line}"
|
17
|
-
end
|
18
|
-
end * "\n"
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,165 +0,0 @@
|
|
1
|
-
require 'docopt'
|
2
|
-
require 'pp'
|
3
|
-
|
4
|
-
module Runfile
|
5
|
-
|
6
|
-
# The RunfileHelper class assists in:
|
7
|
-
# 1. Finding named.runfiles
|
8
|
-
# 2. Creating new runfiles (`run new`)
|
9
|
-
# 3. Showing a list of found system runfiles in a colorful help
|
10
|
-
class RunfileHelper
|
11
|
-
using Refinements
|
12
|
-
include SettingsMixin
|
13
|
-
|
14
|
-
# Handle the case when `run` is called without a Runfile
|
15
|
-
# present. We will let the user know they can type `run new`
|
16
|
-
# to create a new sample Runfile.
|
17
|
-
# If the first argument matches the name of a *.runfile name,
|
18
|
-
# we will return it to the caller. Otherwise, we return false
|
19
|
-
# to indicate "no further handling is needed".
|
20
|
-
def handle(argv)
|
21
|
-
# make a new runfile
|
22
|
-
if argv[0] == "new" && !settings_present?
|
23
|
-
make_runfile argv[1]
|
24
|
-
return false
|
25
|
-
end
|
26
|
-
|
27
|
-
# get a list of *.runfile path-wide
|
28
|
-
runfiles = find_runfiles || []
|
29
|
-
|
30
|
-
# if first arg is a valid *.runfile, run it
|
31
|
-
if argv[0]
|
32
|
-
runfile = runfiles.select { |f| f[/\/#{argv[0]}.runfile/] }.first
|
33
|
-
runfile and return runfile
|
34
|
-
end
|
35
|
-
|
36
|
-
# if we are here, offer some help and advice and show a list
|
37
|
-
# of possible runfiles to run.
|
38
|
-
show_make_help runfiles, settings.folder
|
39
|
-
return false
|
40
|
-
end
|
41
|
-
|
42
|
-
def purge_settings
|
43
|
-
@settings = OpenStruct.new
|
44
|
-
end
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
# Create a new runfile in the current directory. We can either
|
49
|
-
# create a standard 'Runfile' or a 'named.runfile'.
|
50
|
-
def make_runfile(name=nil)
|
51
|
-
name = 'Runfile' if name.nil?
|
52
|
-
template = File.expand_path("../templates/Runfile", __FILE__)
|
53
|
-
name += ".runfile" unless name == 'Runfile'
|
54
|
-
dest = "#{Dir.pwd}/#{name}"
|
55
|
-
begin
|
56
|
-
File.write(dest, File.read(template))
|
57
|
-
puts "#{name} created."
|
58
|
-
rescue => e
|
59
|
-
abort "Failed creating #{name}\n#{e.message}"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Find all *.runfile files in our search difrectories
|
64
|
-
def find_runfiles
|
65
|
-
result = []
|
66
|
-
dirs = runfile_folders
|
67
|
-
dirs.each do |d|
|
68
|
-
found = Dir[File.join(d, '*.runfile')]
|
69
|
-
result << found unless found.empty?
|
70
|
-
end
|
71
|
-
return result.empty? ? false : result.flatten.uniq
|
72
|
-
end
|
73
|
-
|
74
|
-
# Show some helpful tips, and a list of available runfiles
|
75
|
-
def show_make_help(runfiles, compact=false)
|
76
|
-
puts "Runfile engine v#{Runfile::VERSION}" unless compact
|
77
|
-
if runfiles.size < 3 and !compact
|
78
|
-
puts "\nTip: Type 'run new' or 'run new name' to create a runfile.\nFor global access, place named.runfiles in ~/runfile/ or in /etc/runfile/."
|
79
|
-
end
|
80
|
-
if runfiles.empty?
|
81
|
-
puts "\nRunfile not found."
|
82
|
-
else
|
83
|
-
puts ""
|
84
|
-
compact ? say_runfile_usage(runfiles) : say_runfile_list(runfiles)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# Return array of folders we should search in for runfiles.
|
89
|
-
def runfile_folders
|
90
|
-
# This trick allows searching in subfolders recursively, including
|
91
|
-
# one level of symlinked folder
|
92
|
-
subdirs = '**{,/*/**}'
|
93
|
-
|
94
|
-
# If there is a '.runfile' settings file with a folder definition
|
95
|
-
# in it, use it. Otherwise, search globally.
|
96
|
-
if settings.folder
|
97
|
-
["#{settings.folder}/#{subdirs}"]
|
98
|
-
else
|
99
|
-
[Dir.pwd, "#{Dir.home}/runfile/#{subdirs}", "/etc/runfile/#{subdirs}"]
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# [UNUSED] Same as runfile_folders, but including PATH
|
104
|
-
def runfile_folders_with_path
|
105
|
-
dirs = path_dirs
|
106
|
-
dirs.insert 0, Dir.pwd, "#{Dir.home}/runfile", "/etc/runfile"
|
107
|
-
dirs
|
108
|
-
end
|
109
|
-
|
110
|
-
# Output the list of available runfiles
|
111
|
-
def say_runfile_list(runfiles)
|
112
|
-
runfile_paths = runfiles.map { |f| File.dirname f }
|
113
|
-
max = runfile_paths.max_by(&:length).size
|
114
|
-
width = Terminal.width
|
115
|
-
runfiles.each do |f|
|
116
|
-
f[/([^\/]+).runfile$/]
|
117
|
-
command = "run #{$1}"
|
118
|
-
spacer_size = width - max - command.size - 6
|
119
|
-
spacer_size = [1, spacer_size].max
|
120
|
-
spacer = '.' * spacer_size
|
121
|
-
puts " #{command} #{spacer} #{File.dirname f}"
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# Output the list of available runfiles without filename
|
126
|
-
def say_runfile_usage(runfiles)
|
127
|
-
runfiles_as_columns = get_runfiles_as_columns runfiles
|
128
|
-
|
129
|
-
puts "#{settings.intro}\n" if settings.intro
|
130
|
-
puts "Usage: run <file>"
|
131
|
-
puts runfiles_as_columns
|
132
|
-
|
133
|
-
show_shortcuts if settings.shortcuts
|
134
|
-
end
|
135
|
-
|
136
|
-
# Prints a friendly output of the shortcut list
|
137
|
-
def show_shortcuts
|
138
|
-
puts "\nShortcuts:"
|
139
|
-
max = settings.shortcuts.keys.max_by(&:length).length
|
140
|
-
settings.shortcuts.each_pair do |shortcut, command|
|
141
|
-
puts " #{shortcut.rjust max} : #{command}"
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
# Returns the list of runfiles, organized as columns based on the
|
146
|
-
# current terminal width
|
147
|
-
def get_runfiles_as_columns(runfiles)
|
148
|
-
namelist = runfile_names runfiles
|
149
|
-
width = Terminal.width
|
150
|
-
max = namelist.max_by(&:length).length
|
151
|
-
message = " " + namelist.map {|f| f.ljust max+1 }.join(' ')
|
152
|
-
message.word_wrap width
|
153
|
-
end
|
154
|
-
|
155
|
-
def runfile_names(runfiles)
|
156
|
-
runfiles.map {|f| /([^\/]+).runfile$/.match(f)[1] }.sort
|
157
|
-
end
|
158
|
-
|
159
|
-
# Returns an array of path directories
|
160
|
-
def path_dirs
|
161
|
-
ENV['PATH'].split(File::PATH_SEPARATOR)
|
162
|
-
end
|
163
|
-
|
164
|
-
end
|
165
|
-
end
|
data/lib/runfile/settings.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
module Runfile
|
5
|
-
|
6
|
-
# The Settings class handles '.runfile' YAML config files.
|
7
|
-
# If found in the current directory, we will use their content.
|
8
|
-
class Settings
|
9
|
-
def as_struct
|
10
|
-
OpenStruct.new settings
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def settings
|
16
|
-
@settings ||= settings!
|
17
|
-
end
|
18
|
-
|
19
|
-
def settings!
|
20
|
-
File.file?('.runfile') ? YAML.load_file('.runfile') : {}
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
module SettingsMixin
|
25
|
-
def settings
|
26
|
-
@settings ||= Settings.new.as_struct
|
27
|
-
end
|
28
|
-
|
29
|
-
def settings_present?
|
30
|
-
File.file?('.runfile')
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
data/lib/runfile/setup.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
module Runfile
|
2
|
-
class << self
|
3
|
-
# Set the directory where PID files are stored when using `run_bg`
|
4
|
-
# Runfile.pid_dir = 'tmp'
|
5
|
-
attr_accessor :pid_dir
|
6
|
-
|
7
|
-
# Disable echoing of the command when using `run` or `run!`
|
8
|
-
# Runfile.quiet = true
|
9
|
-
attr_accessor :quiet
|
10
|
-
|
11
|
-
# You can also configure Runfile by providing a block:
|
12
|
-
# Runfile.setup do |config|
|
13
|
-
# config.quiet = true
|
14
|
-
# end
|
15
|
-
def setup
|
16
|
-
yield self
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
title "Greeter"
|
2
|
-
summary "A sample Runfile"
|
3
|
-
version "0.1.0"
|
4
|
-
|
5
|
-
usage "hello [<name> --shout]"
|
6
|
-
help "Say hello"
|
7
|
-
option "-s --shout", "Greet louder"
|
8
|
-
action :hello do |args|
|
9
|
-
message = "Hello #{args['<name>']}"
|
10
|
-
|
11
|
-
if args['--shout']
|
12
|
-
puts message.upcase
|
13
|
-
else
|
14
|
-
puts message
|
15
|
-
end
|
16
|
-
end
|
data/lib/runfile/terminal.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# This file provides some terminal related utilities (extracted from Colsole)
|
2
|
-
|
3
|
-
module Runfile
|
4
|
-
class Terminal
|
5
|
-
class << self
|
6
|
-
def size(default = [80,30])
|
7
|
-
if (ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/)
|
8
|
-
result = [ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
|
9
|
-
elsif (RUBY_PLATFORM =~ /java/ || (!STDIN.tty? && ENV['TERM'])) && command_exist?('tput')
|
10
|
-
result = [`tput cols 2>&1`.to_i, `tput lines 2>&1`.to_i]
|
11
|
-
elsif STDIN.tty? && command_exist?('stty')
|
12
|
-
result = `stty size 2>&1`.scan(/\d+/).map { |s| s.to_i }.reverse
|
13
|
-
else
|
14
|
-
result = default
|
15
|
-
end
|
16
|
-
result = default unless result[0].is_a? Integer and result[1].is_a? Integer and result[0] > 0 and result[1] > 0
|
17
|
-
result
|
18
|
-
end
|
19
|
-
|
20
|
-
def width
|
21
|
-
size[0]
|
22
|
-
end
|
23
|
-
|
24
|
-
def command_exist?(command)
|
25
|
-
ENV['PATH'].split(File::PATH_SEPARATOR).any? do |dir|
|
26
|
-
File.exist?(File.join dir, command) or File.exist?(File.join dir, "#{command}.exe")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|