Module: NRSER::Rash::CLI
- Includes:
- SemanticLogger::Loggable
- Defined in:
- lib/nrser/rash/cli/call.rb,
lib/nrser/rash/cli/help.rb,
lib/nrser/rash/cli/list.rb,
lib/nrser/rash/cli/run.rb,
lib/nrser/rash/cli.rb
Overview
Where the CLI commands live as class methods.
Class Method Summary collapse
-
.call(name, argv) ⇒ Object
Call a Rash function.
-
.format(obj) ⇒ Object
formats an object to write to
$stdout
. - .help ⇒ Object
-
.list ⇒ Object
List the Rash functions available.
-
.run ⇒ Object
start here.
Class Method Details
.call(name, argv) ⇒ Object
Call a Rash function.
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/nrser/rash/cli/call.rb', line 24 def self.call name, argv logger.trace "calling #{ name.inspect }", argv: argv # look for options = {} args = argv.reject do |arg| # long options of form '--<name>=<value>' if m = arg.match(/\A--([^=]*)(=?)(.*)/) [m[1].to_sym] = if m[2] == '' true else m[3] end true # short options of form '-<char>' elsif arg.start_with? '-' arg[1..-1].each_char do |char| [char] = true end true end end logger.trace "Extracted options", argv: argv, args: args, options: NRSER::Rash.load_functions if name.include? '.' *namespace, method_name = name.split '.' namespace = namespace.flat_map { |s| s.split '::' } else namespace = [] method_name = name end # Find the module the function is in mod = NRSER::Rash::Functions namespace.each do |submod_name| mod = mod.const_get(submod_name.capitalize) end # Get the function itself ({Metood} instance) meth = mod.method method_name # Symbolize option keys if the method takes keyword args if meth.parameters.any? { |type, *_| [:key, :keyreq, :keyrest].include? type } = .map { |key, value| [key.to_sym, value] }.to_h end # options are the last arg, unless we didn't find any # # NOTE: this causes functions without an optional `options` arg # on the end to raise an exception when called with any options. # # i think this is the correct behavior: the function can't handle # options, and should error out. args << unless .empty? begin result = meth.call *args rescue Exception => error if NRSER::Rash.config( 'PRINT_ERRORS' ).truthy? if NRSER::Rash.config( 'STACKTRACE' ).truthy? raise error else logger.fatal error # this is the error code that ruby seems to exit with when you # don't check the exception exit 1 end end end logger.debug "Function #{ name } returned", result: result if formatted = format( result ) puts formatted end exit 0 end |
.format(obj) ⇒ Object
formats an object to write to $stdout
.
returns nil
if there's nothing to write (different than returning '',
indicating the empty string should be written).
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/nrser/rash/cli/call.rb', line 120 def self.format(obj) # TODO: should formatter be overridable with a env var? # formatter = begin config('FORMATTER'); rescue NameError => e; nil; end # logger.debug "formatter: #{ formatter.inspect }" if obj.rash_formatter # there is some sort of formatting info # even if the value is a string, we want to follow the instructions # hell, maybe we want to write the string out as json or something :/ if obj.rash_formatter.respond_to? :call # the value responds to `call`, so call it to get the value # TODO: should we check that it returns a `String`? obj.rash_formatter.call(obj) # NOTE: `Object.singleton_methods` returns an array of strings in 1.8 # and an array of symbols in 1.9, so use strings to work in # both. elsif NRSER::Rash::Formatters. singleton_methods. map {|_| _.to_s }. include? obj.rash_formatter.to_s # it's a symbol that identifies on of the {NRSER::Rash::Formatters} # class methods, so call that NRSER::Rash::Formatters.send obj.rash_formatter, obj else # whatever, call the default NRSER::Rash::Formatters.send config('DEFAULT_FORMATTER'), obj end else # there is no formatting info if obj.is_a? String # in the case that a method passed back a `String`, i think we should # consider it formatted and just print it obj elsif obj.nil? # the result is nil and there has been no attempt to format it in # a specific way that some program might need to recongize or # something. at this point, i'm going to say that the function # took some successful action and doesn't have anyhting to say about # it, which i think means we shouldn't print anything else # otherwise, send it to the default formatter NRSER::Rash::Formatters.send \ NRSER::Rash.config('DEFAULT_FORMATTER'), obj end end end |
.help ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/nrser/rash/cli/help.rb', line 16 def self.help # TODO: woefully incomplete puts <<~EOF Usage: rash COMMAND [ARGS...] Commands: list List functions you can call. call Call a method from NRSER::Rash::Functions. test Run tests for a method from NRSER::Rash::Functions. help This message. EOF end |
.list ⇒ Object
List the Rash functions available.
31 32 33 34 |
# File 'lib/nrser/rash/cli/list.rb', line 31 def self.list NRSER::Rash.load_functions puts NRSER::Rash.function_names end |
.run ⇒ Object
start here.
this is the entry point for the script when executed. it expects a command as the first argument and dispatches to the associated method.
20 21 22 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 |
# File 'lib/nrser/rash/cli/run.rb', line 20 def self.run SemanticLogger.add_appender io: $stderr, formatter: { color: { ap: {multiline: true}, } } SemanticLogger.default_level = NRSER::Rash.config( 'LOG_LEVEL' ).to_sym # the command is the first argument # we won't need or want it after this, so delete it command = ARGV.shift # filter out the command line config options NRSER::Rash.filter_and_set_config ARGV case command when 'call' # we are being asked to call a function. the name of the function is # the second argument (now at index 0 since we deleted the command) # and the rest of the arguments are passed to the function call ARGV[0], ARGV[1..-1] when 'test' NRSER::Rash._test_function ARGV.shift #, ARGV[1, ARGV.length] when 'list' list when 'help', '-h', '--help', nil help # Exit with error so these calls don't work with `&&` in shell exit 1 when '--version', 'version', '-v' puts NRSER::Rash::VERSION else call command, ARGV end end |