From 920e82c0121ea5e1f0f520251a9a43de0f1a63c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Diego=20Aur=C3=A9lio=20Mesquita?= Date: Mon, 20 Aug 2018 17:45:11 -0300 Subject: [PATCH] completion: Syntaxes can now contain the "dictionary" keyword MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit which specifies a path to a dictionary, ie: a file with a list of words, which will be used when completion is invoked. This allows us to have an arbitrary file with words to be used for completion and preliminary tags support. Signed-off-by: Marco Diego Aurélio Mesquita --- src/files.c | 30 ++++++++++++++++++++++++++++++ src/nano.h | 7 +++++++ src/proto.h | 2 ++ src/rcfile.c | 25 +++++++++++++++++++++++++ src/text.c | 6 ++++++ 5 files changed, 70 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/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 b472148..df79ffb 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 08de4d6..8578778 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; @@ -985,6 +987,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 || @@ -1181,6 +1185,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 b0bf695..e4b77dc 100644 --- a/src/text.c +++ b/src/text.c @@ -3499,6 +3499,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