Milestone 2.
This commit is contained in:
@@ -2,7 +2,8 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from typing import Iterable
|
||||
from pathlib import Path
|
||||
from typing import Iterator
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -15,31 +16,48 @@ class VaultPaths:
|
||||
|
||||
class Vault:
|
||||
def __init__(self, root_path: str):
|
||||
if not root_path:
|
||||
raise ValueError("Vault root path must be provided")
|
||||
self.root_path = os.path.abspath(root_path)
|
||||
self.paths = VaultPaths(
|
||||
root=self.root_path,
|
||||
notes=os.path.join(self.root_path, "notes"),
|
||||
attachments=os.path.join(self.root_path, "attachments"),
|
||||
kb=os.path.join(self.root_path, ".kb"),
|
||||
root = Path(root_path).expanduser().resolve()
|
||||
object.__setattr__(
|
||||
self,
|
||||
"paths",
|
||||
VaultPaths(
|
||||
root=str(root),
|
||||
notes=str(root / "notes"),
|
||||
attachments=str(root / "attachments"),
|
||||
kb=str(root / ".kb"),
|
||||
),
|
||||
)
|
||||
|
||||
def ensure_structure(self) -> None:
|
||||
os.makedirs(self.paths.root, exist_ok=True)
|
||||
os.makedirs(self.paths.notes, exist_ok=True)
|
||||
os.makedirs(self.paths.attachments, exist_ok=True)
|
||||
os.makedirs(self.paths.kb, exist_ok=True)
|
||||
|
||||
def relpath(self, abs_path: str) -> str:
|
||||
return os.path.relpath(abs_path, self.paths.root)
|
||||
Path(self.paths.notes).mkdir(parents=True, exist_ok=True)
|
||||
Path(self.paths.attachments).mkdir(parents=True, exist_ok=True)
|
||||
Path(self.paths.kb).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def abspath(self, rel_path: str) -> str:
|
||||
return os.path.join(self.paths.root, rel_path)
|
||||
# If rel_path is absolute, Path(root) / rel_path will return rel_path as-is.
|
||||
return str((Path(self.paths.root) / rel_path).resolve())
|
||||
|
||||
def iter_markdown_files(self) -> Iterable[str]:
|
||||
"""Yield absolute file paths for all .md files under notes/ recursively."""
|
||||
for dirpath, _, filenames in os.walk(self.paths.notes):
|
||||
for fn in filenames:
|
||||
if fn.lower().endswith(".md"):
|
||||
yield os.path.join(dirpath, fn)
|
||||
def relpath(self, abs_path: str) -> str:
|
||||
return str(Path(abs_path).resolve().relative_to(Path(self.paths.root).resolve()))
|
||||
|
||||
def iter_markdown_files(self) -> Iterator[str]:
|
||||
"""
|
||||
Yield absolute paths to .md files under <vault>/notes recursively.
|
||||
- Allows the vault root to be hidden or not.
|
||||
- Skips hidden subdirectories within notes/ (names starting with '.').
|
||||
- Skips hidden files (names starting with '.').
|
||||
"""
|
||||
notes_dir = Path(self.paths.notes)
|
||||
if not notes_dir.exists():
|
||||
return iter(())
|
||||
|
||||
# Walk manually to filter hidden dirs/files
|
||||
for dirpath, dirnames, filenames in os.walk(notes_dir):
|
||||
# Remove hidden subdirectories in-place (prevents os.walk from entering them)
|
||||
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
|
||||
for fname in filenames:
|
||||
if fname.startswith("."):
|
||||
continue
|
||||
if not fname.endswith(".md"):
|
||||
continue
|
||||
yield str(Path(dirpath, fname).resolve())
|
Reference in New Issue
Block a user