bug-bash
[Top][All Lists]
Advanced

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

previous/next-screen-line (was: readline: How to unbind _all_ keys)


From: Henning
Subject: previous/next-screen-line (was: readline: How to unbind _all_ keys)
Date: Tue, 28 May 2019 10:04:08 +0200
User-agent: Mozilla/5.0 (Windows NT 6.3; rv:56.0) Gecko/20100101 Thunderbird/56.0

On 25/05/2019 11:14, Henning wrote:
On 24/05/2019 17:16, Chet Ramey wrote:

That's not in the distributed version of bash-5.0. If you're applying an
older cygwin patch, have you tried just building the distributed version?
Let's make sure that works.


Bang! It does. So sorry that I didn't have that idea myself. Especially
as I have never used the 'igncr' stuff anyway. I hope there won't
appear ther Windows related issues.

I'm going to explore things now. And I have been waiting for
{previous,next}-screen-line and several other things.

These two (*-screen-line) functions, to my disappointment, don't
work as I expected. They simply shift the cursor left/up or
right/down by COLUMNS characters. And that's seldom useful.

I am using multi-line commands to try out things, usually sed scripts;
while, until or for loops or the like. Once I'm satisfied I put things
into a function or script. Lines are seldom longer than 20 or 30
characters.

So I sat down and developed a solution using 'bind -x': The functions
below find the position on the current screen line and then set
READLINE_POINT to the respective position on the previous/next line.
The result is real vertical cursor movement. Exceptions:

1. if prev/next line is shorter than position in current line
   the cursor is placed at EOL of prev/next line.

2. if there's no prev/next line the cursor jumps to BOL/EOL and
   the terminal bell is rang.

3. if there are special characters like ^[ or ^? inserted literally
   with ^Q/^V in the way there may be a 1 character deviation.
   Similar with literal TABs.

4. My knowledge about and therefore my desire to deal with UTF8,
   Unicode, Multibyte or the like equals zero. So I can't help with that.


#-----------------------------
PreviousScreenLine() {
    local n=$'\n' A B R=$READLINE_LINE
    local -i      a b r=READLINE_POINT
    A=${R:0:r}                  # BOC -> point
    if [[ "$A" != *$n* ]]; then # if there's no previous line
       READLINE_POINT=0         #    go to BOC
       printf \\a               #    and ring terminal bell
    else
       B=${A##*$n}      b=${#B} # BOL -> point & length
       A=${A%$n*}               # lines before current
       B=${A##*$n}      a=${#B} # previous line & length
       ((a<b))       && b=a     # don't go beyond EOL
       A=${A%%+([^$n])} a=${#A} # beginning of prev line
       READLINE_POINT=$((a+b))
    fi; }

NextScreenLine() {
    local n=$'\n' A B R=$READLINE_LINE
    local -i      a b r=READLINE_POINT
    A=${R:r}          B=${R%$A} # point -> EOC, BOC -> point
    if [[ "$A" != *$n* ]]; then # if there's no next line
        READLINE_POINT=${#R}    #    go to EOC
        printf \\a              #    and ring terminal bell
    else
        B=${B##*$n}  b=${#B}    # BOL -> point & length
        A=${A#*$n}              # lines after current
        B=${A%%$n*}  a=${#B}    # next line & length
        ((a<b))   && b=a        # don't go beyond EOL
        A=${R%$A}    a=${#A}    # beginning of next line
        READLINE_POINT=$((a+b))
    fi; }

bind -x '"\e1;5A":PreviousScreenLine' # ^Up      Change to suit your
bind -x '"\e1;5B":NextScreenLine'     # ^Down    needs !!!
#---------------------------------

I would, of course, prefer this algorithm to be used by the two
readline functions. That would be much more resource saving.

By the way - shouldn't READLINE_POINT have the integer attribute set?

Henning



reply via email to

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