Make view columns configurable
[tig.git] / src / grep.c
blobf73cf5f865b4adc165c95b185c9e362042043660
1 /* Copyright (c) 2006-2014 Jonas Fonseca <jonas.fonseca@gmail.com>
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 of
6 * the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include "tig/refdb.h"
15 #include "tig/options.h"
16 #include "tig/parse.h"
17 #include "tig/repo.h"
18 #include "tig/display.h"
19 #include "tig/prompt.h"
20 #include "tig/draw.h"
21 #include "tig/blob.h"
22 #include "tig/grep.h"
24 struct grep_line {
25 const char *file;
26 unsigned long lineno;
27 char text[1];
30 struct grep_state {
31 const char *last_file;
32 bool no_file_group;
35 #define grep_view_lineno(grep) ((grep)->lineno > 0 ? (grep)->lineno - 1 : 0)
37 static struct grep_line *
38 grep_get_line(const struct line *line)
40 static struct grep_line grep_line;
42 if (line->type == LINE_DEFAULT)
43 return line->data;
45 grep_line.file = line->type == LINE_DELIMITER ? "" : get_path(line->data);
46 return &grep_line;
49 static bool
50 grep_get_column_data(struct view *view, const struct line *line, struct view_column_data *column_data)
52 struct grep_line *grep = grep_get_line(line);
54 if (line->type == LINE_DELIMITER)
55 return FALSE;
57 if (*grep->file && !grep->lineno) {
58 static struct view_column file_name_column;
60 file_name_column.type = VIEW_COLUMN_FILE_NAME;
61 file_name_column.opt.file_name.show = FILENAME_ALWAYS;
63 column_data->section = &file_name_column;
66 column_data->line_number = &grep->lineno;
67 column_data->file_name = grep->file;
68 column_data->text = grep->text;
69 return TRUE;
72 static void
73 grep_select(struct view *view, struct line *line)
75 struct grep_line *grep = grep_get_line(line);
77 if (!*grep->file)
78 return;
79 view->env->ref[0] = 0;
80 string_ncopy(view->env->file, grep->file, strlen(grep->file));
81 string_ncopy(view->ref, grep->file, strlen(grep->file));
84 static const char *grep_args[] = {
85 "git", "grep", "--no-color", "-n", "-z", "--full-name", NULL
88 static const char **grep_argv;
90 static bool
91 grep_prompt(void)
93 const char *argv[SIZEOF_ARG];
94 int argc = 0;
95 char *grep = read_prompt("grep: ");
97 if (!grep || !argv_from_string_no_quotes(argv, &argc, grep))
98 return FALSE;
99 if (grep_argv)
100 argv_free(grep_argv);
101 return argv_append_array(&grep_argv, argv);
104 void
105 open_grep_view(struct view *prev)
107 struct view *view = &grep_view;
108 bool in_grep_view = prev == view;
110 if ((!prev && is_initial_view(view)) || (view->lines && !in_grep_view)) {
111 open_view(prev, view, OPEN_DEFAULT);
112 } else {
113 if (grep_prompt())
114 open_view(prev, view, OPEN_RELOAD);
118 static bool
119 grep_open(struct view *view, enum open_flags flags)
121 struct grep_state *state = view->private;
122 const char **argv = NULL;
124 if (is_initial_view(view)) {
125 grep_argv = opt_cmdline_argv;
126 opt_cmdline_argv = NULL;
129 if (!argv_append_array(&argv, grep_args) ||
130 !argv_append_array(&argv, grep_argv))
131 return FALSE;
134 struct view_column *column = get_view_column(view, VIEW_COLUMN_FILE_NAME);
136 state->no_file_group = !column || column->opt.file_name.show != FILENAME_NO;
139 return begin_update(view, NULL, argv, flags);
142 static enum request
143 grep_request(struct view *view, enum request request, struct line *line)
145 struct grep_state *state = view->private;
146 struct grep_line *grep = grep_get_line(line);
147 struct view *file_view = &blob_view;
149 switch (request) {
150 case REQ_REFRESH:
151 refresh_view(view);
152 return REQ_NONE;
154 case REQ_ENTER:
155 if (!*grep->file)
156 return REQ_NONE;
157 if (file_view->parent == view && file_view->prev == view &&
158 state->last_file == grep->file && view_is_displayed(file_view)) {
159 if (grep_view_lineno(grep))
160 select_view_line(file_view, grep_view_lineno(grep));
162 } else {
163 const char *file_argv[] = { repo.cdup, grep->file, NULL };
165 clear_position(&file_view->pos);
166 view->env->lineno = grep_view_lineno(grep);
167 view->env->blob[0] = 0;
168 open_argv(view, file_view, file_argv, repo.cdup, OPEN_SPLIT | OPEN_RELOAD);
170 state->last_file = grep->file;
171 return REQ_NONE;
173 case REQ_EDIT:
174 if (!*grep->file)
175 return request;
176 open_editor(grep->file, grep->lineno);
177 return REQ_NONE;
179 case REQ_VIEW_BLAME:
180 view->env->ref[0] = 0;
181 view->env->lineno = grep_view_lineno(grep);
182 return request;
184 default:
185 return request;
189 static bool
190 grep_read(struct view *view, char *data)
192 struct grep_state *state = view->private;
193 struct grep_line *grep;
194 char *lineno, *text;
195 struct line *line;
196 const char *file;
197 size_t textlen;
199 if (!data) {
200 state->last_file = NULL;
201 return TRUE;
204 if (!strcmp(data, "--"))
205 return add_line_nodata(view, LINE_DELIMITER) != NULL;
207 lineno = io_memchr(&view->io, data, 0);
208 text = io_memchr(&view->io, lineno, 0);
210 if (!lineno || !text)
211 return FALSE;
213 textlen = strlen(text);
215 file = get_path(data);
216 if (!file)
217 return FALSE;
219 if (!state->no_file_group && file != state->last_file &&
220 !add_line_text(view, file, LINE_FILE))
221 return FALSE;
223 line = add_line_alloc(view, &grep, LINE_DEFAULT, textlen, FALSE);
224 if (!line)
225 return FALSE;
227 grep->file = file;
228 grep->lineno = atoi(lineno);
229 strncpy(grep->text, text, textlen);
230 grep->text[textlen] = 0;
231 view_column_info_update(view, line);
233 state->last_file = file;
235 return TRUE;
238 static struct view_ops grep_ops = {
239 "line",
241 VIEW_REFRESH | VIEW_GREP_LIKE,
242 sizeof(struct grep_state),
243 grep_open,
244 grep_read,
245 view_column_draw,
246 grep_request,
247 view_column_grep,
248 grep_select,
249 NULL,
250 view_column_bit(FILE_NAME) | view_column_bit(LINE_NUMBER) |
251 view_column_bit(TEXT),
252 grep_get_column_data,
255 DEFINE_VIEW(grep);
257 /* vim: set ts=8 sw=8 noexpandtab: */