1818 apprise = None
1919
2020
21+ def _non_negative_int (value : str ) -> int :
22+ """argparse type for ``--length``: int >= 0 (0 = no cap)."""
23+ try :
24+ n = int (value )
25+ except (TypeError , ValueError ):
26+ raise argparse .ArgumentTypeError (
27+ f"--length must be a non-negative integer, got { value !r} "
28+ )
29+ if n < 0 :
30+ raise argparse .ArgumentTypeError (
31+ f"--length must be >= 0 (0 = no cap), got { n } "
32+ )
33+ return n
34+
35+
2136def _load_config (args ):
2237 """Load configuration from the --config path."""
2338 return ConfigLoader .load (getattr (args , 'config' , None ))
@@ -368,31 +383,9 @@ def _cmd_deliver_stop(args):
368383
369384def _cmd_monitor (args ):
370385 """Launch the TUI dashboard."""
371- # Validate flag combinations BEFORE _load_config so the rejection
372- # isn't preceded by a "Configuration loaded from: ..." message --
373- # that ordering looked like the validate-then-fail had succeeded.
374- # argparse can't easily express "this flag requires --once" so we
375- # do it here, exit with the same code argparse would use, and
376- # mimic its ``error: ...`` stderr format so log scrapers keep
377- # working.
378- if getattr (args , "full_history" , False ) and not args .once :
379- # Compose the prefix from the actual invocation so users running
380- # ``eneru monitor`` don't get an "eneru tui: ..." message and
381- # vice versa. ``args.command`` is set by argparse via the
382- # subparsers' ``dest="command"``; fall back to ``argv[1]`` if
383- # that's somehow missing (defensive: monitor / tui are aliases).
384- sub = getattr (args , "command" , None ) or (
385- sys .argv [1 ] if len (sys .argv ) > 1 else "monitor"
386- )
387- sys .stderr .write (
388- f"eneru { sub } : error: --full-history requires --once "
389- "(interactive TUI is real-time)\n "
390- )
391- sys .exit (2 )
392-
393386 config = _load_config (args )
394387
395- from eneru .tui import run_tui , run_once
388+ from eneru .tui import run_tui , run_once , EVENTS_MAX_ROWS_NORMAL
396389
397390 if args .once :
398391 run_once (
@@ -401,7 +394,7 @@ def _cmd_monitor(args):
401394 time_range = getattr (args , "time" , "1h" ),
402395 events_only = getattr (args , "events_only" , False ),
403396 verbose = getattr (args , "verbose" , False ),
404- full_history = getattr (args , "full_history " , False ),
397+ length = getattr (args , "length " , EVENTS_MAX_ROWS_NORMAL ),
405398 )
406399 else :
407400 run_tui (
@@ -465,19 +458,26 @@ def _add_monitor_args(p):
465458 choices = ["charge" , "load" , "voltage" , "runtime" ],
466459 help = "Initial graph metric. With --once renders a Braille snapshot; "
467460 "in interactive TUI pre-selects the metric (still cycle with <G>)" )
461+ # IMPORTANT: --time is GRAPH-ONLY in 5.2.2+. It must NOT be
462+ # threaded into the events query. Events are sparse and a fixed
463+ # window made the panel silently empty for normal homelab usage
464+ # (the events panel then fell back to log parsing without the
465+ # operator noticing). Use --length to size the events list.
468466 p .add_argument ("--time" , default = "1h" ,
469- help = "Initial graph time range (1h/6h/24h/7d/30d). Applies to "
470- "--once snapshots and to the interactive TUI's initial view " )
467+ help = "Graph time range (1h/6h/24h/7d/30d). Applies only to the "
468+ "graph -- the events list is independent (use --length to size it) " )
471469 p .add_argument ("--events-only" , action = "store_true" ,
472470 help = "With --once: print only the events list (SQLite, log-tail fallback)" )
473471 p .add_argument ("--verbose" , "-v" , action = "store_true" ,
474472 help = "Show low-priority events alongside the priority defaults "
475473 "(daemon lifecycle, shutdown triggers, power transitions). "
476474 "Applies to both --once and the interactive TUI; toggle "
477475 "in-session with <V>" )
478- p .add_argument ("--full-history" , action = "store_true" ,
479- help = "Ignore --time and query the events table from the beginning. "
480- "Only valid with --once" )
476+ p .add_argument ("--length" , type = _non_negative_int , default = 30 ,
477+ metavar = "N" ,
478+ help = "With --once: max events to print (default: 30, 0 = no cap). "
479+ "Power events are always preserved within the cap; daemon-"
480+ "lifecycle events fill remaining slots" )
481481 p .set_defaults (func = _cmd_monitor )
482482
483483 mon_parser = subparsers .add_parser ("monitor" , help = "Launch real-time TUI dashboard" )
0 commit comments