*
*/
+#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <curses.h>
+
+#define CGIT_HELP "(q)uit, (s)hell, (j) down, (k) up"
+#define KEY_ESC 27
+#define KEY_TAB 9
+
+//WINDOW *titlewin;
+WINDOW *mainwin;
+WINDOW *statuswin;
+
+typedef void (*pipe_filter_T)(char *, int);
+
+FILE *pipe;
+long pipe_lineno;
+pipe_filter_T pipe_filter;
+
+
+static void
+put_status(char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ werase(statuswin);
+ wmove(statuswin, 0, 0);
+ vwprintw(statuswin, msg, args);
+ wrefresh(statuswin);
+ va_end(args);
+}
+
/*
* Init and quit
*/
-static void quit(int sig)
+static void
+quit(int sig)
{
endwin();
static void
init_colors(void)
{
+ int bg = COLOR_BLACK;
+
start_color();
- init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
- init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
- init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
- init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
- init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
- init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
- init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
- init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
+ 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)
{
- (void) signal(SIGINT, quit); /* arrange interrupts to terminate */
+ int x, y;
+
+ signal(SIGINT, quit);
- (void) initscr(); /* initialize the curses library */
- keypad(stdscr, TRUE); /* enable keyboard mapping */
- (void) nonl(); /* tell curses not to do NL->CR/NL on output */
- (void) cbreak(); /* take input chars one at a time, no wait for \n */
- (void) noecho(); /* don't echo input */
+ 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);
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(CGIT_HELP);
+
+ mainwin = newwin(y - 1, 0, 0, 0);
+ scrollok(mainwin, TRUE);
+ keypad(mainwin, TRUE); /* enable keyboard mapping */
}
/*
- * Main
+ * Pipe filters
*/
-int
-main(int argc, char *argv[])
+#define DIFF_CMD \
+ "git-rev-list HEAD^..HEAD | " \
+ "git-diff-tree --stdin --pretty -r --cc --always"
+
+
+#define LOG_CMD \
+ "git-rev-list $(git-rev-parse --since=1.month) HEAD | " \
+ "git-diff-tree --stdin --pretty -r --root"
+
+static void
+log_filter(char *line, int lineno)
+{
+ static int log_filter_skip;
+
+ if (!line) {
+ wattrset(mainwin, A_NORMAL);
+ log_filter_skip = 0;
+ return;
+ }
+
+ if (!strncmp("commit ", line, 7)) {
+ attrset(COLOR_PAIR(COLOR_GREEN));
+
+ } else if (!strncmp("Author: ", line, 8)) {
+ wattrset(mainwin, COLOR_PAIR(COLOR_CYAN));
+
+ } else if (!strncmp("Date: ", line, 6)) {
+ wattrset(mainwin, COLOR_PAIR(COLOR_YELLOW));
+
+ } else if (!strncmp("diff --git ", line, 11)) {
+ wattrset(mainwin, COLOR_PAIR(COLOR_YELLOW));
+
+ } else if (!strncmp("diff-tree ", line, 10)) {
+ wattrset(mainwin, COLOR_PAIR(COLOR_BLUE));
+
+ } else if (!strncmp("index ", line, 6)) {
+ wattrset(mainwin, COLOR_PAIR(COLOR_BLUE));
+
+ } else if (line[0] == '-') {
+ wattrset(mainwin, COLOR_PAIR(COLOR_RED));
+
+ } else if (line[0] == '+') {
+ wattrset(mainwin, COLOR_PAIR(COLOR_GREEN));
+
+ } else if (line[0] == '@') {
+ wattrset(mainwin, COLOR_PAIR(COLOR_MAGENTA));
+
+ } else if (line[0] == ':') {
+ pipe_lineno--;
+ log_filter_skip = 1;
+ return;
+
+ } else if (log_filter_skip) {
+ pipe_lineno--;
+ log_filter_skip = 0;
+ return;
+
+ } else {
+ wattrset(mainwin, A_NORMAL);
+ }
+
+ mvwaddstr(mainwin, lineno, 0, line);
+}
+
+static FILE *
+open_pipe(char *cmd, pipe_filter_T filter)
{
+ pipe = popen(cmd, "r");
+ pipe_lineno = 0;
+ pipe_filter = filter;
+ wclear(mainwin);
+ wmove(mainwin, 0, 0);
+ put_status("Loading...");
+ return pipe;
+}
+
+static void
+read_pipe(int lines)
+{
+ char buffer[BUFSIZ];
+ char *line;
int x, y;
- init();
+ while ((line = fgets(buffer, sizeof(buffer), pipe))) {
+ int linelen;
- getmaxyx(stdscr, y, x);
+ if (!--lines)
+ break;
- attrset(COLOR_PAIR(COLOR_GREEN));
-
- addch(ACS_VLINE);
- printw("%s", "cg-view");
- addch(ACS_LTEE);
- addch(ACS_HLINE);
- addch(ACS_HLINE);
- addch(ACS_HLINE);
- addch(ACS_HLINE);
- addch(ACS_HLINE);
- addch(ACS_HLINE);
- addch(ACS_HLINE);
- mvprintw(y - 1, 0, "%s", "press 'q' to quit");
-
- {
- FILE *rev_list = popen("git-rev-list $(git-rev-parse --since=1.month) HEAD", "r");
- char buffer[BUFSIZ];
- char *line;
- int lineno = 1;
-
- while ((line = fgets(buffer, sizeof(buffer), rev_list))) {
- move(lineno, 0);
- printw("%2d: ", lineno++);
- addch(ACS_LTEE);
- addch(ACS_HLINE);
- addstr(line);
- }
+ linelen = strlen(line);
+ if (linelen)
+ line[linelen - 1] = 0;
+
+ pipe_filter(line, pipe_lineno++);
}
- attrset(A_NORMAL);
-/* scrollok();*/
+
+ if (feof(pipe) || ferror(pipe)) {
+ pipe_filter(NULL, pipe_lineno - 1);
+ pclose(pipe);
+ pipe = NULL;
+ pipe_filter = NULL;
+ put_status("%s (lines %d)", CGIT_HELP, pipe_lineno - 1);
+ }
+}
+
+/*
+ * Main
+ */
+
+int
+main(int argc, char *argv[])
+{
+ init();
+
+ //pipe = open_pipe(LOG_CMD, log_filter);
for (;;) {
- int c = getch(); /* refresh, accept single keystroke of input */
+ int c;
+
+ if (pipe) read_pipe(20);
+ if (pipe) nodelay(mainwin, TRUE);
+
+ c = wgetch(mainwin); /* refresh, accept single keystroke of input */
+
+ if (pipe) nodelay(mainwin, FALSE);
+
+ /* No input from wgetch() with nodelay() enabled. */
+ if (c == ERR)
+ continue;
/* Process the command keystroke */
switch (c) {
+ case KEY_ESC:
case 'q':
quit(0);
return 0;
+ case KEY_DOWN:
+ case 'j':
+ wscrl(mainwin, 1);
+ break;
+
+ case KEY_UP:
+ case 'k':
+ wscrl(mainwin, -1);
+ break;
+
+ case 'c':
+ wclear(mainwin);
+ break;
+
+ case 'd':
+ pipe = open_pipe(DIFF_CMD, log_filter);
+ break;
+
+ case 'l':
+ pipe = open_pipe(LOG_CMD, log_filter);
+ break;
+
case 's':
- addstr("Shelling out...");
+ mvwaddstr(statuswin, 0, 0, "Shelling out...");
def_prog_mode(); /* save current tty modes */
endwin(); /* restore original tty modes */
system("sh"); /* run shell */
- addstr("returned.\n"); /* prepare return message */
+
+ werase(statuswin);
+ mvwaddstr(statuswin, 0, 0, CGIT_HELP);
reset_prog_mode();
- //refresh(); /* restore save modes, repaint screen */
break;
-
- default:
- if (isprint(c) || isspace(c))
- addch(c);
}
+ redrawwin(mainwin);
+ wrefresh(mainwin);
}
quit(0);