2022-01-30

Zsh: Ctrl key combinations don't work

訳あって Zsh を使うことになり、手持ちの Bash 資産を Zsh に対応させていた時のこと。screen / tmux で訳の分からない挙動にハマった。

screen や tmux で Zsh を使うと、何故か Ctrl + p とか Ctrl + n とか、Ctrl キーを絡めた入力が使えなくなる。Ctrl + p と打っても、「^P」とか出る。ググってもみんなは普通に使えてるっぽいし、探し方が悪かったのかこれといった情報も見つからず、解決に 5 週間かかった。:-/

.zshrc に「bindkey -e」を入れるだけ。orz

しかし何故 screen / tmux だけで発生するのか。普通にターミナルで Zsh を使う分には何も問題ない。

% man zshzle

       <...snip...>

       In addition to these names, either `emacs' or `viins' is also linked to
       the name `main'.  If one of the VISUAL or EDITOR environment  variables
       contain  the  string `vi' when the shell starts up then it will be `vi‐
       ins', otherwise it will be `emacs'.  bindkey's -e and -v  options  pro‐
       vide a convenient way to override this default choice.

環境変数 VISUAL / EDITOR に「vi」という文字列があると、Zsh が気を利かせて viins モードにしてくれるらしい。・・・いやいやいや、Vim 使いでもシェルは普通 emacs モードだと思うけど? ともかく、確かに私は(Emacs 使いだけど) EDITOR=vim としている。これで一応は先の疑問に説明はつく。

  1. Zsh 起動時、EDITOR は未設定なので emacs モードになる。
  2. 起動した Zsh が .zshrc を読み込み、EDITOR=vim になる。
  3. この状態で Zsh の子プロセスが起動すると、EDITOR=vim なので viins モードになる。

説明はつくが、これが適切な仕様だとはとても思えない。これだと EDITOR の値に関係なくログインシェルは常に emacs モードになる。だからこそ、他の人は困ってないっていうね。screen / tmux 使いの内、更にその一部の人だけが困ることになる。これが本当に意図通りの仕様だとしたら、こんな分かりにくい仕様はさっさと捨てた方がいいよ。

しばらく Zsh を使ってみて、Zsh は使い勝手を重視した結果として、驚き最小の法則に反することがあるような気がする。別に Zsh に拘りや思い入れがある訳でもなし、これ以上何かあったら Bash に戻すかも知れない。

2022-01-23

Zsh: local `path' variable causes `command not found'

訳あって Zsh を使うことになり、手持ちの Bash 資産を Zsh に対応させていた時のこと。下記のようなコードでハマった。

test.sh:

my_dirname() {
    local path=$1
    dirname "$path"
}

my_dirname "$@"
% zsh test.sh /path/to/file
my_dirname:2: command not found: dirname

Zsh 使いの人にとって、きっとこれは FAQ なのだろうな。Zsh の path 変数は特殊変数なので、path を書き換えることは PATH を書き換えることに等しい。しかしこれは Zsh 初心者の私にとっては完全に盲点だった。そもそも小文字の変数が特殊変数になるという発想がない。お陰で解決に 3 週間かかった。:-/

他にどういう特殊変数があるかは、man zshparam | grep -F '<S>' すれば分かるっぽい。それにしても path とか status とか、これらの変数名が使えないのは私には窮屈でしょうがない。正直これだけでも、私が Zsh を使いたくない理由になる。

% man zshbuiltins

<...snip...>

       typeset [ {+|-}AHUaghlmrtux ] [ {+|-}EFLRZip [ n ] ]
               [ + ] [ name[=value] ... ]
       typeset -T [ {+|-}Uglrux ] [ {+|-}LRZp [ n ] ]
               [ + | SCALAR[=value] array[=(value ...)] [ sep ] ]
       typeset -f [ {+|-}TUkmtuz ] [ + ] [ name ... ]
              Set or display attributes and values for shell parameters.

              <...snip...>

              -h     Hide:  only  useful  for special parameters (those marked
                     `<S>' in the table in zshparam(1)), and for local parame‐
                     ters  with  the  same name as a special parameter, though
                     harmless for others.  A special parameter with  this  at‐
                     tribute  will not retain its special effect when made lo‐
                     cal.  Thus after `typeset -h PATH', a function containing
                     `typeset  PATH'  will  create an ordinary local parameter
                     without the usual behaviour of PATH.  Alternatively,  the
                     local parameter may itself be given this attribute; hence
                     inside a function `typeset -h PATH' creates  an  ordinary
                     local parameter and the special PATH parameter is not al‐
                     tered in any way.  It is also possible to create a  local
                     parameter  using  `typeset  +h  special', where the local
                     copy of special will retain its  special  properties  re‐
                     gardless  of having the -h attribute.  Global special pa‐
                     rameters loaded from shell modules  (currently  those  in
                     zsh/mapfile  and  zsh/parameter)  are automatically given
                     the -h attribute to avoid name clashes.

どうやら typeset -h を使うと、特殊変数をローカル変数で隠せるようだ。このときエラー出力を捨てれば、Bash にも対応できる。

test2.sh:

my_dirname() {
    typeset -h path 2>/dev/null
    local path=$1
    dirname "$path"
}

my_dirname "$@"
% zsh test2.sh /path/to/file
/path/to

もしスクリプト全体で path を特殊変数として使わないと決められるなら、typeset -h をグローバルに置けば良い。逆に Bash を全く気にしないのであれば、「local -h path=...」と 1 行で書ける。

2022-01-15

Animes in the 4th quarter of 2021

アニメは IT エンジニアの必須科目です。 ということで簡単なレビューを。

第 1 クールでイマイチ感、第 2 クールでの挽回を期待するも、却ってつまらなくなった。仕事の苦悩とか見せられても面白くも何ともないんだけど。そして最後まで良く分からないキジムナー。

幾つか他作品からのエッセンスを色濃く感じるものの、オリジナリティはあると思う。ロボット CG とキャラは特徴的。ただ個人的には主人公の声が合わない。もっと別の配役があった気がする。

見るのが苦にならなかったので最後まで見ることはできたが、正直これといった面白さは感じなかった。強いて言うなら、ヒロインのルビー色の瞳の描写が印象的だったくらいか。

TE 視聴済み。デルタ襲来、ほのぼの学園生活、からの人間同士の紛争という展開が全く同じなんだけど。これはマブラヴの様式美か? 実は訳あっての視聴だったが、訳がなかったら速攻切ってた。

メディアミックス作品らしからぬ、アニメ単体としても十分に通用する出来。世界観も独特だし、何と言ってもムジカートのキャラデザが素晴らしい。最後は終わらせた感が強いが、十分に許せる。

これが名古屋リソースで作られたことに驚く。私が見た CG アニメの中では、一番滑らかかも知れない。とはいえまだセル画も多く、話も普通、中の人の演技もうーんだけど、その心意気は評価する。ところでギャバンは名古屋なの?

第一期は妙に力の入った作品だな、くらいの印象だった。第二期になって何やら風格のようなものが出てきた気がする。ギャグとシリアスのバランスが丁度良い。次期についても心配はなさそう。

丁寧に作られているとは感じる。いつか面白くなるかもという期待で見続けたが、むしろ冒険に出てからの方がつまらなくなるという結果に。次期も決まったらしいが、たぶんもう見ないと思う。

第一期と同様、新キャラが登場して美味しいものを食べて幸せになるという、つくづく平和な作品。これはこれで良いと思うが、流石にキャラが飽和してきた感がある。というか既に覚えられない。

第一期で見るのを止めて、今回「大満開」とあったので視聴。しかし相変わらず不幸が前面に出ていて辛い。そんな思いをするためにアニメを見てる訳じゃない。いい加減それに気付いてくれ。

内容がどうこういうよりも、ただ ED を聞くために見ていた。でもヒロインの似非方言は少しクセになるかも。今回は久保あおいを覚えた。

タイトルと絵柄から想像した通りの内容で、最後までストレスなく見られた。二人が近付き過ぎず程良い距離感のままで終わったのは良かったと思う。むしろサブキャラの二人の方は接近し過ぎ。

特に可もなく不可もなくストレスもなく、という感じで見続けていたが、途中からゴーストがウザ過ぎて一気に無理になった。結局まだ生きてるっぽいし、次期は絶対に見ないと断言できる。