Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add command history #79

Merged
merged 12 commits into from
Oct 27, 2021
15 changes: 15 additions & 0 deletions src/main/java/seedu/address/logic/Logic.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,19 @@ public interface Logic {
* @return The command result of the command being executed.
*/
CommandResult undoCommand();

/**
* Get the next or previous command in the command history.
*
* @param isNext produces the next command in the stack if true, else the previous
* @param currentString the string to be cached
* @return string representation of the executed command in order.
*/
String getHistoryCommand(boolean isNext, String currentString);
yeppog marked this conversation as resolved.
Show resolved Hide resolved
yeppog marked this conversation as resolved.
Show resolved Hide resolved

/**
* Resets the history position to the top of the stack
*/
void resetHistoryPosition();

}
11 changes: 11 additions & 0 deletions src/main/java/seedu/address/logic/LogicManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public CommandResult execute(String commandText) throws CommandException, ParseE
Command command = addressBookParser.parseCommand(commandText);
commandResult = command.execute(model);
model.getCommandHistory().pushCommand(command);
model.addCommandToHistory(commandText);

try {
storage.saveAddressBook(model.getAddressBook());
Expand Down Expand Up @@ -142,4 +143,14 @@ public CommandResult undoCommand() {
return new CommandResult(e.getMessage());
}
}

@Override
public String getHistoryCommand(boolean isNext, String currentString) {
yeppog marked this conversation as resolved.
Show resolved Hide resolved
return model.getHistoryCommand(isNext, currentString);
}

@Override
public void resetHistoryPosition() {
model.resetHistoryPosition();
}
}
26 changes: 26 additions & 0 deletions src/main/java/seedu/address/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -196,5 +196,31 @@ public interface Model {
*/
void executeGuiAction(GuiAction action);

/**
* Returns the command history instance.
*
* @return Command history instance.
*/
CommandHistory getCommandHistory();

yeppog marked this conversation as resolved.
Show resolved Hide resolved
/**
* Get the next or previous command in the command history.
*
* @param isNext produces the next command in the stack if true, else the previous
* @param currentString the string to be cached
* @return string representation of the executed command in order.
*/
String getHistoryCommand(boolean isNext, String currentString);

/**
* Adds a command to the the history stack
*
* @param command String representation of the executed command
*/
void addCommandToHistory(String command);

/**
* Resets the history position to the top of the stack
*/
void resetHistoryPosition();
}
22 changes: 22 additions & 0 deletions src/main/java/seedu/address/model/ModelManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import seedu.address.model.task.filters.TaskFilter;
import seedu.address.model.task.filters.TaskFilters;
import seedu.address.storage.CommandHistory;
import seedu.address.storage.InputHistory;

/**
* Represents the in-memory model of the address book data.
Expand All @@ -39,6 +40,7 @@ public class ModelManager implements Model {
private final TaskList taskList;
private final UserPrefs userPrefs;
private final CommandHistory commandHistory;
private final InputHistory historyStorage;
private final FilteredList<Person> filteredPersons;
private final FilteredList<Task> filteredTasks;
private final ObservableList<TaskFilter> availableTaskFilters;
Expand All @@ -57,11 +59,13 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyTaskList taskList,
this.taskList = new TaskList(taskList);
this.userPrefs = new UserPrefs(userPrefs);
this.commandHistory = new CommandHistory(15);
this.historyStorage = new InputHistory();
filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
filteredTasks = new FilteredList<>(this.taskList.getTasks());
availableTaskFilters = FXCollections.observableArrayList();
selectedTaskFilters = FXCollections.observableArrayList();


}

public ModelManager() {
Expand Down Expand Up @@ -450,4 +454,22 @@ private void changeAllTaskContactNames(Name oldName, Name newName) {
public CommandHistory getCommandHistory() {
return commandHistory;
}

//========== Command History Stack ==================================================================


@Override
public String getHistoryCommand(boolean isNext, String currentString) {
return this.historyStorage.getHistoryString(isNext, currentString).orElse("");
}

@Override
public void addCommandToHistory(String command) {
this.historyStorage.pushCommand(command);
}

@Override
public void resetHistoryPosition() {
this.historyStorage.resetHistoryPosition();
}
}
88 changes: 0 additions & 88 deletions src/main/java/seedu/address/storage/HistoryStorage.java

This file was deleted.

129 changes: 129 additions & 0 deletions src/main/java/seedu/address/storage/InputHistory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package seedu.address.storage;

import java.util.Optional;

/**
* Input History encapsulates the String commands that were executed by the user. It is a stack implementation
* that allows the user to obtain the string of the previous command.
*/
public class InputHistory {

/**
* Doubly linked list implementation with explicit pointers.
*/
private static class CommandHistoryNode {
private final String command;
private CommandHistoryNode previous;
private CommandHistoryNode next;

/**
* Basic constructor to create a new CommandHistoryNode
*
* @param command String of the command.
yeppog marked this conversation as resolved.
Show resolved Hide resolved
*/
public CommandHistoryNode(String command) {
this.command = command;
this.previous = null;
this.next = null;
}

/**
* Adds a node to the right of the current node. Assigns the previous pointer of the new node to this.
*
* @param nextNode Node to be added to the next pointer of the current node.
*/
public void addNext(CommandHistoryNode nextNode) {
this.next = nextNode;
nextNode.previous = this;
}

/**
* Obtains the command encapsulated in the CommandHistoryNode
*
* @return String of the command.
*/
public String getCommand() {
return this.command;
}

public Optional<CommandHistoryNode> getNext() {
return Optional.ofNullable(this.next);
}

public Optional<CommandHistoryNode> getPrevious() {
return Optional.ofNullable(this.previous);
}
}

private CommandHistoryNode start;
private CommandHistoryNode end;
private CommandHistoryNode current;
private String currentString;

public InputHistory() {
}

/**
* Pushes a new command into the stack. Resets the current pointer to null to indicate it is at the command
* after the last command of the stack.
*
* @param command The command that was executed and now being stored in the History stack.
*/
public void pushCommand(String command) {
CommandHistoryNode newCommand = new CommandHistoryNode(command);
if (start == null) {
this.start = newCommand;
} else {
this.end.addNext(newCommand);
}
this.end = newCommand;
this.current = null;
this.currentString = null;
}

/**
* Retrieves the history string by iterating through the stack
*
* @param isNext The direction in which we are traversing the doubly linked list.
* @param currentString The last stored unexecuted input from the user.
* @return Optional of the String to be shown in the text box.
*/
public Optional<String> getHistoryString(boolean isNext, String currentString) {
// if on the last item in stack, we store the current input
if (this.current == null) {
this.currentString = currentString;
if (!isNext) {
this.current = this.end;
} else {
return Optional.of(this.currentString);
}
return Optional.of(
Optional
.ofNullable(this.current)
.orElse(new CommandHistoryNode(""))
.getCommand()
);
}
if (isNext) {
this.current = current.next;
} else {
this.current = current.getPrevious().orElse(this.start);
}
return Optional.of(
Optional
.ofNullable(this.current)
.orElse(new CommandHistoryNode(this.currentString))
.getCommand()
);
}

/**
* Resets the history position to the last element. Called when the text box is cleared.
*/
public void resetHistoryPosition() {
this.currentString = null;
this.current = null;
}

}

21 changes: 21 additions & 0 deletions src/main/java/seedu/address/ui/CommandBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ private void handleCommandEntered() {
}
}

/**
* Set the current commandTextField text to the input text of the function.
* @param text The text to change to.
*/
public void setCommandText(String text) {
commandTextField.setText(text);
commandTextField.positionCaret(text.length());
}

/**
* Obtain the current content in the TextField.
* @return String of the current content.
*/
public String getContent() {
return commandTextField.getText();
}

public boolean isEmpty() {
return commandTextField.getText().equals("");
}

/**
* Sets the command box style to use the default style.
*/
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/seedu/address/ui/MainWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,22 @@ private void setAccelerators() {
e.consume();
}
});

primaryStage.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
EventTarget target = event.getTarget();
boolean isTargetEditableTextInput = (target instanceof TextInputControl) && ((TextInputControl) target)
.isEditable();
String currentString = commandBox.getContent();
if (isTargetEditableTextInput && event.getCode() == KeyCode.UP) {
commandBox.setCommandText(logic.getHistoryCommand(false, currentString));
event.consume();
} else if (isTargetEditableTextInput && event.getCode() == KeyCode.DOWN) {
commandBox.setCommandText(logic.getHistoryCommand(true, currentString));
event.consume();
} else if (commandBox.isEmpty()) {
logic.resetHistoryPosition();
}
});
}

/**
Expand Down
Loading