nano-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nano-devel] [PATCH] new feature: functions to jump to previous or follo


From: Benno Schulenberg
Subject: [Nano-devel] [PATCH] new feature: functions to jump to previous or following block of text
Date: Thu, 21 Jul 2016 19:48:48 +0200

And hard-bind the keys Ctrl+Up and Ctrl+Down to these functions.

Unlike the paragraph-jumping code, these new functions disregard
any indentation, treating only blank lines as separators.  They
also do an automatic smart home when that option is set.

This fulfills https://savannah.gnu.org/bugs/?48291.
---
 doc/man/nanorc.5      |  7 +++++++
 doc/texinfo/nano.texi |  7 +++++++
 src/global.c          | 21 +++++++++++++++++++++
 src/move.c            | 42 ++++++++++++++++++++++++++++++++++++++++++
 src/nano.c            |  8 +++++++-
 src/nano.h            |  2 ++
 src/proto.h           |  5 +++++
 src/winio.c           | 16 ++++++++++++----
 8 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/doc/man/nanorc.5 b/doc/man/nanorc.5
index 7c26b59..c9279c4 100644
--- a/doc/man/nanorc.5
+++ b/doc/man/nanorc.5
@@ -510,6 +510,13 @@ Moves the cursor to the beginning of the current paragraph.
 .B endpara
 Moves the cursor to the end of the current paragraph.
 .TP
+.B prevblock
+Moves the cursor to the beginning of the current or preceding block of text.
+(Blocks are separated by one or more blank lines.)
+.TP
+.B nextblock
+Moves the cursor to the beginning of the next block of text.
+.TP
 .B prevpage
 Goes up one screenful.
 .TP
diff --git a/doc/texinfo/nano.texi b/doc/texinfo/nano.texi
index 509d749..fdc5ae3 100644
--- a/doc/texinfo/nano.texi
+++ b/doc/texinfo/nano.texi
@@ -1102,6 +1102,13 @@ Moves the cursor to the beginning of the current 
paragraph.
 @item endpara
 Moves the cursor to the end of the current paragraph.
 
address@hidden prevblock
+Moves the cursor to the beginning of the current or preceding block of text.
+(Blocks are separated by one or more blank lines.)
+
address@hidden nextblock
+Moves the cursor to the beginning of the next block of text.
+
 @item prevpage
 Goes up one screenful.
 
diff --git a/src/global.c b/src/global.c
index ca7d4e1..e2d8749 100644
--- a/src/global.c
+++ b/src/global.c
@@ -46,6 +46,8 @@ message_type lastmessage = HUSH;
 #ifndef NANO_TINY
 int controlleft = CONTROL_LEFT;
 int controlright = CONTROL_RIGHT;
+int controlup = CONTROL_UP;
+int controldown = CONTROL_DOWN;
 #endif
 
 #ifndef DISABLE_WRAPJUSTIFY
@@ -573,6 +575,10 @@ void shortcut_init(void)
     const char *nano_nextline_msg = N_("Go to next line");
     const char *nano_home_msg = N_("Go to beginning of current line");
     const char *nano_end_msg = N_("Go to end of current line");
+#ifndef NANO_TINY
+    const char *nano_prevblock_msg = N_("Go to previous block of text");
+    const char *nano_nextblock_msg = N_("Go to next block of text");
+#endif
 #ifndef DISABLE_JUSTIFY
     const char *nano_parabegin_msg =
        N_("Go to beginning of paragraph; then of previous paragraph");
@@ -872,6 +878,13 @@ void shortcut_init(void)
     add_to_funcs(do_down_void, MMAIN|MBROWSER,
        next_line_tag, IFSCHELP(nano_nextline_msg), BLANKAFTER, VIEW);
 
+#ifndef NANO_TINY
+    add_to_funcs(do_prev_block, MMAIN,
+       N_("Prev Block"), IFSCHELP(nano_prevblock_msg), TOGETHER, VIEW);
+    add_to_funcs(do_next_block, MMAIN,
+       N_("Next Block"), IFSCHELP(nano_nextblock_msg), TOGETHER, VIEW);
+#endif
+
 #ifndef DISABLE_JUSTIFY
     add_to_funcs(do_para_begin_void, MMAIN|MWHEREIS,
        N_("Beg of Par"), IFSCHELP(nano_parabegin_msg), TOGETHER, VIEW);
@@ -1133,6 +1146,10 @@ void shortcut_init(void)
     add_to_sclist(MMAIN|MHELP|MBROWSER, "Up", do_up_void, 0);
     add_to_sclist(MMAIN|MHELP|MBROWSER, "^N", do_down_void, 0);
     add_to_sclist(MMAIN|MHELP|MBROWSER, "Down", do_down_void, 0);
+#ifndef NANO_TINY
+    add_to_sclist(MMAIN, "M-7", do_prev_block, 0);
+    add_to_sclist(MMAIN, "M-8", do_next_block, 0);
+#endif
 #ifndef DISABLE_JUSTIFY
     add_to_sclist(MMAIN, "M-(", do_para_begin_void, 0);
     add_to_sclist(MMAIN, "M-9", do_para_begin_void, 0);
@@ -1453,6 +1470,10 @@ sc *strtosc(const char *input)
        s->scfunc = do_cut_prev_word;
     else if (!strcasecmp(input, "cutwordright"))
        s->scfunc = do_cut_next_word;
+    else if (!strcasecmp(input, "prevblock"))
+       s->scfunc = do_prev_block;
+    else if (!strcasecmp(input, "nextblock"))
+       s->scfunc = do_next_block;
     else if (!strcasecmp(input, "findbracket"))
        s->scfunc = do_find_bracket;
     else if (!strcasecmp(input, "wordcount"))
diff --git a/src/move.c b/src/move.c
index 2f234e5..9d3bd79 100644
--- a/src/move.c
+++ b/src/move.c
@@ -210,6 +210,48 @@ void do_para_end_void(void)
 #endif /* !DISABLE_JUSTIFY */
 
 #ifndef NANO_TINY
+/* Move to the preceding block of text in the file. */
+void do_prev_block(void)
+{
+    filestruct *was_current = openfile->current;
+    bool is_text = FALSE, seen_text = FALSE;
+
+    /* Skip backward until first blank line after some nonblank line(s). */
+    while (openfile->current->prev != NULL && (!seen_text || is_text)) {
+       openfile->current = openfile->current->prev;
+       is_text = !white_string(openfile->current->data);
+       seen_text = seen_text || is_text;
+    }
+
+    /* Step forward one line again if this one is blank. */
+    if (openfile->current->next != NULL &&
+               white_string(openfile->current->data))
+       openfile->current = openfile->current->next;
+
+    openfile->current_x = 0;
+    edit_redraw(was_current);
+    do_home();
+}
+
+/* Move to the next block of text in the file. */
+void do_next_block(void)
+{
+    filestruct *was_current = openfile->current;
+    bool is_white = white_string(openfile->current->data);
+    bool seen_white = is_white;
+
+    /* Skip forward until first nonblank line after some blank line(s). */
+    while (openfile->current->next != NULL && (!seen_white || is_white)) {
+       openfile->current = openfile->current->next;
+       is_white = white_string(openfile->current->data);
+       seen_white = seen_white || is_white;
+    }
+
+    openfile->current_x = 0;
+    edit_redraw(was_current);
+    do_home();
+}
+
 /* Move to the previous word in the file.  If allow_punct is TRUE, treat
  * punctuation as part of a word.  If allow_update is TRUE, update the
  * screen afterwards. */
diff --git a/src/nano.c b/src/nano.c
index d6846b7..74e1e60 100644
--- a/src/nano.c
+++ b/src/nano.c
@@ -2527,13 +2527,19 @@ int main(int argc, char **argv)
 
 #if !defined(NANO_TINY) && defined(HAVE_KEY_DEFINED)
     const char *keyvalue;
-    /* Ask ncurses for the key codes for Control+Left and Control+Right. */
+    /* Ask ncurses for the key codes for Control+Left/Right/Up/Down. */
     keyvalue = tigetstr("kLFT5");
     if (keyvalue != 0 && keyvalue != (char *)-1)
        controlleft = key_defined(keyvalue);
     keyvalue = tigetstr("kRIT5");
     if (keyvalue != 0 && keyvalue != (char *)-1)
        controlright = key_defined(keyvalue);
+    keyvalue = tigetstr("kUP5");
+    if (keyvalue != 0 && keyvalue != (char *)-1)
+       controlup = key_defined(keyvalue);
+    keyvalue = tigetstr("kDN5");
+    if (keyvalue != 0 && keyvalue != (char *)-1)
+       controldown = key_defined(keyvalue);
 #endif
 
 #ifndef USE_SLANG
diff --git a/src/nano.h b/src/nano.h
index ddab2a9..e4c90fc 100644
--- a/src/nano.h
+++ b/src/nano.h
@@ -560,6 +560,8 @@ enum
 /* Codes for "modified" Arrow keys, beyond KEY_MAX of ncurses. */
 #define CONTROL_LEFT 0x401
 #define CONTROL_RIGHT 0x402
+#define CONTROL_UP 0x403
+#define CONTROL_DOWN 0x404
 
 #ifndef NANO_TINY
 /* An imaginary key for when we get a SIGWINCH (window resize). */
diff --git a/src/proto.h b/src/proto.h
index 9ce7fee..6b938cb 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -39,6 +39,8 @@ extern message_type lastmessage;
 #ifndef NANO_TINY
 extern int controlleft;
 extern int controlright;
+extern int controlup;
+extern int controldown;
 #endif
 
 #ifndef DISABLE_WRAPJUSTIFY
@@ -397,6 +399,8 @@ void do_para_end(bool allow_update);
 void do_para_end_void(void);
 #endif
 #ifndef NANO_TINY
+void do_prev_block(void);
+void do_next_block(void);
 void do_prev_word(bool allow_punct, bool allow_update);
 void do_prev_word_void(void);
 bool do_next_word(bool allow_punct, bool allow_update);
@@ -647,6 +651,7 @@ void do_tab(void);
 void do_indent(ssize_t cols);
 void do_indent_void(void);
 void do_unindent(void);
+bool white_string(const char *s);
 void do_undo(void);
 void do_redo(void);
 #endif
diff --git a/src/winio.c b/src/winio.c
index 800e1b9..c54776b 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -638,6 +638,10 @@ int parse_kbinput(WINDOW *win)
            retval = sc_seq_or(do_prev_word_void, 0);
        else if (retval == controlright)
            retval = sc_seq_or(do_next_word_void, 0);
+       else if (retval == controlup)
+           retval = sc_seq_or(do_prev_block, 0);
+       else if (retval == controldown)
+           retval = sc_seq_or(do_next_block, 0);
 #endif
 
        /* If our result is an extended keypad value (i.e. a value
@@ -699,8 +703,9 @@ int convert_sequence(const int *seq, size_t seq_len)
                if (seq_len >= 5) {
                    switch (seq[4]) {
                        case 'A': /* Esc O 1 ; 5 A == Ctrl-Up on Terminal. */
+                           return CONTROL_UP;
                        case 'B': /* Esc O 1 ; 5 B == Ctrl-Down on Terminal. */
-                           return arrow_from_abcd(seq[4]);
+                           return CONTROL_DOWN;
                        case 'C': /* Esc O 1 ; 5 C == Ctrl-Right on Terminal. */
                            return CONTROL_RIGHT;
                        case 'D': /* Esc O 1 ; 5 D == Ctrl-Left on Terminal. */
@@ -769,8 +774,9 @@ int convert_sequence(const int *seq, size_t seq_len)
                    case 'Y': /* Esc O Y == F10 on Mach console. */
                        return KEY_F(10);
                    case 'a': /* Esc O a == Ctrl-Up on rxvt. */
+                       return CONTROL_UP;
                    case 'b': /* Esc O b == Ctrl-Down on rxvt. */
-                       return arrow_from_abcd(seq[1]);
+                       return CONTROL_DOWN;
                    case 'c': /* Esc O c == Ctrl-Right on rxvt. */
                        return CONTROL_RIGHT;
                    case 'd': /* Esc O d == Ctrl-Left on rxvt. */
@@ -844,8 +850,9 @@ int convert_sequence(const int *seq, size_t seq_len)
            case 'o':
                switch (seq[1]) {
                    case 'a': /* Esc o a == Ctrl-Up on Eterm. */
+                       return CONTROL_UP;
                    case 'b': /* Esc o b == Ctrl-Down on Eterm. */
-                       return arrow_from_abcd(seq[1]);
+                       return CONTROL_DOWN;
                    case 'c': /* Esc o c == Ctrl-Right on Eterm. */
                        return CONTROL_RIGHT;
                    case 'd': /* Esc o d == Ctrl-Left on Eterm. */
@@ -898,8 +905,9 @@ int convert_sequence(const int *seq, size_t seq_len)
                if (seq_len >= 5) {
                    switch (seq[4]) {
                        case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on xterm. */
+                           return CONTROL_UP;
                        case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on xterm. */
-                           return arrow_from_abcd(seq[4]);
+                           return CONTROL_DOWN;
                        case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on xterm. */
                            return CONTROL_RIGHT;
                        case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on xterm. */
-- 
2.9.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]