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.
Files changed (62) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +7 -0
  3. data/{History.ja.txt → HISTORY.ja.md} +41 -15
  4. data/HISTORY.md +92 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.ja.md +57 -0
  7. data/README.md +51 -0
  8. data/Rakefile +9 -39
  9. data/bin/gren +2 -7
  10. data/gren.gemspec +21 -0
  11. data/lib/gren.rb +3 -3
  12. data/lib/gren/cli.rb +13 -10
  13. data/lib/{common → gren/common}/grenfiletest.rb +0 -0
  14. data/lib/{common → gren/common}/grensnip.rb +1 -1
  15. data/lib/{common → gren/common}/platform.rb +0 -0
  16. data/lib/{common → gren/common}/string_snip.rb +0 -0
  17. data/lib/{common → gren/common}/util.rb +16 -10
  18. data/lib/{findgrep → gren/findgrep}/findgrep.rb +47 -143
  19. data/lib/{findgrep → gren/findgrep}/result.rb +1 -1
  20. data/lib/gren/version.rb +3 -0
  21. data/test/data/aaa.txt +1 -0
  22. data/test/data/abc.rb +8 -0
  23. data/test/data/bbb.txt +1 -0
  24. data/test/data/ccc.c +1 -0
  25. data/test/data/sub/ccc.txt +1 -0
  26. data/test/test_cli.rb +80 -0
  27. data/test/test_gren.rb +10 -10
  28. data/test/test_gren_util.rb +3 -2
  29. data/test/test_string_snip.rb +31 -31
  30. metadata +67 -177
  31. data/History.txt +0 -66
  32. data/Manifest.txt +0 -48
  33. data/PostInstall.txt +0 -7
  34. data/README.rdoc +0 -181
  35. data/bin/grendb +0 -11
  36. data/bin/grenweb +0 -11
  37. data/bin/mkgrendb +0 -11
  38. data/lib/common/display_util.rb +0 -62
  39. data/lib/grendb/cli.rb +0 -41
  40. data/lib/grenweb/cli.rb +0 -52
  41. data/lib/grenweb/database.rb +0 -179
  42. data/lib/grenweb/grenweb.ru +0 -35
  43. data/lib/grenweb/grep.rb +0 -52
  44. data/lib/grenweb/help.rb +0 -39
  45. data/lib/grenweb/home.rb +0 -39
  46. data/lib/grenweb/html_renderer.rb +0 -243
  47. data/lib/grenweb/public/css/gren.css +0 -63
  48. data/lib/grenweb/public/images/gren-icon-mini.png +0 -0
  49. data/lib/grenweb/public/images/gren-icon.png +0 -0
  50. data/lib/grenweb/query.rb +0 -82
  51. data/lib/grenweb/searcher.rb +0 -129
  52. data/lib/grenweb/viewer.rb +0 -51
  53. data/lib/mkgrendb/cli.rb +0 -49
  54. data/lib/mkgrendb/mkgrendb.rb +0 -230
  55. data/rake_rdoc_custom.rb +0 -13
  56. data/script/console +0 -10
  57. data/script/destroy +0 -14
  58. data/script/generate +0 -14
  59. data/test/test_grenweb_cli.rb +0 -10
  60. data/test/test_grenweb_html_renderer.rb +0 -41
  61. data/test/test_grenweb_query.rb +0 -54
  62. data/test/test_grenweb_searcher.rb +0 -35
@@ -1,52 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'optparse'
3
- require 'rubygems'
4
- require 'rack'
5
- require 'fileutils'
6
- require File.join(File.dirname(__FILE__), 'database')
7
- require 'launchy'
8
-
9
- module Grenweb
10
- class CLI
11
- def self.execute(stdout, arguments=[])
12
- option = {
13
- :Port => 9292,
14
- :DbFile => ENV['GRENDB_DEFAULT_DB'],
15
- }
16
-
17
- opt = OptionParser.new("#{File.basename($0)}")
18
- opt.on('--db [GREN_DB_FILE]', 'Search from the grendb database.') {|v| option[:DbFile] = v }
19
- opt.on('-p', '--port PORT', 'use PORT (default: 9292)') {|v| option[:Port] = v }
20
- opt.on('--no-browser', 'No launch browser.') {|v| option[:NoBrowser] = true }
21
- opt.parse!(arguments)
22
-
23
- # webサーバー起動
24
- stdout.puts <<EOF
25
- Start up grenweb !!
26
- URL : http://localhost:#{option[:Port]}
27
- DB : #{option[:DbFile]}
28
- ----------------------------------------
29
- EOF
30
-
31
- # 使用するデータベースの位置設定
32
- Database.setup(option[:DbFile])
33
-
34
- # サーバースクリプトのある場所へ移動
35
- FileUtils.cd(File.dirname(__FILE__))
36
-
37
- # ブラウザ起動
38
- Launchy.open("http://localhost:#{option[:Port]}") unless (option[:NoBrowser])
39
-
40
- # サーバー起動
41
- Rack::Server.start(
42
- :environment => "development",
43
- :pid => nil,
44
- :Port => option[:Port],
45
- :Host => "0.0.0.0",
46
- :AccessLog => [],
47
- :config => "grenweb.ru"
48
- )
49
-
50
- end
51
- end
52
- end
@@ -1,179 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # @file
4
- # @brief Grenwebで使用するデータベース
5
- # @author ongaeshi
6
- # @date 2010/10/17
7
-
8
- require 'groonga'
9
- require 'pathname'
10
- require 'singleton'
11
-
12
- module Grenweb
13
- class Database
14
- include Singleton
15
-
16
- def self.setup(dbFile)
17
- @@dbFile = dbFile
18
- end
19
-
20
- def initialize
21
- open(@@dbFile)
22
- end
23
-
24
- def open(dbFile)
25
- dbfile = Pathname(File.expand_path(dbFile))
26
-
27
- if dbfile.exist?
28
- Groonga::Database.open(dbfile.to_s)
29
- else
30
- raise "error : #{dbfile.to_s} not found!!"
31
- end
32
-
33
- @documents = Groonga::Context.default["documents"]
34
- end
35
-
36
- def record(shortpath)
37
- before = Time.now
38
- table = @documents.select { |record| record.shortpath == shortpath }
39
- elapsed = Time.now - before
40
- return table.records[0], elapsed
41
- end
42
-
43
- def fileNum
44
- @documents.select.size
45
- end
46
-
47
- def search(patterns, packages, fpaths, suffixs, page = 0, limit = -1)
48
- before = Time.now
49
-
50
- # 全てのパターンを検索
51
- if (fpaths.include?("*"))
52
- records, total_records = selectAll(page, limit)
53
- else
54
- records, total_records = searchMain(patterns, packages, fpaths, suffixs, page, limit)
55
- end
56
-
57
- # 検索にかかった時間
58
- elapsed = Time.now - before
59
-
60
- # 結果
61
- return records, total_records, elapsed
62
- end
63
-
64
- def selectAll(page, limit)
65
- table = @documents.select
66
-
67
- # マッチ数
68
- total_records = table.size
69
-
70
- # 2010/10/29 ongaeshi
71
- # 本当はこのようにgroongaAPIでソートしたいのだが上手くいかなかった
72
- # # ファイル名順にソート
73
- # records = table.sort([{:key => "shortpath", :order => "descending"}],
74
- # :offset => page * limit,
75
- # :limit => limit)
76
-
77
- # ソート
78
- records = table.records.sort_by{|record| record.shortpath.downcase }[page * limit, limit]
79
-
80
- return records, total_records
81
- end
82
-
83
- def searchMain(patterns, packages, fpaths, suffixs, page, limit)
84
- table = @documents.select do |record|
85
- expression = nil
86
-
87
- # キーワード
88
- patterns.each do |word|
89
- sub_expression = record.content =~ word
90
- if expression.nil?
91
- expression = sub_expression
92
- else
93
- expression &= sub_expression
94
- end
95
- end
96
-
97
- # パッケージ(OR)
98
- pe = package_expression(record, packages)
99
- if (pe)
100
- if expression.nil?
101
- expression = pe
102
- else
103
- expression &= pe
104
- end
105
- end
106
-
107
- # ファイルパス
108
- fpaths.each do |word|
109
- sub_expression = record.path =~ word
110
- if expression.nil?
111
- expression = sub_expression
112
- else
113
- expression &= sub_expression
114
- end
115
- end
116
-
117
- # 拡張子(OR)
118
- se = suffix_expression(record, suffixs)
119
- if (se)
120
- if expression.nil?
121
- expression = se
122
- else
123
- expression &= se
124
- end
125
- end
126
-
127
- # 検索式
128
- expression
129
- end
130
-
131
- # マッチ数
132
- total_records = table.size
133
-
134
- # スコアとタイムスタンプでソート
135
- records = table.sort([{:key => "_score", :order => "descending"},
136
- {:key => "timestamp", :order => "descending"}],
137
- :offset => page * limit,
138
- :limit => limit)
139
-
140
- return records, total_records
141
- end
142
- private :searchMain
143
-
144
- def package_expression(record, packages)
145
- sub = nil
146
-
147
- # @todo 専用カラム package が欲しいところ
148
- # でも今でもpackageはORとして機能してるからいいっちゃいい
149
- packages.each do |word|
150
- e = record.path =~ word
151
- if sub.nil?
152
- sub = e
153
- else
154
- sub |= e
155
- end
156
- end
157
-
158
- sub
159
- end
160
- private :package_expression
161
-
162
- def suffix_expression(record, suffixs)
163
- sub = nil
164
-
165
- suffixs.each do |word|
166
- e = record.suffix =~ word
167
- if sub.nil?
168
- sub = e
169
- else
170
- sub |= e
171
- end
172
- end
173
-
174
- sub
175
- end
176
- private :suffix_expression
177
-
178
- end
179
- end
@@ -1,35 +0,0 @@
1
- # -*- mode: ruby; coding: utf-8 -*-
2
- #
3
- # @file
4
- # @brief gren web検索
5
- # @author ongaeshi
6
- # @date 2010/10/13
7
-
8
- require 'rubygems'
9
- require 'rack'
10
- require File.join(File.dirname(__FILE__), 'home')
11
- require File.join(File.dirname(__FILE__), 'searcher')
12
- require File.join(File.dirname(__FILE__), 'viewer')
13
- require File.join(File.dirname(__FILE__), 'help')
14
-
15
- use Rack::CommonLogger
16
- use Rack::Runtime
17
- use Rack::Static, :urls => ["/css", "/images"], :root => "public"
18
- use Rack::ContentLength
19
-
20
- map '/' do
21
- run Grenweb::Home.new
22
- end
23
-
24
- map '/::search' do
25
- run Grenweb::Searcher.new
26
- end
27
-
28
- map '/::view' do
29
- run Grenweb::Viewer.new
30
- end
31
-
32
- map '/::help' do
33
- run Grenweb::Help.new
34
- end
35
-
@@ -1,52 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # @file
4
- # @brief grenwebで使用する行指向の検索
5
- # @author ongaeshi
6
- # @date 2010/10/18
7
-
8
- module Grenweb
9
- class Grep
10
- attr_reader :content
11
-
12
- def initialize(content)
13
- @content = content.split("\n")
14
- end
15
-
16
- MatchLineResult = Struct.new(:index, :match_datas)
17
-
18
- def match_lines_or(patterns)
19
- result = []
20
- patternRegexps = strs2regs(patterns, true) # @todo ignoreオプションを付ける
21
-
22
- @content.each_with_index do |line, index|
23
- match_datas = []
24
- patternRegexps.each {|v| match_datas << v.match(line)}
25
-
26
- if (match_datas.any?)
27
- result << MatchLineResult.new(index, match_datas)
28
- end
29
- end
30
-
31
- result
32
- end
33
-
34
- def context(result, num)
35
- end
36
-
37
- private
38
-
39
- def strs2regs(strs, ignore = false)
40
- regs = []
41
-
42
- strs.each do |v|
43
- option = 0
44
- option |= Regexp::IGNORECASE if (ignore)
45
- regs << Regexp.new(v, option)
46
- end
47
-
48
- regs
49
- end
50
- end
51
- end
52
-
@@ -1,39 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # @file
4
- # @brief ホーム画面
5
- # @author ongaeshi
6
- # @date 2010/10/13
7
-
8
- require 'rack'
9
- require File.join(File.dirname(__FILE__), 'database')
10
- require File.join(File.dirname(__FILE__), 'html_renderer')
11
- require File.join(File.dirname(__FILE__), 'query')
12
-
13
- module Grenweb
14
- class Help
15
- include Rack::Utils
16
-
17
- def call(env)
18
- @env = env
19
- @request = Rack::Request.new(env)
20
- @query = Query.new(@request)
21
-
22
- @response = Rack::Response.new
23
- @response["Content-Type"] = "text/html; charset=UTF-8"
24
-
25
- render
26
- end
27
-
28
- private
29
-
30
- def render
31
- r = HTMLRendeler.new(@request.script_name + '/..')
32
- @response.write r.header("gren - help", "gren - help")
33
- @response.write r.sample_code
34
- @response.write r.footer
35
- @response.to_a
36
- end
37
- end
38
- end
39
-
@@ -1,39 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # @file
4
- # @brief ホーム画面
5
- # @author ongaeshi
6
- # @date 2010/10/13
7
-
8
- require 'rack'
9
- require File.join(File.dirname(__FILE__), 'database')
10
- require File.join(File.dirname(__FILE__), 'html_renderer')
11
- require File.join(File.dirname(__FILE__), 'query')
12
-
13
- module Grenweb
14
- class Home
15
- include Rack::Utils
16
-
17
- def call(env)
18
- @env = env
19
- @request = Rack::Request.new(env)
20
- @query = Query.new(@request)
21
-
22
- @response = Rack::Response.new
23
- @response["Content-Type"] = "text/html; charset=UTF-8"
24
-
25
- render
26
- end
27
-
28
- private
29
-
30
- def render
31
- r = HTMLRendeler.new(@request.script_name)
32
- @response.write r.header_home("gren", "gren", Version)
33
- @response.write r.search_box
34
- @response.write r.footer_home("??", Database.instance.fileNum)
35
- @response.to_a
36
- end
37
- end
38
- end
39
-
@@ -1,243 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # @file
4
- # @brief HTMLの描画ルーチン
5
- # @author ongaeshi
6
- # @date 2010/10/17
7
-
8
- require 'rubygems'
9
- require 'rack'
10
- require File.join(File.dirname(__FILE__), 'grep')
11
-
12
- module Grenweb
13
- class HTMLRendeler
14
- include Rack::Utils
15
-
16
- def initialize(script_name)
17
- @script_name = Pathname(script_name)
18
- end
19
-
20
- def header(title, header1)
21
- <<EOS
22
- <?xml version="1.0" encoding="utf-8"?>
23
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
24
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
25
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
26
- <head>
27
- <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
28
- <!-- <meta name="robot" content="noindex,nofollow" /> -->
29
- <title>#{title}</title>
30
- <link rel="stylesheet" href="#{fullpath('css/gren.css')}" type="text/css" media="all" />
31
- </head>
32
- <body>
33
- <div class="header">
34
- <h1>
35
- <a href="#{fullpath('')}"><img src="#{fullpath('images/gren-icon-mini.png')}" alt="gren-icon" border="0"/></a>
36
- #{header1}
37
- </h1>
38
- </div>
39
-
40
- <div class="content">
41
- EOS
42
- end
43
-
44
- def footer
45
- <<EOS
46
- </div>
47
-
48
- <div class="footer">
49
- </div>
50
- </body>
51
- </html>
52
- EOS
53
- end
54
-
55
- def header_home(title, header1, version)
56
- <<EOS
57
- <?xml version="1.0" encoding="utf-8"?>
58
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
59
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
60
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
61
- <head>
62
- <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
63
- <!-- <meta name="robot" content="noindex,nofollow" /> -->
64
- <title>#{title}</title>
65
- <link rel="stylesheet" href="#{fullpath('css/gren.css')}" type="text/css" media="all" />
66
- </head>
67
- <body>
68
- <div align="center">
69
- <div class="header_home">
70
- <h1>
71
- <a href="#{fullpath('')}"><img src="#{fullpath('images/gren-icon.png')}" alt="gren-icon" border="0" height="100px"/></a>
72
- #{header1} <font class="version">#{version}</font>
73
- </h1>
74
- </div>
75
-
76
- <div class="content">
77
- EOS
78
- end
79
-
80
- def footer_home(package, files)
81
- <<EOS
82
- </div>
83
-
84
- <div class="footer_home">
85
- <!-- <a href="#{fullpath('::search/p:*')}">#{package}</a>のパッケージ , -->
86
- <a href="#{fullpath('::search/f:*')}">#{files}</a>のファイル<br>
87
- <a href="#{fullpath('::help')}">ヘルプ</a> ,
88
- <a href="http://ongaeshi.github.com/gren">grenについて</a>
89
- </div>
90
- </div>
91
- </body>
92
- </html>
93
- EOS
94
- end
95
-
96
- def result_record(record, patterns, nth=1)
97
- if (patterns.size > 0)
98
- <<EOS
99
- <dt class='result-record'><a href='#{fullpath("::view/" + Rack::Utils::escape_html(record.shortpath))}'>#{record.shortpath}</a></dt>
100
- <dd>
101
- <pre class='lines'>
102
- #{result_record_match_line(record, patterns, nth)}
103
- </pre>
104
- </dd>
105
- EOS
106
- else
107
- <<EOS
108
- <dt class='result-record'><a href='#{fullpath("::view/" + Rack::Utils::escape_html(record.shortpath))}'>#{record.shortpath}</a></dt>
109
- EOS
110
- end
111
- end
112
-
113
- def result_record_match_line(record, patterns, nth)
114
- str = ""
115
-
116
- grep = Grep.new(record.content)
117
- lines = grep.match_lines_or(patterns)
118
-
119
- unless (lines.empty?)
120
- index = lines[0].index
121
-
122
- (index - nth..index + nth).each do |i|
123
- if (0 <= i && i < grep.content.size)
124
- match_datas = (i == index) ? lines[0].match_datas : []
125
- str << line(i + 1, grep.content[i], match_datas) + "\n"
126
- end
127
- end
128
- end
129
-
130
- str
131
- end
132
-
133
- def record_content(record)
134
- <<EOS
135
- <pre>
136
- #{record_content_line(record)}
137
- </pre>
138
- EOS
139
- end
140
-
141
- def record_content_line(record)
142
- str = ""
143
-
144
- grep = Grep.new(record.content)
145
- grep.content.each_with_index do |l, index|
146
- str << line(index + 1, l, []) + "\n"
147
- end
148
-
149
- str
150
- end
151
-
152
- def line(lineno, line, match_datas)
153
- sprintf("%5d: %s", lineno, match_strong(Rack::Utils::escape_html(line), match_datas))
154
- end
155
-
156
- def match_strong(line, match_datas)
157
- match_datas.each do |m|
158
- line = line.split(m[0]).join('<strong>' + m[0] + '</strong>') unless (m.nil?)
159
- end
160
-
161
- line
162
- end
163
-
164
- def pagination_link(page, label)
165
- href = "?page=#{page}"
166
- pagination_span("<a href='#{href}'>#{label}</a>")
167
- end
168
-
169
- def pagination_span(content)
170
- "<span class='pagination-link'>#{content}</span>\n"
171
- end
172
-
173
- def empty_summary()
174
- <<EOS
175
- <div class='search-summary'>
176
- <p>gren web検索</p>
177
- </div>
178
- EOS
179
- end
180
-
181
- def search_summary(keyword, total_records, range, elapsed)
182
- <<EOS
183
- <div class='search-summary'>
184
- <span class="keyword">#{keyword}</span>の検索結果:
185
- <span class="total-entries">#{total_records}</span>件中
186
- <span class="display-range">#{range.first} - #{range.last}</span>件(#{elapsed}秒)
187
- </div>
188
- EOS
189
- end
190
-
191
- def view_summary(path, elapsed)
192
- <<EOS
193
- <div class='search-summary'>
194
- <span class="keyword">#{path}</span>(#{elapsed}秒)
195
- </div>
196
- EOS
197
- end
198
-
199
- def search_box(text = "")
200
- <<EOS
201
- <form method="post" action="#{fullpath('::search')}">
202
- <p>
203
- <input name="query" type="text" size="60" value="#{text}" />
204
- <input type="submit" value="検索" />
205
- </p>
206
- </form>
207
- EOS
208
- end
209
-
210
- def sample_code
211
- <<EOS
212
- <div class='sample-code'>
213
- <ol>
214
- <li>キーワードで検索<br>
215
- #{link('def open')}
216
- <li>1フレーズとして検索<br>
217
- #{link('"def open"')}
218
- <li>パッケージ名で絞り込み<br>
219
- #{link('def open p:gren')}
220
- <li>ファイル名や拡張子で絞り込み<br>
221
- #{link('def open f:test s:rb')}
222
- <li>組み合わせ<br>
223
- #{link('p:gren p:tidtools s:rb f:test assert f:cli')}
224
- </ol>
225
- </div>
226
- EOS
227
- end
228
-
229
- def link(keyword)
230
- "<a href='#{fullpath('::search' + '/' + Rack::Utils::escape_html(keyword))}'>#{keyword}</a>"
231
- end
232
-
233
- def fullpath(path)
234
- unless (path == '')
235
- (@script_name + path).to_s
236
- else
237
- @script_name.to_s
238
- end
239
- end
240
- end
241
- end
242
-
243
-