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,63 +0,0 @@
1
- body {
2
- }
3
-
4
- div.header {
5
- }
6
-
7
- div.footer {
8
- }
9
-
10
- div.header_home {
11
- font-size: 170%;
12
- }
13
-
14
- div.footer_home {
15
- font-size: 85%;
16
- margin-top: 3em;
17
- }
18
-
19
- div.search-summary {
20
- border-color:#F4CA3F;
21
- background-color:#FEFFF0;
22
- border-top-style:solid;
23
- border-top-width:1px;
24
- border-bottom-style:solid;
25
- border-bottom-width:1px;
26
- margin-bottom:1em;
27
- margin-top:1em;
28
- padding-bottom:5px;
29
- padding-top:5px;
30
- padding-left:5px;
31
- }
32
-
33
- dt.result-record {
34
- font-size: 105%;
35
- }
36
-
37
- pre.lines {
38
- }
39
-
40
- div.pagination {
41
- background-color:#FEFFF0;
42
- text-align: center;
43
- margin-bottom: 20px;
44
- }
45
-
46
- pre {
47
- border: 1px solid #dedede;
48
- margin-bottom: 5px;
49
- padding-left: 5px;
50
- background-color: #fdfdfd;
51
- font-weight: inherit;
52
- margin-top: 5px;
53
- padding-top: 5px;
54
- padding-bottom: 5px;
55
- }
56
-
57
- span.keyword {
58
- font-weight: bold;
59
- }
60
-
61
- font.version {
62
- font-size: 35%;
63
- }
@@ -1,82 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # @file
4
- # @brief クエリーの解析
5
- # @author ongaeshi
6
- # @date 2010/10/21
7
-
8
- require 'rubygems'
9
- require 'rack'
10
-
11
- module Grenweb
12
- class Query
13
- include Rack::Utils
14
- attr_reader :query_string
15
-
16
- OPTIONS = [
17
- ['package', 'p'],
18
- ['filepath', 'fpath', 'f'],
19
- ['suffix', 's'],
20
- ]
21
-
22
- def initialize(request)
23
- @query_string = unescape(request.path_info.gsub(/\A\/|\/\z/, ''))
24
- init_hash
25
- parse
26
- end
27
-
28
- def escape_html
29
- Rack::Utils::escape_html(@query_string)
30
- end
31
-
32
- def empty?
33
- keywords.size == 0 && packages.size == 0 && fpaths.size == 0 && suffixs.size == 0
34
- end
35
-
36
- def keywords
37
- @hash['keywords']
38
- end
39
-
40
- def packages
41
- calc_param(0)
42
- end
43
-
44
- def fpaths
45
- calc_param(1)
46
- end
47
-
48
- def suffixs
49
- calc_param(2)
50
- end
51
-
52
- private
53
-
54
- def calc_param(index)
55
- OPTIONS[index].inject([]){|result, item| result.concat @hash[item] }
56
- end
57
-
58
- def init_hash
59
- @hash = {}
60
- @hash['keywords'] = []
61
-
62
- OPTIONS.flatten.each do |key|
63
- @hash[key] = []
64
- end
65
- end
66
-
67
- def parse
68
- kp = OPTIONS.flatten.join('|')
69
- parts = @query_string.scan(/(?:(#{kp}):)?(?:"(.+)"|(\S+))/)
70
-
71
- parts.each do |key, quoted_value, value|
72
- text = quoted_value || value
73
- unless (key)
74
- @hash['keywords'] << text
75
- else
76
- @hash[key] << text
77
- end
78
- end
79
- end
80
- end
81
- end
82
-
@@ -1,129 +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 Searcher
15
- include Rack::Utils
16
-
17
- def initialize
18
- end
19
-
20
- def call(env)
21
- @request = Rack::Request.new(env)
22
- @query = Query.new(@request)
23
-
24
- @response = Rack::Response.new
25
- @response["Content-Type"] = "text/html; charset=UTF-8"
26
-
27
- @nth = 3 # マッチした行の前後何行を表示するか
28
-
29
- @rendeler = HTMLRendeler.new(@request.script_name + '/..')
30
-
31
- if @request.post? or @request['query']
32
- post_request
33
- else
34
- search
35
- end
36
- end
37
-
38
- private
39
-
40
- def post_request
41
- query = @request['query'] || ''
42
- if query.empty?
43
- @request.path_info = "/"
44
- else
45
- @request.path_info = "/#{escape(query)}/"
46
- end
47
- @response.redirect(@request.url.split(/\?/, 2)[0])
48
- @response.to_a
49
- end
50
-
51
- def search
52
- render_header
53
- render_search_box
54
- render_search_result
55
- render_footer
56
- @response.to_a
57
- end
58
-
59
- def render_header
60
- @response.write @rendeler.header("gren : #{@query.escape_html}", "gren")
61
- end
62
-
63
- def render_search_box
64
- @response.write @rendeler.search_box(@query.escape_html)
65
- end
66
-
67
- def render_search_result
68
- if @query.empty?
69
- @response.write @rendeler.empty_summary
70
- else
71
- records, total_records, elapsed = Database.instance.search(@query.keywords, @query.packages, @query.fpaths, @query.suffixs, calcPage, calcLimit)
72
- render_search_summary(records, total_records, elapsed)
73
- records.each { |record| @response.write(@rendeler.result_record(record, @query.keywords, @nth)) }
74
- render_pagination(calcPage, total_records)
75
- end
76
- end
77
-
78
- def render_search_summary(records, total_records, elapsed)
79
- pageStart = calcPage * calcLimit
80
- @response.write @rendeler.search_summary(@query.query_string,
81
- total_records,
82
- (total_records.zero? ? 0 : pageStart + 1)..(pageStart + records.size),
83
- elapsed)
84
- end
85
-
86
- def render_pagination(page, total_records)
87
- return if @query.empty?
88
- return if total_records < calcLimit
89
-
90
- last_page = (total_records / calcLimit.to_f).ceil
91
- @response.write("<div class='pagination'>\n")
92
- if page > 0
93
- @response.write(@rendeler.pagination_link(page - 1, "<<"))
94
- end
95
- last_page.times do |i|
96
- if i == page
97
- @response.write(@rendeler.pagination_span(i))
98
- else
99
- @response.write(@rendeler.pagination_link(i, i))
100
- end
101
- end
102
- if page < (last_page - 1)
103
- @response.write(@rendeler.pagination_link(page + 1, ">>"))
104
- end
105
- @response.write("</div>\n")
106
- end
107
-
108
- def render_footer
109
- @response.write @rendeler.footer
110
- end
111
-
112
- private
113
-
114
- # 1ページに表示する最大レコードを計算
115
- def calcLimit
116
- if @query.keywords.size == 0
117
- 100
118
- else
119
- 20
120
- end
121
- end
122
-
123
- # 現在ページを計算
124
- def calcPage
125
- (@request['page'] || 0).to_i
126
- end
127
- end
128
- end
129
-
@@ -1,51 +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
-
12
- module Grenweb
13
- class Viewer
14
- include Rack::Utils
15
-
16
- def initialize
17
- end
18
-
19
- def call(env)
20
- @request = Rack::Request.new(env)
21
- @response = Rack::Response.new
22
- @response["Content-Type"] = "text/html; charset=UTF-8"
23
-
24
- record, elapsed = Database.instance.record(req2query)
25
-
26
- @rendeler = HTMLRendeler.new(@request.script_name + '/..')
27
-
28
- if (record)
29
- @response.write @rendeler.header("gren : #{record.shortpath}", "gren")
30
- @response.write @rendeler.search_box("")
31
- @response.write @rendeler.view_summary(record.shortpath, elapsed)
32
- @response.write @rendeler.record_content(record)
33
- else
34
- @response.write @rendeler.header("gren : not found.", "gren")
35
- @response.write @rendeler.search_box("")
36
- @response.write @rendeler.empty_summary
37
- end
38
- @response.write @rendeler.footer
39
-
40
- @response.to_a
41
- end
42
-
43
- private
44
-
45
- def req2query
46
- p @request.path_info
47
- unescape(@request.path_info.gsub(/\A\/|\/z/, ''))
48
- end
49
-
50
- end
51
- end
@@ -1,49 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'optparse'
3
- require File.join(File.dirname(__FILE__), 'mkgrendb')
4
-
5
- module Mkgrendb
6
- class CLI
7
- def self.execute(stdout, arguments=[])
8
- input_yamls = []
9
- isDump = false
10
- isFull = false
11
- isDelete = false
12
- isReport = false
13
-
14
- opt = OptionParser.new "#{File.basename($0)} INPUT_YAML1 [INPUT_YAML2 ...]"
15
- opt.on('--ddb', "--default-db", "Create or Update default DB. (Plase set ENV['GRENDB_DEFAULT_DB'])") {|v| input_yamls << ENV['GRENDB_DEFAULT_DB']}
16
- opt.on('--full', "Full update DB. (Delete and create)") {|v| isFull = true }
17
- opt.on('--delete', "Delete DB. (Not delete yaml)") {|v| isDelete = true }
18
- opt.on('--dump', "Dump DB.") {|v| isDump = true }
19
- opt.on('--report', "Database Report.") {|v| isReport = true }
20
- opt.parse!(arguments)
21
-
22
- input_yamls.concat arguments
23
-
24
- if (input_yamls.size >= 1)
25
- input_yamls.each do |input_yaml|
26
- obj = Mkgrendb.new(input_yaml)
27
-
28
- if (isFull)
29
- obj.full
30
- stdout.puts
31
- elsif (isDelete)
32
- obj.delete
33
- stdout.puts
34
- elsif (isDump)
35
- obj.dump
36
- elsif (isReport)
37
- obj.report
38
- else
39
- obj.update
40
- stdout.puts
41
- end
42
-
43
- end
44
- else
45
- stdout.puts opt.help
46
- end
47
- end
48
- end
49
- end
@@ -1,230 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- require 'yaml'
4
- require 'pathname'
5
- require 'rubygems'
6
- require 'groonga'
7
- require 'fileutils'
8
- require File.join(File.dirname(__FILE__), '../common/grenfiletest')
9
- require File.join(File.dirname(__FILE__), '../common/util')
10
- include Gren
11
-
12
- module Mkgrendb
13
- class Mkgrendb
14
- def initialize(input)
15
- input = File.expand_path(input)
16
- @input_yaml = input.sub(/\.db$/, ".yaml")
17
- @output_db = input.sub(/\.yaml$/, ".db")
18
- puts "input_yaml : #{@input_yaml} found."
19
- @src = YAML.load(open(@input_yaml).read())
20
- @file_count = 0
21
- @add_count = 0
22
- @update_count = 0
23
- @start_time = Time.now
24
- end
25
-
26
- def update
27
- db_create(@output_db)
28
- db_open(@output_db)
29
- @src["directory"].each do |dir|
30
- dir = File.expand_path(dir)
31
-
32
- if (!FileTest.exist?(dir))
33
- puts "[WARNING] : #{dir} (Not found, skip)"
34
- elsif (FileTest.directory? dir)
35
- db_add_dir(dir)
36
- else
37
- db_add_file(STDOUT, dir, File.basename(dir))
38
- end
39
- end
40
- @end_time = Time.now
41
- print_result
42
- end
43
-
44
- def delete
45
- db_delete(@output_db)
46
- end
47
-
48
- def full
49
- delete
50
- update
51
- end
52
-
53
- def time
54
- @end_time - @start_time
55
- end
56
-
57
- def print_result
58
- puts
59
- puts "input_yaml : #{@input_yaml} (#{Util::time_s(time)})"
60
- puts "output_db : #{@output_db}*"
61
- puts "files : #{@file_count}"
62
- puts "add : #{@add_count}"
63
- puts "update : #{@update_count}"
64
- end
65
-
66
- def dump()
67
- db_open(@output_db)
68
-
69
- documents = Groonga::Context.default["documents"]
70
- records = documents.select
71
- records.each do |record|
72
- p record
73
- puts "path : #{record.path}"
74
- puts "shortpath : #{record.shortpath}"
75
- puts "suffix : #{record.suffix}"
76
- puts "timestamp : #{record.timestamp.strftime('%Y/%m/%d %H:%M:%S')}"
77
- puts "content :", record.content ? record.content[0..64] : nil
78
- puts
79
- end
80
- end
81
-
82
- def db_create(filename)
83
- dbfile = Pathname(File.expand_path(filename))
84
- dbdir = dbfile.dirname
85
- dbdir.mkpath unless dbdir.exist?
86
-
87
- unless dbfile.exist?
88
- Groonga::Database.create(:path => dbfile.to_s)
89
- Groonga::Schema.define do |schema|
90
- schema.create_table("documents") do |table|
91
- table.string("path")
92
- table.string("shortpath")
93
- table.text("content")
94
- table.time("timestamp")
95
- table.text("suffix")
96
- end
97
-
98
- schema.create_table("terms",
99
- :type => :patricia_trie,
100
- :key_normalize => true,
101
- :default_tokenizer => "TokenBigram") do |table|
102
- table.index("documents.path", :with_position => true)
103
- table.index("documents.shortpath", :with_position => true)
104
- table.index("documents.content", :with_position => true)
105
- table.index("documents.suffix", :with_position => true)
106
- end
107
- end
108
- puts "create : #{filename} created."
109
- else
110
- puts "message : #{filename} already exist."
111
- end
112
- end
113
- private :db_create
114
-
115
- def db_delete(filename)
116
- raise "Illegal file name : #{filename}." unless filename =~ /\.db$/
117
- Dir.glob("#{filename}*").each do |f|
118
- puts "delete : #{f}"
119
- FileUtils.rm_r(f)
120
- end
121
- end
122
- private :db_delete
123
-
124
- def db_open(filename)
125
- dbfile = Pathname(File.expand_path(filename))
126
-
127
- if dbfile.exist?
128
- Groonga::Database.open(dbfile.to_s)
129
- puts "open : #{dbfile} open."
130
- else
131
- raise "error : #{dbfile.to_s} not found!!"
132
- end
133
- end
134
- private :db_open
135
-
136
- def db_add_dir(dirname)
137
- searchDirectory(STDOUT, dirname, File.basename(dirname), 0)
138
- end
139
- private :db_add_dir
140
-
141
- def db_add_file(stdout, filename, shortpath)
142
- # 格納するデータ
143
- values = {
144
- :path => filename,
145
- :shortpath => shortpath,
146
- :content => nil,
147
- :timestamp => File.mtime(filename),
148
- :suffix => File::extname(filename),
149
- }
150
-
151
- # 検索するデータベース
152
- documents = Groonga::Context.default["documents"]
153
-
154
- # 既に登録されているファイルならばそれを上書き、そうでなければ新規レコードを作成
155
- _documents = documents.select do |record|
156
- record["path"] == values[:path]
157
- end
158
-
159
- isNewFile = false
160
-
161
- if _documents.size.zero?
162
- document = documents.add
163
- isNewFile = true
164
- else
165
- document = _documents.to_a[0].key
166
- end
167
-
168
- # タイムスタンプが新しければデータベースに格納
169
- if (document[:timestamp] < values[:timestamp])
170
- # 実際に使うタイミングでファイルの内容を読み込み
171
- values[:content] = open(filename).read
172
-
173
- # データベースに格納
174
- values.each do |key, value|
175
- if (key == :path)
176
- if (isNewFile)
177
- @add_count += 1
178
- puts "add_file : #{value}"
179
- else
180
- @update_count += 1
181
- puts "update : #{value}"
182
- end
183
- end
184
- document[key] = value
185
- end
186
- end
187
-
188
- end
189
-
190
- def searchDirectory(stdout, dir, shortdir, depth)
191
- Dir.foreach(dir) do |name|
192
- next if (name == '.' || name == '..')
193
-
194
- fpath = File.join(dir,name)
195
- shortpath = File.join(shortdir,name)
196
-
197
- # 除外ディレクトリならばパス
198
- next if ignoreDir?(fpath)
199
-
200
- # 読み込み不可ならばパス
201
- next unless FileTest.readable?(fpath)
202
-
203
- # ファイルならば中身を探索、ディレクトリならば再帰
204
- case File.ftype(fpath)
205
- when "directory"
206
- searchDirectory(stdout, fpath, shortpath, depth + 1)
207
- when "file"
208
- unless ignoreFile?(fpath)
209
- db_add_file(stdout, fpath, shortpath)
210
- @file_count += 1
211
- puts "file_count : #{@file_count}" if (@file_count % 100 == 0)
212
- end
213
- end
214
- end
215
- end
216
-
217
- def ignoreDir?(fpath)
218
- FileTest.directory?(fpath) &&
219
- GrenFileTest::ignoreDir?(fpath)
220
- end
221
- private :ignoreDir?
222
-
223
- def ignoreFile?(fpath)
224
- GrenFileTest::ignoreFile?(fpath) ||
225
- GrenFileTest::binary?(fpath)
226
- end
227
- private :ignoreFile?
228
-
229
- end
230
- end