Skip to content

Commit

Permalink
Add 'edit' command (no tests)
Browse files Browse the repository at this point in the history
  • Loading branch information
bbugyi200 committed Jan 20, 2024
1 parent 0bd34ea commit 0a7c120
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 23 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,17 @@ print("```", stdout.decode().strip(), "```", sep="\n")
]]]]] -->
```
usage: zorg [-h] [-c CONFIG_FILE] [-L [FILE[:LEVEL][@FORMAT]]] [-v]
[-d ZETTEL_DIR]
{edit} ...
Contains the zorg package's main entry point.
The zettel note manager of the future.
options:
-c CONFIG_FILE, --config CONFIG_FILE
Absolute or relative path to a YAML file that contains
this application's configuration.
-d ZETTEL_DIR, --dir ZETTEL_DIR
The directory where all of your notes are stored.
-h, --help show this help message and exit
-L [FILE[:LEVEL][@FORMAT]], --log [FILE[:LEVEL][@FORMAT]]
This option can be used to enable a new logging
Expand All @@ -85,6 +89,10 @@ options:
multiple times and has a default argument of '+'.
-v, --verbose How verbose should the output be? This option can be
specified multiple times (e.g. -v, -vv, -vvv, ...).
subcommands:
{edit}
edit Open day log in editor.
```
<!-- [[[[[end]]]]] -->

Expand Down
2 changes: 2 additions & 0 deletions requirements.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
bolton-clack ~= 0.3.1
bolton-logrus ~= 0.1.1
jinja2
vimala ~= 0.1.2
25 changes: 3 additions & 22 deletions src/zorg/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,12 @@

from __future__ import annotations

from typing import Sequence

import clack


class Config(clack.Config):
"""Command-line arguments."""

@classmethod
def from_cli_args(cls, argv: Sequence[str]) -> Config:
"""Parses command-line arguments."""
parser = clack.Parser()

args = parser.parse_args(argv[1:])
kwargs = clack.filter_cli_args(args)

return cls(**kwargs)


def run(cfg: Config) -> int:
"""This function acts as this tool's main entry point."""
del cfg
return 0
from .config import clack_parser
from .runners import RUNNERS


main = clack.main_factory("zorg", run)
main = clack.main_factory("zorg", parser=clack_parser, runners=RUNNERS)
if __name__ == "__main__":
main()
79 changes: 79 additions & 0 deletions src/zorg/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""Clack config for zorg."""

from __future__ import annotations

import itertools as it
from pathlib import Path
from typing import Any, Literal, Sequence

import clack


Command = Literal["edit"]


class Config(clack.Config):
"""Shared clack configuration class."""

command: Command

zettel_dir: Path = Path.home() / "org"


class EditConfig(Config):
"""Clack config for the 'edit' command."""

command: Literal["edit"]

day_log_template: str = "bujo_day_log_tmpl.zo"
habit_template: str = "habit_tmpl.zo"
done_template: str = "done_tmpl.zo"
vim_commands: list[str]


def clack_parser(argv: Sequence[str]) -> dict[str, Any]:
"""Parser we pass to the `main_factory()` `parser` kwarg."""
# HACK: Make 'tui' the default sub-command.
if not list(it.dropwhile(lambda x: x.startswith("-"), argv[1:])):
argv = list(argv) + ["edit"]

parser = clack.Parser(description="The zettel note manager of the future.")
parser.add_argument(
"-d",
"--dir",
dest="zettel_dir",
type=Path,
help="The directory where all of your notes are stored.",
)

new_command = clack.new_command_factory(parser)
edit_parser = new_command("edit", help="Open day log in editor.")
edit_parser.add_argument(
"-D",
"--day-log-template-name",
help="Template used to generate day logs.",
)
edit_parser.add_argument(
"-H",
"--habit-template",
help="Template used to generate habit trackers.",
)
edit_parser.add_argument(
"-X",
"--done-template",
help="Template used to generate files for done todos.",
)

args = parser.parse_args(argv[1:])
kwargs = clack.filter_cli_args(args)

_preprocess_template_name(kwargs, "day_log_template")
_preprocess_template_name(kwargs, "habit_template")
_preprocess_template_name(kwargs, "done_template")

return kwargs


def _preprocess_template_name(kwargs: dict[str, Any], key: str) -> None:
if key in kwargs:
kwargs[key] = kwargs[key] + "_tmpl.zo"
92 changes: 92 additions & 0 deletions src/zorg/runners.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"""Contains this project's clack runners."""

from __future__ import annotations

import datetime as dt
from pathlib import Path
from typing import Iterable, Iterator, List

from clack.types import ClackRunner
import jinja2
from logrus import Logger
import metaman
import vimala

from .config import EditConfig


RUNNERS: List[ClackRunner] = []
runner = metaman.register_function_factory(RUNNERS)

logger = Logger(__name__)


@runner
def run_edit(cfg: EditConfig) -> int:
"""Runner for the 'edit' command."""
template_loader = jinja2.FileSystemLoader(searchpath=cfg.zettel_dir)
template_env = jinja2.Environment(loader=template_loader)
template = template_env.get_template(cfg.day_log_template)
habit_template = template_env.get_template(cfg.habit_template)
done_template = template_env.get_template(cfg.done_template)

today = dt.datetime.now()
yesterday = today - dt.timedelta(days=1)
two_days_ago = today - dt.timedelta(days=2)
tomorrow = today + dt.timedelta(days=1)

day_log_vars = {
"year": str(today.year),
"month": f"{today.month:02d}",
"day": f"{today.day:02d}",
"weekday": today.strftime("%a"),
"yesterday": yesterday.strftime("%Y%m%d"),
"tomorrow": tomorrow.strftime("%Y%m%d"),
}
day_log_contents = template.render(day_log_vars)
done_log_contents = done_template.render(day_log_vars)
habit_tracker_contents = habit_template.render(
year=str(yesterday.year),
month=f"{yesterday.month:02d}",
day=f"{yesterday.day:02d}",
weekday=yesterday.strftime("%a"),
day_before=two_days_ago.strftime("%Y%m%d"),
day_after=today.strftime("%Y%m%d"),
)

day_log_path = _get_day_path(cfg.zettel_dir, today)
if not day_log_path.exists():
day_log_path.write_text(day_log_contents)

habit_tracker_path = _get_day_path(
cfg.zettel_dir, yesterday, suffix="habit"
)
if not habit_tracker_path.exists():
habit_tracker_path.write_text(habit_tracker_contents)

done_log_path = _get_day_path(cfg.zettel_dir, today, suffix="done")
if not done_log_path.exists():
done_log_path.write_text(done_log_contents)

vimala.vim(
day_log_path,
commands=_process_vim_commands(cfg.zettel_dir, cfg.vim_commands),
)
return 0


def _get_day_path(
zettel_dir: Path, date: dt.date, *, suffix: str = None
) -> Path:
suffix = f"_{suffix}" if suffix else ""
return zettel_dir / str(date.year) / date.strftime(f"%Y%m%d{suffix}.zo")


def _process_vim_commands(
zettel_dir: Path, vim_commands: Iterable[str]
) -> Iterator[str]:
for vim_cmd in vim_commands:
if "{zdir}" in vim_cmd:
yield vim_cmd.format(zdir=zettel_dir)
else:
yield vim_cmd

0 comments on commit 0a7c120

Please sign in to comment.