// Counts the lines piped into it, in constant memory.
//
// cat something.txt | nikaia run
// 120 lines, 14 blank
// longest: 87 characters
// …the longest line itself…
//
// With a file name, it also appends one summary row to that file as a log:
// `cat something.txt | nikaia run -- runs.log`.
//
// Shows: reading standard input line by line, a loop that can fail, and
// named options after the `;` in a signature and at a call.
//
// A package: `nikaia run` in this directory runs it, and `nikaia test` checks
// what it prints and the file it writes against `tests/` (ADR-247).
use std::io
use std::fs
use std::cli
// `separator` is an option: it stands after the `;`, has a default, and is
// named where a call sets it. A caller that does not need it never sees it.
fn summary(lines: int, blank: int; separator: String = " ") -> String {
return f"{lines}{separator}{blank}"
}
fn main() throws {
let mut lines = 0
let mut blank = 0
let mut longest = String()
// Each turn of this loop reads one line, so only one line is in memory at a
// time, plus the longest seen so far.
//
// A read can fail. Nothing marks that here, just as nothing marks a call
// that can fail: the failure leaves `main`, which is why `main` says
// `throws`. Without it the program does not compile:
//
// error[NK2701]: this function can fail because a turn of this loop can fail
// help: declare the error: add `throws` to this function
//
// So a read that fails is reported as an error, never mistaken for the end
// of the input.
for line in io::lines() {
lines += 1
if line.len() == 0 {
blank += 1
}
if line.len() > longest.len() {
longest = line
}
}
println(f"{lines} lines, {blank} blank")
println(f"longest: {longest.len()} characters")
println(f"{longest}")
// A run log, if a file was named. `append: true` is an option set at the
// call; without it `fs::write` replaces the file.
let log = cli::args().nth(1) ?? ""
if log.len() > 0 {
let row = summary(lines, blank; separator: "\t")
fs::write(ref log, fs::Root::Anywhere, f"{row}\n"; append: true) catch {
eprintln(f"cannot append to {log}: {error}")
return
}
}
}
The file itself · all the examples