i3 - improved tiling WM


Add support for file_exists directive.

Patch status: needinfo

Patch by Kinware AB

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

b/i3status.c

18
@@ -210,6 +210,13 @@ int main(int argc, char *argv[]) {
19
                 CFG_END()
20
         };
21
 
22
+        cfg_opt_t file_exists_opts[] = {
23
+                CFG_STR("file", NULL, CFGF_NONE),
24
+                CFG_STR("format", "%title: %status", CFGF_NONE),
25
+                CFG_CUSTOM_COLOR_OPTS,
26
+                CFG_END()
27
+        };
28
+
29
         cfg_opt_t wireless_opts[] = {
30
                 CFG_STR("format_up", "W: (%quality at %essid, %bitrate) %ip", CFGF_NONE),
31
                 CFG_STR("format_down", "W: down", CFGF_NONE),
32
@@ -297,6 +304,7 @@ int main(int argc, char *argv[]) {
33
                 CFG_STR_LIST("order", "{}", CFGF_NONE),
34
                 CFG_SEC("general", general_opts, CFGF_NONE),
35
                 CFG_SEC("run_watch", run_watch_opts, CFGF_TITLE | CFGF_MULTI),
36
+                CFG_SEC("file_exists", file_exists_opts, CFGF_TITLE | CFGF_MULTI),
37
                 CFG_SEC("wireless", wireless_opts, CFGF_TITLE | CFGF_MULTI),
38
                 CFG_SEC("ethernet", ethernet_opts, CFGF_TITLE | CFGF_MULTI),
39
                 CFG_SEC("battery", battery_opts, CFGF_TITLE | CFGF_MULTI),
40
@@ -480,6 +488,12 @@ int main(int argc, char *argv[]) {
41
                                 SEC_CLOSE_MAP;
42
                         }
43
 
44
+                        CASE_SEC_TITLE("file_exists") {
45
+                                SEC_OPEN_MAP("file_exists");
46
+                                print_file_exists(json_gen, buffer, title, cfg_getstr(sec, "file"), cfg_getstr(sec, "format"));
47
+                                SEC_CLOSE_MAP;
48
+                        }
49
+
50
                         CASE_SEC_TITLE("disk") {
51
                                 SEC_OPEN_MAP("disk_info");
52
                                 print_disk_info(json_gen, buffer, title, cfg_getstr(sec, "format"));

b/include/i3status.h

57
@@ -131,6 +131,7 @@ typedef enum { CS_DISCHARGING, CS_CHARGING, CS_FULL } charging_status_t;
58
 char *skip_character(char *input, char character, int amount);
59
 void die(const char *fmt, ...);
60
 bool slurp(const char *filename, char *destination, int size);
61
+bool file_exists(const char *file);
62
 
63
 /* src/output.c */
64
 void print_seperator();
65
@@ -152,6 +153,7 @@ void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t t);
66
 const char *get_ip_addr();
67
 void print_wireless_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down);
68
 void print_run_watch(yajl_gen json_gen, char *buffer, const char *title, const char *pidfile, const char *format);
69
+void print_file_exists(yajl_gen json_gen, char *buffer, const char *title, const char *file, const char *format);
70
 void print_cpu_temperature_info(yajl_gen json_gen, char *buffer, int zone, const char *path, const char *format, int);
71
 void print_cpu_usage(yajl_gen json_gen, char *buffer, const char *format);
72
 void print_eth_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down);

b/man/i3status.man

77
@@ -51,6 +51,7 @@ order += "ipv6"
78
 order += "disk /"
79
 order += "run_watch DHCP"
80
 order += "run_watch VPN"
81
+order += "file_exists VPN"
82
 order += "wireless wlan0"
83
 order += "ethernet eth0"
84
 order += "battery 0"
85
@@ -82,9 +83,15 @@ run_watch DHCP {
86
 }
87
 
88
 run_watch VPN {
89
+        # status of backgrounded vpnc
90
         pidfile = "/var/run/vpnc/pid"
91
 }
92
 
93
+file_exists VPN {
94
+        # status of 'vpnc --no-detach' when launched by nmcli/nm-applet
95
+        file = "/proc/sys/net/ipv4/conf/tun0"
96
+}
97
+
98
 tztime local {
99
         format = "%Y-%m-%d %H:%M:%S"
100
 }
101
@@ -193,6 +200,16 @@ a specific application, such as a VPN client or your DHCP client is running.
102
 
103
 *Example format*: +%title: %status+
104
 
105
+=== File-exists
106
+
107
+Expands the given path to a filename and checks if the file exists in the
108
+filesystem. You can use this to check if something is active, like
109
+for example a VPN tunnel managed by NetworkManager.
110
+
111
+*Example order*: +file_exists VPN+
112
+
113
+*Example format*: +%title: %status+
114
+
115
 === Wireless
116
 
117
 Gets the link quality and ESSID of the given wireless network interface. You

b/src/general.c

122
@@ -6,6 +6,7 @@
123
 #include <stdlib.h>
124
 #include <unistd.h>
125
 #include <sys/fcntl.h>
126
+#include <sys/stat.h>
127
 
128
 #include "i3status.h"
129
 
130
@@ -28,6 +29,22 @@ bool slurp(const char *filename, char *destination, int size) {
131
         return true;
132
 }
133
 
134
+
135
+/*
136
+ * Checks if the specified file exists in the filesystem or not.
137
+ * Ignores type of file (i.e regular, device, directory, etc).
138
+ *
139
+ */
140
+bool file_exists(const char *file) {
141
+        struct stat st;
142
+
143
+        if (0 != stat(file, &st))
144
+                return false;
145
+
146
+        return true;
147
+}
148
+
149
+
150
 /*
151
  * Skip the given character for exactly 'amount' times, returns
152
  * a pointer to the first non-'character' character in 'input'.

b/src/print_file_exists.c

158
@@ -0,0 +1,33 @@
159
+#include <stdio.h>
160
+#include <string.h>
161
+#include <yajl/yajl_gen.h>
162
+#include <yajl/yajl_version.h>
163
+#include "i3status.h"
164
+
165
+void print_file_exists(yajl_gen json_gen, char *buffer, const char *title, const char *file, const char *format) {
166
+	bool exists = file_exists(file);
167
+	const char *walk;
168
+	char *outwalk = buffer;
169
+
170
+	INSTANCE(file);
171
+
172
+	START_COLOR((exists ? "color_good" : "color_bad"));
173
+
174
+        for (walk = format; *walk != '\0'; walk++) {
175
+                if (*walk != '%') {
176
+			*(outwalk++) = *walk;
177
+                        continue;
178
+                }
179
+
180
+                if (strncmp(walk+1, "title", strlen("title")) == 0) {
181
+			outwalk += sprintf(outwalk, "%s", title);
182
+                        walk += strlen("title");
183
+                } else if (strncmp(walk+1, "status", strlen("status")) == 0) {
184
+			outwalk += sprintf(outwalk, "%s", (exists ? "yes" : "no"));
185
+                        walk += strlen("status");
186
+                }
187
+        }
188
+
189
+	END_COLOR;
190
+	OUTPUT_FULL_TEXT(buffer);
191
+}