Implement term-output-format
Patch status: merged
Patch by Axel Wagner
To apply this patch, use:
curl http://cr.i3wm.org/patch/162/raw.patch | git am
b/i3status.c
17 |
@@ -48,12 +48,15 @@ int general_socket; |
18 |
cfg_t *cfg, *cfg_general, *cfg_section; |
19 |
|
20 |
/* |
21 |
- * Exit upon SIGPIPE because when we have nowhere to write to, gathering |
22 |
- * system information is pointless. |
23 |
+ * Exit upon SIGPIPE because when we have nowhere to write to, gathering system |
24 |
+ * information is pointless. Also exit explicitly on SIGTERM and SIGINT because |
25 |
+ * only this will trigger a reset of the cursor in the terminal output-format. |
26 |
* |
27 |
*/ |
28 |
-void sigpipe(int signum) { |
29 |
- fprintf(stderr, "Received SIGPIPE, exiting\n"); |
30 |
+void fatalsig(int signum) { |
31 |
+ fprintf(stderr, "Received SIG%s, exiting\n", signum == SIGPIPE ? "PIPE" : |
32 |
+ signum == SIGTERM ? "TERM" : |
33 |
+ "INT"); |
34 |
exit(1); |
35 |
} |
36 |
|
37 |
@@ -321,8 +324,10 @@ int main(int argc, char *argv[]) { |
38 |
|
39 |
struct sigaction action; |
40 |
memset(&action, 0, sizeof(struct sigaction)); |
41 |
- action.sa_handler = sigpipe; |
42 |
+ action.sa_handler = fatalsig; |
43 |
sigaction(SIGPIPE, &action, NULL); |
44 |
+ sigaction(SIGTERM, &action, NULL); |
45 |
+ sigaction(SIGINT, &action, NULL); |
46 |
|
47 |
memset(&action, 0, sizeof(struct sigaction)); |
48 |
action.sa_handler = sigusr1; |
49 |
@@ -376,6 +381,8 @@ int main(int argc, char *argv[]) { |
50 |
output_format = O_XMOBAR; |
51 |
else if (strcasecmp(output_str, "i3bar") == 0) |
52 |
output_format = O_I3BAR; |
53 |
+ else if (strcasecmp(output_str, "term") == 0) |
54 |
+ output_format = O_TERM; |
55 |
else if (strcasecmp(output_str, "none") == 0) |
56 |
output_format = O_NONE; |
57 |
else die("Unknown output format: \"%s\"\n", output_str); |
58 |
@@ -400,6 +407,12 @@ int main(int argc, char *argv[]) { |
59 |
yajl_gen_array_open(json_gen); |
60 |
yajl_gen_clear(json_gen); |
61 |
} |
62 |
+ if (output_format == O_TERM) { |
63 |
+ /* Save the cursor-position and hide the cursor */ |
64 |
+ printf("\033[s\033[?25l"); |
65 |
+ /* Undo at exit */ |
66 |
+ atexit(&reset_cursor); |
67 |
+ } |
68 |
|
69 |
if ((general_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) |
70 |
die("Could not create socket\n"); |
71 |
@@ -419,6 +432,9 @@ int main(int argc, char *argv[]) { |
72 |
gettimeofday(&tv, NULL); |
73 |
if (output_format == O_I3BAR) |
74 |
yajl_gen_array_open(json_gen); |
75 |
+ else if (output_format == O_TERM) |
76 |
+ /* Restore the cursor-position */ |
77 |
+ printf("\033[u"); |
78 |
for (j = 0; j < cfg_size(cfg, "order"); j++) { |
79 |
if (j > 0) |
80 |
print_seperator(); |
b/include/i3status.h
85 |
@@ -1,7 +1,7 @@ |
86 |
#ifndef _I3STATUS_H |
87 |
#define _I3STATUS_H |
88 |
|
89 |
-enum { O_DZEN2, O_XMOBAR, O_I3BAR, O_NONE } output_format; |
90 |
+enum { O_DZEN2, O_XMOBAR, O_I3BAR, O_TERM, O_NONE } output_format; |
91 |
|
92 |
#include <stdbool.h> |
93 |
#include <confuse.h> |
94 |
@@ -133,6 +133,7 @@ bool slurp(const char *filename, char *destination, int size); |
95 |
void print_seperator(); |
96 |
char *color(const char *colorstr); |
97 |
char *endcolor() __attribute__ ((pure)); |
98 |
+void reset_cursor(void); |
99 |
|
100 |
/* src/auto_detect_format.c */ |
101 |
char *auto_detect_format(); |
b/man/i3status.man
106 |
@@ -146,6 +146,12 @@ managers like dwm, wmii and xmonad though it will work with any windowmanger |
107 |
xmobar:: |
108 |
xmobar is a minimalistic, text based, status bar. It was designed to work |
109 |
with the xmonad Window Manager. |
110 |
+term:: |
111 |
+Use ANSI Escape sequences to produce a terminal-output as close as possible to |
112 |
+the graphical outputs. This makes debugging your config file a little bit |
113 |
+easier because the terminal-output of i3status becomes much more readable, but |
114 |
+should only used for such quick glances, because it will only support very |
115 |
+basic output-features (for example you only get 3 bits of color depth). |
116 |
none:: |
117 |
Does not use any color codes. Separates values by the pipe symbol. This should |
118 |
be used with i3bar and can be used for custom scripts. |
b/src/auto_detect_format.c
123 |
@@ -30,6 +30,11 @@ |
124 |
* |
125 |
*/ |
126 |
char *auto_detect_format(void) { |
127 |
+ /* If stdout is a tty, we output directly to a terminal. */ |
128 |
+ if (isatty(STDOUT_FILENO)) { |
129 |
+ return "term"; |
130 |
+ } |
131 |
+ |
132 |
pid_t myppid = getppid(); |
133 |
pid_t mypid = getpid(); |
134 |
|
b/src/output.c
139 |
@@ -24,7 +24,19 @@ char *color(const char *colorstr) { |
140 |
(void)snprintf(colorbuf, sizeof(colorbuf), "^fg(%s)", cfg_getstr(cfg_general, colorstr)); |
141 |
else if (output_format == O_XMOBAR) |
142 |
(void)snprintf(colorbuf, sizeof(colorbuf), "<fc=%s>", cfg_getstr(cfg_general, colorstr)); |
143 |
- |
144 |
+ else if (output_format == O_TERM) { |
145 |
+ /* The escape-sequence for color is <CSI><col>;1m (bright/bold |
146 |
+ * output), where col is a 3-bit rgb-value with b in the |
147 |
+ * least-significant bit. We round the given color to the |
148 |
+ * nearist 3-bit-depth color and output the escape-sequence */ |
149 |
+ char *str = cfg_getstr(cfg_general, colorstr); |
150 |
+ int col = strtol(str + 1, NULL, 16); |
151 |
+ int r = (col & (0xFF << 0)) / 0x80; |
152 |
+ int g = (col & (0xFF << 8)) / 0x8000; |
153 |
+ int b = (col & (0xFF << 16)) / 0x800000; |
154 |
+ col = (r << 2) | (g << 1) | b; |
155 |
+ (void)snprintf(colorbuf, sizeof(colorbuf), "\033[3%d;1m", col); |
156 |
+ } |
157 |
return colorbuf; |
158 |
} |
159 |
|
160 |
@@ -35,6 +47,8 @@ char *color(const char *colorstr) { |
161 |
char *endcolor(void) { |
162 |
if (output_format == O_XMOBAR) |
163 |
return "</fc>"; |
164 |
+ else if (output_format == O_TERM) |
165 |
+ return "\033[0m"; |
166 |
else return ""; |
167 |
} |
168 |
|
169 |
@@ -43,6 +57,15 @@ void print_seperator(void) { |
170 |
printf("^fg(%s)^p(5;-2)^ro(2)^p()^fg()^p(5)", cfg_getstr(cfg_general, "color_separator")); |
171 |
else if (output_format == O_XMOBAR) |
172 |
printf("<fc=%s> | </fc>", cfg_getstr(cfg_general, "color_separator")); |
173 |
+ else if (output_format == O_TERM) |
174 |
+ printf(" %s|%s ", color("color_separator"), endcolor()); |
175 |
else if (output_format == O_NONE) |
176 |
printf(" | "); |
177 |
} |
178 |
+ |
179 |
+/* |
180 |
+ * The term-output hides the cursor. We call this on exit to reset that. |
181 |
+ */ |
182 |
+void reset_cursor(void) { |
183 |
+ printf("\033[?25h"); |
184 |
+} |