Module: Rake::ToolkitProgram
- Extended by:
- DSL
- Defined in:
- lib/rake/toolkit_program.rb,
lib/rake/toolkit_program/help.rb,
lib/rake/toolkit_program/utils.rb,
lib/rake/toolkit_program/errors.rb,
lib/rake/toolkit_program/version.rb,
lib/rake/toolkit_program/task_ext.rb,
lib/rake/toolkit_program/completion.rb,
lib/rake/toolkit_program/help_styling.rb,
lib/rake/toolkit_program/command_option_parser.rb
Overview
Tools to easily build CLI programs for UNIX-like systems
In addition to any commands defined, this module provides:
-
a
--install-completionscommand -
a
helpcommand -
-hand--helpflags (until--is encountered)
Use .command_tasks to define commands and .run to execute the CLI.
Defined Under Namespace
Modules: ArgParsingTask, RangeConversion, ShellwordsExt, TaskExt Classes: CommandOptionParser, HelpStyling, InvalidCommandLine, NoCommand, UnknownName, WrongArgumentCount
Constant Summary collapse
- NAMESPACE =
"cli_cmd"- VERSION =
"0.1.1"
Class Method Summary collapse
- .args ⇒ Object
- .available_commands(include: :all) ⇒ Object
-
.command_tasks ⇒ Object
Access the Rake namespace for CLI tasks/commands.
-
.default_parsed_args(&blk) ⇒ Object
Specify a standard type for parsed argument accumulation.
- .each_completion_script_line(static_options: nil, static_flags: nil) ⇒ Object
- .find(name, raise_if_missing: false) ⇒ Object
-
.help_styling ⇒ Object
Access the HelpStyling object used for styling generated help.
- .if_help_request ⇒ Object
- .is_task_name?(name) ⇒ Boolean
- .known_command?(name) ⇒ Boolean
-
.new_default_parsed_args(&blk) ⇒ Object
Construct a parsed argument accumulator.
-
.run(argv = ARGV, on_error: nil) ⇒ Object
Run a CLI.
- .script_name(placeholder_ok: true) ⇒ Object
- .task_name(name) ⇒ Object
- .title ⇒ Object
- .title=(s) ⇒ Object
Class Method Details
.args ⇒ Object
174 175 176 |
# File 'lib/rake/toolkit_program.rb', line 174 def self.args @args end |
.available_commands(include: :all) ⇒ Object
88 89 90 91 92 93 94 95 96 |
# File 'lib/rake/toolkit_program.rb', line 88 def self.available_commands(include: :all) Rake::Task.tasks.select {|t| is_task_name?(t.name)}.reject do |t| case include when :all then false when :listable then t.comment.to_s.empty? else raise ArgumentError, "#{include.inspect} not valid as include:" end end end |
.command_tasks ⇒ Object
Access the Rake namespace for CLI tasks/commands
Defining Rake tasks inside the block of this method (with #task) defines the tasks such that they are recognized as invocable from the command line (via the first command line argument, or the first element of args passed to .run).
To make commands/tasks defined in this block visible in the help and shell completion, use #desc to describe the task.
220 221 222 |
# File 'lib/rake/toolkit_program.rb', line 220 def self.command_tasks namespace(NAMESPACE) {yield} end |
.default_parsed_args(&blk) ⇒ Object
Specify a standard type for parsed argument accumulation
If this is called, the block is used to construct the argument accumulator if no accumulator object is explicitly specified when calling Rake::Task(Rake::ToolkitProgram::TaskExt)#parse_args. This helps Rake::ToolkitProgram.args be more consistent throughout the client program.
187 188 189 |
# File 'lib/rake/toolkit_program.rb', line 187 def self.default_parsed_args(&blk) @default_parsed_args_creator = blk end |
.each_completion_script_line(static_options: nil, static_flags: nil) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/rake/toolkit_program/completion.rb', line 23 def self.each_completion_script_line(static_options: nil, static_flags: nil) = || %Q{$("$1" --commands)} flags = (static_flags.shellescape if static_flags) || \ ('' if ) || \ %Q{$("$1" --flag-completion "${COMP_WORDS[@]}")} " COMPREPLY=()\n MY_WORDNUM=1\n if [ \"${COMP_CWORD}\" = 2 ] && [ \"${COMP_WORDS[1]}\" = help ]; then\n MY_WORDNUM=2\n elif [ \"${COMP_CWORD}\" != \"1\" ]; then\n HELP_FLAG=\"--help\"\n if [ -n \"${COMP_WORDS[$COMP_CWORD]}\" ] && [ \"${HELP_FLAG\\\#${COMP_WORDS[$COMP_CWORD]}}\" = \"$HELP_FLAG\" ]; then\n # Word being completed is NOT a prefix of --help: don't offer --help\n :\n elif ! { echo \" ${COMP_WORDS[*]}\" | egrep -q '\\\\s(--help|-h|--\\\\s)'; }; then\n COMPREPLY=(\"--help\")\n fi\n DO_COMPGEN=true\n if ! { echo \" ${COMP_WORDS[*]}\" | egrep -q '\\\\s(--help|-h|--\\\\s)'; }; then\n FLAGS_CANDIDATE=\#{flags}\n if [ \"$(echo \"$FLAGS_CANDIDATE\" | head -n1)\" == '!NOFSCOMP!' ]; then\n DO_COMPGEN=false\n COMPREPLY+=($(echo \"$FLAGS_CANDIDATE\" | tail -n+2))\n else\n COMPREPLY+=($FLAGS_CANDIDATE)\n fi\n fi\n if $DO_COMPGEN && [ \"${COMP_WORDS[$COMP_CWORD]}\" != \"--\" ] && ! { echo \" ${COMP_WORDS[*]}\" | egrep -q '\\\\s(--help|-h)'; }; then\n COMPREPLY+=($(compgen -f -d -- \"${COMP_WORDS[$COMP_CWORD]}\"))\n fi\n return\n fi\n COMPREPLY=($(compgen -W \"\#{options}\" -- \"${COMP_WORDS[$MY_WORDNUM]}\"))\n END_BASH\nend\n".dedent.each_line {|l| yield(" " + l)} |
.find(name, raise_if_missing: false) ⇒ Object
98 99 100 101 102 103 104 105 |
# File 'lib/rake/toolkit_program.rb', line 98 def self.find(name, raise_if_missing: false) case when known_command?(name) Rake::Task[task_name(name)] when raise_if_missing raise UnknownName.new(name) end end |
.help_styling ⇒ Object
Access the HelpStyling object used for styling generated help
69 70 71 72 73 74 |
# File 'lib/rake/toolkit_program.rb', line 69 def self.help_styling if block_given? yield @help_styling end @help_styling end |
.if_help_request ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/rake/toolkit_program.rb', line 158 def self.if_help_request if args[0] == 'help' yield else args.each do |a| case a when '--' break when '-h', '--help' yield break end end end end |
.is_task_name?(name) ⇒ Boolean
80 81 82 |
# File 'lib/rake/toolkit_program.rb', line 80 def self.is_task_name?(name) name.to_s.start_with?(NAMESPACE + ':') end |
.known_command?(name) ⇒ Boolean
84 85 86 |
# File 'lib/rake/toolkit_program.rb', line 84 def self.known_command?(name) !name.nil? && Rake::Task.task_defined?(task_name(name)) end |
.new_default_parsed_args(&blk) ⇒ Object
Construct a parsed argument accumulator
The constructor can be defined via the block of .default_parsed_args
196 197 198 |
# File 'lib/rake/toolkit_program.rb', line 196 def self.new_default_parsed_args(&blk) (@default_parsed_args_creator || blk).call end |
.run(argv = ARGV, on_error: nil) ⇒ Object
Run a CLI
Idiomatically, this is usually invoked as:
if __FILE__ == $0
Rake::ToolkitProgram.run(on_error: :exit_program!)
end
The first element of args (which defaults to ARGV) names the command to execute. Additional arguments are available via .args.
on_error may be anything supporting #to_proc (including a Proc or lambda) and accepts one parameter, which is an error object that is guaranteed to have an #exit_program! method. Since Symbol#to_proc creates a Proc that sends the target Symbol to the single argument of the created Proc, passing :exit_program! (as in the idiomatic invocation) results in program exit according to the error being handled.
If the error to be handled by on_error does not #respond_to? :exit_program!, it will be extended with ProgramExitFromError, giving it default #exit_program! behavior of printing the error message on STDERR and exiting with code 1.
When on_error is nil, any errors are allowed to propagate out of #run.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/rake/toolkit_program.rb', line 133 def self.run(argv=ARGV, on_error: nil) name, *@args = argv raise NoCommand if name.nil? if_help_request {name, args[0] = 'help', name} specified_task = find(name, raise_if_missing: true) if specified_task.kind_of?(ArgParsingTask) new_args = specified_task.parsed_arguments specified_task.argument_parser.parse( *case new_args when Hash then [args, {into: new_args}] else [args] end ) @args = new_args end specified_task.invoke rescue StandardError => error error.extend(ProgramExitFromError) unless error.respond_to?(:exit_program!) case when on_error then on_error.to_proc else method(:raise) end.call(error) end |
.script_name(placeholder_ok: true) ⇒ Object
200 201 202 203 204 205 206 207 |
# File 'lib/rake/toolkit_program.rb', line 200 def self.script_name(placeholder_ok: true) case when $0 != '-' then $0 when ENV['THIS_SCRIPT'] then ENV['THIS_SCRIPT'] when placeholder_ok then '<script-name>' else raise "Script name unknown" end end |
.task_name(name) ⇒ Object
76 77 78 |
# File 'lib/rake/toolkit_program.rb', line 76 def self.task_name(name) "#{NAMESPACE}:#{name}" end |
.title ⇒ Object
61 62 63 |
# File 'lib/rake/toolkit_program.rb', line 61 def self.title @title || "#{script_name.capitalize} Toolkit Program" end |
.title=(s) ⇒ Object
57 58 59 |
# File 'lib/rake/toolkit_program.rb', line 57 def self.title=(s) @title = s end |