i3 - improved tiling WM


Add file_contents module to print arbitrary file data.

Patch status: superseded

Patch by Luke Heberling

Long description:

This can be used to replace external wrapper scripts with single-purpose
scripts, easily distributable in contrib.

To apply this patch, use:
curl http://cr.i3wm.org/patch/628/raw.patch | git am

b/i3status.c

19
@@ -402,6 +402,14 @@ int main(int argc, char *argv[]) {
20
                 CFG_END()
21
         };
22
 
23
+        cfg_opt_t file_contents_opts[] = {
24
+                CFG_STR("file", NULL, CFGF_NONE),
25
+                CFG_CUSTOM_ALIGN_OPT,
26
+                CFG_CUSTOM_COLOR_OPTS,
27
+                CFG_CUSTOM_MIN_WIDTH_OPT,
28
+                CFG_END()
29
+        };
30
+
31
         cfg_opt_t opts[] = {
32
                 CFG_STR_LIST("order", "{}", CFGF_NONE),
33
                 CFG_SEC("general", general_opts, CFGF_NONE),
34
@@ -419,6 +427,7 @@ int main(int argc, char *argv[]) {
35
                 CFG_SEC("ddate", ddate_opts, CFGF_NONE),
36
                 CFG_SEC("load", load_opts, CFGF_NONE),
37
                 CFG_SEC("cpu_usage", usage_opts, CFGF_NONE),
38
+                CFG_SEC("file_contents", file_contents_opts, CFGF_TITLE | CFGF_MULTI),
39
                 CFG_END()
40
         };
41
 
42
@@ -652,6 +661,12 @@ int main(int argc, char *argv[]) {
43
                                 print_cpu_usage(json_gen, buffer, cfg_getstr(sec, "format"));
44
                                 SEC_CLOSE_MAP;
45
                         }
46
+
47
+                        CASE_SEC_TITLE("file_contents") {
48
+                                SEC_OPEN_MAP("file_contents");
49
+                                print_file_contents(json_gen, buffer, title, cfg_getstr(sec, "file"));
50
+                                SEC_CLOSE_MAP;
51
+                        }
52
                 }
53
                 if (output_format == O_I3BAR) {
54
                         yajl_gen_array_close(json_gen);

b/include/i3status.h

59
@@ -184,6 +184,7 @@ void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format);
60
 void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down);
61
 void print_load(yajl_gen json_gen, char *buffer, const char *format, const float max_threshold);
62
 void print_volume(yajl_gen json_gen, char *buffer, const char *fmt, const char *fmt_muted, const char *device, const char *mixer, int mixer_idx);
63
+void print_file_contents(yajl_gen json_gen, char *buffer, const char *title, const char *file);
64
 bool process_runs(const char *path);
65
 
66
 /* socket file descriptor for general purposes */

b/man/i3status.man

71
@@ -47,6 +47,7 @@ general {
72
         interval = 5
73
 }
74
 
75
+order += "file_contents motd"
76
 order += "ipv6"
77
 order += "disk /"
78
 order += "run_watch DHCP"
79
@@ -60,6 +61,10 @@ order += "load"
80
 order += "tztime local"
81
 order += "tztime berlin"
82
 
83
+file_contents motd {
84
+	path = "/etc/motd"
85
+}
86
+
87
 wireless wlan0 {
88
         format_up = "W: (%quality at %essid, %bitrate) %ip"
89
         format_down = "W: down"
90
@@ -196,6 +201,11 @@ disk "/" {
91
 }
92
 -------------------------------------------------------------
93
 
94
+=== File Contents
95
+This module gets the first line of a file, up to 128 characters.
96
+
97
+*Example path*: +/etc/motd+
98
+
99
 === IPv6
100
 
101
 This module gets the IPv6 address used for outgoing connections (that is, the

b/src/print_file_contents.c

107
@@ -0,0 +1,30 @@
108
+#include <stdio.h>
109
+#include <string.h>
110
+#include <glob.h>
111
+#include <yajl/yajl_gen.h>
112
+#include <yajl/yajl_version.h>
113
+#include "i3status.h"
114
+
115
+void print_file_contents(yajl_gen json_gen, char *buffer, const char *title, const char *file) {
116
+	char *outwalk = buffer;
117
+
118
+	INSTANCE(title);
119
+
120
+	static glob_t globbuf;
121
+
122
+	if (glob(file, GLOB_NOCHECK | GLOB_TILDE, NULL, &globbuf) < 0)
123
+		die("glob() failed\n");
124
+	// We can't access actual size of buffer here, but it's 4096 currently
125
+	if (!slurp((globbuf.gl_pathc > 0 ? globbuf.gl_pathv[0] : file), outwalk, 128))
126
+		*outwalk = '\0';
127
+	// slurp zero-terminates the buffer
128
+
129
+	globfree(&globbuf);
130
+	char *eol = strchr(outwalk, '\n');
131
+	if (eol != NULL) {
132
+		outwalk = eol;
133
+	} else {
134
+		outwalk = strchr(outwalk, '\0');
135
+	}
136
+	OUTPUT_FULL_TEXT(buffer);
137
+}