Build a command-line application
This recipe builds a small native command that reads os.Args, validates a bounded repeat count, and prints a greeting. It uses ordinary Go process arguments, so there is no Kinmokusei-specific argument runtime.
Source
import go fmt from "fmt";
import go os from "os";
import go strconv from "strconv";
import go strings from "strings";
function parseCount(text: bstring): Result<int> {
const count = strconv.Atoi(text)?;
if (count < 1 || count > 5) {
return fail(fmt.Errorf("count must be from 1 through 5"));
}
return ok(count);
}
function render(name: bstring, count: int): bstring {
let lines = makeSlice[bstring](0, count);
for (let index = 0; index < count; index++) {
lines = append(lines, fmt.Sprintf("Hello, %s!", name));
}
return strings.Join(lines, "\n");
}
function main(): void {
if (len(os.Args) !== 3) {
fmt.Println("usage: greeter <name> <count>");
return;
}
const [count, err] = parseCount(os.Args[2]);
if (err !== nil) {
fmt.Println("error:", err.Error());
return;
}
fmt.Println(render(os.Args[1], count));
}Build and run
keika check main.km
keika build -o ./greeter main.km
./greeter Kinmokusei 3keika check .\main.km
keika build -o .\greeter.exe .\main.km
.\greeter.exe Kinmokusei 3Expected output:
Hello, Kinmokusei!
Hello, Kinmokusei!
Hello, Kinmokusei!keika run currently treats all positional arguments as source inputs; it does not forward arguments to the generated program. Build an executable when testing os.Args, as shown above.
Separate parsing from effects
main owns the process boundary, while parseCount and render remain ordinary functions:
strconv.Atoi(text)?converts a Go(int, error)directly into theResult<int>early-return path.- the range check turns a syntactically valid but unacceptable count into an application error;
rendercan be tested without changing process-global arguments;makeSlicereserves capacity, and everyappendresult is assigned back because growth may replace the backing array.
os.Args[0] is the executable path. User arguments begin at index 1, so this command requires exactly three entries: executable, name, and count. The length check happens before either index operation.
Failure behavior
These calls exercise distinct user errors:
./greeter
./greeter Kinmokusei many
./greeter Kinmokusei 10They print a usage line, a strconv.Atoi error, and the application range error respectively. This example reports expected input failures without panicking; a larger command can map them to explicit exit codes in a neighboring Go entry package when required.
The documentation test builds this source, passes Kinmokusei and 3 as separate process arguments, and compares all three output lines exactly. See the CLI reference for compiler-command behavior and testing applications for executable and generated-package test strategies.