chiark / gitweb /
Misc cleanups and improvements
[tig] / cgit.c
CommitLineData
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
21WINDOW *mainwin;
22WINDOW *statuswin;
23
24typedef void (*pipe_filter_T)(char *, int);
25
26FILE *pipe;
27long pipe_lineno;
28pipe_filter_T pipe_filter;
29
e3e7b9fc
JF
30
31static void
32put_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
48static void
49quit(int sig)
800a900c
JF
50{
51 endwin();
52
53 /* do your non-curses wrapup here */
54
55 exit(0);
56}
57
58static void
59init_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
78static void
79init(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
129static void
130log_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
184static FILE *
185open_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
196static void
197read_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
229int
230main(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}