Stop starting pager recursively
[git/git.git] / column.c
CommitLineData
7e29b825
NTND
1#include "cache.h"
2#include "column.h"
3#include "string-list.h"
4#include "parse-options.h"
5
6/* Display without layout when not enabled */
7static void display_plain(const struct string_list *list,
8 const char *indent, const char *nl)
9{
10 int i;
11
12 for (i = 0; i < list->nr; i++)
13 printf("%s%s%s", indent, list->items[i].string, nl);
14}
15
16void print_columns(const struct string_list *list, unsigned int colopts,
17 const struct column_options *opts)
18{
19 struct column_options nopts;
20
21 if (!list->nr)
22 return;
23 assert((colopts & COL_ENABLE_MASK) != COL_AUTO);
24
25 memset(&nopts, 0, sizeof(nopts));
26 nopts.indent = opts && opts->indent ? opts->indent : "";
27 nopts.nl = opts && opts->nl ? opts->nl : "\n";
28 nopts.padding = opts ? opts->padding : 1;
29 nopts.width = opts && opts->width ? opts->width : term_columns() - 1;
30 if (!column_active(colopts)) {
31 display_plain(list, "", "\n");
32 return;
33 }
34 switch (COL_LAYOUT(colopts)) {
35 case COL_PLAIN:
36 display_plain(list, nopts.indent, nopts.nl);
37 break;
38 default:
39 die("BUG: invalid layout mode %d", COL_LAYOUT(colopts));
40 }
41}
42
43int finalize_colopts(unsigned int *colopts, int stdout_is_tty)
44{
45 if ((*colopts & COL_ENABLE_MASK) == COL_AUTO) {
46 if (stdout_is_tty < 0)
47 stdout_is_tty = isatty(1);
48 *colopts &= ~COL_ENABLE_MASK;
49 if (stdout_is_tty)
50 *colopts |= COL_ENABLED;
51 }
52 return 0;
53}
54
55struct colopt {
56 const char *name;
57 unsigned int value;
58 unsigned int mask;
59};
60
61#define LAYOUT_SET 1
62#define ENABLE_SET 2
63
64static int parse_option(const char *arg, int len, unsigned int *colopts,
65 int *group_set)
66{
67 struct colopt opts[] = {
68 { "always", COL_ENABLED, COL_ENABLE_MASK },
69 { "never", COL_DISABLED, COL_ENABLE_MASK },
70 { "auto", COL_AUTO, COL_ENABLE_MASK },
71 { "plain", COL_PLAIN, COL_LAYOUT_MASK },
72 };
73 int i;
74
75 for (i = 0; i < ARRAY_SIZE(opts); i++) {
76 int arg_len = len, name_len;
77 const char *arg_str = arg;
78
79 name_len = strlen(opts[i].name);
80 if (arg_len != name_len ||
81 strncmp(arg_str, opts[i].name, name_len))
82 continue;
83
84 switch (opts[i].mask) {
85 case COL_ENABLE_MASK:
86 *group_set |= ENABLE_SET;
87 break;
88 case COL_LAYOUT_MASK:
89 *group_set |= LAYOUT_SET;
90 break;
91 }
92
93 if (opts[i].mask)
94 *colopts = (*colopts & ~opts[i].mask) | opts[i].value;
95 return 0;
96 }
97
98 return error("unsupported option '%s'", arg);
99}
100
101static int parse_config(unsigned int *colopts, const char *value)
102{
103 const char *sep = " ,";
104 int group_set = 0;
105
106 while (*value) {
107 int len = strcspn(value, sep);
108 if (len) {
109 if (parse_option(value, len, colopts, &group_set))
110 return -1;
111
112 value += len;
113 }
114 value += strspn(value, sep);
115 }
116 /*
117 * Setting layout implies "always" if neither always, never
118 * nor auto is specified.
119 *
120 * Current value in COL_ENABLE_MASK is disregarded. This means if
121 * you set column.ui = auto and pass --column=row, then "auto"
122 * will become "always".
123 */
124 if ((group_set & LAYOUT_SET) && !(group_set & ENABLE_SET))
125 *colopts = (*colopts & ~COL_ENABLE_MASK) | COL_ENABLED;
126 return 0;
127}
128
129static int column_config(const char *var, const char *value,
130 const char *key, unsigned int *colopts)
131{
132 if (!value)
133 return config_error_nonbool(var);
134 if (parse_config(colopts, value))
135 return error("invalid column.%s mode %s", key, value);
136 return 0;
137}
138
139int git_column_config(const char *var, const char *value,
140 const char *command, unsigned int *colopts)
141{
142 const char *it = skip_prefix(var, "column.");
143 if (!it)
144 return 0;
145
146 if (!strcmp(it, "ui"))
147 return column_config(var, value, "ui", colopts);
148
149 if (command && !strcmp(it, command))
150 return column_config(var, value, it, colopts);
151
152 return 0;
153}
154
155int parseopt_column_callback(const struct option *opt,
156 const char *arg, int unset)
157{
158 unsigned int *colopts = opt->value;
159 *colopts |= COL_PARSEOPT;
160 *colopts &= ~COL_ENABLE_MASK;
161 if (unset) /* --no-column == never */
162 return 0;
163 /* --column == always unless "arg" states otherwise */
164 *colopts |= COL_ENABLED;
165 if (arg)
166 return parse_config(colopts, arg);
167
168 return 0;
169}