#define string_ncopy(dst, src, srclen) \
string_ncopy_do(dst, sizeof(dst), src, srclen)
+#define string_copy_rev(dst, src) \
+ string_ncopy_do(dst, SIZEOF_REV, src, SIZEOF_REV - 1)
+
static char *
chomp_string(char *name)
{
static char buf[BUFSIZ];
static char key_char[] = "'X'";
size_t pos = 0;
- char *sep = " ";
+ char *sep = "";
int i;
buf[pos] = 0;
struct view_ops {
/* What type of content being displayed. Used in the title bar. */
const char *type;
- /* Draw one line; @lineno must be < view->height. */
- bool (*draw)(struct view *view, struct line *line, unsigned int lineno, bool selected);
+ /* Open and reads in all view content. */
+ bool (*open)(struct view *view);
/* Read one line; updates view->line. */
bool (*read)(struct view *view, char *data);
+ /* Draw one line; @lineno must be < view->height. */
+ bool (*draw)(struct view *view, struct line *line, unsigned int lineno, bool selected);
/* Depending on view, change display based on current line. */
bool (*enter)(struct view *view, struct line *line);
/* Search for regex in a line. */
static struct view_ops main_ops;
static struct view_ops tree_ops;
static struct view_ops blob_ops;
+static struct view_ops help_ops;
#define VIEW_STR(name, cmd, env, ref, ops, map) \
{ name, cmd, #env, ref, ops, map}
VIEW_(LOG, "log", &pager_ops, ref_head),
VIEW_(TREE, "tree", &tree_ops, ref_commit),
VIEW_(BLOB, "blob", &blob_ops, ref_blob),
- VIEW_(HELP, "help", &pager_ops, "static"),
- VIEW_(PAGER, "pager", &pager_ops, "static"),
+ VIEW_(HELP, "help", &help_ops, ""),
+ VIEW_(PAGER, "pager", &pager_ops, ""),
};
#define VIEW(req) (&views[(req) - REQ_OFFSET - 1])
if (opt_cmd[0]) {
string_copy(view->cmd, opt_cmd);
opt_cmd[0] = 0;
- /* When running random commands, the view ref could have become
- * invalid so clear it. */
- view->ref[0] = 0;
+ /* When running random commands, initially show the
+ * command in the title. However, it maybe later be
+ * overwritten if a commit line is selected. */
+ string_copy(view->ref, view->cmd);
} else if (view == VIEW(REQ_VIEW_TREE)) {
const char *format = view->cmd_env ? view->cmd_env : view->cmd_fmt;
if (!string_format(view->cmd, format, id, id, id, id, id))
return FALSE;
+
+ /* Put the current ref_* value to the view title ref
+ * member. This is needed by the blob view. Most other
+ * views sets it automatically after loading because the
+ * first line is a commit line. */
+ string_copy(view->ref, id);
}
/* Special case for the pager view. */
view->offset = 0;
view->lines = 0;
view->lineno = 0;
- string_copy(view->vid, id);
+ string_copy_rev(view->vid, id);
if (view->line) {
int i;
}
static struct line *
-add_line_text(struct view *view, char *data, enum line_type type)
+add_line_data(struct view *view, void *data, enum line_type type)
{
- struct line *line = &view->line[view->lines];
-
- if (!data)
- return NULL;
-
- line->data = strdup(data);
- if (!line->data)
- return NULL;
+ struct line *line = &view->line[view->lines++];
+ memset(line, 0, sizeof(*line));
line->type = type;
- view->lines++;
+ line->data = data;
return line;
}
-
-/*
- * View opening
- */
-
-static void open_help_view(struct view *view)
+static struct line *
+add_line_text(struct view *view, char *data, enum line_type type)
{
- char buf[BUFSIZ];
- int lines = ARRAY_SIZE(req_info) + 2;
- int i;
+ if (data)
+ data = strdup(data);
- if (view->lines > 0)
- return;
-
- for (i = 0; i < ARRAY_SIZE(req_info); i++)
- if (!req_info[i].request)
- lines++;
-
- view->line = calloc(lines, sizeof(*view->line));
- if (!view->line) {
- report("Allocation failure");
- return;
- }
-
- add_line_text(view, "Quick reference for tig keybindings:", LINE_DEFAULT);
-
- for (i = 0; i < ARRAY_SIZE(req_info); i++) {
- char *key;
-
- if (!req_info[i].request) {
- add_line_text(view, "", LINE_DEFAULT);
- add_line_text(view, req_info[i].help, LINE_DEFAULT);
- continue;
- }
+ return data ? add_line_data(view, data, type) : NULL;
+}
- key = get_key(req_info[i].request);
- if (!string_format(buf, "%-25s %s", key, req_info[i].help))
- continue;
- add_line_text(view, buf, LINE_DEFAULT);
- }
-}
+/*
+ * View opening
+ */
enum open_flags {
OPEN_DEFAULT = 0, /* Use default view switching. */
return;
}
- if (view == VIEW(REQ_VIEW_HELP)) {
- open_help_view(view);
+ if (view->ops->open) {
+ if (!view->ops->open(view)) {
+ report("Failed to load %s view", view->name);
+ return;
+ }
} else if ((reload || strcmp(view->vid, view->id)) &&
!begin_update(view)) {
case REQ_VIEW_BLOB:
if (!ref_blob[0]) {
- report("No file chosen, press 't' to open tree view");
+ report("No file chosen, press %s to open tree view",
+ get_key(REQ_VIEW_TREE));
break;
}
- /* Fall-through */
+ open_view(view, request, OPEN_DEFAULT);
+ break;
+
+ case REQ_VIEW_PAGER:
+ if (!VIEW(REQ_VIEW_PAGER)->lines) {
+ report("No pager content, press %s to run command from prompt",
+ get_key(REQ_PROMPT));
+ break;
+ }
+ open_view(view, request, OPEN_DEFAULT);
+ break;
+
case REQ_VIEW_MAIN:
case REQ_VIEW_DIFF:
case REQ_VIEW_LOG:
case REQ_VIEW_TREE:
case REQ_VIEW_HELP:
- case REQ_VIEW_PAGER:
open_view(view, request, OPEN_DEFAULT);
break;
pager_select(struct view *view, struct line *line)
{
if (line->type == LINE_COMMIT) {
- char *text = line->data;
+ char *text = line->data + STRING_SIZE("commit ");
- string_copy(view->ref, text + STRING_SIZE("commit "));
- string_copy(ref_commit, view->ref);
+ if (view != VIEW(REQ_VIEW_PAGER))
+ string_copy_rev(view->ref, text);
+ string_copy_rev(ref_commit, text);
}
}
static struct view_ops pager_ops = {
"line",
- pager_draw,
+ NULL,
pager_read,
+ pager_draw,
+ pager_enter,
+ pager_grep,
+ pager_select,
+};
+
+
+/*
+ * Help backend
+ */
+
+static bool
+help_open(struct view *view)
+{
+ char buf[BUFSIZ];
+ int lines = ARRAY_SIZE(req_info) + 2;
+ int i;
+
+ if (view->lines > 0)
+ return TRUE;
+
+ for (i = 0; i < ARRAY_SIZE(req_info); i++)
+ if (!req_info[i].request)
+ lines++;
+
+ view->line = calloc(lines, sizeof(*view->line));
+ if (!view->line)
+ return FALSE;
+
+ add_line_text(view, "Quick reference for tig keybindings:", LINE_DEFAULT);
+
+ for (i = 0; i < ARRAY_SIZE(req_info); i++) {
+ char *key;
+
+ if (!req_info[i].request) {
+ add_line_text(view, "", LINE_DEFAULT);
+ add_line_text(view, req_info[i].help, LINE_DEFAULT);
+ continue;
+ }
+
+ key = get_key(req_info[i].request);
+ if (!string_format(buf, " %-25s %s", key, req_info[i].help))
+ continue;
+
+ add_line_text(view, buf, LINE_DEFAULT);
+ }
+
+ return TRUE;
+}
+
+static struct view_ops help_ops = {
+ "line",
+ help_open,
+ NULL,
+ pager_draw,
pager_enter,
pager_grep,
pager_select,
static void
tree_select(struct view *view, struct line *line)
{
- char *text = line->data;
-
- text += STRING_SIZE("100644 blob ");
+ char *text = line->data + STRING_SIZE("100644 blob ");
if (line->type == LINE_TREE_FILE) {
- string_ncopy(ref_blob, text, 40);
- /* Also update the blob view's ref, since all there must always
- * be in sync. */
- string_copy(VIEW(REQ_VIEW_BLOB)->ref, ref_blob);
+ string_copy_rev(ref_blob, text);
} else if (line->type != LINE_TREE_DIR) {
return;
}
- string_ncopy(view->ref, text, 40);
+ string_copy_rev(view->ref, text);
}
static struct view_ops tree_ops = {
"file",
- pager_draw,
+ NULL,
tree_read,
+ pager_draw,
tree_enter,
pager_grep,
tree_select,
static struct view_ops blob_ops = {
"line",
- pager_draw,
+ NULL,
blob_read,
+ pager_draw,
pager_enter,
pager_grep,
pager_select,
line += STRING_SIZE("commit ");
- view->line[view->lines++].data = commit;
- string_copy(commit->id, line);
+ string_copy_rev(commit->id, line);
commit->refs = get_refs(commit->id);
graph->commit = commit;
+ add_line_data(view, commit, LINE_MAIN_COMMIT);
break;
case LINE_PARENT:
{
struct commit *commit = line->data;
- string_copy(view->ref, commit->id);
- string_copy(ref_commit, view->ref);
+ string_copy_rev(view->ref, commit->id);
+ string_copy_rev(ref_commit, view->ref);
}
static struct view_ops main_ops = {
"commit",
- main_draw,
+ NULL,
main_read,
+ main_draw,
main_enter,
main_grep,
main_select,
ref->name[namelen] = 0;
ref->tag = tag;
ref->remote = remote;
- string_copy(ref->id, id);
+ string_copy_rev(ref->id, id);
return OK;
}