Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mimicing Zsh behavior of nsearch (non-incremental prefix search) #101

Closed
rashil2000 opened this issue Apr 25, 2021 · 10 comments
Closed

Mimicing Zsh behavior of nsearch (non-incremental prefix search) #101

rashil2000 opened this issue Apr 25, 2021 · 10 comments
Labels
NYI/NewFeat Not yet implemented or New Feature

Comments

@rashil2000
Copy link

Hi,
Thanks for the great project!

I'd like to move away from Zsh, so ble.sh sounds very promising. However, I would like to mimic Zsh's default history searching behavior in ble.sh. See below:

zsh

(type the beginning of your command, and press Up/Down to browse the history lines that begin with the substring I type)

Below is the default behavior of ble.sh in bash:

bash

I would like to make it like Zsh. Specifically, I would like to:

  1. Remove/hide the nsearch info below my prompt
  2. I would like the cursor to move to the end of line while searching with Up/Down.
  3. If I don't find what I'm looking for in the history, I press Down key the same number of times I have pressed Up key. This brings me back to the string that I had typed (like 'pacman' in the GIF of Zsh above). But in ble.sh/bash, the whole line remains even after pressing Down key repeatedly.

I have put the following lines in my .bashrc

bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'

Any help would be appreciated.
Thanks in advance!!!

@akinomyoga
Copy link
Owner

akinomyoga commented Apr 26, 2021

Remove/hide the nsearch info below my prompt

Thank you for your suggestion! This is related to the discussion in #80 with @Alyetama yesterday. I'm now thinking of adding a new bleopt option bleopt nsearch_opts which is a colon-separated list of, e.g.,

  • hide-status (always hide the nsearch status of '(nsearch#COUNT: << !POS >>) `NEEDLE')
  • hide-status-on-empty (hide the status when the search string is empty)
  • move-on-empty (when the search string is empty, just move to the previous line instead of starting the non-incremental search)
  • move-on-single-key-empty (when the nsearch is called by a single-key binding and the search string is empty, just move to the previous line)

I would like the cursor to move to the end of line while searching with Up/Down.

OK, I'll consider an option for it. Actually, the purple "matched part" is highlighted as the current selection, so if the cursor position is simply moved to the end of the line, the entire line would be highlighted while nsearch. But maybe I can add a special selection so that the matched part is correctly highlighted. Which behavior do you prefer? 1) Highlight the entire line 2) Highlight only the matched part (the initial commandline content).

If I don't find what I'm looking for in the history, I press Down key the same number of times I have pressed Up key. This brings me back to the string that I had typed (like 'pacman' in the GIF of Zsh above). But in ble.sh/bash, the whole line remains even after pressing Down key repeatedly.

Actually, the current behavior is the imitation of Bash's behavior, but I agree that the behavior is not so friendly, so I'll consider the change.

I'm recently a kind of busy, so may take some time. There are several pending fixes of ble.sh, but I think I first try to support this one before the others. Thank you for your understanding.

@akinomyoga akinomyoga changed the title Mimicing Zsh behavior Mimicing Zsh behavior of nsearch (non-incremental prefix search) Apr 26, 2021
@rashil2000
Copy link
Author

I'm now thinking of adding a new bleopt option bleopt nsearch_opts which is a colon-separated list of...

That sounds like a great idea (I personally prefer the 3rd and 4th opts).

Which behavior do you prefer? 1) Highlight the entire line 2) Highlight only the matched part (the initial terminal content).

I think highlighting only the matched part would be more preferable. Highlighting the entire line would give the (false) impression that the entire line is being used in the search. Actually, I sometimes use PowerShell too, and PowerShell's behavior exactly matches Zsh's behavior - searching using only the substring upto the current cursor position, but also moving the cursor to the end when browsing through the matches.

Actually, the current behavior is the imitation of Bash's behavior, but I agree that the behavior is not so friendly, so I'll consider the change.

Thank you, that'll be awesome!

I'm recently a kind of busy, so may take some time. There are several pending fixes of ble.sh, but I think I first try to support this one before the others.

Please take your time! There's no hurry (from my side 😊). Good things do take time. Thanks again for ble.sh!!!

@rashil2000
Copy link
Author

rashil2000 commented Apr 27, 2021

I don't know if it's apparent from the Zsh GIF, but there's one more tiny detail: pressing Enter on any search item in Zsh straight up runs that command, whereas on ble.sh you have to press Enter twice (one to accept the search item, one to run it). The Zsh behavior is more seamless, in this case

@akinomyoga
Copy link
Owner

akinomyoga commented Apr 27, 2021

whereas on ble.sh you have to press Enter twice (one to accept the search item, one to run it

That's also discussed in #80 (comment), but it's intentional. If you want to immediately run the command, you can press C-j or C-RET. You can change the keybinding using ble-bind. I don't currently have a plan to change the current default behavior unless there is a convincing reason to change. Maybe I can instead add some description in Q&A or add an explicit bleopt option to change the behavior.

@rashil2000
Copy link
Author

rashil2000 commented Apr 28, 2021

ble-bind -m 'nsearch' -f 'RET' 'nsearch/accept-line'

I tried to issue this command but it didn't work, am I doing this wrong?

I also tried ble-bind -m 'nsearch' -f 'ESC' 'nsearch/cancel' to map Esc key for clearing search, but this also doesn't seem to work. Is there any other way to do this?

@akinomyoga
Copy link
Owner

akinomyoga commented Apr 28, 2021

As written in Manual §3.1/¶5,

Quoted from Manual §3.1/¶5: [...] These control characters (originally received as characters) are converted to keys C-@, C-a...C-z, C-[, C-\, C-], C-^, C-_ during decoding to key sequences, so normally they cannot appear directly in key sequences.

In terminals, raw bytes \000-\037 are used to encode C-@-C-_, so the "key RET" is usually transferred as C-m by the terminal unless your terminal explicitly encodes RET using the special key sequences of CSI ... u or CSI 2 7 ; ... ~. Similarly "key ESC" is transferred as C-[. "key TAB" is C-i. So you first want to try to bind them to C-m and C-[. For some rich terminals that distinguish RET/ESC from C-m/C-[, you could additionally set up the same keybindings for RET and ESC.

ble-bind -m 'nsearch' -f 'C-m' 'nsearch/accept-line'
ble-bind -m 'nsearch' -f 'RET' 'nsearch/accept-line'
ble-bind -m 'nsearch' -f 'C-[' 'nsearch/cancel'
ble-bind -m 'nsearch' -f 'ESC' 'nsearch/cancel'

When you want to bind a widget to C-[ (ESC), I recommend you to read §3.5. The byte ESC is also used to represent the Meta modifier of a key in terminals so is essentially ambiguous. ble.sh takes some heuristic approach to determine the role of ESC. You may want to also check bleopt decode_isolated_esc.

If you want to distinguish RET from C-m and assign different keybindings, you may use a terminal that sends distinct sequences of RET in §3.6 modifyOtherKeys mode. Or, if your terminal allows you to manually configure the escape sequence of each key, you may let it send \e[13;1u for RET, \e[27;1u for ESC, \e[9;1u for TAB, etc. (see also §3.6.3), but it will break other terminal applications that don't support modifyOtherKeys so you need to enable these settings only when ble.sh is active.

@rashil2000
Copy link
Author

Wow, thanks for such a detailed answer. C-m and C-[ work like a charm.

The byte ESC is also used to represent the Meta modifier of a key in terminals so is essentially ambiguous.

Thanks, will keep that in mind.

...you may use a terminal that sends distinct sequences of RET in §3.6 modifyOtherKeys mode...

For the most part, I'm using Windows Terminal, and as far as I know, there's no way to set key sequences in it yet.

@akinomyoga
Copy link
Owner

New options for nsearch widgets

@rashil2000 @Alyetama @carv-silva In the commit 9125795, I've implemented options of nsearch as an argument of nsearch widgets.

ble-bind -f up 'history-search-forward OPTS'
ble-bind -f down 'history-search-backward OPTS'

where OPTS is a colon-separated list of the following options:

  • hide-status ... do not show the nsearch status of (nsearch #N: << !M >>) `NEEDLE' (requested by @carv-silva (?) and @rashil2000)
  • immediate-accept ... the widget nsearch/exit---which is defautly bound to C-m and RET---immediately runs the command (requested by @Alyetama and @rashil2000)
  • action=ACTION ... specifies the type of action taken when the search string is matched to a history entry. ACTION is one of the following values:
    • goto (default) ... go to the history entry
    • load ... load the text of the history entry without moving the current history position. This is Bash's default behavior.
  • point=POINT ... specifies the cursor position after the action. POINT is one of the following values:
    • begin ... the beginning of the command line
    • end ... the end of the command line (@rashil2000's request)
    • match-begin ... the beginning of the matched part
    • match-end (default) ... the end of the matched part
  • empty=EMPTY ... specifies the special treatment on the empty command search
    • empty-search (default) ... starts nsearch with an empty string
    • hide-status ... starts nsearch with an empty string but do not show the nsearch status
    • previous-search ... starts nsearch with the previous search string
    • history-move ... just go to the previous/next history entry without starting the nsearch. The cursor position is set to the beginning of the command line to keep the string before the cursor empty.

Compared to the previous behavior the following two points are changed:

  • Now the default action on the match is changed from action=load (Bash-like) to action=goto (Zsh-like).
  • When the user presses down the same number of times as up (including the one used to enter the nsearch mode), it recovers the original command line (when it matches with the search string). (@rashil2000's suggestion)

nsearch of ble.sh default keybindings

For the default keybindings in ble.sh, C-x up, C-x C-p, C-x p, C-x <, etc., OPTS is empty.

nsearch from Readline user settings

bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'

The above Readline settings are now interpreted as the following ble.sh settings:

ble-bind -f up 'history-search-backward empty=history-move'
ble-bind -f down 'history-search-forward empty=history-move'

It seems that (naive) users are confused by the old behavior that ble.sh starts a non-incremental search for the empty string, I have changed the default behavior so that it just moves the history entries forward/backward when there is no string before the cursor.

If one would like to make the behavior as close to Bash's as possible, one can explicitly use the following keybindings:

ble-bind -f up 'history-search-backward hide-status:immediate-accept:action=load'
ble-bind -f down 'history-search-forward hide-status:immediate-accept:action=load'

@rashil2000

You can use the following keybindings:

ble-bind -f up 'history-search-backward hide-status:immediate-accept:point=end'
ble-bind -f down 'history-search-forward hide-status:immediate-accept:point=end'

Now with the option immediate-accept, you don't have to rebind C-m and RET.

#101 (comment) by @rashil2000
ble-bind -m 'nsearch' -f 'RET' 'nsearch/accept-line'

I tried to issue this command but it didn't work, am I doing this wrong?

I also tried ble-bind -m 'nsearch' -f 'ESC' 'nsearch/cancel' to map Esc key for clearing search, but this also doesn't seem to work. Is there any other way to do this?

I have added a subsection in Manual §3.1.1. It's basically the same as the explanation in my previous reply.

@Alyetama

#80 (comment) by @Alyetama
I would like to know if there is a way to bypass this and instead just hit up then enter to run the previous line (the normal bash behavior)?

Now you can use the option immediate-accept. I'm not sure exactly how you set up nsearch, but for example, you can use the following settings. Now you don't have to rebind C-m and RET in nsearch keymap.

ble-bind -f up 'history-search-backward immediate-accept'
ble-bind -f down 'history-search-forward immediate-accept'

You may also add other options if you want to change the detailed behavior.

#80 (comment) by @Alyetama
I have been looking for a configuration before I posted my comment, but have found none. If there is one, then I would have just used it.

I have added a description in Manual §4.10.1. I also added examples in blerc.

@carv-silva

#80 (comment) by @carv-silva
How to turn off the nsearch (nsearch#1: << !1170 ) `'?
Theres one workaround like exec_errexit_mark= to hide (nsearch#1: << !1170 ) `'?

Finally, I'm not sure if this is what you wanted, and also I'm not sure how you set up nsearch. But if I take your request literally and if I assume that you have set up the nsearch for up and down through e.g. oh-my-bash, you may add the following settings in ~/.blerc:

ble-bind -f up 'history-search-backward hide-status'
ble-bind -f down 'history-search-forward hide-status'

But I think this setting is confusing. Maybe you can also add immediate-accept option:

ble-bind -f up 'history-search-backward hide-status:immediate-accept'
ble-bind -f down 'history-search-forward hide-status:immediate-accept'

@rashil2000
Copy link
Author

Beautiful! Can't thank you enough...

Should I close this then?

@akinomyoga
Copy link
Owner

OK! Thank you! I'll close it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NYI/NewFeat Not yet implemented or New Feature
Projects
None yet
Development

No branches or pull requests

2 participants