goatNote.py (5591B)
1 from enum import Enum 2 import re 3 import os 4 5 # Assigning numbers to types of data 6 class tokenTypes (Enum): 7 HEADING = 1 8 DATE = 2 9 TODO = 3 10 BULLETPOINT = 4 11 12 class date: 13 day = 0 14 month = 0 15 year = 0 16 def __init__(self, dateString: str): 17 dateString = dateString.split(".") 18 self.year = int(dateString[0]) 19 self.month = int(dateString[1]) 20 self.day = int(dateString[2]) 21 22 def asString(self): 23 return f"{str(self.year)}.{str(self.month):{'0'}>2}.{str(self.day):{'0'}>2}" 24 25 26 def tokenize(file: str): 27 headingRe = r"\s*\*\s*([A-z0-9 ]+)\s*\*\s*\[(\d\d\d\d[.]\d\d[.]\d\d)\]\s*{(TO[.]DO|DONE)}\s*" 28 bulletPointRe = r"-\s*((\s|[A-z0-9])+)\s*" 29 unprocessed = [] 30 end = False 31 32 while not end: 33 heading = re.match(headingRe, file) 34 bulletPoint = re.match(bulletPointRe, file) 35 36 if heading != None: 37 unprocessed.append(heading.group()) 38 file = file[heading.span()[1]:] 39 40 elif bulletPoint != None: 41 unprocessed.append(bulletPoint.group()) 42 file = file[bulletPoint.span()[1]:] 43 else: 44 end = True 45 46 values = [] 47 types = [] 48 for i in unprocessed: 49 heading = re.findall(headingRe, i) 50 bulletPoint = re.findall(bulletPointRe, i) 51 52 if heading != []: 53 heading = heading[0] 54 values.append(heading[0]) 55 types.append(tokenTypes.HEADING) 56 57 values.append(date(heading[1])) 58 types.append(tokenTypes.DATE) 59 60 if heading[2] == "TO.DO": 61 values.append(True) 62 else: 63 values.append(False) 64 types.append(tokenTypes.TODO) 65 66 elif bulletPoint != []: 67 values.append(bulletPoint[0]) 68 types.append(tokenTypes.BULLETPOINT) 69 70 return values, types 71 72 def printHeading(values, i): 73 if values[i + 2]: 74 toDoString = "DONE" 75 else: 76 toDoString = "TO.DO" 77 print(f"{values[i]:{" "}<30}| {values[i+1].asString()} | {toDoString}") 78 79 def view(values, types): 80 output = "" 81 for i in range(len(values)): 82 if types[i] == tokenTypes.HEADING: 83 output += values[i] + "|" 84 if types[i] == tokenTypes.DATE: 85 output += values[i].asString() + "|" 86 if types[i] == tokenTypes.TODO: 87 if not values[i]: 88 output += "DONE\n" 89 else: 90 output += "TO.DO\n" 91 if types[i] == tokenTypes.BULLETPOINT: 92 output += str(values[i][0]) 93 return output 94 95 def outputGoatNote(values, types): 96 output = "" 97 for i in range(len(values)): 98 if types[i] == tokenTypes.HEADING: 99 output += "* " + values[i] + " * " 100 if types[i] == tokenTypes.DATE: 101 output += "[" + values[i].asString() + "] " 102 if types[i] == tokenTypes.TODO: 103 if not values[i]: 104 output += "{DONE}\n" 105 else: 106 output += "{TO.DO}\n" 107 if types[i] == tokenTypes.BULLETPOINT: 108 output += "- " + str(values[i][0]) 109 return output 110 111 # MAIN CODE STARTS HERE Put user into shell then ask for which file to read from 112 fileName = input("Which GOATED file do you wanna read?? \n") 113 if fileName == "": fileName = f"{os.environ["HOME"]}/.global.gn" 114 if ".gn" not in fileName: 115 print("That's not a goatNote file! Silly goose! Automatically putting you into the global file!") 116 fileName = f"{os.environ["HOME"]}/.global.gn" 117 118 try: file = open(fileName, "r") 119 except: 120 print("ABORT MISSION (couldn't open file)", fileName, "does not exist") 121 exit(1) 122 123 values, types = tokenize(file.read()) 124 file.close() 125 126 file = open(fileName, "w") 127 128 # Drop user into a shell 129 print("enter one of the following commands: list, toggle, view, help, save, or type close (make sure to save first!!) to exit program") 130 line = input(": ").lower().split(" ") 131 132 while line[0] != "close": 133 if line[0] == "list": 134 for i in range(len(types)): 135 if types[i] == tokenTypes.HEADING: 136 printHeading(values, i) 137 138 elif line[0] == "toggle": 139 for i in range(len(types)): 140 if types[i] == tokenTypes.HEADING: 141 if values[i] == line[1]: 142 values[i+2] = not values[i+2] 143 break 144 145 elif line[0] == "view": 146 print(view(values, types)) 147 148 elif line[0] == "help": 149 if len(line) == 1: print("enter one of the following commands following the word \"help\": list, toggle, view, formatting, save, or type close (make sure to save first!!) to exit program") 150 elif line[1] == "list": print("This command allows you to view a list of all the headings you have in one file.") 151 elif line[1] == "toggle": print("This command allows you to change any specific goatNote from to-do to done. To use this command, type \"toggle (header you want to change)\"") 152 elif line[1] == "view": print("This command allows you to view and read every goatNote you have in your selected file.") 153 elif line[1] == "formatting": print("The formatting style for goatNote files is as follows: \n * heading * [yyyy.mm.dd] {TO.TO/DONE} \n - note body") 154 else: print("enter one of the following commands following the word \"help\": list, toggle, view, formatting, or type close to exit program") 155 156 elif line[0] == "save": 157 file.write(outputGoatNote(values, types)) 158 file.flush() 159 #save file 160 161 else: 162 print("Invalid command :(") 163 164 line = input(": ").lower().split(" ") 165 166 print("byee(closing program)") 167 file.close()