214 lines
6.1 KiB
Python
Executable file
214 lines
6.1 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
# import modules
|
|
import os
|
|
import re
|
|
import json
|
|
import time
|
|
from sys import stdout
|
|
from sys import exit as byebye
|
|
|
|
# global variables for reuse
|
|
appName = "Task"
|
|
dirName = "hello-task"
|
|
homeDir = os.path.expanduser("~")
|
|
targetDir = homeDir + "/.local/share/" + dirName
|
|
#targetFile = targetDir + "/tasks.json"
|
|
data = {}
|
|
data["tasks"] = []
|
|
data["settings"] = []
|
|
updateMsg = ""
|
|
idCounter = 1
|
|
unixDay = 86400
|
|
|
|
# clear screen buffer
|
|
def clearScreen():
|
|
os.system("cls" if os.name == "nt" else "clear")
|
|
|
|
# get custom task lists
|
|
clearScreen()
|
|
print("Select a task list:")
|
|
listOfLists = []
|
|
for i in os.listdir(targetDir):
|
|
print(len(listOfLists), i[:-5])
|
|
listOfLists.append(i[:-5])
|
|
inputList = input("> ")
|
|
try:
|
|
inputInt = int(inputList)
|
|
targetFile = targetDir + "/" + listOfLists[inputInt] + ".json"
|
|
except ValueError:
|
|
targetFile = targetDir + "/" + inputList + ".json"
|
|
|
|
# function is used by read and write functions
|
|
def timeGrab():
|
|
return int(time.time())
|
|
|
|
|
|
# check if JSON exists, execute creation if not
|
|
def jsonCheck():
|
|
try:
|
|
f = open(targetFile)
|
|
taskList(targetFile)
|
|
except:
|
|
jsonCreate()
|
|
|
|
|
|
# create JSON file and directory
|
|
def jsonCreate():
|
|
if not os.path.exists(targetDir):
|
|
os.mkdir(targetDir, 0o755)
|
|
data["settings"].append({
|
|
"idCounter": idCounter,
|
|
"lvl": 3
|
|
})
|
|
with open(targetFile, "w") as taskfile:
|
|
json.dump(data, taskfile)
|
|
taskList(targetFile)
|
|
|
|
|
|
# write new content to JSON file
|
|
def jsonWrite(n):
|
|
global updateMsg
|
|
global data
|
|
global idCounter
|
|
# it's important to 'try' otherwise entries that don't end in
|
|
# the search string will cause massive errors
|
|
try:
|
|
dueTime = re.search(r'in\s+(.+?)\s+day(s\b|\b)', n, re.M|re.I)
|
|
dueTemp = re.search(r'(\d+)', dueTime.group(), re.M|re.I)
|
|
task = n[:-(len(dueTime.group())+1)]
|
|
data["tasks"].append({
|
|
"id": idCounter,
|
|
"task": task,
|
|
# we need to reduce the due time by one second to prevent
|
|
# the timer showing a wrong due date after creation
|
|
"due": timeGrab()+(int(dueTemp.group())*unixDay-1)
|
|
})
|
|
except:
|
|
task = n
|
|
data["tasks"].append({
|
|
"id": idCounter,
|
|
"task": task
|
|
})
|
|
idCounter += 1
|
|
data["settings"][0]["idCounter"] = idCounter
|
|
updateMsg = "[+] Added new task to list!"
|
|
with open(targetFile, "w") as outfile:
|
|
json.dump(data, outfile)
|
|
taskList(targetFile)
|
|
|
|
|
|
# remove item from JSON file
|
|
def jsonRemove(n):
|
|
global updateMsg
|
|
# we need to make sure that we're dealing with a number
|
|
try:
|
|
check = int(n)
|
|
for i in range(len(data["tasks"])):
|
|
if data["tasks"][i]["id"] == check:
|
|
data["tasks"].pop(i)
|
|
with open (targetFile, "w") as outfile:
|
|
json.dump(data, outfile)
|
|
updateMsg = "[-] Removed task id " + n
|
|
break
|
|
else:
|
|
updateMsg = "[!] Unable to find task id " + n
|
|
except ValueError:
|
|
updateMsg = "[!] Please use the id of the task"
|
|
taskList(targetFile)
|
|
|
|
|
|
# read JSON file into memory and print to stdout
|
|
def jsonRead(content):
|
|
global data
|
|
global idCounter
|
|
global updateMsg
|
|
with open(content) as objects:
|
|
data = json.load(objects)
|
|
if idCounter <= 1:
|
|
idCounter = data["settings"][0]["idCounter"]
|
|
# this needs to sort o into lists for further displaying
|
|
# as grouped items according to due date
|
|
for o in data["tasks"]:
|
|
print(("[" + str(o["id"]) + "] " + o["task"]))
|
|
try:
|
|
days = int(o["due"]) - timeGrab()
|
|
days = days/24/60/60+1
|
|
if days < 0:
|
|
print("Overdue\n")
|
|
elif days < 1:
|
|
print("Due today\n")
|
|
elif days < 2:
|
|
print("Due tomorrow\n")
|
|
else:
|
|
print(("Due in " + str(int(days)) + " days\n"))
|
|
except:
|
|
print("Whenever you feel like it\n")
|
|
|
|
|
|
# display JSON content as task list
|
|
def taskList(tasks):
|
|
clearScreen()
|
|
jsonRead(tasks)
|
|
stdout.write("\x1b]2;" + appName + "\x07")
|
|
if not updateMsg == "":
|
|
print(updateMsg)
|
|
userInput()
|
|
|
|
|
|
# await user input and add or remove tasks
|
|
def userInput():
|
|
global updateMsg
|
|
print("Type 'help' or '?' for more info")
|
|
choice = input("> ").strip()
|
|
if (choice.lower() == "help") or (choice == "?"):
|
|
userHelp()
|
|
elif (choice.lower() == "quit") or (choice.lower() == "exit"):
|
|
byebye
|
|
elif choice.startswith(":d"):
|
|
jsonRemove(choice[2:].strip())
|
|
elif choice.startswith(":lvl"):
|
|
settingsUpdate(choice[1:4], choice[4:5])
|
|
elif choice == "":
|
|
updateMsg = "[?] Not sure what to do"
|
|
taskList(targetFile)
|
|
else:
|
|
jsonWrite(choice)
|
|
|
|
|
|
# update user settings
|
|
def settingsUpdate(m, n):
|
|
global updateMsg
|
|
updateMsg = "[+] View level at " + n
|
|
taskList(targetFile)
|
|
|
|
|
|
# short help print
|
|
def userHelp():
|
|
clearScreen()
|
|
print("""
|
|
I8 ,dPYb,
|
|
I8 IP'`Yb
|
|
88888888 I8 8I
|
|
I8 I8 8bgg,
|
|
I8 ,gggg,gg ,g, I8 dP" "8
|
|
I8 dP" "Y8I ,8'8, I8d8bggP"
|
|
,I8, i8' ,8I ,8' Yb I8P' "Yb,
|
|
,d88b,,d8, ,d8b,,8'_ 8) ,d8 `Yb,
|
|
8P""Y8P"Y8888P"`Y8P' "YY8P8P88P Y8
|
|
""")
|
|
print("A todo list application\n")
|
|
print("Task allows you to quickly create to-do lists by typing them without any additional frizz. Write anything into the input field and see it added as a new item.")
|
|
print("Task understands you. By using a natural suffix like 'in 3 days', Task will automatically create a timestamp and sort the added task according to it's due date.")
|
|
print("Once a task is finished, you can use it's id and delete it by typing ':d id' where 'id' would be the number displayed with the task.")
|
|
print("""\nAvailable commands are:
|
|
|
|
:d(id) - Remove a task by ID
|
|
help/? - View this screen
|
|
quit/exit - exit the application""")
|
|
input("\nPress return to go back...")
|
|
taskList(targetFile)
|
|
|
|
# execute program
|
|
jsonCheck()
|