使用 Fish shell,我想创建一个函数 ( gcom
) 用作命令的别名git commit
,接受任意数量的字符串参数并将它们作为-m
选项传递,以便
git commit -m "a" -m "b" -m "c"
可以写成,简而言之,gcom "a" "b" "c"
.
该gcom
函数应接受 N 个参数,并git command
使用相应的 N 个-m
选项运行。
这可以通过数组上的循环来完成$argv
,使用 手动构建命令string join
并使用 执行此类命令eval
。
然而,这看起来很笨重,我很想找到一个更时尚的替代品。
如果附加gcom -?
选项不加修改地通过就更好了!
git commit -mfoo
使用“foo”作为消息,因此您可以简单地为每个参数添加前缀-m
:
function gcom
git commit -m$argv
end
Run Code Online (Sandbox Code Playgroud)
由于 $argv 是一个列表,这将为其中的每个参数添加“-m”。
与其他 shell 不同,这里没有分词。$argv 不按空格分割,$argv 是给出的所有参数的列表。所以它适用于空格、换行符等。参数只需要在你给它们的地方加引号即可gcom
:
gcom "first argument with spaces" "second"\n"argument"\n"with"\n"newlines"
Run Code Online (Sandbox Code Playgroud)
将运行相当于
git commit -m"first argument with spaces" -m "second
argument
with
newlines"
Run Code Online (Sandbox Code Playgroud)
尝试一下printf
:
set -l mylist "first argument with spaces" "second"\n"argument"\n"with"\n"newlines"
printf '<%s>\n' -m$mylist
Run Code Online (Sandbox Code Playgroud)
将打印
<-mfirst argument with spaces>
<-msecond
argument
with
newlines>
Run Code Online (Sandbox Code Playgroud)
如果额外的 gcom - 就更好了?选项未经修改地通过!
如果您想这样做,您可以将所有以 $args 开头的参数保留-
在附加的 $args 列表中,而不添加-m
. 如果任何选项本身带有参数,例如 ,这就会被破坏--author
。
想一想:
gcom --author "mycoolemail@example.com" these are my message words
Run Code Online (Sandbox Code Playgroud)
这应该像这样执行
git commit --author mycoolemail@example.com -m these -m are -m my -m message -m words
Run Code Online (Sandbox Code Playgroud)
但要弄清楚“mycoolemail@example.com”属于--author
并因此不应该有对应的唯一方法-m
是知道--author
需要选项。
为此,您可以使用 Fish 的argparse内置函数,并且您必须告诉它所有 git-commit 的选项。这就像
function gcom
# The part before the `--` are descriptions for the options that git-commit takes
# A "=" means that the option takes a mandatory argument and so it can be written like "--author foo",
# A "=?" means it takes an optional argument and needs to be written like "-ufoo".
argparse author= a interactive patch s v 'u=?' -- $argv
# Argparse leaves all the non-option arguments in $argv.
# For each option it gives you a $_flag_option variable,
# but that only includes the *value* for the options that take arguments
#
# If we wanted to pass all --author= options we could use the `string split -m1` trick from above,
# but here we assume that only the last --author is of use.
#
# This needs to be done for all the options that take arguments,
# simple boolean flags are just stored as the flags
# - `$_flag_patch` will contain "--patch"
set -l flags $_flag_a $_flag_interactive $_flag_patch
if set -q _flag_author
set -a flags --author $_flag_author[-1]
end
if set -q _flag_u
set -a flags -u$_flag_u[-1]
end
# [ now do the -m trick with the leftover $argv ]
# ...
git commit $flags -m$argv
end
Run Code Online (Sandbox Code Playgroud)
不幸的是,没有办法列出所有带参数的选项,因为否则选项的参数会与普通的消息参数混淆。鱼在这里根本无法做任何事情,这就是参数解析的工作原理。
您可以运行argparse --ignore-unknown
,这会告诉 argparse 在 $argv 中留下未知选项,然后仍然跳过以-
. 如果您曾经传递过一个选项组(想想ls -lah
,它有三个短选项)并且最后一个选项带有一个参数,但您之前没有列出其中一个选项,那么这将会中断。
因为如果你没有告诉它“-s”存在的话,鱼就无法弄清楚eg的-sFfile
意思-s -F=file
——因为它不知道不-s
带任何选项。如果是的话,这将与 相同-s=Ffile
。所以只能让整个集团完好无损。