milkode 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/Gemfile +1 -1
  2. data/HISTORY.ja.rdoc +29 -0
  3. data/HISTORY.rdoc +14 -0
  4. data/VERSION +1 -1
  5. data/bin/gmilk +1 -1
  6. data/bin/milk +1 -1
  7. data/lib/milkode/cdstk/cdstk.rb +90 -38
  8. data/lib/milkode/cdstk/milkode_yaml.rb +6 -0
  9. data/lib/milkode/cdstk/yaml_file_wrapper.rb +4 -0
  10. data/lib/milkode/cdweb/app.rb +5 -5
  11. data/lib/milkode/cdweb/lib/command.rb +20 -4
  12. data/lib/milkode/cdweb/lib/database.rb +20 -16
  13. data/lib/milkode/cdweb/lib/grep.rb +6 -6
  14. data/lib/milkode/cdweb/lib/query.rb +36 -1
  15. data/lib/milkode/cdweb/lib/search_contents.rb +134 -19
  16. data/lib/milkode/cdweb/lib/search_fuzzy_gotoline.rb +162 -0
  17. data/lib/milkode/cdweb/lib/web_setting.rb +9 -1
  18. data/lib/milkode/cdweb/public/css/milkode.css +5 -0
  19. data/lib/milkode/cdweb/public/images/favicon.ico +0 -0
  20. data/lib/milkode/cdweb/public/js/milkode.js +46 -48
  21. data/lib/milkode/cdweb/views/index.haml +1 -0
  22. data/lib/milkode/cli.rb +6 -3
  23. data/lib/milkode/common/util.rb +19 -0
  24. data/lib/milkode/database/document_table.rb +40 -22
  25. data/lib/milkode/database/package_table.rb +1 -1
  26. data/lib/milkode/database/updater.rb +14 -7
  27. data/lib/milkode/findgrep/findgrep.rb +23 -11
  28. data/lib/milkode/grep/cli_grep.rb +1 -4
  29. data/milkode.gemspec +10 -5
  30. data/test/data/.gitignore.sjis +46 -0
  31. data/test/data/ignore_test_sjis/.gitignore +2 -0
  32. data/test/data/ignore_test_sjis/a.txt +1 -0
  33. data/test/test_cdstk.rb +2 -1
  34. data/test/test_ignore_setting.rb +9 -0
  35. data/test/test_query.rb +6 -0
  36. data/test/test_updater.rb +13 -1
  37. data/test/test_util.rb +10 -0
  38. metadata +17 -4
@@ -88,20 +88,23 @@ module Milkode
88
88
 
89
89
  # 検索
90
90
  result, total_records = [], 0
91
-
92
- unless is_not_search
93
- result, total_records = @documents.search_with_match(
94
- :patterns => patterns,
95
- :keywords => keywords,
96
- :paths => paths,
97
- :packages => packages,
98
- :strict_packages => strict_packages,
99
- :restpaths => fpaths,
100
- :suffixs => suffixs,
101
- :fpath_or_packages => fpath_or_packages,
102
- :offset => offset,
103
- :limit => limit
104
- )
91
+
92
+ begin
93
+ unless is_not_search
94
+ result, total_records = @documents.search_with_match(
95
+ :patterns => patterns,
96
+ :keywords => keywords,
97
+ :paths => paths,
98
+ :packages => packages,
99
+ :strict_packages => strict_packages,
100
+ :restpaths => fpaths,
101
+ :suffixs => suffixs,
102
+ :fpath_or_packages => fpath_or_packages,
103
+ :offset => offset,
104
+ :limit => limit
105
+ )
106
+ end
107
+ rescue Groonga::TooLargeOffset
105
108
  end
106
109
 
107
110
  # 結果
@@ -198,8 +201,9 @@ module Milkode
198
201
  def update_in(package)
199
202
  updater = Updater.new(@grndb, package.name)
200
203
  updater.set_package_ignore IgnoreSetting.new("/", package.ignore)
201
- updater.enable_no_auto_ignore if package.options[:no_auto_ignore]
202
- updater.enable_update_with_git_pull if package.options[:update_with_git_pull]
204
+ updater.enable_no_auto_ignore if package.options[:no_auto_ignore]
205
+ updater.enable_update_with_git_pull if package.options[:update_with_git_pull]
206
+ updater.enable_update_with_svn_update if package.options[:update_with_svn_update]
203
207
  updater.exec
204
208
  updater.result
205
209
  end
@@ -17,7 +17,7 @@ module Milkode
17
17
 
18
18
  def match_lines_stopover(patterns, max_match, start_index, is_sensitive)
19
19
  result = []
20
- patternRegexps = strs2regs(patterns, Util::ignore_case?(patterns, is_sensitive))
20
+ patternRegexps = strs2regs(patterns, is_sensitive)
21
21
  index = start_index
22
22
 
23
23
  lines = @content.split($/)
@@ -45,7 +45,7 @@ module Milkode
45
45
 
46
46
  def match_lines_and(patterns, is_sensitive)
47
47
  result = []
48
- patternRegexps = strs2regs(patterns, Util::ignore_case?(patterns, is_sensitive))
48
+ patternRegexps = strs2regs(patterns, is_sensitive)
49
49
  index = 0
50
50
 
51
51
  @content.each_line do |line|
@@ -63,7 +63,7 @@ module Milkode
63
63
  end
64
64
 
65
65
  def one_match_and(patterns, is_sensitive)
66
- patternRegexps = strs2regs(patterns, Util::ignore_case?(patterns, is_sensitive))
66
+ patternRegexps = strs2regs(patterns, is_sensitive)
67
67
  index = 0
68
68
 
69
69
  @content.each_line do |line|
@@ -82,13 +82,13 @@ module Milkode
82
82
 
83
83
  private
84
84
 
85
- def strs2regs(strs, ignore = false)
85
+ def strs2regs(strs, is_sensitive)
86
86
  regs = []
87
87
 
88
88
  strs.each do |v|
89
89
  option = 0
90
- option |= Regexp::IGNORECASE if (ignore)
91
- regs << Regexp.new(Regexp.escape(v), option)
90
+ option |= Regexp::IGNORECASE if (!is_sensitive && Util::downcase?(v))
91
+ regs << Regexp.new(Regexp.escape(v), option)
92
92
  end
93
93
 
94
94
  regs
@@ -18,6 +18,7 @@ module Milkode
18
18
  ['suffix', 's'],
19
19
  ['fp'], # fpath or package
20
20
  ['keyword', 'k'],
21
+ ['gotoline', 'g'],
21
22
  ]
22
23
 
23
24
  def initialize(str)
@@ -31,7 +32,11 @@ module Milkode
31
32
  end
32
33
 
33
34
  def empty?
34
- keywords.size == 0 && packages.size == 0 && fpaths.size == 0 && suffixs.size == 0 && fpath_or_packages.size == 0
35
+ keywords.size == 0 && packages.size == 0 && fpaths.size == 0 && suffixs.size == 0 && fpath_or_packages.size == 0 && gotolines.size == 0
36
+ end
37
+
38
+ def only_keywords
39
+ packages.size == 0 && fpaths.size == 0 && suffixs.size == 0 && fpath_or_packages.size == 0 && gotolines.size == 0
35
40
  end
36
41
 
37
42
  def keywords
@@ -59,6 +64,10 @@ module Milkode
59
64
  calc_param(4)
60
65
  end
61
66
 
67
+ def gotolines
68
+ calc_param(5)
69
+ end
70
+
62
71
  def conv_keywords_to_fpath
63
72
  s = query_string.split.map {|v|
64
73
  if keywords.include? v
@@ -83,6 +92,32 @@ module Milkode
83
92
  Query.new(s)
84
93
  end
85
94
 
95
+ # 'name def test' -> 'fp:name def test'
96
+ def conv_head_keyword_to_fpath_or_packages
97
+ s = query_string.split.map {|v|
98
+ if keywords[0].include? v
99
+ "fp:#{v}"
100
+ else
101
+ v
102
+ end
103
+ }.join(' ')
104
+
105
+ Query.new(s)
106
+ end
107
+
108
+ # 'cdstk.rb:11' -> 'g:cdstk.rb:11'
109
+ def conv_fuzzy_gotoline
110
+ s = query_string.split.map {|v|
111
+ if keywords[0].include? v
112
+ "g:#{v}"
113
+ else
114
+ v
115
+ end
116
+ }.join(' ')
117
+
118
+ Query.new(s)
119
+ end
120
+
86
121
  private
87
122
 
88
123
  def calc_param(index)
@@ -9,11 +9,11 @@ require 'milkode/cdweb/lib/query'
9
9
  require 'milkode/cdweb/lib/grep'
10
10
  require 'milkode/cdweb/lib/mkurl'
11
11
  require 'milkode/common/util'
12
+ require 'milkode/cdweb/lib/search_fuzzy_gotoline'
12
13
 
13
14
  module Milkode
14
15
  class SearchContents
15
16
  attr_reader :total_records
16
- attr_reader :elapsed
17
17
  attr_reader :page
18
18
 
19
19
  DISP_NUM = 20 # 1ページの表示数
@@ -23,7 +23,7 @@ module Milkode
23
23
 
24
24
  MATH_FILE_DISP = 3 # マッチファイルの最大表示数
25
25
  MATH_FILE_LIMIT = MATH_FILE_DISP + 1 # マッチファイルの検索リミット数
26
-
26
+
27
27
  def initialize(path, params, query)
28
28
  @path = path
29
29
  @params = params
@@ -33,23 +33,48 @@ module Milkode
33
33
  @line = params[:line].to_i
34
34
  @is_onematch = params[:onematch] == 'on'
35
35
  @is_sensitive = params[:sensitive] == 'on'
36
-
37
- # メインの検索
38
- @records, @total_records, @elapsed = Database.instance.search(@q.keywords, @q.multi_match_keywords, @q.packages, path, @q.fpaths, @q.suffixs, @q.fpath_or_packages, @offset, LIMIT_NUM)
39
-
40
- # マッチするファイル
36
+ @searcher_fuzzy_gotoline = nil
37
+
38
+ # 検索1 : クエリーそのまま
39
+ @records, @total_records = Database.instance.search(@q.keywords, @q.multi_match_keywords, @q.packages, path, @q.fpaths, @q.suffixs, @q.fpath_or_packages, @offset, LIMIT_NUM)
40
+ grep_contents(@q.keywords)
41
+
42
+ # 検索2 : マッチしなかった時におすすめクエリーがある場合
43
+ if @match_records.empty?
44
+ if recommended_fuzzy_gotoline?
45
+ # 専用の Searcher を作成
46
+ @searcher_fuzzy_gotoline = SearchFuzzyGotoLine.new(@path, @params, @q)
47
+
48
+ # 結果をコピーする
49
+ @total_records = @searcher_fuzzy_gotoline.total_records
50
+ @match_records = @searcher_fuzzy_gotoline.match_records
51
+ @next_index = @searcher_fuzzy_gotoline.next_index
52
+ @end_index = @searcher_fuzzy_gotoline.end_index
53
+ @next_line = nil
54
+
55
+ elsif recommended_fpath_or_packages?
56
+ # おすすめクエリーに変換
57
+ q2 = @q.conv_head_keyword_to_fpath_or_packages
58
+
59
+ # 検索
60
+ @records, @total_records = Database.instance.search(q2.keywords, q2.multi_match_keywords, q2.packages, path, q2.fpaths, q2.suffixs, q2.fpath_or_packages, @offset, LIMIT_NUM)
61
+
62
+ # 再grep
63
+ grep_contents(q2.keywords)
64
+ end
65
+ end
66
+
67
+ # 検索3 : マッチするファイル
41
68
  @match_files = []
42
69
  if @offset == 0 && @line == 0
43
70
  t = 0
44
71
 
45
72
  if (@path != "")
46
- @match_files, t, @elapsed = Database.instance.search([], @q.multi_match_keywords, @q.packages, path, @q.fpaths + @q.keywords, @q.suffixs, @q.fpath_or_packages, @offset, MATH_FILE_LIMIT)
73
+ @match_files, t = Database.instance.search([], @q.multi_match_keywords, @q.packages, path, @q.fpaths + @q.keywords, @q.suffixs, @q.fpath_or_packages, @offset, MATH_FILE_LIMIT)
47
74
  else
48
- @match_files, t, @elapsed = Database.instance.search([], @q.multi_match_keywords, @q.packages, path, @q.fpaths, @q.suffixs, @q.fpath_or_packages + @q.keywords, @offset, MATH_FILE_LIMIT)
75
+ @match_files, t = Database.instance.search([], @q.multi_match_keywords, @q.packages, path, @q.fpaths, @q.suffixs, @q.fpath_or_packages + @q.keywords, @offset, MATH_FILE_LIMIT)
49
76
  end
50
77
  end
51
-
52
- grep_contents
53
78
  end
54
79
 
55
80
  def query
@@ -85,11 +110,59 @@ module Milkode
85
110
  end
86
111
 
87
112
  <<EOF
88
- #{match_files_contents}
113
+ #{recommended_contents}
89
114
  #{match_groups.map{|g|result_match_record(g)}.join}
90
115
  EOF
91
116
  end
92
117
 
118
+ def recommended_contents
119
+ contents = []
120
+
121
+ str = recommended_query_contents
122
+ contents << str unless str.empty?
123
+
124
+ str = match_files_contents
125
+ contents << str unless str.empty?
126
+
127
+ unless contents.empty?
128
+ contents.join
129
+ else
130
+ ""
131
+ end
132
+ end
133
+
134
+ def recommended_fuzzy_gotoline?
135
+ @q.keywords.size == 1 && @q.only_keywords && Util::fuzzy_gotoline_keyword?(@q.keywords[0])
136
+ end
137
+
138
+ def recommended_fpath_or_packages?
139
+ @q.keywords.size >= 2 && @q.only_keywords
140
+ end
141
+
142
+ def recommended_query_contents
143
+ if recommended_fuzzy_gotoline?
144
+ conv_query = @q.conv_fuzzy_gotoline
145
+ tmpp = @params.clone
146
+ tmpp[:query] = conv_query.query_string
147
+ url = Mkurl.new(@path, tmpp).inherit_query_shead
148
+ <<EOS
149
+ <dt class='result-file'>#{img_icon('document-new-4.png')}<a href='#{url}'>#{conv_query.query_string}</a></dt>
150
+ <hr>
151
+ EOS
152
+ elsif recommended_fpath_or_packages?
153
+ conv_query = @q.conv_head_keyword_to_fpath_or_packages
154
+ tmpp = @params.clone
155
+ tmpp[:query] = conv_query.query_string
156
+ url = Mkurl.new(@path, tmpp).inherit_query_shead
157
+ <<EOS
158
+ <dt class='result-file'>#{img_icon('document-new-4.png')}<a href='#{url}'>#{conv_query.query_string}</a></dt>
159
+ <hr>
160
+ EOS
161
+ else
162
+ ""
163
+ end
164
+ end
165
+
93
166
  def match_files_contents
94
167
  unless @match_files.empty?
95
168
  is_and_more = @match_files.size >= MATH_FILE_LIMIT
@@ -107,7 +180,7 @@ EOF
107
180
  ""
108
181
  end
109
182
  end
110
-
183
+
111
184
  def html_pagination
112
185
  return "" if @q.empty?
113
186
  return "" if next_offset >= @total_records
@@ -123,11 +196,19 @@ EOF
123
196
  @match_records.size
124
197
  end
125
198
 
199
+ def directjump?
200
+ @searcher_fuzzy_gotoline && @searcher_fuzzy_gotoline.directjump?
201
+ end
202
+
203
+ def directjump_url
204
+ @searcher_fuzzy_gotoline.directjump_url
205
+ end
206
+
126
207
  private
127
208
 
128
209
  MatchRecord = Struct.new(:record, :match_line)
129
210
 
130
- def grep_contents
211
+ def grep_contents(keywords)
131
212
  @match_records = []
132
213
  @end_index = @next_index = @records.size
133
214
  @next_line = nil
@@ -137,7 +218,7 @@ EOF
137
218
 
138
219
  if @is_onematch
139
220
  grep = Grep.new(record.content)
140
- match_line = grep.one_match_and(@q.keywords, @is_sensitive)
221
+ match_line = grep.one_match_and(keywords, @is_sensitive)
141
222
  @match_records << MatchRecord.new(record, match_line) if match_line
142
223
 
143
224
  if @match_records.size >= DISP_NUM
@@ -146,7 +227,7 @@ EOF
146
227
  break
147
228
  end
148
229
  else
149
- break if grep_match_lines_stopover(record, index)
230
+ break if grep_match_lines_stopover(record, index, keywords)
150
231
  end
151
232
  else
152
233
  @match_records << MatchRecord.new(record, Grep::MatchLineResult.new(0, nil))
@@ -160,9 +241,9 @@ EOF
160
241
  end
161
242
  end
162
243
 
163
- def grep_match_lines_stopover(record, index)
244
+ def grep_match_lines_stopover(record, index, keywords)
164
245
  grep = Grep.new(record.content)
165
- r = grep.match_lines_stopover(@q.keywords, DISP_NUM - @match_records.size, (index == 0) ? @line : 0, @is_sensitive)
246
+ r = grep.match_lines_stopover(keywords, DISP_NUM - @match_records.size, (index == 0) ? @line : 0, @is_sensitive)
166
247
 
167
248
  r[:result].each do |match_line|
168
249
  @match_records << MatchRecord.new(record, match_line) if match_line
@@ -197,7 +278,7 @@ EOF
197
278
  url = "/home/" + record_link(record)
198
279
 
199
280
  <<EOS
200
- <dt class='result-record'><a href='#{url + "#n#{coderay.highlight_lines[0]}"}'>#{Util::relative_path record.shortpath, @path}</a></dt>
281
+ <dt class='result-record'><a href='#{url + "#n#{coderay.highlight_lines[0]}"}'>#{Util::relative_path record.shortpath, @path}</a>#{result_refinement(record)}</dt>
201
282
  <dd>
202
283
  #{coderay.to_html_anchorlink(url)}
203
284
  </dd>
@@ -226,6 +307,40 @@ EOS
226
307
  Mkurl.new(record.shortpath, @params).inherit_query_shead
227
308
  end
228
309
 
310
+ def refinement_suffix(suffix)
311
+ params = @params.clone
312
+ params[:query] = [@params[:query], "s:#{suffix}"].join(" ")
313
+ "/home/" + Mkurl.new(@path, params).inherit_query_shead
314
+ end
315
+
316
+ def refinement_directory(path)
317
+ "/home/" + Mkurl.new(path, @params).inherit_query_shead
318
+ end
319
+
320
+ def result_refinement(record)
321
+ refinements = []
322
+
323
+ # 拡張子で絞り込み
324
+ refinements << "<a href='#{refinement_suffix(record.suffix)}'>.#{record.suffix}で絞り込み</a>" if record.suffix
325
+
326
+ # ディレクトリで絞り込み
327
+ path = Util::relative_path(record.shortpath, @path)
328
+ dirname = path.to_s.split('/')[-2]
329
+ refinements << "<a href='#{refinement_directory(record.shortpath + '/..')}'>#{dirname}/以下で再検索</a>" if dirname
330
+
331
+ unless refinements.empty?
332
+ space1 = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'
333
+ space2 = '&nbsp;&nbsp;,&nbsp;&nbsp;'
334
+
335
+ <<EOF
336
+ #{space1}<span id="result-refinement">[#{refinements.join(space2)}]</span>
337
+ EOF
338
+ else
339
+ ''
340
+ end
341
+
342
+ end
343
+
229
344
  end
230
345
  end
231
346
 
@@ -0,0 +1,162 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # @file
4
+ # @brief 曖昧ジャンプ
5
+ # @author ongaeshi
6
+ # @date 2012/07/08
7
+
8
+ require 'milkode/cdweb/lib/query'
9
+ require 'milkode/cdweb/lib/grep'
10
+ require 'milkode/cdweb/lib/mkurl'
11
+ require 'milkode/common/util'
12
+
13
+ module Milkode
14
+ class SearchFuzzyGotoLine
15
+ attr_reader :total_records
16
+ attr_reader :match_records
17
+ attr_reader :next_index
18
+ attr_reader :end_index
19
+
20
+ DISP_NUM = 20 # 1ページの表示数
21
+ LIMIT_NUM = 50 # 最大検索ファイル数
22
+ NTH = 3 # 表示範囲
23
+ COL_LIMIT = 200 # 1行の桁制限
24
+
25
+ def initialize(path, params, query)
26
+ @path = path
27
+ @params = params
28
+ @q = query
29
+ @page = params[:page].to_i || 0
30
+ @offset = params[:offset].to_i
31
+
32
+ # 検索クエリを解析
33
+ gotolines = Util::parse_gotoline(@q.gotolines + @q.keywords)
34
+ @gotoline = gotolines[0]
35
+
36
+ # 検索
37
+ fpaths = @q.fpaths + @gotoline[0]
38
+ @records, @total_records = Database.instance.search([], @q.multi_match_keywords, @q.packages, path, fpaths, @q.suffixs, @q.fpath_or_packages, @offset, LIMIT_NUM)
39
+
40
+ # 検索結果を表示
41
+ grep_contents
42
+ end
43
+
44
+ def query
45
+ @q.query_string
46
+ end
47
+
48
+ def next_offset
49
+ @offset + @next_index
50
+ end
51
+
52
+ def data_range
53
+ @offset..(@offset + @end_index)
54
+ end
55
+
56
+ def html_contents
57
+ match_groups = @match_records.reduce([]) do |g, m|
58
+ # 近接マッチ無効
59
+ g << [m]
60
+ end
61
+
62
+ <<EOF
63
+ #{match_groups.map{|g|result_match_record(g)}.join}
64
+ EOF
65
+ end
66
+
67
+ def html_pagination
68
+ return "" if @q.empty?
69
+ return "" if next_offset >= @total_records
70
+
71
+ return <<EOF
72
+ <div class='pagination pagination-centered'>
73
+ #{pagination_link(next_offset, @next_line, "next >>")}
74
+ </div>
75
+ EOF
76
+ end
77
+
78
+ def match_num
79
+ @match_records.size
80
+ end
81
+
82
+ def directjump?
83
+ match_num == 1
84
+ end
85
+
86
+ def directjump_url
87
+ path = File.join('/home', @match_records[0].record.shortpath)
88
+ lineno = "#n#{@gotoline[1]}"
89
+ Mkurl.new(path, @params).inherit_query_shead + lineno
90
+ end
91
+
92
+ private
93
+
94
+ MatchRecord = Struct.new(:record, :match_line)
95
+
96
+ def grep_contents
97
+ @match_records = []
98
+ @end_index = @next_index = @records.size
99
+ @next_line = nil
100
+
101
+ @records.each_with_index do |record, index|
102
+ lineidx = @gotoline[1] - 1
103
+
104
+ if (lineidx < record.content.split("\n").size)
105
+ @match_records << MatchRecord.new(record, Grep::MatchLineResult.new(lineidx, nil))
106
+
107
+ if @match_records.size >= DISP_NUM
108
+ @end_index = index
109
+ @next_index = index + 1
110
+ break
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ def result_match_record(match_group)
117
+ record = match_group[0].record
118
+
119
+ first_index = match_group[0].match_line.index - NTH
120
+ last_index = match_group[-1].match_line.index + NTH
121
+ match_lines = match_group.map{|m| m.match_line}
122
+
123
+ coderay = CodeRayWrapper.new(record.content, record.shortpath, match_lines)
124
+ coderay.col_limit(COL_LIMIT)
125
+ coderay.set_range(first_index..last_index)
126
+
127
+ url = "/home/" + record_link(record)
128
+
129
+ <<EOS
130
+ <dt class='result-record'><a href='#{url + "#n#{coderay.highlight_lines[0]}"}'>#{Util::relative_path record.shortpath, @path}</a></dt>
131
+ <dd>
132
+ #{coderay.to_html_anchorlink(url)}
133
+ </dd>
134
+ EOS
135
+ end
136
+
137
+ def pagination_link(offset, line, label)
138
+ tmpp = @params.clone
139
+ tmpp[:offset] = offset.to_s
140
+ tmpp[:line] = line.to_s
141
+ href = Mkurl.new("", tmpp).inherit_query_shead_offset
142
+ pagination_span("<a href='#{href}' rel='next'>#{label}</a>")
143
+ end
144
+
145
+ def pagination_span(content)
146
+ "<ul><li>#{content}</li></ul>\n"
147
+ end
148
+
149
+ def result_record(record)
150
+ <<EOS
151
+ <dt class='result-file'>#{file_or_dirimg(true)}<a href='#{"/home/" + record_link(record)}'>#{Util::relative_path record.shortpath, @path}</a></dt>
152
+ EOS
153
+ end
154
+
155
+ def record_link(record)
156
+ Mkurl.new(record.shortpath, @params).inherit_query_shead
157
+ end
158
+
159
+ end
160
+ end
161
+
162
+