2011/2/2 Bart Schaefer > On Feb 1, 10:15pm, Julien Nicoulaud wrote: > } > } Some commands take passwords as option values, which is not very > } secure... I was wondering if there is some way to handle that, for > } example through a custom completer. > > I don't know about a custom completer -- it's pretty difficult to > have the completion system go off and do something interactive in > the middle, at least not without the display ending up hopelessly > muddled afterward -- but it should be possible to implement it as > a widget. > > send-invisible() { > emulate -L zsh > # Shamelessly cribbed from read-from-minibuffer. > > # send-invisible reads a line from the terminal, displaying an > # asterisk for each character typed. It stores the line in the > # global variable INVISIBLE, and when finished reading, inserts > # the string ${INVISIBLE} into the original command buffer. > > # If one argument is given, it is the prompt. The default is > # "Non-echoed text: " > > # If two or three arguments are given, they form the prefix and > # suffix of the inserted INVISIBLE. Defaults are '${' and '}' > # but these can be replaced, for example with '"${' and '}"' to > # enclose the whole word in double quotes, or '${(z)' and '}' to > # split the value of $INVISIBLE like the shell parser. > > # Hide the value of INVISIBLE in any output of set and typeset > typeset -g -H INVISIBLE= > > local pretext="$PREDISPLAY$LBUFFER$RBUFFER$POSTDISPLAY"$'\n' > > # Can't directly make these locals because send-invisible is > # called as a widget, so these special variables are already > # local at the current level and wouldn't get restored > local save_lbuffer=$LBUFFER > local save_rbuffer=$RBUFFER > local save_predisplay=$PREDISPLAY > local save_postdisplay=$POSTDISPLAY > local -a save_region_highlight > save_region_highlight=("${region_highlight[@]}") > > { > local lb rb opn=${2:-'${'} cls=${3:-'}'} > LBUFFER= > RBUFFER= > PREDISPLAY="$pretext${1:-Non-echoed text: }" > POSTDISPLAY= > region_highlight=("P${(m)#pretext} ${(m)#PREDISPLAY} bold") > > while zle -R && zle .read-command > do > # There are probably more commands that should go into > # the first clause here to harmlessly beep, because ... > case $REPLY in > (send-invisible|run-help|undefined-key|where-is|which-command) > zle .beep;; > (push-*|send-break) INVISIBLE=;& > (accept-*) break;; > (*) > LBUFFER=$lb > RBUFFER=$rb > zle $REPLY # ... this could expose something > lb=$LBUFFER > rb=$RBUFFER > INVISIBLE=$BUFFER > LBUFFER=${(l:$#LBUFFER::*:):-} > RBUFFER=${(l:$#RBUFFER::*:):-} > ;; > esac > done > } always { > LBUFFER=$save_lbuffer > RBUFFER=$save_rbuffer > PREDISPLAY=$save_predisplay > POSTDISPLAY=$save_postdisplay > region_highlight=("${save_region_highlight[@]}") > zle -R > > # Now that the highlight has been restored with all the old > # text and cursor positioning, insert the new text. > LBUFFER+=${INVISIBLE:+${opn}INVISIBLE${cls}} > } > } > zle -N send-invisible > > Perfect, thank you ! You can unset INVISIBLE in precmd too: unset_invisible () {unset INVISIBLE} add-zsh-hook precmd unset_invisible > } Ideally, I here is how it should behave: > } - When reaching an option which expected value is a password, prompt for > it > } and read it from stdin > > If you can figure out how to auto-invoke the above in these circumstances, > go for it. Possibly something in zle-line-init that examines the word > at the end of $LBUFFER. > > I think the widget approach is the only one that will work in every case... > } - Do not display it in the buffer (just replace it with "XXXX" for > example) > } - When accepting the buffer, replace the displayed buffer with the real > one > } - Save the displayed buffer in the history rather than the real one > > I think the above covers all of this. >