Skip to content

Commit

Permalink
Merge pull request nus-cs2103-AY1718S2#99 from Aquarinte/v1.3
Browse files Browse the repository at this point in the history
Add support for basic autocomplete
  • Loading branch information
chialejing committed Mar 30, 2018
2 parents dc469d1 + bddfe53 commit bdeb528
Show file tree
Hide file tree
Showing 10 changed files with 434 additions and 8 deletions.
12 changes: 8 additions & 4 deletions docs/DeveloperGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ After the appointment class being finished, we'll be able to implement `setAppoi

We may also make enhancements to the Medeina's UI such as changing theme colour to match the UI colour of CalendarFX.

=== [Proposed] Command Syntax
=== Improvements to Command Syntax
==== Current Implementation

Command syntax can be long and complicated as there is a lot of information required from the user for each of the three classes: `Person.java`, `PetPatient.java` and `Appointment.java`.
Expand Down Expand Up @@ -482,10 +482,14 @@ Keeping to one main command is simpler and more user-friendly as compared to hav
===== Aspect: Improving user-friendliness

* Command syntax highlighting
** Use different colours to highlight [COMMAND WORDS], [PARSING OPTIONS] and [USER INPUT] --> improve readability for the user
** Use different colours to highlight [COMMAND WORDS], [PARSING OPTIONS] and [USER INPUT] to improve readability for the user.

* Command auto-complete
** auto-complete of prefixes using the `tab` key to increase efficiency of using Medeina --> reduce typing and mistypes to improve efficiency in using the application.
image::autocomplete.png[width="500"]

* Command syntax auto-complete suggestions
** auto-complete suggestions of command words, options and prefixes shown on a ContextMenu.
** User can traverse through the suggestions in the ContextMenu using kbd:[Up] and kbd:[Down], or kbd:[Tab].
** Press kbd:[Enter] to select the suggestion in the ContextMenu and the command box will be updated.

// end::commandsyntax[]

Expand Down
19 changes: 15 additions & 4 deletions docs/UserGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
* **`delete`**`3` : deletes the 3rd contact shown in the current list
* *`exit`* : exits the app

. Refer to section 3: <<Features>> for details of each command.
. Refer to <<Features>> for details of each command.

[[Features]]
== Features
Expand All @@ -74,12 +74,22 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
* Parameters can be in any order e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
* Shorthand equivalent alias is available for all commands to simplify execution of commands.
====
====
*Command autocomplete in Medeina :* `[Since v1.3]`
image::autocomplete.png[width="500"]
* Medeina supports autocomplete for command words, options and prefixes.
* You will also be shown a list of existing NRICs and a list of existing pet patients names when you need to reference them in `*-o* nr/OWNER_NRIC` and `*-p* n/PET_PATIENT_NAME` respectively.
* You can use kbd:[Up] and kbd:[Down], or kbd:[Tab] to traverse through the autocomplete suggestions in the pop-up context menu.
* Press kbd:[Enter] to select an autocomplete suggestion on the pop-up context menu.
====

=== Viewing help : `help` or `h`

If you are feeling lost, enter `help` or `h` in Medeina's command box, or press kbd:[F1] to bring up this user guide document in a pop-up window.
If you are feeling lost, enter `help` or `h` in Medeina's command box, or press kbd:[Enter] to bring up this user guide document in a pop-up window.

=== Adding a contact, pet patient or appointment : `add` or `a`
=== Adding a contact, pet patient or appointment : `add` or `a` `[Since v1.2]`

You can use the `add` or `a` to do the following :

Expand Down Expand Up @@ -281,7 +291,8 @@ The command format should be: `clear` or `cls`
====
This command **cannot** be undone. Please be certain that you have backed up your data (which is located in the `data` folder) before executing this command!
====
=== Changing theme : `theme` or `t`

=== Changing theme : `theme` or `t` `[Since v1.1]`

To change Medeina's current theme to another pre-loaded theme. +
The command format should be: `theme THEME_NAME` or `t THEME_NAME`
Expand Down
Binary file added docs/images/autocomplete.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions src/main/java/seedu/address/logic/CommandSyntaxWords.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package seedu.address.logic;

import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_BLOODTYPE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_BREED;
import static seedu.address.logic.parser.CliSyntax.PREFIX_COLOUR;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NRIC;
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_REMARK;
import static seedu.address.logic.parser.CliSyntax.PREFIX_SPECIES;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;

import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import seedu.address.logic.commands.AddCommand;
import seedu.address.logic.commands.ChangeThemeCommand;
import seedu.address.logic.commands.ClearCommand;
import seedu.address.logic.commands.DeleteCommand;
import seedu.address.logic.commands.EditCommand;
import seedu.address.logic.commands.ExitCommand;
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.HistoryCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.commands.RedoCommand;
import seedu.address.logic.commands.UndoCommand;
import seedu.address.logic.parser.Prefix;

//@@author aquarinte
/**
* Stores all command syntax used in Medeina: command words, prefixes and options.
*/
public class CommandSyntaxWords {

private static CommandSyntaxWords instance;

private static final Set<String> commandWords = Stream.of(
AddCommand.COMMAND_WORD, EditCommand.COMMAND_WORD, DeleteCommand.COMMAND_WORD, ListCommand.COMMAND_WORD,
FindCommand.COMMAND_WORD, ChangeThemeCommand.COMMAND_WORD, ClearCommand.COMMAND_WORD,
HelpCommand.COMMAND_WORD, ExitCommand.COMMAND_WORD, RedoCommand.COMMAND_WORD, UndoCommand.COMMAND_WORD,
HistoryCommand.COMMAND_WORD).collect(Collectors.toSet());

private static final Set<Prefix> prefixes = Stream.of(
PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_NRIC, PREFIX_BREED, PREFIX_SPECIES,
PREFIX_COLOUR, PREFIX_BLOODTYPE, PREFIX_DATE, PREFIX_REMARK, PREFIX_TAG).collect(Collectors.toSet());

private static final Set<String> options = Stream.of("-o", "-p", "-a").collect(Collectors.toSet());

public static CommandSyntaxWords getInstance() {
if (instance == null) {
instance = new CommandSyntaxWords();
}
return instance;
}

public Set<String> getCommandWords() {
return commandWords;
}

public Set<Prefix> getPrefixes() {
return prefixes;
}

public Set<String> getOptions() {
return options;
}
}
18 changes: 18 additions & 0 deletions src/main/java/seedu/address/logic/Logic.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package seedu.address.logic;

import java.util.Set;

import javafx.collections.ObservableList;
import seedu.address.logic.commands.CommandResult;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.logic.parser.Prefix;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.Person;

Expand All @@ -24,4 +27,19 @@ public interface Logic {

/** Returns the list of input entered by the user, encapsulated in a {@code ListElementPointer} object */
ListElementPointer getHistorySnapshot();

/** Returns a set of all command words */
Set<String> getAllCommandWords();

/** Returns a set of all prefixes */
Set<Prefix> getAllPrefixes();

/** Returns a set of all options used in command syntax */
Set<String> getAllOptions();

/** Returns a set of all Nric found in model*/
Set<String> getAllNric();

/** Returns a set of all pet patient names found in model*/
Set<String> getAllPetPatientNames();
}
41 changes: 41 additions & 0 deletions src/main/java/seedu/address/logic/LogicManager.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package seedu.address.logic;

import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;

import javafx.collections.ObservableList;
Expand All @@ -9,9 +11,11 @@
import seedu.address.logic.commands.CommandResult;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.logic.parser.AddressBookParser;
import seedu.address.logic.parser.Prefix;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.Model;
import seedu.address.model.person.Person;
import seedu.address.model.petpatient.PetPatient;

/**
* The main LogicManager of the app.
Expand All @@ -24,11 +28,14 @@ public class LogicManager extends ComponentManager implements Logic {
private final AddressBookParser addressBookParser;
private final UndoRedoStack undoRedoStack;

private CommandSyntaxWords commandSyntax;

public LogicManager(Model model) {
this.model = model;
history = new CommandHistory();
addressBookParser = new AddressBookParser();
undoRedoStack = new UndoRedoStack();
commandSyntax = CommandSyntaxWords.getInstance();
}

@Override
Expand All @@ -54,4 +61,38 @@ public ObservableList<Person> getFilteredPersonList() {
public ListElementPointer getHistorySnapshot() {
return new ListElementPointer(history.getHistory());
}

//@@author aquarinte
@Override
public Set<String> getAllCommandWords() {
return commandSyntax.getCommandWords();
}

@Override
public Set<Prefix> getAllPrefixes() {
return commandSyntax.getPrefixes();
}

@Override
public Set<String> getAllOptions() {
return commandSyntax.getOptions();
}

@Override
public Set<String> getAllNric() {
Set<String> allNricInModel = new HashSet<>();
for (Person p : model.getAddressBook().getPersonList()) {
allNricInModel.add(p.getNric().toString());
}
return allNricInModel;
}

@Override
public Set<String> getAllPetPatientNames() {
Set<String> allPetPatientNamesInModel = new HashSet<>();
for (PetPatient p : model.getAddressBook().getPetPatientList()) {
allPetPatientNamesInModel.add(p.getName().toString());
}
return allPetPatientNamesInModel;
}
}
100 changes: 100 additions & 0 deletions src/main/java/seedu/address/ui/Autocomplete.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package seedu.address.ui;

import java.util.HashSet;
import java.util.Set;
//import java.util.regex.Pattern;

import javafx.scene.control.TextField;
import seedu.address.logic.Logic;
import seedu.address.logic.parser.Prefix;

//@@author aquarinte
/**
* Handles autocompletion of command input such as command word, options and prefixes.
*/
public class Autocomplete {

/*private static final Pattern ADD_COMMAND1 = Pattern.compile("add -(a)+(?<apptInfo>.*)-(o)(?<ownerNric>.*)"
+ "-(p)+(?<petName>.*)");
private static final Pattern ADD_COMMAND2 = Pattern.compile("add -(p)+(?<petInfo>.*)-(o)+(?<ownerNric>.*)");
private static final Pattern ADD_COMMAND3 = Pattern.compile("add -(o)+(?<ownerInfo>.*)-(p)+(?<petInfo>.*)"
+ "-(a)+(?<apptInfo>.*)");
private static final Pattern ADD_COMMAND4 = Pattern.compile("add -(o)+(?<ownerInfo>.*)");
*/
private static Autocomplete instance;
private Set<String> suggestions;

public static Autocomplete getInstance() {
if (instance == null) {
instance = new Autocomplete();
}
return instance;
}

/**
* Find suggestions for current user-input in commandTextField.
*/
public Set<String> getSuggestions(Logic logic, TextField commandTextField) {
suggestions = new HashSet<>();
String userInput = commandTextField.getText().trim();
String[] words = userInput.split(" ");
//for (String s : words) {
//System.out.println("Word: " + s);
//}
//The string to auto-complete:
String target = words[words.length - 1];

if (words.length == 1) {
suggestCommandWords(logic, words[0]);
} else {

if (words[words.length - 2].equals("-o") && target.equals("nr/")) {
for (String nric : logic.getAllNric()) {
suggestions.add(nric);
}
}

if (words[words.length - 2].equals("-p") && target.equals("n/")) {
for (String petName : logic.getAllPetPatientNames()) {
suggestions.add(petName);
}
}
suggestOptions(logic, target);
suggestPrefixes(logic, target);
}
return suggestions;
}

/**
* Find suggestions for prefixes.
*/
private void suggestPrefixes(Logic logic, String target) {
for (Prefix p : logic.getAllPrefixes()) {
if (p.toString().startsWith(target) && !p.toString().equals(target)) {
suggestions.add(p.toString());
}
}
}

/**
* Find suggestions for options.
*/
private void suggestOptions(Logic logic, String target) {
for (String option : logic.getAllOptions()) {
if (option.startsWith(target) && !option.equals(target)) {
suggestions.add(option);
}
}
}

/**
* Find suggestions for command word.
*/
private void suggestCommandWords(Logic logic, String word) {
for (String command : logic.getAllCommandWords()) {
if (command.startsWith(word) && !command.equals(word)) {
suggestions.add(command);
}
}
}
}
Loading

0 comments on commit bdeb528

Please sign in to comment.