gren 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,35 @@
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
+
@@ -0,0 +1,52 @@
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
+
@@ -0,0 +1,37 @@
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
+ @request = Rack::Request.new(env)
19
+ @query = Query.new(@request)
20
+
21
+ @response = Rack::Response.new
22
+ @response["Content-Type"] = "text/html; charset=UTF-8"
23
+
24
+ render
25
+ end
26
+
27
+ private
28
+
29
+ def render
30
+ @response.write HTMLRendeler.header("gren - help", "gren - help")
31
+ @response.write HTMLRendeler.sample_code
32
+ @response.write HTMLRendeler.footer
33
+ @response.to_a
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,37 @@
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
+ @request = Rack::Request.new(env)
19
+ @query = Query.new(@request)
20
+
21
+ @response = Rack::Response.new
22
+ @response["Content-Type"] = "text/html; charset=UTF-8"
23
+
24
+ render
25
+ end
26
+
27
+ private
28
+
29
+ def render
30
+ @response.write HTMLRendeler.header_home("gren", "gren", Version)
31
+ @response.write HTMLRendeler.search_box
32
+ @response.write HTMLRendeler.footer_home("??", Database.instance.fileNum)
33
+ @response.to_a
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,231 @@
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 self.header(title, header1)
17
+ <<EOS
18
+ <?xml version="1.0" encoding="utf-8"?>
19
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
20
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
21
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
22
+ <head>
23
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
24
+ <!-- <meta name="robot" content="noindex,nofollow" /> -->
25
+ <title>#{title}</title>
26
+ <link rel="stylesheet" href="/css/gren.css" type="text/css" media="all" />
27
+ </head>
28
+ <body>
29
+ <div class="header">
30
+ <h1>
31
+ <a href="/"><img src="/images/gren-icon-mini.png" alt="gren-icon" border="0"/></a>
32
+ #{header1}
33
+ </h1>
34
+ </div>
35
+
36
+ <div class="content">
37
+ EOS
38
+ end
39
+
40
+ def self.footer
41
+ <<EOS
42
+ </div>
43
+
44
+ <div class="footer">
45
+ </div>
46
+ </body>
47
+ </html>
48
+ EOS
49
+ end
50
+
51
+ def self.header_home(title, header1, version)
52
+ <<EOS
53
+ <?xml version="1.0" encoding="utf-8"?>
54
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
55
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
56
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
57
+ <head>
58
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
59
+ <!-- <meta name="robot" content="noindex,nofollow" /> -->
60
+ <title>#{title}</title>
61
+ <link rel="stylesheet" href="/css/gren.css" type="text/css" media="all" />
62
+ </head>
63
+ <body>
64
+ <div align="center">
65
+ <div class="header_home">
66
+ <h1>
67
+ <a href="/"><img src="/images/gren-icon.png" alt="gren-icon" border="0" height="100px"/></a>
68
+ #{header1} <font class="version">#{version}</font>
69
+ </h1>
70
+ </div>
71
+
72
+ <div class="content">
73
+ EOS
74
+ end
75
+
76
+ def self.footer_home(package, files)
77
+ <<EOS
78
+ </div>
79
+
80
+ <div class="footer_home">
81
+ <!-- <a href="/::search/p:*">#{package}</a>のパッケージ , -->
82
+ <a href="/::search/f:*">#{files}</a>のファイル<br>
83
+ <a href="/::help">ヘルプ</a> ,
84
+ <a href="http://ongaeshi.github.com/gren">grenについて</a>
85
+ </div>
86
+ </div>
87
+ </body>
88
+ </html>
89
+ EOS
90
+ end
91
+
92
+ def self.result_record(record, patterns, nth=1)
93
+ if (patterns.size > 0)
94
+ <<EOS
95
+ <dt class='result-record'><a href='#{"/::view/" + Rack::Utils::escape_html(record.shortpath)}'>#{record.shortpath}</a></dt>
96
+ <dd>
97
+ <pre class='lines'>
98
+ #{result_record_match_line(record, patterns, nth)}
99
+ </pre>
100
+ </dd>
101
+ EOS
102
+ else
103
+ <<EOS
104
+ <dt class='result-record'><a href='#{"/::view/" + Rack::Utils::escape_html(record.shortpath)}'>#{record.shortpath}</a></dt>
105
+ EOS
106
+ end
107
+ end
108
+
109
+ def self.result_record_match_line(record, patterns, nth)
110
+ str = ""
111
+
112
+ grep = Grep.new(record.content)
113
+ lines = grep.match_lines_or(patterns)
114
+
115
+ unless (lines.empty?)
116
+ index = lines[0].index
117
+
118
+ (index - nth..index + nth).each do |i|
119
+ if (0 <= i && i < grep.content.size)
120
+ match_datas = (i == index) ? lines[0].match_datas : []
121
+ str << line(i + 1, grep.content[i], match_datas) + "\n"
122
+ end
123
+ end
124
+ end
125
+
126
+ str
127
+ end
128
+
129
+ def self.record_content(record)
130
+ <<EOS
131
+ <pre>
132
+ #{record_content_line(record)}
133
+ </pre>
134
+ EOS
135
+ end
136
+
137
+ def self.record_content_line(record)
138
+ str = ""
139
+
140
+ grep = Grep.new(record.content)
141
+ grep.content.each_with_index do |l, index|
142
+ str << line(index + 1, l, []) + "\n"
143
+ end
144
+
145
+ str
146
+ end
147
+
148
+ def self.line(lineno, line, match_datas)
149
+ sprintf("%5d: %s", lineno, match_strong(Rack::Utils::escape_html(line), match_datas))
150
+ end
151
+
152
+ def self.match_strong(line, match_datas)
153
+ match_datas.each do |m|
154
+ line = line.split(m[0]).join('<strong>' + m[0] + '</strong>') unless (m.nil?)
155
+ end
156
+
157
+ line
158
+ end
159
+
160
+ def self.pagination_link(page, label)
161
+ href = "?page=#{page}"
162
+ pagination_span("<a href='#{href}'>#{label}</a>")
163
+ end
164
+
165
+ def self.pagination_span(content)
166
+ "<span class='pagination-link'>#{content}</span>\n"
167
+ end
168
+
169
+ def self.empty_summary()
170
+ <<EOS
171
+ <div class='search-summary'>
172
+ <p>gren web検索</p>
173
+ </div>
174
+ EOS
175
+ end
176
+
177
+ def self.search_summary(keyword, total_records, range, elapsed)
178
+ <<EOS
179
+ <div class='search-summary'>
180
+ <span class="keyword">#{keyword}</span>の検索結果:
181
+ <span class="total-entries">#{total_records}</span>件中
182
+ <span class="display-range">#{range.first} - #{range.last}</span>件(#{elapsed}秒)
183
+ </div>
184
+ EOS
185
+ end
186
+
187
+ def self.view_summary(path, elapsed)
188
+ <<EOS
189
+ <div class='search-summary'>
190
+ <span class="keyword">#{path}</span>(#{elapsed}秒)
191
+ </div>
192
+ EOS
193
+ end
194
+
195
+ def self.search_box(text = "")
196
+ <<EOS
197
+ <form method="post" action="/::search">
198
+ <p>
199
+ <input name="query" type="text" size="60" value="#{text}" />
200
+ <input type="submit" value="検索" />
201
+ </p>
202
+ </form>
203
+ EOS
204
+ end
205
+
206
+ def self.sample_code
207
+ <<EOS
208
+ <div class='sample-code'>
209
+ <ol>
210
+ <li>キーワードで検索<br>
211
+ #{link('def open')}
212
+ <li>1フレーズとして検索<br>
213
+ #{link('"def open"')}
214
+ <li>パッケージ名で絞り込み<br>
215
+ #{link('def open p:gren')}
216
+ <li>ファイル名や拡張子で絞り込み<br>
217
+ #{link('def open f:test s:rb')}
218
+ <li>組み合わせ<br>
219
+ #{link('p:gren p:tidtools s:rb f:test assert f:cli')}
220
+ </ol>
221
+ </div>
222
+ EOS
223
+ end
224
+
225
+ def self.link(keyword)
226
+ "<a href='/::search/#{Rack::Utils::escape_html(keyword)}'>#{keyword}</a>"
227
+ end
228
+ end
229
+ end
230
+
231
+
@@ -0,0 +1,63 @@
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
+ }