diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2016-11-14 23:30:17 +0100 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2016-11-15 12:56:56 +0100 |
| commit | 0f479c4da7f0c62d7422417d3d0601c853f043aa (patch) | |
| tree | 6bb592276fd977cdbca06f8bab4eac6c4d148cf5 | |
| parent | d770aa314255313e97b3ecb4c0cafde0fca16c9d (diff) | |
| download | vis-0f479c4da7f0c62d7422417d3d0601c853f043aa.tar.gz vis-0f479c4da7f0c62d7422417d3d0601c853f043aa.tar.xz | |
vis: defer UI initialization and overhaul argument parsing
Do not initalize curses UI before it is actually needed.
Move vis command line argument parsing logic into main.c.
This fixes `vis -v` output and exit status.
Fix #351
| -rw-r--r-- | main.c | 64 | ||||
| -rw-r--r-- | ui-curses.c | 56 | ||||
| -rw-r--r-- | ui.h | 1 | ||||
| -rw-r--r-- | vis-core.h | 1 | ||||
| -rw-r--r-- | vis.c | 67 |
5 files changed, 98 insertions, 91 deletions
@@ -4,6 +4,9 @@ #include <wchar.h> #include <ctype.h> #include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> #include "ui-curses.h" #include "vis.h" @@ -2242,6 +2245,67 @@ int main(int argc, char *argv[]) { sigprocmask(SIG_BLOCK, &blockset, NULL); signal(SIGPIPE, SIG_IGN); + for (int i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + continue; + } else if (strcmp(argv[i], "-") == 0) { + continue; + } else if (strcmp(argv[i], "--") == 0) { + break; + } else if (strcmp(argv[i], "-v") == 0) { + puts("vis " VERSION); + return 0; + } else { + fprintf(stderr, "Unknown command option: %s\n", argv[i]); + return 1; + } + } + + char *cmd = NULL; + bool end_of_options = false, win_created = false; + + for (int i = 1; i < argc; i++) { + if (argv[i][0] == '-' && !end_of_options) { + if (strcmp(argv[i], "-") == 0) { + if (!vis_window_new_fd(vis, STDOUT_FILENO)) + vis_die(vis, "Can not create empty buffer\n"); + ssize_t len = 0; + char buf[PIPE_BUF]; + Text *txt = vis_text(vis); + while ((len = read(STDIN_FILENO, buf, sizeof buf)) > 0) + text_insert(txt, text_size(txt), buf, len); + if (len == -1) + vis_die(vis, "Can not read from stdin\n"); + text_snapshot(txt); + int fd = open("/dev/tty", O_RDONLY); + if (fd == -1) + vis_die(vis, "Can not reopen stdin\n"); + dup2(fd, STDIN_FILENO); + close(fd); + } else if (strcmp(argv[i], "--") == 0) { + end_of_options = true; + } + end_of_options = !strcmp(argv[i], "--"); + } else if (argv[i][0] == '+' && !end_of_options) { + cmd = argv[i] + (argv[i][1] == '/' || argv[i][1] == '?'); + } else if (!vis_window_new(vis, argv[i])) { + vis_die(vis, "Can not load `%s': %s\n", argv[i], strerror(errno)); + } else { + win_created = true; + if (cmd) { + vis_prompt_cmd(vis, cmd); + cmd = NULL; + } + } + } + + if (!vis_window(vis) && !win_created) { + if (!vis_window_new(vis, NULL)) + vis_die(vis, "Can not create empty buffer\n"); + if (cmd) + vis_prompt_cmd(vis, cmd); + } + int status = vis_run(vis, argc, argv); vis_free(vis); return status; diff --git a/ui-curses.c b/ui-curses.c index b8f1e05..b1972da 100644 --- a/ui-curses.c +++ b/ui-curses.c @@ -1048,16 +1048,6 @@ static void ui_info_hide(Ui *ui) { } } -static bool ui_init(Ui *ui, Vis *vis) { - UiCurses *uic = (UiCurses*)ui; - uic->vis = vis; - return true; -} - -static bool ui_start(Ui *ui) { - return true; -} - static TermKey *ui_termkey_new(int fd) { TermKey *termkey = termkey_new(fd, TERMKEY_FLAG_UTF8); if (termkey) @@ -1127,12 +1117,9 @@ static int ui_colors(Ui *ui) { return COLORS; } -Ui *ui_curses_new(void) { - - UiCurses *uic = calloc(1, sizeof(UiCurses)); - Ui *ui = (Ui*)uic; - if (!uic) - return NULL; +static bool ui_init(Ui *ui, Vis *vis) { + UiCurses *uic = (UiCurses*)ui; + uic->vis = vis; tcgetattr(STDERR_FILENO, &uic->tio); if (!(uic->termkey = ui_termkey_new(STDIN_FILENO))) goto err; @@ -1155,13 +1142,30 @@ Ui *ui_curses_new(void) { keypad(stdscr, TRUE); meta(stdscr, TRUE); curs_set(0); - /* needed because we use getch() which implicitly calls refresh() which - would clear the screen (overwrite it with an empty / unused stdscr */ - refresh(); + + struct sigaction sa; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = sigwinch_handler; + sigaction(SIGWINCH, &sa, NULL); + sigaction(SIGCONT, &sa, NULL); + + ui_resize(ui); + + return true; +err: + ui_die_msg(ui, "Failed to start curses interface\n"); + return false; +} + +Ui *ui_curses_new(void) { + + Ui *ui = calloc(1, sizeof(UiCurses)); + if (!ui) + return NULL; *ui = (Ui) { .init = ui_init, - .start = ui_start, .free = ui_curses_free, .termkey_get = ui_termkey_get, .suspend = ui_suspend, @@ -1183,19 +1187,7 @@ Ui *ui_curses_new(void) { .colors = ui_colors, }; - struct sigaction sa; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = sigwinch_handler; - sigaction(SIGWINCH, &sa, NULL); - sigaction(SIGCONT, &sa, NULL); - - ui_resize(ui); - return ui; -err: - ui_curses_free(ui); - return NULL; } void ui_curses_free(Ui *ui) { @@ -51,7 +51,6 @@ enum UiStyle { struct Ui { bool (*init)(Ui*, Vis*); - bool (*start)(Ui*); void (*free)(Ui*); void (*resize)(Ui*); UiWin* (*window_new)(Ui*, View*, File*, enum UiOption); @@ -172,6 +172,7 @@ struct Vis { Action action_prev; /* last operator action used by the repeat (dot) command */ Mode *mode; /* currently active mode, used to search for keybindings */ Mode *mode_prev; /* previsouly active user mode */ + bool initialized; /* whether UI and Lua integration has been initialized */ volatile bool running; /* exit main loop once this becomes false */ int exit_status; /* exit status when terminating main loop */ volatile sig_atomic_t cancel_filter; /* abort external command/filter (SIGINT occured) */ @@ -37,6 +37,13 @@ bool vis_event_emit(Vis *vis, enum VisEvents id, ...) { if (!vis->event) return true; + if (!vis->initialized) { + vis->initialized = true; + vis->ui->init(vis->ui, vis); + if (vis->event && vis->event->vis_init) + vis->event->vis_init(vis); + } + va_list ap; va_start(ap, id); bool ret = true; @@ -493,7 +500,6 @@ Vis *vis_new(Ui *ui, VisEvent *event) { if (!vis) return NULL; vis->ui = ui; - vis->ui->init(vis->ui, vis); vis->tabwidth = 8; vis->expandtab = false; vis->registers[VIS_REG_BLACKHOLE].type = REGISTER_BLACKHOLE; @@ -525,9 +531,6 @@ Vis *vis_new(Ui *ui, VisEvent *event) { goto err; vis->mode_prev = vis->mode = &vis_modes[VIS_MODE_NORMAL]; vis->event = event; - if (event && event->vis_init) - event->vis_init(vis); - vis->ui->start(vis->ui); return vis; err: vis_free(vis); @@ -982,62 +985,10 @@ bool vis_signal_handler(Vis *vis, int signum, const siginfo_t *siginfo, const vo return false; } -static void vis_args(Vis *vis, int argc, char *argv[]) { - char *cmd = NULL; - bool end_of_options = false; - for (int i = 1; i < argc; i++) { - if (argv[i][0] == '-' && !end_of_options) { - switch (argv[i][1]) { - case '-': - end_of_options = true; - break; - case 'v': - vis_die(vis, "vis %s\n", VERSION); - break; - case '\0': - break; - default: - vis_die(vis, "Unknown command option: %s\n", argv[i]); - break; - } - } else if (argv[i][0] == '+') { - cmd = argv[i] + (argv[i][1] == '/' || argv[i][1] == '?'); - } else if (!vis_window_new(vis, argv[i])) { - vis_die(vis, "Can not load `%s': %s\n", argv[i], strerror(errno)); - } else if (cmd) { - vis_prompt_cmd(vis, cmd); - cmd = NULL; - } - } - - if (!vis->windows && vis->running) { - if (!strcmp(argv[argc-1], "-")) { - if (!vis_window_new_fd(vis, STDOUT_FILENO)) - vis_die(vis, "Can not create empty buffer\n"); - ssize_t len = 0; - char buf[PIPE_BUF]; - Text *txt = vis_text(vis); - while ((len = read(STDIN_FILENO, buf, sizeof buf)) > 0) - text_insert(txt, text_size(txt), buf, len); - if (len == -1) - vis_die(vis, "Can not read from stdin\n"); - text_snapshot(txt); - int fd = open("/dev/tty", O_RDONLY); - if (fd == -1) - vis_die(vis, "Can not reopen stdin\n"); - dup2(fd, STDIN_FILENO); - close(fd); - } else if (!vis_window_new(vis, NULL)) { - vis_die(vis, "Can not create empty buffer\n"); - } - if (cmd) - vis_prompt_cmd(vis, cmd); - } -} - int vis_run(Vis *vis, int argc, char *argv[]) { + if (!vis->windows) + return EXIT_SUCCESS; vis->running = true; - vis_args(vis, argc, argv); vis_event_emit(vis, VIS_EVENT_START); |
