Console windows aren't complete without the ability to save an easily traversible input history.
The technique I describe below isn't only useful in console windows. Chat applications can also utilize it effectively.
Consoles are made up of 2 main GUI components:
When I use a console interface I expect the following intuitive behavior:
Here's code I wrote in Dart that achieves all these effects by utilizing key listeners:
List<String> scrollback = [""];
int scrollbackIndex = 0;
InputElement inputField = new InputElement(type: "text");
inputField
..onKeyDown.listen((KeyboardEvent event) {
if (event.keyCode == KeyCode.UP || event.keyCode == KeyCode.DOWN) {
event.preventDefault();
if (event.keyCode == KeyCode.UP) scrollbackIndex = min(scrollbackIndex + 1, scrollback.length - 1);
if (event.keyCode == KeyCode.DOWN) scrollbackIndex = max(scrollbackIndex - 1, 0);
inputField.value = scrollback[scrollbackIndex];
}
})
..onKeyUp.listen((KeyboardEvent event) {
if (KeyCode.isCharacterKey(event.keyCode)) {
if (scrollbackIndex != 0) scrollbackIndex = 0;
if (scrollbackIndex == 0) scrollback[0] = inputField.value.trim();
}
})
..onKeyPress.listen((KeyboardEvent event) {
String input = inputField.value.replaceAll(new RegExp("\\s+"), " ");
if (event.keyCode == KeyCode.ENTER && input.length != 0) {
scrollback[0] = input;
int index = scrollback.lastIndexOf(input);
if (index != 0) scrollback.removeAt(index);
scrollback.insert(0, "");
scrollbackIndex = 0;
inputField.value = "";
evaluateCommand(input);
}
});
scrollback is the list that will store the input history. I use the first index[0] as the "stash" (note that the list is initialized with an empty string at index[0])scrollbackIndex keeps track of our place in the scrollback list as we traverse itinputField is our input text fieldonKeyDown (fired when a key is depressed):
scrollbackIndex depending on what key was pressed while making sure to constrain it within its bounds (low bound is 0, high bound is scrollback.length - 1)scrollback[scrollbackIndex], effectively displaying that command from the scrollback historyonKeyUp (fired when a key is released):
scrollbackIndex isn't 0 (indicating that the user is typing over a command from the history). If true, set scrollbackIndex to 0 (this will ensure that what the user is currently typing gets stashed)scrollbackIndex is 0 (indicating that the user is working on the stash). If true, trim the text from the input field and put it in the stashonKeyPressed:
input. This is optional, I do it to keep things cleaninput isn't an empty string. If true:input in the stash (in case it isn't already)input doesn't appear more than once in scrollback by removing any doublesscrollback effectively committing the command to history and resetting the stashscrollbackIndex to 0Click here to check out a demo featuring the Dart code above.