commandline apps
I wanted to create an app that could accept text input interactively from the terminal or have it piped:
Note that I want Ctrl-D to close the input, or in dart terms that would be closing the subscription.
Naturally, input is modeled as a stream. Whether each keystroke is treated as an input event/data or whether each line is treated as the event/data depends on the following setting:
When stdin.lineMode
is false
ever keystroke appears as an event. When it is true
, every the text appears as an event only after line break appears or Enter
key is pressed.
Now, we only want stdin.lineMode
to be false
when entering text interactively, when Ctrl-d
should terminate stream subscription. Therefore, our code will work in 2 different ways depending on whether stdin.hasTerminal
returns true
or false
. Based on this logic, we've written:
import 'dart:convert';
import 'dart:io';
void main() {
var subscription;
if (stdin.hasTerminal) {
stdin.lineMode = false;
stdin.echoMode = true;
List<int> input = [];
subscription = stdin.listen((data) {
if (data.contains(4)) {
subscription.cancel();
print("\n${utf8.decode(input)}");
} else {
input.add(data[0]);
}
});
} else { // if there is no terminal
stdin.map((data) => utf8.decode(data)).listen((data) {
print(data);
});
}
}