Benry-ActionRunner
($Release: 0.1.0 $)
What's this?
Benry-ActionRunner is a task runner.
Similar to Rake, but much improved over Rake.
The main feature of Benry-ActionRunner compared to Rake is that each actions can take options and arguments.
For example, arun hello -l fr Alice
runs hello
action with an option -l fr
and an argument Alice
.
(Benry-ActionRunner requires Ruby >= 2.3)
Table of Contents
Install
$ gem install benry-actionrunner
$ arun --version
1.0.0
Example
[bash]$ arun -h | less
[bash]$ arun -g
[bash]$ less Actionfile.rb
[bash]$ arun
[bash]$ arun -h hello
[bash]$ arun hello Alice
Hello, Alice!
[bash]$ arun hello Alice -l fr
Bonjour, Alice!
[bash]$ arun xxxx:
[bash]$ arun :
Basic Features
Action
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class MyAction < Action
@action.("print greeting message")
def hello()
puts "Hello, world!"
end
end
Output:
[bash]$ ls Actionfile.rb
Actionfile.rb
[bash]$ arun hello
Hello, world!
It is not allowed to override existing method by action method.
For example, you can't define print()
or test()
method as action method
because these methods are defined in parent or ancestor class.
In this case, please rename action methods to print_()
or test_()
.
These action methods are treated as action name print
or test
.
Arguments
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class MyAction < Action
@action.("print greeting message")
def hello(name="world")
puts "Hello, #{name}!"
end
end
Output:
[bash]$ arun hello Alice
Hello, Alice!
Arguments are displayed in help message of actions.
[bash]$ arun -h hello
arun hello --- print greeting message
Usage:
$ arun hello [<options>] [<name>]
Options
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class MyAction < Action
@action.("print greeting message")
@option.(:lang, "-l, --lang=<lang>", "language (en/fr/it)")
@option.(:repeat, "-n <N>", "repeat N times")
def hello(name="world", lang: "en", repeat: 1)
repeat.times do
case lang
when "en" ; puts "Hello, #{name}!"
when "fr" ; puts "Bonjour, #{name}!"
when "it" ; puts "Chao, #{name}!"
else ; raise "#{lang}: Unknown language."
end
end
end
end
Output:
[bash]$ arun hello -l fr Alice
Bonjour, Alice!
[bash]$ arun hello --lang=it Alice
Chao, Alice!
Available option formats:
- No arguments
-h
--- short--help
--- long-h, --help
--- both
- Argument required
-f <file>
--- short--file=<file>
--- long-f, --file=<file>
--- both
- Optional argument
-i[<width>]
--- short--indent[=<width>]
--- long-i, --indent[=<width>]
--- both
Notice: --lang it
style option is not supported for usability reason.
Use --lang=it
style instead.
Validation for Option Value
Keyword arguments of @option.()
:
type: Integer
--- Option value should be an integer.- `rexp: /^\d+$/ --- Option value should match to pattern.
enum: ["A", "B", "C"]
--- Option value should be one of "A", "B", or "C".- `range: 1..10 --- Option value should be between 1 and 10.
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class MyAction < Action
@action.("print greeting message")
@option.(:lang, "-l, --lang=<lang>", "language", enum: ["en", "fr", "it"])
@option.(:repeat, "-n <N>", "repeat N times", type: Integer, range: 1..5)
def hello(name="world", lang: "en", repeat: 1)
repeat.times do
case lang
when "en" ; puts "Hello, #{name}!"
when "fr" ; puts "Bonjour, #{name}!"
when "it" ; puts "Chao, #{name}!"
else ; raise "#{lang}: Unknown language."
end
end
end
end
Output:
[bash]$ arun hello -l po Alice
[ERROR] -l po: Expected one of en/fr/it.
[bash]$ arun hello -n 99 Alice
[ERROR] -n 99: Too large (max: 5)
Boolean Option
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class MyAction < Action
@action.("print greeting message")
@option.(:lang, "-l, --lang=<lang>", "language", enum: ["en", "fr", "it"])
@option.(:repeat, "-n <N>", "repeat N times", type: Integer, range: 1..5)
@option.(:color, "-c, --color[=<on|off>]", "color mode", type: TrueClass)
def hello(name="world", lang: "en", repeat: 1, color: false)
if color
name = "\e[32m#{name}\e[0m"
end
repeat.times do
case lang
when "en" ; puts "Hello, #{name}!"
when "fr" ; puts "Bonjour, #{name}!"
when "it" ; puts "Chao, #{name}!"
else ; raise "#{lang}: Unknown language."
end
end
end
end
Output:
[bash]$ arun hello --color=on Alice
Hello, Alice! # displayed with color
[bash]$ arun hello --color Alice
Hello, Alice! # displayed with color
Prefix of Actions
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class GitAction < Action
prefix "git:"
@action.("show current status in compact format")
def status(path=".")
sys "git status -sb #{path}"
end
end
Output:
[bash]$ arun -l
Actions:
git:status : show current status in compact format
help : print help message (of action if specified)
[bash]$ arun git:status
$ git status -sb .
Prefix name should be a string which ends with ":".
Symbol is not avaiable.
class GitAction < Action
prefix :git
Nested Prefix
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class GitAction < Action
prefix "git:" do
prefix "commit:" do
@action.("create a commit of current changes")
def create(msg); sys "git commit -m '#{msg}'"; end
end
prefix "branch:" do
@action.("create a new branch")
def create(name); sys "git checkout -b #{name}" ; end
@action.("switch current branch")
def switch(name); sys "git checkout #{name}"; end
end
end
end
Output:
[bash]$ arun -l
Actions:
git:branch:create : create a new branch
git:branch:switch : switch current branch
git:commit:create : create a commit of current changes
help : print help message (of action if specified)
Alias of Action
Alias is a shortcut of action.
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class GitAction < Action
prefix "git:" do
prefix "commit:" do
@action.("create a commit of current changes")
def create(msg); sys "git commit -m '#{msg}'"; end
end
prefix "branch:" do
@action.("create a new branch")
def create(name); sys "git checkout -b #{name}" ; end
@action.("switch current branch")
def switch(name); sys "git checkout #{name}"; end
end
end
end
define_alias "ci" , "git:commit:create"
define_alias "fork" , "git:branch:create"
define_alias "sw" , "git:branch:switch"
Output:
[bash]$ arun -l
Actions:
ci : alias of 'git:commit:create'
fork : alias of 'git:branch:create'
git:branch:create : create a new branch
git:branch:switch : switch current branch
git:commit:create : create a commit of current changes
help : print help message (of action if specified)
sw : alias of 'git:branch:switch'
[bash]$ arun fork topic-foo
[bash]$ arun sw topic-foo
Alias definition can include options and arguments.
For example, define_alias "correct", ["git:commit", "--amend"]
defines an alias correct
which invokes git:commit
action with --amend
option.
Prefix Action and Prefix Alias
Rename git:status
action to git
(= prefix name):
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class GitAction < Action
prefix "git:", action: "status"
@action.("show current status in compact format")
def status(path=".")
sys "git status -sb #{path}"
end
end
Output: (git:status
is renamed to git
)
[bash]$ arun -l
Actions:
git : show current status in compact format
help : print help message (of action if specified)
Define an alias of git:status
task as git
(= prefix name):
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class GitAction < Action
prefix "git:", alias_of: "status"
@action.("show current status in compact format")
def status(path=".")
sys "git status -sb #{path}"
end
end
Output: (git
is an alias of git:status
)
[bash]$ arun -l
Actions:
git : alias of 'git:status'
git:status : show current status in compact format
help : print help message (of action if specified)
Prerequisite Action
Prerequisite Action is not supported.
Instead, use run_once()
which invokes other action only once.
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
class BuildAction < Action
@action.("setup something")
def setup()
puts ".... setup ...."
at_end {
puts ".... teardown ...."
}
end
@action.("build something")
def build()
run_once "setup"
run_once "setup"
puts ".... build ...."
end
end
Output:
[bash]$ arun build
.... setup ....
.... build ....
.... teardown ....
Global Variable
Global long option such as --release=1.2.3
is recognized as global variable name and value.
File: Actionfile.rb
require 'benry/actionrunner'
include Benry::ActionRunner::Export
$project = "exmaple"
$release = "1.0.0"
class MyAction < Action
@action.("show global variables")
def gvars()
puts "$project=#{$project.inspect}, $release=#{$release.inspect}"
end
end
Output:
[bash]$ arun --project=myapp --release=1.2.3 gvars
$project="myapp", $release="1.2.3"
Debug option -D
prints global variables specified in commiand-line.
This is useful to debug values of global variables.
[bash]$ arun -l -D --project=myapp --release=1.2.3
[DEBUG] $project = "myapp"
[DEBUG] $release = "1.2.3"
Actions:
gvars : show global variables
help : print help message (of action if specified)
Values of global variables in command-line are parsed as JSON string.
If failed to parse as JSON string, it is handled as string value.
#
[bash]$ arun -l -D --data='["abc",123,true]' | grep DEBUG
[DEBUG] $data = ["abc", 123, true]
#
[bash]$ arun -l -D --data="null" | grep DEBUG
[DEBUG] $data = nil
#
[bash]$ arun -l -D --data='"foo"' | grep DEBUG
[DEBUG] $data = "foo"
#
[bash]$ arun -l -D --data="'foo'" | grep DEBUG
[DEBUG] $data = "'foo'"
#
[bash]$ arun -l -D --data="foo" | grep DEBUG
[DEBUG] $data = "foo"
Available Commands
In action methods, UNIX-like commands are available.
These commands are implemented in Benry-UnixCommand and different from FileUtils.rb.
For example:
mv "*.txt", to: "dir"
instead of mv Dir["*.txt"], "dir"
.cp :p, "*.txt", to: "dir"
instead of cp_p Dir["*.txt"], "dir"
.rm :rf, "dir/*"
instead of rm_rf Dir["dir/*"]
.mkdir :p, "dir"
instead of mkdir_p "dir"
.sys "command"
instead of sh "command"
or system "command"
.
See the document of Benry-UnixCommand for details:
https://kwatch.github.io/benry-ruby/benry-unixcommand.html
More Features
Search Actionfile in Parent or Higher Directory
In contrast to Rake, Benry-ActionRunner doesn't automatically look for action file in the parent or higher directory (this is for security reason).
If you want Benry-ActionRunner to behave like Rake, add -u
and -w
options.
-u
--- search for action file in parent or upper directory.-w
--- change current directory to where action file exists.
If you want to add these options always, set environment variable $ACTIONRUNNER_OPTION
.
[bash]$ ls Actionfile.rb
Actionfile.rb
[bash]$ mkdir -p foo/bar/
[bash]$ cd foo/bar/
[bash]$ arun -l
[ERROR] Action file ('Actionfile.rb') not found. Create it by `arun -g` command firstly.
[bash]$ arun -l -wu
Actions:
hello : print greeting message
help : print help message (of action if specified)
[bash]$ export ACTIONRUNNER_OPTION="-up"
[bash]$ arun -l
$ cd ../..
Actions:
build : build something
help : print help message (of action if specified)
setup : setup something
Hidden Action, Alias or Option
It is possible to make visibility of actions/aliases/options as hidden.
@action.("preparation", hidden: true)
@option.(:debug, "--debug", "enable debug mode", hidden: true)
def preparation()
....
end
define_alias "prep", "preparation", hidden: true
Hidden actions and options are not displayed in help message.
If you want to display hidden actions or options, add -a
or --all
option.
[bash]$ arun -la
[bash]$ arun -la hello
Important Action, Alias or Option
It is possible to mark actions/aliases/options as important or not.
- Actions/aliases/options marked as important are displayed in bold font in help message.
- Actions/aliases/options marked as not important are displayed in gray color in help message.
@action.("print greeting message", important: true)
@option.(:lang, "-l, --lang=<lang>", "language", important: true)
@option.(:repeat, "--repeat=<N>", "repeat N times", important: false)
def hello(name="world", lang: "en", repeat: 1)
end
define_alias "hi", "hello", important: false
Delete Action/Alias
undef_alias("fork")
undef_action("git:branch:create")
Default Action
CONFIG.default_action = "xxxx"
More Topics
Benry-ActionRunner is empowerd by Benry-CmdApp.
Many features of Benry-ActionRunner is derived from Benry-CmdApp.
If you are looking for any features not written in this document,
see the document of Benry-CmdApp framework:
https://kwatch.github.io/benry-ruby/benry-cmdapp.html
License and Copyright
$License: MIT License $
$Copyright: copyright(c) 2023 kwatch@gmail.com $