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 |
+} |