From b801d8b2bc1a6aac6b9744f21f7a10a51e16c53e Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Thu, 27 Apr 2006 01:27:53 +0200 Subject: [PATCH] The pager is begining to work. :) Organization: Straylight/Edgeware From: Jonas Fonseca --- Makefile | 19 +- cgit.c | 401 ------------------------------- tig.c | 703 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 714 insertions(+), 409 deletions(-) delete mode 100644 cgit.c create mode 100644 tig.c diff --git a/Makefile b/Makefile index efeca0d..3872851 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ LDFLAGS = -lcurses -CFLAGS = -g -PROGS = cgit -DOCS = cgit.1.txt cgit.1 cgit.1.html +CFLAGS = -g '-DVERSION="$(VERSION)"' -Wall +PROGS = tig +DOCS = tig.1.txt tig.1 tig.1.html +VERSION = $(shell git-describe) all: $(PROGS) docs: $(DOCS) @@ -14,12 +15,14 @@ install: all clean: rm -f $(PROGS) $(DOCS) -cgit: cgit.c +.PHONY: all docs install clean -cgit.1.txt: cgit.c - sed -n '/\*\*/,/\*\*/p' < $< | \ - sed '/\*\*/d' | \ - sed -n 's/^ \* *//p' > $@ +tig: tig.c + +tig.1.txt: tig.c + sed -n '/^\/\*\*/,/\*\*\//p' < $< | \ + sed '/^[^*]\*\*/d' | \ + sed 's/\*\///;s/^[^*]*\* *//' > $@ %.1.html : %.1.txt asciidoc -b xhtml11 -d manpage -f asciidoc.conf $< diff --git a/cgit.c b/cgit.c deleted file mode 100644 index 20d58fa..0000000 --- a/cgit.c +++ /dev/null @@ -1,401 +0,0 @@ -/** - * gitzilla(1) - * =========== - * - * NAME - * ---- - * gitzilla - cursed git browser - * - * SYNOPSIS - * -------- - * gitzilla - * - * DESCRIPTION - * ----------- - * - * a - * - **/ - -#include -#include -#include -#include -#include -#include - -#include - -/** - * OPTIONS - * ------- - * - * None - * - **/ - -/** - * KEYS - * ---- - * - * q:: quit - * s:: shell - * j:: down - * k:: up - * - **/ - -#define MSG_HELP "(q)uit, (s)hell, (j) down, (k) up" - -#define KEY_ESC 27 -#define KEY_TAB 9 - -struct view { - WINDOW *win; - - char *cmd; - void (*reader)(char *, int); - FILE *pipe; - - unsigned long lines; - unsigned long lineno; -}; - -static struct view main_view; -static struct view diff_view; -static struct view log_view; -static struct view status_view; - -int do_resize = 1; - -static void -put_status(char *msg, ...) -{ - va_list args; - - va_start(args, msg); - werase(status_view.win); - wmove(status_view.win, 0, 0); - vwprintw(status_view.win, msg, args); - wrefresh(status_view.win); - va_end(args); -} - -static void -resize_views(void) -{ - int x, y; - - getmaxyx(stdscr, y, x); - - if (status_view.win) - delwin(status_view.win); - status_view.win = newwin(1, 0, y - 1, 0); - - wattrset(status_view.win, COLOR_PAIR(COLOR_GREEN)); - put_status(MSG_HELP); - - if (main_view.win) - delwin(main_view.win); - main_view.win = newwin(y - 1, 0, 0, 0); - - scrollok(main_view.win, TRUE); - keypad(main_view.win, TRUE); /* enable keyboard mapping */ - put_status("%d %d", y, x); -} - -/* - * Init and quit - */ - -static void -quit(int sig) -{ - endwin(); - - /* do your non-curses wrapup here */ - - exit(0); -} - -static void -init_colors(void) -{ - int bg = COLOR_BLACK; - - start_color(); - - if (use_default_colors() != ERR) - bg = -1; - - init_pair(COLOR_BLACK, COLOR_BLACK, bg); - init_pair(COLOR_GREEN, COLOR_GREEN, bg); - init_pair(COLOR_RED, COLOR_RED, bg); - init_pair(COLOR_CYAN, COLOR_CYAN, bg); - init_pair(COLOR_WHITE, COLOR_WHITE, bg); - init_pair(COLOR_MAGENTA, COLOR_MAGENTA, bg); - init_pair(COLOR_BLUE, COLOR_BLUE, bg); - init_pair(COLOR_YELLOW, COLOR_YELLOW, bg); -} - -static void -init(void) -{ - signal(SIGINT, quit); - - initscr(); /* initialize the curses library */ - nonl(); /* tell curses not to do NL->CR/NL on output */ - cbreak(); /* take input chars one at a time, no wait for \n */ - noecho(); /* don't echo input */ - leaveok(stdscr, TRUE); - /* curs_set(0); */ - - if (has_colors()) - init_colors(); -} - -/* - * Pipe readers - */ - -#define DIFF_CMD \ - "git log --stat -n1 HEAD ; echo; " \ - "git diff --find-copies-harder -B -C HEAD^ HEAD" - -#define LOG_CMD \ - "git log --stat -n100" - -static void -log_reader(char *line, int lineno) -{ - static int log_reader_skip; - - if (!line) { - wattrset(main_view.win, A_NORMAL); - log_reader_skip = 0; - return; - } - - if (!strncmp("commit ", line, 7)) { - wattrset(main_view.win, COLOR_PAIR(COLOR_GREEN)); - - } else if (!strncmp("Author: ", line, 8)) { - wattrset(main_view.win, COLOR_PAIR(COLOR_CYAN)); - - } else if (!strncmp("Date: ", line, 8)) { - wattrset(main_view.win, COLOR_PAIR(COLOR_YELLOW)); - - } else if (!strncmp("diff --git ", line, 11)) { - wattrset(main_view.win, COLOR_PAIR(COLOR_YELLOW)); - - } else if (!strncmp("diff-tree ", line, 10)) { - wattrset(main_view.win, COLOR_PAIR(COLOR_BLUE)); - - } else if (!strncmp("index ", line, 6)) { - wattrset(main_view.win, COLOR_PAIR(COLOR_BLUE)); - - } else if (line[0] == '-') { - wattrset(main_view.win, COLOR_PAIR(COLOR_RED)); - - } else if (line[0] == '+') { - wattrset(main_view.win, COLOR_PAIR(COLOR_GREEN)); - - } else if (line[0] == '@') { - wattrset(main_view.win, COLOR_PAIR(COLOR_MAGENTA)); - - } else if (line[0] == ':') { - main_view.lines--; - log_reader_skip = 1; - return; - - } else if (log_reader_skip) { - main_view.lines--; - log_reader_skip = 0; - return; - - } else { - wattrset(main_view.win, A_NORMAL); - } - - mvwaddstr(main_view.win, lineno, 0, line); -} - -static struct view * -update_view(struct view *view, char *cmd) -{ - view->cmd = cmd; - view->pipe = popen(cmd, "r"); - view->lines = 0; - view->lineno = 0; - view->reader = log_reader; - - wclear(view->win); - wmove(view->win, 0, 0); - - put_status("Loading..."); - - return view; -} - -static struct view * -read_pipe(struct view *view, int lines) -{ - char buffer[BUFSIZ]; - char *line; - int x, y; - - while ((line = fgets(buffer, sizeof(buffer), view->pipe))) { - int linelen; - - if (!--lines) - break; - - linelen = strlen(line); - if (linelen) - line[linelen - 1] = 0; - - view->reader(line, view->lines++); - } - - if (ferror(view->pipe)) { - put_status("Failed to read %s", view->cmd, view->lines - 1); - - } else if (feof(view->pipe)) { - put_status("%s (lines %d)", MSG_HELP, view->lines - 1); - - } else { - return view; - } - - view->reader(NULL, view->lines - 1); - pclose(view->pipe); - view->pipe = NULL; - view->reader = NULL; -} - -/* - * Main - */ - -int -main(int argc, char *argv[]) -{ - static struct view *loading_view; - - init(); - - //pipe = open_pipe(LOG_CMD, log_reader); - - for (;;) { - int c; - - if (do_resize) { - resize_views(); - do_resize = 0; - } - - if (loading_view && (loading_view = read_pipe(loading_view, 20))) - nodelay(loading_view->win, TRUE); - - c = wgetch(main_view.win); /* refresh, accept single keystroke of input */ - - if (loading_view) - nodelay(loading_view->win, FALSE); - - /* No input from wgetch() with nodelay() enabled. */ - if (c == ERR) { - doupdate(); - continue; - } - - /* Process the command keystroke */ - switch (c) { - case KEY_RESIZE: - fprintf(stderr, "resize"); - exit; - break; - - case KEY_ESC: - case 'q': - quit(0); - main_view.lineno--; - return 0; - - case KEY_DOWN: - case 'j': - { - int x, y; - - getmaxyx(main_view.win, y, x); - if (main_view.lineno + y < main_view.lines) { - wscrl(main_view.win, 1); - main_view.lineno++; - put_status("line %d out of %d (%d%%)", - main_view.lineno, - main_view.lines, - 100 * main_view.lineno / main_view.lines); - } else { - put_status("last line reached"); - } - break; - } - case KEY_UP: - case 'k': - if (main_view.lineno > 1) { - wscrl(main_view.win, -1); - main_view.lineno--; - put_status("line %d out of %d (%d%%)", - main_view.lineno, - main_view.lines, - 100 * main_view.lineno / main_view.lines); - } else { - put_status("first line reached"); - } - break; - - case 'c': - wclear(main_view.win); - break; - - case 'd': - loading_view = update_view(&main_view, DIFF_CMD); - break; - - case 'l': - loading_view = update_view(&main_view, LOG_CMD); - break; - - case 's': - mvwaddstr(status_view.win, 0, 0, "Shelling out..."); - def_prog_mode(); /* save current tty modes */ - endwin(); /* restore original tty modes */ - system("sh"); /* run shell */ - - werase(status_view.win); - mvwaddstr(status_view.win, 0, 0, MSG_HELP); - reset_prog_mode(); - break; - } - - redrawwin(main_view.win); - wrefresh(main_view.win); - } - - quit(0); -} - -/** - * COPYRIGHT - * --------- - * Copyright (c) Jonas Fonseca, 2006 - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * SEE ALSO - * -------- - * gitlink:cogito[7], - * gitlink:git[7] - **/ diff --git a/tig.c b/tig.c new file mode 100644 index 0000000..5f0a9e1 --- /dev/null +++ b/tig.c @@ -0,0 +1,703 @@ +/** + * TIG(1) + * ====== + * + * NAME + * ---- + * tig - text-mode interface for git + * + * SYNOPSIS + * -------- + * [verse] + * tig + * tig log [git log options] + * tig diff [git diff options] + * tig < [git log or git diff output] + * + * DESCRIPTION + * ----------- + * Browse changes in a git repository. + * + * OPTIONS + * ------- + * + * None. + * + **/ + +#define DEBUG + +#ifndef DEBUG +#define NDEBUG +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +static void die(const char *err, ...); +static void report(const char *msg, ...); + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +#define KEY_ESC 27 +#define KEY_TAB 9 + +#define REQ_OFFSET (MAX_COMMAND + 1) + +/* Requests for switching between the different views. */ +#define REQ_DIFF (REQ_OFFSET + 0) +#define REQ_LOG (REQ_OFFSET + 1) +#define REQ_MAIN (REQ_OFFSET + 2) + +#define REQ_QUIT (REQ_OFFSET + 11) +#define REQ_VERSION (REQ_OFFSET + 12) +#define REQ_STOP (REQ_OFFSET + 13) +#define REQ_UPDATE (REQ_OFFSET + 14) +#define REQ_REDRAW (REQ_OFFSET + 15) + + +/** + * KEYS + * ---- + * + * d:: + * diff + * l:: + * log + * q:: + * quit + * r:: + * redraw screen + * s:: + * stop all background loading + * j:: + * down + * k:: + * up + * h, ?:: + * help + * v:: + * version + * + **/ + +#define HELP "(d)iff, (l)og, (m)ain, (q)uit, (v)ersion, (h)elp" + +struct keymap { + int alias; + int request; +}; + +struct keymap keymap[] = { + { KEY_UP, REQ_PREV_LINE }, + { 'k', REQ_PREV_LINE }, + { KEY_DOWN, REQ_NEXT_LINE }, + { 'j', REQ_NEXT_LINE }, + { KEY_NPAGE, REQ_NEXT_PAGE }, + { KEY_PPAGE, REQ_PREV_PAGE }, + + { 'd', REQ_DIFF }, + { 'l', REQ_LOG }, + { 'm', REQ_MAIN }, + + /* No input from wgetch() with nodelay() enabled. */ + { ERR, REQ_UPDATE }, + + { KEY_ESC, REQ_QUIT }, + { 'q', REQ_QUIT }, + { 's', REQ_STOP }, + { 'v', REQ_VERSION }, + { 'r', REQ_REDRAW }, +}; + +static int +get_request(int request) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(keymap); i++) + if (keymap[i].alias == request) + return keymap[i].request; + + return request; +} + + +/* + * Viewer + */ + +struct view { + char *name; + char *cmd; + + /* Rendering */ + int (*render)(struct view *, int); + WINDOW *win; + + /* Navigation */ + unsigned long offset; /* Offset of the window top */ + unsigned long lineno; /* Current line number */ + + /* Buffering */ + unsigned long lines; /* Total number of lines */ + char **line; /* Line index */ + + /* Loading */ + FILE *pipe; +}; + +static int default_renderer(struct view *view, int lineno); + +#define DIFF_CMD \ + "git log --stat -n1 %s ; echo; " \ + "git diff --find-copies-harder -B -C %s^ %s" + +#define LOG_CMD \ + "git log --stat -n100 %s" + +/* The status window at the bottom. Used for polling keystrokes. */ +static WINDOW *status_win; + +static struct view views[] = { + { "diff", DIFF_CMD, default_renderer }, + { "log", LOG_CMD, default_renderer }, + { "main", NULL }, +}; + +static struct view *display[ARRAY_SIZE(views)]; +static unsigned int current_view; +static unsigned int nloading; + +#define foreach_view(view, i) \ + for (i = 0; i < sizeof(display) && (view = display[i]); i++) + +static void +redraw_view(struct view *view) +{ + int lineno; + int lines, cols; + + wclear(view->win); + wmove(view->win, 0, 0); + + getmaxyx(view->win, lines, cols); + + for (lineno = 0; lineno < lines; lineno++) { + view->render(view, lineno); + } + + redrawwin(view->win); + wrefresh(view->win); +} + +/* FIXME: Fix percentage. */ +static void +report_position(struct view *view, int all) +{ + report(all ? "line %d of %d (%d%%) viewing from %d" + : "line %d of %d", + view->lineno + 1, + view->lines, + view->lines ? view->offset * 100 / view->lines : 0, + view->offset); +} + +static void +scroll_view(struct view *view, int request) +{ + int x, y, lines = 1; + enum { BACKWARD = -1, FORWARD = 1 } direction = FORWARD; + + getmaxyx(view->win, y, x); + + switch (request) { + case REQ_NEXT_PAGE: + lines = y; + case REQ_NEXT_LINE: + if (view->offset + lines > view->lines) + lines = view->lines - view->offset - 1; + + if (lines == 0 || view->offset + y >= view->lines) { + report("already at last line"); + return; + } + break; + + case REQ_PREV_PAGE: + lines = y; + case REQ_PREV_LINE: + if (lines > view->offset) + lines = view->offset; + + if (lines == 0) { + report("already at first line"); + return; + } + + direction = BACKWARD; + break; + + default: + lines = 0; + } + + report("off=%d lines=%d lineno=%d move=%d", view->offset, view->lines, view->lineno, lines * direction); + + /* The rendering expects the new offset. */ + view->offset += lines * direction; + + /* Move current line into the view. */ + if (view->lineno < view->offset) + view->lineno = view->offset; + if (view->lineno > view->offset + y) + view->lineno = view->offset + y; + + assert(0 <= view->offset && view->offset < view->lines); + //assert(0 <= view->offset + lines && view->offset + lines < view->lines); + assert(view->offset <= view->lineno && view->lineno <= view->lines); + + if (lines) { + int from = direction == FORWARD ? y - lines : 0; + int to = from + lines; + + wscrl(view->win, lines * direction); + + for (; from < to; from++) { + if (!view->render(view, from)) + break; + } + } + + redrawwin(view->win); + wrefresh(view->win); + + report_position(view, lines); +} + +static void +resize_view(struct view *view) +{ + int lines, cols; + + getmaxyx(stdscr, lines, cols); + + if (view->win) { + mvwin(view->win, 0, 0); + wresize(view->win, lines - 1, cols); + + } else { + view->win = newwin(lines - 1, 0, 0, 0); + if (!view->win) { + report("Failed to create %s view", view->name); + return; + } + scrollok(view->win, TRUE); + } +} + + +static bool +begin_update(struct view *view) +{ + char buf[1024]; + + if (view->cmd) { + if (snprintf(buf, sizeof(buf), view->cmd, "HEAD", "HEAD", "HEAD") < sizeof(buf)) + view->pipe = popen(buf, "r"); + + if (!view->pipe) + return FALSE; + + if (nloading++ == 0) + nodelay(status_win, TRUE); + } + + display[current_view] = view; + + view->offset = 0; + view->lines = 0; + view->lineno = 0; + + return TRUE; +} + +static void +end_update(struct view *view) +{ + wattrset(view->win, A_NORMAL); + pclose(view->pipe); + view->pipe = NULL; + + if (nloading-- == 1) + nodelay(status_win, FALSE); +} + +static int +update_view(struct view *view) +{ + char buffer[BUFSIZ]; + char *line; + int lines, cols; + char **tmp; + int redraw; + + if (!view->pipe) + return TRUE; + + getmaxyx(view->win, lines, cols); + + redraw = !view->line; + + tmp = realloc(view->line, sizeof(*view->line) * (view->lines + lines)); + if (!tmp) + goto alloc_error; + + view->line = tmp; + + while ((line = fgets(buffer, sizeof(buffer), view->pipe))) { + int linelen; + + if (!lines--) + break; + + linelen = strlen(line); + if (linelen) + line[linelen - 1] = 0; + + view->line[view->lines] = strdup(line); + if (!view->line[view->lines]) + goto alloc_error; + view->lines++; + } + + if (redraw) + redraw_view(view); + + if (ferror(view->pipe)) { + report("Failed to read %s", view->cmd); + goto end; + + } else if (feof(view->pipe)) { + report_position(view, 0); + goto end; + } + + return TRUE; + +alloc_error: + report("Allocation failure"); + +end: + end_update(view); + return FALSE; +} + + +static struct view * +switch_view(struct view *prev, int request) +{ + struct view *view = &views[request - REQ_OFFSET]; + struct view *displayed; + int i; + + if (view == prev) { + foreach_view (displayed, i) ; + + if (i == 1) + report("Already in %s view", view->name); + else + report("FIXME: Maximize"); + + return view; + + } else { + foreach_view (displayed, i) { + if (view == displayed) { + current_view = i; + report("New current view"); + return view; + } + } + } + + if (!view->win) + resize_view(view); + + /* Reload */ + + if (view->line) { + for (i = 0; i < view->lines; i++) + if (view->line[i]) + free(view->line[i]); + + free(view->line); + view->line = NULL; + } + + if (prev && prev->pipe) + end_update(prev); + + if (begin_update(view)) { + if (!view->cmd) + report("%s", HELP); + else + report("loading..."); + } + + return view; +} + + +/* Process a keystroke */ +static int +view_driver(struct view *view, int key) +{ + int request = get_request(key); + int i; + + switch (request) { + case REQ_NEXT_LINE: + case REQ_NEXT_PAGE: + case REQ_PREV_LINE: + case REQ_PREV_PAGE: + if (view) + scroll_view(view, request); + break; + + case REQ_MAIN: + case REQ_LOG: + case REQ_DIFF: + view = switch_view(view, request); + break; + + case REQ_REDRAW: + redraw_view(view); + break; + + case REQ_STOP: + foreach_view (view, i) { + if (view->pipe) { + end_update(view); + scroll_view(view, 0); + } + } + break; + + case REQ_VERSION: + report("version %s", VERSION); + return TRUE; + + case REQ_UPDATE: + doupdate(); + return TRUE; + + case REQ_QUIT: + return FALSE; + + default: + report(HELP); + return TRUE; + } + + return TRUE; +} + + +/* + * Rendering + */ + +#define ATTR(line, attr) { (line), sizeof(line) - 1, (attr) } + +struct attr { + char *line; + int linelen; + int attr; +}; + +static struct attr attrs[] = { + ATTR("commit ", COLOR_PAIR(COLOR_GREEN)), + ATTR("Author: ", COLOR_PAIR(COLOR_CYAN)), + ATTR("Date: ", COLOR_PAIR(COLOR_YELLOW)), + ATTR("diff --git ", COLOR_PAIR(COLOR_YELLOW)), + ATTR("diff-tree ", COLOR_PAIR(COLOR_BLUE)), + ATTR("index ", COLOR_PAIR(COLOR_BLUE)), + ATTR("-", COLOR_PAIR(COLOR_RED)), + ATTR("+", COLOR_PAIR(COLOR_GREEN)), + ATTR("@", COLOR_PAIR(COLOR_MAGENTA)), +}; + +static int +default_renderer(struct view *view, int lineno) +{ + char *line; + int linelen; + int attr = A_NORMAL; + int i; + + line = view->line[view->offset + lineno]; + if (!line) return FALSE; + + linelen = strlen(line); + + for (i = 0; i < ARRAY_SIZE(attrs); i++) { + if (linelen < attrs[i].linelen + || strncmp(attrs[i].line, line, attrs[i].linelen)) + continue; + + attr = attrs[i].attr; + break; + } + + wattrset(view->win, attr); + mvwprintw(view->win, lineno, 0, "%4d: %s", view->offset + lineno, line); + + return TRUE; +} + +/* + * Main + */ + +static void +quit(int sig) +{ + if (status_win) + delwin(status_win); + endwin(); + + /* FIXME: Shutdown gracefully. */ + + exit(0); +} + +static void die(const char *err, ...) +{ + va_list args; + + endwin(); + + va_start(args, err); + fputs("tig: ", stderr); + vfprintf(stderr, err, args); + fputs("\n", stderr); + va_end(args); + + exit(1); +} + +static void +report(const char *msg, ...) +{ + va_list args; + + va_start(args, msg); + + werase(status_win); + wmove(status_win, 0, 0); + + if (display[current_view]) + wprintw(status_win, "%4s: ", display[current_view]->name); + + vwprintw(status_win, msg, args); + wrefresh(status_win); + + va_end(args); +} + +static void +init_colors(void) +{ + int bg = COLOR_BLACK; + + start_color(); + + if (use_default_colors() != ERR) + bg = -1; + + init_pair(COLOR_BLACK, COLOR_BLACK, bg); + init_pair(COLOR_GREEN, COLOR_GREEN, bg); + init_pair(COLOR_RED, COLOR_RED, bg); + init_pair(COLOR_CYAN, COLOR_CYAN, bg); + init_pair(COLOR_WHITE, COLOR_WHITE, bg); + init_pair(COLOR_MAGENTA, COLOR_MAGENTA, bg); + init_pair(COLOR_BLUE, COLOR_BLUE, bg); + init_pair(COLOR_YELLOW, COLOR_YELLOW, bg); +} + +int +main(int argc, char *argv[]) +{ + int request = REQ_MAIN; + int x, y; + + signal(SIGINT, quit); + + initscr(); /* initialize the curses library */ + nonl(); /* tell curses not to do NL->CR/NL on output */ + cbreak(); /* take input chars one at a time, no wait for \n */ + noecho(); /* don't echo input */ + leaveok(stdscr, TRUE); + /* curs_set(0); */ + + if (has_colors()) + init_colors(); + + getmaxyx(stdscr, y, x); + status_win = newwin(1, 0, y - 1, 0); + if (!status_win) + die("Failed to create status window"); + + /* Enable keyboard mapping */ + keypad(status_win, TRUE); + wattrset(status_win, COLOR_PAIR(COLOR_GREEN)); + + while (view_driver(display[current_view], request)) { + struct view *view; + int i; + + foreach_view (view, i) { + if (view->pipe) { + update_view(view); + } + } + + /* Refresh, accept single keystroke of input */ + request = wgetch(status_win); + if (request == KEY_RESIZE) { + int lines, cols; + + getmaxyx(stdscr, lines, cols); + mvwin(status_win, lines - 1, 0); + wresize(status_win, 1, cols - 1); + } + } + + quit(0); + + return 0; +} + +/** + * COPYRIGHT + * --------- + * Copyright (c) Jonas Fonseca, 2006 + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * SEE ALSO + * -------- + * link:http://www.kernel.org/pub/software/scm/git/docs/[git(7)], + * link:http://www.kernel.org/pub/software/scm/cogito/docs/[cogito(7)] + **/ -- [mdw]