mirror of
https://github.com/kuhyx/diet-guard.git
synced 2026-11-10 18:07:20 +01:00
Every Python consumer now speaks slot minutes:
- satisfaction is nearest-slot snapping (_slot_wire.satisfied_by_entries)
at every "is this slot logged?" site: gate, CLI status, MCP, catering
occupancy and dedup. Nothing on disk is rewritten; 07:00/10:00 entries
keep covering 07:15/10:15 after a schedule move.
- log_meal writes slot_fields(minute) before signing (slot + slot_min).
- schedule store and sync encode via schedule_to_wire/from_wire; a
whole-hour schedule stays byte-identical (f/l/n only).
- CLI ate --hour takes HH or HH:MM; MCP log_meal takes "HH:MM" or a
legacy int hour, validated against today's slots; get_slots returns
{minute, label}.
- gate History tab: first/last are HH:MM ttk.Comboboxes (quarter-hour
list, typed times, Up/Down step without posting the popdown), locked
as disabled; validation mirrors normalized().
- gate timer fires every 15 min; docs rewritten for minutes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015npsYVB2PdtWkG7MPAi4tn
119 lines
3.8 KiB
Python
119 lines
3.8 KiB
Python
"""Argument parsing for the diet_guard CLI.
|
|
|
|
Split out of :mod:`diet_guard._cli` to hold the repo's 250-line cap. This is
|
|
the declarative half -- every subcommand and flag the CLI accepts -- kept apart
|
|
from the handlers that act on them, so adding a flag never grows a file that
|
|
also contains logic.
|
|
|
|
Subparsers owned by a sibling handler register themselves through their own
|
|
module (``register_averages_subparser``, ``register_sync_subparser``) rather
|
|
than being spelled out here, so a subcommand's flags live next to its code.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
|
|
from diet_guard._cli_averages import register_averages_subparser
|
|
from diet_guard._cli_body import register_body_subparsers
|
|
from diet_guard._cli_kuchnia import register_kuchnia_subparser
|
|
from diet_guard._cli_prune import register_prune_subparser
|
|
from diet_guard._cli_sync import register_sync_subparser
|
|
|
|
|
|
def parse_args(argv: list[str]) -> argparse.Namespace:
|
|
"""Parse diet_guard CLI arguments."""
|
|
parser = argparse.ArgumentParser(
|
|
prog="diet_guard",
|
|
description="Log calories and check your daily budget.",
|
|
)
|
|
sub = parser.add_subparsers(dest="command", required=True)
|
|
|
|
sub.add_parser(
|
|
"init",
|
|
help="Compute your starting daily budget from biometrics.",
|
|
)
|
|
|
|
ate = sub.add_parser("ate", help="Log a meal you just ate.")
|
|
ate.add_argument("description", help='What you ate, e.g. "big mac".')
|
|
ate.add_argument(
|
|
"--grams",
|
|
type=float,
|
|
default=None,
|
|
help="Portion size in grams (default: OFF serving size, else 100 g).",
|
|
)
|
|
ate.add_argument(
|
|
"--kcal",
|
|
type=float,
|
|
default=None,
|
|
help="Calories entered manually; skips the food bank and OFF lookup.",
|
|
)
|
|
ate.add_argument(
|
|
"--protein",
|
|
type=float,
|
|
default=None,
|
|
help="Protein in grams (recorded with --kcal to seed the food bank).",
|
|
)
|
|
ate.add_argument(
|
|
"--carbs",
|
|
type=float,
|
|
default=None,
|
|
help="Carbohydrate in grams (recorded with --kcal).",
|
|
)
|
|
ate.add_argument(
|
|
"--fat",
|
|
type=float,
|
|
default=None,
|
|
help="Fat in grams (recorded with --kcal).",
|
|
)
|
|
ate.add_argument(
|
|
"--per",
|
|
type=float,
|
|
default=None,
|
|
help="Grams the macros are stated for (e.g. 100 for a per-100 g label);"
|
|
" the typed macros are scaled from this to how much you ate.",
|
|
)
|
|
ate.add_argument(
|
|
"--count",
|
|
type=float,
|
|
default=None,
|
|
help="Number of items eaten (e.g. 5 apples) instead of --grams;"
|
|
" multiplied by the staple's unit weight.",
|
|
)
|
|
ate.add_argument(
|
|
"--date",
|
|
default=None,
|
|
help="Pre-log for a future date (YYYY-MM-DD) instead of now; requires --hour.",
|
|
)
|
|
ate.add_argument(
|
|
"--hour",
|
|
type=str,
|
|
default=None,
|
|
help="Meal slot on --date this meal satisfies, as HH:MM or HH (e.g."
|
|
" 07:15 or 20); must be one of that day's slots. Requires --date.",
|
|
)
|
|
|
|
sub.add_parser("status", help="Show today's calories and budget band.")
|
|
sub.add_parser("undo", help="Remove today's most recent entry.")
|
|
register_averages_subparser(sub)
|
|
register_kuchnia_subparser(sub)
|
|
register_prune_subparser(sub)
|
|
register_sync_subparser(sub)
|
|
register_body_subparsers(sub)
|
|
|
|
gate = sub.add_parser(
|
|
"gate",
|
|
help="Log-to-unlock screen gate (intended to be run by a timer).",
|
|
)
|
|
gate.add_argument(
|
|
"--check",
|
|
action="store_true",
|
|
help="Headless: exit 0 if NOT due, 1 if a lock is due. Prints, no window.",
|
|
)
|
|
gate.add_argument(
|
|
"--demo",
|
|
action="store_true",
|
|
help="Show the lock in safe demo mode (local grab + close button).",
|
|
)
|
|
return parser.parse_args(argv)
|