Commit: 325cecc67dfc7dd267bc85b4f978f902dfb185a8
Parent: c7b7295f5de572d98a77d9d292758626989e60cc
Author: Randy Palamar
Date: Sat, 16 Jul 2022 13:05:02 -0600
implement an interactive/repl mode for [-i]
this also involved a slight refactoring for better code reuse
Diffstat:
M | config.def.h | | | 4 | ++++ |
M | jdict.c | | | 120 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------- |
M | util.c | | | 19 | +++++++++++++++++++ |
M | util.h | | | 1 | + |
4 files changed, 115 insertions(+), 29 deletions(-)
diff --git a/config.def.h b/config.def.h
@@ -3,6 +3,10 @@
/* dir where unzipped yomidicts are stored */
static char *prefix = "/usr/share/yomidicts";
+/* repl prompt and quit strings */
+static char *repl_prompt = "\033[32;1m入力:\033[0m ";
+static char *repl_quit = "\n\033[36m(=^ᆺ^)ノ バイバイ~\033[0m";
+
/* default yomidicts to search */
static struct Dict {
const char *rom;
diff --git a/jdict.c b/jdict.c
@@ -17,6 +17,9 @@
#define YOMI_TOKS_PER_ENT 10
#define YOMI_TOK_DELTA (YOMI_TOKS_PER_ENT * 100)
+/* buffer length for interactive mode */
+#define BUFLEN 256
+
typedef struct {
char *term;
char **defs;
@@ -28,7 +31,22 @@ char *argv0;
static void
usage(void)
{
- die("usage: %s [-d path] term ...\n", argv0);
+ die("usage: %s [-d path] [-i] term ...\n", argv0);
+}
+
+static void
+free_ents(DictEnt *ents, size_t nents)
+{
+ size_t i, j;
+
+ for (i = 0; i < nents; i++) {
+ for (j = 0; j < ents[i].ndefs; j++)
+ free(ents[i].defs[j]);
+ free(ents[i].defs);
+ free(ents[i].term);
+ }
+ free(ents);
+ ents = NULL;
}
/* takes a token of type YOMI_ENTRY and creates a DictEnt */
@@ -128,14 +146,15 @@ cleanup:
}
static DictEnt *
-make_dict(const char *path, size_t *stride, size_t *nents)
+make_dict(struct Dict *dict, size_t *nents)
{
- char tbank[PATH_MAX];
+ char path[PATH_MAX - 20], tbank[PATH_MAX];
size_t i, nbanks = 0;
DIR *dir;
struct dirent *dent;
- DictEnt *dict = NULL;
+ DictEnt *ents = NULL;
+ snprintf(path, LEN(path), "%s/%s", prefix, dict->rom);
if (!(dir = opendir(path)))
die("opendir(): failed to open: %s\n", path);
@@ -149,13 +168,13 @@ make_dict(const char *path, size_t *stride, size_t *nents)
closedir(dir);
for (i = 1; i <= nbanks; i++) {
- snprintf(tbank, sizeof(tbank), "%s/term_bank_%d.json", path, (int)i);
- dict = parse_term_bank(dict, nents, tbank, stride);
- if (dict == NULL)
+ snprintf(tbank, LEN(tbank), "%s/term_bank_%d.json", path, (int)i);
+ ents = parse_term_bank(ents, nents, tbank, &dict->stride);
+ if (ents == NULL)
return NULL;
}
- return dict;
+ return ents;
}
static int
@@ -208,35 +227,72 @@ print_ent(DictEnt *ent)
printf("%s\n", fix_newlines(ent->defs[i]));
}
+static void
+find_and_print(const char *term, DictEnt *ents, size_t nents)
+{
+ DictEnt *ent;
+
+ ent = find_ent(term, ents, nents);
+ if (ent)
+ print_ent(ent);
+ else
+ printf("term not found: %s\n\n", term);
+}
+
static int
find_and_print_defs(struct Dict *dict, char **terms, size_t nterms)
{
- char path[PATH_MAX - 18];
- size_t i, j;
- size_t nents = 0;
- DictEnt *ent, *ents;
+ size_t i, nents = 0;
+ DictEnt *ents;
- snprintf(path, LEN(path), "%s/%s", prefix, dict->rom);
- ents = make_dict(path, &dict->stride, &nents);
+ ents = make_dict(dict, &nents);
if (ents == NULL)
return -1;
qsort(ents, nents, sizeof(DictEnt), entcmp);
printf("%s\n", dict->name);
- for (i = 0; i < nterms; i++) {
- ent = find_ent(terms[i], ents, nents);
- if (ent != NULL)
- print_ent(ent);
- else
- printf("term not found: %s\n\n", terms[i]);
+ for (i = 0; i < nterms; i++)
+ find_and_print(terms[i], ents, nents);
+
+ free_ents(ents, nents);
+
+ return 0;
+}
+
+static int
+repl(struct Dict *dicts, size_t ndicts)
+{
+ DictEnt **ents;
+ char buf[BUFLEN];
+ size_t i, *nents;
+
+ nents = xreallocarray(NULL, ndicts, sizeof(size_t));
+ ents = xreallocarray(NULL, ndicts, sizeof(DictEnt *));
+
+ for (i = 0; i < ndicts; i++) {
+ ents[i] = make_dict(&dicts[i], &nents[i]);
+ if (ents[i] == NULL)
+ die("make_dict(%s): returned NULL\n", dicts[i].rom);
+ qsort(ents[i], nents[i], sizeof(DictEnt), entcmp);
}
- for (i = 0; i < nents; i++) {
- for (j = 0; j < ents[i].ndefs; j++)
- free(ents[i].defs[j]);
- free(ents[i].defs);
- free(ents[i].term);
+
+ fputs(repl_prompt, stdout);
+ fflush(stdout);
+ while (fgets(buf, LEN(buf), stdin)) {
+ trim(buf);
+ for (i = 0; i < ndicts; i++) {
+ printf("%s\n", dicts[i].name);
+ find_and_print(buf, ents[i], nents[i]);
+ }
+ fputs(repl_prompt, stdout);
+ fflush(stdout);
}
+ puts(repl_quit);
+
+ for (i = 0; i < ndicts; i++)
+ free_ents(ents[i], nents[i]);
free(ents);
+ free(nents);
return 0;
}
@@ -247,7 +303,7 @@ main(int argc, char *argv[])
char **terms = NULL, *t;
struct Dict *dicts = NULL;
size_t ndicts = 0, nterms = 0;
- int i;
+ int i, iflag = 0;
argv0 = argv[0];
@@ -264,6 +320,9 @@ main(int argc, char *argv[])
if (dicts == NULL)
die("invalid dictionary name: %s\n", t);
break;
+ case 'i':
+ iflag = 1;
+ break;
default:
usage();
} ARGEND
@@ -279,11 +338,14 @@ main(int argc, char *argv[])
terms[i] = *argv;
}
- if (nterms == 0)
+ if (nterms == 0 && iflag == 0)
usage();
- for (i = 0; i < ndicts; i++)
- find_and_print_defs(&dicts[i], terms, nterms);
+ if (iflag == 0)
+ for (i = 0; i < ndicts; i++)
+ find_and_print_defs(&dicts[i], terms, nterms);
+ else
+ repl(dicts, ndicts);
free(terms);
diff --git a/util.c b/util.c
@@ -1,7 +1,9 @@
/* See LICENSE for license details. */
+#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "util.h"
@@ -17,6 +19,23 @@ die(const char *fmt, ...)
exit(1);
}
+void
+trim(char *s)
+{
+ char *p = s;
+ size_t len;
+
+ if (s == NULL)
+ return;
+
+ len = strlen(s);
+
+ for (; isspace(p[len-1]); p[--len] = 0);
+ for (; *p && isspace(*p); p++, len--);
+
+ memmove(s, p, len + 1);
+}
+
void *
xreallocarray(void *o, size_t n, size_t s)
{
diff --git a/util.h b/util.h
@@ -2,4 +2,5 @@
#define LEN(a) (sizeof(a) / sizeof(*a))
void die(const char *, ...);
+void trim(char *);
void *xreallocarray(void *, size_t, size_t);