Quantcast
Channel: Bashタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 2818

MacのBashでReadlineのキーバインド`operate-and-get-next`(Ctrl-O)がきかなかった話

$
0
0

まえおき

数ヶ月前にMacBook Airを購入しましたが、シェルはBashを使っています。

Bashに対するキー入力は、Readlineが解釈してコマンドラインに反映します。
ある日、Readlineの数あるキーバインドのうちCtrl-Oが動いていないことに気づき、一時しのぎでEsc-Oに割当ててしばらく使っていたんですが、やっぱり使いにくかったので調査して直した記録になります。

環境

  • MacBook Air (macOS Catalina)
  • GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19)
  • GNU Readline version 8.0 (たぶん)

普段使っている端末はiTerm2ですが、Mac標準の端末で確かめてもやはり同じように動きませんでした。

期待する本来の動き

Ctrl-Oには、既定ではReadlineのoperate-and-get-nextが割当てられています。man bashに、operate-and-get-nextについての次のような説明が見られます。

operate-and-get-next (C-o)

Accept the current line for execution and fetch the next line relative to the current line from the history for editing. Any argument is ignored.

実際の挙動としては、本来は↓のような動きになります。

expected_behaviour.gif

入力したls -aがまず実行され、実行後のプロンプトに最後に実行したコマンド(つまりls -a)を最初から表示した状態で待機します。

場面としては、似たようなコマンドを続けて実行する場合や、正しく動くことを都度確認しながら少しずつコマンドを打ちこんでいきたい場合(長いsedやちょっと複雑めなfor文など)に使うと便利です。

これをやりたくてCtrl-Oを何回入力しても、端末はうんともすんとも言わず、困ったわけです。

原因

普段仕事で使っているWSLやUbuntuのBashでは問題なく動いているので、Mac特有の問題か…?とか思っていたんですが、どうやら原因は、sttyCtrl-Oの入力をReadlineに届く前に奪い取ってしまっているためのようでした。

sttyには現在の設定を表示する--all(-a)オプションがあります。これを実行すると、次のように出力されました(今回の内容と直接関係がない部分は省略しています)。

出力
# all current settings in human-readable form$ stty--all# (省略...)
werase = ^W; lnext = ^V; discard = ^O; status = ^T; min = 1;time= 0;# (省略...)

↑のdiscard = ^Oが悪さをしている箇所です。

ReadlineがCtrl-Ooperate-and-get-nextとして解釈する前に、sttyが入力を受け取ってdiscordとして解釈してしまっている、という機序のようです。

解決

sttydiscardが何をするのかはよくわかりませんが、とりあえず直します。

~/.bashrcに次のように追記し、Ctrl-Oを送ってもstty discardで邪魔されないようにします。

~/.bashrc
stty discard undef

これで動くようになりました。めでたし。

参考

今回の不具合について調べていたら、Bashで履歴のインクリメンタルサーチがきかない不具合を直す記事を見かけ、「もしかしたら今回の不具合も…」と思ったらドンピシャでした。


Viewing all articles
Browse latest Browse all 2818

Trending Articles