-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add column layout skeleton and git-column
A column option string consists of many token separated by either a space or a comma. A token belongs to one of three groups: - enabling: always, never and auto - layout mode: currently plain (which does not layout at all) - other future tuning flags git-column can be used to pipe output to from a command that wants column layout, but not to mess with its own output code. Simpler output code can be changed to use column layout code directly. Thanks-to: Ramsay Jones <ramsay@ramsay1.demon.co.uk> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
- Loading branch information
Showing
12 changed files
with
391 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ | |
/git-cherry-pick | ||
/git-clean | ||
/git-clone | ||
/git-column | ||
/git-commit | ||
/git-commit-tree | ||
/git-config | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
git-column(1) | ||
============= | ||
|
||
NAME | ||
---- | ||
git-column - Display data in columns | ||
|
||
SYNOPSIS | ||
-------- | ||
[verse] | ||
'git column' [--command=<name>] [--[raw-]mode=<mode>] [--width=<width>] | ||
[--indent=<string>] [--nl=<string>] [--pading=<n>] | ||
|
||
DESCRIPTION | ||
----------- | ||
This command formats its input into multiple columns. | ||
|
||
OPTIONS | ||
------- | ||
--command=<name>:: | ||
Look up layout mode using configuration variable column.<name> and | ||
column.ui. | ||
|
||
--mode=<mode>:: | ||
Specify layout mode. See configuration variable column.ui for option | ||
syntax. | ||
|
||
--raw-mode=<n>:: | ||
Same as --mode but take mode encoded as a number. This is mainly used | ||
by other commands that have already parsed layout mode. | ||
|
||
--width=<width>:: | ||
Specify the terminal width. By default 'git column' will detect the | ||
terminal width, or fall back to 80 if it is unable to do so. | ||
|
||
--indent=<string>:: | ||
String to be printed at the beginning of each line. | ||
|
||
--nl=<N>:: | ||
String to be printed at the end of each line, | ||
including newline character. | ||
|
||
--padding=<N>:: | ||
The number of spaces between columns. One space by default. | ||
|
||
|
||
Author | ||
------ | ||
Written by Nguyen Thai Ngoc Duy <pclouds@gmail.com> | ||
|
||
GIT | ||
--- | ||
Part of the linkgit:git[1] suite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#include "builtin.h" | ||
#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 [options]", | ||
NULL | ||
}; | ||
static unsigned int colopts; | ||
|
||
static int column_config(const char *var, const char *value, void *cb) | ||
{ | ||
return git_column_config(var, value, cb, &colopts); | ||
} | ||
|
||
int cmd_column(int argc, const char **argv, const char *prefix) | ||
{ | ||
struct string_list list = STRING_LIST_INIT_DUP; | ||
struct strbuf sb = STRBUF_INIT; | ||
struct column_options copts; | ||
const char *command = NULL, *real_command = NULL; | ||
struct option options[] = { | ||
OPT_STRING(0, "command", &real_command, "name", "lookup config vars"), | ||
OPT_COLUMN(0, "mode", &colopts, "layout to use"), | ||
OPT_INTEGER(0, "raw-mode", &colopts, "layout to use"), | ||
OPT_INTEGER(0, "width", &copts.width, "Maximum width"), | ||
OPT_STRING(0, "indent", &copts.indent, "string", "Padding space on left border"), | ||
OPT_INTEGER(0, "nl", &copts.nl, "Padding space on right border"), | ||
OPT_INTEGER(0, "padding", &copts.padding, "Padding space between columns"), | ||
OPT_END() | ||
}; | ||
|
||
/* This one is special and must be the first one */ | ||
if (argc > 1 && !prefixcmp(argv[1], "--command=")) { | ||
command = argv[1] + 10; | ||
git_config(column_config, (void *)command); | ||
} else | ||
git_config(column_config, NULL); | ||
|
||
memset(&copts, 0, sizeof(copts)); | ||
copts.width = term_columns(); | ||
copts.padding = 1; | ||
argc = parse_options(argc, argv, "", options, builtin_column_usage, 0); | ||
if (argc) | ||
usage_with_options(builtin_column_usage, options); | ||
if (real_command || command) { | ||
if (!real_command || !command || strcmp(real_command, command)) | ||
die(_("--command must be the first argument")); | ||
} | ||
finalize_colopts(&colopts, -1); | ||
while (!strbuf_getline(&sb, stdin, '\n')) | ||
string_list_append(&list, sb.buf); | ||
|
||
print_columns(&list, colopts, &copts); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
#include "cache.h" | ||
#include "column.h" | ||
#include "string-list.h" | ||
#include "parse-options.h" | ||
|
||
/* Display without layout when not enabled */ | ||
static void display_plain(const struct string_list *list, | ||
const char *indent, const char *nl) | ||
{ | ||
int i; | ||
|
||
for (i = 0; i < list->nr; i++) | ||
printf("%s%s%s", indent, list->items[i].string, nl); | ||
} | ||
|
||
void print_columns(const struct string_list *list, unsigned int colopts, | ||
const struct column_options *opts) | ||
{ | ||
struct column_options nopts; | ||
|
||
if (!list->nr) | ||
return; | ||
assert((colopts & COL_ENABLE_MASK) != COL_AUTO); | ||
|
||
memset(&nopts, 0, sizeof(nopts)); | ||
nopts.indent = opts && opts->indent ? opts->indent : ""; | ||
nopts.nl = opts && opts->nl ? opts->nl : "\n"; | ||
nopts.padding = opts ? opts->padding : 1; | ||
nopts.width = opts && opts->width ? opts->width : term_columns() - 1; | ||
if (!column_active(colopts)) { | ||
display_plain(list, "", "\n"); | ||
return; | ||
} | ||
switch (COL_LAYOUT(colopts)) { | ||
case COL_PLAIN: | ||
display_plain(list, nopts.indent, nopts.nl); | ||
break; | ||
default: | ||
die("BUG: invalid layout mode %d", COL_LAYOUT(colopts)); | ||
} | ||
} | ||
|
||
int finalize_colopts(unsigned int *colopts, int stdout_is_tty) | ||
{ | ||
if ((*colopts & COL_ENABLE_MASK) == COL_AUTO) { | ||
if (stdout_is_tty < 0) | ||
stdout_is_tty = isatty(1); | ||
*colopts &= ~COL_ENABLE_MASK; | ||
if (stdout_is_tty) | ||
*colopts |= COL_ENABLED; | ||
} | ||
return 0; | ||
} | ||
|
||
struct colopt { | ||
const char *name; | ||
unsigned int value; | ||
unsigned int mask; | ||
}; | ||
|
||
#define LAYOUT_SET 1 | ||
#define ENABLE_SET 2 | ||
|
||
static int parse_option(const char *arg, int len, unsigned int *colopts, | ||
int *group_set) | ||
{ | ||
struct colopt opts[] = { | ||
{ "always", COL_ENABLED, COL_ENABLE_MASK }, | ||
{ "never", COL_DISABLED, COL_ENABLE_MASK }, | ||
{ "auto", COL_AUTO, COL_ENABLE_MASK }, | ||
{ "plain", COL_PLAIN, COL_LAYOUT_MASK }, | ||
}; | ||
int i; | ||
|
||
for (i = 0; i < ARRAY_SIZE(opts); i++) { | ||
int arg_len = len, name_len; | ||
const char *arg_str = arg; | ||
|
||
name_len = strlen(opts[i].name); | ||
if (arg_len != name_len || | ||
strncmp(arg_str, opts[i].name, name_len)) | ||
continue; | ||
|
||
switch (opts[i].mask) { | ||
case COL_ENABLE_MASK: | ||
*group_set |= ENABLE_SET; | ||
break; | ||
case COL_LAYOUT_MASK: | ||
*group_set |= LAYOUT_SET; | ||
break; | ||
} | ||
|
||
if (opts[i].mask) | ||
*colopts = (*colopts & ~opts[i].mask) | opts[i].value; | ||
return 0; | ||
} | ||
|
||
return error("unsupported option '%s'", arg); | ||
} | ||
|
||
static int parse_config(unsigned int *colopts, const char *value) | ||
{ | ||
const char *sep = " ,"; | ||
int group_set = 0; | ||
|
||
while (*value) { | ||
int len = strcspn(value, sep); | ||
if (len) { | ||
if (parse_option(value, len, colopts, &group_set)) | ||
return -1; | ||
|
||
value += len; | ||
} | ||
value += strspn(value, sep); | ||
} | ||
/* | ||
* Setting layout implies "always" if neither always, never | ||
* nor auto is specified. | ||
* | ||
* Current value in COL_ENABLE_MASK is disregarded. This means if | ||
* you set column.ui = auto and pass --column=row, then "auto" | ||
* will become "always". | ||
*/ | ||
if ((group_set & LAYOUT_SET) && !(group_set & ENABLE_SET)) | ||
*colopts = (*colopts & ~COL_ENABLE_MASK) | COL_ENABLED; | ||
return 0; | ||
} | ||
|
||
static int column_config(const char *var, const char *value, | ||
const char *key, unsigned int *colopts) | ||
{ | ||
if (!value) | ||
return config_error_nonbool(var); | ||
if (parse_config(colopts, value)) | ||
return error("invalid column.%s mode %s", key, value); | ||
return 0; | ||
} | ||
|
||
int git_column_config(const char *var, const char *value, | ||
const char *command, unsigned int *colopts) | ||
{ | ||
const char *it = skip_prefix(var, "column."); | ||
if (!it) | ||
return 0; | ||
|
||
if (!strcmp(it, "ui")) | ||
return column_config(var, value, "ui", colopts); | ||
|
||
if (command && !strcmp(it, command)) | ||
return column_config(var, value, it, colopts); | ||
|
||
return 0; | ||
} | ||
|
||
int parseopt_column_callback(const struct option *opt, | ||
const char *arg, int unset) | ||
{ | ||
unsigned int *colopts = opt->value; | ||
*colopts |= COL_PARSEOPT; | ||
*colopts &= ~COL_ENABLE_MASK; | ||
if (unset) /* --no-column == never */ | ||
return 0; | ||
/* --column == always unless "arg" states otherwise */ | ||
*colopts |= COL_ENABLED; | ||
if (arg) | ||
return parse_config(colopts, arg); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#ifndef COLUMN_H | ||
#define COLUMN_H | ||
|
||
#define COL_LAYOUT_MASK 0x000F | ||
#define COL_ENABLE_MASK 0x0030 /* always, never or auto */ | ||
#define COL_PARSEOPT 0x0040 /* --column is given from cmdline */ | ||
|
||
#define COL_DISABLED 0x0000 /* must be zero */ | ||
#define COL_ENABLED 0x0010 | ||
#define COL_AUTO 0x0020 | ||
|
||
#define COL_LAYOUT(c) ((c) & COL_LAYOUT_MASK) | ||
#define COL_PLAIN 15 /* one column */ | ||
|
||
#define explicitly_enable_column(c) \ | ||
(((c) & COL_PARSEOPT) && column_active(c)) | ||
|
||
struct column_options { | ||
int width; | ||
int padding; | ||
const char *indent; | ||
const char *nl; | ||
}; | ||
|
||
struct option; | ||
extern int parseopt_column_callback(const struct option *, const char *, int); | ||
extern int git_column_config(const char *var, const char *value, | ||
const char *command, unsigned int *colopts); | ||
extern int finalize_colopts(unsigned int *colopts, int stdout_is_tty); | ||
static inline int column_active(unsigned int colopts) | ||
{ | ||
return (colopts & COL_ENABLE_MASK) == COL_ENABLED; | ||
} | ||
|
||
extern void print_columns(const struct string_list *list, unsigned int colopts, | ||
const struct column_options *opts); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.