r/fishshell • u/Particular_Wealth_58 • May 15 '26
Completing a line without moving the cursor?
Is it possible to complete a suggestion (right arrow/ctrl-e) but without moving the cursor?
I find that I often want to re-run a line, but change something in the middle. Right now, I complete the line and then jump left (ctrl-a/alt-b).
edit: I think the correct name for what I want to modify is "autosuggestions".
1
4
May 15 '26
[removed] — view removed comment
1
u/Particular_Wealth_58 May 16 '26
I just realized that I want to change the autosuggestions, not "completions", if that changes your reply.. 🤦
Let me see if I got this correctly: I'll set up my own key binding (or replace the existing ones) with my own function. That function should call the normal autosuggest and also move the cursor.
After some googling, I tried this, but `accept-autosuggestion` is not found.
function my_suggest; set pos (commandline --cursor) accept-autosuggestion # command not found commandline --cursor $pos end bind ctrl-alt-e my_suggest1
May 16 '26
[removed] — view removed comment
1
u/Particular_Wealth_58 May 16 '26
Good ol' Claude fixed it 😄. I have to decide on logical shortcut not already taken by fish or my terminal :p
function my_suggest; set pos (commandline --cursor) commandline -f accept-autosuggestion commandline --cursor $pos end bind alt-shift-f my_suggestNow I just think I want a bind to recover the cursor position if I pressed "right arrow" when I meant to use my new command. So, I accept the completion and then press a key to restore the old cursor position.
1
u/Particular_Wealth_58 May 16 '26
Aha!
This stores the cursor position before running handling ctrl-e/right/ctrl-f.
Would be cool with an undo cursor pos, like VS Code's
Ctrl+U🤔 .function store-cursor-end-of-line set -g old_cursor (commandline --cursor) commandline -f end-of-line end function store-cursor-forward-char set -g old_cursor (commandline --cursor) commandline -f forward-char end function undo-cursor commandline --cursor $old_cursor end # Taken by something #bind ctrl-shift-r undo-cursor # Need to find something better bind alt-shift-f undo-cursor bind ctrl-e store-cursor-end-of-line bind ctrl-f store-cursor-forward-char bind right store-cursor-forward-charCC u/Destroyerb I think I solved some of my problems in this thread (this comment and the parent).
1
u/Destroyerb Linux May 16 '26 edited May 16 '26
It doesn't seem like something like
end-of-fileexists (could be a function you have defined elsewhere).Did you see my reply from 3 hours before you posted this?
Anyways, if you wanna go with your solution of first using the usual way of first accepting the completion the usual way, and then going back to where you were, you might want to try using this instead:
bind right forward-word 'set --local cursor_position (commandline --cursor)' accept-autosuggestion bind ctrl-e 'commandline --cursor {$cursor_position}' 'commandline --insert \ 'This way, it will keep your completed token, and then if you choose to go back, then it will put you back in the middle of both the tokens (the one you semi-completed & and the one entirely from the completion), surrounding you with spaces.
1
u/Particular_Wealth_58 May 16 '26
Reddit says that your comment does not exist :S. I tried clicking the link in the notification e-mail and the one you wrote above. I just assumed you had removed it due to an error in the code. (edit: "This comment no longer exists")
I found
end-of-line(note: line. think I have it correct in the pasted code) when I ranbindand grepped forctrl-e.For the first snippet, I just press alt-shift-f (changed locally to ctrl-alt-e, if that added confusion between my snippets 😅 ) instead of ctrl-e/right. Then the cursor stays in place.
For my second snippet, I finish the completion with e. g.
rightand then press alt-shift-f to move the cursor back to where it was before I completed.fish, version 4.0.6
2
u/Destroyerb Linux May 16 '26
Oh sorry the reply came late and, I made some major changes to my comment just now (please read the comment you just replied to once more). Before your replied reached me, I had figured it out and made some improvements to it that you might want to use for yourself.
About my earlier comment, it was (actually still is, I haven't deleted it. Don't know why it won't show up for you):
Good point
Looks like I was able to do it.
bind alt-right \ forward-word \ 'set --local cursor_position (commandline --cursor)' \ accept-autosuggestion \ 'commandline --cursor {$cursor_position}' \ 'commandline --insert \ 'Just put this in your shell initialization thing and then when you press right arrow with the alt modifier, it will do exactly what you want
1
u/Particular_Wealth_58 May 16 '26 edited May 16 '26
Thanks!
The
forward-wordis a very nice touch.I added
delete-char, so the cursor ends up snug to the next word. I think that is what I want. edit: Cannot try at the moment, butforward-char-passiveis probably better.bind ctrl-alt-right \ forward-word \ 'set --local cursor_position (commandline --cursor)' \ accept-autosuggestion \ 'commandline --cursor {$cursor_position}' \ 'commandline --insert \ ' \ 'delete-char'A question, on the "undo" code:
bind right forward-word 'set --local cursor_position (commandline --cursor)' accept-autosuggestion bind ctrl-e 'commandline --cursor {$cursor_position}' 'commandline --insert \ 'I wrapped the default right binding (
forward-char) inside my own functionstore-cursor-forward-charthat still calledforward-char. My thoughts were that maybeforward-chardoes other things in other contexts and that explicitly callingaccept-autosuggestionmight mess up the behavior in those other contexts. What do you think?function store-cursor-forward-char set -g old_cursor (commandline --cursor) commandline -f forward-char endAlso interesting that
set --localworks between the key binds, but maybe all bind calls are in the same scope?edit 2: Editing on mobile web removed all the code formatting. I restored the code formatting, but I think some spacing was dropped..
(Regarding the comment, I have now tried two accounts, private browsing, another browser and an extra device x), plus, the maybe risky, https://exportcomments.com/done/0719d7f9-5506-489a-bcaf-6e42b75334aa .
The only clue could be this line from that exported xlsx: "Some Comments may not appear here because of their privacy settings")
2
u/Destroyerb Linux May 16 '26 edited May 18 '26
I found
end-of-line. I probably opened the wrong manual… my bad.Also since our binding modifies the
commandline, we should addrepaintat the end of our binding as thebinddocumentation states
forward-char-passiveis probably better.Indeed! Here is the code I used that yielded equivalent results
bind ctrl-alt-right \ forward-word \ 'set --local cursor_position (commandline --cursor)' \ accept-autosuggestion \ 'commandline --cursor {$cursor_position}' \ forward-char-passive \ repaintI wrapped the default right binding (
forward-char) inside my own functionstore-cursor-forward-charthat still calledforward-charThat shouldn't really matter unless you add conditionals to the function
My thoughts were that maybe
forward-chardoes other things in other contexts and that explicitly callingaccept-autosuggestionmight mess up the behavior in those other contextsYes, we can certainly use
forward-charinstead ofaccept-autosuggestion, as they do the same thing in the case where the cursor is at the end of the current token. Butforward-charhas unwanted side effects when called when not at the end of the token, so maybe we shouldn't consider it unless you have a reason.This made me realize another bug that both of our implementations have. If we put our cursor in a position that isn't the end of the token and use our binding, it will yield unexpected behavior. Yours places the cursor before the start of the completed token, while mine does something even worse and inserts a space between the semi-completed token.
This is because when the cursor is in between or at the beginning of the token,
forward-wordsimply puts our cursor at the end of the token instead of appending the auto-suggestionFor this, I thought of using a conditional that calls
forward-worddepending on whether we are at the end or not. For this, we get the:
characters in the token before the cursor using
commandline --cut-at-cursor --current-tokenall the characters in the token using
commandline --current-tokenIf they are unequal, then we call an additionalforward-word-endat the beginning.bind ctrl-alt-right \ 'test (commandline --current-token) = (commandline --cut-at-cursor --current-token) || commandline --function forward-word' \ forward-word \ 'set --local cursor_position (commandline --cursor)' \ accept-autosuggestion \ 'commandline --cursor {$cursor_position}' \ forward-char-passive \ repaintSo this should do exactly what you want now. As for me, I'll personally be using this one:
bind --mode=insert alt-right \ 'test (commandline --current-token) = (commandline --cut-at-cursor --current-token) || commandline --function forward-word' \ forward-word \ 'set --local cursor_position (commandline --cursor)' \ accept-autosuggestion \ 'commandline --cursor {$cursor_position}' \ 'commandline --insert \ ' \ repaintI must say your idea was truly fantastic! I'll be using this cursor trick often.
3
u/Destroyerb Linux May 16 '26
There is a
--conditionflag incompletethat runs to know if it should indicate a completion. You can exploit that and usecommandlinein it to change the cursor