From ecd4120b0a82f3f5be0f1caa6223a461c07b53a7 Mon Sep 17 00:00:00 2001 From: Rapturate Date: Mon, 23 Feb 2026 09:50:15 -0500 Subject: [PATCH] Gitea Migration --- LICENSE | 18 ++ README.md | 3 + To_Do_List_Console.jar | Bin 0 -> 9509 bytes bin/list.txt | 6 + src/Item.java | 224 +++++++++++++++++++ src/MainLoop.java | 21 ++ src/ToDoList.java | 481 +++++++++++++++++++++++++++++++++++++++++ src/UserInterface.java | 115 ++++++++++ 8 files changed, 868 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 To_Do_List_Console.jar create mode 100644 bin/list.txt create mode 100644 src/Item.java create mode 100644 src/MainLoop.java create mode 100644 src/ToDoList.java create mode 100644 src/UserInterface.java diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..37db34f --- /dev/null +++ b/LICENSE @@ -0,0 +1,18 @@ +MIT License + +Copyright (c) 2026 rapturate + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b8da1a4 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# To_Do_List + +A console To Do List, written in Java, for a software development class. Shows my functional understanding of Java and organizational skills for code \ No newline at end of file diff --git a/To_Do_List_Console.jar b/To_Do_List_Console.jar new file mode 100644 index 0000000000000000000000000000000000000000..b4250d351fbd59e8f48029345e270a9d23540d87 GIT binary patch literal 9509 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 literal 0 HcmV?d00001 diff --git a/bin/list.txt b/bin/list.txt new file mode 100644 index 0000000..5eab067 --- /dev/null +++ b/bin/list.txt @@ -0,0 +1,6 @@ +Health, Doctors Appointment, 10/31/2025, 2 +Health, Dentist Appointment, 10/31/2025, 3 +School, School Visit, 11/22/2025, 3 +Rover, Sadie, 11/22/1995, 4 +Rover, Sadie and Finn, 09/10/2025, 4 +na, Dog Sit, 12/31/1969, 10 diff --git a/src/Item.java b/src/Item.java new file mode 100644 index 0000000..02dc2ef --- /dev/null +++ b/src/Item.java @@ -0,0 +1,224 @@ + + + + + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class Item { + private String category = " "; + private String name; + private Date dueDate; + private int priority = 10; + + //Constructors + /** + * Initializes an {@code Item} object. + *

+ * Usage: + * {@snippet : + * Item item = new Item("Jump up and down"); + * } + * @param String The name of the item to do. + * @return {@code void} + */ + public Item(String name){ + this.name = name; + } + + public Item(String name, String category, String dateString, int priority){ + SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); + + this.name = name; + this.category = category; + try { + this.dueDate = formatter.parse(dateString); + } catch (ParseException e){ + System.out.println("Date formatting failed."); + e.printStackTrace(); + } + this.priority = priority; + + } + //Setters + + // Method Signature: setCategoty(String) -> void + // Purpose: sets the category name + // Example: Item.setCategory("Health") + + /** + * Sets the {@code String category} field. + *

+ * Usage: + * {@snippet : + * item.setCategory("Health"); + * } + * @param String The String for {@code Private String category}. + * @return {@code void} + */ + public void setCategory(String category){ + this.category = category; + } + + // Method Signature: setName(String) -> void + // Purpose: sets the name of the event + // Example: Item.setName("Workout") + + /** + * Sets the {@code private String name} field. + *

+ * Usage: + * {@snippet : + * item.setName("Field Work"); + * } + * @param String The String for {@code Private String name}. + * @return {@code void} + */ + public void setName(String name){ + this.name = name; + } + + // Method Signature: setDueDate(String) -> void + // Purpose: sets the date. This class takes in a String, converts it into a Date and puts it into dueDate. + // Default: if the date is input incorrectly, it defaults to 12/31/1969. + // Example: Item.setCategory(dateString) + + /** + * Sets the {@code private Date dueDate} field. + *

+ * The date MUST be formatted as MM/DD/YYYY. + *

+ * Usage: + * {@snippet : + * item.setDueDate("MM/DD/YYYY"); + * } + * @param String The String that will be formatted for {@code Private Date dueDate}. + * @return {@code void} + */ + public void setDueDate(String dateString){ + SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); + Date date = new Date(0); + try { + date = formatter.parse(dateString); + } catch (ParseException e){ + System.out.println("Bad Date format."); + } + + this.dueDate = date; + } + + // Method Signature: setPriority(int) -> void + // Purpose: sets the priority on a scale of 1-10. 10 being the least important and 1 being the most. + // Example: Item.setPriority(1) + + /** + * Sets the {@code private int priority} field. + *

+ * Usage: + * {@snippet : + * item.setPriority(10); + * } + * @param int The integer for {@code Private String priority}. + * @return {@code void} + */ + public void setPriority(int priority){ + this.priority = priority; + } + + + //Getters + + /** + * Gets the String stored in {@code private String category} field. + *

+ * Usage: + * {@snippet : + * String category = item.getCategory(); + * } + * @return {@code String} + */ + public String getCategory() { + return this.category; + } + + /** + * Gets the String stored in {@code private String name} field. + *

+ * Usage: + * {@snippet : + * String name = item.getName(); + * } + * @return {@code String} + */ + public String getName() { + return this.name; + } + + /** + * Gets the {@code Date} object stored in {@code private int dueDate} field. + *

+ * Usage: + * {@snippet : + * Date dueDate = item.getDueDate(); + * } + * @return {@code Date} + */ + public Date getDueDate() { + return this.dueDate; + } + + /** + * Gets the integer stored in {@code private int dueDate} field and converts it to a {@code String}. + *

+ * Usage: + * {@snippet : + * String dueDateString = item.getDueDateString(); + * } + * @return {@code String} + */ + public String getDueDateString(){ + SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); + return formatter.format(this.dueDate); + } + + /** + * Gets the integer stored in {@code private int priority} field. + *

+ * Usage: + * {@snippet : + * int priority = item.getPriority(); + * } + * @return {@code int} + */ + public int getPriority() { + return this.priority; + } + + /** + * Takes all of the fields in {@code Item} and converts them to a formatted {@code String} for command line printing. + *

+ * Usage: + * {@snippet : + * String itemString = item.formatString(); + * } + * @return {@code String}: returns "" if there is no date + */ + public String formatString(){ + String dateString = ""; + + if(dueDate.compareTo(new Date(0)) != 0 ){ //If the compareTo funcioon returns 0 than the date is set to default which means 12/31/1969. + SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyy"); + dateString = format.format(this.dueDate); + if(dateString.equals("12/31/1969")){ + dateString = ""; + } + } + if(this.category.equals("na")){ + this.category = ""; + } + + return String.format("%-23s %-20s %-12s %-10d\n", this.name, this.category, dateString, this.priority); + } + } \ No newline at end of file diff --git a/src/MainLoop.java b/src/MainLoop.java new file mode 100644 index 0000000..bea2fb8 --- /dev/null +++ b/src/MainLoop.java @@ -0,0 +1,21 @@ +import java.util.Scanner; + +/** + * + * @author Lewis Price + * @since 1.0 + */ + +public class MainLoop { + public static void main(String[] args) { + String listPath; + System.out.println("Enter the path to where you want the todo list file to be."); + Scanner scanner = new Scanner(System.in); + listPath = scanner.next(); + + UserInterface ui = new UserInterface(listPath); + ui.run(); + + scanner.close(); + } +} diff --git a/src/ToDoList.java b/src/ToDoList.java new file mode 100644 index 0000000..6b36c8f --- /dev/null +++ b/src/ToDoList.java @@ -0,0 +1,481 @@ + + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.InputMismatchException; +import java.util.Scanner; + +public class ToDoList { + private ArrayList listArr; + private String pathName; + private Scanner scanner; + private String listHeader = String.format("%-23s %-20s %-12s %-10s\n----------------------------------------------------------------------------------------------------\n" + , "Name", "Category", "Date", "Priority"); + private String footer = "----------------------------------------------------------------------------------------------------\n"; + + //Constructor + /** + * Constructor for creating a new ToDoList. + * + * {@snippet : + * ToDoList list = new ToDoList( [filePath] , [Scanner Object] ); + * } + * + * @param pathName Takes the path of the list.txt file to open or create a new file. + * @param Scanner Scanner passthrough to prevent {@code Scanner} clashes. + */ + public ToDoList(String pathName, Scanner scanner){ + listArr = new ArrayList(); + this.pathName = pathName; + this.scanner = scanner; + openList(); + } + + //Setters + /** + * Used by the system to add a new {@code Item} to the {@code ArrayList} + * + * {@snippet : + * list.addItem( [item] ); + * } + * + * @param Item The {@code Item} being added to the {@code ArrayList} + * @return void + */ + private void addItem(Item item){ + listArr.add(item); + } + + /** + * Used by the system to create a header for console output. + * + * {@snippet : + * formatHeader( "Add Item" ); + * } + * + * @param String: the name of the page that needs a header output string. + * @return {@code String header} + */ + private String formatHeader(String pageName){ + String formatedHeader = ""; + int i; + for(i = 0; i < (50 - pageName.length()/2); i++){ + formatedHeader += "-"; + } + formatedHeader += pageName; + + for( i += pageName.length(); i < 100; i++){ + formatedHeader += "-"; + } + formatedHeader += "\n"; + return formatedHeader; + } + + + + /** + * Begins the System output and input to create and add a new {@code Item} to {@code ArrayList}. + *

+ * Usage + * {@snippet : + * list.addItemAction(); + * } + *

+ * ------------- + *

+ * Defaults: + *

+ * Date: 12/31/1969 + *

+ * - This date is read by the system as null and won't be visibly printed. + *

+ * Category: "na" + *

+ * - "na" is read by the system as null and won't be visibly printed. + *

+ * Priority: 10 + *

+ * - Priority 10 is the least important therefore the default if not provided. + * + * @return void, but prints messages to console. + */ + public void addItemAction() { + System.out.println(formatHeader("Add Item")); + System.out.print("Name (Required): "); + String name = scanner.nextLine(); + Item newItem = new Item(name); + + + System.out.print("Category: "); + String category = scanner.nextLine(); + if(category.equals("na") || category.equals("")) { + category = "na"; + } + newItem.setCategory(category); + + System.out.print("Date (MM/DD/YYYY): "); + String dateString = scanner.nextLine(); + + if(dateString.equals("na") || dateString.equals("")) { + newItem.setDueDate("12/31/1969"); //defaults to 12/31/1969 + } else { + newItem.setDueDate(dateString); + } + + System.out.print("Priority: "); + String priority = scanner.nextLine(); + try { + Integer.parseInt(priority); + } catch (NumberFormatException e){ + priority = "10"; + } + + if(priority.equals("")){ + priority = "10"; + }else if(Integer.parseInt(priority) < 1 || Integer.parseInt(priority) > 10) { + System.out.println("Priority out of range, defaulted to 10."); + priority = "10"; + } + + newItem.setPriority(Integer.parseInt(priority)); + addItem(newItem); + System.out.println("\n\nAdded:\n" + listHeader + newItem.formatString()); + } + + /** + * Takes a {@code String} to create an {@code Item} to {@code ArrayList}. + *

+ * This function must include a all {@code Item} parameters. + *

+ * Usage + * {@snippet : + * list.addItemAction({@code "name, category, date, priority"); + * } + *

+ * + * @param String, parses this string into different sections to create a new {@code Item} + * @return void, but prints messages to console. + */ + public void addItemByString(String inputString) { + String[] parsedString = inputString.split(", "); + Item newItem = new Item(parsedString[0], parsedString[1], parsedString[2], Integer.parseInt(parsedString[3])); + addItem(newItem); + System.out.println("\n\nAdded:\n" + listHeader + newItem.formatString()); + } + + + + + + + /** + * Formats, displays, and deletes an {@code Item} from user input from {@code ArrayList}. + *

+ * Does not save to the txt file. See {@code saveChanges()}. + *

+ * Usage: + * {@snippet : + * list.deleteItem(); + * } + * + * @return void, but prints to console. + */ + public void deleteItem(){ + System.out.println(formatHeader("Delete Item")); + System.out.println("Type one name and all items by that name will be removed."); + System.out.print("Name: "); + String name = scanner.nextLine(); + ArrayList tempList = new ArrayList<>(); + ArrayList deletedItems = new ArrayList<>(); + + //Deletes + for(Item list: listArr){ + if(!list.getName().equalsIgnoreCase(name)){ + tempList.add(list); + } else { + deletedItems.add(list); + } + } + + if(deletedItems.size() > 0){ + System.out.println(formatHeader("Deleted Items")); + for(Item list: deletedItems){ + System.out.print(list.formatString()); + } + System.out.print(footer); + listArr = tempList; + saveChanges(); + } else { + System.out.println("No item by that name."); + } + } + + /** + * Formats, displays, and changes an {@code Item} from user input from {@code ArrayList}. + *

+ * Does not save to the txt file. See {@code saveChanges()}. + *

+ * Usage: + * {@snippet : + * list.changeItem(); + * } + * + * @return void, but prints to console. + */ + public void changeItem(){ + System.out.println(formatHeader("Change Item")); + ArrayList alteredItems = new ArrayList<>(); + System.out.println(); + + System.out.println("Type the name of the item you'd like to change."); + System.out.print("Name: "); + String name = scanner.nextLine(); + + System.out.println("What aspect would you like to change?"); + System.out.println("Type 'Name', 'Category', 'Date' or 'Priority'."); + System.out.print("Response: "); + String response = scanner.nextLine(); + + int changeCount = 0; + + //Change Name + if(response.equalsIgnoreCase("Name")){ + System.out.print("New Name: "); + String newName = scanner.nextLine(); + + for(Item changedItem : listArr){ + if(changedItem.getName().equalsIgnoreCase(name)){ + alteredItems.add(changedItem); + changedItem.setName(newName); + changeCount++; + } + } + System.out.println(String.format("%d item(s) changed", changeCount)); + + //Change Category + } else if(response.equalsIgnoreCase("Category")){ + System.out.print("\nNew Category Name: "); + String newCatName = scanner.nextLine(); + for(Item changedItem : listArr){ + if(changedItem.getName().equalsIgnoreCase(name)){ + alteredItems.add(changedItem); + changedItem.setCategory(newCatName); + changeCount++; + } + } + System.out.println(String.format("%d item(s) changed", changeCount)); + + //Change Date + } else if(response.equalsIgnoreCase("Date")){ + System.out.print("New Date (MM/DD/YYY): "); + String dateString = scanner.nextLine(); + for(Item changedItem : listArr){ + if(changedItem.getName().equalsIgnoreCase(name)){ + alteredItems.add(changedItem); + changedItem.setDueDate(dateString); + changeCount++; + } + } + System.out.println(String.format("%d item(s) changed", changeCount)); + + //Change Priority + } else if(response.equalsIgnoreCase("Priority")){ + System.out.print("New Priority: "); + + for(Item changedItem : listArr){ + if(changedItem.getName().equalsIgnoreCase(name)){ + try { + String newPriorityString = scanner.nextLine(); + alteredItems.add(changedItem); + int newPriority = Integer.parseInt(newPriorityString); + changedItem.setPriority(newPriority); + changeCount++; + + } catch (InputMismatchException e) { + System.out.println("Not an integer. Nothing changed."); + } + } + } + + System.out.println(String.format("%d item(s) changed", changeCount)); + + //Bad Input + } else { + System.out.println("Bad input, nothing altered."); + } + + //Print Changed Items + System.out.print(listHeader); + for(Item item : alteredItems){ + System.out.println(item.formatString()); + } + System.out.print(footer); + printList(); + } + + + /** + *Opens a {@code .txt file} from a developers {@code main} function. + *

+ * Usage: + * {@snippet : + * list.openList(); + * } + * + * @return void, but prints to console. + */ + public void openList(){ + File listFile = new File(pathName); + try(Scanner fileReader = new Scanner(listFile)){ + while (fileReader.hasNextLine()) { + + String line = fileReader.nextLine(); + String[] splitLine = line.split(", "); + Item item = new Item(splitLine[1]); + + if(splitLine.length == 0){ + break; + } + + if(splitLine[0].equals("na")){ + item.setCategory(""); + } else { + item.setCategory(splitLine[0]); + } + + if(splitLine[2].equals("12/31/1969")){ + item.setDueDate("12/31/1969"); + } else { + item.setDueDate(splitLine[2]); + } + + if(splitLine[3].equals("na")){ + item.setPriority(10); + } else { + item.setPriority(Integer.parseInt(splitLine[3])); + } + + listArr.add(item); + } + } catch (FileNotFoundException e) { + System.out.println("No Previous List. Creating a new one."); + File file = new File(pathName); + try{ + file.createNewFile(); + + } catch(IOException failed){ + System.out.println("File creation failed."); + failed.printStackTrace(); + } + } + } + + + //Organization + /** + * Sorts the {@code ArrayList} by asking users which field they want to sort by. + *

+ * Does not save to the txt file. See {@code saveChanges()}. + *

+ * Usage: + * {@snippet : + * list.sortBy(); + * } + * + * @return void, but prints to console. + */ + public void sortBy(){ + System.out.println(formatHeader("Sort By")); + System.out.println( "- Category: Alphabetically by category name then alphabetically by Name.\n" + + "- Name: Alphabetically by Name.\n" + + "- Date: Earliest Date first, then by Category for repeated Dates.\n" + + "- Priorty: 1 is most important, 10 is least important. If Priorities are equal, sorted by Date. \n"); + System.out.print("Option: "); + String organizeBy = scanner.nextLine(); + if(organizeBy.equalsIgnoreCase("category")){ + listArr.sort(Comparator.comparing(Item::getCategory).thenComparing(Item::getName)); + + } else if(organizeBy.equalsIgnoreCase("name")){ + listArr.sort(Comparator.comparing(Item::getName).thenComparing(Item::getDueDate)); + + } else if(organizeBy.equalsIgnoreCase("date")){ + listArr.sort(Comparator.comparing(Item::getDueDate).thenComparing(Item::getCategory)); + + } else if(organizeBy.equalsIgnoreCase("priority")){ + listArr.sort(Comparator.comparingInt(Item::getPriority).thenComparing(Item::getDueDate)); + + } else { + System.out.println("Cannot organize by that."); + return; + } + } + + /** + * Saves the {@code ArrayList} to the {@code list.txt} using the developer provided {@code path}. + *

+ * Usage: + * {@snippet : + * list.saveChanges(); + * } + * @return void, but prints to console. + */ + public void saveChanges(){ + File file = new File(pathName); + try (FileWriter writer = new FileWriter(file, false)){ + for(Item listInput : listArr){ + String category = listInput.getCategory(); + if(category.equals("")){ + category = "na"; + } + String name = listInput.getName(); + String date = listInput.getDueDateString(); + String priority = Integer.toString(listInput.getPriority()); + + String line = String.format("%s, %s, %s, %s\n",category, name, date, priority); + writer.write(line); + } + writer.close(); + } catch (IOException e){ + System.out.println("File not found."); + e.printStackTrace(); + } + } + + + + //Getters + /** + * Formats a {@code String} from the encapsulated {@code ArrayList listArr}. + *

+ * Usage: + * {@snippet : + * list.openList(); + * } + * + * @return {@code String} + */ + public String printList(){ + String list = footer + + formatHeader("To Do List") + + footer + + listHeader; + for(int i = 0; i < listArr.size(); i++){ + list = list.concat(listArr.get(i).formatString()); + } + return list; + } + + public String getCategory(String category){ + String list = listHeader; + for(int i = 0; i < listArr.size(); i++){ + if(listArr.get(i).getCategory().equals(category)){ + list = list.concat(i+1 + ": " + listArr.get(i).formatString()); + } + } + return list; + } + } diff --git a/src/UserInterface.java b/src/UserInterface.java new file mode 100644 index 0000000..ffa5456 --- /dev/null +++ b/src/UserInterface.java @@ -0,0 +1,115 @@ + +import java.util.Scanner; + +public class UserInterface { + + private String pathName; + private Scanner scanner; + private ToDoList list; + + /** + * Constructor + *

+ * Initializes a {@code UserInterface} object. + *

+ * Usage: + * {@snippet : + * UserInterface ui = new UserInterface("./list.txt"); + * } + * @param String The path to the list.txt file as a string. + */ + public UserInterface(String listPath){ + this.pathName = listPath; //Relative path to the starting .txt file. If one is not found, a new one is created. + this.scanner = new Scanner(System.in); //The only scanner that will be declared in the overall program + this.list = new ToDoList(pathName, scanner); + } + + /** + * Starts a while loop that runs an instance of ToDoList. + *

+ * Usage: + * {@snippet : + * ToDoList list.run(); + * } + * @return {@code void}, but has outputs to the terminal. + */ + public void run(){ + + //Loop that continues until the user inputs "quit". Capitalization not important + while(true){ + printChoices(); + String input = getInput(); + if(runInput(input)) break; + list.saveChanges(); + } + scanner.close(); + } + + + /** + * Formats and prints a consistent "Directions" message. + *

+ * Usage: + * {@snippet : + * printChoices(); + * } + * @return {@code void}, but prints to console. + */ + private void printChoices(){ + System.out.println(list.printList()); + String directionMessage = "\n" + + "-'Home': takes you to your current list.\n" + + "-'Add': adds new item.\n" + + "-'Delete': deletes an item.\n" + + "-'Change': changes an item.\n" + + "-'Organize': organizes based on what you want to organize by.\n" + + "-'Quit': exits the program.\n"; + System.out.println(directionMessage); + } + + /** + * Recieves the {@code String input} via the instance of {@code java.util.Scanner} that was declared in this class. + *

+ * Usage: + * {@snippet : + * String input = getInput(); + * } + * @return {@code String input}, and prints a prompt to console. + */ + private String getInput(){ + System.out.print("Choice: "); + return scanner.nextLine(); + } + + /** + * Recieves the {@code String input} via the instance of {@code java.util.Scanner} that was declared in this class. If the user types "quit", the program quits, otherwise it continues. + *

+ * The {@code input string} is not case sensitive. + *

+ * Usage: + * {@snippet : + * if(runInput("Quit")) break; //this will break out of a loop. + * } + * @param String input: the input {@code String} that {@code runInput()} will use. + * @return {@code boolean endLoop}: returns true if input = "Quit" to end the loop in {@code run()}, false otherwise. + */ + private boolean runInput(String input){ + if(input.equalsIgnoreCase("quit")){ + System.out.println("Bye!"); + return true; + } else if(input.equalsIgnoreCase("Add")){ + list.addItemAction(); + } else if (input.equalsIgnoreCase("Delete")){ + list.deleteItem(); + } else if(input.equalsIgnoreCase("Change")){ + list.changeItem(); + } else if (input.equalsIgnoreCase("Organize")){ + list.sortBy(); + } else if (input.equalsIgnoreCase("Home")){ + System.out.println(list.printList()); + } else { + System.out.println("That was not an option."); + } + return false; + } +}