2013-12-11

タブ補完(その0) - Bash Advent Calendar - Day 11

ネタがない。

準備

基本的にありものを使ってね、というのは嫌なのですが、まずは bash-completion というパッケージを導入するのが近道です。そこで共通で使われてる関数達が超絶便利なんです。とりあえず、それをインストールしたら今日はおしまいです。続きは明日。

仕様

ユーザーが入力している情報

とりあえず、自作関数で補完をしようとした場合、以下の変数のお世話になります。

  • COMP_WORDS
    現在入力中の行が、単語分割されて、配列として格納されています。ただし、単語分割は Bash の文法とは関係なく、readline というライブラリが好き勝手に分割してくれます。
  • COMP_WORDBREAKS
    上記 readline ライブラリが単語と単語の区切りとみなす文字のリスト。 参照オンリーです。この値を変更することは可能ですが、この値を変更しても readline ライブラリは何もしてくれません。昔は変更すると Bash が死んで楽しかったのですが、最近はそんなことはさすがにないみたいです。
  • COMP_CWORD
    現在カーソルがある場所の、その単語が COMP_WORDS で格納されている位置。
  • COMP_LINE
    現在入力中の行全体。
  • COMP_POINT
    現在のカーソルの場所、COMP_LINEでの文字位置に相当(0スタートなので、行末にカーソルがある場合はCOMP_POINTの長さに同じ)
他にも少し、名前が COMP_ で始まる変数があるのですが、使い道がよくわかりません。

とりあえず ${COMP_WORDS[COMP_CWORD]} で「何となく」のカーソル位置の単語が取れるのですが、COMP_WORDBREAKS に中の文字がカーソル位置の単語に含まれている場合にうまくいきません。

補完候補をユーザーに返す方法

COMPREPLYという配列変数に文字列をセットすると、それらが補完候補とみなされます。これはグローバル変数なので、なんの気にもせず上書きしてオッケーです。

TABでの補完時に自作関数が使われるようにする

complete -F 関数名 [-o オプション [-o オプション]... ] コマンド名
で登録が可能です。オプションは以下から複数指定が可能です、というか機能的にどうみても複数指定可能じゃないとおかしいだけど、man ページ読んだだけじゃ分からないよ。
  • bashdefault
    COMPREPLY の中身が空だったら、Bashのデフォルト動作(ファイル名補完とか、変数名補完とか)をする。自作関数がしょぼくて(意図せず)何も補完候補を返せなくても、全く補完をしない代わりにそれっぽい補完候補を返してくれる。他人に使って貰う場合には必須のオプションw
  • default
    bashdefault とほぼ一緒だけど、readline のデフォルト動作をする。と、man ページには書いてあるが、じゃー readline がデフォルトでどんな補完してくれるのかというのはどこにも書いてない。よく分からん。とりあえず、ファイル名補完、~展開、環境変数の変数名補完ぐらいはしてくれる気がする。
  • dirnames
    上のやつらと一緒で、COMPREPLYが空だった場合の動作指定。dirnamesはディレクトリ名補完をしてくれる。mount コマンドのように、オプションじゃない部分はがディレクトリ名と確定しているような場合に使う。ので、普通はこれ単独で使う機会はそうそうない。
  • filenames
    これまた上のやつらの仲間。-o dirnames -o filenames とすると、まーそれっぽい動作はする。ユーザーにデフォルトでは変数名補完とかさせたくない、という偏屈な人は "-o dirnames -o filenames" とかすればいいよ!
  • nospace
    このオプションが指定された場合、補完した結果の末尾に自動的にスペースを追加しない。たとえば "ホスト名:パス" のホスト名(と後続のコロン)だけを補完させる場合、勝手にスペースを追加されると困りますよね。そんな場合に使うのですが、この場合「パス」の後ろにはスペースを追加したいわけでして、自力で補完候補に適宜スペースを追加するという面倒な作業が発生します。
  • plusdirs
    このオプションが指定された場合、補完結果がディレクトリ名(の一部)だとみなし、ディレクトリ名補完を追加でおこないます。って書いてみたけどさっぱり意味がわからない。特定のディレクトリを除いてディレクトリ名補完をしたい、というような場合(昔で言えば CSV/ とか RCS/ とかを補完候補に出させない)に使うのかもしれません。
仕様としては以上です。これで君も明日から補完マスター。

なんてことがあるなら、こんなブログを読んでないでしょう。というわけで明日に続きます。

0 件のコメント:

prometheusのrate()関数の罠

 久しぶりのAdventカレンダー挑戦、うまくいく気がしません。 閑話休題。実のところ、rate()関数というよりは、サーバー側のmetric初期化問題です。 さて、何らかのサーバーAがあったとして、それが更に他のサーバーBにRPCを送っているとします。サーバーBの方でホワイトボ...