new feature: functions to jump to previous or following block of text

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.
master
Benno Schulenberg 2016-06-25 15:16:52 +02:00
parent 8c7a38596d
commit c6dbcf91c3
8 changed files with 103 additions and 5 deletions

View File

@ -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

View File

@ -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.
@item prevblock
Moves the cursor to the beginning of the current or preceding block of text.
(Blocks are separated by one or more blank lines.)
@item nextblock
Moves the cursor to the beginning of the next block of text.
@item prevpage
Goes up one screenful.

View File

@ -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"))

View File

@ -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. */

View File

@ -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

View File

@ -564,6 +564,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). */

View File

@ -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

View File

@ -635,6 +635,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
@ -696,8 +700,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. */
@ -766,8 +771,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. */
@ -841,8 +847,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. */
@ -895,8 +902,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. */