From 1adf551c41e87d691898100aa4ff286467e92090 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 | 24 +++++----
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, 139 insertions(+), 98 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..4f50fd2 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
@@ -764,7 +762,7 @@ void shortcut_init(void)
add_to_funcs(regexp_void, MWHEREIS|MREPLACE,
N_("Regexp"), IFSCHELP(nano_regexp_msg), TOGETHER, VIEW);
#endif
- add_to_funcs(backwards_void, MWHEREIS|MREPLACE,
+ add_to_funcs(backwards_void, MWHEREIS|MREPLACE|MFINDINHELP,
N_("Backwards"), IFSCHELP(nano_reverse_msg), TOGETHER, VIEW);
add_to_funcs(flip_replace_void, MWHEREIS,
@@ -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,11 +1201,11 @@ 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|MFINDINHELP, "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);
@@ -1215,7 +1213,7 @@ void shortcut_init(void)
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