{"thread":{"id":"13251","subject":"[PATCH 1/5] help: use man viewer path from \"man.<tool>.path\" config var","startedAt":"2008-04-25T06:24:22Z","lastAt":"2008-04-25T06:24:22Z","messageCount":1,"participants":["Christian Couder"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"75167","messageId":"20080425082422.3a0cdd05.chriscool@tuxfamily.org","threadId":"13251","inReplyTo":null,"subject":"[PATCH 1/5] help: use man viewer path from \"man.<tool>.path\" config var","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2008-04-25T06:24:22Z","receivedAt":"2008-04-25T06:24:22Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This patch implements reading values from \"man.<tool>.path\"\nconfiguration variables, and using these values as pathes to\nthe man viewer <tool>s when lauching them.\n\nThis makes it possible to use different version of the tools\nthan the one on the current PATH, or maybe a custom script.\n\nIn this patch we also try to launch \"konqueror\" using\n\"kfmclient\" even if a path to a konqueror binary is given\nin \"man.konqueror.path\".\n\nThe \"man_viewer_list\" becomes a simple string list to simplify\nthings for the following patches.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n help.c |  143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--------\n 1 files changed, 124 insertions(+), 19 deletions(-)\n\n\tThe main changes since previous version are:\n\n\t- \"man_viewer_list\" becomes a simple string list, so the function\n\tpointers have been removed as they are useless now,\n\n\t- \"exec_man_konqueror\" is more carefull when playing with a given\n\tpath.\n\n\tSo this patch is bigger than its previous version, but the following\n\tpatch to add \"man.<tool>.cmd\" is smaller.\n\ndiff --git a/help.c b/help.c\nindex 10298fb..483e1e9 100644\n--- a/help.c\n+++ b/help.c\n@@ -11,10 +11,16 @@\n #include \"run-command.h\"\n \n static struct man_viewer_list {\n-\tvoid (*exec)(const char *);\n \tstruct man_viewer_list *next;\n+\tchar name[FLEX_ARRAY];\n } *man_viewer_list;\n \n+static struct man_viewer_info_list {\n+\tstruct man_viewer_info_list *next;\n+\tconst char *info;\n+\tchar name[FLEX_ARRAY];\n+} *man_viewer_info_list;\n+\n enum help_format {\n \tHELP_FORMAT_MAN,\n \tHELP_FORMAT_INFO,\n@@ -49,6 +55,18 @@ static enum help_format parse_help_format(const char *format)\n \tdie(\"unrecognized help format '%s'\", format);\n }\n \n+static const char *get_man_viewer_info(const char *name)\n+{\n+\tstruct man_viewer_info_list *viewer;\n+\n+\tfor (viewer = man_viewer_info_list; viewer; viewer = viewer->next)\n+\t{\n+\t\tif (!strcasecmp(name, viewer->name))\n+\t\t\treturn viewer->info;\n+\t}\n+\treturn NULL;\n+}\n+\n static int check_emacsclient_version(void)\n {\n \tstruct strbuf buffer = STRBUF_INIT;\n@@ -95,56 +113,126 @@ static int check_emacsclient_version(void)\n \treturn 0;\n }\n \n-static void exec_woman_emacs(const char *page)\n+static void exec_woman_emacs(const char* path, const char *page)\n {\n \tif (!check_emacsclient_version()) {\n \t\t/* This works only with emacsclient version >= 22. */\n \t\tstruct strbuf man_page = STRBUF_INIT;\n+\n+\t\tif (!path)\n+\t\t\tpath = \"emacsclient\";\n \t\tstrbuf_addf(&man_page, \"(woman \\\"%s\\\")\", page);\n-\t\texeclp(\"emacsclient\", \"emacsclient\", \"-e\", man_page.buf, NULL);\n+\t\texeclp(path, \"emacsclient\", \"-e\", man_page.buf, NULL);\n+\t\twarning(\"failed to exec '%s': %s\", path, strerror(errno));\n \t}\n }\n \n-static void exec_man_konqueror(const char *page)\n+static void exec_man_konqueror(const char* path, const char *page)\n {\n \tconst char *display = getenv(\"DISPLAY\");\n \tif (display && *display) {\n \t\tstruct strbuf man_page = STRBUF_INIT;\n+\t\tconst char *filename = \"kfmclient\";\n+\n+\t\t/* It's simpler to launch konqueror using kfmclient. */\n+\t\tif (path) {\n+\t\t\tconst char *file = strrchr(path, '/');\n+\t\t\tif (file && !strcmp(file + 1, \"konqueror\")) {\n+\t\t\t\tchar *new = xstrdup(path);\n+\t\t\t\tchar *dest = strrchr(new, '/');\n+\n+\t\t\t\t/* strlen(\"konqueror\") == strlen(\"kfmclient\") */\n+\t\t\t\tstrcpy(dest + 1, \"kfmclient\");\n+\t\t\t\tpath = new;\n+\t\t\t}\n+\t\t\tif (file)\n+\t\t\t\tfilename = file;\n+\t\t} else\n+\t\t\tpath = \"kfmclient\";\n \t\tstrbuf_addf(&man_page, \"man:%s(1)\", page);\n-\t\texeclp(\"kfmclient\", \"kfmclient\", \"newTab\", man_page.buf, NULL);\n+\t\texeclp(path, filename, \"newTab\", man_page.buf, NULL);\n+\t\twarning(\"failed to exec '%s': %s\", path, strerror(errno));\n \t}\n }\n \n-static void exec_man_man(const char *page)\n+static void exec_man_man(const char* path, const char *page)\n {\n-\texeclp(\"man\", \"man\", page, NULL);\n+\tif (!path)\n+\t\tpath = \"man\";\n+\texeclp(path, \"man\", page, NULL);\n+\twarning(\"failed to exec '%s': %s\", path, strerror(errno));\n }\n \n-static void do_add_man_viewer(void (*exec)(const char *))\n+static void do_add_man_viewer(const char *name)\n {\n \tstruct man_viewer_list **p = &man_viewer_list;\n+\tsize_t len = strlen(name);\n \n \twhile (*p)\n \t\tp = &((*p)->next);\n-\t*p = xmalloc(sizeof(**p));\n-\t(*p)->next = NULL;\n-\t(*p)->exec = exec;\n+\t*p = xcalloc(1, (sizeof(**p) + len + 1));\n+\tstrncpy((*p)->name, name, len);\n+}\n+\n+static int supported_man_viewer(const char *name, size_t len)\n+{\n+\treturn (!strncasecmp(\"man\", name, len) ||\n+\t\t!strncasecmp(\"woman\", name, len) ||\n+\t\t!strncasecmp(\"konqueror\", name, len));\n }\n \n static int add_man_viewer(const char *value)\n {\n-\tif (!strcasecmp(value, \"man\"))\n-\t\tdo_add_man_viewer(exec_man_man);\n-\telse if (!strcasecmp(value, \"woman\"))\n-\t\tdo_add_man_viewer(exec_woman_emacs);\n-\telse if (!strcasecmp(value, \"konqueror\"))\n-\t\tdo_add_man_viewer(exec_man_konqueror);\n+\tif (supported_man_viewer(value, strlen(value)))\n+\t\tdo_add_man_viewer(value);\n \telse\n \t\twarning(\"'%s': unsupported man viewer.\", value);\n \n \treturn 0;\n }\n \n+static void do_add_man_viewer_info(const char *name,\n+\t\t\t\t   size_t len,\n+\t\t\t\t   const char *value)\n+{\n+\tstruct man_viewer_info_list *new = xcalloc(1, sizeof(*new) + len + 1);\n+\n+\tstrncpy(new->name, name, len);\n+\tnew->info = xstrdup(value);\n+\tnew->next = man_viewer_info_list;\n+\tman_viewer_info_list = new;\n+}\n+\n+static int add_man_viewer_path(const char *name,\n+\t\t\t       size_t len,\n+\t\t\t       const char *value)\n+{\n+\tif (supported_man_viewer(name, len))\n+\t\tdo_add_man_viewer_info(name, len, value);\n+\telse\n+\t\twarning(\"'%s': path for unsupported man viewer.\", name);\n+\n+\treturn 0;\n+}\n+\n+static int add_man_viewer_info(const char *var, const char *value)\n+{\n+\tconst char *name = var + 4;\n+\tconst char *subkey = strrchr(name, '.');\n+\n+\tif (!subkey)\n+\t\treturn error(\"Config with no key for man viewer: %s\", name);\n+\n+\tif (!strcmp(subkey, \".path\")) {\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\treturn add_man_viewer_path(name, subkey - name, value);\n+\t}\n+\n+\twarning(\"'%s': unsupported man viewer sub key.\", subkey);\n+\treturn 0;\n+}\n+\n static int git_help_config(const char *var, const char *value)\n {\n \tif (!strcmp(var, \"help.format\")) {\n@@ -158,6 +246,9 @@ static int git_help_config(const char *var, const char *value)\n \t\t\treturn config_error_nonbool(var);\n \t\treturn add_man_viewer(value);\n \t}\n+\tif (!prefixcmp(var, \"man.\"))\n+\t\treturn add_man_viewer_info(var, value);\n+\n \treturn git_default_config(var, value);\n }\n \n@@ -453,6 +544,20 @@ static void setup_man_path(void)\n \tstrbuf_release(&new_path);\n }\n \n+static void exec_viewer(const char *name, const char *page)\n+{\n+\tconst char *path = get_man_viewer_info(name);\n+\n+\tif (!strcasecmp(name, \"man\"))\n+\t\texec_man_man(path, page);\n+\telse if (!strcasecmp(name, \"woman\"))\n+\t\texec_woman_emacs(path, page);\n+\telse if (!strcasecmp(name, \"konqueror\"))\n+\t\texec_man_konqueror(path, page);\n+\telse\n+\t\twarning(\"'%s': unsupported man viewer.\", name);\n+}\n+\n static void show_man_page(const char *git_cmd)\n {\n \tstruct man_viewer_list *viewer;\n@@ -461,9 +566,9 @@ static void show_man_page(const char *git_cmd)\n \tsetup_man_path();\n \tfor (viewer = man_viewer_list; viewer; viewer = viewer->next)\n \t{\n-\t\tviewer->exec(page); /* will return when unable */\n+\t\texec_viewer(viewer->name, page); /* will return when unable */\n \t}\n-\texec_man_man(page);\n+\texec_viewer(\"man\", page);\n \tdie(\"no man viewer handled the request\");\n }\n \n-- \n1.5.5.1.142.g5a727.dirty\n"}]}