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.