diff --git a/src/global.c b/src/global.c index fc5fad3..1a5f49a 100644 --- a/src/global.c +++ b/src/global.c @@ -1845,6 +1845,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 e05ae52..ff8f3ac 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,10 @@ 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 *completer; + /* The path to the completer dicitonary to this type of file. */ + struct filestruct *dict; + /* The dicitonary cache to this type of file. */ char *formatter; /* The formatting command (for programming languages mainly). */ #ifdef ENABLE_COMMENT diff --git a/src/proto.h b/src/proto.h index 30d18a7..a3d56e1 100644 --- a/src/proto.h +++ b/src/proto.h @@ -477,6 +477,7 @@ void grab_and_store(const char *kind, char *ptr, regexlisttype **storage); #endif void parse_rcfile(FILE *rcstream, bool syntax_only); void do_rcfiles(void); +bool is_good_file(char *file); #endif /* ENABLE_NANORC */ /* Most functions in search.c. */ diff --git a/src/rcfile.c b/src/rcfile.c index 42fc84a..2b05a5e 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -301,6 +301,8 @@ void parse_syntax(char *ptr) live_syntax->headers = NULL; live_syntax->magics = NULL; live_syntax->linter = NULL; + live_syntax->completer = NULL; + live_syntax->dict = NULL; live_syntax->formatter = NULL; #ifdef ENABLE_COMMENT live_syntax->comment = mallocstrcpy(NULL, GENERAL_COMMENT_CHARACTER); @@ -986,6 +988,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, "completer") == 0) + pick_up_name("completer", ptr, &live_syntax->completer); else if (strcasecmp(keyword, "formatter") == 0) #ifdef ENABLE_SPELLER pick_up_name("formatter", ptr, &live_syntax->formatter); diff --git a/src/text.c b/src/text.c index 9cd355c..a6be6b6 100644 --- a/src/text.c +++ b/src/text.c @@ -3549,6 +3549,59 @@ char *copy_completion(char *check_line, int start) return word; } +filestruct *get_dict(char *shard) +{ + char *file = openfile->syntax->completer; + FILE *rcstream; + filestruct *lines = openfile->syntax->dict, *tmpline = NULL, *curline = NULL; + + if (lines) + goto end; + + statusbar(_("Loading dictionary, please wait")); + + /* If no file is specified, return no dictionaray. */ + if (!file) + goto end; + + /* Don't open directories, character files, or block files. */ + if (!is_good_file(file)) + goto end; + + /* Open the included syntax file. */ + rcstream = fopen(file, "rb"); + + if (rcstream == NULL) { + statusline(ALERT, _("Error reading %s: %s"), file, strerror(errno)); + goto end; + } + + char *buf = NULL; + ssize_t len; + size_t n = 0; + size_t lineno = 0; + + while ((len = getline(&buf, &n, rcstream)) > 0) { + tmpline = curline; + curline = nmalloc(sizeof(filestruct)); + curline->next = NULL; + curline->prev = tmpline; + if (curline->prev != NULL) + curline->prev->next = curline; + curline->data = mallocstrcpy(NULL, buf); + curline->lineno = ++lineno; + curline->multidata = NULL; + + if (lines == NULL) + lines = curline; + } + + wipe_statusbar(); + openfile->syntax->dict = lines; +end: + return lines; +} + /* Look at the fragment the user has typed, then search the current buffer for * the first word that starts with this fragment, and tentatively complete the * fragment. If the user types 'Complete' again, search and paste the next @@ -3610,6 +3663,11 @@ void complete_a_word(void) shard[shard_length++] = openfile->current->data[start_of_shard++]; shard[shard_length] = '\0'; + if (pletion_line == openfile->fileage) { + pletion_line = get_dict(shard); + pletion_line = pletion_line == NULL ? openfile->fileage : pletion_line; + } + /* 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;