class Cli
class Cli
lib/cli.tya:2
Cli provides the cli/Cli standard library API.
Source
# Cli provides the cli/Cli standard library API.
class Cli
# Cli.value stores instance state.
# @type Nil
value: nil
# Cli.initialize stores command-line args or a command name.
# @param value String value value.
# @return Self the initialized object.
initialize: value ->
self.value = value
# Cli.apply_defaults provides the cli/Cli standard library operation.
# @param state Any state value.
# @return Any the resulting value.
apply_defaults: state ->
options = Cli(nil).spec_options(state["spec"])
names = options.keys()
for name in names
opt = options[name]
if opt.has("default")
state["options"][name] = opt["default"]
else
typ = Cli(nil).option_type(opt)
if typ == "bool"
state["options"][name] = false
elseif typ == "array"
state["options"][name] = []
# Cli.assign_value provides the cli/Cli standard library operation.
# @param state Any state value.
# @param name String name value.
# @param opt Any opt value.
# @param value String value value.
# @return Any the resulting value.
assign_value: state, name, opt, value ->
typ = Cli(nil).option_type(opt)
if typ == "string"
state["options"][name] = value
elseif typ == "int"
try
state["options"][name] = value.to_i()
catch _
Cli(nil).error(state, "invalid_value", name, "--{name} expects int")
else
if typ == "float"
try
state["options"][name] = value.to_f()
catch _
Cli(nil).error(state, "invalid_value", name, "--{name} expects float")
elseif typ == "array"
if not state["options"].has(name)
state["options"][name] = []
state["options"][name].push(value)
else
Cli(nil).error(
state,
"invalid_type",
name,
"unsupported option type {typ}"
)
# Cli.check_required provides the cli/Cli standard library operation.
# @param state Any state value.
# @return Any the resulting value.
check_required: state ->
options = Cli(nil).spec_options(state["spec"])
names = options.keys().sort()
for name in names
opt = options[name]
if (
Cli(nil).spec_bool(opt, "required", false) and not state["options"].has(name)
)
Cli(nil).error(state, "required", name, "--{name} is required")
# Cli.error provides the cli/Cli standard library operation.
# @param state Any state value.
# @param kind Any kind value.
# @param name String name value.
# @param message String message value.
# @return Any the resulting value.
error: state, kind, name, message ->
state["errors"].push({ kind: kind, option: name, message: message })
# Cli.index_of provides the cli/Cli standard library operation.
# @param text String text value.
# @param needle Any needle value.
# @return Any the resulting value.
index_of: text, needle ->
i = 0
while i < text.byte_len()
if text[i] == needle
return i
i = i + 1
-1
# Cli.name_for_alias provides the cli/Cli standard library operation.
# @param spec Any spec value.
# @param alias Any alias value.
# @return Any the resulting value.
name_for_alias: spec, alias ->
options = Cli(nil).spec_options(spec)
names = options.keys()
for name in names
opt = options[name]
if Cli(nil).spec_string(opt, "alias", "") == alias
return name
""
# Cli.option_type provides the cli/Cli standard library operation.
# @param opt Any opt value.
# @return Any the resulting value.
option_type: opt ->
Cli(nil).spec_string(opt, "type", "string")
# Cli.parse provides the cli/Cli standard library operation.
# @param args Array args value.
# @param spec Any spec value.
# @return Any the resulting value.
parse: args, spec = nil ->
if self.value != nil
spec = args
args = self.value
state =
args: args
spec: spec
options: {}
positionals: []
rest: []
errors: []
stop_options: false
Cli(nil).apply_defaults(state)
i = 0
while i < args.len()
arg = args[i]
if state["stop_options"]
state["rest"].push(arg)
elseif arg == "--"
state["stop_options"] = true
if Cli(nil).spec_bool(spec, "stop_at_double_dash", true)
j = i + 1
while j < args.len()
state["rest"].push(args[j])
j = j + 1
i = args.len()
else
if arg.starts_with("--") and arg.byte_len() > 2
i = Cli(nil).parse_long(state, i)
elseif arg.starts_with("-") and arg != "-"
i = Cli(nil).parse_short(state, i)
else
state["positionals"].push(arg)
i = i + 1
Cli(nil).check_required(state)
result =
options: state["options"]
positionals: state["positionals"]
rest: state["rest"]
errors: state["errors"]
result
# Cli.parse_bool_value provides the cli/Cli standard library operation.
# @param state Any state value.
# @param name String name value.
# @param value String value value.
# @return Any the resulting value.
parse_bool_value: state, name, value ->
if value == "true" or value == "1" or value == "yes"
return true
if value == "false" or value == "0" or value == "no"
return false
Cli(nil).error(state, "invalid_value", name, "--{name} expects bool")
false
# Cli.parse_long provides the cli/Cli standard library operation.
# @param state Any state value.
# @param i Int i value.
# @return Any the resulting value.
parse_long: state, i ->
arg = state["args"][i]
raw = arg.slice(2, arg.len())
eq = Cli(nil).index_of(raw, "=")
name = raw
value = nil
has_value = false
if eq >= 0
name = raw.slice(0, eq)
value = raw.slice(eq + 1, raw.len())
has_value = true
negated = false
if name.starts_with("no-")
negated = true
name = name.slice(3, name.len())
options = Cli(nil).spec_options(state["spec"])
if not options.has(name)
Cli(nil).unknown(state, arg)
return i
opt = options[name]
typ = Cli(nil).option_type(opt)
if typ == "bool"
if negated
state["options"][name] = false
elseif has_value
state["options"][name] = Cli(nil).parse_bool_value(state, name, value)
else
state["options"][name] = true
return i
if negated
Cli(nil).error(
state,
"invalid_option",
name,
"--no-{name} is only valid for bool options"
)
return i
if not has_value
if i + 1 >= state["args"].len()
Cli(nil).error(
state,
"missing_value",
name,
"--{name} requires a value"
)
return i
i = i + 1
value = state["args"][i]
Cli(nil).assign_value(state, name, opt, value)
i
# Cli.parse_or_exit provides the cli/Cli standard library operation.
# @param args Array args value.
# @param spec Any spec value.
# @return Any the resulting value.
parse_or_exit: args, spec = nil ->
if self.value != nil
spec = args
args = self.value
result = Cli(args).parse(spec)
if result["errors"].len() > 0
command = Cli(nil).spec_string(spec, "command", "usage")
println(Cli(nil).usage(command, spec))
for err in result["errors"]
println(err["message"])
exit(1)
result
# Cli.parse_short provides the cli/Cli standard library operation.
# @param state Any state value.
# @param i Int i value.
# @return Any the resulting value.
parse_short: state, i ->
arg = state["args"][i]
raw = arg.slice(1, arg.len())
j = 0
while j < raw.byte_len()
alias = raw[j]
name = Cli(nil).name_for_alias(state["spec"], alias)
if name == ""
Cli(nil).unknown(state, "-{alias}")
j = j + 1
else
opt = Cli(nil).spec_options(state["spec"])[name]
typ = Cli(nil).option_type(opt)
if typ == "bool"
state["options"][name] = true
j = j + 1
else
if j + 1 < raw.byte_len()
value = raw.slice(j + 1, raw.len())
Cli(nil).assign_value(state, name, opt, value)
return i
if i + 1 >= state["args"].len()
Cli(nil).error(
state,
"missing_value",
name,
"-{alias} requires a value"
)
return i
i = i + 1
Cli(nil).assign_value(state, name, opt, state["args"][i])
return i
i
# Cli.spec_bool provides the cli/Cli standard library operation.
# @param spec Any spec value.
# @param name String name value.
# @param fallback Any fallback value.
# @return Any the resulting value.
spec_bool: spec, name, fallback ->
if spec.has(name)
return spec[name]
fallback
# Cli.spec_options provides the cli/Cli standard library operation.
# @param spec Any spec value.
# @return Dict the resulting value.
spec_options: spec ->
if spec.has("options")
return spec["options"]
{}
# Cli.spec_string provides the cli/Cli standard library operation.
# @param spec Any spec value.
# @param name String name value.
# @param fallback Any fallback value.
# @return String the resulting value.
spec_string: spec, name, fallback ->
if spec.has(name)
return spec[name]
fallback
# Cli.unknown provides the cli/Cli standard library operation.
# @param state Any state value.
# @param raw Any raw value.
# @return Any the resulting value.
unknown: state, raw ->
if Cli(nil).spec_bool(state["spec"], "allow_unknown", false)
state["rest"].push(raw)
else
Cli(nil).error(state, "unknown_option", raw, "unknown option {raw}")
# Cli.usage provides the cli/Cli standard library operation.
# @param command Any command value.
# @param spec Any spec value.
# @return String the resulting value.
usage: command, spec = nil ->
if self.value != nil
spec = command
command = self.value
parts = ["Usage: {command}"]
options = Cli(nil).spec_options(spec)
names = options.keys().sort()
if names.len() > 0
parts.push("[options]")
if spec.has("positionals")
for pos in spec["positionals"]
if pos.class == String
parts.push("<{pos}>")
else
name = Cli(nil).spec_string(pos, "name", "arg")
required = Cli(nil).spec_bool(pos, "required", true)
if required
parts.push("<{name}>")
else
parts.push("[{name}]")
out = parts.join(" ")
if names.len() > 0
out = out + "\nOptions:"
for name in names
opt = options[name]
line = " --{name}"
alias = Cli(nil).spec_string(opt, "alias", "")
if alias != ""
line = " -{alias}, --{name}"
typ = Cli(nil).option_type(opt)
if typ != "bool"
line = line + " <{typ}>"
markers = []
if Cli(nil).spec_bool(opt, "required", false)
markers.push("required")
if opt.has("default")
default_value = opt["default"]
markers.push("default: {default_value}")
if markers.len() > 0
line = line + " (" + markers.join(", ") + ")"
if opt.has("help")
line = line + " " + opt["help"]
out = out + "\n" + line
out
Instance Variables
value
Cli.value
lib/cli.tya:5
Cli.value stores instance state.
Source
# Cli.value stores instance state.
# @type Nil
value: nil
Methods
apply_defaults
Cli.apply_defaults(state)
lib/cli.tya:16
Cli.apply_defaults provides the cli/Cli standard library operation.
Source
# Cli.apply_defaults provides the cli/Cli standard library operation.
# @param state Any state value.
# @return Any the resulting value.
apply_defaults: state ->
options = Cli(nil).spec_options(state["spec"])
names = options.keys()
for name in names
opt = options[name]
if opt.has("default")
state["options"][name] = opt["default"]
else
typ = Cli(nil).option_type(opt)
if typ == "bool"
state["options"][name] = false
elseif typ == "array"
state["options"][name] = []
assign_value
Cli.assign_value(state, name, opt, value)
lib/cli.tya:36
Cli.assign_value provides the cli/Cli standard library operation.
Source
# Cli.assign_value provides the cli/Cli standard library operation.
# @param state Any state value.
# @param name String name value.
# @param opt Any opt value.
# @param value String value value.
# @return Any the resulting value.
assign_value: state, name, opt, value ->
typ = Cli(nil).option_type(opt)
if typ == "string"
state["options"][name] = value
elseif typ == "int"
try
state["options"][name] = value.to_i()
catch _
Cli(nil).error(state, "invalid_value", name, "--{name} expects int")
else
if typ == "float"
try
state["options"][name] = value.to_f()
catch _
Cli(nil).error(state, "invalid_value", name, "--{name} expects float")
elseif typ == "array"
if not state["options"].has(name)
state["options"][name] = []
state["options"][name].push(value)
else
Cli(nil).error(
state,
"invalid_type",
name,
"unsupported option type {typ}"
)
check_required
Cli.check_required(state)
lib/cli.tya:66
Cli.check_required provides the cli/Cli standard library operation.
Source
# Cli.check_required provides the cli/Cli standard library operation.
# @param state Any state value.
# @return Any the resulting value.
check_required: state ->
options = Cli(nil).spec_options(state["spec"])
names = options.keys().sort()
for name in names
opt = options[name]
if (
Cli(nil).spec_bool(opt, "required", false) and not state["options"].has(name)
)
Cli(nil).error(state, "required", name, "--{name} is required")
error
Cli.error(state, kind, name, message)
lib/cli.tya:82
Cli.error provides the cli/Cli standard library operation.
Source
# Cli.error provides the cli/Cli standard library operation.
# @param state Any state value.
# @param kind Any kind value.
# @param name String name value.
# @param message String message value.
# @return Any the resulting value.
error: state, kind, name, message ->
state["errors"].push({ kind: kind, option: name, message: message })
index_of
Cli.index_of(text, needle)
lib/cli.tya:89
Cli.index_of provides the cli/Cli standard library operation.
Source
# Cli.index_of provides the cli/Cli standard library operation.
# @param text String text value.
# @param needle Any needle value.
# @return Any the resulting value.
index_of: text, needle ->
i = 0
while i < text.byte_len()
if text[i] == needle
return i
i = i + 1
-1
initialize
Cli.initialize(value)
lib/cli.tya:10
Cli.initialize stores command-line args or a command name.
Source
# Cli.initialize stores command-line args or a command name.
# @param value String value value.
# @return Self the initialized object.
initialize: value ->
self.value = value
name_for_alias
Cli.name_for_alias(spec, alias)
lib/cli.tya:101
Cli.name_for_alias provides the cli/Cli standard library operation.
Source
# Cli.name_for_alias provides the cli/Cli standard library operation.
# @param spec Any spec value.
# @param alias Any alias value.
# @return Any the resulting value.
name_for_alias: spec, alias ->
options = Cli(nil).spec_options(spec)
names = options.keys()
for name in names
opt = options[name]
if Cli(nil).spec_string(opt, "alias", "") == alias
return name
""
option_type
Cli.option_type(opt)
lib/cli.tya:113
Cli.option_type provides the cli/Cli standard library operation.
Source
# Cli.option_type provides the cli/Cli standard library operation.
# @param opt Any opt value.
# @return Any the resulting value.
option_type: opt ->
Cli(nil).spec_string(opt, "type", "string")
parse
Cli.parse(args, spec = nil)
lib/cli.tya:120
Cli.parse provides the cli/Cli standard library operation.
Source
# Cli.parse provides the cli/Cli standard library operation.
# @param args Array args value.
# @param spec Any spec value.
# @return Any the resulting value.
parse: args, spec = nil ->
if self.value != nil
spec = args
args = self.value
state =
args: args
spec: spec
options: {}
positionals: []
rest: []
errors: []
stop_options: false
Cli(nil).apply_defaults(state)
i = 0
while i < args.len()
arg = args[i]
if state["stop_options"]
state["rest"].push(arg)
elseif arg == "--"
state["stop_options"] = true
if Cli(nil).spec_bool(spec, "stop_at_double_dash", true)
j = i + 1
while j < args.len()
state["rest"].push(args[j])
j = j + 1
i = args.len()
else
if arg.starts_with("--") and arg.byte_len() > 2
i = Cli(nil).parse_long(state, i)
elseif arg.starts_with("-") and arg != "-"
i = Cli(nil).parse_short(state, i)
else
state["positionals"].push(arg)
i = i + 1
Cli(nil).check_required(state)
result =
options: state["options"]
positionals: state["positionals"]
rest: state["rest"]
errors: state["errors"]
result
parse_bool_value
Cli.parse_bool_value(state, name, value)
lib/cli.tya:167
Cli.parse_bool_value provides the cli/Cli standard library operation.
Source
# Cli.parse_bool_value provides the cli/Cli standard library operation.
# @param state Any state value.
# @param name String name value.
# @param value String value value.
# @return Any the resulting value.
parse_bool_value: state, name, value ->
if value == "true" or value == "1" or value == "yes"
return true
if value == "false" or value == "0" or value == "no"
return false
Cli(nil).error(state, "invalid_value", name, "--{name} expects bool")
false
parse_long
Cli.parse_long(state, i)
lib/cli.tya:179
Cli.parse_long provides the cli/Cli standard library operation.
Source
# Cli.parse_long provides the cli/Cli standard library operation.
# @param state Any state value.
# @param i Int i value.
# @return Any the resulting value.
parse_long: state, i ->
arg = state["args"][i]
raw = arg.slice(2, arg.len())
eq = Cli(nil).index_of(raw, "=")
name = raw
value = nil
has_value = false
if eq >= 0
name = raw.slice(0, eq)
value = raw.slice(eq + 1, raw.len())
has_value = true
negated = false
if name.starts_with("no-")
negated = true
name = name.slice(3, name.len())
options = Cli(nil).spec_options(state["spec"])
if not options.has(name)
Cli(nil).unknown(state, arg)
return i
opt = options[name]
typ = Cli(nil).option_type(opt)
if typ == "bool"
if negated
state["options"][name] = false
elseif has_value
state["options"][name] = Cli(nil).parse_bool_value(state, name, value)
else
state["options"][name] = true
return i
if negated
Cli(nil).error(
state,
"invalid_option",
name,
"--no-{name} is only valid for bool options"
)
return i
if not has_value
if i + 1 >= state["args"].len()
Cli(nil).error(
state,
"missing_value",
name,
"--{name} requires a value"
)
return i
i = i + 1
value = state["args"][i]
Cli(nil).assign_value(state, name, opt, value)
i
parse_or_exit
Cli.parse_or_exit(args, spec = nil)
lib/cli.tya:234
Cli.parse_or_exit provides the cli/Cli standard library operation.
Source
# Cli.parse_or_exit provides the cli/Cli standard library operation.
# @param args Array args value.
# @param spec Any spec value.
# @return Any the resulting value.
parse_or_exit: args, spec = nil ->
if self.value != nil
spec = args
args = self.value
result = Cli(args).parse(spec)
if result["errors"].len() > 0
command = Cli(nil).spec_string(spec, "command", "usage")
println(Cli(nil).usage(command, spec))
for err in result["errors"]
println(err["message"])
exit(1)
result
parse_short
Cli.parse_short(state, i)
lib/cli.tya:251
Cli.parse_short provides the cli/Cli standard library operation.
Source
# Cli.parse_short provides the cli/Cli standard library operation.
# @param state Any state value.
# @param i Int i value.
# @return Any the resulting value.
parse_short: state, i ->
arg = state["args"][i]
raw = arg.slice(1, arg.len())
j = 0
while j < raw.byte_len()
alias = raw[j]
name = Cli(nil).name_for_alias(state["spec"], alias)
if name == ""
Cli(nil).unknown(state, "-{alias}")
j = j + 1
else
opt = Cli(nil).spec_options(state["spec"])[name]
typ = Cli(nil).option_type(opt)
if typ == "bool"
state["options"][name] = true
j = j + 1
else
if j + 1 < raw.byte_len()
value = raw.slice(j + 1, raw.len())
Cli(nil).assign_value(state, name, opt, value)
return i
if i + 1 >= state["args"].len()
Cli(nil).error(
state,
"missing_value",
name,
"-{alias} requires a value"
)
return i
i = i + 1
Cli(nil).assign_value(state, name, opt, state["args"][i])
return i
i
spec_bool
Cli.spec_bool(spec, name, fallback)
lib/cli.tya:290
Cli.spec_bool provides the cli/Cli standard library operation.
Source
# Cli.spec_bool provides the cli/Cli standard library operation.
# @param spec Any spec value.
# @param name String name value.
# @param fallback Any fallback value.
# @return Any the resulting value.
spec_bool: spec, name, fallback ->
if spec.has(name)
return spec[name]
fallback
spec_options
Cli.spec_options(spec)
lib/cli.tya:298
Cli.spec_options provides the cli/Cli standard library operation.
Source
# Cli.spec_options provides the cli/Cli standard library operation.
# @param spec Any spec value.
# @return Dict the resulting value.
spec_options: spec ->
if spec.has("options")
return spec["options"]
{}
spec_string
Cli.spec_string(spec, name, fallback)
lib/cli.tya:308
Cli.spec_string provides the cli/Cli standard library operation.
Source
# Cli.spec_string provides the cli/Cli standard library operation.
# @param spec Any spec value.
# @param name String name value.
# @param fallback Any fallback value.
# @return String the resulting value.
spec_string: spec, name, fallback ->
if spec.has(name)
return spec[name]
fallback
unknown
Cli.unknown(state, raw)
lib/cli.tya:317
Cli.unknown provides the cli/Cli standard library operation.
Source
# Cli.unknown provides the cli/Cli standard library operation.
# @param state Any state value.
# @param raw Any raw value.
# @return Any the resulting value.
unknown: state, raw ->
if Cli(nil).spec_bool(state["spec"], "allow_unknown", false)
state["rest"].push(raw)
else
Cli(nil).error(state, "unknown_option", raw, "unknown option {raw}")
usage
Cli.usage(command, spec = nil)
lib/cli.tya:327
Cli.usage provides the cli/Cli standard library operation.
Source
# Cli.usage provides the cli/Cli standard library operation.
# @param command Any command value.
# @param spec Any spec value.
# @return String the resulting value.
usage: command, spec = nil ->
if self.value != nil
spec = command
command = self.value
parts = ["Usage: {command}"]
options = Cli(nil).spec_options(spec)
names = options.keys().sort()
if names.len() > 0
parts.push("[options]")
if spec.has("positionals")
for pos in spec["positionals"]
if pos.class == String
parts.push("<{pos}>")
else
name = Cli(nil).spec_string(pos, "name", "arg")
required = Cli(nil).spec_bool(pos, "required", true)
if required
parts.push("<{name}>")
else
parts.push("[{name}]")
out = parts.join(" ")
if names.len() > 0
out = out + "\nOptions:"
for name in names
opt = options[name]
line = " --{name}"
alias = Cli(nil).spec_string(opt, "alias", "")
if alias != ""
line = " -{alias}, --{name}"
typ = Cli(nil).option_type(opt)
if typ != "bool"
line = line + " <{typ}>"
markers = []
if Cli(nil).spec_bool(opt, "required", false)
markers.push("required")
if opt.has("default")
default_value = opt["default"]
markers.push("default: {default_value}")
if markers.len() > 0
line = line + " (" + markers.join(", ") + ")"
if opt.has("help")
line = line + " " + opt["help"]
out = out + "\n" + line
out