mirror of
https://github.com/ascii-boxes/boxes.git
synced 2025-06-21 10:18:17 +02:00
Add argument to -q option for tag queries #23
-q is no longer undocumented, but can officially be used in combination with -l
This commit is contained in:
parent
aab643acbc
commit
27adf5b6ba
88
src/boxes.c
88
src/boxes.c
@ -90,7 +90,7 @@ static void usage(FILE *st)
|
|||||||
fprintf(st, " -m mend box, i.e. remove it and redraw it afterwards\n");
|
fprintf(st, " -m mend box, i.e. remove it and redraw it afterwards\n");
|
||||||
fprintf(st, " -n enc Character encoding of input and output [default: %s]\n", locale_charset());
|
fprintf(st, " -n enc Character encoding of input and output [default: %s]\n", locale_charset());
|
||||||
fprintf(st, " -p fmt padding [default: none]\n");
|
fprintf(st, " -p fmt padding [default: none]\n");
|
||||||
/* fprintf(st, " -q modify command for needs of the web UI (undocumented)\n"); */
|
fprintf(st, " -q qry in combination with -l, query design list by tag\n"); /* with (undoc) arg, trigger undocumented webui stuff */
|
||||||
fprintf(st, " -r remove box\n");
|
fprintf(st, " -r remove box\n");
|
||||||
fprintf(st, " -s wxh box size (width w and/or height h)\n");
|
fprintf(st, " -s wxh box size (width w and/or height h)\n");
|
||||||
fprintf(st, " -t str tab stop distance and expansion [default: %de]\n", DEF_TABSTOP);
|
fprintf(st, " -t str tab stop distance and expansion [default: %de]\n", DEF_TABSTOP);
|
||||||
@ -128,6 +128,55 @@ static void usage_long(FILE *st)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int validate_tag(char *tag)
|
||||||
|
{
|
||||||
|
if (strcmp(tag, "(all)") == 0 || strcmp(tag, "(undoc)") == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return tag_is_valid(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static char **parse_tag_query(char *optarg)
|
||||||
|
{
|
||||||
|
char **result = NULL;
|
||||||
|
char *dup = strdup(optarg); /* required because strtok() modifies its input */
|
||||||
|
|
||||||
|
size_t num_expr = 0;
|
||||||
|
for (char *q = strtok(dup, ","); q != NULL; q = strtok(NULL, ","))
|
||||||
|
{
|
||||||
|
char *trimmed = trimdup(q, q + strlen(q) - 1);
|
||||||
|
if (strlen(trimmed) == 0) {
|
||||||
|
BFREE(trimmed);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trimmed[0] == '+' || trimmed[0] == '-') {
|
||||||
|
if (!validate_tag(trimmed + 1)) {
|
||||||
|
fprintf(stderr, "%s: not a tag -- %s\n", PROJECT, trimmed + 1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else if (!validate_tag(trimmed)) {
|
||||||
|
fprintf(stderr, "%s: not a tag -- %s\n", PROJECT, trimmed);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
++num_expr;
|
||||||
|
result = (char **) realloc(result, (num_expr + 1) * sizeof(char *));
|
||||||
|
if (result == NULL) {
|
||||||
|
perror(PROJECT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result[num_expr - 1] = trimmed;
|
||||||
|
result[num_expr] = NULL;
|
||||||
|
}
|
||||||
|
BFREE(dup);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int process_commandline(int argc, char *argv[])
|
static int process_commandline(int argc, char *argv[])
|
||||||
/*
|
/*
|
||||||
* Process command line options.
|
* Process command line options.
|
||||||
@ -157,6 +206,7 @@ static int process_commandline(int argc, char *argv[])
|
|||||||
opt.tabexp = 'e';
|
opt.tabexp = 'e';
|
||||||
opt.killblank = -1;
|
opt.killblank = -1;
|
||||||
opt.encoding = NULL;
|
opt.encoding = NULL;
|
||||||
|
opt.query = NULL;
|
||||||
for (idummy = 0; idummy < ANZ_SIDES; ++idummy) {
|
for (idummy = 0; idummy < ANZ_SIDES; ++idummy) {
|
||||||
opt.padding[idummy] = -1;
|
opt.padding[idummy] = -1;
|
||||||
}
|
}
|
||||||
@ -173,7 +223,7 @@ static int process_commandline(int argc, char *argv[])
|
|||||||
* Parse Command Line
|
* Parse Command Line
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
oc = getopt(argc, argv, "a:c:d:f:hi:k:lmn:p:qrs:t:v");
|
oc = getopt(argc, argv, "a:c:d:f:hi:k:lmn:p:q:rs:t:v");
|
||||||
|
|
||||||
switch (oc) {
|
switch (oc) {
|
||||||
|
|
||||||
@ -416,9 +466,13 @@ static int process_commandline(int argc, char *argv[])
|
|||||||
|
|
||||||
case 'q':
|
case 'q':
|
||||||
/*
|
/*
|
||||||
* Activate special behavior for web UI (undocumented)
|
* Record the argument of the '-q' option. Combined with '-l', this is a tag query,
|
||||||
|
* else it activates undocumented special behavior used by the web UI.
|
||||||
*/
|
*/
|
||||||
opt.q = 1;
|
opt.query = parse_tag_query(optarg);
|
||||||
|
if (opt.query == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
@ -584,7 +638,15 @@ static int process_commandline(int argc, char *argv[])
|
|||||||
fprintf (stderr, "- Line justification: \'%c\'\n", opt.justify? opt.justify: '?');
|
fprintf (stderr, "- Line justification: \'%c\'\n", opt.justify? opt.justify: '?');
|
||||||
fprintf (stderr, "- Kill blank lines: %d\n", opt.killblank);
|
fprintf (stderr, "- Kill blank lines: %d\n", opt.killblank);
|
||||||
fprintf (stderr, "- Remove box: %d\n", opt.r);
|
fprintf (stderr, "- Remove box: %d\n", opt.r);
|
||||||
fprintf (stderr, "- Special handling for Web UI: %d\n", opt.q);
|
fprintf (stderr, "- Tag Query / Special handling for Web UI: ");
|
||||||
|
if (opt.query != NULL) {
|
||||||
|
for (size_t qidx = 0; opt.query[qidx] != NULL; ++qidx) {
|
||||||
|
fprintf(stderr, "%s%s", qidx > 0 ? ", " : "", opt.query[qidx]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf (stderr, "(none)");
|
||||||
|
}
|
||||||
|
fprintf (stderr, "\n");
|
||||||
fprintf (stderr, "- Mend box: %d\n", opt.mend);
|
fprintf (stderr, "- Mend box: %d\n", opt.mend);
|
||||||
fprintf (stderr, "- Design Definition W shape: %s\n", opt.cld? opt.cld: "n/a");
|
fprintf (stderr, "- Design Definition W shape: %s\n", opt.cld? opt.cld: "n/a");
|
||||||
#endif
|
#endif
|
||||||
@ -765,6 +827,14 @@ static char *names(design_t *design)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int filter_by_tag(char **tags)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return 1; // TODO or 0 if the tags don't match
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int list_styles()
|
static int list_styles()
|
||||||
/*
|
/*
|
||||||
* Generate sorted listing of available box styles.
|
* Generate sorted listing of available box styles.
|
||||||
@ -927,7 +997,7 @@ static int list_styles()
|
|||||||
/*
|
/*
|
||||||
* Display all shapes
|
* Display all shapes
|
||||||
*/
|
*/
|
||||||
if (opt.q) {
|
if (opt.query != NULL) {
|
||||||
fprintf(opt.outfile, "Sample:\n%s\n", d->sample);
|
fprintf(opt.outfile, "Sample:\n%s\n", d->sample);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -966,16 +1036,18 @@ static int list_styles()
|
|||||||
}
|
}
|
||||||
qsort(list, anz_designs, sizeof(design_t *), style_sort);
|
qsort(list, anz_designs, sizeof(design_t *), style_sort);
|
||||||
|
|
||||||
if (!opt.q) {
|
if (opt.query == NULL) {
|
||||||
print_design_list_header();
|
print_design_list_header();
|
||||||
}
|
}
|
||||||
for (i = 0; i < anz_designs; ++i) {
|
for (i = 0; i < anz_designs; ++i) {
|
||||||
if (opt.q) {
|
if (opt.query != NULL) {
|
||||||
|
if (filter_by_tag(list[i]->tags)) {
|
||||||
fprintf(opt.outfile, "%s\n", list[i]->name);
|
fprintf(opt.outfile, "%s\n", list[i]->name);
|
||||||
for (size_t aidx = 0; list[i]->aliases[aidx] != NULL; ++aidx) {
|
for (size_t aidx = 0; list[i]->aliases[aidx] != NULL; ++aidx) {
|
||||||
fprintf(opt.outfile, "%s (alias)\n", list[i]->aliases[aidx]);
|
fprintf(opt.outfile, "%s (alias)\n", list[i]->aliases[aidx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
char *all_names = names(list[i]);
|
char *all_names = names(list[i]);
|
||||||
if (list[i]->author && list[i]->designer && strcmp(list[i]->author, list[i]->designer) != 0) {
|
if (list[i]->author && list[i]->designer && strcmp(list[i]->author, list[i]->designer) != 0) {
|
||||||
|
@ -123,7 +123,7 @@ typedef struct { /* Command line options: */
|
|||||||
int l; /** list available designs */
|
int l; /** list available designs */
|
||||||
char *f; /** the string specified as argument to -f ; config file path */
|
char *f; /** the string specified as argument to -f ; config file path */
|
||||||
int mend; /** 1 if -m is given, 2 in 2nd loop */
|
int mend; /** 1 if -m is given, 2 in 2nd loop */
|
||||||
int q; /** special handling of web UI needs */
|
char **query; /** parsed tag query expression passed in via -q; also, special handling of web UI needs */
|
||||||
int r; /** remove box from input */
|
int r; /** remove box from input */
|
||||||
int tabstop; /** tab stop distance */
|
int tabstop; /** tab stop distance */
|
||||||
char tabexp; /** tab expansion mode (for leading tabs) */
|
char tabexp; /** tab expansion mode (for leading tabs) */
|
||||||
|
@ -1034,7 +1034,7 @@ int output_box(const sentry_t *thebox)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* add info line for web ui if requested with -q */
|
/* add info line for web ui if requested with -q */
|
||||||
if (opt.q) {
|
if (opt.query != NULL) {
|
||||||
fprintf(opt.outfile, "%d ", (int) (thebox[BTOP].height + vfill1_save - skip_start));
|
fprintf(opt.outfile, "%d ", (int) (thebox[BTOP].height + vfill1_save - skip_start));
|
||||||
for (j = 0; j < input.anz_lines; j++) {
|
for (j = 0; j < input.anz_lines; j++) {
|
||||||
fprintf(opt.outfile, "%d%s",
|
fprintf(opt.outfile, "%d%s",
|
||||||
|
32
src/parser.y
32
src/parser.y
@ -416,18 +416,6 @@ static int design_name_exists(pass_to_bison *bison_args, char *name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tag_is_valid(char *tag)
|
|
||||||
{
|
|
||||||
const size_t len = strlen(tag);
|
|
||||||
return len > 0
|
|
||||||
&& strspn(tag, "abcdefghijklmnopqrstuvwxyz-0123456789") == len
|
|
||||||
&& strchr("abcdefghijklmnopqrstuvwxyz", tag[0]) != NULL
|
|
||||||
&& tag[len - 1] != '-'
|
|
||||||
&& strstr(tag, "--") == NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tag_add(pass_to_bison *bison_args, char *tag)
|
static int tag_add(pass_to_bison *bison_args, char *tag)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@ -463,22 +451,6 @@ static char *tag_next_comma(char *s)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static char *tag_trim(char *s, char *e)
|
|
||||||
{
|
|
||||||
if (s > e || (s == e && *s == '\0')) {
|
|
||||||
return strdup("");
|
|
||||||
}
|
|
||||||
while (s <= e && (*s == ' ' || *s == '\t')) {
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
while (e > s && (*e == ' ' || *e == '\t')) {
|
|
||||||
--e;
|
|
||||||
}
|
|
||||||
return strndup(s, e - s + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tag_split_add(pass_to_bison *bison_args, char *tag)
|
static int tag_split_add(pass_to_bison *bison_args, char *tag)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@ -486,7 +458,7 @@ static int tag_split_add(pass_to_bison *bison_args, char *tag)
|
|||||||
char *c = NULL;
|
char *c = NULL;
|
||||||
do {
|
do {
|
||||||
c = tag_next_comma(s);
|
c = tag_next_comma(s);
|
||||||
char *single_tag = tag_trim(s, c - 1);
|
char *single_tag = trimdup(s, c - 1);
|
||||||
int rc_add = tag_add(bison_args, single_tag);
|
int rc_add = tag_add(bison_args, single_tag);
|
||||||
if (rc_add != 0) {
|
if (rc_add != 0) {
|
||||||
rc = rc_add;
|
rc = rc_add;
|
||||||
@ -511,7 +483,7 @@ static int tag_record(pass_to_bison *bison_args, char *tag)
|
|||||||
rc = tag_split_add(bison_args, tag);
|
rc = tag_split_add(bison_args, tag);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char *trimmed = tag_trim(tag, tag + strlen(tag) - 1);
|
char *trimmed = trimdup(tag, tag + strlen(tag) - 1);
|
||||||
rc = tag_add(bison_args, trimmed);
|
rc = tag_add(bison_args, trimmed);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
33
src/tools.c
33
src/tools.c
@ -682,4 +682,37 @@ size_t array_count0(char **array)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
char *trimdup(char *s, char *e)
|
||||||
|
{
|
||||||
|
if (s > e || (s == e && *s == '\0')) {
|
||||||
|
return strdup("");
|
||||||
|
}
|
||||||
|
while (s <= e && (*s == ' ' || *s == '\t')) {
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
while (e > s && (*e == ' ' || *e == '\t')) {
|
||||||
|
--e;
|
||||||
|
}
|
||||||
|
return strndup(s, e - s + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int tag_is_valid(char *tag)
|
||||||
|
{
|
||||||
|
if (tag == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t len = strlen(tag);
|
||||||
|
return len > 0
|
||||||
|
&& strspn(tag, "abcdefghijklmnopqrstuvwxyz-0123456789") == len
|
||||||
|
&& strchr("abcdefghijklmnopqrstuvwxyz", tag[0]) != NULL
|
||||||
|
&& tag[len - 1] != '-'
|
||||||
|
&& strstr(tag, "--") == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*EOF*/ /* vim: set sw=4: */
|
/*EOF*/ /* vim: set sw=4: */
|
||||||
|
18
src/tools.h
18
src/tools.h
@ -97,6 +97,24 @@ int array_contains0(char **array, const char *s);
|
|||||||
*/
|
*/
|
||||||
size_t array_count0(char **array);
|
size_t array_count0(char **array);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trim leading and trailing whitespace from a string and return the result in a new string, for which memory is
|
||||||
|
* allocated. `s` and `e` may point into some other string, which will not be modified. `e` should be greater than `s`.
|
||||||
|
* @param s pointer to the first character of the string
|
||||||
|
* @param e pointer to the last character of the string (NOT the character AFTER the last)
|
||||||
|
* @returns a new string, which may be the empty string if the input was invalid or consisted only of whitespace
|
||||||
|
*/
|
||||||
|
char *trimdup(char *s, char *e);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the given string is a valid tag. Valid tags are lower-case alphanumeric strings which may have
|
||||||
|
* intermixed, single hyphens. A valid tag starts with a letter. Hyphens may also not appear as last character.
|
||||||
|
* @param tag a potential tag
|
||||||
|
* @return flag indicating validity
|
||||||
|
*/
|
||||||
|
int tag_is_valid(char *tag);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*EOF*/ /* vim: set cindent sw=4: */
|
/*EOF*/ /* vim: set cindent sw=4: */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-ac -q -s 12
|
-ac -q (undoc) -s 12
|
||||||
:INPUT
|
:INPUT
|
||||||
foo
|
foo
|
||||||
barf
|
barf
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-ar -q -s 12
|
-ar -q (undoc) -s 12
|
||||||
:INPUT
|
:INPUT
|
||||||
foo
|
foo
|
||||||
barf
|
barf
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-q -s 12
|
-q (undoc) -s 12
|
||||||
:INPUT
|
:INPUT
|
||||||
foo
|
foo
|
||||||
barf
|
barf
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-ac -q -s 18x5 -p h3
|
-ac -q (undoc) -s 18x5 -p h3
|
||||||
:INPUT
|
:INPUT
|
||||||
foo
|
foo
|
||||||
barf
|
barf
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-ac -q -s 18 -p a3 -i box
|
-ac -q (undoc) -s 18 -p a3 -i box
|
||||||
:INPUT
|
:INPUT
|
||||||
foo
|
foo
|
||||||
barf
|
barf
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-ac -q -p a3 -d diamonds -i text
|
-ac -q (undoc) -p a3 -d diamonds -i text
|
||||||
:INPUT
|
:INPUT
|
||||||
foo
|
foo
|
||||||
barf
|
barf
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-q -t 8k
|
-q (undoc) -t 8k
|
||||||
:INPUT
|
:INPUT
|
||||||
foo
|
foo
|
||||||
barf
|
barf
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-q -s 12
|
-q (undoc) -s 12
|
||||||
:INPUT
|
:INPUT
|
||||||
f
|
f
|
||||||
fo
|
fo
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-q -s 12 -al
|
-q (undoc) -s 12 -al
|
||||||
:INPUT
|
:INPUT
|
||||||
f
|
f
|
||||||
fo
|
fo
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
:ARGS
|
:ARGS
|
||||||
-q -d right
|
-q (undoc) -d right
|
||||||
:INPUT
|
:INPUT
|
||||||
foo
|
foo
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ Reversion Rules: none
|
|||||||
Minimum Box Dimensions: 3 x 3 (width x height)
|
Minimum Box Dimensions: 3 x 3 (width x height)
|
||||||
Default Padding: left 1, right 1
|
Default Padding: left 1, right 1
|
||||||
Default Killblank: no
|
Default Killblank: no
|
||||||
Tags: (none)
|
Tags: none
|
||||||
Elastic Shapes: N, E, S, W
|
Elastic Shapes: N, E, S, W
|
||||||
Defined Shapes: E: "X"
|
Defined Shapes: E: "X"
|
||||||
W: "X"
|
W: "X"
|
||||||
|
@ -20,7 +20,7 @@ Reversion Rules: none
|
|||||||
Minimum Box Dimensions: 5 x 3 (width x height)
|
Minimum Box Dimensions: 5 x 3 (width x height)
|
||||||
Default Padding: left 1, right 1
|
Default Padding: left 1, right 1
|
||||||
Default Killblank: no
|
Default Killblank: no
|
||||||
Tags: (none)
|
Tags: none
|
||||||
Elastic Shapes: N, E, S, W
|
Elastic Shapes: N, E, S, W
|
||||||
Defined Shapes: E: "X3"
|
Defined Shapes: E: "X3"
|
||||||
W: "X3"
|
W: "X3"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user