]> git.wh0rd.org Git - nano.git/commitdiff
add paragraph searching ability
authorDavid Lawrence Ramsey <pooka109@gmail.com>
Thu, 4 Sep 2003 20:25:29 +0000 (20:25 +0000)
committerDavid Lawrence Ramsey <pooka109@gmail.com>
Thu, 4 Sep 2003 20:25:29 +0000 (20:25 +0000)
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1538 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

ChangeLog
TODO
global.c
nano.c
nano.h
proto.h
winio.c

index 6716e3bec982f9a759925d893f064909a40daf29..2e551ef4aa7c2c53efee478e66bc2911e07cb35b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,12 @@ CVS code -
        - Add the ability to repeat the last search without prompting
          via Meta-W, and move the line wrapping toggle to Meta-L.  New
          function do_research(). (Wouter van Hemel)
+       - Added the ability to move to the beginning or end of the
+         paragraph, which Pico has via ^W^W (previous paragraph)
+         and ^W^O (next paragraph).  Modifications to do_justify(),
+         new functions do_para_operation(), do_para_begin(), and
+         do_para_end().  Note that the last three functions are
+         disabled if justification is disabled. (DLR)
 - files.c:
   do_browser()
        - Some of the Pico compatibility options in the file browser
diff --git a/TODO b/TODO
index 09698d2dfb004276943d4eb512d33bf9c0d02b46..8c6f11d2f8fa0051d6d93504f7ac363f0f71f9c7 100644 (file)
--- a/TODO
+++ b/TODO
@@ -3,7 +3,7 @@ TODO file (? means the feature may be implemented, but not definitely)
 
 For version 1.4:
 - UTF-8 support.
-- Support for Pico's paragraph searching ability.
+- Support for Pico's paragraph searching ability. [DONE]
 - Undo/Redo key?
 - Rebindable keys?
 - Keystroke to implement "Add next sequence as raw" like vi's ^V.
index 648856b398016c12fe76355a91120308ee026bf7..6389239139d1f8c97b57a260b6aa16c85f769811 100644 (file)
--- a/global.c
+++ b/global.c
@@ -337,7 +337,8 @@ void shortcut_init(int unjustify)
        "", *nano_gotodir_msg = "", *nano_case_msg =
        "", *nano_reverse_msg = "", *nano_execute_msg =
        "", *nano_dos_msg = "", *nano_mac_msg =
-       "", *nano_backup_msg = "", *nano_editstr_msg = "";
+       "", *nano_backup_msg = "", *nano_editstr_msg =
+       "", *nano_parabegin_msg = "", *nano_paraend_msg = "";
 
 #ifdef ENABLE_MULTIBUFFER
     const char *nano_openprev_msg = "", *nano_opennext_msg =
@@ -395,6 +396,8 @@ void shortcut_init(int unjustify)
     nano_mac_msg = _("Write file out in Mac format");
     nano_backup_msg = _("Back up original file when saving");
     nano_editstr_msg = _("Edit the previous search/replace strings");
+    nano_parabegin_msg = _("Go to the beginning of the current paragraph");
+    nano_paraend_msg = _("Go to the end of the current paragraph");
 #ifdef HAVE_REGEX_H
     nano_regexp_msg = _("Use regular expressions");
     nano_bracket_msg = _("Find other bracket");
@@ -585,44 +588,54 @@ void shortcut_init(int unjustify)
     sc_init_one(&whereis_list, NANO_HELP_KEY, _("Get Help"),
                IFHELP(nano_help_msg, 0), 0, 0, VIEW, do_help);
 
-    /* Translators: try to keep this string under 12 characters long */
+    /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, NANO_CANCEL_KEY, _("Cancel"),
                IFHELP(nano_cancel_msg, 0), 0, 0, VIEW, 0);
 
-    /* Translators: try to keep this string under 12 characters long */
+    /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, NANO_FIRSTLINE_KEY, _("First Line"),
                IFHELP(nano_firstline_msg, 0),
                0, 0, VIEW, do_first_line);
 
-    /* Translators: try to keep this string under 12 characters long */
+    /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, NANO_LASTLINE_KEY, _("Last Line"),
                IFHELP(nano_lastline_msg, 0), 0, 0, VIEW, do_last_line);
 
-    /* Translators: try to keep this string under 12 characters long */
+    /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, NANO_OTHERSEARCH_KEY, _("Replace"),
                IFHELP(nano_replace_msg, 0), 0, 0, VIEW, do_replace);
 
-    /* Translators: try to keep this string under 12 characters long */
+    /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, NANO_FROMSEARCHTOGOTO_KEY, _("Go To Line"),
                IFHELP(nano_goto_msg, 0), 0, 0, VIEW, do_gotoline_void);
 
+#ifndef DISABLE_JUSTIFY
+    /* Translators: try to keep this string under 10 characters long */
+    sc_init_one(&whereis_list, NANO_PARABEGIN_KEY, _("Beg of Par"),
+               IFHELP(nano_parabegin_msg, 0), 0, 0, VIEW, do_para_begin);
+
+    /* Translators: try to keep this string under 10 characters long */
+    sc_init_one(&whereis_list, NANO_PARAEND_KEY, _("End of Par"),
+               IFHELP(nano_paraend_msg, 0), 0, 0, VIEW, do_para_end);
+#endif
+
 #ifndef NANO_SMALL
-    /* Translators: try to keep this string under 12 characters long */
+    /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, TOGGLE_CASE_KEY, _("Case Sens"),
                IFHELP(nano_case_msg, 0), 0, 0, VIEW, 0);
 
-    /* Translators: try to keep this string under 12 characters long */
+    /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, TOGGLE_BACKWARDS_KEY, _("Direction"),
                IFHELP(nano_reverse_msg, 0), 0, 0, VIEW, 0);
 
 #ifdef HAVE_REGEX_H
-    /* Translators: try to keep this string under 12 characters long */
+    /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, TOGGLE_REGEXP_KEY, _("Regexp"),
                IFHELP(nano_regexp_msg, 0), 0, 0, VIEW, 0);
 #endif
 
 #ifndef NANO_SMALL
-    /* Translators: try to keep this string under 12 characters long */
+    /* Translators: try to keep this string under 10 characters long */
     sc_init_one(&whereis_list, KEY_UP, _("History"),
                IFHELP(nano_editstr_msg, 0), NANO_UP_KEY, 0, VIEW, 0);
 #endif
diff --git a/nano.c b/nano.c
index 202bab234c7844b75d70916b91f4fc7e22a7587e..65c9bcbeea01685940024ae636e4a61444836cc0 100644 (file)
--- a/nano.c
+++ b/nano.c
@@ -2244,17 +2244,17 @@ int break_line(const char *line, int goal, int force)
        space_loc++;
     return space_loc;
 }
-#endif /* !DISABLE_JUSTIFY */
 
-/* This function justifies the current paragraph. */
-int do_justify(void)
+/* This function performs operations on paragraphs: justify, go to
+ * beginning, and go to end. */
+int do_para_operation(int operation)
 {
-#ifdef DISABLE_JUSTIFY
-    nano_disabled_msg();
-    return 1;
-#else
-
-/* To explain the justifying algorithm, I first need to define some
+/* operation == 0 means we're justifying the paragraph, operation == 1
+ * means we're moving to the beginning line of the paragraph, and
+ * operation == 2 means we're moving to the ending line of the
+ * paragraph.
+ *
+ * To explain the justifying algorithm, I first need to define some
  * phrases about paragraphs and quotation:
  *   A line of text consists of a "quote part", followed by an
  *   "indentation part", followed by text.  The functions quote_length()
@@ -2314,6 +2314,10 @@ int do_justify(void)
     filestruct *line;  /* generic line of text */
     size_t i;          /* generic loop variable */
 
+    static int no_restart = 0;
+       /* whether we're blocking restarting when searching for the
+        * beginning line of the paragraph */
+
 #ifdef HAVE_REGEX_H
     regex_t qreg;      /* qreg is the compiled quotation regexp. 
                         * We no longer care about quotestr. */
@@ -2333,13 +2337,15 @@ int do_justify(void)
     /* Here is an assumption that is always true anyway. */
     assert(current != NULL);
 
+    current_x = 0;
+
+  restart_bps:
 /* Here we find the first line of the paragraph to justify.  If the
  * current line is in a paragraph, then we move back to the first line. 
  * Otherwise we move down to the first line that is in a paragraph. */
     quote_len = quote_length(IFREG(current->data, &qreg));
     indent_len = indent_length(current->data + quote_len);
 
-    current_x = 0;
     if (current->data[quote_len + indent_len] != '\0') {
        /* This line is part of a paragraph.  So we must search back to
         * the first line of this paragraph.  First we check items 1) and
@@ -2365,6 +2371,25 @@ int do_justify(void)
            current = current->prev;
            current_y--;
        }
+    } else if (operation == 1) {
+       /* This line is not part of a paragraph.  Move up until we get
+        * to a non "blank" line, and then move down once. */
+       do {
+           /* There is no previous paragraph, so nothing to move to. */
+           if (current->prev == NULL) {
+               placewewant = 0;
+               if (current_y < 0)
+                   edit_update(current, CENTER);
+               else
+                   edit_refresh();
+               return 0;
+           }
+           current = current->prev;
+           current_y--;
+           quote_len = quote_length(IFREG(current->data, &qreg));
+           indent_len = indent_length(current->data + quote_len);
+       } while (current->data[quote_len + indent_len] == '\0');
+       current = current->next;
     } else {
        /* This line is not part of a paragraph.  Move down until we get
         * to a non "blank" line. */
@@ -2410,12 +2435,29 @@ int do_justify(void)
        par_len++;
     }
 #ifdef HAVE_REGEX_H
-    /* We no longer need to check quotation. */
-    regfree(&qreg);
+    /* We no longer need to check quotation, unless we're searching for
+       the beginning of the paragraph. */
+    if (operation != 1)
+       regfree(&qreg);
 #endif
 /* Now par_len is the number of lines in this paragraph.  Should never
  * call quotes_match() or quote_length() again. */
 
+    /* If operation is nonzero, skip the justification, since we're only
+     * searching through the paragraph.  If operation is 2, move down the
+     * number of lines in the paragraph, so that we end up at the
+     * paragraph's end. */
+    if (operation != 0) {
+       if (operation == 2) {
+           while (par_len > 0) {
+               current = current->next;
+               current_y++;
+               par_len--;
+           }
+       }
+       goto skip_justify;
+    }
+
 /* Next step, we loop through the lines of this paragraph, justifying
  * each one individually. */
     SET(JUSTIFY_MODE);
@@ -2572,8 +2614,8 @@ int do_justify(void)
     }
     UNSET(JUSTIFY_MODE);
 
-/* We are now done justifying the paragraph.  There are cleanup things to
- * do, and we check for unjustify. */
+/* We are now done justifying the paragraph.  There are cleanup things
+ * to do, and we check for unjustify. */
 
     /* totlines, totsize, and current_y have been maintained above.  We
      * now set last_par_line to the new end of the paragraph, update
@@ -2586,6 +2628,67 @@ int do_justify(void)
        renumber(first_mod_line);
     }
 
+  skip_justify:
+    if (operation != 0) {
+       switch (operation) {
+           case 1:
+               /* We're on the same line we started on.  Search for the
+                * first non-"blank" line before the line we're on (if
+                * there is one), continually restart that search from
+                * the current position until we find a line that's part
+                * of a paragraph, and then search once more from there,
+                * so that we end up on the first line of that
+                * paragraph.  In the process, skip over lines
+                * consisting only of spacing characters, as searching
+                * for the end of the paragraph does.  Then update the
+                * screen. */
+               if (current != fileage && current == current_save &&
+                       !no_restart) {
+                   while (current->prev != NULL) {
+                       int j, j_space = 0;
+                       current = current->prev;
+                       current_y--;
+                       for (j = 0; j < strlen(current->data); j++) {
+                           if (isspace(current->data[j]))
+                               j_space++;
+                           else {
+                               j = -1;
+                               break;
+                           }
+                       }
+                       if (j != j_space && strlen(current->data) >=
+                               (quote_len + indent_len) &&
+                               current->data[quote_len + indent_len] != '\0') {
+                           no_restart = 1;
+                           break;
+                       }
+                   }
+                   goto restart_bps;
+               } else
+                   no_restart = 0;
+#ifdef HAVE_REGEX_H
+               /* We no longer need to check quotation, if we were
+                  searching for the beginning of the paragraph. */
+               regfree(&qreg);
+#endif
+               if (current_y < 0)
+                   edit_update(current, CENTER);
+               else
+                   edit_refresh();
+               break;
+           case 2:
+               /* We've already moved to the end of the paragraph.
+                * Update the screen. */
+               if (current_y > editwinrows - 1)
+                   edit_update(current, CENTER);
+               else
+                   edit_refresh();
+               break;
+       }
+       if (operation != 0)
+           return 0;
+    }
+
     if (current_y > editwinrows - 1)
        edit_update(current, CENTER);
     else
@@ -2663,9 +2766,31 @@ int do_justify(void)
     display_main_list();
 
     return 0;
+}
+#endif /* !DISABLE_JUSTIFY */
+
+int do_justify(void)
+{
+#ifdef DISABLE_JUSTIFY
+    nano_disabled_msg();
+    return 1;
+#else
+    return do_para_operation(0);
 #endif
 }
 
+#ifndef DISABLE_JUSTIFY
+int do_para_begin(void)
+{
+    return do_para_operation(1);
+}
+
+int do_para_end(void)
+{
+    return do_para_operation(2);
+}
+#endif
+
 int do_exit(void)
 {
     int i;
diff --git a/nano.h b/nano.h
index c5f729b21e79deeebd640e269c02f66c09af0039..25613a2f20f0f3fbff5b29cbf455068ec8ebf96c 100644 (file)
--- a/nano.h
+++ b/nano.h
@@ -389,6 +389,8 @@ know what you're doing */
 #define NANO_EXTCMD_KEY                NANO_CONTROL_X
 #define NANO_NEXTWORD_KEY      NANO_CONTROL_SPACE
 #define NANO_PREVWORD_KEY      NANO_ALT_SPACE
+#define NANO_PARABEGIN_KEY     NANO_CONTROL_W
+#define NANO_PARAEND_KEY       NANO_CONTROL_O
 
 #ifndef NANO_SMALL
 /* Toggles do not exist with NANO_SMALL. */
diff --git a/proto.h b/proto.h
index fcca1e4a9d4318e71065189f0ec908a5bb5d5df7..a341abbdec009a290422b831e83b6d41294fb321 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -311,8 +311,13 @@ filestruct *backup_lines(filestruct *first_line, size_t par_len,
                        size_t quote_len);
 int breakable(const char *line, int goal);
 int break_line(const char *line, int goal, int force);
+int do_para_operation(int operation);
 #endif /* !DISABLE_JUSTIFY */
 int do_justify(void);
+#ifndef DISABLE_JUSTIFY
+int do_para_begin(void);
+int do_para_end(void);
+#endif
 int do_exit(void);
 void signal_init(void);
 RETSIGTYPE handle_hupterm(int signal);
diff --git a/winio.c b/winio.c
index 4ebf3fb136004b57b76d5be6e0d448bda7a536ee..e88d1c13f51524e9a230a71bb891dd7d25b51e35 100644 (file)
--- a/winio.c
+++ b/winio.c
@@ -1447,6 +1447,16 @@ int statusq(int tabs, const shortcut *s, const char *def,
        do_last_line();
        resetstatuspos = 1;
        break;
+#ifndef DISABLE_JUSTIFY
+    case NANO_PARABEGIN_KEY:
+       do_para_begin();
+       resetstatuspos = 1;
+       break;
+    case NANO_PARAEND_KEY:
+       do_para_end();
+       resetstatuspos = 1;
+       break;
+#endif
     case NANO_CANCEL_KEY:
        ret = -1;
        resetstatuspos = 1;