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 · 18 comments

Comments

Projects
None yet
9 participants
@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

This comment has been minimized.

Show comment
Hide comment
@ridiculousfish

ridiculousfish Dec 30, 2013

Member

Probably this can be done with a custom binding.

Member

ridiculousfish commented Dec 30, 2013

Probably this can be done with a custom binding.

@lanterndev

This comment has been minimized.

Show comment
Hide comment
@lanterndev

lanterndev 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/fish-shell/fish-shell/issues/1215#issuecomment-31333516
.

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/fish-shell/fish-shell/issues/1215#issuecomment-31333516
.

@maxfl

This comment has been minimized.

Show comment
Hide comment
@maxfl

maxfl Dec 30, 2013

Contributor

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.

Contributor

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

This comment has been minimized.

Show comment
Hide comment
@lanterndev

lanterndev 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.

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

This comment has been minimized.

Show comment
Hide comment
@maxfl

maxfl Dec 30, 2013

Contributor

@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/fish-shell/fish-shell/issues/1215#issuecomment-31357797
.

Contributor

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/fish-shell/fish-shell/issues/1215#issuecomment-31357797
.

@lanterndev

This comment has been minimized.

Show comment
Hide comment
@lanterndev

lanterndev 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.

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

This comment has been minimized.

Show comment
Hide comment
@zanchey

zanchey Jan 6, 2014

Member

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

Member

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

This comment has been minimized.

Show comment
Hide comment
@zanchey

zanchey Jan 15, 2014

Member

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?

Member

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

This comment has been minimized.

Show comment
Hide comment
@maxfl

maxfl Jan 15, 2014

Contributor

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

Contributor

maxfl commented Jan 15, 2014

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

@mrak

This comment has been minimized.

Show comment
Hide comment
@mrak

mrak May 30, 2014

Contributor

Thanks all! Super useful

Contributor

mrak commented May 30, 2014

Thanks all! Super useful

@ridiculousfish ridiculousfish added this to the fish-future milestone Nov 2, 2014

@mfilej

This comment has been minimized.

Show comment
Hide comment
@mfilej

mfilej Sep 1, 2015

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

mfilej commented Sep 1, 2015

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

@maxfl

This comment has been minimized.

Show comment
Hide comment
@maxfl

maxfl Sep 1, 2015

Contributor

It's because of #2210.

Contributor

maxfl commented Sep 1, 2015

It's because of #2210.

@mfilej

This comment has been minimized.

Show comment
Hide comment
@mfilej

mfilej Sep 1, 2015

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

mfilej commented Sep 1, 2015

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

@braham-snyder

This comment has been minimized.

Show comment
Hide comment
@braham-snyder

braham-snyder 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)

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 from support input via external editor to support editing the command line with an external editor Dec 6, 2016

@krader1961

This comment has been minimized.

Show comment
Hide comment
@krader1961

krader1961 Dec 6, 2016

Contributor

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.

Contributor

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

This comment has been minimized.

Show comment
Hide comment
@krader1961

krader1961 Dec 6, 2016

Contributor

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.

Contributor

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

This comment has been minimized.

Show comment
Hide comment
@braham-snyder

braham-snyder Dec 6, 2016

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

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

This comment has been minimized.

Show comment
Hide comment
@krader1961

krader1961 Dec 6, 2016

Contributor

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.

Contributor

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.

krader1961 added a commit to krader1961/fish-shell that referenced this issue Dec 7, 2016

function for editing command line in ext editor
This implements a standard function and bindings for editing the command
line in an external editor. This feature has been requested multiple
times in the past year with various solutions cut and pasted into those
issues. This change combines the best aspects of those solutions.

Fixes #1215

krader1961 added a commit to krader1961/fish-shell that referenced this issue Dec 7, 2016

function for editing command line in ext editor
This implements a standard function and bindings for editing the command
line in an external editor. This feature has been requested multiple
times in the past year with various solutions cut and pasted into those
issues. This change combines the best aspects of those solutions.

Fixes #1215

@krader1961 krader1961 closed this in 59fa04b Dec 9, 2016

@zanchey zanchey modified the milestones: fish 2.5.0, fish-future Dec 9, 2016

@faho faho added the release notes label Dec 10, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment