From ecb8e4726a5f4921f7e7c2e686f59481d94afde4 Mon Sep 17 00:00:00 2001 From: "sumedh.pendurkar" Date: Thu, 22 Sep 2016 15:50:00 +0530 Subject: [PATCH] Added auto complete that searches in the current file and completes it or suggests words if more than 1 results are found --- src/global.c | 7 ++- src/text.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 203 insertions(+), 2 deletions(-) diff --git a/src/global.c b/src/global.c index 029b68b..e2aea0f 100644 --- a/src/global.c +++ b/src/global.c @@ -246,6 +246,7 @@ size_t length_of_list(int menu) #define TOGETHER FALSE /* Just throw this here. */ +void auto_complete_void(void); void case_sens_void(void) { } @@ -483,6 +484,7 @@ const char *unjust_tag = N_("Unjustify"); /* Initialize the list of functions and the list of shortcuts. */ void shortcut_init(void) { + const char *auto_complete_tag = N_("Auto Complete"); const char *read_file_tag = N_("Read File"); const char *whereis_tag = N_("Where Is"); const char *replace_tag = N_("Replace"); @@ -526,6 +528,7 @@ void shortcut_init(void) const char *nano_browser_lefthand_msg = N_("Go to lefthand column"); const char *nano_browser_righthand_msg = N_("Go to righthand column"); #endif + const char *nano_auto_complete_msg = ("Look up for the current word in the file"); const char *nano_prevpage_msg = N_("Go one screenful up"); const char *nano_nextpage_msg = N_("Go one screenful down"); const char *nano_cut_msg = @@ -721,7 +724,8 @@ void shortcut_init(void) add_to_funcs(goto_dir_void, MBROWSER, N_("Go To Dir"), IFSCHELP(nano_gotodir_msg), BLANKAFTER, VIEW); #endif - + add_to_funcs(auto_complete_void, MMAIN, auto_complete_tag, + IFSCHELP(nano_auto_complete_msg), TOGETHER, VIEW); #ifndef DISABLE_HELP /* The description ("x") and blank_after (0) are irrelevant, * because the help viewer does not have a help text. */ @@ -1064,6 +1068,7 @@ void shortcut_init(void) add_to_sclist(MMAIN, "^\\", do_replace, 0); add_to_sclist(MMAIN, "M-R", do_replace, 0); add_to_sclist(MMAIN, "F14", do_replace, 0); + add_to_sclist(MMAIN, "^A", auto_complete_void, 0); add_to_sclist(MMOST, "^K", do_cut_text_void, 0); add_to_sclist(MMOST, "F9", do_cut_text_void, 0); add_to_sclist(MMAIN, "^U", do_uncut_text, 0); diff --git a/src/text.c b/src/text.c index d0d1955..33daacd 100644 --- a/src/text.c +++ b/src/text.c @@ -45,7 +45,203 @@ static bool prepend_wrap = FALSE; static filestruct *jusbottom = NULL; /* Pointer to the end of the justify buffer. */ #endif - +#define WORDLEN_MAX 64 +#define WORD_MAX 20 +#define TOFIND_MAX 40 +/* Complete the common parts found in the results */ +void complete_max(char words[][WORDLEN_MAX], int start, int no_of_words) +{ + int i = start, j; + while(1) { + for(j = 0; j < no_of_words - 1; j++) { + if(words[j][i] != words[j + 1][i]) + return; + } + do_output(&words[j][i], 1, FALSE); + i++; + } +} +/* Copy the word from the line which contains the pattern + * Removes duplicates from the words + * also checks for error to avoid segfaults + */ +int copy_arrays(char words[][WORDLEN_MAX], char *check_line, int start, int *len_match) +{ + int i = start; + int j = 0; + while(check_line[i] != ' ' && check_line[i] != '\t' && check_line[i] != '\n' && + check_line[i] != '\0' && check_line[i] != ',' && check_line[i] != '.' && + check_line[i] != ')' && check_line[i] != ']' && check_line[i] != '}' && + check_line[i] != '\"' && check_line[i] != '(' && check_line[i] != '[' && + check_line[i] != '{' && check_line[i] != ';') { + if(j == WORDLEN_MAX) + return 1; + words[*len_match - 1][j++] = check_line[i]; + i++; + } + words[*len_match - 1][j] = '\0'; + if(*len_match == 1) + return 0; + for (i = *len_match - 2; i >= 0; i--) { + if(strcmp(words[i], words[*len_match - 1]) == 0) + break; + } + if(i != -1) + (*len_match)--; + return 0; +} +int check_if_exceeds(int number) +{ + if (number > WORD_MAX) + return 1; + else + return 0; +} +void auto_complete_void(void) +{ + filestruct *check_line = openfile->current; + char to_find[TOFIND_MAX]; + int curpos = openfile->current_x, len_to_find = 0, to_find_start_pos = curpos; + int to_find_end_pos = curpos, i = 0, j = 0, match = 0; + int curmax = strlen(openfile->current->data); + char words[WORD_MAX][WORDLEN_MAX]; + while (to_find_start_pos-- != 0) { + if(check_line->data[to_find_start_pos] == ' ' || check_line->data[to_find_start_pos] == '\t' || + check_line->data[to_find_start_pos] == '\n' || check_line->data[to_find_start_pos] == '(' || + check_line->data[to_find_start_pos] == '[' || check_line->data[to_find_start_pos] == '{' || + check_line->data[to_find_start_pos] == '\"') + break; + } + to_find_start_pos++; + if(to_find_end_pos - to_find_start_pos > TOFIND_MAX) { + statusline(ALERT, "The word to be found cannot be more than %d characters", TOFIND_MAX); + return; + } + /*copy what is to be searched in to find*/ + while(to_find_start_pos + i < curpos) { + to_find[len_to_find++] = check_line->data[to_find_start_pos + i++]; + } + to_find[len_to_find] = '\0'; + if(len_to_find == 0) + return; + /* Case:1 at current line */ + /*before the current word*/ + i = 0; + while(i < to_find_start_pos) { + for(j = 0; (i == 0 || check_line->data[i - 1] == ' ' || + check_line->data[i - 1] == '\t' || check_line->data[i - 1] == '('|| + check_line->data[i - 1] == '[' || check_line->data[i - 1] == '{' || + check_line->data[i - 1] == '\"') && j < len_to_find; j++) + if(to_find[j] != check_line->data[i + j]) + break; + if(j == len_to_find) { + match++; + if(check_if_exceeds(match)) { + statusline(ALERT, "More than %d words are not supported yet", WORD_MAX); + return; + } + if(copy_arrays(words,check_line->data, i, &match) == 1) { + statusline(ALERT, "Words with more than %d characters are not supported", WORDLEN_MAX); + return; + } + } + i++; + } + /*after the current word*/ + i = to_find_end_pos; + while(i < curmax) { + for(j = 0; (i == 0 || check_line->data[i - 1] == ' ' || + check_line->data[i - 1] == '\t' || check_line->data[i - 1] == '('|| + check_line->data[i - 1] == '[' || check_line->data[i - 1] == '{' || + check_line->data[i - 1] == '\"') && j < len_to_find ; j++) + if(to_find[j] != check_line-> data[i + j]) + break; + if(j == len_to_find) { + match++; + if(check_if_exceeds(match)) { + statusline(ALERT, "More than %d words are not supported yet", WORD_MAX); + return; + } + if(copy_arrays(words, check_line->data, i, &match) == 1) { + statusline(ALERT, "Words with more than %d characters are not supported", WORDLEN_MAX); + return; + } + } + i++; + } + /* Case:2 above the current line*/ + check_line = check_line->prev; + while(check_line != NULL) { + int len_data = strlen(check_line->data); + for(i = 0; i < len_data; i++) { + for(j = 0; (i == 0 || check_line->data[i - 1] == ' ' || + check_line->data[i - 1] == '\t' || check_line->data[i - 1] == '(' || + check_line->data[i - 1] == '[' || check_line->data[i - 1] == '{' || + check_line->data[i - 1] == '\"') && j < len_to_find; j++) + if(to_find[j] != check_line->data[i + j]) + break; + if(j == len_to_find) { + match++; + if(check_if_exceeds(match)) { + statusline(ALERT, "More than %d words are not supported yet", WORD_MAX); + return; + } + if(copy_arrays(words, check_line->data, i, &match) == 1) { + statusline(ALERT, "Words with more than %d characters are not supported", WORDLEN_MAX); + return; + } + } + } + check_line = check_line->prev; + } + /*Case3: below the current line*/ + check_line = openfile->current->next; + while(check_line != NULL) { + int len_data = strlen(check_line->data); + for(i = 0; i < len_data; i++) { + for(j = 0; (i == 0 || check_line->data[i - 1] == ' ' || check_line->data[i - 1] == '\t' || + check_line->data[i - 1] == '(' || check_line->data[i - 1] == '[' || + check_line->data[i - 1] == '{' || check_line->data[i - 1] == '\"') && j < len_to_find; j++) + if(to_find[j] != check_line->data[i + j]) + break; + if(j == len_to_find) { + match++; + if(check_if_exceeds(match)) { + statusline(ALERT, "More than %d words are not supported yet", WORD_MAX); + return; + } + if(copy_arrays(words,check_line->data, i, &match) == 1) { + statusline(ALERT, "Words are with more than 64 characters are not supported"); + } + } + } + check_line = check_line->next; + } + /*No match found*/ + if(match == 0) + statusline(ALERT, "No matches found"); + /*One match found*/ + else if(match == 1) { + statusline(ALERT, "Done"); + do_output(&words[0][len_to_find],strlen(words[0]) - len_to_find, FALSE); + } + /*else find out the common parts and complete it and display the rest part as suggestions*/ + else { + complete_max(words, len_to_find, match); + char *to_print; + if((to_print = (char *)malloc(65 * match)) == NULL) { + statusline(ALERT, "Insufficient memory"); + return; + } + strcpy(to_print, words[0]); + for(i = 1; i < match;i++) { + strcat(to_print, " "); + strcat(to_print, words[i]); + } + statusline(ALERT, "Suggested Words : %s", to_print); + free(to_print); + } +} #ifndef NANO_TINY /* Toggle the mark. */ void do_mark(void) -- 2.7.4