In a nutshell I'm trying to make Perforce work with less. At the moment a command such as p4 diff will happily dump 5000 lines to the console. I want commands like this to automatically pipe into less without me having to type it (you know, like g*t does).
My two best "solutions" so far:
"Solution" 1 - A bash function
function p4() {
pager=""
if [ "$1" = "diff" ]
then
pager=" | less"
fi
/bin/sh -c "/usr/local/bin/p4 "$@" $pager"
}
Problem with this is Perforce syntax overlaps Unix shell syntax.
i.e. p4 jobs ...@\>2015/01/20 will fail horribly because of the > symbol.
"Solution" 2 - Function with a different name
function p4d() {
p4 diff "$@" | less
}
Which is lame because now I have to remember to type p4d instead of p4 diff and won't work for p4 diff2 for the same reason as solution 1.
Are there any shell or Perforce tricks I can use to get commands like p4 diff to pipe into less without me having to remember to type it all the time?
Is there a way I can safely wrap the p4 arguments ($@) so that shell symbols like > are not reinterpreted but | is?
Does not have to be bash. If you have some funky shell from the 60s which solves my problem let's hear it!
Thank you for your help.
Eval-type solutions generally fail to be robust against arguments with odd characters in them. On the other hand, they are often unnecessary.
Instead of
/bin/sh -c "/usr/local/bin/p4 "$@" $pager"
which has a quotation error (the quotes around $@ are actually unquoting $@ although fixing that won't help since you would actually need to insert escapes into the string passed to bash -c), you can just execute the command directly:
/usr/local/bin/p4 "$@" | "$pager"
That requires that $pager be defined; you would probably want:
if [[ $pager ]]; then
/usr/local/bin/p4 "$@" | "$pager"
else
/usr/local/bin/p4 "$@"
fi
The explicit path is a bit annoying. With bash, you can make this more robust by using the command builtin:
if [[ $pager ]]; then
command p4 "$@" | "$pager"
else
command p4 "$@"
fi
That introduces a small duplication of code, and it's a bit much if you're going to use that snipped in various places. You could define the following function (in your ~/.bashrc file, for example):
page() {
if [[ $pager ]]; then
"$@" | "${pager[@]}"
else
"$@"
fi
}
Then your p4 script could be:
p4() {
local pager=
if [[ $1 = diff ]]; then pager=less; fi
page command p4 "$@"
}
There are lots of other variants. Note the use of "${pager[@]}" in the page function; this allows pager to be an array, in case you want to pass arguments to less. For example:
( pager=(less -N); p4 diff ...; )
(The parentheses are to make the setting of pager local; you can't use the normal var=value command syntax with arrays.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With