@matheusbsbs / matheus-bagliano / commits / 69099d6bed
Fork 0

help: implement multi-valued "man.viewer" config option

This allows multiple viewer candidates to be listed in the configuration file, like this: [man] viewer = woman viewer = konqueror viewer = man The candidates are tried in the order listed in the configuration file, and the first suitable one (e.g. konqueror cannot be used outside windowed environment) is used. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Tested-by: Xavier Maillard <xma@gnu.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Christian Couder committed Mar 11, 2008 at 08:51 UTC 69099d6bedb0217d7c35f7202acd6185551d762f
1 file changed +113 -78
help.c
+113 -78
@@ -10,7 +10,10 @@
10 #include "parse-options.h"
11 #include "run-command.h"
12
13 -static const char *man_viewer;
13 +static struct man_viewer_list {
14 + void (*exec)(const char *);
15 + struct man_viewer_list *next;
16 +} *man_viewer_list;
17
18 enum help_format {
19 HELP_FORMAT_MAN,
@@ -45,6 +48,102 @@ static enum help_format parse_help_format(const char *format)
48 die("unrecognized help format '%s'", format);
49 }
50
51 +static int check_emacsclient_version(void)
52 +{
53 + struct strbuf buffer = STRBUF_INIT;
54 + struct child_process ec_process;
55 + const char *argv_ec[] = { "emacsclient", "--version", NULL };
56 + int version;
57 +
58 + /* emacsclient prints its version number on stderr */
59 + memset(&ec_process, 0, sizeof(ec_process));
60 + ec_process.argv = argv_ec;
61 + ec_process.err = -1;
62 + ec_process.stdout_to_stderr = 1;
63 + if (start_command(&ec_process)) {
64 + fprintf(stderr, "Failed to start emacsclient.\n");
65 + return -1;
66 + }
67 + strbuf_read(&buffer, ec_process.err, 20);
68 + close(ec_process.err);
69 +
70 + /*
71 + * Don't bother checking return value, because "emacsclient --version"
72 + * seems to always exits with code 1.
73 + */
74 + finish_command(&ec_process);
75 +
76 + if (prefixcmp(buffer.buf, "emacsclient")) {
77 + fprintf(stderr, "Failed to parse emacsclient version.\n");
78 + strbuf_release(&buffer);
79 + return -1;
80 + }
81 +
82 + strbuf_remove(&buffer, 0, strlen("emacsclient"));
83 + version = atoi(buffer.buf);
84 +
85 + if (version < 22) {
86 + fprintf(stderr,
87 + "emacsclient version '%d' too old (< 22).\n",
88 + version);
89 + strbuf_release(&buffer);
90 + return -1;
91 + }
92 +
93 + strbuf_release(&buffer);
94 + return 0;
95 +}
96 +
97 +static void exec_woman_emacs(const char *page)
98 +{
99 + if (!check_emacsclient_version()) {
100 + /* This works only with emacsclient version >= 22. */
101 + struct strbuf man_page = STRBUF_INIT;
102 + strbuf_addf(&man_page, "(woman \"%s\")", page);
103 + execlp("emacsclient", "emacsclient", "-e", man_page.buf, NULL);
104 + }
105 +}
106 +
107 +static void exec_man_konqueror(const char *page)
108 +{
109 + const char *display = getenv("DISPLAY");
110 + if (display && *display) {
111 + struct strbuf man_page = STRBUF_INIT;
112 + strbuf_addf(&man_page, "man:%s(1)", page);
113 + execlp("kfmclient", "kfmclient", "newTab", man_page.buf, NULL);
114 + }
115 +}
116 +
117 +static void exec_man_man(const char *page)
118 +{
119 + execlp("man", "man", page, NULL);
120 +}
121 +
122 +static void do_add_man_viewer(void (*exec)(const char *))
123 +{
124 + struct man_viewer_list **p = &man_viewer_list;
125 +
126 + while (*p)
127 + p = &((*p)->next);
128 + *p = xmalloc(sizeof(**p));
129 + (*p)->next = NULL;
130 + (*p)->exec = exec;
131 +}
132 +
133 +static int add_man_viewer(const char *value)
134 +{
135 + if (!strcasecmp(value, "man"))
136 + do_add_man_viewer(exec_man_man);
137 + else if (!strcasecmp(value, "woman"))
138 + do_add_man_viewer(exec_woman_emacs);
139 + else if (!strcasecmp(value, "konqueror"))
140 + do_add_man_viewer(exec_man_konqueror);
141 + else
142 + return error("'%s': unsupported man viewer.", value);
143 +
144 + return 0;
145 +}
146 +
147 static int git_help_config(const char *var, const char *value)
148 {
149 if (!strcmp(var, "help.format")) {
@@ -53,8 +152,11 @@ static int git_help_config(const char *var, const char *value)
152 help_format = parse_help_format(value);
153 return 0;
154 }
56 - if (!strcmp(var, "man.viewer"))
57 - return git_config_string(&man_viewer, var, value);
155 + if (!strcmp(var, "man.viewer")) {
156 + if (!value)
157 + return config_error_nonbool(var);
158 + return add_man_viewer(value);
159 + }
160 return git_default_config(var, value);
161 }
162
@@ -350,85 +452,18 @@ static void setup_man_path(void)
452 strbuf_release(&new_path);
453 }
454
353 -static int check_emacsclient_version(void)
354 -{
355 - struct strbuf buffer = STRBUF_INIT;
356 - struct child_process ec_process;
357 - const char *argv_ec[] = { "emacsclient", "--version", NULL };
358 - int version;
359 -
360 - /* emacsclient prints its version number on stderr */
361 - memset(&ec_process, 0, sizeof(ec_process));
362 - ec_process.argv = argv_ec;
363 - ec_process.err = -1;
364 - ec_process.stdout_to_stderr = 1;
365 - if (start_command(&ec_process)) {
366 - fprintf(stderr, "Failed to start emacsclient.\n");
367 - return -1;
368 - }
369 - strbuf_read(&buffer, ec_process.err, 20);
370 - close(ec_process.err);
371 -
372 - /*
373 - * Don't bother checking return value, because "emacsclient --version"
374 - * seems to always exits with code 1.
375 - */
376 - finish_command(&ec_process);
377 -
378 - if (prefixcmp(buffer.buf, "emacsclient")) {
379 - fprintf(stderr, "Failed to parse emacsclient version.\n");
380 - strbuf_release(&buffer);
381 - return -1;
382 - }
383 -
384 - strbuf_remove(&buffer, 0, strlen("emacsclient"));
385 - version = atoi(buffer.buf);
386 -
387 - if (version < 22) {
388 - fprintf(stderr,
389 - "emacsclient version '%d' too old (< 22).\n",
390 - version);
391 - strbuf_release(&buffer);
392 - return -1;
393 - }
394 -
395 - strbuf_release(&buffer);
396 - return 0;
397 -}
398 -
399 -static void exec_woman_emacs(const char *page)
400 -{
401 - if (!check_emacsclient_version()) {
402 - /* This works only with emacsclient version >= 22. */
403 - struct strbuf man_page = STRBUF_INIT;
404 - strbuf_addf(&man_page, "(woman \"%s\")", page);
405 - execlp("emacsclient", "emacsclient", "-e", man_page.buf, NULL);
406 - } else
407 - execlp("man", "man", page, NULL);
408 -}
409 -
410 -static void exec_man_konqueror(const char *page)
411 -{
412 - const char *display = getenv("DISPLAY");
413 - if (display && *display) {
414 - struct strbuf man_page = STRBUF_INIT;
415 - strbuf_addf(&man_page, "man:%s(1)", page);
416 - execlp("kfmclient", "kfmclient", "newTab", man_page.buf, NULL);
417 - } else
418 - execlp("man", "man", page, NULL);
419 -}
420 -
455 static void show_man_page(const char *git_cmd)
456 {
457 + struct man_viewer_list *viewer;
458 const char *page = cmd_to_page(git_cmd);
459 +
460 setup_man_path();
425 - if (!man_viewer || !strcmp(man_viewer, "man"))
426 - execlp("man", "man", page, NULL);
427 - if (!strcmp(man_viewer, "woman"))
428 - exec_woman_emacs(page);
429 - if (!strcmp(man_viewer, "konqueror"))
430 - exec_man_konqueror(page);
431 - die("'%s': unsupported man viewer.", man_viewer);
461 + for (viewer = man_viewer_list; viewer; viewer = viewer->next)
462 + {
463 + viewer->exec(page); /* will return when unable */
464 + }
465 + exec_man_man(page);
466 + die("no man viewer handled the request");
467 }
468
469 static void show_info_page(const char *git_cmd)