| コメント(0) | トラックバック(0)

コマンドラインから行番号を指定してEmacsでファイルを開く 第1回の続きです。今回は grep による検索結果からコピーした ./Framework/TestCase.php:882: を直接 gnuclient に渡せるようにします。

KUBO Atsuhiro

Bashに代表されるUnix系OSのシェルは、対話的に使われるだけでなくスクリプト言語としてもよく使われています。シェルにはPerlやRubyのような汎用スクリプト言語が提供するような強力な機能はありませんが、Unix系OSにインストールされている豊富なコマンドを簡単に呼び出すことができるため、あたかも豊富な関数を持っている言語のように使うことができます。今回のようなコマンドラインの改善を行うものとして、シェルは最適なツールだといえるでしょう。筆者はBashを使っていますので、今回はBashの関数によって目的を達成したいと思います。

まずは形式を整えることから始めます。gnuclient をラップしただけの簡単な関数を.bashrcに追加します。

itemanbf_gnuclient() {
    /usr/bin/gnuclient -q "$1"
}

次に動作を確認します。

. ~/.bashrc
itemanbf_gnuclient ./Framework/TestCase.php

次に grep による検索結果から得られる文字列 ./Framework/TestCase.php:882:gnuclient -q +882 ./Framework/TestCase.php に変換するコードを実装します。変換するためのフローは下記のようになります。

  1. ./Framework/TestCase.php:882: からファイル名 ./Framework/TestCase.php を取り出す
  2. ./Framework/TestCase.php:882: から行番号 882 を取り出す
  3. gnuclient -q +882 ./Framework/TestCase.php を実行する

文字列から部分文字列を取り出すコマンドには sedcut があります。今回は正規表現によって特定の文字列パターンにマッチさせる必要があるため sed を使うことにします。まず、ファイル名を取り出すコードを書いてテストします。

itemanbf_gnuclient() {
    local file
    file=`echo $1 | sed -e 's/:[0-9]\+:\?$//'`
    echo "File: $file"
#     /usr/bin/gnuclient -q "$1"
}
$ . ~/.bashrc
$ itemanbf_gnuclient ./Framework/TestCase.php:882:
File: ./Framework/TestCase.php

次に、行番号を取り出すコードを追加しテストします。

itemanbf_gnuclient() {
    local file line
    file=`echo $1 | sed -e 's/:[0-9]\+:\?$//'`
    echo "File: $file"
    line=`echo $1 | sed -e 's/^.\+:\([0-9]\+\):\?$/\1/'`
    echo "Line: $line"
#     /usr/bin/gnuclient -q "$1"
}
$ . ~/.bashrc
$ itemanbf_gnuclient ./Framework/TestCase.php:882:
File: ./Framework/TestCase.php
Line: 882

上手く動作したら gnuclient の実行コードを変更します。

itemanbf_gnuclient() {
    local file line
    file=`echo $1 | sed -e 's/:[0-9]\+:\?$//'`
    line=`echo $1 | sed -e 's/^.\+:\([0-9]\+\):\?$/\1/'`
    /usr/bin/gnuclient -q +$line "$file"
}

最後に gnuclient の実行コードを変更します。上手く動作してくれるでしょうか。

$ . ~/.bashrc
$ itemanbf_gnuclient ./Framework/TestCase.php:882:
emacs-by-gnuclient-with-line-number2.png

上手くいきました!しかし、itemanbf_gnuclient は行番号を含むファイル名については動作しますが、含まないファイル名については動作しません。下記は行番号を含むか含まないかにかかわらず、きちんと動作するように変更を加えたものです。

itemanbf_gnuclient() {
    local file line retval
    file=`echo $1 | sed -e 's/:[0-9]\+:\?$//'`
    line=`echo $1 | sed -e 's/^.\+:\([0-9]\+\):\?$/\1/'`
    if [ $line = $file ]; then
        line=1
    fi
    /usr/bin/gnuclient -q +$line "$file"
}

上記では行番号を含まない場合に $line の値が $file と同じになることを利用してみました。さらに、引数が与えられなかった場合はヘルプを出力するように変更を加えたものを示します。

itemanbf_gnuclient() {
    if [ $# -eq 0 ]; then
        echo 'Usage: 1. itemanbf_gnuclient FILE'
        echo '       2. itemanbf_gnuclient FILE:LINE-NUMBER[:]'
        return 1
    fi

    local file line retval
    file=`echo $1 | sed -e 's/:[0-9]\+:\?$//'`
    line=`echo $1 | sed -e 's/^.\+:\([0-9]\+\):\?$/\1/'`
    if [ $line = $file ]; then
        line=1
    fi
    /usr/bin/gnuclient -q +$line "$file"
}

ヘルプを表示してみましょう。ちなみに、行番号の後ろの : (コロン)は省略できるようになっています。

$ . ~/.bashrc
$ itemanbf_gnuclient
Usage: 1. itemanbf_gnuclient FILE
       2. itemanbf_gnuclient FILE:LINE-NUMBER[:]

itemanbf_gnuclient という長い関数名では使いづらいのでエイリアスを定義しておきましょう。最終的なコードは下記のようになります。

itemanbf_gnuclient() {
    if [ $# -eq 0 ]; then
        echo 'Usage: 1. itemanbf_gnuclient FILE'
        echo '       2. itemanbf_gnuclient FILE:LINE-NUMBER[:]'
        return 1
    fi

    local file line retval
    file=`echo $1 | sed -e 's/:[0-9]\+:\?$//'`
    line=`echo $1 | sed -e 's/^.\+:\([0-9]\+\):\?$/\1/'`
    if [ $line = $file ]; then
        line=1
    fi
    /usr/bin/gnuclient -q +$line "$file"
}
alias gc=itemanbf_gnuclient

実際に便利になったのかを知るために前回と同様に具体的な手順を書き出してみます。

  1. gc△ を入力する(△は半角スペース)
  2. 検索結果の ./Framework/TestCase.php:882: 部分をダブルクリックする
  3. すると ./Framework/TestCase.php:882: 部分が反転するので Ctrl+C でコピーする
  4. 入力行に戻りペーストする
  5. Ctrl+M を入力してコマンドを実行する

前回9つあった手順が今回は5つになりました。まずまずの結果といえるのではないでしょうか。

参考文献

トラックバック(0)
  • このブログ記事のトラックバックURL:
コメント