Last active
April 1, 2022 17:33
-
-
Save pratu16x7/98ff6b94e827c3a9e63f093df7a6113c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
***TINY JOURNALLING APP*** | |
be simple, easy to run, and migratable to any system | |
needs a daylife.md file somewhere, that is the source of all knowledge, | |
which has something a template to fill the day's journal entry with, | |
followed by some fun titles, one of which will be randomly chosen each day. | |
A sample daylife.md could look like this: | |
@template | |
Todays tasks: | |
- [ ] Wake up at 6 | |
- [ ] _ | |
- [ ] _ | |
- [ ] Go to bed at 10 | |
@titles | |
Keep Looking Up | |
Hakuna Matata | |
A New Day Has Come | |
Back from Cryostasis | |
Forth Eorlingas | |
Add the following fou lines to your bash profile to use as a command (run this: `vi ~/.bash_profile`): | |
export JOURNAL_ENTRIES_PATH="/home/pratu16x7/[index] daylifes" | |
export JOURNAL_TEMPLATE_PATH="/home/pratu16x7/daylife.md" | |
export JOURNAL_OPEN_COMMAND="open" | |
alias "journal"="python3 /<path>/<to>/<file>/journal.py" | |
And the reload bash_profile with this on the command line: | |
. ~/.bash_profile | |
The python `fire` module will have to be installed globally | |
Here's a gist of what it does: | |
- makes an entry inside a folder | |
- gives it a random title from the @titles list in daylife.md | |
- fills it with what you tell it to after the '@template' line in daylife.md (can be a list of tasks, sections ... anything) | |
Can be set inside a hugo folder, so that you can style the md pages as you wish with css and make a site | |
- [ ] Handle KeyError: 'JOURNAL_DAYLIFE_PATH' in case not set in env | |
""" | |
import os | |
import random | |
import subprocess | |
import random | |
from datetime import datetime | |
from pathlib import Path | |
from typing import TextIO | |
from lxml import etree | |
import fire | |
ENTRIES_PATH = os.environ['JOURNAL_ENTRIES_PATH'] # "/Users/pratu/Dropbox/sheets/[index] daylifes" | |
MONTH_DIRNAME_FORMAT = "%b_%Y" | |
ENTRY_DIRNAME_FORMAT = "%-d_%a_%b_%Y" # Not adding any more info to filename as of yet | |
ENTRY_BASENAME = "index" # Hugo's file format | |
ENTRY_FILE_EXT = ".md" | |
DAYLIFE_PATH = os.environ['JOURNAL_DAYLIFE_PATH'] # "/Users/prateekshasingh/Dropbox/I Mindful Consciousness.svg" | |
DEFAULT_ENCODING = "utf-8" # utf-8-sig for devnagri script and things? | |
OPEN_COMMAND = os.environ['JOURNAL_OPEN_COMMAND'] | |
# Humanisers | |
HUMAN_DATE_FORMAT = '%-d %B, %Y' | |
TITLES_LIST_ID = "Titles" | |
DAY_TASKS_LIST_ID = "Day tasks" | |
def write(title: str=""): | |
""" | |
make a new entry for today if not present | |
open today's entry | |
""" | |
filepath = get_or_make_entry(datetime.today(), title) | |
cat_random_entry() | |
subprocess.call((OPEN_COMMAND, filepath)) | |
def get_or_make_entry(date: datetime, title: str): | |
""" | |
Makes new journal entry for given date: A folder, and a file, with bootstrapped content | |
If folder exists, do nothing. Return path either ways. | |
:param date: date for which entry is to be made | |
:param title: optional, title that will set in H1 on entry markdown top of file | |
:return: (str) file path of the journal entry | |
""" | |
entry_dir_path = get_entry_dir_path(date) | |
if not entry_dir_path.exists(): | |
entry_dir_path.mkdir(parents=True) | |
entry_file_path = (entry_dir_path / (date.strftime(ENTRY_DIRNAME_FORMAT) + ENTRY_FILE_EXT)) | |
if not entry_file_path.exists(): | |
print("making the entry file", str(entry_file_path)) | |
with entry_file_path.open('w', encoding=DEFAULT_ENCODING) as f: | |
write_base_entry_as_per_daylife(f, title) | |
return str(entry_file_path) | |
def cat_random_entry(): | |
root = ENTRIES_PATH | |
all_entries = [] | |
for cur_path, directories, files in os.walk(root): | |
for file_name in files: | |
if ".md" in file_name: | |
all_entries.append(cur_path + "/" + file_name) | |
if all_entries: | |
chosen_entry = random.choice(all_entries) | |
path_split = os.path.split(chosen_entry) | |
print(os.path.split(path_split[0])[1], path_split[1]) | |
with Path(chosen_entry).open('r', encoding=DEFAULT_ENCODING) as f: | |
print(f.read()) | |
else: | |
print("No entries yet here, make your first one!") | |
def write_base_entry_as_per_daylife(entry_file: TextIO, title: str): | |
root = etree.parse(DAYLIFE_PATH) | |
# root.findall('.//*[@id = "Titles"]') | |
title = title or random.choice(get_list_items(root, TITLES_LIST_ID)) | |
tasks = ['- [ ] ' + task for task in get_list_items(root, DAY_TASKS_LIST_ID)] | |
todays_entry = f"# Today, {title}" + '\n'*7 + "\n".join(tasks) | |
entry_file.write(todays_entry) | |
def get_title(): | |
pass | |
def get_entry_content(): | |
pass | |
def get_list_items(root, list_id: str): | |
ns = {'d': 'http://www.w3.org/2000/svg'} # https://stackoverflow.com/questions/37434549/python-elementtree-findall-not-working | |
well_behaved_tspans = root.findall(f'.//*[@id = "{list_id}"]/d:g/d:text', ns) | |
return [''.join(tspan.itertext()) for tspan in well_behaved_tspans] | |
def get_entry_dir_path(date: datetime): | |
return Path(ENTRIES_PATH + "/" + date.strftime(MONTH_DIRNAME_FORMAT)) | |
def del_expired_docs(): | |
""" | |
TODO: Will have to show the git diff of the paths of docs, so that | |
helps if I lock the vvimp docs and keep. | |
Some folders and files should be off limits. | |
""" | |
pass | |
# from numbers_parser import Document # Haha, I globally installed it | |
# doc = Document("Things.numbers") | |
# sheets = doc.sheets() | |
# | |
# tables = sheets["my stuff"].tables() | |
# # tables[0].rows()[0] | |
# stuff_table = tables[0] | |
# print("Cell A1 contains", stuff_table.cell(0, 1).value) | |
# TEMPLATE_PATH = os.environ['JOURNAL_TEMPLATE_PATH'] # "/Users/prateekshasingh/Dropbox/daylife.md" | |
# TEMPLATE_SEPARATOR = "@template\n" | |
# FUN_TITLES_SEPARATOR = "@titles\n" | |
# | |
# | |
# def write_base_entry_as_per_template(entry_file: TextIO, title: str): | |
# with get_template_path().open('r', encoding=DEFAULT_ENCODING) as template_file: | |
# template_content, titles = parse_template_file(template_file) | |
# title = title or random.choice(titles) | |
# entry_file.write(template_content.format(title=title)) | |
# | |
# | |
# def parse_template_file(template_file: TextIO): | |
# content = template_file.read() | |
# template_gen = content.split(TEMPLATE_SEPARATOR)[-1] | |
# template, titles_gen = template_gen.split(FUN_TITLES_SEPARATOR) | |
# return template, titles_gen.strip().split('\n') | |
if __name__ == "__main__": | |
fire.Fire({ | |
"write": write | |
}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment