editor.con commit Merge branch 'dl/use-sq-from-test-lib' (d693345)
   1#include "cache.h"
   2#include "config.h"
   3#include "strbuf.h"
   4#include "run-command.h"
   5#include "sigchain.h"
   6
   7#ifndef DEFAULT_EDITOR
   8#define DEFAULT_EDITOR "vi"
   9#endif
  10
  11int is_terminal_dumb(void)
  12{
  13        const char *terminal = getenv("TERM");
  14        return !terminal || !strcmp(terminal, "dumb");
  15}
  16
  17const char *git_editor(void)
  18{
  19        const char *editor = getenv("GIT_EDITOR");
  20        int terminal_is_dumb = is_terminal_dumb();
  21
  22        if (!editor && editor_program)
  23                editor = editor_program;
  24        if (!editor && !terminal_is_dumb)
  25                editor = getenv("VISUAL");
  26        if (!editor)
  27                editor = getenv("EDITOR");
  28
  29        if (!editor && terminal_is_dumb)
  30                return NULL;
  31
  32        if (!editor)
  33                editor = DEFAULT_EDITOR;
  34
  35        return editor;
  36}
  37
  38const char *git_sequence_editor(void)
  39{
  40        const char *editor = getenv("GIT_SEQUENCE_EDITOR");
  41
  42        if (!editor)
  43                git_config_get_string_const("sequence.editor", &editor);
  44        if (!editor)
  45                editor = git_editor();
  46
  47        return editor;
  48}
  49
  50static int launch_specified_editor(const char *editor, const char *path,
  51                                   struct strbuf *buffer, const char *const *env)
  52{
  53        if (!editor)
  54                return error("Terminal is dumb, but EDITOR unset");
  55
  56        if (strcmp(editor, ":")) {
  57                const char *args[] = { editor, real_path(path), NULL };
  58                struct child_process p = CHILD_PROCESS_INIT;
  59                int ret, sig;
  60                int print_waiting_for_editor = advice_waiting_for_editor && isatty(2);
  61
  62                if (print_waiting_for_editor) {
  63                        /*
  64                         * A dumb terminal cannot erase the line later on. Add a
  65                         * newline to separate the hint from subsequent output.
  66                         *
  67                         * Make sure that our message is separated with a whitespace
  68                         * from further cruft that may be written by the editor.
  69                         */
  70                        const char term = is_terminal_dumb() ? '\n' : ' ';
  71
  72                        fprintf(stderr,
  73                                _("hint: Waiting for your editor to close the file...%c"),
  74                                term);
  75                        fflush(stderr);
  76                }
  77
  78                p.argv = args;
  79                p.env = env;
  80                p.use_shell = 1;
  81                p.trace2_child_class = "editor";
  82                if (start_command(&p) < 0)
  83                        return error("unable to start editor '%s'", editor);
  84
  85                sigchain_push(SIGINT, SIG_IGN);
  86                sigchain_push(SIGQUIT, SIG_IGN);
  87                ret = finish_command(&p);
  88                sig = ret - 128;
  89                sigchain_pop(SIGINT);
  90                sigchain_pop(SIGQUIT);
  91                if (sig == SIGINT || sig == SIGQUIT)
  92                        raise(sig);
  93                if (ret)
  94                        return error("There was a problem with the editor '%s'.",
  95                                        editor);
  96
  97                if (print_waiting_for_editor && !is_terminal_dumb())
  98                        /*
  99                         * Erase the entire line to avoid wasting the
 100                         * vertical space.
 101                         */
 102                        term_clear_line();
 103        }
 104
 105        if (!buffer)
 106                return 0;
 107        if (strbuf_read_file(buffer, path, 0) < 0)
 108                return error_errno("could not read file '%s'", path);
 109        return 0;
 110}
 111
 112int launch_editor(const char *path, struct strbuf *buffer, const char *const *env)
 113{
 114        return launch_specified_editor(git_editor(), path, buffer, env);
 115}
 116
 117int launch_sequence_editor(const char *path, struct strbuf *buffer,
 118                           const char *const *env)
 119{
 120        return launch_specified_editor(git_sequence_editor(), path, buffer, env);
 121}