help: use man viewer path from "man.<tool>.path" config var
This patch implements reading values from "man.<tool>.path" configuration variables, and using these values as pathes to the man viewer <tool>s when lauching them. This makes it possible to use different version of the tools than the one on the current PATH, or maybe a custom script. In this patch we also try to launch "konqueror" using "kfmclient" even if a path to a konqueror binary is given in "man.konqueror.path". The "man_viewer_list" becomes a simple string list to simplify things for the following patches. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Christian Couder committed
Apr 25, 2008 at 08:24 UTC
7b15f872f23855de59bd06b0ebdbbc47b27b781b
1 file changed
+124
-19
help.c
+124
-19
@@ -11,10 +11,16 @@
11
#include "run-command.h"
12
13
static struct man_viewer_list {
14
- void (*exec)(const char *);
14
struct man_viewer_list *next;
15
+ char name[FLEX_ARRAY];
16
} *man_viewer_list;
17
18
+static struct man_viewer_info_list {
19
+ struct man_viewer_info_list *next;
20
+ const char *info;
21
+ char name[FLEX_ARRAY];
22
+} *man_viewer_info_list;
23
+
24
enum help_format {
25
HELP_FORMAT_MAN,
26
HELP_FORMAT_INFO,
@@ -49,6 +55,18 @@ static enum help_format parse_help_format(const char *format)
55
die("unrecognized help format '%s'", format);
56
}
57
58
+static const char *get_man_viewer_info(const char *name)
59
+{
60
+ struct man_viewer_info_list *viewer;
61
+
62
+ for (viewer = man_viewer_info_list; viewer; viewer = viewer->next)
63
+ {
64
+ if (!strcasecmp(name, viewer->name))
65
+ return viewer->info;
66
+ }
67
+ return NULL;
68
+}
69
+
70
static int check_emacsclient_version(void)
71
{
72
struct strbuf buffer = STRBUF_INIT;
@@ -95,56 +113,126 @@ static int check_emacsclient_version(void)
113
return 0;
114
}
115
98
-static void exec_woman_emacs(const char *page)
116
+static void exec_woman_emacs(const char* path, const char *page)
117
{
118
if (!check_emacsclient_version()) {
119
/* This works only with emacsclient version >= 22. */
120
struct strbuf man_page = STRBUF_INIT;
121
+
122
+ if (!path)
123
+ path = "emacsclient";
124
strbuf_addf(&man_page, "(woman \"%s\")", page);
104
- execlp("emacsclient", "emacsclient", "-e", man_page.buf, NULL);
125
+ execlp(path, "emacsclient", "-e", man_page.buf, NULL);
126
+ warning("failed to exec '%s': %s", path, strerror(errno));
127
}
128
}
129
108
-static void exec_man_konqueror(const char *page)
130
+static void exec_man_konqueror(const char* path, const char *page)
131
{
132
const char *display = getenv("DISPLAY");
133
if (display && *display) {
134
struct strbuf man_page = STRBUF_INIT;
135
+ const char *filename = "kfmclient";
136
+
137
+ /* It's simpler to launch konqueror using kfmclient. */
138
+ if (path) {
139
+ const char *file = strrchr(path, '/');
140
+ if (file && !strcmp(file + 1, "konqueror")) {
141
+ char *new = xstrdup(path);
142
+ char *dest = strrchr(new, '/');
143
+
144
+ /* strlen("konqueror") == strlen("kfmclient") */
145
+ strcpy(dest + 1, "kfmclient");
146
+ path = new;
147
+ }
148
+ if (file)
149
+ filename = file;
150
+ } else
151
+ path = "kfmclient";
152
strbuf_addf(&man_page, "man:%s(1)", page);
114
- execlp("kfmclient", "kfmclient", "newTab", man_page.buf, NULL);
153
+ execlp(path, filename, "newTab", man_page.buf, NULL);
154
+ warning("failed to exec '%s': %s", path, strerror(errno));
155
}
156
}
157
118
-static void exec_man_man(const char *page)
158
+static void exec_man_man(const char* path, const char *page)
159
{
120
- execlp("man", "man", page, NULL);
160
+ if (!path)
161
+ path = "man";
162
+ execlp(path, "man", page, NULL);
163
+ warning("failed to exec '%s': %s", path, strerror(errno));
164
}
165
123
-static void do_add_man_viewer(void (*exec)(const char *))
166
+static void do_add_man_viewer(const char *name)
167
{
168
struct man_viewer_list **p = &man_viewer_list;
169
+ size_t len = strlen(name);
170
171
while (*p)
172
p = &((*p)->next);
129
- *p = xmalloc(sizeof(**p));
130
- (*p)->next = NULL;
131
- (*p)->exec = exec;
173
+ *p = xcalloc(1, (sizeof(**p) + len + 1));
174
+ strncpy((*p)->name, name, len);
175
+}
176
+
177
+static int supported_man_viewer(const char *name, size_t len)
178
+{
179
+ return (!strncasecmp("man", name, len) ||
180
+ !strncasecmp("woman", name, len) ||
181
+ !strncasecmp("konqueror", name, len));
182
}
183
184
static int add_man_viewer(const char *value)
185
{
136
- if (!strcasecmp(value, "man"))
137
- do_add_man_viewer(exec_man_man);
138
- else if (!strcasecmp(value, "woman"))
139
- do_add_man_viewer(exec_woman_emacs);
140
- else if (!strcasecmp(value, "konqueror"))
141
- do_add_man_viewer(exec_man_konqueror);
186
+ if (supported_man_viewer(value, strlen(value)))
187
+ do_add_man_viewer(value);
188
else
189
warning("'%s': unsupported man viewer.", value);
190
191
return 0;
192
}
193
194
+static void do_add_man_viewer_info(const char *name,
195
+ size_t len,
196
+ const char *value)
197
+{
198
+ struct man_viewer_info_list *new = xcalloc(1, sizeof(*new) + len + 1);
199
+
200
+ strncpy(new->name, name, len);
201
+ new->info = xstrdup(value);
202
+ new->next = man_viewer_info_list;
203
+ man_viewer_info_list = new;
204
+}
205
+
206
+static int add_man_viewer_path(const char *name,
207
+ size_t len,
208
+ const char *value)
209
+{
210
+ if (supported_man_viewer(name, len))
211
+ do_add_man_viewer_info(name, len, value);
212
+ else
213
+ warning("'%s': path for unsupported man viewer.", name);
214
+
215
+ return 0;
216
+}
217
+
218
+static int add_man_viewer_info(const char *var, const char *value)
219
+{
220
+ const char *name = var + 4;
221
+ const char *subkey = strrchr(name, '.');
222
+
223
+ if (!subkey)
224
+ return error("Config with no key for man viewer: %s", name);
225
+
226
+ if (!strcmp(subkey, ".path")) {
227
+ if (!value)
228
+ return config_error_nonbool(var);
229
+ return add_man_viewer_path(name, subkey - name, value);
230
+ }
231
+
232
+ warning("'%s': unsupported man viewer sub key.", subkey);
233
+ return 0;
234
+}
235
+
236
static int git_help_config(const char *var, const char *value)
237
{
238
if (!strcmp(var, "help.format")) {
@@ -158,6 +246,9 @@ static int git_help_config(const char *var, const char *value)
246
return config_error_nonbool(var);
247
return add_man_viewer(value);
248
}
249
+ if (!prefixcmp(var, "man."))
250
+ return add_man_viewer_info(var, value);
251
+
252
return git_default_config(var, value);
253
}
254
@@ -453,6 +544,20 @@ static void setup_man_path(void)
544
strbuf_release(&new_path);
545
}
546
547
+static void exec_viewer(const char *name, const char *page)
548
+{
549
+ const char *path = get_man_viewer_info(name);
550
+
551
+ if (!strcasecmp(name, "man"))
552
+ exec_man_man(path, page);
553
+ else if (!strcasecmp(name, "woman"))
554
+ exec_woman_emacs(path, page);
555
+ else if (!strcasecmp(name, "konqueror"))
556
+ exec_man_konqueror(path, page);
557
+ else
558
+ warning("'%s': unsupported man viewer.", name);
559
+}
560
+
561
static void show_man_page(const char *git_cmd)
562
{
563
struct man_viewer_list *viewer;
@@ -461,9 +566,9 @@ static void show_man_page(const char *git_cmd)
566
setup_man_path();
567
for (viewer = man_viewer_list; viewer; viewer = viewer->next)
568
{
464
- viewer->exec(page); /* will return when unable */
569
+ exec_viewer(viewer->name, page); /* will return when unable */
570
}
466
- exec_man_man(page);
571
+ exec_viewer("man", page);
572
die("no man viewer handled the request");
573
}
574