Den var lagt fast øverst i ruden, med den begrundelse at en menu, der følger markøren, rykker sig et par pixels for hvert bogstav. Det er rigtigt, og det var alligevel forkert: i en note på en skærmfuld skriver man `#` nederst og får en menu i toppen — fire hundrede pixels fra det, øjet ser på, og langt nok væk til at man ikke opdager, at den er der. Begge dele kan lade sig gøre. Positionen måles, når menuen åbner, og ikke igen mens listen snævres ind: den står ved tegnet, og den står stille. Målt på `#term` frem for på markøren, fordi et sammenfaldet område ikke har nogen kasse på en tom linje. Klemt inden for ruden, og vendt op over linjen, når der ikke er plads under — ellers ville en note, der er skrevet helt ned i bunden, lægge menuen uden for skærmen. Og pak-noter-i-portioner.py, fordi en Apple Noter-eksport er hundrede og enoghalvfems megabyte, hvoraf teksten er fire: importen tager 64 MB ad gangen, og tunnelen foran den tager mindre. Delt efter hvad en note vejer med sine billeder, og altid med billederne i samme portion som den note, der peger på dem. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
89 lines
3.2 KiB
Python
Executable File
89 lines
3.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Pakker en Apple Noter-eksport i portioner, der kan importeres.
|
|
|
|
Eksporten af tolv hundrede noter fylder knap to hundrede megabyte, og næsten
|
|
alt sammen er billeder: teksten selv er under fire. Importen tager 64 MB ad
|
|
gangen, og tunnelen foran den tager mindre — så det skal deles.
|
|
|
|
Delt efter hvad en note *vejer med sine billeder*, ikke efter antal. De fleste
|
|
noter har ingen, så de fylder én portion til sammen; de få med et fotoalbum i
|
|
får hver deres. En note og dens billeder ligger altid i samme portion, for
|
|
linkene i teksten er relative, og en note, hvis billeder kom med i næste
|
|
portion, ville pege på ingenting.
|
|
|
|
./pak-noter-i-portioner.py ~/Desktop/apple-noter [MB]
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
import zipfile
|
|
|
|
# Under importens 64 MB og under det, en tunnel plejer at tage. Hellere en
|
|
# portion mere end en, der ryger på målstregen.
|
|
DEFAULT_LIMIT_MB = 40
|
|
|
|
LINK = re.compile(r"!\[[^\]]*\]\((vedhaeftninger/[^)]+)\)")
|
|
|
|
|
|
def main() -> int:
|
|
src = os.path.expanduser(sys.argv[1] if len(sys.argv) > 1 else "~/Desktop/apple-noter")
|
|
limit = int(float(sys.argv[2] if len(sys.argv) > 2 else DEFAULT_LIMIT_MB) * 1024 * 1024)
|
|
out_dir = src.rstrip("/") + "-portioner"
|
|
os.makedirs(out_dir, exist_ok=True)
|
|
|
|
notes = sorted(f for f in os.listdir(src) if f.endswith(".md"))
|
|
if not notes:
|
|
print(f"Ingen .md-filer i {src}")
|
|
return 1
|
|
|
|
# Hvad hver note vejer, og hvad den trækker med sig.
|
|
weighed = []
|
|
for name in notes:
|
|
path = os.path.join(src, name)
|
|
text = open(path, encoding="utf-8", errors="replace").read()
|
|
files = []
|
|
size = os.path.getsize(path)
|
|
for rel in LINK.findall(text):
|
|
f = os.path.join(src, rel)
|
|
if os.path.exists(f):
|
|
files.append(rel)
|
|
size += os.path.getsize(f)
|
|
weighed.append((name, files, size))
|
|
|
|
# En note, der alene er større end grænsen, får sin egen portion frem for at
|
|
# blive sprunget over: den skal med, og en portion på 25 MB er stadig en, der
|
|
# kan sendes.
|
|
batches, current, current_size = [], [], 0
|
|
for item in weighed:
|
|
if current and current_size + item[2] > limit:
|
|
batches.append(current)
|
|
current, current_size = [], 0
|
|
current.append(item)
|
|
current_size += item[2]
|
|
if current:
|
|
batches.append(current)
|
|
|
|
print(f"{len(notes)} noter → {len(batches)} portioner\n")
|
|
for i, batch in enumerate(batches, start=1):
|
|
zip_path = os.path.join(out_dir, f"noter-{i:02d}.zip")
|
|
seen = set()
|
|
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as z:
|
|
for name, files, _ in batch:
|
|
z.write(os.path.join(src, name), name)
|
|
for rel in files:
|
|
if rel in seen:
|
|
continue
|
|
seen.add(rel)
|
|
z.write(os.path.join(src, rel), rel)
|
|
mb = os.path.getsize(zip_path) / 1024 / 1024
|
|
print(f" {os.path.basename(zip_path)} {len(batch):4d} noter {len(seen):3d} bilag {mb:6.1f} MB")
|
|
|
|
print(f"\nLigger i:\n {out_dir}")
|
|
print("\nImportér én ad gangen under Indstillinger → Data → Noter.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|