1. Christian Hudon
  2. vcprompt

Commits

Christian Hudon  committed 0d80337

Add support for VC system-specific VCPROMPT_FORMAT environment variables (e.g. VCPROMPT_FORMAT_GIT, etc.).

  • Participants
  • Parent commits 582a6fd
  • Branches default

Comments (0)

Files changed (8)

File README.txt

View file
 
 You can customize the output of vcprompt using format strings, which can
 be specified either on the command line or in the VCPROMPT_FORMAT
-environment variable.  For example:
+environment variables.  For example:
 
   vcprompt -f "%b"
 
 
 are equivalent.
 
+If you want to set a different format string for different VC systems, you
+can do so via VCPROMPT_FORMAT_GIT, VCPROMPT_FORMAT_HG, etc., which are
+checked before the generic VCPROMPT_FORMAT environment variable.
+
 Format strings use printf-like "%" escape sequences:
 
   %n  name of the VC system managing the current directory
 
 In chronological order:
 
+  Christian Hudon
   Daniel Serpell
   Jannis Leidel
   Yuya Nishihara
 Copyright & License
 ===================
 
-Copyright (C) 2009, 2010, Gregory P. Ward and contributors.
+Copyright (C) 2009, 2010, 2012, Gregory P. Ward and contributors.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by

File src/common.c

View file
 /*
- * Copyright (C) 2009, 2010, Gregory P. Ward and contributors.
+ * Copyright (C) 2009, 2010, 2012, Gregory P. Ward and contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
 #include <sys/stat.h>
 #include <unistd.h>
 #include <errno.h>
+#include <ctype.h>
 
 #include "common.h"
 
     return !!result->branch;
 }
 
+void parse_format(options_t* options)
+{
+    size_t i;
+
+    options->show_branch = 0;
+    options->show_unknown = 0;
+    options->show_modified = 0;
+
+    char* format = options->format;
+    size_t len = strlen(format);
+    for (i = 0; i < len; i++) {
+        if (format[i] == '%') {
+            i++;
+            switch (format[i]) {
+                case '\0':              /* at end of string: ignore */
+                    break;
+                case 'b':
+                    options->show_branch = 1;
+                    break;
+                case 'r':
+                    options->show_revision = 1;
+                    break;
+                case 'u':
+                    options->show_unknown = 1;
+                    break;
+                case 'm':
+                    options->show_modified = 1;
+                    break;
+                case 'n':               /* name of VC system */
+                case '%':
+                    break;
+                default:
+                    fprintf(stderr,
+                            "error: invalid format string: %%%c\n",
+                            format[i]);
+                    break;
+            }
+        }
+    }
+}
+
 vccontext_t*
 init_context(const char *name,
              options_t* options,
              result_t* (*get_info)(vccontext_t*))
 {
     vccontext_t* context = (vccontext_t*) calloc(1, sizeof(vccontext_t));
-    context->options = options;
+    context->options = *options;
     context->name = name;
     context->probe = probe;
     context->get_info = get_info;
+
+    if (context->options.format == NULL)
+        context->options.format = get_format_from_env(context->name);
+
+    parse_format(&context->options);
+
     return context;
 }
 
     strncpy(dest, src, nchars);
     dest[nchars] = '\0';
 }
+
+char*
+get_format_from_env(const char *vcname)
+{
+    char vc_format_envname[30];
+    snprintf(vc_format_envname, sizeof (vc_format_envname),
+             "VCPROMPT_FORMAT_%s", vcname);
+    /* Make sure vc_format_envname is NULL-terminated. */
+    vc_format_envname[sizeof(vc_format_envname)-1] = '\0';
+
+    /* Convert vc_format_envname to uppercase. */
+    char* s = vc_format_envname;
+    while (*s) {
+        *s = toupper(*s);
+        s++;
+    }
+
+    char* format = getenv(vc_format_envname);
+    if (format == NULL) {
+        format = getenv("VCPROMPT_FORMAT");
+        if (format == NULL)
+            format = DEFAULT_FORMAT;
+    }
+
+    return format;
+}

File src/common.h

View file
 /*
- * Copyright (C) 2009, 2010, Gregory P. Ward and contributors.
+ * Copyright (C) 2009, 2010, 2012, Gregory P. Ward and contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
 #ifndef VCPROMPT_H
 #define VCPROMPT_H
 
+#define DEFAULT_FORMAT "[%n:%b%m%u] "
+
 /* What the user asked for (environment + command-line).
  */
 typedef struct {
 typedef struct vccontext_t vccontext_t;
 struct vccontext_t {
     const char *name;                   /* name of the VC system */
-    options_t* options;
+    options_t options;
 
     /* context methods */
     int (*probe)(vccontext_t*);
 void
 free_result(result_t*);
 
+/* Retrieves the desired output format from environment variables, for a
+ * given version control system. First try vc-specific format environment
+ * variable (e.g. VCPROMPT_FORMAT_GIT). If that is not set, try the
+ * VCPROMPT_FORMAT environment variable. If that is not set too, fall back
+ * to default hardcoded format.
+ */
+char*
+get_format_from_env(const char *);
+
 /* printf()-style output of fmt and other args to stdout, but only if
  * debug mode is on (e.g. from the command line -d).
  */

File src/fossil.c

View file
 /*
- * Copyright (C) 2011 Jan Spakula and contributors.
+ * Copyright (C) 2011, 2012, Jan Spakula and contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
     buf[rlen] = '\0';
     pclose(stream);
 
-    if (context->options->show_branch) {
+    if (context->options.show_branch) {
         if ((t = strstr(buf, "\ntags:"))) {
             // This in fact shows also other tags than just the
             // propagating ones (=branches).  So either we show all
             result_set_branch(result, "(unknown)");
         }
     }
-    if (context->options->show_revision) {
+    if (context->options.show_revision) {
         if ((t = strstr(buf, "\ncheckout:"))) {
             get_till_eol(buf2, t + tab_len + 1, 80);
             debug("found revision line: '%s'", buf2);
             result_set_revision(result, "unknown", 7);
         }
     }
-    if (context->options->show_modified) {
+    if (context->options.show_modified) {
         // This can be also done by 'test -n'ing 'fossil changes',
         // but we save a system() call this way.
         if ( strstr(buf, "\nEDITED") || strstr(buf, "\nADDED")
             || strstr(buf, "\nUPDATED") || strstr(buf, "\nMERGED") )
             result->modified = 1;
     }
-    if (context->options->show_unknown) {
+    if (context->options.show_unknown) {
         // This can't be read from 'fossil status' output
         int status = system("test -n \"$(fossil extra)\"");
         if (WEXITSTATUS(status) == 0)

File src/git.c

View file
 /*
- * Copyright (C) 2009, 2010, Gregory P. Ward and contributors.
+ * Copyright (C) 2009, 2010, 2012, Gregory P. Ward and contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
         char* prefix = "ref: refs/heads/";
         int prefixlen = strlen(prefix);
 
-        if (context->options->show_branch || context->options->show_revision) {
+        if (context->options.show_branch || context->options.show_revision) {
             int found_branch = 0;
             if (strncmp(prefix, buf, prefixlen) == 0) {
                 /* yep, we're on a known branch */
                 result_set_branch(result, "(unknown)");
                 result_set_revision(result, buf, 12);
             }
-            if (context->options->show_revision && found_branch) {
+            if (context->options.show_revision && found_branch) {
                 char buf[1024];
                 char filename[1024] = ".git/refs/heads/";
                 int nchars = sizeof(filename) - strlen(filename) - 1;
                 }
             }
         }
-        if (context->options->show_modified) {
+        if (context->options.show_modified) {
             int status = system("git diff --no-ext-diff --quiet --exit-code");
             if (WEXITSTATUS(status) == 1)       /* files modified */
                 result->modified = 1;
                failure to run git, or diff error): assume no
                modifications */
         }
-        if (context->options->show_unknown) {
+        if (context->options.show_unknown) {
             int status = system("test -n \"$(git ls-files --others --exclude-standard)\"");
             if (WEXITSTATUS(status) == 0)
                 result->unknown = 1;

File src/hg.c

View file
     char buf[NODEID_LEN * 2];
     size_t readsize;
 
-    if (!context->options->show_revision) return;
+    if (!context->options.show_revision) return;
 
     readsize = read_file(".hg/dirstate", buf, NODEID_LEN * 2);
     if (readsize == NODEID_LEN * 2) {

File src/svn.c

View file
 /*
- * Copyright (C) 2009, 2010, Gregory P. Ward and contributors.
+ * Copyright (C) 2009, 2010, 2012, Gregory P. Ward and contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by

File src/vcprompt.c

View file
 /*
- * Copyright (C) 2009, 2010, Gregory P. Ward and contributors.
+ * Copyright (C) 2009, 2010, 2012 Gregory P. Ward and contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
 #include "bzr.h"
 */
 
-#define DEFAULT_FORMAT "[%n:%b%m%u] "
-
 void parse_args(int argc, char** argv, options_t* options)
 {
     int opt;
                 );
                 printf("Environment Variables:\n"
                 " VCPROMPT_FORMAT\n"
+                " VCPROMPT_FORMAT_GIT, VCPROMPT_FORMAT_HG, etc.\n"
                 );
                 exit(1);
         }
     }
 }
 
-void parse_format(options_t* options)
+void print_result(vccontext_t* context, result_t* result)
 {
     size_t i;
-
-    options->show_branch = 0;
-    options->show_unknown = 0;
-    options->show_modified = 0;
-
-    char* format = options->format;
-    size_t len = strlen(format);
-    for (i = 0; i < len; i++) {
-        if (format[i] == '%') {
-            i++;
-            switch (format[i]) {
-                case '\0':              /* at end of string: ignore */
-                    break;
-                case 'b':
-                    options->show_branch = 1;
-                    break;
-                case 'r':
-                    options->show_revision = 1;
-                    break;
-                case 'u':
-                    options->show_unknown = 1;
-                    break;
-                case 'm':
-                    options->show_modified = 1;
-                    break;
-                case 'n':               /* name of VC system */
-                case '%':
-                    break;
-                default:
-                    fprintf(stderr,
-                            "error: invalid format string: %%%c\n",
-                            format[i]);
-                    break;
-            }
-        }
-    }
-}
-
-void print_result(vccontext_t* context, options_t* options, result_t* result)
-{
-    size_t i;
-    char* format = options->format;
+    char* format = context->options.format;
     size_t len = strlen(format);
 
     for (i = 0; i < len; i++) {
 
 int main(int argc, char** argv)
 {
-    char* format = getenv("VCPROMPT_FORMAT");
-    if (format == NULL)
-        format = DEFAULT_FORMAT;
     options_t options = {
         .debug         = 0,
-        .format        = format,
+        .format        = NULL,
         .show_branch   = 0,
         .show_revision = 0,
         .show_unknown  = 0,
     };
 
     parse_args(argc, argv, &options);
-    parse_format(&options);
     set_debug(&options);
 
     vccontext_t* contexts[] = {
     /* Analyze the working copy metadata and print the result. */
     result = context->get_info(context);
     if (result != NULL) {
-        print_result(context, &options, result);
+        print_result(context, result);
         free_result(result);
         if (options.debug)
             putc('\n', stdout);