jdict

command line tool for looking up terms in yomidict dictionaries
git clone anongit@rnpnr.xyz:jdict.git
Log | Files | Refs | Feed | README | LICENSE

Commit: 8cf31445204356a14fd50664db67238bac2b4cfb
Parent: b8ad9e19bad361b8e95ee1dfc928c2e9e63e31e4
Author: Randy Palamar
Date:   Thu, 16 Nov 2023 06:10:44 -0700

make output field separator configurable

for now embedded newlines are only replaced when FS == "\n"

Diffstat:
Mconfig.def.h | 3+++
Mjdict.1 | 9+++++++--
Mjdict.c | 33+++++++++++++++++----------------
Mutil.c | 18++++++++++++------
Mutil.h | 2+-
5 files changed, 40 insertions(+), 25 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -6,6 +6,9 @@ /* dir where unzipped yomidicts are stored */ static char *prefix = "/usr/share/yomidicts"; +/* field separator for output printing */ +static char *fsep = "\t"; + /* repl prompt and quit strings */ static char *repl_prompt = "\033[32;1m入力:\033[0m "; static char *repl_quit = "\n\033[36m(=^ᆺ^)ノ バイバイ~\033[0m"; diff --git a/jdict.1 b/jdict.1 @@ -1,4 +1,4 @@ -.Dd November 12, 2023 +.Dd November 16, 2023 .Dt JDICT 1 . .Sh NAME @@ -8,6 +8,7 @@ .Sh SYNOPSIS .Nm .Op Fl d Ar dictionary +.Op Fl F Ar FS .Op Fl i .Ar term ... . @@ -25,8 +26,12 @@ The following options are supported: .It Fl d Ar dictionary limit search to the specified .Ar dictionary . +.It Fl F Ar FS +use +.Ar FS +for output field separation. .It Fl i -run the program in interactive mode. +run the program in interactive mode. FS will be set to "\\n". .El . .Sh CUSTOMIZATION diff --git a/jdict.c b/jdict.c @@ -369,21 +369,21 @@ find_ent(const char *term, DictEnt *ents, size_t nents) } static void -print_ent(DictEnt *ent) -{ - size_t i; - for (i = 0; i < ent->ndefs; i++) - puts(fix_newlines(ent->defs[i])); -} - -static void find_and_print(const char *term, Dict *d) { DictEnt *ent = find_ent(term, d->ents, d->nents); - if (ent) - print_ent(ent); - else - printf("term not found: %s\n\n", term); + size_t i; + + if (!ent) + return; + + for (i = 0; i < ent->ndefs; i++) { + fputs(d->name, stdout); + fputs(fsep, stdout); + fputs(!strcmp(fsep, "\n")? unescape(ent->defs[i]) + : ent->defs[i], stdout); + fputc('\n', stdout); + } } static void @@ -397,7 +397,6 @@ find_and_print_defs(Dict *dict, char **terms, size_t nterms) return; } - puts(dict->name); for (i = 0; i < nterms; i++) find_and_print(terms[i], dict); @@ -412,15 +411,14 @@ repl(Dict *dicts, size_t ndicts) make_dicts(dicts, ndicts); + fsep = "\n"; for (;;) { fputs(repl_prompt, stdout); fflush(stdout); if (fgets(buf, LEN(buf), stdin) == NULL) break; - for (i = 0; i < ndicts; i++) { - puts(dicts[i].name); + for (i = 0; i < ndicts; i++) find_and_print(trim(buf), &dicts[i]); - } } puts(repl_quit); @@ -451,6 +449,9 @@ main(int argc, char *argv[]) if (dicts == NULL) die("invalid dictionary name: %s\n", t); break; + case 'F': + fsep = unescape(EARGF(usage())); + break; case 'i': iflag = 1; break; diff --git a/util.c b/util.c @@ -35,16 +35,22 @@ trim(char *s) return s; } -/* replace embedded escaped newlines with actual newlines */ +/* replace escaped control chars with their actual char */ char * -fix_newlines(char *s) +unescape(char *s) { char *t = s; + int off; - while ((t = strstr(t, "\\n")) != NULL) { - t[0] = '\n'; - t++; - memmove(t, t + 1, strlen(t + 1) + 1); + while ((t = strchr(t, '\\')) != NULL) { + off = 1; + switch (t[1]) { + case 'n': t[0] = '\n'; t++; break; + case 't': t[0] = '\t'; t++; break; + case 'u': t++; continue; + default: off++; + } + memmove(t, t + off, strlen(t + off) + 1); } return s; diff --git a/util.h b/util.h @@ -2,7 +2,7 @@ #define LEN(a) (sizeof(a) / sizeof(*a)) void die(const char *, ...); -char *fix_newlines(char *); +char *unescape(char *); char *trim(char *); char *xmemdup(void *, ptrdiff_t); void *xreallocarray(void *, size_t, size_t);