Add uninstall target
[tig.git] / src / pager.c
blobc5a84c9f93e57657dccf19b679fa3b0a23c6780b
1 /* Copyright (c) 2006-2015 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/tig.h"
15 #include "tig/options.h"
16 #include "tig/request.h"
17 #include "tig/line.h"
18 #include "tig/keys.h"
19 #include "tig/display.h"
20 #include "tig/view.h"
21 #include "tig/draw.h"
22 #include "tig/diff.h"
25 * Pager backend
28 bool
29 pager_get_column_data(struct view *view, const struct line *line, struct view_column_data *column_data)
31 column_data->text = line->data;
32 return true;
35 static void
36 add_pager_refs(struct view *view, const char *commit_id)
38 char buf[SIZEOF_STR];
39 const struct ref *list;
40 size_t bufpos = 0;
41 const char *sep = "Refs: ";
43 list = get_ref_list(commit_id);
44 if (!list) {
45 if (view_has_flags(view, VIEW_ADD_DESCRIBE_REF) && refs_contain_tag())
46 add_line_text(view, sep, LINE_PP_REFS);
47 return;
50 for (; list; list = list->next) {
51 const struct ref *ref = list;
52 const struct ref_format *fmt = get_ref_format(opt_reference_format, ref);
54 if (!string_format_from(buf, &bufpos, "%s%s%s%s", sep,
55 fmt->start, ref->name, fmt->end))
56 return;
57 sep = ", ";
60 if (bufpos == 0)
61 return;
63 add_line_text(view, buf, LINE_PP_REFS);
66 static struct line *
67 pager_wrap_line(struct view *view, const char *data, enum line_type type)
69 size_t first_line = 0;
70 bool has_first_line = false;
71 size_t datalen = strlen(data);
72 size_t lineno = 0;
74 while (datalen > 0 || !has_first_line) {
75 bool wrapped = !!first_line;
76 size_t linelen = string_expanded_length(data, datalen, opt_tab_size, view->width - !!wrapped);
77 struct line *line;
78 char *text;
80 line = add_line(view, NULL, type, linelen + 1, wrapped);
81 if (!line)
82 break;
83 if (!has_first_line) {
84 first_line = view->lines - 1;
85 has_first_line = true;
88 if (!wrapped)
89 lineno = line->lineno;
91 line->wrapped = wrapped;
92 line->lineno = lineno;
93 text = line->data;
94 if (linelen)
95 strncpy(text, data, linelen);
96 text[linelen] = 0;
98 datalen -= linelen;
99 data += linelen;
102 return has_first_line ? &view->line[first_line] : NULL;
105 bool
106 pager_common_read(struct view *view, const char *data, enum line_type type, struct line **line_ptr)
108 struct line *line;
110 if (!data)
111 return true;
113 if (opt_wrap_lines) {
114 line = pager_wrap_line(view, data, type);
115 } else {
116 line = add_line_text(view, data, type);
119 if (!line)
120 return false;
122 if (line_ptr)
123 *line_ptr = line;
125 if (line->type == LINE_COMMIT && view_has_flags(view, VIEW_ADD_PAGER_REFS))
126 add_pager_refs(view, data + STRING_SIZE("commit "));
128 return true;
131 bool
132 pager_read(struct view *view, struct buffer *buf)
134 if (!buf)
135 return true;
137 return pager_common_read(view, buf->data, get_line_type(buf->data), NULL);
140 enum request
141 pager_request(struct view *view, enum request request, struct line *line)
143 int split = 0;
145 if (request != REQ_ENTER)
146 return request;
148 if (line->type == LINE_COMMIT && view_has_flags(view, VIEW_OPEN_DIFF)) {
149 open_diff_view(view, OPEN_SPLIT);
150 split = 1;
153 /* Always scroll the view even if it was split. That way
154 * you can use Enter to scroll through the log view and
155 * split open each commit diff. */
156 scroll_view(view, REQ_SCROLL_LINE_DOWN);
158 /* FIXME: A minor workaround. Scrolling the view will call report_clear()
159 * but if we are scrolling a non-current view this won't properly
160 * update the view title. */
161 if (split)
162 update_view_title(view);
164 return REQ_NONE;
167 void
168 pager_select(struct view *view, struct line *line)
170 if (line->type == LINE_COMMIT) {
171 string_copy_rev_from_commit_line(view->env->commit, line->data);
172 if (!view_has_flags(view, VIEW_NO_REF))
173 string_copy_rev(view->ref, view->env->commit);
177 static bool
178 pager_open(struct view *view, enum open_flags flags)
180 if (!open_from_stdin(flags) && !view->lines && !(flags & OPEN_PREPARED)) {
181 report("No pager content, press %s to run command from prompt",
182 get_view_key(view, REQ_PROMPT));
183 return false;
186 return begin_update(view, NULL, NULL, flags);
189 static struct view_ops pager_ops = {
190 "line",
192 VIEW_OPEN_DIFF | VIEW_NO_REF | VIEW_NO_GIT_DIR,
194 pager_open,
195 pager_read,
196 view_column_draw,
197 pager_request,
198 view_column_grep,
199 pager_select,
200 NULL,
201 view_column_bit(LINE_NUMBER) | view_column_bit(TEXT),
202 pager_get_column_data,
205 DEFINE_VIEW(pager);
207 /* vim: set ts=8 sw=8 noexpandtab: */