From b2e42fd4edf32f1f0e5af6216c719f6be4e240b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Diego=20Aur=C3=A9lio=20Mesquita?= Date: Fri, 10 Aug 2018 20:55:09 -0300 Subject: [PATCH] Syntaxes can now contain the "dictionary" keyword which specifies a path to a dictionary, ie: a file with a list of words, which will be used when completion is invoked. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marco Diego Aurélio Mesquita --- src/files.c | 30 ++++++++++++++++++++++++++++++ src/global.c | 5 +++++ src/nano.h | 7 +++++++ src/proto.h | 2 ++ src/rcfile.c | 25 +++++++++++++++++++++++++ src/text.c | 6 ++++++ 6 files changed, 75 insertions(+) diff --git a/src/files.c b/src/files.c index c137b09..ab10988 100644 --- a/src/files.c +++ b/src/files.c @@ -753,6 +753,36 @@ char *encode_data(char *buf, size_t buf_len) return mallocstrcpy(NULL, buf); } +/* Loads dictionary from given path. */ +struct filestruct *load_dictionary(char *path) +{ + FILE *rcstream; + filestruct *new_word = NULL, *lines = NULL; + char *buf = NULL; + size_t n = 0; + + /* Open the dictionary file. */ + rcstream = fopen(path, "rb"); + + if (rcstream == NULL) { + statusline(ALERT, _("Error reading %s: %s"), path, strerror(errno)); + return NULL; + } + + statusbar(_("Loading dictionary, please wait")); + + while (getline(&buf, &n, rcstream) > 0) { + new_word = nmalloc(sizeof(filestruct)); + new_word->next = lines; + new_word->data = mallocstrcpy(NULL, buf); + lines = new_word; + } + + wipe_statusbar(); + + return lines; +} + /* Read the given open file f into the current buffer. filename should be * set to the name of the file. undoable means that undo records should be * created and that the file does not need to be checked for writability. */ diff --git a/src/global.c b/src/global.c index 6e81e3e..27beb9f 100644 --- a/src/global.c +++ b/src/global.c @@ -1800,6 +1800,11 @@ void thanks_for_all_the_fish(void) free(item->full_regex); free(item); } + while (sint->dict != NULL) { + struct filestruct *item = sint->dict; + sint->dict = sint->dict->next; + free(item); + } while (sint->color != NULL) { colortype *ink = sint->color; diff --git a/src/nano.h b/src/nano.h index c077980..c3fc1f8 100644 --- a/src/nano.h +++ b/src/nano.h @@ -218,6 +218,9 @@ typedef struct regexlisttype { /* The next regex. */ } regexlisttype; +struct filestruct; + /* Foreward declaration of filestruct. */ + typedef struct syntaxtype { char *name; /* The name of this syntax. */ @@ -229,6 +232,8 @@ typedef struct syntaxtype { /* The list of libmagic results that this syntax applies to. */ char *linter; /* The command with which to lint this type of file. */ + char *dictionary; + /* The path to the completions dicitonary for this type of file. */ #ifdef ENABLE_COMMENT char *comment; /* The line comment prefix (and postfix) for this type of file. */ @@ -237,6 +242,8 @@ typedef struct syntaxtype { /* The colors and their regexes used in this syntax. */ int nmultis; /* How many multiline regex strings this syntax has. */ + struct filestruct *completions; + /* The list of valid words for this syntax. */ struct syntaxtype *next; /* Next syntax. */ } syntaxtype; diff --git a/src/proto.h b/src/proto.h index 46794ff..3f7d97f 100644 --- a/src/proto.h +++ b/src/proto.h @@ -279,6 +279,7 @@ void switch_to_prev_buffer(void); void switch_to_next_buffer(void); bool close_buffer(void); #endif +filestruct *load_dictionary(char *path); void read_file(FILE *f, int fd, const char *filename, bool undoable); int open_file(const char *filename, bool newfie, bool quiet, FILE **f); char *get_next_filename(const char *name, const char *suffix); @@ -476,6 +477,7 @@ int do_yesno_prompt(bool all, const char *msg); void grab_and_store(const char *kind, char *ptr, regexlisttype **storage); #endif void parse_rcfile(FILE *rcstream, bool syntax_only); +filestruct *get_dictionary(); void do_rcfiles(void); #endif /* ENABLE_NANORC */ diff --git a/src/rcfile.c b/src/rcfile.c index b63a2c4..5e213fa 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -300,12 +300,14 @@ void parse_syntax(char *ptr) live_syntax->headers = NULL; live_syntax->magics = NULL; live_syntax->linter = NULL; + live_syntax->dictionary = NULL; #ifdef ENABLE_COMMENT live_syntax->comment = mallocstrcpy(NULL, GENERAL_COMMENT_CHARACTER); #endif live_syntax->color = NULL; lastcolor = NULL; live_syntax->nmultis = 0; + live_syntax->completions = NULL; /* Hook the new syntax in at the top of the list. */ live_syntax->next = syntaxes; @@ -984,6 +986,8 @@ void parse_rcfile(FILE *rcstream, bool syntax_only) parse_colors(ptr, NANO_REG_EXTENDED | REG_ICASE); else if (strcasecmp(keyword, "linter") == 0) pick_up_name("linter", ptr, &live_syntax->linter); + else if (strcasecmp(keyword, "dictionary") == 0) + pick_up_name("dictionary", ptr, &live_syntax->dictionary); else if (syntax_only && (strcasecmp(keyword, "set") == 0 || strcasecmp(keyword, "unset") == 0 || strcasecmp(keyword, "bind") == 0 || @@ -1180,6 +1184,27 @@ void parse_rcfile(FILE *rcstream, bool syntax_only) return; } +/* Loads the completions dictionary for the currently open file. */ +filestruct *get_dictionary() +{ + /* When it has already been loaded, there is no need to reload. */ + if (openfile->syntax->completions) + return openfile->syntax->completions; + + /* If no file is specified, return empty dictionary. */ + if (!openfile->syntax->dictionary) + return NULL; + + /* Don't open directories, character files, or block files. */ + if (!is_good_file(openfile->syntax->dictionary)) + return NULL; + + openfile->syntax->completions = + load_dictionary(openfile->syntax->dictionary); + + return openfile->syntax->completions; +} + /* Read and interpret one of the two nanorc files. */ void parse_one_nanorc(void) { diff --git a/src/text.c b/src/text.c index 18a62f0..c38a50c 100644 --- a/src/text.c +++ b/src/text.c @@ -3491,6 +3491,12 @@ void complete_a_word(void) shard[shard_length++] = openfile->current->data[start_of_shard++]; shard[shard_length] = '\0'; + if (pletion_line == openfile->fileage) { + struct filestruct *completions = get_dictionary(); + if (completions) + pletion_line = completions; + } + /* Run through all of the lines in the buffer, looking for shard. */ while (pletion_line != NULL) { int threshold = strlen(pletion_line->data) - shard_length - 1; -- 2.7.4