tm-timer 2.1__tar.gz → 2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tm-timer
3
- Version: 2.1
3
+ Version: 2.2
4
4
  Summary: Minimalistic terminal-based timer with Study/Train tracking
5
5
  Author: ph4nt01
6
6
  Author-email: Ph4nt01 <ph4nt0.84@email.com>
@@ -14,18 +14,19 @@ Dynamic: requires-python
14
14
 
15
15
  ---
16
16
  # ⏱️ tm-timer
17
- >Minimalistic Terminal timer with Study session tracking
17
+ > Minimalistic Terminal timer with dynamic activity tracking
18
18
 
19
19
  ## Features
20
20
 
21
21
  - Countdown timer:
22
22
  - `tm 10s`, `tm 25m`, `tm 1h30m`
23
- - Study/Train modes:
24
- - `tm --study` track study sessions (resets daily, accumulates across multiple runs)
25
- - `tm --train` track training sessions (same behavior, separate table)
23
+ - Dynamic Activity modes (track anything):
24
+ - `tm -a study` -> track study sessions
25
+ - `tm -a train` -> track training sessions
26
+ - `tm -a reading` -> track custom activities (resets daily, accumulates across multiple runs)
26
27
  - Daily logging:
27
28
  - Records totals in `~/.tm_timer/data.json`
28
- - Each day resets at midnight
29
+ - Each day resets at midnight (splits time correctly if a session crosses midnight)
29
30
  - Statistics:
30
31
  - Average daily hours
31
32
  - Standard Deviation of Time
@@ -33,13 +34,13 @@ Dynamic: requires-python
33
34
  - **Very Good** (SD < AVG/2)
34
35
  - **Good** (SD = AVG/2)
35
36
  - **Not Good** (SD > AVG/2)
36
- - Export:
37
- - `tm --studystatus` show study table + stats
38
- - `tm --trainstatus` show train table + stats
39
- - `tm --tables` export both tables to `tables.md`
37
+ - Export & Management:
38
+ - `tm -s study` -> show study table + stats
39
+ - `tm --list` -> list all tracked activities and their total time
40
+ - `tm -t` -> export all activity tables to `tables.md`
40
41
  - Controls:
41
- - `p` pause/resume
42
- - `q` quit and save
42
+ - `p` -> pause/resume
43
+ - `q` -> quit and save
43
44
 
44
45
  ---
45
46
 
@@ -58,16 +59,22 @@ exec $SHELL # reload shell
58
59
 
59
60
  ```bash
60
61
  # Start a study session
61
- tm --study
62
+ tm -a study
62
63
 
63
64
  # Check study stats
64
- tm --studystatus
65
+ tm -s study
65
66
 
66
67
  # Start a train session
67
- tm --train
68
+ tm -a train
69
+
70
+ # Start a custom activity session (e.g., reading)
71
+ tm -a reading
72
+
73
+ # List all recorded activities
74
+ tm --list
68
75
 
69
76
  # Export tables to tables.md
70
- tm --tables
77
+ tm -t
71
78
  ```
72
79
 
73
80
  ---
@@ -75,10 +82,6 @@ tm --tables
75
82
  ## Example Tables Output
76
83
 
77
84
  ```markdown
78
- # tm_timer Tables
79
-
80
- ---
81
-
82
85
  ## STUDY Table
83
86
 
84
87
  | Date | Day | Time |
@@ -88,9 +91,8 @@ tm --tables
88
91
  | 2025-09-29 | MON | 04:05:00 |
89
92
  | 2025-09-27 | SAT | 03:36:00 |
90
93
 
91
- **[AVG] = 3.98h [Standard Deviation of Time] = 0.75h Status = Very Good**
94
+ [AVG] = 3.98h [Standard Deviation of Time] = 0.75h Status = Very Good
92
95
 
93
- ---
94
96
 
95
97
  ## TRAIN Table
96
98
 
@@ -101,16 +103,6 @@ tm --tables
101
103
  | 2025-09-30 | SUN | 00:35:00 |
102
104
  | 2025-09-28 | SAT | 01:36:00 |
103
105
 
104
- **[AVG] = 1.05h [Standard Deviation of Time] = 0.38h Status = Very Good**
106
+ [AVG] = 1.05h [Standard Deviation of Time] = 0.38h Status = Very Good
105
107
  ```
106
108
 
107
- ---
108
-
109
- ## Preview
110
-
111
-
112
- ![Timer preview](demo1.gif)
113
-
114
- ![Timer preview](demo2.gif)
115
-
116
- ![Timer preview](demo3.gif)
@@ -2,18 +2,19 @@
2
2
 
3
3
  ---
4
4
  # ⏱️ tm-timer
5
- >Minimalistic Terminal timer with Study session tracking
5
+ > Minimalistic Terminal timer with dynamic activity tracking
6
6
 
7
7
  ## Features
8
8
 
9
9
  - Countdown timer:
10
10
  - `tm 10s`, `tm 25m`, `tm 1h30m`
11
- - Study/Train modes:
12
- - `tm --study` track study sessions (resets daily, accumulates across multiple runs)
13
- - `tm --train` track training sessions (same behavior, separate table)
11
+ - Dynamic Activity modes (track anything):
12
+ - `tm -a study` -> track study sessions
13
+ - `tm -a train` -> track training sessions
14
+ - `tm -a reading` -> track custom activities (resets daily, accumulates across multiple runs)
14
15
  - Daily logging:
15
16
  - Records totals in `~/.tm_timer/data.json`
16
- - Each day resets at midnight
17
+ - Each day resets at midnight (splits time correctly if a session crosses midnight)
17
18
  - Statistics:
18
19
  - Average daily hours
19
20
  - Standard Deviation of Time
@@ -21,13 +22,13 @@
21
22
  - **Very Good** (SD < AVG/2)
22
23
  - **Good** (SD = AVG/2)
23
24
  - **Not Good** (SD > AVG/2)
24
- - Export:
25
- - `tm --studystatus` show study table + stats
26
- - `tm --trainstatus` show train table + stats
27
- - `tm --tables` export both tables to `tables.md`
25
+ - Export & Management:
26
+ - `tm -s study` -> show study table + stats
27
+ - `tm --list` -> list all tracked activities and their total time
28
+ - `tm -t` -> export all activity tables to `tables.md`
28
29
  - Controls:
29
- - `p` pause/resume
30
- - `q` quit and save
30
+ - `p` -> pause/resume
31
+ - `q` -> quit and save
31
32
 
32
33
  ---
33
34
 
@@ -46,16 +47,22 @@ exec $SHELL # reload shell
46
47
 
47
48
  ```bash
48
49
  # Start a study session
49
- tm --study
50
+ tm -a study
50
51
 
51
52
  # Check study stats
52
- tm --studystatus
53
+ tm -s study
53
54
 
54
55
  # Start a train session
55
- tm --train
56
+ tm -a train
57
+
58
+ # Start a custom activity session (e.g., reading)
59
+ tm -a reading
60
+
61
+ # List all recorded activities
62
+ tm --list
56
63
 
57
64
  # Export tables to tables.md
58
- tm --tables
65
+ tm -t
59
66
  ```
60
67
 
61
68
  ---
@@ -63,10 +70,6 @@ tm --tables
63
70
  ## Example Tables Output
64
71
 
65
72
  ```markdown
66
- # tm_timer Tables
67
-
68
- ---
69
-
70
73
  ## STUDY Table
71
74
 
72
75
  | Date | Day | Time |
@@ -76,9 +79,8 @@ tm --tables
76
79
  | 2025-09-29 | MON | 04:05:00 |
77
80
  | 2025-09-27 | SAT | 03:36:00 |
78
81
 
79
- **[AVG] = 3.98h [Standard Deviation of Time] = 0.75h Status = Very Good**
82
+ [AVG] = 3.98h [Standard Deviation of Time] = 0.75h Status = Very Good
80
83
 
81
- ---
82
84
 
83
85
  ## TRAIN Table
84
86
 
@@ -89,16 +91,6 @@ tm --tables
89
91
  | 2025-09-30 | SUN | 00:35:00 |
90
92
  | 2025-09-28 | SAT | 01:36:00 |
91
93
 
92
- **[AVG] = 1.05h [Standard Deviation of Time] = 0.38h Status = Very Good**
94
+ [AVG] = 1.05h [Standard Deviation of Time] = 0.38h Status = Very Good
93
95
  ```
94
96
 
95
- ---
96
-
97
- ## Preview
98
-
99
-
100
- ![Timer preview](demo1.gif)
101
-
102
- ![Timer preview](demo2.gif)
103
-
104
- ![Timer preview](demo3.gif)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tm-timer"
7
- version = "2.1"
7
+ version = "2.2"
8
8
  description = "Minimalistic terminal-based timer with Study/Train tracking"
9
9
  readme = "README.md"
10
10
  authors = [{ name="Ph4nt01", email="ph4nt0.84@email.com" }]
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="tm-timer",
5
- version="2.1",
5
+ version="2.2",
6
6
  packages=find_packages(),
7
7
  entry_points={
8
8
  "console_scripts": [
@@ -57,18 +57,21 @@ DATA_FILE = DATA_DIR / "data.json"
57
57
 
58
58
  def load_data():
59
59
  if not DATA_FILE.exists():
60
- return {"study": {}, "train": {}}
60
+ return {}
61
61
  try:
62
62
  with DATA_FILE.open("r", encoding="utf-8") as f:
63
63
  data = json.load(f)
64
64
  except Exception:
65
- return {"study": {}, "train": {}}
66
- # Ensure keys
67
- if "study" not in data:
68
- data["study"] = {}
69
- if "train" not in data:
70
- data["train"] = {}
71
- return data
65
+ return {}
66
+ if not isinstance(data, dict):
67
+ return {}
68
+ # normalize: every value must be a dict of {date_str: int_seconds}
69
+ cleaned = {}
70
+ for activity, days in data.items():
71
+ if not isinstance(days, dict):
72
+ continue
73
+ cleaned[activity] = {str(k): int(v) for k, v in days.items()}
74
+ return cleaned
72
75
 
73
76
 
74
77
  def save_data(data):
@@ -159,11 +162,12 @@ def print_activity_table(activity):
159
162
  def write_tables_md(path="tables.md"):
160
163
  data = load_data()
161
164
  lines = []
162
- for activity in ("study", "train"):
165
+ for activity in sorted(data.keys()):
163
166
  lines.append(f"## {activity.upper()} Table\n")
164
167
  lines.append("| Date | Day | Time |\n")
165
168
  lines.append("| ---- | --- | ---- |\n")
166
- items = sorted(data.get(activity, {}).items(), key=lambda kv: kv[0], reverse=True)
169
+ items = sorted(data.get(activity, {}).items(),
170
+ key=lambda kv: kv[0], reverse=True)
167
171
  for date_str, secs in items:
168
172
  try:
169
173
  dt = datetime.datetime.strptime(date_str, "%Y-%m-%d").date()
@@ -171,13 +175,17 @@ def write_tables_md(path="tables.md"):
171
175
  except Exception:
172
176
  day_name = ""
173
177
  lines.append(f"| {date_str} | {day_name} | {format_hms(secs)} |\n")
178
+
174
179
  stats = compute_stats_for_activity(activity)
175
180
  if stats["n"] < 2:
176
181
  lines.append("\nNot enough recording for statistics (need 2+ days).\n\n")
177
182
  else:
178
183
  lines.append(
179
- f"\n[AVG] = {stats['avg']:.2f}h [Standard Deviation of Time] = {stats['sd']:.2f}h Status = {status_from_avg_sd(stats['avg'], stats['sd'])}\n\n"
184
+ f"\n[AVG] = {stats['avg']:.2f}h "
185
+ f"[Standard Deviation of Time] = {stats['sd']:.2f}h "
186
+ f"Status = {status_from_avg_sd(stats['avg'], stats['sd'])}\n\n"
180
187
  )
188
+
181
189
  out_path = Path.cwd() / path
182
190
  out_path.write_text("".join(lines), encoding="utf-8")
183
191
  return str(out_path.resolve())
@@ -337,37 +345,93 @@ def run_countdown(target_seconds, target_input):
337
345
  print("Timer stopped.")
338
346
 
339
347
 
340
- # --- CLI entrypoint ---
348
+ # Back-compat alias map: old flag -> activity name
349
+ # LEGACY_ALIASES = {
350
+ # "study": "study",
351
+ # "train": "train",
352
+ # "studystatus": "study", # for --studystatus
353
+ # "trainstatus": "train", # for --trainstatus
354
+ # }
355
+
356
+
341
357
  def main():
342
- parser = argparse.ArgumentParser(description="tm_timer - terminal timer with study/train logging")
343
- parser.add_argument("--study", action="store_true", help="Run study timer (no limit until 'q')")
344
- parser.add_argument("--train", action="store_true", help="Run train timer (no limit until 'q')")
345
- parser.add_argument("--studystatus", action="store_true", help="Show study daily table and SD")
346
- parser.add_argument("--trainstatus", action="store_true", help="Show train daily table and SD")
347
- parser.add_argument("--tables", action="store_true", help="Export tables.md to current directory")
348
- parser.add_argument("duration", nargs="?", help="Optional duration e.g. 1h30m (if not using --study/--train)")
358
+ parser = argparse.ArgumentParser(
359
+ description="tm_timer - terminal timer with per-activity logging",
360
+ formatter_class=argparse.RawDescriptionHelpFormatter,
361
+ epilog=(
362
+ "Examples:\n"
363
+ " tm_timer -a study # start study timer\n"
364
+ " tm_timer -a reading # start a custom 'reading' timer\n"
365
+ " tm_timer -s study # show study table + stats\n"
366
+ " tm_timer -t # export tables.md\n"
367
+ " tm_timer 25m # plain countdown\n"
368
+ ),
369
+ )
370
+ parser.add_argument(
371
+ "-a", "--activity", metavar="NAME",
372
+ help="Run timer for the given activity (any name you like).",
373
+ )
374
+ parser.add_argument(
375
+ "-s", "--status", metavar="NAME",
376
+ help="Show daily table and statistics for the given activity.",
377
+ )
378
+ parser.add_argument(
379
+ "--list", action="store_true",
380
+ help="List all activities recorded so far.",
381
+ )
382
+ parser.add_argument(
383
+ "-t", "--tables", action="store_true",
384
+ help="Export tables.md (all activities) to the current directory.",
385
+ )
386
+
387
+ # Deprecated back-compat aliases
388
+ # parser.add_argument("--study", action="store_true", help="(deprecated) alias for -a study")
389
+ # parser.add_argument("--train", action="store_true", help="(deprecated) alias for -a train")
390
+ # parser.add_argument("--studystatus", action="store_true", help="(deprecated) alias for --status study")
391
+ # parser.add_argument("--trainstatus", action="store_true", help="(deprecated) alias for --status train")
392
+
393
+ parser.add_argument("duration", nargs="?",
394
+ help="Optional duration e.g. 1h30m (countdown mode).")
349
395
  args = parser.parse_args()
350
396
 
351
- # priority actions
352
- if args.studystatus:
353
- print_activity_table("study")
354
- return
355
- if args.trainstatus:
356
- print_activity_table("train")
397
+ # Resolve legacy aliases into the new flags
398
+ activity = args.activity
399
+ status_of = args.status
400
+ # if args.study: activity = activity or "study"
401
+ # if args.train: activity = activity or "train"
402
+ # if args.studystatus: status_of = status_of or "study"
403
+ # if args.trainstatus: status_of = status_of or "train"
404
+
405
+ # 1) status
406
+ if status_of:
407
+ print_activity_table(status_of)
357
408
  return
409
+
410
+ # 2) tables export
358
411
  if args.tables:
359
412
  out = write_tables_md("tables.md")
360
413
  print(f"created {out}")
361
414
  return
362
415
 
363
- if args.study:
364
- run_activity("study")
416
+ # 3) list activities
417
+ if args.list:
418
+ data = load_data()
419
+ if not data:
420
+ print("No activities recorded yet.")
421
+ return
422
+ print("Activities:")
423
+ for name in sorted(data):
424
+ n_days = len(data[name])
425
+ total = sum(data[name].values())
426
+ print(f" - {name:<15} {n_days:>3} days total {format_hms(total)}")
365
427
  return
366
- if args.train:
367
- run_activity("train")
428
+
429
+ # 4) run an activity timer
430
+ if activity:
431
+ run_activity(activity)
368
432
  return
369
433
 
370
- # fallback: duration countdown (compat)
434
+ # 5) plain countdown (backward compatible)
371
435
  if args.duration:
372
436
  try:
373
437
  target_seconds = parse_time_input(args.duration)
@@ -375,8 +439,9 @@ def main():
375
439
  print(e)
376
440
  sys.exit(1)
377
441
  run_countdown(target_seconds, args.duration)
378
- else:
379
- parser.print_help()
442
+ return
443
+
444
+ parser.print_help()
380
445
 
381
446
 
382
447
  if __name__ == "__main__":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tm-timer
3
- Version: 2.1
3
+ Version: 2.2
4
4
  Summary: Minimalistic terminal-based timer with Study/Train tracking
5
5
  Author: ph4nt01
6
6
  Author-email: Ph4nt01 <ph4nt0.84@email.com>
@@ -14,18 +14,19 @@ Dynamic: requires-python
14
14
 
15
15
  ---
16
16
  # ⏱️ tm-timer
17
- >Minimalistic Terminal timer with Study session tracking
17
+ > Minimalistic Terminal timer with dynamic activity tracking
18
18
 
19
19
  ## Features
20
20
 
21
21
  - Countdown timer:
22
22
  - `tm 10s`, `tm 25m`, `tm 1h30m`
23
- - Study/Train modes:
24
- - `tm --study` track study sessions (resets daily, accumulates across multiple runs)
25
- - `tm --train` track training sessions (same behavior, separate table)
23
+ - Dynamic Activity modes (track anything):
24
+ - `tm -a study` -> track study sessions
25
+ - `tm -a train` -> track training sessions
26
+ - `tm -a reading` -> track custom activities (resets daily, accumulates across multiple runs)
26
27
  - Daily logging:
27
28
  - Records totals in `~/.tm_timer/data.json`
28
- - Each day resets at midnight
29
+ - Each day resets at midnight (splits time correctly if a session crosses midnight)
29
30
  - Statistics:
30
31
  - Average daily hours
31
32
  - Standard Deviation of Time
@@ -33,13 +34,13 @@ Dynamic: requires-python
33
34
  - **Very Good** (SD < AVG/2)
34
35
  - **Good** (SD = AVG/2)
35
36
  - **Not Good** (SD > AVG/2)
36
- - Export:
37
- - `tm --studystatus` show study table + stats
38
- - `tm --trainstatus` show train table + stats
39
- - `tm --tables` export both tables to `tables.md`
37
+ - Export & Management:
38
+ - `tm -s study` -> show study table + stats
39
+ - `tm --list` -> list all tracked activities and their total time
40
+ - `tm -t` -> export all activity tables to `tables.md`
40
41
  - Controls:
41
- - `p` pause/resume
42
- - `q` quit and save
42
+ - `p` -> pause/resume
43
+ - `q` -> quit and save
43
44
 
44
45
  ---
45
46
 
@@ -58,16 +59,22 @@ exec $SHELL # reload shell
58
59
 
59
60
  ```bash
60
61
  # Start a study session
61
- tm --study
62
+ tm -a study
62
63
 
63
64
  # Check study stats
64
- tm --studystatus
65
+ tm -s study
65
66
 
66
67
  # Start a train session
67
- tm --train
68
+ tm -a train
69
+
70
+ # Start a custom activity session (e.g., reading)
71
+ tm -a reading
72
+
73
+ # List all recorded activities
74
+ tm --list
68
75
 
69
76
  # Export tables to tables.md
70
- tm --tables
77
+ tm -t
71
78
  ```
72
79
 
73
80
  ---
@@ -75,10 +82,6 @@ tm --tables
75
82
  ## Example Tables Output
76
83
 
77
84
  ```markdown
78
- # tm_timer Tables
79
-
80
- ---
81
-
82
85
  ## STUDY Table
83
86
 
84
87
  | Date | Day | Time |
@@ -88,9 +91,8 @@ tm --tables
88
91
  | 2025-09-29 | MON | 04:05:00 |
89
92
  | 2025-09-27 | SAT | 03:36:00 |
90
93
 
91
- **[AVG] = 3.98h [Standard Deviation of Time] = 0.75h Status = Very Good**
94
+ [AVG] = 3.98h [Standard Deviation of Time] = 0.75h Status = Very Good
92
95
 
93
- ---
94
96
 
95
97
  ## TRAIN Table
96
98
 
@@ -101,16 +103,6 @@ tm --tables
101
103
  | 2025-09-30 | SUN | 00:35:00 |
102
104
  | 2025-09-28 | SAT | 01:36:00 |
103
105
 
104
- **[AVG] = 1.05h [Standard Deviation of Time] = 0.38h Status = Very Good**
106
+ [AVG] = 1.05h [Standard Deviation of Time] = 0.38h Status = Very Good
105
107
  ```
106
108
 
107
- ---
108
-
109
- ## Preview
110
-
111
-
112
- ![Timer preview](demo1.gif)
113
-
114
- ![Timer preview](demo2.gif)
115
-
116
- ![Timer preview](demo3.gif)
File without changes
File without changes