Commit | Line | Data |
---|---|---|
800a900c JF |
1 | /* |
2 | * | |
3 | * | |
4 | */ | |
5 | ||
e3e7b9fc | 6 | #include <stdarg.h> |
800a900c JF |
7 | #include <stdlib.h> |
8 | #include <stdio.h> | |
e3e7b9fc | 9 | #include <string.h> |
800a900c JF |
10 | #include <ctype.h> |
11 | #include <signal.h> | |
12 | ||
13 | #include <curses.h> | |
14 | ||
e3e7b9fc | 15 | |
05f1685b JF |
16 | #define CGIT_HELP "(q)uit, (s)hell, (j) down, (k) up" |
17 | #define KEY_ESC 27 | |
18 | #define KEY_TAB 9 | |
19 | ||
e3e7b9fc | 20 | //WINDOW *titlewin; |
05f1685b JF |
21 | WINDOW *mainwin; |
22 | WINDOW *statuswin; | |
23 | ||
24 | typedef void (*pipe_filter_T)(char *, int); | |
25 | ||
26 | FILE *pipe; | |
27 | long pipe_lineno; | |
28 | pipe_filter_T pipe_filter; | |
29 | ||
e3e7b9fc JF |
30 | |
31 | static void | |
32 | put_status(char *msg, ...) | |
33 | { | |
34 | va_list args; | |
35 | ||
36 | va_start(args, msg); | |
37 | werase(statuswin); | |
38 | wmove(statuswin, 0, 0); | |
39 | vwprintw(statuswin, msg, args); | |
40 | wrefresh(statuswin); | |
41 | va_end(args); | |
42 | } | |
43 | ||
800a900c JF |
44 | /* |
45 | * Init and quit | |
46 | */ | |
47 | ||
05f1685b JF |
48 | static void |
49 | quit(int sig) | |
800a900c JF |
50 | { |
51 | endwin(); | |
52 | ||
53 | /* do your non-curses wrapup here */ | |
54 | ||
55 | exit(0); | |
56 | } | |
57 | ||
58 | static void | |
59 | init_colors(void) | |
60 | { | |
05f1685b JF |
61 | int bg = COLOR_BLACK; |
62 | ||
800a900c JF |
63 | start_color(); |
64 | ||
e3e7b9fc | 65 | if (use_default_colors() != ERR) |
05f1685b JF |
66 | bg = -1; |
67 | ||
68 | init_pair(COLOR_BLACK, COLOR_BLACK, bg); | |
69 | init_pair(COLOR_GREEN, COLOR_GREEN, bg); | |
70 | init_pair(COLOR_RED, COLOR_RED, bg); | |
71 | init_pair(COLOR_CYAN, COLOR_CYAN, bg); | |
72 | init_pair(COLOR_WHITE, COLOR_WHITE, bg); | |
73 | init_pair(COLOR_MAGENTA, COLOR_MAGENTA, bg); | |
74 | init_pair(COLOR_BLUE, COLOR_BLUE, bg); | |
75 | init_pair(COLOR_YELLOW, COLOR_YELLOW, bg); | |
800a900c JF |
76 | } |
77 | ||
78 | static void | |
79 | init(void) | |
80 | { | |
05f1685b | 81 | int x, y; |
800a900c | 82 | |
05f1685b JF |
83 | signal(SIGINT, quit); |
84 | ||
85 | initscr(); /* initialize the curses library */ | |
86 | nonl(); /* tell curses not to do NL->CR/NL on output */ | |
87 | cbreak(); /* take input chars one at a time, no wait for \n */ | |
88 | noecho(); /* don't echo input */ | |
e3e7b9fc | 89 | leaveok(stdscr, TRUE); |
800a900c JF |
90 | |
91 | if (has_colors()) | |
92 | init_colors(); | |
05f1685b JF |
93 | |
94 | getmaxyx(stdscr, y, x); | |
95 | ||
e3e7b9fc JF |
96 | #if 0 |
97 | titlewin = newwin(1, 0, y - 2, 0); | |
05f1685b JF |
98 | |
99 | wattrset(titlewin, COLOR_PAIR(COLOR_GREEN)); | |
100 | waddch(titlewin, ACS_VLINE); | |
101 | wprintw(titlewin, "%s", "cg-view"); | |
102 | waddch(titlewin, ACS_LTEE); | |
103 | whline(titlewin, ACS_HLINE, x); | |
104 | wrefresh(titlewin); | |
e3e7b9fc | 105 | #endif |
05f1685b JF |
106 | statuswin = newwin(1, 0, y - 1, 0); |
107 | ||
108 | wattrset(statuswin, COLOR_PAIR(COLOR_GREEN)); | |
e3e7b9fc | 109 | put_status(CGIT_HELP); |
05f1685b | 110 | |
e3e7b9fc | 111 | mainwin = newwin(y - 1, 0, 0, 0); |
05f1685b JF |
112 | scrollok(mainwin, TRUE); |
113 | keypad(mainwin, TRUE); /* enable keyboard mapping */ | |
114 | } | |
115 | ||
116 | /* | |
117 | * Pipe filters | |
118 | */ | |
119 | ||
120 | #define DIFF_CMD \ | |
e3e7b9fc | 121 | "git-rev-list HEAD^..HEAD | " \ |
05f1685b JF |
122 | "git-diff-tree --stdin --pretty -r --cc --always" |
123 | ||
124 | ||
125 | #define LOG_CMD \ | |
126 | "git-rev-list $(git-rev-parse --since=1.month) HEAD | " \ | |
67392cc4 | 127 | "git-diff-tree --stdin --pretty -r --root" |
05f1685b JF |
128 | |
129 | static void | |
130 | log_filter(char *line, int lineno) | |
131 | { | |
132 | static int log_filter_skip; | |
133 | ||
134 | if (!line) { | |
135 | wattrset(mainwin, A_NORMAL); | |
136 | log_filter_skip = 0; | |
137 | return; | |
138 | } | |
139 | ||
140 | if (!strncmp("commit ", line, 7)) { | |
141 | attrset(COLOR_PAIR(COLOR_GREEN)); | |
142 | ||
143 | } else if (!strncmp("Author: ", line, 8)) { | |
144 | wattrset(mainwin, COLOR_PAIR(COLOR_CYAN)); | |
145 | ||
146 | } else if (!strncmp("Date: ", line, 6)) { | |
147 | wattrset(mainwin, COLOR_PAIR(COLOR_YELLOW)); | |
148 | ||
149 | } else if (!strncmp("diff --git ", line, 11)) { | |
150 | wattrset(mainwin, COLOR_PAIR(COLOR_YELLOW)); | |
151 | ||
152 | } else if (!strncmp("diff-tree ", line, 10)) { | |
153 | wattrset(mainwin, COLOR_PAIR(COLOR_BLUE)); | |
154 | ||
155 | } else if (!strncmp("index ", line, 6)) { | |
156 | wattrset(mainwin, COLOR_PAIR(COLOR_BLUE)); | |
157 | ||
158 | } else if (line[0] == '-') { | |
159 | wattrset(mainwin, COLOR_PAIR(COLOR_RED)); | |
160 | ||
161 | } else if (line[0] == '+') { | |
162 | wattrset(mainwin, COLOR_PAIR(COLOR_GREEN)); | |
163 | ||
164 | } else if (line[0] == '@') { | |
165 | wattrset(mainwin, COLOR_PAIR(COLOR_MAGENTA)); | |
166 | ||
167 | } else if (line[0] == ':') { | |
67392cc4 | 168 | pipe_lineno--; |
05f1685b JF |
169 | log_filter_skip = 1; |
170 | return; | |
171 | ||
172 | } else if (log_filter_skip) { | |
67392cc4 | 173 | pipe_lineno--; |
05f1685b JF |
174 | log_filter_skip = 0; |
175 | return; | |
176 | ||
177 | } else { | |
178 | wattrset(mainwin, A_NORMAL); | |
179 | } | |
180 | ||
181 | mvwaddstr(mainwin, lineno, 0, line); | |
182 | } | |
183 | ||
184 | static FILE * | |
185 | open_pipe(char *cmd, pipe_filter_T filter) | |
186 | { | |
187 | pipe = popen(cmd, "r"); | |
e3e7b9fc | 188 | pipe_lineno = 0; |
05f1685b | 189 | pipe_filter = filter; |
e3e7b9fc JF |
190 | wclear(mainwin); |
191 | wmove(mainwin, 0, 0); | |
192 | put_status("Loading..."); | |
05f1685b JF |
193 | return pipe; |
194 | } | |
195 | ||
196 | static void | |
197 | read_pipe(int lines) | |
198 | { | |
199 | char buffer[BUFSIZ]; | |
200 | char *line; | |
e3e7b9fc | 201 | int x, y; |
05f1685b JF |
202 | |
203 | while ((line = fgets(buffer, sizeof(buffer), pipe))) { | |
e3e7b9fc JF |
204 | int linelen; |
205 | ||
05f1685b JF |
206 | if (!--lines) |
207 | break; | |
e3e7b9fc JF |
208 | |
209 | linelen = strlen(line); | |
210 | if (linelen) | |
211 | line[linelen - 1] = 0; | |
212 | ||
213 | pipe_filter(line, pipe_lineno++); | |
05f1685b JF |
214 | } |
215 | ||
216 | if (feof(pipe) || ferror(pipe)) { | |
217 | pipe_filter(NULL, pipe_lineno - 1); | |
218 | pclose(pipe); | |
219 | pipe = NULL; | |
220 | pipe_filter = NULL; | |
e3e7b9fc | 221 | put_status("%s (lines %d)", CGIT_HELP, pipe_lineno - 1); |
05f1685b | 222 | } |
800a900c JF |
223 | } |
224 | ||
225 | /* | |
226 | * Main | |
227 | */ | |
228 | ||
229 | int | |
230 | main(int argc, char *argv[]) | |
231 | { | |
800a900c JF |
232 | init(); |
233 | ||
e3e7b9fc | 234 | //pipe = open_pipe(LOG_CMD, log_filter); |
800a900c JF |
235 | |
236 | for (;;) { | |
05f1685b JF |
237 | int c; |
238 | ||
239 | if (pipe) read_pipe(20); | |
240 | if (pipe) nodelay(mainwin, TRUE); | |
241 | ||
242 | c = wgetch(mainwin); /* refresh, accept single keystroke of input */ | |
243 | ||
244 | if (pipe) nodelay(mainwin, FALSE); | |
245 | ||
e3e7b9fc | 246 | /* No input from wgetch() with nodelay() enabled. */ |
05f1685b JF |
247 | if (c == ERR) |
248 | continue; | |
800a900c JF |
249 | |
250 | /* Process the command keystroke */ | |
251 | switch (c) { | |
05f1685b | 252 | case KEY_ESC: |
800a900c JF |
253 | case 'q': |
254 | quit(0); | |
255 | return 0; | |
256 | ||
05f1685b JF |
257 | case KEY_DOWN: |
258 | case 'j': | |
259 | wscrl(mainwin, 1); | |
260 | break; | |
261 | ||
262 | case KEY_UP: | |
263 | case 'k': | |
264 | wscrl(mainwin, -1); | |
265 | break; | |
266 | ||
e3e7b9fc JF |
267 | case 'c': |
268 | wclear(mainwin); | |
269 | break; | |
270 | ||
05f1685b JF |
271 | case 'd': |
272 | pipe = open_pipe(DIFF_CMD, log_filter); | |
05f1685b JF |
273 | break; |
274 | ||
275 | case 'l': | |
276 | pipe = open_pipe(LOG_CMD, log_filter); | |
05f1685b JF |
277 | break; |
278 | ||
800a900c | 279 | case 's': |
e3e7b9fc | 280 | mvwaddstr(statuswin, 0, 0, "Shelling out..."); |
800a900c JF |
281 | def_prog_mode(); /* save current tty modes */ |
282 | endwin(); /* restore original tty modes */ | |
283 | system("sh"); /* run shell */ | |
05f1685b | 284 | |
e3e7b9fc | 285 | werase(statuswin); |
05f1685b | 286 | mvwaddstr(statuswin, 0, 0, CGIT_HELP); |
800a900c | 287 | reset_prog_mode(); |
800a900c | 288 | break; |
800a900c JF |
289 | } |
290 | ||
05f1685b JF |
291 | redrawwin(mainwin); |
292 | wrefresh(mainwin); | |
800a900c JF |
293 | } |
294 | ||
295 | quit(0); | |
296 | } |