Skip to content

Commit

Permalink
[GH #65] Support binding more advanced external commands
Browse files Browse the repository at this point in the history
  • Loading branch information
jonas committed Aug 23, 2012
1 parent e35b50d commit 98760f2
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 12 deletions.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ Improvements:
Example: `bind main B !?git rebase -i %(commit)`.
- User-defined commands prefixed with a '<' means exit after execution.
Example: `bind main C !<git commit`. (GH #66)
- User-defined commands are executed unquoted to support shell commands.
Example: `bind generic I !@sh -c "echo -n %(commit) | xclip -selection c"`.
(GH #65)
- Configure case-insensitive searches using: `set ignore-case = yes`.
- Add "deleted mode" line type for better diff coloring.
- Open editor when requesting edit action from within a file diff.
Expand Down
31 changes: 28 additions & 3 deletions io.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,18 @@ argv_to_string(const char *argv[SIZEOF_ARG], char *buf, size_t buflen, const cha
}

static inline int
get_arg_valuelen(const char *arg, bool *quoted)
get_arg_valuelen(const char *arg, char *quoted)
{
if (*arg == '"' || *arg == '\'') {
const char *end = *arg == '"' ? "\"" : "'";
int valuelen = strcspn(arg + 1, end);

if (quoted)
*quoted = TRUE;
*quoted = *arg;
return valuelen > 0 ? valuelen + 2 : strlen(arg);
} else {
if (quoted)
*quoted = 0;
return strcspn(arg, " \t");
}
}
Expand All @@ -46,7 +48,7 @@ static bool
split_argv_string(const char *argv[SIZEOF_ARG], int *argc, char *cmd, bool remove_quotes)
{
while (*cmd && *argc < SIZEOF_ARG) {
bool quoted = FALSE;
char quoted = 0;
int valuelen = get_arg_valuelen(cmd, &quoted);
bool advance = cmd[valuelen] != 0;
int quote_offset = !!(quoted && remove_quotes);
Expand Down Expand Up @@ -140,6 +142,29 @@ argv_append_array(const char ***dst_argv, const char *src_argv[])
return TRUE;
}

bool
argv_remove_quotes(const char *argv[])
{
int argc;

for (argc = 0; argv[argc]; argc++) {
char quoted = 0;
const char *arg = argv[argc];
int arglen = get_arg_valuelen(arg, &quoted);

if (!quoted)
continue;

arg = strndup(arg + 1, arglen - 1 - (arg[arglen - 1] == quoted));
if (!arg)
return FALSE;
free((void *) argv[argc]);
argv[argc] = arg;
}

return TRUE;
}

bool
argv_copy(const char ***dst, const char *src[])
{
Expand Down
1 change: 1 addition & 0 deletions io.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ size_t argv_size(const char **argv);
bool argv_append(const char ***argv, const char *arg);
bool argv_append_array(const char ***dst_argv, const char *src_argv[]);
bool argv_copy(const char ***dst, const char *src[]);
bool argv_remove_quotes(const char *argv[]);

/*
* Encoding conversion.
Expand Down
12 changes: 6 additions & 6 deletions tig.c
Original file line number Diff line number Diff line change
Expand Up @@ -3419,12 +3419,12 @@ open_run_request(enum request request)
}
}

if (!confirmed)
; /* Nothing */
else if (req->silent)
io_run_bg(argv);
else
open_external_viewer(argv, NULL, !req->exit);
if (confirmed && argv_remove_quotes(argv)) {
if (req->silent)
io_run_bg(argv);
else
open_external_viewer(argv, NULL, !req->exit);
}
}

if (argv)
Expand Down
14 changes: 11 additions & 3 deletions tigrc.5.txt
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,18 @@ are:
As an example, the following external command will save the current commit as
a patch file: "!git format-patch -1 %(commit)". If your external command
requires use of dynamic features, such as subshells, expansion of environment
variables and process control, this can be achieved by using a combination of
git aliases and tig external commands. The following example entries can be
put in either the .gitconfig or .git/config file:
variables and process control, this can be achieved by using a shell command:

.Configure a binding in ~/.tigrc to put a commit ID in the clipboard.
--------------------------------------------------------------------------
bind generic I !@sh -c "echo -n %(commit) | xclip -selection c"
--------------------------------------------------------------------------

Or by using a combination of git aliases and tig external commands. The
following example entries can be put in either the .gitconfig or .git/config
file:

.Git configuration which binds tig keys to git command aliasas.
--------------------------------------------------------------------------
[alias]
gitk-bg = !"gitk HEAD --not $(git rev-parse --remotes) &"
Expand Down

0 comments on commit 98760f2

Please sign in to comment.