Skip to content

Instantly share code, notes, and snippets.

@parttimenerd
Created May 20, 2022 16:41
Show Gist options
  • Save parttimenerd/c42c79f5f23f720120842722b2318529 to your computer and use it in GitHub Desktop.
Save parttimenerd/c42c79f5f23f720120842722b2318529 to your computer and use it in GitHub Desktop.
Note splitter
import json
import re
import sys
from dataclasses import dataclass, field
from pathlib import Path
from typing import List, Optional, Dict
COMMENT_SEP = "_____________"
def prompt(question: str, default: Optional[str] = None, regexp: Optional[str] = None) -> str:
if regexp:
while not re.fullmatch(regexp, (reply := prompt(question, default))):
pass
return reply
if default:
reply = input(f"{question} [{default}] ")
if reply:
return reply
return default
return input(question + " ")
@dataclass(frozen=True)
class Note:
category: str
text: str
def text_version(self, categories: bool):
if categories:
return f"{self.category}:\n{self.text}"
return f"{self.text}"
@dataclass
class Day:
date: str
notes: List[Note]
def add(self, note: Note):
if note not in self.notes:
self.notes.append(note)
def text_version(self, categories: bool):
return self.date + "\n\n" + "\n\n".join(note.text_version(categories) for note in self.notes)
@dataclass
class NoteFile:
path: Path
comment: str
days: Dict[str, Day]
def add(self, date: str, note: Note):
if date not in self.days:
self.days[date] = Day(date, [])
self.days[date].add(note)
def text_version(self, categories: bool):
dates = sorted(list(self.days.keys()), key=int)
return (self.comment + f"\n{COMMENT_SEP}\n" if self.comment else "") +\
"\n\n".join(self.days[date].text_version(categories) for date in dates)
def save(self, categories: bool):
self.path.write_text(self.text_version(categories))
@staticmethod
def load(path: Path, category: Optional[str], categories: "Categories") -> "NoteFile":
print(f"parsing {path}")
parts = re.split(COMMENT_SEP + "_*", path.read_text(), maxsplit=1)
comment = parts[0] if len(parts) == 2 else ""
lines = [p.rstrip() for p in parts[-1].split("\n")]
note_file = NoteFile(path, comment, {})
line_num = 0
date_re = "[0-9]{8}"
def skip_linebreaks() -> int:
l = line_num
while l < len(lines) and (not lines[l]):
l += 1
return l
line_num = skip_linebreaks()
while line_num < len(lines):
current = lines[line_num]
date = prompt(f"Date {current} is incorrect, give new ", regexp=date_re) \
if not re.fullmatch("[0-9]{8}", current) else current
line_num += 1
line_num = skip_linebreaks()
day = Day(date, [])
while line_num < len(lines):
cat = category
finished_cats = [cat]
if not cat:
cat_re = "\\w+([, /]+\\w+)*:"
current = lines[line_num]
line_num += 1
cat_str = prompt(f"Category line \"{current}\"", regexp=cat_re) if not re.fullmatch(cat_re, current) else current
cats = [p for p in re.split("[,/ ]+", cat_str[:-1]) if p]
finished_cats = []
for cat in cats:
if categories.has_category(cat):
finished_cats.append(cat)
else:
cat = prompt("Type correct category", default=cat, regexp="\\w+")
if not categories.has_category(cat):
categories.add(cat, Path(prompt("File for category?", default=f"{categories.path.parent.absolute()}/{cat.lower()}.txt"))) # here name default
finished_cats.append(cat)
text = []
while line_num < len(lines) and lines[line_num]:
text.append(lines[line_num])
line_num += 1
for cat in finished_cats:
note_file.add(day.date, Note(cat, "\n".join(text)))
line_num = skip_linebreaks()
if line_num < len(lines) and re.fullmatch(date_re, lines[line_num]):
break
return note_file
@dataclass
class Categories:
path: Path
categories: Dict[str, NoteFile]
def has_category(self, category: str):
return category in self.categories
def add(self, category: str, path: Path):
self.categories[category] = NoteFile.load(path, category, self) if path.exists() else NoteFile(path, "", {})
self.save()
def save(self):
self.path.write_text(json.dumps({cat: str(nf.path.absolute()) for cat, nf in self.categories.items()}, indent=2))
@staticmethod
def load(path: Path) -> "Categories":
cats = Categories(path, {})
if not path.exists():
print(f"created new category file {path}")
cats.save()
for cat, p in json.loads(path.read_text()).items():
cats.add(cat, Path(p))
return cats
def run(collection: Path, categories: Path):
cats = Categories.load(categories)
notefile = NoteFile.load(collection, category=None, categories=cats)
for day in notefile.days.values():
for note in day.notes:
cats.categories[note.category].add(day.date, note)
for nf in cats.categories.values():
nf.save(categories=False)
if __name__ == '__main__':
print("main.py [collection file] [category file]")
run(Path(sys.argv[1]), Path(sys.argv[2]))
Some comment
__________________
20220506
memo food:
memo and food matter, this is a note
organisation:
more time is better, yeah
memo:
some stuff is weird
20220505
music:
bach related video https://www.youtube.com/watch?v=MzXoVo16pTg
words:
words are like thoughts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment