Your requirements are logically contradictory. Given input like gitploy up -t 2.0.0 test_repo
, you need to parse the options, and in particular notice the presence of the -t
option and the fact that it takes one argument, in order to identify that the first non-option argument is test_repo
.
So first parse the options normally. Then you can know what the first operand is. At that point, process the options. Store the information you need about the options in variables.
action="$1"
shift
unset t_arg
while getopts "zhvdurqw:c:i:e:o:b:t:f:p:g" opt; do
case "$opt" in
c) c_arg="$OPTARG";;
…
esac
done
shift "$((OPTIND-1))"
root_arg="$1"
if [ -n "${c_arg+1}" ]; then
queue_callback "$OPTARG"
echo "$root_arg was here"
fi
With zsh
, it should just be a matter of:
precmd() print -z 'foo '
Or to avoid it overriding commands queued by the user with Alt+q:
zle-line-init() { [ -n "$BUFFER" ] || LBUFFER='foo '; }
zle -N zle-line-init
With bash
, instead of xdotool
, you could use the TIOCSTI
ioctl
:
insert() {
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
PROMPT_COMMAND='insert "foo "'
It's preferable to xdotool
because it's inserting those characters directly in the input buffer of the device bash
is reading from. xdotool
would only work if there's a X server running (wouldn't work on the console or real terminals or over ssh
(without -X
) for instance), that it is the one identified by $DISPLAY
and that's the one you're interacting with, and that the terminal emulator bash
is running in has the focus when $PROMPT_COMMAND
is evaluated.
Now, like in your xdotool
case, because the ioctl()
is done before the prompt is displayed and the tty terminal line discipline is put out of icanon+echo
mode by readline, you're likely to see the echo of that foo
by the tty line discipline messing up the display.
You could work around that by instead inserting a string whose echo is invisible (like U+200B if using exclusively Unicode locales) and bind that to an action that inserts "foo "
:
insert() {
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV' -- "$@"
}
bind $'"\u200b":"foo "'
PROMPT_COMMAND="insert $'\u200b'"
Or you could delay the TIOCSTI
ioctl enough for readline to have time to initialise:
insert_with_delay() {
perl -le 'require "sys/ioctl.ph";
$delay = shift @ARGV;
unless(fork) {
select undef, undef, undef, $delay;
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV;
}' -- "$@";
}
PROMPT_COMMAND='insert_with_delay 0.05 "foo "'
If, like in the zsh
approaches, you want to handle the case where the user enters text before the prompt is displayed, you could either
- drain that by doing a
tcflush(0, TCIFLUSH)
in perl
before the TIOCSTI
ioctl (also needs a -MPOSIX
option), or
like in the zsh
approach, ensure the foo
is inserted at the start of the buffer by inserting a ^A
(assuming you use the emacs
(default) editing mode where that moves the cursor to the beginning of the line) before foo
and ^E
after (to move to the end):
insert_with_delay 0.05 $'\1foo \5'
or
bind $'"\u200b":"\1foo \5"'
Best Answer
When using
rm
with both-i
and-f
options, the first one will be ignored. This is documented in the POSIX standard:and also in GNU
info
page:Let's see what happens under the hood:
rm
processes its option withgetopt(3)
, specificallygetopt_long
. This function will process the option arguments in the command line (**argv
) in order of appearance:This function is typically called in a loop until all options are processed. From this functions perspective, the options are processed in order. What actually happens, however, is application dependent, as the application logic can choose to detect conflicting options, override them, or present an error. For the case of
rm
and thei
andf
options, they perfectly overwrite eachother. Fromrm.c
:Both options set the same variables, and the state of these variables will be whichever option is last in the command line. The effect of this is inline with the POSIX standard and the
rm
documentation.