aboutsummaryrefslogtreecommitdiff
path: root/patches/ttym-persist-alert-2.0.diff
blob: 7e9d64b8fe1adc86d564c2e891a2339af314c1d7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
diff -ruN a/config.def.h b/config.def.h
--- a/config.def.h	2026-05-20 11:57:26.574344832 +0200
+++ b/config.def.h	2026-05-20 11:57:26.578344915 +0200
@@ -3,3 +3,9 @@
 /* progress bar glyphs (ASCII default) */
 static const char *const BAR_FILL  = ">";
 static const char *const BAR_EMPTY = "-";
+
+/* persistent alert: keep ringing the bell until any key is pressed.
+ * Foreground-only; backgrounded runs always fall through.
+ * Override per-run with --no-persist.
+ */
+static const int ALERT_PERSIST = 1;
diff -ruN a/ttym.c b/ttym.c
--- a/ttym.c	2026-05-20 11:57:26.574344832 +0200
+++ b/ttym.c	2026-05-20 11:57:26.578344915 +0200
@@ -23,6 +23,7 @@
 typedef struct {
 	int quiet;            /* -q: suppress completion bell */
 	int silent;           /* -s: no bell, no extras */
+	int alert_persist;    /* alert loop until keypress; --no-persist disables */
 } Config;
 
 static struct termios oldtios;
@@ -226,6 +227,48 @@
 	fflush(stdout);
 }
 
+/* ===== alert loop =====
+ * Bell + poll for keypress, ~1.5s per beat; 4-min safety cap.
+ */
+
+static int
+is_foreground(void)
+{
+	if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO)) return 0;
+	pid_t pgrp = tcgetpgrp(STDIN_FILENO);
+	if (pgrp < 0) return 0;
+	return pgrp == getpgrp();
+}
+
+static void
+alert_loop(void)
+{
+	fputs("\033[?25h\033[?7h", stdout);
+	int ticks = 0;
+	while (!interrupted) {
+		fputc('\a', stdout);
+		fflush(stdout);
+		sleep_ms(150);
+
+		int acked = 0;
+		for (int i = 0; i < 15 && !interrupted; i++) {
+			if (ttyfd < 0) { sleep_ms(100); continue; }
+			struct pollfd pfd = { .fd = ttyfd, .events = POLLIN };
+			int pr = poll(&pfd, 1, 100);
+			if (pr > 0 && (pfd.revents & POLLIN)) {
+				char ch;
+				ssize_t rd = read(ttyfd, &ch, 1);
+				if (rd >= 0) { acked = 1; break; }
+			} else if (pr < 0) {
+				sleep_ms(100);
+			}
+		}
+		if (acked) break;
+		if (++ticks > 160) break;
+	}
+	fflush(stdout);
+}
+
 /* ===== usage =====
  * Patches MUST update this in lockstep with new flags so -h always
  * reflects the build.
@@ -243,6 +286,7 @@
 "FLAGS:\n"
 "  -q              no sound\n"
 "  -s              silent\n"
+"  --no-persist    skip alert-until-keypress loop\n"
 "  --              end of options\n"
 "  -h              help\n"
 "\n"
@@ -375,6 +419,10 @@
 			fflush(stdout);
 			sleep_ms(50);
 		}
+		if (!cfg->silent && cfg->alert_persist && is_foreground()) {
+			interrupted = 0;
+			alert_loop();
+		}
 	}
 
 	(void)cfg;
@@ -387,6 +435,7 @@
 main(int argc, char **argv)
 {
 	Config cfg = {0};
+	cfg.alert_persist = ALERT_PERSIST;
 
 	/* Pre-strip long-form flags before getopt. Stop at "--". */
 	int new_argc = 0;
@@ -399,6 +448,10 @@
 			new_argv[new_argc++] = argv[i];
 			continue;
 		}
+		if (!past_dd && !strcmp(argv[i], "--no-persist")) {
+			cfg.alert_persist = 0;
+			continue;
+		}
 		new_argv[new_argc++] = argv[i];
 	}
 	new_argv[new_argc] = NULL;