症状
Emacs 23 の *shell* バッファにて、 git パスワードを入れようとすると、中身出てた。
$ git push
Username for 'https://github.com':y2q-actionman
Password for 'https://y2q-actionman@github.com':ウワーここで入力した文字そのまま出るじゃん!
orz...
原因
Emacs 23 の shell-mode で、各行がパスワード入力を促すものかどうかを判定する関数は、 comint-watch-for-password-prompt である。そして、この関数の行う判定とは、各行について「 comint-password-prompt-regexp で指定された正規表現にマッチするかどうか」である。
この comint-password-prompt-regexp に初期状態で設定されている正規表現では、git のパスワード入力のプロンプトにはマッチせず、そのためパスワード入力ではないと判定されてしまったため、我々は自らの内腑を曝けだす凄惨な所業を目撃するに至ったのであった。
comint-password-prompt-regexp の初期状態の正規表現は、パスワードを尋ねるっぽい文字列の後に for があった場合、 for のあとに空白以外を置かずに : が続く ことを要求しているため、 git のようにURI が挟まってしまうと、それに含まれる : のためにマッチしなくなっ てしまうのである。
対策
for のあとにどんな文字があっても、一個 : があったら、まあそれでいいんじゃない? という雑な基準にしてみることで対策してみた。
;; workaround for git prompt, because it contains URL
(add-hook 'shell-mode-hook
#'(lambda ()
(setq comint-password-prompt-regexp
(replace-regexp-in-string "for \\[\\^:\\]\\+" "for .+"
comint-password-prompt-regexp t t))))
(追記) Emacs25での対処
上の設定をしても、 Emacs 25 だと再び出るようになってしまっていたので見てみたら、 comint-password-prompt-regexp が変わっていて、 for の後に来る文字は : のみではなく ::៖ の三つに変わっていた。
というわけでもっと基準を緩くして、 for ってあったらいいんじゃない? という雑なマッチにしてみて試用中。
(add-hook 'shell-mode-hook
#'(lambda ()
(setq comint-password-prompt-regexp
(replace-regexp-in-string "for \\[\\^.+?\\]\\+" "for .+"
comint-password-prompt-regexp t t))))