infod 0.0.3.2 → 0.0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/infod +1 -1
- data/infod.rb +14 -9
- data/infod/404.rb +19 -6
- data/infod/500.rb +2 -2
- data/infod/GET.rb +18 -16
- data/infod/HTTP.rb +5 -7
- data/infod/POST.rb +27 -20
- data/infod/audio.rb +1 -1
- data/infod/blog.rb +23 -6
- data/infod/cal.rb +2 -2
- data/infod/code.rb +2 -2
- data/infod/constants.rb +5 -3
- data/infod/csv.rb +5 -5
- data/infod/edit.rb +24 -28
- data/infod/facets.rb +4 -4
- data/infod/feed.rb +12 -12
- data/infod/forum.rb +1 -1
- data/infod/fs.rb +57 -109
- data/infod/graph.rb +37 -17
- data/infod/grep.rb +4 -4
- data/infod/groonga.rb +14 -14
- data/infod/histogram.rb +5 -5
- data/infod/html.rb +41 -38
- data/infod/image.rb +7 -9
- data/infod/index.rb +13 -43
- data/infod/infod.rb +14 -9
- data/infod/lambda.rb +32 -20
- data/infod/ls.rb +32 -9
- data/infod/mail.rb +104 -94
- data/infod/man.rb +6 -6
- data/infod/microblog.rb +12 -12
- data/infod/mime.rb +8 -15
- data/infod/names.rb +89 -235
- data/infod/rdf.rb +9 -15
- data/infod/schema.rb +17 -17
- data/infod/text.rb +58 -15
- data/infod/threads.rb +12 -9
- data/infod/time.rb +5 -6
- metadata +41 -59
- data/infod/HEAD.rb +0 -23
- data/infod/find.rb +0 -19
- data/infod/glob.rb +0 -25
- data/infod/kv.rb +0 -56
- data/infod/page.rb +0 -19
- data/infod/postscript.rb +0 -26
- data/infod/ruby.rb +0 -57
- data/infod/sh.rb +0 -19
- data/infod/webid.rb +0 -0
- data/infod/wiki.rb +0 -18
data/infod/groonga.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#watch __FILE__
|
2
|
-
class
|
2
|
+
class R
|
3
3
|
=begin
|
4
4
|
gem install rroonga
|
5
5
|
a ruby full-text searcher & column-store
|
@@ -9,12 +9,12 @@ class E
|
|
9
9
|
fn 'view/'+Search+'Groonga',-> d,e {{_: :form, action: '/', c: [{_: :input, name: :q, style: 'font-size:2em'},{_: :input, type: :hidden, name: :graph, value: :groonga}]}}
|
10
10
|
|
11
11
|
fn 'protograph/groonga',->d,e,m{
|
12
|
-
|
12
|
+
R.groonga.do{|ga|
|
13
13
|
q = e['q'] # search expression
|
14
14
|
g = e["context"] || d.env['SERVER_NAME'] # context
|
15
15
|
|
16
16
|
begin
|
17
|
-
m['/'] = {Type =>
|
17
|
+
m['/'] = {Type => R[Search+'Groonga']} # add a groonga resource to the graph
|
18
18
|
|
19
19
|
r = (q && !q.empty?) ? ga.select{|r|(r['graph'] == g) & r["content"].match(q)} : # expression if exists
|
20
20
|
ga.select{|r| r['graph'] == g} # or just an ordered set
|
@@ -24,25 +24,25 @@ class E
|
|
24
24
|
down = r.size > start+c # prev
|
25
25
|
up = !(start<=0) # next
|
26
26
|
r = r.sort(e.has_key?('best') ? [["_score"]]:[["time","descending"]],:offset =>start,:limit =>c) # sort
|
27
|
-
r = r.map{|r|
|
27
|
+
r = r.map{|r|r['.uri'].R} # read URI
|
28
28
|
(r.map &:docs).flatten.uniq.map{|r|m[r.uri] = r.env e} # set resource thunks
|
29
29
|
|
30
|
-
m['#'] = {'uri' => '#', RDFs+'member' => r, Type=>
|
30
|
+
m['#'] = {'uri' => '#', RDFs+'member' => r, Type=>R[HTTP+'Response']} # add pagination data to request-graph
|
31
31
|
m['#'][Prev]={'uri' => '/' + {'graph' => 'groonga', 'q' => q, 'start' => start + c, 'c' => c}.qs} if down
|
32
32
|
m['#'][Next]={'uri' => '/' + {'graph' => 'groonga', 'q' => q, 'start' => start - c, 'c' => c}.qs} if up
|
33
33
|
|
34
34
|
rescue Groonga::SyntaxError => x
|
35
|
-
m['#'] = {Type =>
|
35
|
+
m['#'] = {Type => R[COGS+'Exception'], Title => "invalid expr", Content => CGI.escapeHTML(x.message)}
|
36
36
|
e['nocache']=true
|
37
37
|
end
|
38
38
|
|
39
39
|
F['docsID'][m,e]}}
|
40
40
|
|
41
|
-
def
|
41
|
+
def R.groonga
|
42
42
|
@groonga ||=
|
43
43
|
(begin require 'groonga'
|
44
|
-
|
45
|
-
Groonga["
|
44
|
+
R['/index/groonga'].groonga
|
45
|
+
Groonga["R"]
|
46
46
|
rescue LoadError => e; end)
|
47
47
|
end
|
48
48
|
|
@@ -52,7 +52,7 @@ class E
|
|
52
52
|
dirname.mk # create containing dir
|
53
53
|
Groonga::Database.create(:path => d) # create db
|
54
54
|
Groonga::Schema.define{|s| # create schema
|
55
|
-
s.create_table("
|
55
|
+
s.create_table("R",:type => :hash,:key_type => "ShortText"){|t|
|
56
56
|
t.short_text "uri"
|
57
57
|
t.short_text "graph"
|
58
58
|
t.text "content"
|
@@ -61,25 +61,25 @@ class E
|
|
61
61
|
:type => :patricia_trie,
|
62
62
|
:key_normalize => true,
|
63
63
|
:default_tokenizer => "TokenBigram"){|t|
|
64
|
-
%w{graph content}.map{|c| t.index("
|
64
|
+
%w{graph content}.map{|c| t.index("R." + c) }}}
|
65
65
|
end
|
66
66
|
|
67
67
|
# add
|
68
68
|
def roonga graph="global", m = self.graph
|
69
|
-
|
69
|
+
R.groonga.do{|g|
|
70
70
|
m.map{|u,i|
|
71
71
|
r = g[u] || g.add(u) # create or load entry
|
72
72
|
r.uri = u # update data
|
73
73
|
r.graph = graph.to_s
|
74
74
|
r.content = i.to_s
|
75
|
-
r.time = i[
|
75
|
+
r.time = i[R::Date].do{|t|t[0].to_time}
|
76
76
|
}}
|
77
77
|
self
|
78
78
|
end
|
79
79
|
|
80
80
|
# remove
|
81
81
|
def unroonga
|
82
|
-
g =
|
82
|
+
g = R.groonga
|
83
83
|
graph.keys.push(uri).map{|u|g[u].delete}
|
84
84
|
end
|
85
85
|
|
data/infod/histogram.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#watch __FILE__
|
2
|
-
class
|
2
|
+
class R
|
3
3
|
|
4
4
|
fn 'view/histogram',->m,e{
|
5
|
-
e.q['a'].do{|a|
|
6
|
-
(
|
5
|
+
e.q['a'].do{|a|F['histogram/main'][m,e]} ||
|
6
|
+
(F['view/facetSelect'][m,e])}
|
7
7
|
|
8
8
|
fn 'histogram/main',->d,e{
|
9
9
|
|
@@ -17,10 +17,10 @@ class E
|
|
17
17
|
v = F['view/'+(e.q['hv']||'title')]
|
18
18
|
|
19
19
|
# construct histogram bins
|
20
|
-
|
20
|
+
F['histogram/bins'][d,a,n].do{|h,m|
|
21
21
|
|
22
22
|
[H.css('/css/hist'),%w{mu hist}.map{|s|H.js('/js/'+s)},
|
23
|
-
|
23
|
+
F['histogram'][h],{style: "width: 100%; height: 5em"},
|
24
24
|
h.map{|b,r|
|
25
25
|
# skip empty bins
|
26
26
|
r.empty? ? ' ' :
|
data/infod/html.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
#watch __FILE__
|
2
2
|
|
3
|
-
# (H) templates
|
4
3
|
def H _
|
5
4
|
case _
|
6
5
|
when Hash
|
@@ -21,14 +20,14 @@ class H
|
|
21
20
|
|
22
21
|
def H.js a,inline=false
|
23
22
|
p = a + '.js'
|
24
|
-
inline ? {_: :script, c: p.
|
23
|
+
inline ? {_: :script, c: p.R.r} :
|
25
24
|
{_: :script, type: "text/javascript", src: p}
|
26
25
|
end
|
27
26
|
|
28
27
|
def H.css a,inline=false
|
29
28
|
p = a + '.css'
|
30
|
-
inline ? {_: :style, c: p.
|
31
|
-
{_: :link, href: p, rel: :stylesheet, type:
|
29
|
+
inline ? {_: :style, c: p.R.r} :
|
30
|
+
{_: :link, href: p, rel: :stylesheet, type: R::MIME[:css]}
|
32
31
|
end
|
33
32
|
|
34
33
|
def H.once e,n,*h
|
@@ -39,17 +38,19 @@ class H
|
|
39
38
|
end
|
40
39
|
|
41
40
|
class Array
|
42
|
-
def
|
43
|
-
|
41
|
+
def cr; intersperse "\n" end
|
42
|
+
def head; self[0] end
|
43
|
+
def html v=nil,g=nil; map{|e|e.html v,g}.join ' ' end
|
44
|
+
def h; join.h end
|
45
|
+
def intersperse i
|
46
|
+
inject([]){|a,b|a << b << i}[0..-2]
|
44
47
|
end
|
48
|
+
def tail; self[1..-1] end
|
49
|
+
def justArray; self end
|
45
50
|
end
|
46
51
|
|
47
52
|
class Object
|
48
|
-
def html *a
|
49
|
-
name = self.class
|
50
|
-
href = "https://duckduckgo.com/?q=ruby+#{name}"
|
51
|
-
"<a href=#{href}><b>#{name}</b></a>"
|
52
|
-
end
|
53
|
+
def html *a; self.class end
|
53
54
|
end
|
54
55
|
|
55
56
|
class String
|
@@ -69,10 +70,14 @@ end
|
|
69
70
|
|
70
71
|
class Fixnum
|
71
72
|
def html e=nil,g=nil; to_s end
|
73
|
+
def max i; i > self ? self : i end
|
74
|
+
def min i; i < self ? self : i end
|
72
75
|
end
|
73
76
|
|
74
77
|
class Float
|
75
78
|
def html e=nil,g=nil; to_s end
|
79
|
+
def max i; i > self ? self : i end
|
80
|
+
def min i; i < self ? self : i end
|
76
81
|
end
|
77
82
|
|
78
83
|
class TrueClass
|
@@ -98,10 +103,10 @@ class Hash
|
|
98
103
|
H({_: :table, class: :html, c: map{|k,v|
|
99
104
|
unless k == 'uri' && (v.match IsBnode)
|
100
105
|
{_: :tr, property: k, c:
|
101
|
-
[k ==
|
106
|
+
[k == R::Content ? {_: :td, class: :val, colspan: 2, c: v} :
|
102
107
|
[
|
103
|
-
({_: :td, c: [{_: :a, name: k, href: (k == 'uri' ? v : k), c: k.to_s.abbrURI}], class: :key} if key),
|
104
|
-
{_: :td, c: k == 'uri' ? v.
|
108
|
+
({_: :td, c: [{_: :a, name: k, href: (k == 'uri' ? (v.R.docBase.localURL e)+'?graph=edit' : k), c: k.to_s.abbrURI}], class: :key} if key),
|
109
|
+
{_: :td, c: k == 'uri' ? v.R.do{|u| {_: :a, id: u, href: u.url, c: v}} : v.html(e,g), class: :val},
|
105
110
|
]]}
|
106
111
|
end
|
107
112
|
}})
|
@@ -109,34 +114,31 @@ class Hash
|
|
109
114
|
end
|
110
115
|
end
|
111
116
|
|
112
|
-
class
|
117
|
+
class R
|
113
118
|
|
114
119
|
def html *a
|
115
120
|
url.href
|
116
121
|
end
|
117
122
|
|
118
|
-
|
123
|
+
F['view']=->d,e{
|
119
124
|
d.values.select{|r|
|
120
125
|
!r.has_key?('uri') || # URI field missing
|
121
126
|
!r.uri.match(IsBnode) # blank node
|
122
127
|
true
|
123
128
|
}.
|
124
129
|
sort_by{|r| r[Date].do{|d| d[0].to_s} || ''}.reverse.
|
125
|
-
map{|r|
|
130
|
+
map{|r| F['view/select'][r,e,d]}}
|
126
131
|
|
127
|
-
|
132
|
+
F['view/base']=->d,e,k=true,graph=nil{
|
128
133
|
[H.once(e,'base',H.css('/css/html')),
|
129
134
|
d.values.map{|v|v.html e,graph,k}]}
|
130
135
|
|
131
|
-
|
136
|
+
F['view/select']=->r,e,d=nil{
|
132
137
|
graph = {r.uri => r}
|
133
138
|
view = nil
|
134
139
|
if r.class == Hash
|
135
140
|
(r[Type].class==Array ? r[Type] : [r[Type]]).do{|types|
|
136
|
-
views = types.map{|t|
|
137
|
-
# discard non-URIs
|
138
|
-
t.uri if t.respond_to? :uri}.
|
139
|
-
compact.map{|t|
|
141
|
+
views = types.map(&:maybeURI).compact.map{|t|
|
140
142
|
subtype = t
|
141
143
|
type = subtype.split(/\//)[-2]
|
142
144
|
[F['view/' + subtype],
|
@@ -150,12 +152,6 @@ class E
|
|
150
152
|
view[graph,e]
|
151
153
|
end}
|
152
154
|
|
153
|
-
# enumerate available views
|
154
|
-
fn 'view/?',->d,e{
|
155
|
-
F.keys.grep(/^view\/(?!application|text\/x-)/).map{|v|
|
156
|
-
v = v[5..-1] # eat selector
|
157
|
-
[{_: :a, href: e['REQUEST_PATH']+e.q.merge({'view'=>v}).qs, c: v},"<br>\n"]}}
|
158
|
-
|
159
155
|
def triplrBlob
|
160
156
|
glob.select(&:f).do{|f|f.map{|r|
|
161
157
|
yield r.uri,Type,E('blob')
|
@@ -165,7 +161,6 @@ class E
|
|
165
161
|
yield uri,Content,(f && read).do{|r|enc ? r.force_encoding(enc).to_utf8 : r}.hrefs
|
166
162
|
end
|
167
163
|
|
168
|
-
require 'nokogiri'
|
169
164
|
def nokogiri; Nokogiri::HTML.parse read end
|
170
165
|
|
171
166
|
F['HTMLbody'] = -> b {
|
@@ -179,6 +174,14 @@ class E
|
|
179
174
|
h.to_s
|
180
175
|
}
|
181
176
|
|
177
|
+
fn 'view/'+HTTP+'Response',->d,e{
|
178
|
+
d['#'].do{|u|
|
179
|
+
[u[Prev].do{|p|{_: :a, rel: :prev, href: p.uri, c: '←',style: 'color:#fff;background-color:#000;font-size:2.4em;float:left;clear:both'}},
|
180
|
+
u[Next].do{|n|{_: :a, rel: :next, href: n.uri, c: '→',style: 'color:#000;background-color:#fff;font-size:2.4em;float:right;clear:both;'}},
|
181
|
+
{_: :a, rel: :nofollow, href: e['REQUEST_PATH'].sub(/\.html$/,'') + e.q.merge({'view'=>'data'}).qs, # data browser
|
182
|
+
c: {_: :img, src: '/css/misc/cube.png', style: 'height:2em;background-color:white;padding:.54em;border-radius:1em;margin:.2em'}},
|
183
|
+
(H.js '/js/pager'),(H.once e,:mu,(H.js '/js/mu'))]}} # (n)ext (p)rev key binding
|
184
|
+
|
182
185
|
def contentURIresolve *f
|
183
186
|
send(*f){|s,p,o|
|
184
187
|
yield s, p, p == Content ?
|
@@ -210,11 +213,11 @@ class E
|
|
210
213
|
{_: :a, href: '#', c: '-', id: :hideP},
|
211
214
|
{_: :a, href: '#', c: '+', id: :showP},
|
212
215
|
{_: :span, id: 'properties',
|
213
|
-
c:
|
216
|
+
c: R.graphProperties(d).map{|k|
|
214
217
|
{_: :a, class: :n, href: k, c: k.label+' '}}},
|
215
218
|
{_: :style, id: :pS},
|
216
219
|
{_: :style, id: :lS}),
|
217
|
-
|
220
|
+
F['view/'+(e.q['pv']||'table')][d,e]]}
|
218
221
|
|
219
222
|
# table-cell placement on sparse matrix of rows/columns
|
220
223
|
# cal.rb contains an example usage
|
@@ -223,7 +226,7 @@ class E
|
|
223
226
|
if layout
|
224
227
|
[H.once(e,'table',H.css('/css/table')),
|
225
228
|
{_: :table, c:
|
226
|
-
{_: :tbody, c:
|
229
|
+
{_: :tbody, c: F['table/'+layout][d].do{|t|
|
227
230
|
rx = t.keys.max
|
228
231
|
rm = t.keys.min
|
229
232
|
c = t.values.map(&:keys)
|
@@ -234,15 +237,15 @@ class E
|
|
234
237
|
t[r].do{|r|
|
235
238
|
(cm..cx).map{|c|
|
236
239
|
r[c].do{|c|
|
237
|
-
{_: :td, class: :cell, c:
|
238
|
-
|
239
|
-
|
240
|
+
{_: :td, class: :cell, c:F['view/'+(a||e.q['cellview']||'title')][c,e]}} ||
|
241
|
+
{_: :td}}}}} ||
|
242
|
+
'' }}}]
|
240
243
|
else
|
241
244
|
"table= layout arg required"
|
242
245
|
end}
|
243
246
|
|
244
247
|
fn 'view/table',->g,e{
|
245
|
-
keys =
|
248
|
+
keys = R.graphProperties g
|
246
249
|
v = g.values
|
247
250
|
e.q['sort'].do{|p|
|
248
251
|
p = p.expand
|
@@ -253,6 +256,6 @@ class E
|
|
253
256
|
[H.css('/css/table'),
|
254
257
|
{_: :table,:class => :tab,
|
255
258
|
c: [{_: :tr, c: keys.map{|k|{_: :th, class: :label, property: k, c: k.abbrURI}}},
|
256
|
-
v.map{|e|{_: :tr, about: e.uri, c: keys.map{|k| {_: :td, property: k, c: k=='uri' ? e.
|
259
|
+
v.map{|e|{_: :tr, about: e.uri, c: keys.map{|k| {_: :td, property: k, c: k=='uri' ? e.R.html : e[k].html}}}}]}]}
|
257
260
|
|
258
261
|
end
|
data/infod/image.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#watch __FILE__
|
2
|
-
class
|
2
|
+
class R
|
3
3
|
|
4
4
|
def triplrImage &f
|
5
|
-
yield uri,Type,
|
5
|
+
yield uri,Type,R[DC+'Image']
|
6
6
|
triplrStdOut 'exiftool', EXIF, &f
|
7
7
|
end
|
8
8
|
|
@@ -12,7 +12,7 @@ class E
|
|
12
12
|
size = r.q['px'].to_i.min(8).max(4096)
|
13
13
|
stat = i.node.stat
|
14
14
|
id = [stat.ino,stat.mtime,size].h.dive
|
15
|
-
path =
|
15
|
+
path = R['/cache/thumbnail/'+id+'.png']
|
16
16
|
if !path.e
|
17
17
|
path.dirname.mk
|
18
18
|
if i.mimeP.match(/^video/)
|
@@ -28,7 +28,7 @@ class E
|
|
28
28
|
|
29
29
|
fn 'view/img',->i,_{
|
30
30
|
[i.values.select{|v|v.class==Hash}.map{|i|
|
31
|
-
i[Type] && (i[Type].class==Array ? i[Type] : [i[Type]]).map
|
31
|
+
i[Type] && (i[Type].class==Array ? i[Type] : [i[Type]]).map(&:maybeURI).include?(DC+'Image') &&
|
32
32
|
[{_: :a, href: i.url, c: {_: :img, style:'float:left;max-width:61.8%', src: i.url}},
|
33
33
|
i.html]},
|
34
34
|
(H.css '/css/img')]}
|
@@ -70,9 +70,7 @@ class E
|
|
70
70
|
|
71
71
|
# check object URIs for image extension
|
72
72
|
(v.respond_to?(:values) &&
|
73
|
-
v.values.flatten.map
|
74
|
-
v.respond_to?(:uri) && v.uri
|
75
|
-
}.select(&x))
|
73
|
+
v.values.flatten.map(&:maybeURI).select(&x))
|
76
74
|
|
77
75
|
].flatten.uniq.compact.map{|s|
|
78
76
|
# view
|
@@ -85,8 +83,8 @@ class E
|
|
85
83
|
(seen[i[:uri]] = true
|
86
84
|
i[:c].())}]}
|
87
85
|
|
88
|
-
def
|
89
|
-
def
|
86
|
+
def R.c; '#%06x' % rand(16777216) end
|
87
|
+
def R.cs; '#%02x%02x%02x' % F['color/hsv2rgb'][rand*6,1,1] end
|
90
88
|
|
91
89
|
fn 'color/hsv2rgb',->h,s,v{
|
92
90
|
i = h.floor
|
data/infod/index.rb
CHANGED
@@ -1,24 +1,12 @@
|
|
1
1
|
#watch __FILE__
|
2
|
-
class
|
2
|
+
class R
|
3
3
|
|
4
4
|
# POSIX-fs based index of triples
|
5
5
|
#
|
6
6
|
|
7
|
-
# index a triple
|
8
7
|
def index p,o
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
# index a triple - no type-normalization
|
14
|
-
# we jsut rotate them, use existing k/v store and set @noIndex to stop looping infinitely to index the index..
|
15
|
-
def indexEdit p,o,a
|
16
|
-
return if @noIndex
|
17
|
-
p.pIndex.noIndex[o,self,a]
|
18
|
-
end
|
19
|
-
def noIndex
|
20
|
-
@noIndex = 1
|
21
|
-
self
|
8
|
+
return unless o.class == R
|
9
|
+
p.R.indexPath.setFs o,self,false,false
|
22
10
|
end
|
23
11
|
|
24
12
|
# reachable graph along named predicate
|
@@ -28,10 +16,10 @@ class E
|
|
28
16
|
v[uri] = true # visited mark
|
29
17
|
|
30
18
|
rel = g[uri].do{|s|s[p]} ||[]
|
31
|
-
rev = (p.
|
19
|
+
rev = (p.R.po self) ||[]
|
32
20
|
|
33
21
|
rel.concat(rev).map{|r|
|
34
|
-
v[r.uri] || (r.
|
22
|
+
v[r.uri] || (r.R.walk p,g,v)}
|
35
23
|
|
36
24
|
g
|
37
25
|
end
|
@@ -40,51 +28,34 @@ class E
|
|
40
28
|
global = !r.has_key?('local')
|
41
29
|
p = global ? d.pathSegment : d
|
42
30
|
loc = global ? '' : '&local'
|
43
|
-
c = ((r['c'].do{|c|c.to_i} || 12) + 1).max(
|
31
|
+
c = ((r['c'].do{|c|c.to_i} || 12) + 1).max(1024) # an extra for next-page pointer
|
44
32
|
o = r['d'] =~ /^a/ ? :asc : :desc # direction
|
45
|
-
(p.take c, o, r['offset'].do{|o|o.
|
33
|
+
(p.take c, o, r['offset'].do{|o|o.R}).do{|s| # take subtree
|
46
34
|
first, last = s[0], s.size > 1 && s.pop
|
47
35
|
desc, asc = o == :asc ? [first,last] : [last,first]
|
48
36
|
u = m['#']
|
49
|
-
u[Type] =
|
37
|
+
u[Type] = R[HTTP+'Response']
|
50
38
|
u[Prev] = {'uri' => d.uri + "?set=depth&c=#{c-1}&d=desc#{loc}&offset=" + (URI.escape desc.uri)} if desc
|
51
39
|
u[Next] = {'uri' => d.uri + "?set=depth&c=#{c-1}&d=asc#{loc}&offset=" + (URI.escape asc.uri)} if asc
|
52
40
|
s }}
|
53
41
|
|
54
|
-
def pIndex
|
55
|
-
shorten.prependURI '/index/'
|
56
|
-
end
|
57
|
-
|
58
|
-
def poIndex o
|
59
|
-
pIndex.concatURI o
|
60
|
-
end
|
61
|
-
|
62
|
-
# predicate+object pair lookup
|
63
42
|
def po o
|
64
|
-
|
43
|
+
indexPath.predicate o, false
|
65
44
|
end
|
66
45
|
|
67
|
-
def
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
def rangePO n=8,d=:desc,s=nil,o
|
72
|
-
poIndex(o).subtree(n,d,s).map &:ro
|
73
|
-
end
|
74
|
-
|
75
|
-
def subtree *a
|
76
|
-
u.take *a
|
46
|
+
def indexPath
|
47
|
+
shorten.prependURI '/index/'
|
77
48
|
end
|
78
49
|
|
79
50
|
def take *a
|
80
|
-
|
51
|
+
node.take(*a).map &:R
|
81
52
|
end
|
82
53
|
|
83
54
|
def randomLeaf
|
84
55
|
c.empty? && self || c.r.randomLeaf
|
85
56
|
end
|
86
57
|
|
87
|
-
def
|
58
|
+
def R.graphProperties g
|
88
59
|
g.values.select{|v|v.respond_to? :keys}.map(&:keys).flatten.uniq
|
89
60
|
end
|
90
61
|
|
@@ -108,7 +79,6 @@ class Pathname
|
|
108
79
|
nodes.sort_by(&:to_s).send(v).each{|n|
|
109
80
|
ns = n.to_s
|
110
81
|
return if 0 >= count
|
111
|
-
|
112
82
|
(ok || # already in-range
|
113
83
|
!offset || # no offset required
|
114
84
|
(sz = [ns,offset].map(&:size).min
|