Paper Plane xUI(PPx)からエントリーへのgrep

[前回の記事](http://qiita.com/wordijp/items/4d73c77f2993c309e246)ではエントリーへのfindを行いました、今回はそのgrep版です。

# デモ

![grepdemo.gif](https://qiita-image-store.s3.amazonaws.com/0/51728/0b0089f7-5342-e8f6-71ab-5bc4bf0c23d8.gif)

文字コードに違いがあっても、その違いを意識する必要はないはずです、検証したのはsjisとutf8のみですが、Rubyの文字コード変換処理が賢ければeuc-jpやutf-16等の文字コードでも問題ないはずです、マルチバイト文字の場合はjvgrepのSupported Encodingsの通りです。

grep用のメニューは「Ctrl+G」で開く設定にしています、5種類用意しています、ascii文字はgrep、日本語等のマルチバイト文字はjvgrepと使い分けています。

- grep -l
    - 検索文字がascii時のファイル単位
- jvgrep -l
    - 検索文字がマルチバイト時のファイル単位
- grep -n
    - 検索文字がascii時の行単位
- jvgrep -n
    - 検索文字がマルチバイト時の行単位
- grep entry string
    - エントリ文字列の検索(ascii、マルチバイトどちらもOK)

ptコマンド等、asciiとマルチバイト文字の両対応なgrep亜種はあるんですが、検索オプションがgrepとがらっと変わるので、メニュー数は増えてしまいますがgrepとjvgrepを使い分けています。

grep entry stringは特殊で、エントリー文字列自体をgrepします、「find . | xargs grep 検索文字1 | grep 検索文字2」のように、grepのand処理をしたい時に利用します。

# ツール構成

## jvgrep

こちらで配布されています。
[mattn/jvgrep](https://github.com/mattn/jvgrep) - [Binary](https://github.com/mattn/jvgrep/releases)

## tolistfilegrepn.rb

[前回の記事のtolistfile.rb](http://qiita.com/wordijp/items/4d73c77f2993c309e246#tolistfilerb)から、grep -n専用として作成しています。
マルチバイト文字を含むテキストにgrep -nを実行した場合、結果文字列にマルチバイト文字が含まれている場合の文字コードは

    utf8(ファイルパス):ascii(行番号):sjis等(内容)

となります、これをそのままListFile用のsjisに変換できません、その為、文字列を分割してそれぞれの文字コードを変換してからまた結合しています。

```rb:tolistfilegrepn.rb
# coding: utf-8
#
# grep -nの行単位の検索結果専用
#

require 'kconv'

def putsUtf8(str)
  puts NKF.nkf('-w', str)
end

putsUtf8 ";ListFile"
putsUtf8 ";Base=" + `cwd`
# Windows用バイナリのRubyならこちらでも良い
#putsUtf8 ";Base=" + Dir.pwd.gsub(/\//, '\\')

ARGV.each{|arg|
  putsUtf8 arg
}

while STDIN.gets
  begin
    # 複数の文字コードが混じってる一行を、utf8へ統一する
    # NOTE : 文字コードがsjisのファイルへのgrep -n結果は「utf8文字列:行数:sjis文字列」となっているため、
    #        分割して個別に文字コード変換する
    puts $_.split(':')
      .map(){|token| NKF.nkf('-w', token)}
      .join(':')
  rescue ArgumentError => e
    # すでにutf-8
    puts $_
  end
end
```

## loadevent.js

(grep | jvgrep) -nのコマンド群実行時にviewstyleをgrep -n用に変更しているので、ListFile以外を開いたら元に戻すようにしています。
ただ、この設定は影響範囲が広いので、合わなければコマンド群側とこのスクリプトのviewstyle変更は削除してください。

```js:loadevent.js
//!*script

//
// LOADEVENT処理
//

// ListFileの場合
var VFSDT_LFILE = 4; // 4:ListFile

if (PPx.DirectoryType == VFSDT_LFILE) {
	// 19: 読み込み順ソート
	PPx.Execute('*sortentry 19');
	// タブ色
	PPx.Execute('*pane color t,_BLA,_GRE');
} else {
	PPx.Execute('*pane color t,_AUTO,_AUTO');
	PPx.Execute('*viewstyle -temp "default"'); // 影響範囲が広いので欲しい時だけ有効
}
```


## PPx設定

差分のみです。
(grep | jvgrep) -nの時だけviewstyleを変更しています、それと、jvgrepは結果のパスが「\」区切りなので、grepと統一するためにgawkで「/」へと変換しています。

※自身の設定が消えないように、適用前にバックアップを取るか、追加取り込みをしてください
※スクリプトのパスは自身の環境へと合わせて下さい

```:PPx.CFG
MC_celS	= {	; エントリ表示 書式([;]メニュー)
GrepN	= wf30
}

KC_main	= {	; PPcメイン窓
^W	,%M_menuCustomGrep
}

M_menuCustomGrep	= {	** comment **
grep -&l(ascii | utf8)(一致ファイル検索)	= 
	*set dummy='エントリへのgrep -l'
	*set ENTRY_FILE=%'temp'\entryfile.tmp
	*set CIN_LSTFILE=%'temp'\cin2listfile.tmp
	*set ARG=%"xargs grep -lオプション(-i:大小無視,-E:拡張正規表現,-w:単語単位,-L:以外)"%{-i -E "%|word%|"%}
	*set CMD=xargs grep -l %'ARG'
	*script %0\script\entry2file.js, %'ENTRY_FILE'
	%Obsq cat %'ENTRY_FILE' | nkf -Lu -w | %'CMD' | ruby %0\script\shell\tolistfile.rb ';MySearch=%'CMD'' | nkf -Lw -s > %'CIN_LSTFILE'
	*jumppath %'CIN_LSTFILE'
jvgrep -&l(日本語)(一致ファイル検索)	= 
	*set dummy='エントリへのjvgrep -l'
	*set ENTRY_FILE=%'temp'\entryfile.tmp
	*set CIN_LSTFILE=%'temp'\cin2listfile.tmp
	*set ARG=%"xargs jvgrep -lオプション"%{"%|word%|"%}
	*set CMD=xargs jvgrep -8 -r --no-color -l %'ARG'
	*set LAWK=gawk '{gsub(/\\\\/, "/", $0); print "./" $0;}'
	*script %0\script\entry2file.js, %'ENTRY_FILE'
	%Obsq cat %'ENTRY_FILE' | nkf -Lu -w | %'CMD' | %'LAWK' | ruby %0\script\shell\tolistfile.rb ';MySearch=%'CMD'' | nkf -Lw -s > %'CIN_LSTFILE'
	*jumppath %'CIN_LSTFILE'
grep -&n(ascii | utf8)(一致行検索)	= 
	*set dummy='エントリへのgrep -nH'
	*set ENTRY_FILE=%'temp'\entryfile.tmp
	*set CIN_LSTFILE=%'temp'\cin2listfile.tmp
	*set ARG=%"xargs grep -nH --textオプション(-i:大小無視,-E:拡張正規表現,-w:単語単位,-v:以外)"%{-i -E "%|word%|"%}
	*set CMD=xargs grep -nH --text %'ARG'
	*script %0\script\entry2file.js, %'ENTRY_FILE'
	%Obsq cat %'ENTRY_FILE' | nkf -Lu -w | %'CMD' | ruby %0\script\shell\tolistfilegrepn.rb ';MySearch=%'CMD'' | nkf -Lw -s > %'CIN_LSTFILE'
	*jumppath %'CIN_LSTFILE'
	*set dummy='loadevent.js'と設定を合わせる
	*viewstyle -temp GrepN
jvgrep -&n(日本語)(一致行検索)	= 
	*set dummy='エントリへのjvgrep -n'
	*set ENTRY_FILE=%'temp'\entryfile.tmp
	*set CIN_LSTFILE=%'temp'\cin2listfile.tmp
	*set ARG=%"xargs jvgrepオプション(-v:以外)"%{"%|word%|"%}
	*set CMD=xargs jvgrep -8 -r --no-color -n %'ARG'
	*set NAWK=gawk '{idx=index($0, ":"); path=substr($0, 0, idx-1); str=substr($0, idx); gsub(/\\\\/, "/", path); print "./" path str;}'
	*script %0\script\entry2file.js, %'ENTRY_FILE'
	%Obsq cat %'ENTRY_FILE' | nkf -Lu -w | %'CMD' | %'NAWK' | ruby %0\script\shell\tolistfile.rb ';MySearch=%'CMD'' | nkf -Lw -s > %'CIN_LSTFILE'
	*jumppath %'CIN_LSTFILE'
	*set dummy='loadevent.js'と設定を合わせる
	*viewstyle -temp GrepN
grep entry &string(エントリ文字列の検索)	= 
	*set dummy='エントリ文字列へのgrep'
	*set ENTRY_FILE=%'temp'\entryfile.tmp
	*set CIN_LSTFILE=%'temp'\cin2listfile.tmp
	*set ARG=%"grep --textオプション(-i:大小無視,-E:拡張正規表現,-w:単語単位,-v:以外)"%{-i -E "%|word%|"%}
	*set CMD=grep --text %'ARG'
	*script %0\script\entry2file.js, %'ENTRY_FILE'
	%Obsq cat %'ENTRY_FILE' | nkf -Lu -w | %'CMD' | ruby %0\script\shell\tolistfile.rb ';MySearch=%'CMD'' | nkf -Lw -s > %'CIN_LSTFILE'
	*jumppath %'CIN_LSTFILE'
}
```