gren 0.3.2 → 1.0.0
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/.gitignore +17 -0
- data/Gemfile +7 -0
- data/{History.ja.txt → HISTORY.ja.md} +41 -15
- data/HISTORY.md +92 -0
- data/LICENSE.txt +22 -0
- data/README.ja.md +57 -0
- data/README.md +51 -0
- data/Rakefile +9 -39
- data/bin/gren +2 -7
- data/gren.gemspec +21 -0
- data/lib/gren.rb +3 -3
- data/lib/gren/cli.rb +13 -10
- data/lib/{common → gren/common}/grenfiletest.rb +0 -0
- data/lib/{common → gren/common}/grensnip.rb +1 -1
- data/lib/{common → gren/common}/platform.rb +0 -0
- data/lib/{common → gren/common}/string_snip.rb +0 -0
- data/lib/{common → gren/common}/util.rb +16 -10
- data/lib/{findgrep → gren/findgrep}/findgrep.rb +47 -143
- data/lib/{findgrep → gren/findgrep}/result.rb +1 -1
- data/lib/gren/version.rb +3 -0
- data/test/data/aaa.txt +1 -0
- data/test/data/abc.rb +8 -0
- data/test/data/bbb.txt +1 -0
- data/test/data/ccc.c +1 -0
- data/test/data/sub/ccc.txt +1 -0
- data/test/test_cli.rb +80 -0
- data/test/test_gren.rb +10 -10
- data/test/test_gren_util.rb +3 -2
- data/test/test_string_snip.rb +31 -31
- metadata +67 -177
- data/History.txt +0 -66
- data/Manifest.txt +0 -48
- data/PostInstall.txt +0 -7
- data/README.rdoc +0 -181
- data/bin/grendb +0 -11
- data/bin/grenweb +0 -11
- data/bin/mkgrendb +0 -11
- data/lib/common/display_util.rb +0 -62
- data/lib/grendb/cli.rb +0 -41
- data/lib/grenweb/cli.rb +0 -52
- data/lib/grenweb/database.rb +0 -179
- data/lib/grenweb/grenweb.ru +0 -35
- data/lib/grenweb/grep.rb +0 -52
- data/lib/grenweb/help.rb +0 -39
- data/lib/grenweb/home.rb +0 -39
- data/lib/grenweb/html_renderer.rb +0 -243
- data/lib/grenweb/public/css/gren.css +0 -63
- data/lib/grenweb/public/images/gren-icon-mini.png +0 -0
- data/lib/grenweb/public/images/gren-icon.png +0 -0
- data/lib/grenweb/query.rb +0 -82
- data/lib/grenweb/searcher.rb +0 -129
- data/lib/grenweb/viewer.rb +0 -51
- data/lib/mkgrendb/cli.rb +0 -49
- data/lib/mkgrendb/mkgrendb.rb +0 -230
- data/rake_rdoc_custom.rb +0 -13
- data/script/console +0 -10
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/test/test_grenweb_cli.rb +0 -10
- data/test/test_grenweb_html_renderer.rb +0 -41
- data/test/test_grenweb_query.rb +0 -54
- data/test/test_grenweb_searcher.rb +0 -35
data/gren.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gren/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "gren"
|
8
|
+
gem.version = Gren::VERSION
|
9
|
+
gem.authors = ["ongaeshi"]
|
10
|
+
gem.email = ["ongaeshi0621@gmail.com"]
|
11
|
+
gem.description = %q{gren is a next grep tool.}
|
12
|
+
gem.summary = %q{gren is a next grep tool. The basis is find+grep.}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency 'termcolor','>= 1.2.0'
|
21
|
+
end
|
data/lib/gren.rb
CHANGED
data/lib/gren/cli.rb
CHANGED
@@ -1,33 +1,36 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require 'optparse'
|
3
|
-
require
|
3
|
+
require 'gren/findgrep/findgrep'
|
4
4
|
|
5
5
|
module Gren
|
6
6
|
class CLI
|
7
7
|
def self.execute(stdout, arguments=[])
|
8
8
|
# オプション
|
9
|
-
option = FindGrep::FindGrep::
|
9
|
+
option = FindGrep::FindGrep::create_default_option
|
10
|
+
option.isSilent = true
|
10
11
|
|
11
12
|
# オプション解析
|
12
13
|
opt = OptionParser.new("#{File.basename($0)} [option] pattern")
|
13
14
|
opt.on('--not PATTERN', 'Keyword is not included.') {|v| option.keywordsNot << v}
|
14
15
|
opt.on('--or PATTERN', 'Either of keyword is contained.') {|v| option.keywordsOr << v}
|
16
|
+
opt.on('-c', '--color', 'Color highlight.') {|v| option.colorHighlight = true}
|
17
|
+
opt.on('--cs', '--case-sensitive', 'Case sensitivity.') {|v| option.caseSensitive = true }
|
15
18
|
opt.on('-d DIR', '--directory DIR', 'Start directory. (deafult:".")') {|v| option.directory = v}
|
16
|
-
opt.on('--depth DEPTH', 'Limit search depth. ') {|v| option.depth = v.to_i}
|
17
|
-
opt.on('--this', '"--depth 0"') {|v| option.depth = 0}
|
18
|
-
opt.on('-i', '--ignore', 'Ignore case.') {|v| option.ignoreCase = true}
|
19
|
-
opt.on('-s', '--silent', 'Silent. Display match line only.') {|v| option.isSilent = true}
|
20
19
|
opt.on('--debug', 'Debug display.') {|v| option.debugMode = true}
|
21
|
-
opt.on('
|
20
|
+
opt.on('--depth DEPTH', 'Limit search depth. ') {|v| option.depth = v.to_i}
|
21
|
+
opt.on('-e ENCODE', '--encode ENCODE', 'Specify encode(none, auto, jis, sjis, euc, ascii, utf8, utf16). Default is "auto"') {|v| setupEncodeOption(option, v) }
|
22
22
|
opt.on('-f REGEXP', '--file-regexp REGEXP', 'Search file regexp. (Enable multiple call)') {|v| option.filePatterns << v}
|
23
|
-
opt.on('
|
23
|
+
opt.on('-i', '--ignore', 'Ignore case.') {|v| option.ignoreCase = true}
|
24
24
|
opt.on('--id REGEXP', '--ignore-dir REGEXP', 'Ignore dir pattern. (Enable multiple call)') {|v| option.ignoreDirs << v}
|
25
|
-
opt.on('
|
25
|
+
opt.on('--if REGEXP', '--ignore-file REGEXP', 'Ignore file pattern. (Enable multiple call)') {|v| option.ignoreFiles << v}
|
26
26
|
opt.on('--no-snip', 'There being a long line, it does not snip.') {|v| option.noSnip = true }
|
27
|
+
opt.on('--silent', 'Silent. Display match line only.') {|v| option.isSilent = true}
|
28
|
+
opt.on('--this', '"--depth 0"') {|v| option.depth = 0}
|
29
|
+
opt.on('-v', '--verbose', 'Set the verbose level of output.') {|v| option.isSilent = false }
|
27
30
|
opt.parse!(arguments)
|
28
31
|
|
29
32
|
# 検索オブジェクトの生成
|
30
|
-
if (arguments.size > 0 || option.keywordsOr.size > 0)
|
33
|
+
if (arguments.size > 0 || option.keywordsOr.size > 0 || Util.pipe?($stdin))
|
31
34
|
findGrep = FindGrep::FindGrep.new(arguments, option)
|
32
35
|
findGrep.searchAndPrint(stdout)
|
33
36
|
else
|
File without changes
|
File without changes
|
File without changes
|
@@ -2,13 +2,15 @@
|
|
2
2
|
|
3
3
|
module Gren
|
4
4
|
module Util
|
5
|
+
module_function
|
6
|
+
|
5
7
|
def time_s(time)
|
6
8
|
t = time.truncate
|
7
9
|
h = t / 3600
|
8
10
|
t = t % 3600
|
9
11
|
m = t / 60
|
10
12
|
t = t % 60
|
11
|
-
t += round(time - time.
|
13
|
+
t += round(time - time.to_i, 2)
|
12
14
|
|
13
15
|
if (h > 0 && m > 0)
|
14
16
|
"#{h}h #{m}m #{t}s"
|
@@ -18,12 +20,10 @@ module Gren
|
|
18
20
|
"#{t}sec"
|
19
21
|
end
|
20
22
|
end
|
21
|
-
module_function :time_s
|
22
23
|
|
23
24
|
def round(n, d)
|
24
25
|
(n * 10 ** d).round / 10.0 ** d
|
25
26
|
end
|
26
|
-
module_function :round
|
27
27
|
|
28
28
|
def size_s(size)
|
29
29
|
tb = 1024 ** 4
|
@@ -32,18 +32,17 @@ module Gren
|
|
32
32
|
kb = 1024
|
33
33
|
|
34
34
|
if (size >= tb)
|
35
|
-
round(size / tb.
|
35
|
+
round(size / tb.to_f, 2).to_s + "TB"
|
36
36
|
elsif (size >= gb)
|
37
|
-
round(size / gb.
|
37
|
+
round(size / gb.to_f, 2).to_s + "GB"
|
38
38
|
elsif (size >= mb)
|
39
|
-
round(size / mb.
|
39
|
+
round(size / mb.to_f, 2).to_s + "MB"
|
40
40
|
elsif (size >= kb)
|
41
|
-
round(size / kb.
|
41
|
+
round(size / kb.to_f, 2).to_s + "KB"
|
42
42
|
else
|
43
43
|
size.to_s + "Byte"
|
44
44
|
end
|
45
45
|
end
|
46
|
-
module_function :size_s
|
47
46
|
|
48
47
|
# アルファベットと演算子で表示する数を変える
|
49
48
|
ALPHABET_DISP_NUM = 5
|
@@ -61,7 +60,6 @@ module Gren
|
|
61
60
|
c = c.superclass
|
62
61
|
end
|
63
62
|
end
|
64
|
-
module_function :p_classtree
|
65
63
|
|
66
64
|
def p_classtree_sub(c)
|
67
65
|
# メソッドの一覧を得る
|
@@ -92,7 +90,15 @@ module Gren
|
|
92
90
|
end
|
93
91
|
puts
|
94
92
|
end
|
95
|
-
|
93
|
+
|
94
|
+
# StringIO patch
|
95
|
+
def pipe?(io)
|
96
|
+
io.instance_of?(IO) && File.pipe?(io)
|
97
|
+
end
|
98
|
+
|
99
|
+
def downcase?(str)
|
100
|
+
str == str.downcase
|
101
|
+
end
|
96
102
|
|
97
103
|
end
|
98
104
|
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require 'find'
|
3
|
-
require
|
3
|
+
require 'gren/findgrep/result'
|
4
4
|
require 'rubygems'
|
5
5
|
require 'termcolor'
|
6
6
|
require 'kconv'
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require '
|
11
|
-
require File.join(File.dirname(__FILE__), '../common/util')
|
7
|
+
require 'gren/common/platform'
|
8
|
+
require 'gren/common/grenfiletest'
|
9
|
+
require 'gren/common/grensnip'
|
10
|
+
require 'gren/common/util'
|
12
11
|
include Gren
|
13
12
|
require 'cgi'
|
14
13
|
|
@@ -19,6 +18,7 @@ module FindGrep
|
|
19
18
|
:directory,
|
20
19
|
:depth,
|
21
20
|
:ignoreCase,
|
21
|
+
:caseSensitive,
|
22
22
|
:colorHighlight,
|
23
23
|
:isSilent,
|
24
24
|
:debugMode,
|
@@ -28,66 +28,47 @@ module FindGrep
|
|
28
28
|
:ignoreDirs,
|
29
29
|
:kcode,
|
30
30
|
:noSnip,
|
31
|
-
:
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
false,
|
52
|
-
false,
|
53
|
-
false)
|
31
|
+
:isMatchFile)
|
32
|
+
|
33
|
+
def self.create_default_option
|
34
|
+
Option.new([],
|
35
|
+
[],
|
36
|
+
".",
|
37
|
+
-1,
|
38
|
+
false,
|
39
|
+
false,
|
40
|
+
false,
|
41
|
+
false,
|
42
|
+
false,
|
43
|
+
[],
|
44
|
+
[],
|
45
|
+
[],
|
46
|
+
[],
|
47
|
+
Kconv::UTF8, # Platform.get_shell_kcode,
|
48
|
+
false,
|
49
|
+
false)
|
50
|
+
end
|
54
51
|
|
55
52
|
attr_reader :documents
|
56
53
|
|
57
54
|
def initialize(patterns, option)
|
58
|
-
@patterns
|
59
|
-
@option
|
60
|
-
@patternRegexps = strs2regs(patterns
|
61
|
-
@subRegexps
|
62
|
-
@orRegexps
|
63
|
-
@filePatterns
|
64
|
-
@ignoreFiles
|
65
|
-
@ignoreDirs
|
66
|
-
@result
|
67
|
-
open_database if (@option.dbFile)
|
55
|
+
@patterns = patterns
|
56
|
+
@option = option
|
57
|
+
@patternRegexps = strs2regs(patterns)
|
58
|
+
@subRegexps = strs2regs(option.keywordsNot)
|
59
|
+
@orRegexps = strs2regs(option.keywordsOr)
|
60
|
+
@filePatterns = strs2regs(option.filePatterns)
|
61
|
+
@ignoreFiles = strs2regs(option.ignoreFiles)
|
62
|
+
@ignoreDirs = strs2regs(option.ignoreDirs)
|
63
|
+
@result = Result.new(option.directory)
|
68
64
|
end
|
69
65
|
|
70
|
-
def
|
71
|
-
# データベース開く
|
72
|
-
dbfile = Pathname(File.expand_path(@option.dbFile))
|
73
|
-
|
74
|
-
if dbfile.exist?
|
75
|
-
Groonga::Database.open(dbfile.to_s)
|
76
|
-
puts "open : #{dbfile} open."
|
77
|
-
else
|
78
|
-
raise "error : #{dbfile.to_s} not found!!"
|
79
|
-
end
|
80
|
-
|
81
|
-
# ドキュメントを取
|
82
|
-
@documents = Groonga::Context.default["documents"]
|
83
|
-
end
|
84
|
-
|
85
|
-
def strs2regs(strs, ignore = false)
|
66
|
+
def strs2regs(strs)
|
86
67
|
regs = []
|
87
68
|
|
88
69
|
strs.each do |v|
|
89
70
|
option = 0
|
90
|
-
option |= Regexp::IGNORECASE if (
|
71
|
+
option |= Regexp::IGNORECASE if (@option.ignoreCase || (!@option.caseSensitive && Util::downcase?(v)))
|
91
72
|
regs << Regexp.new(v, option)
|
92
73
|
end
|
93
74
|
|
@@ -95,15 +76,15 @@ module FindGrep
|
|
95
76
|
end
|
96
77
|
|
97
78
|
def searchAndPrint(stdout)
|
98
|
-
unless (
|
79
|
+
unless Util.pipe?($stdin)
|
99
80
|
searchFromDir(stdout, @option.directory, 0)
|
100
81
|
else
|
101
|
-
|
82
|
+
searchData(stdout, $stdin.read.split("\n"), nil)
|
102
83
|
end
|
103
84
|
|
104
85
|
@result.time_stop
|
105
86
|
|
106
|
-
if
|
87
|
+
if !@option.isSilent
|
107
88
|
if (@option.debugMode)
|
108
89
|
stdout.puts
|
109
90
|
stdout.puts "--- search --------"
|
@@ -128,56 +109,6 @@ module FindGrep
|
|
128
109
|
end
|
129
110
|
end
|
130
111
|
|
131
|
-
def searchFromDB(stdout, dir)
|
132
|
-
# 全てのパターンを検索
|
133
|
-
table = @documents.select do |record|
|
134
|
-
expression = nil
|
135
|
-
|
136
|
-
# キーワード
|
137
|
-
@patterns.each do |word|
|
138
|
-
sub_expression = record.content =~ word
|
139
|
-
if expression.nil?
|
140
|
-
expression = sub_expression
|
141
|
-
else
|
142
|
-
expression &= sub_expression
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
# パス
|
147
|
-
@option.filePatterns.each do |word|
|
148
|
-
sub_expression = record.path =~ word
|
149
|
-
if expression.nil?
|
150
|
-
expression = sub_expression
|
151
|
-
else
|
152
|
-
expression &= sub_expression
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
# 拡張子(OR)
|
157
|
-
se = suffix_expression(record)
|
158
|
-
expression &= se if (se)
|
159
|
-
|
160
|
-
# 検索式
|
161
|
-
expression
|
162
|
-
end
|
163
|
-
|
164
|
-
# タイムスタンプでソート
|
165
|
-
records = table.sort([{:key => "_score", :order => "descending"},
|
166
|
-
{:key => "timestamp", :order => "descending"}])
|
167
|
-
|
168
|
-
# データベースにヒット
|
169
|
-
stdout.puts "Found : #{records.size} records." unless (@option.dispHtml)
|
170
|
-
|
171
|
-
# 検索にヒットしたファイルを実際に検索
|
172
|
-
records.each do |record|
|
173
|
-
if (@option.groongaOnly)
|
174
|
-
searchGroongaOnly(stdout, record)
|
175
|
-
else
|
176
|
-
searchFile(stdout, record.path, record.path) if FileTest.exist?(record.path)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
112
|
def and_expression(key, list)
|
182
113
|
sub = nil
|
183
114
|
|
@@ -303,21 +234,6 @@ module FindGrep
|
|
303
234
|
end
|
304
235
|
private :searchFile
|
305
236
|
|
306
|
-
def searchGroongaOnly(stdout, record)
|
307
|
-
file_size = record.content.size
|
308
|
-
|
309
|
-
@result.count += 1
|
310
|
-
@result.size += file_size
|
311
|
-
|
312
|
-
@result.search_count += 1
|
313
|
-
@result.search_size += file_size
|
314
|
-
|
315
|
-
@result.search_files << record.path if (@option.debugMode)
|
316
|
-
|
317
|
-
searchData(stdout, record.content, record.path)
|
318
|
-
end
|
319
|
-
private :searchGroongaOnly
|
320
|
-
|
321
237
|
def searchData(stdout, data, path)
|
322
238
|
match_file = false
|
323
239
|
|
@@ -325,29 +241,17 @@ module FindGrep
|
|
325
241
|
result, match_datas = match?(line)
|
326
242
|
|
327
243
|
if ( result )
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
stdout.puts header + line
|
334
|
-
else
|
335
|
-
stdout.puts HighLine::BLUE + header + HighLine::CLEAR + GrenSnip::coloring(line, match_datas)
|
336
|
-
end
|
244
|
+
header = path ? "#{path}:#{index + 1}:" : ""
|
245
|
+
line = GrenSnip::snip(line, match_datas) unless (@option.noSnip)
|
246
|
+
|
247
|
+
unless (@option.colorHighlight)
|
248
|
+
stdout.puts header + line
|
337
249
|
else
|
338
|
-
|
339
|
-
line = GrenSnip::snip(line, match_datas) unless (@option.noSnip)
|
340
|
-
|
341
|
-
stdout.puts <<EOF
|
342
|
-
<h2><a href="../::view#{path}">#{path}</a></h2>
|
343
|
-
<pre>
|
344
|
-
#{line_no} : #{CGI.escapeHTML(line)}
|
345
|
-
</pre>
|
346
|
-
EOF
|
250
|
+
stdout.puts HighLine::BLUE + header + HighLine::CLEAR + GrenSnip::coloring(line, match_datas)
|
347
251
|
end
|
348
252
|
|
349
253
|
unless match_file
|
350
|
-
|
254
|
+
@result.match_file_count += 1
|
351
255
|
@result.match_files << path if (@option.debugMode)
|
352
256
|
match_file = true
|
353
257
|
break if (@option.isMatchFile)
|
data/lib/gren/version.rb
ADDED
data/test/data/aaa.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
aaa
|