cannot bind complex external commands #65

thomasjachmann opened this Issue Jun 6, 2012 · 8 comments


None yet

5 participants


I want to add a binding to put the current commit hash into the system's clipboard (Mac OS X), so here's my .gitconfig

[tig "bind"]
    main = c !echo "%(commit)" | pbcopy

The output of this is:

9c118dcfea9a65ed668bf26e1984544a0bb083fa | pbcopy

So my assumption is that everything after the first space is treated as a parameter and passed to the command before the first space. This isn't a pbcopy issue, the following also doesn't work:

[tig "bind"]
    main = c !echo "%(commit)" > sha1.txt

This outputs (no file created):

9c118dcfea9a65ed668bf26e1984544a0bb083fa > sha1.txt

richo commented Jun 6, 2012

The external command is run with execv so shell pipelines won't work.

You can either do

sh -c "9c118dcfea9a65ed668bf26e1984544a0bb083fa | pbcopy"

Which will work or make the command a git alias or somesuch.


The sh trick didn't work, I already tried that:

[tig "bind"]
    main = 1 !`sh -c "%(commit) | pbcopy"`
    main = 2 !`sh -c "echo %(commit) | pbcopy"`
    main = 3 !`sh -c "echo '%(commit)' | pbcopy"`
    main = 4 !sh -c "%(commit) | pbcopy"
    main = 5 !sh -c "echo %(commit) | pbcopy"
    main = 6 !sh -c "echo '%(commit)' | pbcopy"

None of those put anything in the clipboard, the first three didn't have any output, the 5th and 6th had an empty line as output, and the 4th:

|: db4d7c3b175aa504c8e880deb1fad278eae30058: command not found

But this worked:

    pbcopy = !sh -c 'echo $1 | pbcopy' -
[tig "bind"]
    main = 7 !@git pbcopy %(commit)

I can work with that, thank you for the suggestion! But certainly it is a complex workaround. Shouldn't something a bit more complex (but surely not highly sophisticated) work with bindings?

richo commented Jun 6, 2012

I'll have a look at it at some point and see if it's workable to execute aliases in a subshell (which would let things like pipelines and output redirection work).

Ultimately, it's @jonas' call anyway, I'm just an interested party and don't have any sway in the project.


That's cool. I've got it working for now thanks to your hint. And maybe it's getting even easier in future versions.

vivien commented Jun 6, 2012

I've already run into this issue, a solution can be to use system() if the command contains a pipe:
EDIT: I put it in a gist because it wasn't readable.

With this, bindings such as bind main c !@echo %(commit) | xclip work great.
@jonas, what do you think?

jonas commented Aug 10, 2012

Tig originally supported this kind of bindings. It was changed in 10b1023 to stream-line general IO handling. See line 2818

We can reintroduce it if a majority finds it useful and somebody is ready to submit a patch. Just make sure that you properly shell quote all the arguments passed to system(). See a6113cb for the original sq_quote() lifted from git.=

vspinu commented Aug 10, 2012

Actually would be very nice to have the suggested clipboard action as a core tig functionality. But I guess it's a very OS dependent issue.

jonas commented Aug 23, 2012

With the above commit you can now bind a key to update the clipboard with the commit ID, for example:

bind generic I !@sh -c "echo -n %(commit) | xclip -selection c"
@jonas jonas added a commit that referenced this issue Mar 3, 2013
@jonas Add example user-defined commands to the manual
Inspired by GH #121, GH #65 and GH #74.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment