gren 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +12 -1
- data/Rakefile +3 -1
- data/bin/gren +1 -1
- data/lib/gren.rb +1 -1
- data/lib/gren/cli.rb +13 -16
- data/lib/gren/findgrep.rb +148 -70
- metadata +21 -7
data/History.txt
CHANGED
@@ -1,6 +1,17 @@
|
|
1
|
+
=== 0.2.0 2010/08/xx
|
2
|
+
|
3
|
+
!!!公開前に...
|
4
|
+
英語にする
|
5
|
+
文章を綺麗にする
|
6
|
+
|
7
|
+
* --depth, --this で探索する階層数を指定出来るように
|
8
|
+
* -sでサイレントモード、マッチした行のみを表示する
|
9
|
+
* -f, --if, --idオプションを何個でも設定出来るように
|
10
|
+
* -cで色付き表示
|
11
|
+
|
1
12
|
=== 0.1.0 2010/08/02
|
2
13
|
|
3
|
-
*
|
14
|
+
* Update README.doc (to English).
|
4
15
|
|
5
16
|
=== 0.0.6 2010/07/29
|
6
17
|
|
data/Rakefile
CHANGED
@@ -18,7 +18,9 @@ $hoe = Hoe.spec 'gren' do
|
|
18
18
|
self.developer 'ongaeshi', 'ongaeshi0621@gmail.com'
|
19
19
|
self.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
20
20
|
self.rubyforge_name = self.name # TODO this is default value
|
21
|
-
|
21
|
+
|
22
|
+
# 必要とするgem
|
23
|
+
self.extra_deps = [['termcolor','>= 1.2.0']]
|
22
24
|
|
23
25
|
# 本来はnewgemの中で設定されるべき(後で報告した方がいいかも)
|
24
26
|
self.extra_rdoc_files << "README.rdoc"
|
data/bin/gren
CHANGED
data/lib/gren.rb
CHANGED
data/lib/gren/cli.rb
CHANGED
@@ -6,28 +6,25 @@ module Gren
|
|
6
6
|
class CLI
|
7
7
|
def self.execute(stdout, arguments=[])
|
8
8
|
# オプション
|
9
|
-
option = FindGrep::Option.new(false, false,
|
9
|
+
option = FindGrep::Option.new(".", -1, false, false, false, false, [], [], [])
|
10
10
|
|
11
11
|
# オプション解析
|
12
|
-
opt = OptionParser.new("#{File.basename($0)} [option] pattern
|
12
|
+
opt = OptionParser.new("#{File.basename($0)} [option] pattern")
|
13
|
+
opt.on('-d DIR', '--directory DIR', 'Start directory. (deafult:".")') {|v| option.directory = v}
|
14
|
+
opt.on('--depth DEPTH', 'Limit search depth. ') {|v| option.depth = v.to_i}
|
15
|
+
opt.on('--this', '"--depth 0"') {|v| option.depth = 0}
|
13
16
|
opt.on('-i', '--ignore', 'Ignore case.') {|v| option.ignoreCase = true}
|
14
|
-
opt.on('-
|
15
|
-
opt.on('
|
16
|
-
opt.on('
|
17
|
-
opt.on('
|
17
|
+
opt.on('-s', '--silent', 'Silent. Display match line only.') {|v| option.isSilent = true}
|
18
|
+
opt.on('--debug', 'Debug display.') {|v| option.debugMode = true}
|
19
|
+
opt.on('-c', 'Color highlight.') {|v| option.colorHighlight = true}
|
20
|
+
opt.on('-f REGEXP', '--file-regexp REGEXP', 'Search file regexp. (Enable multiple call)') {|v| option.filePatterns << v}
|
21
|
+
opt.on('--if REGEXP', '--ignore-file REGEXP', 'Ignore file pattern. (Enable multiple call)') {|v| option.ignoreFiles << v}
|
22
|
+
opt.on('--id REGEXP', '--ignore-dir REGEXP', 'Ignore dir pattern. (Enable multiple call)') {|v| option.ignoreDirs << v}
|
18
23
|
opt.parse!(arguments)
|
19
24
|
|
20
25
|
# 検索オブジェクトの生成
|
21
|
-
|
22
|
-
|
23
|
-
case ARGV.length
|
24
|
-
when 1:
|
25
|
-
findGrep = FindGrep.new(arguments[0], '.', option)
|
26
|
-
when 2:
|
27
|
-
findGrep = FindGrep.new(arguments[0], arguments[1], option)
|
28
|
-
end
|
29
|
-
|
30
|
-
if (findGrep)
|
26
|
+
if (ARGV.size > 0)
|
27
|
+
findGrep = FindGrep.new(arguments, option)
|
31
28
|
findGrep.searchAndPrint(stdout)
|
32
29
|
else
|
33
30
|
stdout.print opt.help
|
data/lib/gren/findgrep.rb
CHANGED
@@ -1,80 +1,122 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require 'find'
|
3
3
|
require File.join(File.dirname(__FILE__), 'result')
|
4
|
+
require 'rubygems'
|
5
|
+
require 'termcolor'
|
4
6
|
|
5
7
|
module Gren
|
6
8
|
class FindGrep
|
7
9
|
IGNORE_FILE = /(\A#.*#\Z)|(~\Z)|(\A\.#)/
|
8
10
|
IGNORE_DIR = /(\A\.svn\Z)|(\A\.git\Z)|(\ACVS\Z)/
|
9
11
|
|
10
|
-
Option = Struct.new(:
|
12
|
+
Option = Struct.new(:directory,
|
13
|
+
:depth,
|
14
|
+
:ignoreCase,
|
15
|
+
:colorHighlight,
|
16
|
+
:isSilent,
|
17
|
+
:debugMode,
|
18
|
+
:filePatterns,
|
19
|
+
:ignoreFiles,
|
20
|
+
:ignoreDirs)
|
11
21
|
|
12
|
-
def initialize(
|
13
|
-
@pattern = pattern
|
14
|
-
@dir = dir
|
22
|
+
def initialize(patterns, option)
|
15
23
|
@option = option
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@result = Result.new(
|
24
|
+
@patternRegexps = strs2regs(patterns, @option.ignoreCase)
|
25
|
+
@filePatterns = strs2regs(option.filePatterns)
|
26
|
+
@ignoreFiles = strs2regs(option.ignoreFiles)
|
27
|
+
@ignoreDirs = strs2regs(option.ignoreDirs)
|
28
|
+
@result = Result.new(option.directory)
|
21
29
|
end
|
22
30
|
|
23
|
-
def
|
24
|
-
|
25
|
-
fpath_disp = fpath.gsub(/^.\//, "")
|
26
|
-
|
27
|
-
# 除外ディレクトリ
|
28
|
-
if ignoreDir?(fpath)
|
29
|
-
@result.prune_dirs << fpath_disp if (@option.fpathDisp)
|
30
|
-
Find.prune
|
31
|
-
end
|
31
|
+
def strs2regs(strs, ignore = false)
|
32
|
+
regs = []
|
32
33
|
|
33
|
-
|
34
|
-
|
34
|
+
strs.each do |v|
|
35
|
+
option = 0
|
36
|
+
option |= Regexp::IGNORECASE if (ignore)
|
37
|
+
regs << Regexp.new(v, option)
|
38
|
+
end
|
35
39
|
|
36
|
-
|
37
|
-
|
38
|
-
# 読み込み不可ならば探索しない
|
39
|
-
unless FileTest.readable?(fpath)
|
40
|
-
@result.unreadable_files << fpath_disp if (@option.fpathDisp)
|
41
|
-
next
|
42
|
-
end
|
43
|
-
|
44
|
-
@result.size += FileTest.size(fpath)
|
40
|
+
regs
|
41
|
+
end
|
45
42
|
|
46
|
-
|
47
|
-
|
48
|
-
@result.ignore_files << fpath_disp if (@option.fpathDisp)
|
49
|
-
next
|
50
|
-
end
|
51
|
-
|
52
|
-
@result.search_count += 1
|
53
|
-
@result.search_size += FileTest.size(fpath)
|
43
|
+
def searchAndPrint(stdout)
|
44
|
+
searchAndPrintIN(stdout, @option.directory, 0)
|
54
45
|
|
55
|
-
# 検索
|
56
|
-
searchMain(stdout, fpath, fpath_disp)
|
57
|
-
}
|
58
|
-
|
59
46
|
@result.time_stop
|
60
47
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
48
|
+
unless (@option.isSilent)
|
49
|
+
if (@option.debugMode)
|
50
|
+
stdout.puts
|
51
|
+
stdout.puts "--- search --------"
|
52
|
+
print_fpaths stdout, @result.search_files
|
53
|
+
stdout.puts "--- match --------"
|
54
|
+
print_fpaths stdout, @result.match_files
|
55
|
+
stdout.puts "--- ignore-file --------"
|
56
|
+
print_fpaths stdout, @result.ignore_files
|
57
|
+
stdout.puts "--- ignore-dir --------"
|
58
|
+
print_fpaths stdout, @result.prune_dirs
|
59
|
+
stdout.puts "--- unreadable --------"
|
60
|
+
print_fpaths stdout, @result.unreadable_files
|
61
|
+
end
|
62
|
+
|
63
|
+
unless (@option.colorHighlight)
|
64
|
+
stdout.puts
|
65
|
+
else
|
66
|
+
stdout.puts TermColor.parse("<7>------------------------------------------------------------</7>")
|
67
|
+
end
|
68
|
+
|
69
|
+
@result.print(stdout)
|
73
70
|
end
|
71
|
+
end
|
74
72
|
|
75
|
-
|
76
|
-
@
|
73
|
+
def searchAndPrintIN(stdout, dir, depth)
|
74
|
+
if (@option.depth == -1 || depth > @option.depth)
|
75
|
+
return
|
76
|
+
end
|
77
|
+
|
78
|
+
Dir.foreach(dir) do |name|
|
79
|
+
if name != '.' and name != '..' then
|
80
|
+
fpath = File.join(dir,name)
|
81
|
+
fpath_disp = fpath.gsub(/^.\//, "")
|
82
|
+
|
83
|
+
# 除外ディレクトリ
|
84
|
+
if ignoreDir?(fpath)
|
85
|
+
@result.prune_dirs << fpath_disp if (@option.debugMode)
|
86
|
+
next;
|
87
|
+
end
|
88
|
+
|
89
|
+
# ファイルでなければ次のディレクトリへ
|
90
|
+
unless FileTest.file?(fpath)
|
91
|
+
searchAndPrintIN(stdout, fpath, depth + 1)
|
92
|
+
next;
|
93
|
+
end
|
94
|
+
|
95
|
+
@result.count += 1
|
96
|
+
|
97
|
+
# 読み込み不可ならば探索しない
|
98
|
+
unless FileTest.readable?(fpath)
|
99
|
+
@result.unreadable_files << fpath_disp if (@option.debugMode)
|
100
|
+
next
|
101
|
+
end
|
102
|
+
|
103
|
+
@result.size += FileTest.size(fpath)
|
104
|
+
|
105
|
+
# 除外ファイル
|
106
|
+
if ignoreFile?(fpath)
|
107
|
+
@result.ignore_files << fpath_disp if (@option.debugMode)
|
108
|
+
next
|
109
|
+
end
|
110
|
+
|
111
|
+
@result.search_count += 1
|
112
|
+
@result.search_size += FileTest.size(fpath)
|
113
|
+
|
114
|
+
# 検索
|
115
|
+
searchMain(stdout, fpath, fpath_disp)
|
116
|
+
end
|
117
|
+
end
|
77
118
|
end
|
119
|
+
private :searchAndPrintIN
|
78
120
|
|
79
121
|
def print_fpaths(stdout, data)
|
80
122
|
stdout.print data.join("\n")
|
@@ -84,46 +126,67 @@ module Gren
|
|
84
126
|
end
|
85
127
|
private :print_fpaths
|
86
128
|
|
87
|
-
def makePattenRegexp
|
88
|
-
option = 0
|
89
|
-
option |= Regexp::IGNORECASE if (@option.ignoreCase)
|
90
|
-
Regexp.new(@pattern, option)
|
91
|
-
end
|
92
|
-
private :makePattenRegexp
|
93
|
-
|
94
129
|
def ignoreDir?(fpath)
|
95
130
|
FileTest.directory?(fpath) &&
|
96
|
-
(IGNORE_DIR.match(File.basename(fpath)) ||
|
97
|
-
(@ignoreDir && @ignoreDir.match(File.basename(fpath))))
|
131
|
+
(IGNORE_DIR.match(File.basename(fpath)) || ignoreDirUser?(fpath))
|
98
132
|
end
|
99
133
|
private :ignoreDir?
|
100
134
|
|
135
|
+
def ignoreDirUser?(fpath)
|
136
|
+
@ignoreDirs.any? {|v| v.match File.basename(fpath) }
|
137
|
+
end
|
138
|
+
private :ignoreDirUser?
|
139
|
+
|
101
140
|
def ignoreFile?(fpath)
|
102
|
-
|
141
|
+
!correctFileUser?(fpath) ||
|
103
142
|
IGNORE_FILE.match(File.basename(fpath)) ||
|
104
|
-
(
|
143
|
+
ignoreFileUser?(fpath) ||
|
105
144
|
binary?(fpath)
|
106
145
|
end
|
107
146
|
private :ignoreFile?
|
108
147
|
|
148
|
+
def correctFileUser?(fpath)
|
149
|
+
@filePatterns.empty? ||
|
150
|
+
@filePatterns.any? {|v| v.match File.basename(fpath) }
|
151
|
+
end
|
152
|
+
private :correctFileUser?
|
153
|
+
|
154
|
+
def ignoreFileUser?(fpath)
|
155
|
+
@ignoreFiles.any? {|v| v.match File.basename(fpath) }
|
156
|
+
end
|
157
|
+
private :ignoreFileUser?
|
158
|
+
|
109
159
|
def binary?(file)
|
110
160
|
s = File.read(file, 1024) or return false
|
111
161
|
return s.index("\x00")
|
112
162
|
end
|
113
163
|
|
114
164
|
def searchMain(stdout, fpath, fpath_disp)
|
115
|
-
@result.search_files << fpath_disp if (@option.
|
165
|
+
@result.search_files << fpath_disp if (@option.debugMode)
|
116
166
|
|
117
167
|
open(fpath, "r") { |file|
|
118
168
|
match_file = false
|
119
169
|
file.each() { |line|
|
120
170
|
line.chomp!
|
121
|
-
|
122
|
-
|
171
|
+
|
172
|
+
result, match_datas = match?(line)
|
173
|
+
|
174
|
+
if ( result )
|
175
|
+
unless (@option.colorHighlight)
|
176
|
+
stdout.puts "#{fpath_disp}:#{file.lineno}:#{line}"
|
177
|
+
else
|
178
|
+
header = "#{fpath_disp}:#{file.lineno}"
|
179
|
+
|
180
|
+
begin
|
181
|
+
stdout.puts TermColor.parse("<34>#{header}</34>:") + coloring(line, match_datas)
|
182
|
+
rescue REXML::ParseException
|
183
|
+
stdout.puts header + line
|
184
|
+
end
|
185
|
+
end
|
123
186
|
|
124
187
|
unless match_file
|
125
188
|
@result.match_file_count += 1
|
126
|
-
@result.match_files << fpath_disp if (@option.
|
189
|
+
@result.match_files << fpath_disp if (@option.debugMode)
|
127
190
|
match_file = true
|
128
191
|
end
|
129
192
|
|
@@ -134,5 +197,20 @@ module Gren
|
|
134
197
|
end
|
135
198
|
private :searchMain
|
136
199
|
|
200
|
+
def match?(line)
|
201
|
+
match_datas = []
|
202
|
+
@patternRegexps.each {|v| match_datas << v.match(line)}
|
203
|
+
return match_datas.all?, match_datas
|
204
|
+
end
|
205
|
+
private :match?
|
206
|
+
|
207
|
+
def coloring(line, match_datas)
|
208
|
+
match_datas.each do |m|
|
209
|
+
line = line.split(m[0]).join(TermColor.parse("<42>#{m[0]}</42>"))
|
210
|
+
end
|
211
|
+
line
|
212
|
+
end
|
213
|
+
private :coloring
|
214
|
+
|
137
215
|
end
|
138
216
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- ongaeshi
|
@@ -14,13 +14,27 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-08-
|
17
|
+
date: 2010-08-05 00:00:00 +09:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: termcolor
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 0
|
31
|
+
version: 1.2.0
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rubyforge
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
24
38
|
requirements:
|
25
39
|
- - ">="
|
26
40
|
- !ruby/object:Gem::Version
|
@@ -30,11 +44,11 @@ dependencies:
|
|
30
44
|
- 4
|
31
45
|
version: 2.0.4
|
32
46
|
type: :development
|
33
|
-
version_requirements: *
|
47
|
+
version_requirements: *id002
|
34
48
|
- !ruby/object:Gem::Dependency
|
35
49
|
name: hoe
|
36
50
|
prerelease: false
|
37
|
-
requirement: &
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
38
52
|
requirements:
|
39
53
|
- - ">="
|
40
54
|
- !ruby/object:Gem::Version
|
@@ -44,7 +58,7 @@ dependencies:
|
|
44
58
|
- 1
|
45
59
|
version: 2.6.1
|
46
60
|
type: :development
|
47
|
-
version_requirements: *
|
61
|
+
version_requirements: *id003
|
48
62
|
description: gren is a next grep tool.
|
49
63
|
email:
|
50
64
|
- ongaeshi0621@gmail.com
|