7 * gitzilla - cursed git browser
48 #define MSG_HELP "(q)uit, (s)hell, (j) down, (k) up"
57 void (*reader)(char *, int);
64 static struct view main_view;
65 static struct view diff_view;
66 static struct view log_view;
67 static struct view status_view;
72 put_status(char *msg, ...)
77 werase(status_view.win);
78 wmove(status_view.win, 0, 0);
79 vwprintw(status_view.win, msg, args);
80 wrefresh(status_view.win);
89 getmaxyx(stdscr, y, x);
92 delwin(status_view.win);
93 status_view.win = newwin(1, 0, y - 1, 0);
95 wattrset(status_view.win, COLOR_PAIR(COLOR_GREEN));
99 delwin(main_view.win);
100 main_view.win = newwin(y - 1, 0, 0, 0);
102 scrollok(main_view.win, TRUE);
103 keypad(main_view.win, TRUE); /* enable keyboard mapping */
104 put_status("%d %d", y, x);
116 /* do your non-curses wrapup here */
124 int bg = COLOR_BLACK;
128 if (use_default_colors() != ERR)
131 init_pair(COLOR_BLACK, COLOR_BLACK, bg);
132 init_pair(COLOR_GREEN, COLOR_GREEN, bg);
133 init_pair(COLOR_RED, COLOR_RED, bg);
134 init_pair(COLOR_CYAN, COLOR_CYAN, bg);
135 init_pair(COLOR_WHITE, COLOR_WHITE, bg);
136 init_pair(COLOR_MAGENTA, COLOR_MAGENTA, bg);
137 init_pair(COLOR_BLUE, COLOR_BLUE, bg);
138 init_pair(COLOR_YELLOW, COLOR_YELLOW, bg);
144 signal(SIGINT, quit);
146 initscr(); /* initialize the curses library */
147 nonl(); /* tell curses not to do NL->CR/NL on output */
148 cbreak(); /* take input chars one at a time, no wait for \n */
149 noecho(); /* don't echo input */
150 leaveok(stdscr, TRUE);
162 "git log --stat -n1 HEAD ; echo; " \
163 "git diff --find-copies-harder -B -C HEAD^ HEAD"
166 "git log --stat -n100"
169 log_reader(char *line, int lineno)
171 static int log_reader_skip;
174 wattrset(main_view.win, A_NORMAL);
179 if (!strncmp("commit ", line, 7)) {
180 wattrset(main_view.win, COLOR_PAIR(COLOR_GREEN));
182 } else if (!strncmp("Author: ", line, 8)) {
183 wattrset(main_view.win, COLOR_PAIR(COLOR_CYAN));
185 } else if (!strncmp("Date: ", line, 8)) {
186 wattrset(main_view.win, COLOR_PAIR(COLOR_YELLOW));
188 } else if (!strncmp("diff --git ", line, 11)) {
189 wattrset(main_view.win, COLOR_PAIR(COLOR_YELLOW));
191 } else if (!strncmp("diff-tree ", line, 10)) {
192 wattrset(main_view.win, COLOR_PAIR(COLOR_BLUE));
194 } else if (!strncmp("index ", line, 6)) {
195 wattrset(main_view.win, COLOR_PAIR(COLOR_BLUE));
197 } else if (line[0] == '-') {
198 wattrset(main_view.win, COLOR_PAIR(COLOR_RED));
200 } else if (line[0] == '+') {
201 wattrset(main_view.win, COLOR_PAIR(COLOR_GREEN));
203 } else if (line[0] == '@') {
204 wattrset(main_view.win, COLOR_PAIR(COLOR_MAGENTA));
206 } else if (line[0] == ':') {
211 } else if (log_reader_skip) {
217 wattrset(main_view.win, A_NORMAL);
220 mvwaddstr(main_view.win, lineno, 0, line);
224 update_view(struct view *view, char *cmd)
227 view->pipe = popen(cmd, "r");
230 view->reader = log_reader;
233 wmove(view->win, 0, 0);
235 put_status("Loading...");
241 read_pipe(struct view *view, int lines)
247 while ((line = fgets(buffer, sizeof(buffer), view->pipe))) {
253 linelen = strlen(line);
255 line[linelen - 1] = 0;
257 view->reader(line, view->lines++);
260 if (ferror(view->pipe)) {
261 put_status("Failed to read %s", view->cmd, view->lines - 1);
263 } else if (feof(view->pipe)) {
264 put_status("%s (lines %d)", MSG_HELP, view->lines - 1);
270 view->reader(NULL, view->lines - 1);
281 main(int argc, char *argv[])
283 static struct view *loading_view;
287 //pipe = open_pipe(LOG_CMD, log_reader);
297 if (loading_view && (loading_view = read_pipe(loading_view, 20)))
298 nodelay(loading_view->win, TRUE);
300 c = wgetch(main_view.win); /* refresh, accept single keystroke of input */
303 nodelay(loading_view->win, FALSE);
305 /* No input from wgetch() with nodelay() enabled. */
311 /* Process the command keystroke */
314 fprintf(stderr, "resize");
329 getmaxyx(main_view.win, y, x);
330 if (main_view.lineno + y < main_view.lines) {
331 wscrl(main_view.win, 1);
333 put_status("line %d out of %d (%d%%)",
336 100 * main_view.lineno / main_view.lines);
338 put_status("last line reached");
344 if (main_view.lineno > 1) {
345 wscrl(main_view.win, -1);
347 put_status("line %d out of %d (%d%%)",
350 100 * main_view.lineno / main_view.lines);
352 put_status("first line reached");
357 wclear(main_view.win);
361 loading_view = update_view(&main_view, DIFF_CMD);
365 loading_view = update_view(&main_view, LOG_CMD);
369 mvwaddstr(status_view.win, 0, 0, "Shelling out...");
370 def_prog_mode(); /* save current tty modes */
371 endwin(); /* restore original tty modes */
372 system("sh"); /* run shell */
374 werase(status_view.win);
375 mvwaddstr(status_view.win, 0, 0, MSG_HELP);
380 redrawwin(main_view.win);
381 wrefresh(main_view.win);
390 * Copyright (c) Jonas Fonseca, 2006
392 * This program is free software; you can redistribute it and/or modify
393 * it under the terms of the GNU General Public License as published by
394 * the Free Software Foundation; either version 2 of the License, or
395 * (at your option) any later version.