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

support editing the command line with an external editor #1215

Closed
lanterndev opened this issue Dec 30, 2013 · 20 comments
Closed

support editing the command line with an external editor #1215

lanterndev opened this issue Dec 30, 2013 · 20 comments

Comments

@lanterndev
Copy link

@lanterndev lanterndev commented Dec 30, 2013

In bash you can press C-x C-e and it will drop you into your $EDITOR so you can input commands with it. Could fish support something similar?

@ridiculousfish
Copy link
Member

@ridiculousfish ridiculousfish commented Dec 30, 2013

Probably this can be done with a custom binding.

@lanterndev
Copy link
Author

@lanterndev lanterndev commented Dec 30, 2013

Cool, thanks. Would be interested to see how, if it's possible. For a
future version, I think it's worth making it a default keybinding, like
bash does.

On Sun, Dec 29, 2013 at 11:54 PM, ridiculousfish
notifications@github.comwrote:

Probably this can be done with a custom binding.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1215#issuecomment-31333516
.

@maxfl
Copy link
Contributor

@maxfl maxfl commented Dec 30, 2013

I use the following piece of code

function edit_cmd --description 'Edit cmdline in editor'
        set -l f (mktemp --tmpdir=.)
        set -l p (commandline -C)
        commandline -b > $f
        vim -c set\ ft=fish $f
        commandline -r (more $f)
        commandline -C $p
        rm $f
end

then

bind -k F4 edit_cmd

The user might want to change temporary folder for /tmp so the command could work in any directory.

@lanterndev
Copy link
Author

@lanterndev lanterndev commented Dec 30, 2013

Thanks for sharing, @maxfl. When I try that though I get:

usage: mktemp [-d] [-q] [-t prefix] [-u] template ...
       mktemp [-d] [-q] [-u] -t prefix 
fish: Expected redirection specification, got token of type '$f'
/Users/_pants/.config/fish/config.fish (line 5):         commandline -b > $f
                                                                          ^
in function 'edit_cmd',
    called on standard input,

I'm on OS X 10.9.1 + homebrew fish version 2.1.0.

@maxfl
Copy link
Contributor

@maxfl maxfl commented Dec 30, 2013

@skivvies, 'mktmp' should return unique name for the temp filename.
You can replace that line with (for example):

set -l f /tmp/fish.cmd.(random)

On Mon, Dec 30, 2013 at 9:44 PM, skivvies notifications@github.com wrote:

Thanks for sharing, @maxfl https://github.com/maxfl. When I try that
though I get:

usage: mktemp [-d] [-q] [-t prefix] [-u] template ...
mktemp [-d] [-q] [-u] -t prefix
fish: Expected redirection specification, got token of type '$f'
/Users/_pants/.config/fish/config.fish (line 5): commandline -b > $f
^
in function 'edit_cmd',
called on standard input,

I'm on OS X 10.9.1 + homebrew fish version 2.1.0.

Reply to this email directly or view it on GitHubhttps://github.com//issues/1215#issuecomment-31357797
.

@lanterndev
Copy link
Author

@lanterndev lanterndev commented Dec 30, 2013

Ah, BSD (OS X's) mktemp doesn't accept a --tmpdir argument. This works though:

    function edit_cmd --description 'Input command in external editor'
        set -l f (mktemp /tmp/fish.cmd.XXXXXXXX)
        if test -n "$f"
            set -l p (commandline -C)
            commandline -b > $f
            vim -c 'set ft=fish' $f
            commandline -r (more $f)
            commandline -C $p
            command rm $f
        end
    end

    function fish_user_key_bindings
      bind \ev 'edit_cmd'
    end

Thanks for the tip, @maxfl.

@zanchey
Copy link
Member

@zanchey zanchey commented Jan 6, 2014

I think this would be worth including, although we would have to use $EDITOR or $VISUAL rather than hard-encoding vim.

@zanchey
Copy link
Member

@zanchey zanchey commented Jan 15, 2014

I note that in Bash, C-x C-e executes the command when the editor exits, so we actually need to bind edit_cmd; commandline -f execute.

Any suggestions for a default binding? We don't support multi-character sequences yet, so C-x C-e is out. M-e?

@maxfl
Copy link
Contributor

@maxfl maxfl commented Jan 15, 2014

I use M-e and F4 bindings. They seem not to intersect with anything.

@mrak
Copy link
Contributor

@mrak mrak commented May 30, 2014

Thanks all! Super useful

@ridiculousfish ridiculousfish added this to the fish-future milestone Nov 2, 2014
@mfilej
Copy link
Contributor

@mfilej mfilej commented Sep 1, 2015

@maxfl's snippet seems to have stopped working for me at some point. Did anything change in fish?

@maxfl
Copy link
Contributor

@maxfl maxfl commented Sep 1, 2015

It's because of #2210.

@mfilej
Copy link
Contributor

@mfilej mfilej commented Sep 1, 2015

Thanks! I'll keep an eye on that then.

@braham-snyder
Copy link

@braham-snyder braham-snyder commented Dec 6, 2016

something like this can be useful for completion, etc., depending on your editor:

set -l tmpfile (mktemp --suffix=".fish" --tmpdir=.); or return 1

if you're on OS X, you'll need homebrew's gmktemp (available in the formula coreutils, I think)

@krader1961 krader1961 changed the title support input via external editor support editing the command line with an external editor Dec 6, 2016
@krader1961
Copy link
Contributor

@krader1961 krader1961 commented Dec 6, 2016

In the past year I've seen several solutions documented in other issues. The one I've been using for a long time is an enhanced version of @skivvies that works whether you're using BSD or GNU mktemp:

function edit_command_buffer --description 'Edit the command buffer in an external editor'
    set -l f (mktemp)
    if set -q f[1]
        mv $f $f.fish
        set f $f.fish
    else
        # We should never execute this block but better to be paranoid.
        set f /tmp/fish.(echo %self).fish
        touch $f
    end

    set -l p (commandline -C)
    commandline -b > $f
    if set -q EDITOR
        eval $EDITOR $f
    else
        vim $f
    end

    commandline -r (cat $f)
    commandline -C $p
    command rm $f
end

Something like that should be bundled with fish. What the default bindings should be is TBD. I use \ee ([meta-e] and \ev ([meta-v] which matches the ksh binding in vi mode that I was used to using). It would be nice if we could get some people to try this and report whether or not it works on their system.

@krader1961
Copy link
Contributor

@krader1961 krader1961 commented Dec 6, 2016

Also from my comment in issue #3477 regarding the function I just mentioned:

It's not perfect. For example, you get a weird but harmless error if you save an empty buffer when exiting the editor. It really should also check the exit status of the editor and use a non-zero status to mean the editors buffer shouldn't be used (like git commit does). But the point is that if you're doing non-trivial editing of the command line you're probably better off using a real editor than adding a bunch of fish key bindings that will never make fish truly behave like your editor.

@braham-snyder
Copy link

@braham-snyder braham-snyder commented Dec 6, 2016

@krader1961 works for me on El Capitan with emacsclient (with that weird but harmless error when saving an empty command)

@krader1961 krader1961 self-assigned this Dec 6, 2016
@krader1961
Copy link
Contributor

@krader1961 krader1961 commented Dec 6, 2016

This question and various solutions has occurred often enough that I decided it was time to make my solution more robust. I've modified the function I posted above to make it more robust and will open a pull request to invite review of it.

@hashier
Copy link

@hashier hashier commented Sep 19, 2018

To everyone who started to copy/paste the solution of @krader1961 like me. This is not needed anymore. This got merged into fish and got even two shortcuts. Alt-e and Alt-v.

Documentation: https://fishshell.com/docs/current/ (search for "edit the current command line in an external editor")
PR: #3627

@dniku
Copy link

@dniku dniku commented Mar 28, 2019

Also, Alt-e and Alt-v are equivalent according to the documentation.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

You can’t perform that action at this time.