@matheusbsbs / matheus-bagliano / commits / 7b15f872f2
Fork 0

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