gonzui 1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS.txt +9 -0
- data/History.txt +5539 -0
- data/Manifest.txt +115 -0
- data/PostInstall.txt +17 -0
- data/README.rdoc +149 -0
- data/Rakefile +28 -0
- data/bin/gonzui-db +167 -0
- data/bin/gonzui-import +177 -0
- data/bin/gonzui-remove +58 -0
- data/bin/gonzui-search +68 -0
- data/bin/gonzui-server +176 -0
- data/bin/gonzui-update +53 -0
- data/data/gonzui/catalog/catalog.ja +80 -0
- data/data/gonzui/doc/favicon.ico +0 -0
- data/data/gonzui/doc/folder.png +0 -0
- data/data/gonzui/doc/gonzui.css +279 -0
- data/data/gonzui/doc/gonzui.js +111 -0
- data/data/gonzui/doc/text.png +0 -0
- data/data/gonzuirc.sample +29 -0
- data/ext/autopack/autopack.c +88 -0
- data/ext/autopack/extconf.rb +3 -0
- data/ext/delta/delta.c +147 -0
- data/ext/delta/extconf.rb +5 -0
- data/ext/texttokenizer/extconf.rb +5 -0
- data/ext/texttokenizer/texttokenizer.c +93 -0
- data/ext/xmlformatter/extconf.rb +5 -0
- data/ext/xmlformatter/xmlformatter.c +207 -0
- data/lib/gonzui.rb +59 -0
- data/lib/gonzui/apt.rb +193 -0
- data/lib/gonzui/bdbdbm.rb +118 -0
- data/lib/gonzui/cmdapp.rb +14 -0
- data/lib/gonzui/cmdapp/app.rb +175 -0
- data/lib/gonzui/cmdapp/search.rb +134 -0
- data/lib/gonzui/config.rb +117 -0
- data/lib/gonzui/content.rb +19 -0
- data/lib/gonzui/dbm.rb +673 -0
- data/lib/gonzui/deindexer.rb +162 -0
- data/lib/gonzui/delta.rb +49 -0
- data/lib/gonzui/extractor.rb +347 -0
- data/lib/gonzui/fetcher.rb +309 -0
- data/lib/gonzui/gettext.rb +144 -0
- data/lib/gonzui/importer.rb +84 -0
- data/lib/gonzui/indexer.rb +316 -0
- data/lib/gonzui/info.rb +80 -0
- data/lib/gonzui/license.rb +100 -0
- data/lib/gonzui/logger.rb +48 -0
- data/lib/gonzui/monitor.rb +177 -0
- data/lib/gonzui/progressbar.rb +235 -0
- data/lib/gonzui/remover.rb +38 -0
- data/lib/gonzui/searcher.rb +330 -0
- data/lib/gonzui/searchquery.rb +235 -0
- data/lib/gonzui/searchresult.rb +111 -0
- data/lib/gonzui/updater.rb +254 -0
- data/lib/gonzui/util.rb +415 -0
- data/lib/gonzui/vcs.rb +128 -0
- data/lib/gonzui/webapp.rb +25 -0
- data/lib/gonzui/webapp/advsearch.rb +123 -0
- data/lib/gonzui/webapp/filehandler.rb +24 -0
- data/lib/gonzui/webapp/jsfeed.rb +61 -0
- data/lib/gonzui/webapp/markup.rb +445 -0
- data/lib/gonzui/webapp/search.rb +269 -0
- data/lib/gonzui/webapp/servlet.rb +319 -0
- data/lib/gonzui/webapp/snippet.rb +155 -0
- data/lib/gonzui/webapp/source.rb +37 -0
- data/lib/gonzui/webapp/stat.rb +137 -0
- data/lib/gonzui/webapp/top.rb +63 -0
- data/lib/gonzui/webapp/uri.rb +140 -0
- data/lib/gonzui/webapp/webrick.rb +48 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/makemanifest.rb +21 -0
- data/tasks/extconf.rake +13 -0
- data/tasks/extconf/autopack.rake +43 -0
- data/tasks/extconf/delta.rake +43 -0
- data/tasks/extconf/texttokenizer.rake +43 -0
- data/tasks/extconf/xmlformatter.rake +43 -0
- data/test/_external_tools.rb +13 -0
- data/test/_test-util.rb +142 -0
- data/test/foo/Makefile.foo +66 -0
- data/test/foo/bar.c +5 -0
- data/test/foo/bar.h +6 -0
- data/test/foo/foo.c +25 -0
- data/test/foo/foo.spec +33 -0
- data/test/test_apt.rb +42 -0
- data/test/test_autopack_extn.rb +7 -0
- data/test/test_bdbdbm.rb +79 -0
- data/test/test_cmdapp-app.rb +35 -0
- data/test/test_cmdapp-search.rb +99 -0
- data/test/test_config.rb +28 -0
- data/test/test_content.rb +15 -0
- data/test/test_dbm.rb +171 -0
- data/test/test_deindexer.rb +50 -0
- data/test/test_delta.rb +66 -0
- data/test/test_extractor.rb +78 -0
- data/test/test_fetcher.rb +75 -0
- data/test/test_gettext.rb +50 -0
- data/test/test_gonzui.rb +11 -0
- data/test/test_helper.rb +10 -0
- data/test/test_importer.rb +56 -0
- data/test/test_indexer.rb +37 -0
- data/test/test_info.rb +82 -0
- data/test/test_license.rb +49 -0
- data/test/test_logger.rb +60 -0
- data/test/test_monitor.rb +23 -0
- data/test/test_searcher.rb +37 -0
- data/test/test_searchquery.rb +27 -0
- data/test/test_searchresult.rb +43 -0
- data/test/test_texttokenizer.rb +47 -0
- data/test/test_updater.rb +95 -0
- data/test/test_util.rb +149 -0
- data/test/test_vcs.rb +61 -0
- data/test/test_webapp-markup.rb +42 -0
- data/test/test_webapp-util.rb +19 -0
- data/test/test_webapp-xmlformatter.rb +19 -0
- metadata +291 -0
data/lib/gonzui/vcs.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
#
|
2
|
+
# vcs.rb - simple interface to version control systems
|
3
|
+
#
|
4
|
+
# Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
|
5
|
+
# All rights reserved.
|
6
|
+
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
#
|
8
|
+
# You can redistribute it and/or modify it under the terms of
|
9
|
+
# the GNU General Public License version 2.
|
10
|
+
#
|
11
|
+
|
12
|
+
module Gonzui
|
13
|
+
class VCSError < GonzuiError; end
|
14
|
+
|
15
|
+
class AbstractVCS
|
16
|
+
include Util
|
17
|
+
|
18
|
+
def initialize(config, root, mozule)
|
19
|
+
@config = config
|
20
|
+
@root = root
|
21
|
+
@mozule = mozule
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def run_command(command_line, message)
|
26
|
+
printf("running %s...\n", message) unless @config.quiet
|
27
|
+
dn = "/dev/null"
|
28
|
+
dn = "nul" if (/mswin|mingw|bccwin/ =~ RUBY_PLATFORM)
|
29
|
+
command_line += ">#{dn} 2>&1" unless @config.verbose
|
30
|
+
status = system(command_line)
|
31
|
+
raise VCSError.new("command execution failed") if status == false
|
32
|
+
end
|
33
|
+
|
34
|
+
public
|
35
|
+
def extract
|
36
|
+
File.mkpath(@config.cache_directory)
|
37
|
+
output_directory = File.join(@config.cache_directory, @mozule)
|
38
|
+
if not File.exist?(output_directory)
|
39
|
+
do_checkout(output_directory)
|
40
|
+
elsif File.directory?(output_directory)
|
41
|
+
do_update(output_directory)
|
42
|
+
else
|
43
|
+
raise VCSError.new("#{output_directory}: obstacle found")
|
44
|
+
end
|
45
|
+
return output_directory
|
46
|
+
end
|
47
|
+
|
48
|
+
def clean
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class CVS < AbstractVCS
|
53
|
+
def initialize(config, root, mozule)
|
54
|
+
require_command("cvs")
|
55
|
+
super(config, root, mozule)
|
56
|
+
end
|
57
|
+
|
58
|
+
def do_checkout(output_directory)
|
59
|
+
Dir.chdir(@config.cache_directory) {
|
60
|
+
command_line = sprintf("cvs -z3 -d %s co -P %s",
|
61
|
+
shell_escape(@root),
|
62
|
+
shell_escape(@mozule))
|
63
|
+
run_command(command_line, "cvs checkout")
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def do_update(output_directory)
|
68
|
+
Dir.chdir(output_directory) {
|
69
|
+
run_command("cvs -z3 update -dP", "cvs update")
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def do_extract
|
74
|
+
File.mkpath(@config.cache_directory)
|
75
|
+
output_directory = File.join(@config.cache_directory, @mozule)
|
76
|
+
if File.exist?(output_directory)
|
77
|
+
run_cvs_update(output_directory)
|
78
|
+
else
|
79
|
+
run_cvs_checkout
|
80
|
+
end
|
81
|
+
return output_directory
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class Subversion < AbstractVCS
|
86
|
+
def initialize(config, root, mozule)
|
87
|
+
require_command("svn")
|
88
|
+
super(config, root, mozule)
|
89
|
+
end
|
90
|
+
|
91
|
+
def do_checkout(output_directory)
|
92
|
+
Dir.chdir(@config.cache_directory) {
|
93
|
+
command_line = sprintf("svn co %s %s",
|
94
|
+
shell_escape(@root),
|
95
|
+
shell_escape(@mozule))
|
96
|
+
run_command(command_line, "svn checkout")
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
def do_update(output_directory)
|
101
|
+
Dir.chdir(output_directory) {
|
102
|
+
run_command("svn update","svn update")
|
103
|
+
}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Git < AbstractVCS
|
108
|
+
def initialize(config, root, mozule = nil)
|
109
|
+
require_command("git")
|
110
|
+
mozule = File.basename(URI.parse(root).path, ".git") unless mozule
|
111
|
+
super(config, root, mozule)
|
112
|
+
end
|
113
|
+
|
114
|
+
def do_checkout(output_directory)
|
115
|
+
Dir.chdir(@config.cache_directory) {
|
116
|
+
command_line = sprintf("git clone %s",
|
117
|
+
shell_escape(@root))
|
118
|
+
run_command(command_line, "git clone")
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
def do_update(output_directory)
|
123
|
+
Dir.chdir(output_directory) {
|
124
|
+
run_command("git pull","git pull")
|
125
|
+
}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# webapp.rb - a library for web-based applications
|
3
|
+
#
|
4
|
+
# Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
|
5
|
+
# All rights reserved.
|
6
|
+
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
#
|
8
|
+
# You can redistribute it and/or modify it under the terms of
|
9
|
+
# the GNU General Public License version 2.
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'gonzui/webapp/xmlformatter'
|
13
|
+
require 'gonzui/webapp/webrick'
|
14
|
+
require 'gonzui/webapp/uri'
|
15
|
+
require 'gonzui/webapp/servlet'
|
16
|
+
require 'gonzui/webapp/snippet'
|
17
|
+
|
18
|
+
require 'gonzui/webapp/advsearch'
|
19
|
+
require 'gonzui/webapp/filehandler'
|
20
|
+
require 'gonzui/webapp/jsfeed'
|
21
|
+
require 'gonzui/webapp/markup'
|
22
|
+
require 'gonzui/webapp/search'
|
23
|
+
require 'gonzui/webapp/source'
|
24
|
+
require 'gonzui/webapp/stat'
|
25
|
+
require 'gonzui/webapp/top'
|
@@ -0,0 +1,123 @@
|
|
1
|
+
#
|
2
|
+
# advsearch.rb - advanced search servlet
|
3
|
+
#
|
4
|
+
# Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
|
5
|
+
# All rights reserved.
|
6
|
+
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
#
|
8
|
+
# You can redistribute it and/or modify it under the terms of
|
9
|
+
# the GNU General Public License version 2.
|
10
|
+
#
|
11
|
+
|
12
|
+
module Gonzui
|
13
|
+
class AdvancedSearchServlet < GonzuiAbstractServlet
|
14
|
+
def self.mount_point
|
15
|
+
"advsearch"
|
16
|
+
end
|
17
|
+
|
18
|
+
def do_make_status_line
|
19
|
+
[]
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_target_select
|
23
|
+
tt = get_short_name(:target_type)
|
24
|
+
select = [:select, {:name => tt}]
|
25
|
+
oall = [:option, {:type => "radio", :name => tt,
|
26
|
+
:value => ""}, _("All")]
|
27
|
+
select.push(oall)
|
28
|
+
LangScan::Type.each_group {|group|
|
29
|
+
og = [:optgroup, {:label => _(group.name)}]
|
30
|
+
added_p = false
|
31
|
+
group.each {|type_info|
|
32
|
+
if @dbm.has_type?(type_info.type)
|
33
|
+
o = [:option, {:type => "radio", :name => tt,
|
34
|
+
:value => type_info.type}, _(type_info.name)]
|
35
|
+
og.push(o)
|
36
|
+
added_p = true
|
37
|
+
end
|
38
|
+
}
|
39
|
+
select.push(og) if added_p
|
40
|
+
}
|
41
|
+
return select
|
42
|
+
end
|
43
|
+
|
44
|
+
def make_nresults_select
|
45
|
+
nr = get_short_name(:nresults_per_page)
|
46
|
+
select = [:select, {:name => nr}]
|
47
|
+
@config.nresults_candidates.each {|n|
|
48
|
+
o = [:option, {:type => "radio", :name => nr,
|
49
|
+
:value => n}, sprintf(_("%d results"), n)]
|
50
|
+
select.push(o)
|
51
|
+
}
|
52
|
+
return select
|
53
|
+
end
|
54
|
+
|
55
|
+
def make_target_specific_search_form
|
56
|
+
form = [:form, { :method => "get",
|
57
|
+
:action => make_uri_general(SearchServlet)}]
|
58
|
+
|
59
|
+
ikeyword = [:input, {:type => "text", :size => 30,
|
60
|
+
:name => get_short_name(:basic_query),
|
61
|
+
:value => @search_query.keywords.join(" ")}]
|
62
|
+
iphrase = [:input, {:type => "text", :size => 30,
|
63
|
+
:name => get_short_name(:phrase_query),
|
64
|
+
:value => (@search_query.phrases.first or []).join(" ")}]
|
65
|
+
|
66
|
+
nresults_select = make_nresults_select
|
67
|
+
|
68
|
+
isubmit = [:input, {:type => "submit", :value => _("Search")}]
|
69
|
+
|
70
|
+
table = [:table]
|
71
|
+
table.push([:tr, [:td, {:width => "20%"}, _("Keyword")],
|
72
|
+
[:td, {:width => "30%"}, ikeyword],
|
73
|
+
[:td, {:width => "15%"}, nresults_select],
|
74
|
+
[:td, {:width => "15%"}, isubmit]])
|
75
|
+
table.push([:tr, [:td, {:width => "20%"}, _("Phrase")],
|
76
|
+
[:td, {:width => "30%"}, iphrase]])
|
77
|
+
|
78
|
+
table.push([:tr])
|
79
|
+
|
80
|
+
target_select = make_target_select
|
81
|
+
table.push([:tr, [:td, _("Target")],
|
82
|
+
[:td, target_select], [:td]])
|
83
|
+
|
84
|
+
format_select = make_format_select
|
85
|
+
table.push([:tr, [:td, _("Format")], [:td, format_select], [:td]])
|
86
|
+
|
87
|
+
license_select = make_license_select
|
88
|
+
table.push([:tr, [:td, _("License")], [:td, license_select], [:td]])
|
89
|
+
|
90
|
+
form.push(table)
|
91
|
+
return form
|
92
|
+
end
|
93
|
+
|
94
|
+
def make_advanced_search_form
|
95
|
+
form = make_target_specific_search_form
|
96
|
+
return [:div, {:class =>"advanced-search"}, form]
|
97
|
+
end
|
98
|
+
|
99
|
+
def do_GET(request, response)
|
100
|
+
init_servlet(request, response)
|
101
|
+
log()
|
102
|
+
|
103
|
+
html = make_html
|
104
|
+
title = make_title(_("Advanced Search"))
|
105
|
+
head = [:head, title, *make_meta_and_css]
|
106
|
+
body = [:body]
|
107
|
+
|
108
|
+
h1 = make_h1
|
109
|
+
status_line = make_status_line(_("Advanced Search"))
|
110
|
+
content = make_advanced_search_form
|
111
|
+
footer = make_footer
|
112
|
+
body.push(h1, status_line, content, footer)
|
113
|
+
|
114
|
+
html.push(head)
|
115
|
+
html.push(body)
|
116
|
+
set_content_type_text_html
|
117
|
+
response.body = format_html(html)
|
118
|
+
end
|
119
|
+
|
120
|
+
GonzuiServlet.register(self)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# filehandler.rb - file handler servlet
|
3
|
+
#
|
4
|
+
# Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
|
5
|
+
# All rights reserved.
|
6
|
+
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
#
|
8
|
+
# You can redistribute it and/or modify it under the terms of
|
9
|
+
# the GNU General Public License version 2.
|
10
|
+
#
|
11
|
+
|
12
|
+
module Gonzui
|
13
|
+
class FileHandler < WEBrick::HTTPServlet::FileHandler
|
14
|
+
def self.mount_point
|
15
|
+
"doc"
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(server, config, logger, dbm, catalogs)
|
19
|
+
super(server, config.doc_directory)
|
20
|
+
end
|
21
|
+
|
22
|
+
GonzuiServlet.register(self)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# jsfeed - javascript-feed servlet
|
3
|
+
#
|
4
|
+
# Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
|
5
|
+
# All rights reserved.
|
6
|
+
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
#
|
8
|
+
# You can redistribute it and/or modify it under the terms of
|
9
|
+
# the GNU General Public License version 2.
|
10
|
+
#
|
11
|
+
|
12
|
+
module Gonzui
|
13
|
+
class JSFeedServlet < GonzuiAbstractServlet
|
14
|
+
def self.mount_point
|
15
|
+
"jsfeed"
|
16
|
+
end
|
17
|
+
|
18
|
+
def do_GET(request, response)
|
19
|
+
init_servlet(request, response)
|
20
|
+
path = make_path
|
21
|
+
log(path)
|
22
|
+
|
23
|
+
from = to = nil
|
24
|
+
if m = /^(\d+)-(\d+)$/.match(request.query_string)
|
25
|
+
from = m[1].to_i
|
26
|
+
to = m[2].to_i
|
27
|
+
end
|
28
|
+
|
29
|
+
if from and to
|
30
|
+
path_id = @dbm.get_path_id(path)
|
31
|
+
if path_id
|
32
|
+
content = @dbm.get_content(path_id)
|
33
|
+
lineno = 0
|
34
|
+
lines = []
|
35
|
+
range = Range.new(from, to)
|
36
|
+
content.each_line {|line|
|
37
|
+
lineno += 1
|
38
|
+
if range.include?(lineno)
|
39
|
+
line_with_lineno = sprintf("%5d: %s", lineno, line)
|
40
|
+
line_with_lineno.chop!
|
41
|
+
lines.push(HTMLUtils.escape(line_with_lineno))
|
42
|
+
end
|
43
|
+
}
|
44
|
+
snippet = lines.join("<br />")
|
45
|
+
response.body = sprintf("document.writeln('<pre>%s</pre>');",
|
46
|
+
snippet)
|
47
|
+
response['Content-Type'] = "application/x-javascript"
|
48
|
+
else
|
49
|
+
response.body = sprintf("%s: not found", path)
|
50
|
+
response.status = 404
|
51
|
+
response['Content-Type'] = "text/html"
|
52
|
+
end
|
53
|
+
else
|
54
|
+
response.body = "invalid query"
|
55
|
+
response['Content-Type'] = "text/html"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
GonzuiServlet.register(self)
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,445 @@
|
|
1
|
+
#
|
2
|
+
# markup.rb - markup servlet
|
3
|
+
#
|
4
|
+
# Copyright (C) 2004-2005 Satoru Takabayashi <satoru@namazu.org>
|
5
|
+
# All rights reserved.
|
6
|
+
# This is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
#
|
8
|
+
# You can redistribute it and/or modify it under the terms of
|
9
|
+
# the GNU General Public License version 2.
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'stringio'
|
13
|
+
require 'zlib'
|
14
|
+
require 'strscan'
|
15
|
+
|
16
|
+
module Gonzui
|
17
|
+
class TextBeautifier
|
18
|
+
def initialize(content, digest, occurrences, search_uri)
|
19
|
+
@content = content
|
20
|
+
@digest = digest # to be destroyed
|
21
|
+
@occurrences = occurrences # to be destroyed
|
22
|
+
@search_uri = search_uri
|
23
|
+
|
24
|
+
@break_points = [0, @content.length]
|
25
|
+
@lines = {}
|
26
|
+
pos = lineno = 0
|
27
|
+
@content.each_line {|line|
|
28
|
+
lineno += 1
|
29
|
+
@break_points.push(pos)
|
30
|
+
@lines[pos] = [lineno, line]
|
31
|
+
pos += line.length
|
32
|
+
}
|
33
|
+
@digest.each {|info|
|
34
|
+
@break_points.push(info.byteno)
|
35
|
+
@break_points.push(info.end_byteno)
|
36
|
+
}
|
37
|
+
@occurrences.each {|occ|
|
38
|
+
@break_points.push(occ.byteno)
|
39
|
+
@break_points.push(occ.end_byteno)
|
40
|
+
}
|
41
|
+
@break_points.uniq!
|
42
|
+
@break_points.sort!
|
43
|
+
|
44
|
+
@info = @digest.shift
|
45
|
+
@occ = @occurrences.shift
|
46
|
+
@seen_ids = {}
|
47
|
+
@latest_id = "0"
|
48
|
+
end
|
49
|
+
|
50
|
+
def make_line_mark(lineno)
|
51
|
+
anchor = "l" + lineno.to_s
|
52
|
+
[:span, {:class => "lineno", :onclick => "olnc(this);"},
|
53
|
+
[:a, {:id => anchor, :name => anchor, :href => "#" + anchor},
|
54
|
+
sprintf("%5d: ", lineno)]]
|
55
|
+
end
|
56
|
+
|
57
|
+
def choose_target_type
|
58
|
+
case @info.type
|
59
|
+
when :fundef
|
60
|
+
:funcall
|
61
|
+
when :funcall
|
62
|
+
:fundef
|
63
|
+
when :fundecl
|
64
|
+
:fundef
|
65
|
+
else
|
66
|
+
assert_not_reached
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def decorate(text)
|
71
|
+
unless @seen_ids.include?(text)
|
72
|
+
@seen_ids[text] = @latest_id
|
73
|
+
@latest_id = @latest_id.next
|
74
|
+
end
|
75
|
+
id = @seen_ids[text]
|
76
|
+
inner = [:span, {:class => id, :onmouseover => "hl('#{id}');"}, text]
|
77
|
+
part = [:span, {:class => @info.type.to_s}, inner]
|
78
|
+
|
79
|
+
if LangScan::Type.function?(@info.type)
|
80
|
+
tt = choose_target_type
|
81
|
+
query_string = sprintf("%s:%s", tt, HTTPUtils.escape_form(text))
|
82
|
+
uri = @search_uri + query_string
|
83
|
+
part = [:a, {:href => uri}, part]
|
84
|
+
end
|
85
|
+
return part
|
86
|
+
end
|
87
|
+
|
88
|
+
def markup_part(bp, ep)
|
89
|
+
part = @content[bp...ep]
|
90
|
+
if @info and (bp == @info.byteno or @info.range.include?(bp))
|
91
|
+
part = decorate(part)
|
92
|
+
@info = @digest.shift if @info.end_byteno <= ep
|
93
|
+
end
|
94
|
+
if @occ and (bp == @occ.byteno or @occ.range.include?(bp))
|
95
|
+
part = [:strong, {:class => "highlight"}, part]
|
96
|
+
@occ = @occurrences.shift if @occ.end_byteno <= ep
|
97
|
+
end
|
98
|
+
return part
|
99
|
+
end
|
100
|
+
|
101
|
+
def make_lineno_part(bp)
|
102
|
+
lineno, line = @lines[bp]
|
103
|
+
[:span, {:class => "line", :title => line}, make_line_mark(lineno)]
|
104
|
+
end
|
105
|
+
|
106
|
+
def beautify
|
107
|
+
code = []
|
108
|
+
bp = @break_points.shift
|
109
|
+
line = nil
|
110
|
+
while not @break_points.empty?
|
111
|
+
ep = @break_points.shift
|
112
|
+
if @lines.include?(bp)
|
113
|
+
code.push(line) if line
|
114
|
+
line = make_lineno_part(bp)
|
115
|
+
end
|
116
|
+
part = markup_part(bp, ep)
|
117
|
+
line.push(part)
|
118
|
+
bp = ep
|
119
|
+
end
|
120
|
+
code.push(line) if line
|
121
|
+
return code
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class MarkupServlet < GonzuiAbstractServlet
|
126
|
+
def self.mount_point
|
127
|
+
"markup"
|
128
|
+
end
|
129
|
+
|
130
|
+
def make_breadcrumbs(path)
|
131
|
+
parts = path.split("/")
|
132
|
+
breadcrumbs = (1 .. parts.length).map {|i|
|
133
|
+
[ parts[i - 1], parts[0, i]]
|
134
|
+
}.map {|part, parts|
|
135
|
+
path = parts.join("/")
|
136
|
+
uri = make_markup_uri(parts.join("/"), @search_query)
|
137
|
+
[:a, {:href => uri}, part]
|
138
|
+
}
|
139
|
+
(breadcrumbs.length - 1).times {|i|
|
140
|
+
breadcrumbs.insert(i * 2 + 1, "/")
|
141
|
+
}
|
142
|
+
return [:span, *breadcrumbs]
|
143
|
+
end
|
144
|
+
|
145
|
+
def do_make_status_line(method)
|
146
|
+
items = []
|
147
|
+
|
148
|
+
case method
|
149
|
+
when :markup_file
|
150
|
+
if @path_id
|
151
|
+
bare = [:a, {:href => make_source_uri(@path)},
|
152
|
+
_("bare source")]
|
153
|
+
permlink = [:a, {:href => make_markup_uri(@path)},
|
154
|
+
_("permlink")]
|
155
|
+
items.push(bare)
|
156
|
+
items.push(permlink)
|
157
|
+
end
|
158
|
+
when :list_files
|
159
|
+
if @total
|
160
|
+
items.push([:span, [:strong, @total], _(" contents.")])
|
161
|
+
end
|
162
|
+
when :list_packages
|
163
|
+
if @to and @total
|
164
|
+
packages = [:span, _("Packages "),
|
165
|
+
[:strong, commify(@from + 1)], " - ",
|
166
|
+
[:strong, commify(@to)], _(" of "),
|
167
|
+
[:strong, commify(@total)], _(".")]
|
168
|
+
items.push(packages)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
return items
|
172
|
+
end
|
173
|
+
|
174
|
+
def calc_ncolumns(items)
|
175
|
+
sum = items.inject(0) {|a, b|
|
176
|
+
name = b.first
|
177
|
+
a + name.length
|
178
|
+
}
|
179
|
+
average = sum / items.length
|
180
|
+
ncolumns = [40 / average, items.length].min
|
181
|
+
ncolumns = 1 if ncolumns == 0
|
182
|
+
return ncolumns
|
183
|
+
end
|
184
|
+
|
185
|
+
def make_table(items)
|
186
|
+
table = [:table, {:class => "fullwidth"}]
|
187
|
+
return table if items.empty?
|
188
|
+
ncolumns = calc_ncolumns(items)
|
189
|
+
width = sprintf("%d%%", 100/ncolumns)
|
190
|
+
|
191
|
+
nrows = (items.length - 1) / ncolumns + 1
|
192
|
+
nrows.times {|i|
|
193
|
+
k = if (i + 1) % 2 == 0 then "even" else "odd" end
|
194
|
+
row = [:tr, {:class => k}]
|
195
|
+
ncolumns.times {|j|
|
196
|
+
# item = items[j * nrows + i] # for vertical arrange
|
197
|
+
item = items[i * ncolumns + j]
|
198
|
+
value = if item
|
199
|
+
name, klass, image, uri, title = item
|
200
|
+
tr = [:tr]
|
201
|
+
if image
|
202
|
+
img = [:img, {:src => image, :alt => ""}]
|
203
|
+
tr << [:td, [:a, {:href => uri}, img]]
|
204
|
+
end
|
205
|
+
a = [:a, {:class => klass, :href =>uri,:title =>title}, name]
|
206
|
+
tr << [:td, a]
|
207
|
+
[:table, {:class => "item"}, tr]
|
208
|
+
else
|
209
|
+
make_spacer
|
210
|
+
end
|
211
|
+
k = if j == 0 then "first" else "nonfirst" end
|
212
|
+
td = [:td, {:width => width, :class => k}, value]
|
213
|
+
row.push(td)
|
214
|
+
}
|
215
|
+
table.push(row)
|
216
|
+
}
|
217
|
+
return table
|
218
|
+
end
|
219
|
+
|
220
|
+
def make_title_for_path(path, file_p)
|
221
|
+
title = if file_p
|
222
|
+
path_id = @dbm.get_path_id(path)
|
223
|
+
info = @dbm.get_content_info(path_id)
|
224
|
+
sprintf(_("Size: %s (%s lines)"),
|
225
|
+
format_bytes(info.size),
|
226
|
+
commify(info.nlines))
|
227
|
+
else
|
228
|
+
""
|
229
|
+
end
|
230
|
+
return title
|
231
|
+
end
|
232
|
+
|
233
|
+
def make_table_of_files(paths)
|
234
|
+
items = paths.map {|path, file_p|
|
235
|
+
basename = File.basename(path)
|
236
|
+
klass = if file_p then "file" else "directory" end
|
237
|
+
image = if file_p
|
238
|
+
make_doc_uri("text.png")
|
239
|
+
else
|
240
|
+
make_doc_uri("folder.png")
|
241
|
+
end
|
242
|
+
uri = make_markup_uri(path, @search_query)
|
243
|
+
title = make_title_for_path(path, file_p)
|
244
|
+
[basename, klass, image, uri, title]
|
245
|
+
}
|
246
|
+
return make_table(items)
|
247
|
+
end
|
248
|
+
|
249
|
+
def make_table_of_packages(package_names)
|
250
|
+
items = package_names.map {|package_name|
|
251
|
+
package_id = @dbm.get_package_id(package_name)
|
252
|
+
uri = make_markup_uri(package_name)
|
253
|
+
title = ""
|
254
|
+
[package_name, "directory", nil, uri, title]
|
255
|
+
}
|
256
|
+
return make_table(items)
|
257
|
+
end
|
258
|
+
|
259
|
+
def list_files
|
260
|
+
path_parts = @path.split("/")
|
261
|
+
depth = path_parts.length
|
262
|
+
|
263
|
+
package_id = @dbm.get_package_id(@package_name)
|
264
|
+
path_ids = @dbm.get_path_ids(package_id)
|
265
|
+
paths = path_ids.map {|path_id|
|
266
|
+
@dbm.get_path(path_id)
|
267
|
+
}.map {|path|
|
268
|
+
path.split("/")
|
269
|
+
}.find_all {|parts|
|
270
|
+
parts.length > depth and parts[0, depth] == path_parts
|
271
|
+
}.map {|parts|
|
272
|
+
file_p = parts.length == depth + 1
|
273
|
+
[parts[0, depth + 1].join("/"), file_p]
|
274
|
+
}.uniq
|
275
|
+
if paths.empty?
|
276
|
+
return ""
|
277
|
+
else
|
278
|
+
@total = paths.length
|
279
|
+
return make_table_of_files(paths)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def do_make_navi(from)
|
284
|
+
make_markup_uri("", nil, :from => from)
|
285
|
+
end
|
286
|
+
|
287
|
+
def list_packages
|
288
|
+
# FIXME: sorting every time is not efficient.
|
289
|
+
all = []
|
290
|
+
@dbm.each_package_name {|package_name|
|
291
|
+
all.push(package_name)
|
292
|
+
}
|
293
|
+
all.sort!
|
294
|
+
|
295
|
+
package_names = all[@from, @config.max_packages_per_page]
|
296
|
+
if package_names
|
297
|
+
@to = @from + package_names.length
|
298
|
+
@total = all.length
|
299
|
+
table = make_table_of_packages(package_names)
|
300
|
+
navi = make_navi(all.length, @from, @config.max_packages_per_page)
|
301
|
+
return [:div, table, navi]
|
302
|
+
else
|
303
|
+
return ""
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def markup_source
|
308
|
+
content = @dbm.get_content(@path_id)
|
309
|
+
digest = @dbm.get_digest(@path_id)
|
310
|
+
occurrences = if @search_query.string.empty?
|
311
|
+
[]
|
312
|
+
else
|
313
|
+
search_query = @search_query.clone
|
314
|
+
search_query.path ||= @path
|
315
|
+
searcher = Searcher.new(@dbm, search_query,
|
316
|
+
@config.max_results_overall)
|
317
|
+
result = searcher.search
|
318
|
+
item = result.first
|
319
|
+
if item and not item.list.empty?
|
320
|
+
item.list
|
321
|
+
else
|
322
|
+
[]
|
323
|
+
end
|
324
|
+
end
|
325
|
+
search_uri = make_search_uri_partial("")
|
326
|
+
beautifier = TextBeautifier.new(content, digest, occurrences, search_uri)
|
327
|
+
return beautifier.beautify
|
328
|
+
end
|
329
|
+
|
330
|
+
def make_isearch_form
|
331
|
+
isearch = [:div, {:class => "isearch"}]
|
332
|
+
form = [:form, {:method => "get", :action => "",
|
333
|
+
:onsubmit => "return false;"}]
|
334
|
+
p = [:p]
|
335
|
+
p.push(_("Search this content: "))
|
336
|
+
p.push([:input, {:type => "text", :name => "g", :size => "20",
|
337
|
+
:onkeyup => "isearch(this.value);",
|
338
|
+
:value => ""
|
339
|
+
}])
|
340
|
+
p.push(" ")
|
341
|
+
form.push(p)
|
342
|
+
isearch.push(form)
|
343
|
+
return isearch
|
344
|
+
end
|
345
|
+
|
346
|
+
def markup_file
|
347
|
+
path = @dbm.get_path(@path_id)
|
348
|
+
|
349
|
+
mime_type = get_mime_type(path)
|
350
|
+
media_type = get_media_type(path)
|
351
|
+
if media_type == "image"
|
352
|
+
img = [:img, {:src => make_source_uri(path),
|
353
|
+
:alt => path }]
|
354
|
+
content = [:div, {:class => "image"}, img]
|
355
|
+
elsif mime_type == "text/html"
|
356
|
+
iframe = [:iframe, {:src => make_source_uri(path),
|
357
|
+
:width => "100%", :height => "400"},
|
358
|
+
[:a, {:href => make_source_uri(path)}, path]
|
359
|
+
]
|
360
|
+
content = iframe
|
361
|
+
else
|
362
|
+
content = [:div]
|
363
|
+
isearch = make_isearch_form
|
364
|
+
content.push(isearch)
|
365
|
+
code = markup_source
|
366
|
+
content.push([:pre, *code])
|
367
|
+
end
|
368
|
+
return content
|
369
|
+
end
|
370
|
+
|
371
|
+
def make_not_found
|
372
|
+
sprintf(_("No contents were found matching %s"),
|
373
|
+
@path)
|
374
|
+
end
|
375
|
+
|
376
|
+
def gzip(string)
|
377
|
+
strio = StringIO.new
|
378
|
+
writer = Zlib::GzipWriter.new(strio)
|
379
|
+
writer.print(string)
|
380
|
+
writer.finish
|
381
|
+
return strio.string
|
382
|
+
end
|
383
|
+
|
384
|
+
def set_response(html)
|
385
|
+
set_content_type_text_html
|
386
|
+
body = format_html(html)
|
387
|
+
if @request.gzip_encoding_supported?
|
388
|
+
@response["Content-Encoding"] = "gzip"
|
389
|
+
@response.body = gzip(body)
|
390
|
+
else
|
391
|
+
@response.body = body
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
def choose_method
|
396
|
+
method = :make_not_found
|
397
|
+
if @path.empty?
|
398
|
+
method = :list_packages
|
399
|
+
title = make_title(_("List of Packages"))
|
400
|
+
status_title = _("List of Packages")
|
401
|
+
else
|
402
|
+
@path_id = @dbm.get_path_id(@path)
|
403
|
+
@package_name = @path.split("/").first
|
404
|
+
if @path_id
|
405
|
+
method = :markup_file
|
406
|
+
elsif @dbm.has_package?(@package_name)
|
407
|
+
method = :list_files
|
408
|
+
end
|
409
|
+
title = make_title(@path)
|
410
|
+
status_title = make_breadcrumbs(@path)
|
411
|
+
end
|
412
|
+
return method, title, status_title
|
413
|
+
end
|
414
|
+
|
415
|
+
def do_GET(request, response)
|
416
|
+
init_servlet(request, response)
|
417
|
+
log(@path)
|
418
|
+
|
419
|
+
@path = make_path
|
420
|
+
@to = nil
|
421
|
+
@total = nil
|
422
|
+
|
423
|
+
method, title, status_title = choose_method
|
424
|
+
|
425
|
+
html = make_html
|
426
|
+
head = [:head, title, make_script, *make_meta_and_css]
|
427
|
+
body = [:body, {:onload => "initCache();",
|
428
|
+
:onclick => "clearHighlight();" }]
|
429
|
+
body.push(make_h1)
|
430
|
+
body.push(make_search_form)
|
431
|
+
content = self.send(method)
|
432
|
+
|
433
|
+
status_line = make_status_line(status_title, method)
|
434
|
+
body.push(status_line)
|
435
|
+
body.push(content)
|
436
|
+
body.push(make_footer)
|
437
|
+
|
438
|
+
html.push(head)
|
439
|
+
html.push(body)
|
440
|
+
set_response(html)
|
441
|
+
end
|
442
|
+
|
443
|
+
GonzuiServlet.register(self)
|
444
|
+
end
|
445
|
+
end
|