From a7bc4b1447f974fbbe400c3657d9ec3d0fda133e Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Sat, 22 Apr 2006 21:39:33 +0200 Subject: [PATCH] Exploration --- Makefile | 25 ++++- asciidoc.conf | 25 +++++ cgit.c | 292 +++++++++++++++++++++++++++++++++----------------- 3 files changed, 241 insertions(+), 101 deletions(-) create mode 100644 asciidoc.conf diff --git a/Makefile b/Makefile index eec1e03..efeca0d 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,31 @@ LDFLAGS = -lcurses CFLAGS = -g +PROGS = cgit +DOCS = cgit.1.txt cgit.1 cgit.1.html -all: cgit +all: $(PROGS) +docs: $(DOCS) install: all - install cgit $(HOME)/bin + for prog in $(PROGS); do \ + install $$prog $(HOME)/bin; \ + done clean: - rm -f cgit + rm -f $(PROGS) $(DOCS) cgit: cgit.c + +cgit.1.txt: cgit.c + sed -n '/\*\*/,/\*\*/p' < $< | \ + sed '/\*\*/d' | \ + sed -n 's/^ \* *//p' > $@ + +%.1.html : %.1.txt + asciidoc -b xhtml11 -d manpage -f asciidoc.conf $< + +%.1.xml : %.1.txt + asciidoc -b docbook -d manpage -f asciidoc.conf $< + +%.1 : %.1.xml + xmlto man $< diff --git a/asciidoc.conf b/asciidoc.conf new file mode 100644 index 0000000..e4178cc --- /dev/null +++ b/asciidoc.conf @@ -0,0 +1,25 @@ +## gitlink: macro +# +# Usage: gitlink:command[manpage-section] +# +# Note, {0} is the manpage section, while {target} is the command. +# +# Show GIT link as: (
); if section is defined, else just show +# the command. + +ifdef::backend-docbook[] +[gitlink-inlinemacro] +{0%{target}} +{0#} +{0#{target}{0}} +{0#} +endif::backend-docbook[] + +ifdef::backend-xhtml11[] +[gitlink-inlinemacro] +{target}{0?({0})} +endif::backend-xhtml11[] + +[attributes] +# Five non breaking spaces used for option indentation in the quick reference +cg-refopt=      diff --git a/cgit.c b/cgit.c index a05103e..20d58fa 100644 --- a/cgit.c +++ b/cgit.c @@ -1,12 +1,21 @@ -/* Cursed git browser +/** + * gitzilla(1) + * =========== * - * Copyright (c) Jonas Fonseca, 2006 + * NAME + * ---- + * gitzilla - cursed git browser * - * 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. - */ + * SYNOPSIS + * -------- + * gitzilla + * + * DESCRIPTION + * ----------- + * + * a + * + **/ #include #include @@ -17,22 +26,47 @@ #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 -//WINDOW *titlewin; -WINDOW *mainwin; -WINDOW *statuswin; +struct view { + WINDOW *win; -typedef void (*pipe_reader_T)(char *, int); + char *cmd; + void (*reader)(char *, int); + FILE *pipe; -FILE *pipe; -long pipe_lineno; -pipe_reader_T pipe_reader; + 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, ...) @@ -40,13 +74,36 @@ put_status(char *msg, ...) va_list args; va_start(args, msg); - werase(statuswin); - wmove(statuswin, 0, 0); - vwprintw(statuswin, msg, args); - wrefresh(statuswin); + 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 */ @@ -84,8 +141,6 @@ init_colors(void) static void init(void) { - int x, y; - signal(SIGINT, quit); initscr(); /* initialize the curses library */ @@ -93,30 +148,10 @@ init(void) 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); - -#if 0 - titlewin = newwin(1, 0, y - 2, 0); - - wattrset(titlewin, COLOR_PAIR(COLOR_GREEN)); - waddch(titlewin, ACS_VLINE); - wprintw(titlewin, "%s", "cg-view"); - waddch(titlewin, ACS_LTEE); - whline(titlewin, ACS_HLINE, x); - wrefresh(titlewin); -#endif - statuswin = newwin(1, 0, y - 1, 0); - - wattrset(statuswin, COLOR_PAIR(COLOR_GREEN)); - put_status(MSG_HELP); - - mainwin = newwin(y - 1, 0, 0, 0); - scrollok(mainwin, TRUE); - keypad(mainwin, TRUE); /* enable keyboard mapping */ } /* @@ -124,16 +159,11 @@ init(void) */ #define DIFF_CMD \ - "git-rev-list HEAD^..HEAD | " \ - "git-diff-tree --stdin --pretty -r --cc --always --stat" - - -#define LOG_CMD0 \ - "git-rev-list $(git-rev-parse --since=1.month) HEAD | " \ - "git-diff-tree --stdin --pretty -r --root" + "git log --stat -n1 HEAD ; echo; " \ + "git diff --find-copies-harder -B -C HEAD^ HEAD" #define LOG_CMD \ - "git-rev-list HEAD | git-diff-tree --stdin --pretty -r --root" + "git log --stat -n100" static void log_reader(char *line, int lineno) @@ -141,75 +171,80 @@ log_reader(char *line, int lineno) static int log_reader_skip; if (!line) { - wattrset(mainwin, A_NORMAL); + wattrset(main_view.win, A_NORMAL); log_reader_skip = 0; return; } if (!strncmp("commit ", line, 7)) { - wattrset(mainwin, COLOR_PAIR(COLOR_GREEN)); + wattrset(main_view.win, COLOR_PAIR(COLOR_GREEN)); } else if (!strncmp("Author: ", line, 8)) { - wattrset(mainwin, COLOR_PAIR(COLOR_CYAN)); + wattrset(main_view.win, COLOR_PAIR(COLOR_CYAN)); - } else if (!strncmp("Date: ", line, 6)) { - wattrset(mainwin, COLOR_PAIR(COLOR_YELLOW)); + } else if (!strncmp("Date: ", line, 8)) { + wattrset(main_view.win, COLOR_PAIR(COLOR_YELLOW)); } else if (!strncmp("diff --git ", line, 11)) { - wattrset(mainwin, COLOR_PAIR(COLOR_YELLOW)); + wattrset(main_view.win, COLOR_PAIR(COLOR_YELLOW)); } else if (!strncmp("diff-tree ", line, 10)) { - wattrset(mainwin, COLOR_PAIR(COLOR_BLUE)); + wattrset(main_view.win, COLOR_PAIR(COLOR_BLUE)); } else if (!strncmp("index ", line, 6)) { - wattrset(mainwin, COLOR_PAIR(COLOR_BLUE)); + wattrset(main_view.win, COLOR_PAIR(COLOR_BLUE)); } else if (line[0] == '-') { - wattrset(mainwin, COLOR_PAIR(COLOR_RED)); + wattrset(main_view.win, COLOR_PAIR(COLOR_RED)); } else if (line[0] == '+') { - wattrset(mainwin, COLOR_PAIR(COLOR_GREEN)); + wattrset(main_view.win, COLOR_PAIR(COLOR_GREEN)); } else if (line[0] == '@') { - wattrset(mainwin, COLOR_PAIR(COLOR_MAGENTA)); + wattrset(main_view.win, COLOR_PAIR(COLOR_MAGENTA)); } else if (line[0] == ':') { - pipe_lineno--; + main_view.lines--; log_reader_skip = 1; return; } else if (log_reader_skip) { - pipe_lineno--; + main_view.lines--; log_reader_skip = 0; return; } else { - wattrset(mainwin, A_NORMAL); + wattrset(main_view.win, A_NORMAL); } - mvwaddstr(mainwin, lineno, 0, line); + mvwaddstr(main_view.win, lineno, 0, line); } -static FILE * -open_pipe(char *cmd, pipe_reader_T reader) +static struct view * +update_view(struct view *view, char *cmd) { - pipe = popen(cmd, "r"); - pipe_lineno = 0; - pipe_reader = reader; - wclear(mainwin); - wmove(mainwin, 0, 0); + 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 pipe; + + return view; } -static void -read_pipe(int lines) +static struct view * +read_pipe(struct view *view, int lines) { char buffer[BUFSIZ]; char *line; int x, y; - while ((line = fgets(buffer, sizeof(buffer), pipe))) { + while ((line = fgets(buffer, sizeof(buffer), view->pipe))) { int linelen; if (!--lines) @@ -219,16 +254,23 @@ read_pipe(int lines) if (linelen) line[linelen - 1] = 0; - pipe_reader(line, pipe_lineno++); + view->reader(line, view->lines++); } - if (feof(pipe) || ferror(pipe)) { - pipe_reader(NULL, pipe_lineno - 1); - pclose(pipe); - pipe = NULL; - pipe_reader = NULL; - put_status("%s (lines %d)", MSG_HELP, pipe_lineno - 1); + 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; } /* @@ -238,6 +280,8 @@ read_pipe(int lines) int main(int argc, char *argv[]) { + static struct view *loading_view; + init(); //pipe = open_pipe(LOG_CMD, log_reader); @@ -245,61 +289,113 @@ main(int argc, char *argv[]) for (;;) { int c; - if (pipe) read_pipe(20); - if (pipe) nodelay(mainwin, TRUE); + 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(mainwin); /* refresh, accept single keystroke of input */ + c = wgetch(main_view.win); /* refresh, accept single keystroke of input */ - if (pipe) nodelay(mainwin, FALSE); + if (loading_view) + nodelay(loading_view->win, FALSE); /* No input from wgetch() with nodelay() enabled. */ - if (c == ERR) + 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': - wscrl(mainwin, 1); + { + 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': - wscrl(mainwin, -1); + 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(mainwin); + wclear(main_view.win); break; case 'd': - pipe = open_pipe(DIFF_CMD, log_reader); + loading_view = update_view(&main_view, DIFF_CMD); break; case 'l': - pipe = open_pipe(LOG_CMD, log_reader); + loading_view = update_view(&main_view, LOG_CMD); break; case 's': - mvwaddstr(statuswin, 0, 0, "Shelling out..."); + 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(statuswin); - mvwaddstr(statuswin, 0, 0, MSG_HELP); + werase(status_view.win); + mvwaddstr(status_view.win, 0, 0, MSG_HELP); reset_prog_mode(); break; } - redrawwin(mainwin); - wrefresh(mainwin); + 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] + **/ -- 2.30.2