From f1000dc0002ec742eb7ac3a05118e3b09ad6c3d6 Mon Sep 17 00:00:00 2001 From: Rishabh Dave Date: Tue, 25 Oct 2016 21:26:12 +0530 Subject: [PATCH] feature: add search facility to help Allow user to search all help text with ^W. This accomplishes https://savannah.gnu.org/bugs/?28994. Signed-off-by: Rishabh Dave --- src/files.c | 20 +++++--- src/global.c | 28 +++++------ src/help.c | 158 ++++++++++++++++++++++++++++++++++------------------------- src/nano.c | 7 +-- src/nano.h | 1 + src/prompt.c | 10 +++- src/search.c | 4 +- src/winio.c | 13 +++-- 8 files changed, 141 insertions(+), 100 deletions(-) diff --git a/src/files.c b/src/files.c index a4ac750..d5f7961 100644 --- a/src/files.c +++ b/src/files.c @@ -486,7 +486,7 @@ bool open_buffer(const char *filename, bool undoable) /* If the filename isn't blank, and we are not in NOREAD_MODE, * open the file. Otherwise, treat it as a new file. */ rc = (filename[0] != '\0' && !ISSET(NOREAD_MODE)) ? - open_file(realname, new_buffer, FALSE, &f) : -2; + open_file(realname, new_buffer, currmenu == MHELP, &f) : -2; /* If we have a file, and we're loading into a new buffer, update * the filename. */ @@ -553,8 +553,10 @@ void replace_buffer(const char *filename) /* Update the screen to account for the current buffer. */ void display_buffer(void) { - /* Update the titlebar, since the filename may have changed. */ - titlebar(NULL); + /* Update the titlebar, since the filename may have changed. In case + * of MHELP, titlebar() in done in help.c. */ + if (currmenu != MHELP) + titlebar(NULL); #ifndef DISABLE_COLOR /* Make sure we're using the buffer's associated colors. */ @@ -594,9 +596,10 @@ void switch_to_prevnext_buffer(bool to_next) display_buffer(); /* Indicate the switch on the statusbar. */ - statusline(HUSH, _("Switched to %s"), - ((openfile->filename[0] == '\0') ? - _("New Buffer") : openfile->filename)); + if (currmenu != MHELP) + statusline(HUSH, _("Switched to %s"), + ((openfile->filename[0] == '\0') ? + _("New Buffer") : openfile->filename)); #ifdef DEBUG dump_filestruct(openfile->current); @@ -911,6 +914,9 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable, bool checkw * file we inserted. */ openfile->placewewant = xplustabs(); + if (currmenu == MHELP) + return; + if (!writable) statusline(ALERT, "File '%s' is unwritable", filename); #ifndef NANO_TINY @@ -1010,7 +1016,7 @@ int open_file(const char *filename, bool newfie, bool quiet, FILE **f) if (*f == NULL) { statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno)); close(fd); - } else + } else if (currmenu != MHELP) statusbar(_("Reading File")); } diff --git a/src/global.c b/src/global.c index dd2e71a..8f3bbaa 100644 --- a/src/global.c +++ b/src/global.c @@ -655,7 +655,7 @@ void shortcut_init(void) /* TRANSLATORS: Try to keep the following strings at most 10 characters. */ N_("Get Help"), IFSCHELP(nano_help_msg), TOGETHER, VIEW); - add_to_funcs(do_cancel, ((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), + add_to_funcs(do_cancel, ((MMOST & ~MMAIN & ~MBROWSER) | MYESNO | MFINDINHELP), N_("Cancel"), IFSCHELP(nano_cancel_msg), BLANKAFTER, VIEW); add_to_funcs(do_exit, MMAIN, @@ -694,7 +694,7 @@ void shortcut_init(void) #endif } - add_to_funcs(do_search, MMAIN, + add_to_funcs(do_search, MMAIN|MHELP, whereis_tag, IFSCHELP(nano_whereis_msg), TOGETHER, VIEW); add_to_funcs(do_replace, MMAIN, @@ -713,8 +713,6 @@ void shortcut_init(void) * because the help viewer does not have a help text. */ add_to_funcs(do_exit, MHELP, exit_tag, "x", 0, VIEW); - add_to_funcs(total_refresh, MHELP, refresh_tag, "x", 0, VIEW); - add_to_funcs(do_up_void, MHELP, prev_line_tag, "x", 0, VIEW); add_to_funcs(do_down_void, MHELP, next_line_tag, "x" , 0, VIEW); #endif @@ -754,7 +752,7 @@ void shortcut_init(void) defined(DISABLE_JUSTIFY) && defined(DISABLE_SPELLER) && defined(DISABLE_COLOR)) /* Conditionally placing this one here or further on, to keep the * help items nicely paired in most conditions. */ - add_to_funcs(do_gotolinecolumn_void, MMAIN, + add_to_funcs(do_gotolinecolumn_void, MMAIN|MFINDINHELP, gotoline_tag, IFSCHELP(nano_gotoline_msg), BLANKAFTER, VIEW); #endif @@ -786,9 +784,9 @@ void shortcut_init(void) add_to_funcs(do_page_down, MMAIN|MHELP, next_page_tag, IFSCHELP(nano_nextpage_msg), TOGETHER, VIEW); - add_to_funcs(do_first_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, + add_to_funcs(do_first_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MFINDINHELP, N_("First Line"), IFSCHELP(nano_firstline_msg), TOGETHER, VIEW); - add_to_funcs(do_last_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, + add_to_funcs(do_last_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MFINDINHELP, N_("Last Line"), IFSCHELP(nano_lastline_msg), BLANKAFTER, VIEW); #ifndef NANO_TINY @@ -941,10 +939,10 @@ void shortcut_init(void) #ifndef DISABLE_HISTORIES add_to_funcs(get_history_older_void, - (MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE), + (MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP), N_("PrevHstory"), IFSCHELP(nano_prev_history_msg), TOGETHER, VIEW); add_to_funcs(get_history_newer_void, - (MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE), + (MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP), N_("NextHstory"), IFSCHELP(nano_next_history_msg), BLANKAFTER, VIEW); #endif @@ -1045,8 +1043,8 @@ void shortcut_init(void) add_to_sclist(MMAIN, "^R", 0, do_insertfile_void, 0); add_to_sclist(MMAIN, "F5", 0, do_insertfile_void, 0); add_to_sclist(MMAIN, "Ins", 0, do_insertfile_void, 0); - add_to_sclist(MMAIN|MBROWSER, "^W", 0, do_search, 0); - add_to_sclist(MMAIN|MBROWSER, "F6", 0, do_search, 0); + add_to_sclist(MMAIN|MBROWSER|MHELP, "^W", 0, do_search, 0); + add_to_sclist(MMAIN|MBROWSER|MHELP, "F6", 0, do_search, 0); add_to_sclist(MMAIN, "^\\", 0, do_replace, 0); add_to_sclist(MMAIN, "M-R", 0, do_replace, 0); add_to_sclist(MMAIN, "F14", 0, do_replace, 0); @@ -1203,19 +1201,19 @@ void shortcut_init(void) add_to_sclist(MMAIN, "^Q", 0, xon_complaint, 0); add_to_sclist(MMAIN, "^S", 0, xoff_complaint, 0); - add_to_sclist(((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), "^C", 0, do_cancel, 0); + add_to_sclist(((MMOST & ~MMAIN & ~MBROWSER) | MYESNO | MFINDINHELP), "^C", 0, do_cancel, 0); add_to_sclist(MWHEREIS|MREPLACE, "M-C", 0, case_sens_void, 0); add_to_sclist(MWHEREIS|MREPLACE, "M-R", 0, regexp_void, 0); add_to_sclist(MWHEREIS|MREPLACE, "M-B", 0, backwards_void, 0); add_to_sclist(MWHEREIS|MREPLACE, "^R", 0, flip_replace_void, 0); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, "^Y", 0, do_first_line, 0); - add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, "^V", 0, do_last_line, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MFINDINHELP, "^Y", 0, do_first_line, 0); + add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MFINDINHELP, "^V", 0, do_last_line, 0); #ifndef DISABLE_JUSTIFY add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^W", 0, do_para_begin_void, 0); add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^O", 0, do_para_end_void, 0); #endif - add_to_sclist(MWHEREIS, "^T", 0, do_gotolinecolumn_void, 0); + add_to_sclist(MWHEREIS|MFINDINHELP, "^T", 0, do_gotolinecolumn_void, 0); add_to_sclist(MGOTOLINE, "^T", 0, gototext_void, 0); #ifndef DISABLE_HISTORIES add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "^P", 0, get_history_older_void, 0); diff --git a/src/help.c b/src/help.c index b694192..25e76ed 100644 --- a/src/help.c +++ b/src/help.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifndef DISABLE_HELP @@ -40,31 +41,56 @@ void do_help(void) { int kbinput = ERR; bool old_no_help = ISSET(NO_HELP); - size_t line = 0; - /* The line number in help_text of the first displayed help - * line. This variable is zero-based. */ - size_t last_line = 0; - /* The line number in help_text of the last help line. This - * variable is zero-based. */ int oldmenu = currmenu; /* The menu we were called from. */ - const char *ptr; - /* The current line of the help text. */ - size_t old_line = (size_t)-1; - /* The line we were on before the current line. */ functionptrtype func; /* The function of the key the user typed in. */ + int saved_margin = 0; + /* For avoiding the line numbers on the help screen. */ + FILE *fp; + char *tempfilename = NULL; + char *title = charalloc(MAX_BUF_SIZE * sizeof(char)); + /* Title of the help text. */ + int line_size; + const char *p; - /* Don't show a cursor in the help screen. */ - curs_set(0); - blank_edit(); blank_statusbar(); + tempfilename = safe_tempfile(&fp); + if (tempfilename == NULL) { + statusline(ALERT, _("Error writing temp file: %s"), strerror(errno)); + return; + } + /* Set help_text as the string to display. */ help_init(); assert(help_text != NULL); + help_text[strlen(help_text)] = '\0'; + p = help_text; + line_size = break_line(p, 74, TRUE); + strncpy(title, p, line_size); + title[line_size] = '\0'; + p += line_size; + line_size = 0; + while (*p == '\n') + ++p; + + while (strlen(p) > 0) { + line_size = help_line_len(p); + fwrite(p, sizeof(char), line_size, fp); + p += line_size; + + if (p < end_of_intro && *p != '\n') + fwrite("\n", sizeof(char), 1, fp); + while (*p == '\n') { + fwrite("\n", sizeof(char), 1, fp); + ++p; + } + } + fclose(fp); + if (ISSET(NO_HELP)) { /* Make sure that the help screen's shortcut list will actually * be displayed. */ @@ -75,48 +101,26 @@ void do_help(void) bottombars(MHELP); wnoutrefresh(bottomwin); - while (TRUE) { - size_t i; - - ptr = help_text; - - /* Find the line number of the last line of the help text. */ - for (last_line = 0; *ptr != '\0'; last_line++) { - ptr += help_line_len(ptr); - if (*ptr == '\n') - ptr++; - } - - if (last_line > 0) - last_line--; - - /* Redisplay if the text was scrolled or an invalid key was pressed. */ - if (line != old_line || kbinput == ERR) { - blank_edit(); - - ptr = help_text; - - /* Advance in the text to the first line to be displayed. */ - for (i = 0; i < line; i++) { - ptr += help_line_len(ptr); - if (*ptr == '\n') - ptr++; - } - - /* Now display as many lines as the window will hold. */ - for (i = 0; i < editwinrows && *ptr != '\0'; i++) { - size_t j = help_line_len(ptr); +#ifdef ENABLE_LINENUMBERS + if (ISSET(LINE_NUMBERS)) { + saved_margin = margin; + margin = 0; + UNSET(LINE_NUMBERS); + } +#endif - mvwaddnstr(edit, i, 0, ptr, j); - ptr += j; - if (*ptr == '\n') - ptr++; - } - } + if (!ISSET(MULTIBUFFER)) { + SET(MULTIBUFFER); + open_buffer(tempfilename, FALSE); + UNSET(MULTIBUFFER); + } else + open_buffer(tempfilename, FALSE); - wnoutrefresh(edit); + display_buffer(); + titlebar(title); - old_line = line; + while (TRUE) { + edit_refresh(); lastmessage = HUSH; @@ -128,7 +132,6 @@ void do_help(void) continue; /* Redraw the screen. */ } #endif - #ifndef DISABLE_MOUSE if (kbinput == KEY_MOUSE) { int mouse_x, mouse_y; @@ -142,31 +145,47 @@ void do_help(void) if (func == total_refresh) { total_redraw(); } else if (func == do_up_void) { - if (line > 0) - line--; + do_up(FALSE); } else if (func == do_down_void) { - if (line + (editwinrows - 1) < last_line) - line++; + do_down(FALSE); } else if (func == do_page_up) { - if (line > editwinrows - 2) - line -= editwinrows - 2; - else - line = 0; + do_page_up(); } else if (func == do_page_down) { - if (line + (editwinrows - 1) < last_line) - line += editwinrows - 2; + do_page_down(); } else if (func == do_first_line) { - line = 0; + do_first_line(); } else if (func == do_last_line) { - if (line + (editwinrows - 1) < last_line) - line = last_line - (editwinrows - 1); + do_last_line(); } else if (func == do_exit) { /* Exit from the help viewer. */ + close_buffer(); break; - } else + } else if (func == do_search) { + if (answer != NULL) { + char *answer_copy = strdup(answer); + do_search(); + answer = mallocstrcpy(answer, answer_copy); + free(answer_copy); + } else + do_search(); + bottombars(MHELP); + wnoutrefresh(bottomwin); + /* No text can be entered at help screen. */ + } else if ((kbinput >= '0' && kbinput <= '9') || + (kbinput >= 'a' && kbinput <= 'z') || + (kbinput >= 'A' && kbinput <= 'Z')) + ; + else unbound_key(kbinput); } +#ifdef ENABLE_LINENUMBERS + if (saved_margin != 0) { + margin = saved_margin; + SET(LINE_NUMBERS); + } +#endif + if (old_no_help) { blank_bottombars(); wnoutrefresh(bottomwin); @@ -183,6 +202,9 @@ void do_help(void) #endif edit_refresh(); + remove(tempfilename); + free(tempfilename); + free(title); /* We're exiting from the help screen. */ free(help_text); } @@ -503,7 +525,7 @@ size_t help_line_len(const char *ptr) /* Full length of the line, until the first newline. */ /* Avoid overwide paragraphs in the introductory text. */ - if (ptr < end_of_intro && COLS > 74) + if (COLS > 74) wrapping_point = 74; wrap_location = break_line(ptr, wrapping_point, TRUE); diff --git a/src/nano.c b/src/nano.c index c975112..07189e4 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1442,8 +1442,9 @@ void do_toggle(int flag) ) enabled = !enabled; - statusline(HUSH, "%s %s", _(flagtostr(flag)), - enabled ? _("enabled") : _("disabled")); + if (currmenu != MHELP) + statusline(HUSH, "%s %s", _(flagtostr(flag)), + enabled ? _("enabled") : _("disabled")); } /* Bleh. */ @@ -1578,7 +1579,7 @@ void unbound_key(int code) statusline(ALERT, _("Unbound key: M-%c"), toupper(code)); } else if (code < 0x20) statusline(ALERT, _("Unbound key: ^%c"), code + 0x40); - else + else if (currmenu != MHELP) statusline(ALERT, _("Unbound key: %c"), code); } diff --git a/src/nano.h b/src/nano.h index 93ec5e1..e778ee4 100644 --- a/src/nano.h +++ b/src/nano.h @@ -557,6 +557,7 @@ enum #define MGOTODIR (1<<12) #define MYESNO (1<<13) #define MLINTER (1<<14) +#define MFINDINHELP (1<<15) /* This is an abbreviation for all menus except Help and YesNo. */ #define MMOST (MMAIN|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE|MWRITEFILE|MINSERTFILE|\ MEXTCMD|MBROWSER|MWHEREISFILE|MGOTODIR|MSPELL|MLINTER) diff --git a/src/prompt.c b/src/prompt.c index 34e7b4c..65a9314 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -662,9 +662,17 @@ int do_prompt(bool allow_tabs, #endif /* Save a possible current statusbar x position. */ size_t was_statusbar_x = statusbar_x; + char *prompt_save = NULL; + /* In case we need prompt again before completing previous one, + * above variables become useful. */ bottombars(menu); + if (prompt != NULL) { + prompt_save = strdup(prompt); + free(prompt); + } + answer = mallocstrcpy(answer, curranswer); #ifndef NANO_TINY @@ -687,7 +695,7 @@ int do_prompt(bool allow_tabs, refresh_func); free(prompt); - prompt = NULL; + prompt = prompt_save; #ifndef NANO_TINY if (retval == KEY_WINCH) diff --git a/src/search.c b/src/search.c index 8a7b9b1..67b699e 100644 --- a/src/search.c +++ b/src/search.c @@ -126,6 +126,8 @@ int search_init(bool replacing, bool use_answer) static char *backupstring = NULL; /* The search string we'll be using. */ functionptrtype func; + int menu = ((currmenu == MHELP) ? MFINDINHELP : + (replacing ? MREPLACE : MWHEREIS)); /* If use_answer is TRUE, set backupstring to answer and get out. */ if (use_answer) { @@ -154,7 +156,7 @@ int search_init(bool replacing, bool use_answer) #ifndef DISABLE_TABCOMP TRUE, #endif - replacing ? MREPLACE : MWHEREIS, backupstring, + menu, backupstring, #ifndef DISABLE_HISTORIES &search_history, #endif diff --git a/src/winio.c b/src/winio.c index 18f98f0..31fbc2b 100644 --- a/src/winio.c +++ b/src/winio.c @@ -1913,10 +1913,11 @@ char *display_string(const char *buf, size_t start_col, size_t span, /* If path is NULL, we're in normal editing mode, so display the current * version of nano, the current filename, and whether the current file - * has been modified on the titlebar. If path isn't NULL, we're in the - * file browser, and path contains the directory to start the file - * browser in, so display the current version of nano and the contents - * of path on the titlebar. */ + * has been modified on the titlebar. If path isn't NULL, either we're + * in the file browser or help. If we are in file browser, path contains + * the directory to start the file browser in, so display the current + * version of nano and the contents of path on the titlebar. If we are + * in help, path contains the name of title of the help text. */ void titlebar(const char *path) { size_t verlen, prefixlen, pathlen, statelen; @@ -1948,7 +1949,9 @@ void titlebar(const char *path) /* Figure out the path, prefix and state strings. */ #ifndef DISABLE_BROWSER - if (path != NULL) + if (currmenu == MHELP && path != NULL) + state = _("View"); + else if (path != NULL) prefix = _("DIR:"); else #endif -- 2.7.4