Skip to content

Instantly share code, notes, and snippets.

@srid
Forked from felko/migrate.py
Last active May 19, 2020 12:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save srid/a1321d559fd1a5fe464bb20c1a536107 to your computer and use it in GitHub Desktop.
Save srid/a1321d559fd1a5fe464bb20c1a536107 to your computer and use it in GitHub Desktop.
Migrate neuron zettelkastens to the new hash ID format
#!/usr/bin/env python3.8
import re
import sys
import os
import uuid
from pathlib import Path
import glob
import time
import datetime
import subprocess
from collections import namedtuple
SRC_ZK, DEST_ZK = map(Path, sys.argv[1:])
Zettel = namedtuple('Zettel', ['id', 'date', 'content'])
SHORT_LINK = re.compile(r"<([A-Za-z-_0-9]+)>")
MARKDOWN_LINK = re.compile(r"\[([A-Z-a-z-_0-9]+)\]\(((?:z(?:cf)?).*?)\)")
# date-id => hash id
remap = {}
def get_zettel_date(path):
cmd = f"neuron -d {SRC_ZK} query --id {path.stem} | jq -r .result.day"
return subprocess.run(cmd, shell=True, capture_output=True).stdout.decode("utf-8")
def generate_new_id():
zid = '0'
while zid.isdigit():
zid = str(uuid.uuid4())[:8]
return zid
def replace_links(md):
repl_short_link = lambda match: f"<{remap[match.group(1)]}>"
repl_markdown_link = lambda match: f"[{remap[match.group(1)]}]({match.group(2)})"
step1 = re.sub(SHORT_LINK, repl_short_link, md)
step2 = re.sub(MARKDOWN_LINK, repl_markdown_link, step1)
return step2
def migrate_zettel(zettel):
new_id = remap[zettel.id]
with (DEST_ZK / f"{new_id}.md").open('w') as file:
lines = replace_links(zettel.content).split('\n')
file.writelines('\n'.join(lines[:2]))
file.write(f"\ndate: {zettel.date}\n")
file.writelines('\n'.join(lines[2:]))
# Delete the old file (so effectively we are renaming it)
# Recommended to use git before running this script.
os.remove(DEST_ZK / f"{zettel.id}.md")
def make_zettel_from_path(path):
with (SRC_ZK / path).open() as file:
zid = path.stem
content = file.read()
date = get_zettel_date(path)
return Zettel(zid, date, content)
def main():
zettels = []
# Migrate only date IDs.
idPattern = f"[0-9]" * 7 + f"*.md"
for zettel_path in map(Path, glob.glob(str(SRC_ZK / idPattern))):
zettel = make_zettel_from_path(zettel_path)
# Guessing whether it's a date or a custom ID
if zettel.id.isdigit():
remap[zettel.id] = generate_new_id()
else:
# Keep non-date IDs since they can be meaningful
remap[zettel.id] = zettel.id
print(f"{zettel.id:<10} => {remap[zettel.id]}")
zettels.append(zettel)
for zettel in zettels:
migrate_zettel(zettel)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment