From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH 3/9] column: add functions to parse column settings
Date: Sun, 20 Mar 2011 19:57:47 +0700 [thread overview]
Message-ID: <1300625873-18435-4-git-send-email-pclouds@gmail.com> (raw)
In-Reply-To: <1300625873-18435-1-git-send-email-pclouds@gmail.com>
A column option string consists of many token separated by either
space of commas. A token belongs to one of three groups:
- enabling: always, never and auto
- layout mode: to be implemented
- other tuning, which could be negated be prefix 'no'
A command line option without argument (e.g. --column) will enable
column output and reuse existing settings (layout mode and options..).
--no-column disables columnar output.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
.gitignore | 1 +
Makefile | 1 +
column.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++
column.h | 4 ++
parse-options.h | 2 +
t/t9002-column.sh | 27 +++++++++++
test-column.c | 39 ++++++++++++++++
7 files changed, 199 insertions(+), 0 deletions(-)
create mode 100755 t/t9002-column.sh
create mode 100644 test-column.c
diff --git a/.gitignore b/.gitignore
index 3dd6ef7..a1a1202 100644
--- a/.gitignore
+++ b/.gitignore
@@ -162,6 +162,7 @@
/gitweb/gitweb.cgi
/gitweb/static/gitweb.min.*
/test-chmtime
+/test-column
/test-ctype
/test-date
/test-delta
diff --git a/Makefile b/Makefile
index 94e1cf0..ba9944b 100644
--- a/Makefile
+++ b/Makefile
@@ -417,6 +417,7 @@ PROGRAM_OBJS += http-backend.o
PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
TEST_PROGRAMS_NEED_X += test-chmtime
+TEST_PROGRAMS_NEED_X += test-column
TEST_PROGRAMS_NEED_X += test-ctype
TEST_PROGRAMS_NEED_X += test-date
TEST_PROGRAMS_NEED_X += test-delta
diff --git a/column.c b/column.c
index 8422c89..b32b9f9 100644
--- a/column.c
+++ b/column.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "column.h"
#include "string-list.h"
+#include "parse-options.h"
#define MODE(mode) ((mode) & COL_MODE)
@@ -35,3 +36,127 @@ void display_columns(const struct string_list *list, int mode,
}
die("BUG: invalid mode %d", MODE(mode));
}
+
+struct colopt {
+ enum {
+ ENABLE,
+ MODE,
+ OPTION
+ } type;
+ const char *name;
+ int value;
+};
+
+/*
+ * Set COL_ENABLED and COL_ENABLED_SET. If 'set' is -1, check if
+ * stdout is tty.
+ */
+static int set_enable_bit(int *mode, int set, int stdout_is_tty)
+{
+ if (set < 0) { /* auto */
+ if (stdout_is_tty < 0)
+ stdout_is_tty = isatty(1);
+ set = stdout_is_tty || (pager_in_use() && pager_use_color);
+ }
+ if (set)
+ *mode = *mode | COL_ENABLED | COL_ENABLED_SET;
+ else
+ *mode = (*mode & ~COL_ENABLED) | COL_ENABLED_SET;
+ return 0;
+}
+
+/*
+ * Set COL_MODE_*. mode is intially copied from column.ui. If
+ * COL_ENABLED_SET is not set, then neither 'always', 'never' nor
+ * 'auto' has been used. Default to 'always'.
+ */
+static int set_mode(int *mode, int value)
+{
+ *mode = (*mode & ~COL_MODE) | value;
+ if (!(*mode & COL_ENABLED_SET))
+ *mode |= COL_ENABLED | COL_ENABLED_SET;
+
+ return 0;
+}
+
+/* Set or unset other COL_* */
+static int set_option(int *mode, int opt, int set)
+{
+ if (set)
+ *mode |= opt;
+ else
+ *mode &= ~opt;
+ return 0;
+}
+
+static int parse_option(const char *arg, int len,
+ int *mode, int stdout_is_tty)
+{
+ struct colopt opts[] = {
+ { ENABLE, "always", 1 },
+ { ENABLE, "never", 0 },
+ { ENABLE, "auto", -1 },
+ };
+ int i, set, name_len;
+
+ for (i = 0; i < ARRAY_SIZE(opts); i++) {
+ if (opts[i].type == OPTION) {
+ if (len > 2 && !strncmp(arg, "no", 2)) {
+ arg += 2;
+ len -= 2;
+ set = 0;
+ }
+ else
+ set = 1;
+ }
+
+ name_len = strlen(opts[i].name);
+ if (len != name_len ||
+ strncmp(arg, opts[i].name, name_len))
+ continue;
+
+ switch (opts[i].type) {
+ case ENABLE: return set_enable_bit(mode, opts[i].value,
+ stdout_is_tty);
+ case MODE: return set_mode(mode, opts[i].value);
+ case OPTION: return set_option(mode, opts[i].value, set);
+ default: die("BUG: Unknown option type %d", opts[i].type);
+ }
+ }
+
+ return error("unsupported style '%s'", arg);
+}
+
+static int parse_string(int *mode, const char *value,
+ int stdout_is_tty)
+{
+ const char *sep = " ,";
+
+ while (*value) {
+ int len = strcspn(value, sep);
+ if (len) {
+ if (parse_option(value, len, mode, stdout_is_tty))
+ return -1;
+
+ value += len;
+ }
+ value += strspn(value, sep);
+ }
+ return 0;
+}
+
+int parseopt_column_callback(const struct option *opt,
+ const char *arg, int unset)
+{
+ int *mode = opt->value;
+ if (unset) {
+ *mode = (*mode & ~COL_ENABLED) | COL_ENABLED_SET;
+ return 0;
+ }
+ if (arg)
+ return parse_string(mode, arg, -1);
+
+ /* no arg, turn it on */
+ *mode |= COL_ENABLED | COL_ENABLED_SET;
+ return 0;
+}
diff --git a/column.h b/column.h
index ffae87c..a8b24e8 100644
--- a/column.h
+++ b/column.h
@@ -3,9 +3,13 @@
#define COL_MODE 0x000F
#define COL_ENABLED (1 << 4)
+#define COL_ENABLED_SET (1 << 5) /* Has COL_ENABLED been set? */
extern int term_columns(void);
extern struct string_list_item *add_to_columns(struct string_list *list, int mode, const char *string);
extern void display_columns(const struct string_list *list, int mode, int width, int padding, const char *indent);
+struct option;
+extern int parseopt_column_callback(const struct option *opt, const char *arg, int unset);
+
#endif
diff --git a/parse-options.h b/parse-options.h
index 31ec5d2..14816b6 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -220,5 +220,7 @@ extern int parse_opt_tertiary(const struct option *, const char *, int);
PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
#define OPT__COLOR(var, h) \
OPT_COLOR_FLAG(0, "color", (var), (h))
+#define OPT_COLUMN(s, l, v, h) \
+ { OPTION_CALLBACK, (s), (l), (v), "style", (h), PARSE_OPT_OPTARG, parseopt_column_callback }
#endif
diff --git a/t/t9002-column.sh b/t/t9002-column.sh
new file mode 100755
index 0000000..099a29f
--- /dev/null
+++ b/t/t9002-column.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+test_description='git column'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ cat >lista <<\EOF
+one
+two
+three
+four
+five
+six
+seven
+eight
+nine
+ten
+eleven
+EOF
+'
+
+test_expect_success 'never' '
+ test-column --mode=never <lista >actual &&
+ test_cmp lista actual
+'
+
+test_done
diff --git a/test-column.c b/test-column.c
new file mode 100644
index 0000000..d6321a4
--- /dev/null
+++ b/test-column.c
@@ -0,0 +1,39 @@
+#include "cache.h"
+#include "strbuf.h"
+#include "parse-options.h"
+#include "string-list.h"
+#include "column.h"
+
+static const char * const builtin_column_usage[] = {
+ "git column [--mode=<mode>] [--width=<width>] [--left-space=<N>] [--right-space=<N>]",
+ NULL
+};
+
+int main(int argc, const char **argv)
+{
+ struct string_list list = STRING_LIST_INIT_DUP;
+ int mode = 0;
+ struct strbuf sb = STRBUF_INIT;
+ int left_space = 0, right_space = 0, padding = 1;
+ int term_width = term_columns();
+ struct option options[] = {
+ OPT_INTEGER(0, "width", &term_width, "Maximum width"),
+ OPT_INTEGER(0, "left", &left_space, "Padding space on left border"),
+ OPT_INTEGER(0, "right", &right_space, "Padding space on right border"),
+ OPT_INTEGER(0, "padding", &padding, "Padding space between columns"),
+ OPT_COLUMN(0, "mode", &mode, "layout to use"),
+ OPT_END()
+ };
+
+ argc = parse_options(argc, argv, "", options, builtin_column_usage, 0);
+
+ while (!strbuf_getline(&sb, stdin, '\n'))
+ string_list_append(&list, sb.buf);
+
+ strbuf_setlen(&sb, left_space);
+ memset(sb.buf, ' ', left_space);
+ display_columns(&list, mode,
+ term_width - right_space - left_space,
+ padding, sb.buf);
+ return 0;
+}
--
1.7.4.74.g639db
next prev parent reply other threads:[~2011-03-20 12:58 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-20 12:57 [PATCH 0/9] column output v3 Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 1/9] Move term_columns() to pager.c and save terminal width before pager Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 2/9] Add display_columns() to display in columnar layout Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` Nguyễn Thái Ngọc Duy [this message]
2011-03-20 12:57 ` [PATCH 4/9] display_columns: add COL_MODE_{COLUMN,ROW} mode Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 5/9] display_columns: add COL_DENSE to do unequal column layout Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 6/9] column: add column.ui for default column output settings Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 7/9] help: reuse display_columns() for help -a Nguyễn Thái Ngọc Duy
2011-03-20 16:04 ` Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 8/9] tag: add --column Nguyễn Thái Ngọc Duy
2011-03-20 12:57 ` [PATCH 9/9] branch: " Nguyễn Thái Ngọc Duy
2011-03-20 19:52 ` Teemu Likonen
2011-03-20 23:26 ` Nguyễn Thái Ngọc Duy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1300625873-18435-4-git-send-email-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.