Building a Small CLI App
Keep parsing and I/O at the edge, with a pure core that is easy to test.
Argparse
std/argparse provides a Cli record plus flag, option, parse, and accessor helpers. Pass full args; parse skips the first element (the program entry).
cli: Cli = {
name = "app",
version = "0.1",
description = "demo",
params = []
}
Pure Core
Put deterministic word-count logic in pure functions.
pure func count_words(text: String) -> Int:
text
.words()
.length()
Impure Shell
Read files, parse args, and print in main.
func main(args: List[String]) -> Int:
print(count_words("one two"))
0
Tests
Test the pure core without invoking the CLI.
func test_count_words() -> Bool:
count_words("one two") == 2
Example
wordcount.brp
import:
argparse:
Cli,
ArgumentParseOutcome(ArgumentsParsed, ArgumentsHelpRequested, ArgumentsVersionRequested, ArgumentsParseFailed),
arg_int,
format_error,
get_int_or,
parse,
io: read_line
pure func count_words(text: String, min_len: Int) -> Int:
var count: Int = 0
for word in text.words():
if word.length() >= min_len:
count += 1
count
func main(args: List[String]) -> Int:
cli: Cli = {
name = "wordcount",
version = "0.1",
description = "count words",
params = [
arg_int("min-length", Some("--min-length"), Some("-m"), "minimum length", Some("N")),
]
}
match parse(cli, args):
ArgumentsParsed(parsed):
min_len: Int = get_int_or(parsed, "min-length", 1)
var total: Int = 0
while True:
match read_line():
Some(line): total += count_words(line, min_len)
None: break
print(total)
0
ArgumentsParseFailed(err):
print_error(format_error(err))
1
ArgumentsHelpRequested(text):
print(text)
0
ArgumentsVersionRequested(text):
print(text)
0
Try it
terminal
printf 'one three seven\n' | blorp run examples/docs/working-programs/building-a-small-cli-app/wordcount.brp -- --min-length 4