50 lines
1.9 KiB
Python
50 lines
1.9 KiB
Python
"""
|
|
Folder suggestion: plain token overlap between the text you've typed
|
|
(filename, topic, subtopic — whatever's available) and each candidate
|
|
destination folder's path segments.
|
|
|
|
Deliberately simple and inspectable rather than clever — no ML, nothing
|
|
that runs over the network, and you can always see exactly why a folder
|
|
was suggested (shared words) rather than trusting a black box. If the
|
|
suggestions turn out too weak once you try it on real files, the obvious
|
|
next upgrade is peeking at file content for .md/.txt files — but that's
|
|
worth trying this simple version against real data first.
|
|
"""
|
|
|
|
import re
|
|
from pathlib import Path
|
|
from typing import List
|
|
|
|
from .sanitiser import UMLAUT_MAP
|
|
|
|
|
|
def _tokens(text: str) -> set:
|
|
"""Split on ANY run of non-alphanumeric characters (underscore, hyphen,
|
|
space, ...) — folder names use underscores (04_ARBEIT), typed text uses
|
|
spaces, so the tokeniser has to treat both as word boundaries. This is
|
|
deliberately more lenient than sanitise(), which is for building the
|
|
final filename, not for comparing words."""
|
|
folded = text.lower()
|
|
for src, repl in UMLAUT_MAP.items():
|
|
folded = folded.replace(src, repl)
|
|
return {t for t in re.split(r"[^a-z0-9]+", folded) if len(t) > 2}
|
|
|
|
|
|
def suggest_folders(query_text: str, all_folders: List[str], top_n: int = 5) -> List[str]:
|
|
"""Rank candidate folders by shared tokens with query_text.
|
|
Returns [] if query_text has no usable tokens — never guesses blind."""
|
|
query_tokens = _tokens(query_text)
|
|
if not query_tokens:
|
|
return []
|
|
|
|
scored = []
|
|
for folder in all_folders:
|
|
folder_tokens = set()
|
|
for segment in Path(folder).parts:
|
|
folder_tokens |= _tokens(segment)
|
|
overlap = len(query_tokens & folder_tokens)
|
|
if overlap:
|
|
scored.append((overlap, folder))
|
|
|
|
scored.sort(key=lambda pair: (-pair[0], pair[1]))
|
|
return [folder for _, folder in scored[:top_n]]
|