infod 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/infod.rb +2 -3
- data/infod/Es.rb +31 -67
- data/infod/{W/source.rb → Es/code.rb} +6 -10
- data/infod/Es/css.rb +21 -0
- data/infod/{W → Es}/csv.rb +0 -0
- data/infod/Es/du.rb +16 -0
- data/infod/{W → Es}/feed.rb +13 -11
- data/infod/Es/filter.rb +75 -0
- data/infod/Es/find.rb +20 -0
- data/infod/Es/fs.rb +145 -136
- data/infod/Es/glob.rb +22 -0
- data/infod/Es/grep.rb +61 -0
- data/infod/Es/groonga.rb +47 -56
- data/infod/Es/html.rb +271 -0
- data/infod/Es/image.rb +114 -0
- data/infod/Es/in.rb +68 -0
- data/infod/Es/index.rb +183 -0
- data/infod/{W → Es}/json.rb +28 -4
- data/infod/Es/kv.rb +60 -0
- data/infod/Es/ls.rb +58 -0
- data/infod/Es/mail.rb +87 -0
- data/infod/Es/man.rb +112 -0
- data/infod/Es/mime.rb +59 -0
- data/infod/Es/out.rb +52 -0
- data/infod/{W/page.rb → Es/pager.rb} +7 -3
- data/infod/Es/pdf.rb +19 -0
- data/infod/Es/rdf.rb +35 -0
- data/infod/Es/schema.rb +99 -0
- data/infod/Es/search.rb +24 -0
- data/infod/Es/sh.rb +21 -0
- data/infod/{W → Es}/text.rb +26 -14
- data/infod/H.rb +15 -29
- data/infod/H/audio.rb +19 -0
- data/infod/H/blog.rb +15 -0
- data/infod/{W → H}/cal.rb +2 -31
- data/infod/H/edit.rb +88 -0
- data/infod/{W/examine/examine.rb → H/facets.rb} +17 -17
- data/infod/{W → H}/forum.rb +1 -0
- data/infod/{W/examine/sw.rb → H/hf.rb} +12 -12
- data/infod/H/histogram.rb +78 -0
- data/infod/H/mail.rb +92 -0
- data/infod/{W/chat.rb → H/microblog.rb} +21 -16
- data/infod/H/threads.rb +77 -0
- data/infod/H/time.rb +131 -0
- data/infod/H/who.rb +30 -0
- data/infod/{W → H}/wiki.rb +0 -0
- data/infod/K.rb +28 -60
- data/infod/N.rb +151 -74
- data/infod/Rb.rb +3 -3
- data/infod/Th.rb +27 -101
- data/infod/Th/404.rb +29 -36
- data/infod/Th/500.rb +36 -5
- data/infod/Th/GET.rb +48 -118
- data/infod/Th/POST.rb +31 -11
- data/infod/Th/perf.rb +37 -0
- data/infod/Th/util.rb +89 -0
- data/infod/Y.rb +24 -7
- data/infod/infod.rb +2 -3
- metadata +92 -64
- data/infod/Es/redis.rb +0 -3
- data/infod/Es/sqlite.rb +0 -3
- data/infod/Th/local.rb +0 -22
- data/infod/W.rb +0 -34
- data/infod/W/audio.rb +0 -56
- data/infod/W/blog.rb +0 -3
- data/infod/W/color.rb +0 -28
- data/infod/W/core.rb +0 -77
- data/infod/W/css.rb +0 -24
- data/infod/W/du.rb +0 -35
- data/infod/W/edit.rb +0 -8
- data/infod/W/examine/exhibit.rb +0 -34
- data/infod/W/examine/hist.rb +0 -55
- data/infod/W/examine/history.rb +0 -19
- data/infod/W/examine/normal.rb +0 -31
- data/infod/W/examine/protovis.rb +0 -30
- data/infod/W/examine/time/graph.rb +0 -86
- data/infod/W/examine/time/line.rb +0 -24
- data/infod/W/find.rb +0 -24
- data/infod/W/grep.rb +0 -27
- data/infod/W/html.rb +0 -143
- data/infod/W/image.rb +0 -61
- data/infod/W/kv.rb +0 -66
- data/infod/W/ls.rb +0 -50
- data/infod/W/mail.rb +0 -248
- data/infod/W/pdf.rb +0 -16
- data/infod/W/post.rb +0 -9
- data/infod/W/rdf.rb +0 -32
- data/infod/W/schema.rb +0 -172
- data/infod/W/search.rb +0 -33
- data/infod/W/shell.rb +0 -30
- data/infod/W/table.rb +0 -87
- data/infod/W/tree.rb +0 -26
- data/infod/W/vfs.rb +0 -175
data/infod.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
|
2
2
|
# the table of elements
|
3
3
|
|
4
|
-
# Es
|
4
|
+
# Es infrastructure
|
5
5
|
# H HTML
|
6
6
|
# K constants
|
7
7
|
# N naming
|
8
8
|
# Rb Ruby native-types
|
9
9
|
# Th HTTP
|
10
|
-
# W forms and formats
|
11
10
|
# Y lambdas
|
12
11
|
|
13
|
-
%w{Y K Rb N
|
12
|
+
%w{Y K Rb N Es H Th}.map{|e| require 'infod/' + e}
|
data/infod/Es.rb
CHANGED
@@ -1,67 +1,31 @@
|
|
1
|
-
%w{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
fn 'filter/frag',->e,m,r{
|
34
|
-
f = [r.uri].concat m['frag']['res']
|
35
|
-
m.keys.map{|u|
|
36
|
-
m.delete u unless f.member? u}}
|
37
|
-
|
38
|
-
fn 'filter/basic',->o,m,_{
|
39
|
-
d=m.values
|
40
|
-
o['match'] && (p=o['matchP'].expand
|
41
|
-
d=d.select{|r|r[p].do{|p|(p.class==Array ? p[0] : p).to_s.match o['match']}})
|
42
|
-
o['min'] && (min=o['min'].to_f
|
43
|
-
p=o['minP'].expand
|
44
|
-
d=d.select{|r|r[p].do{|p|(p.class==Array ? p[0] : p).to_f >= min }})
|
45
|
-
o['max'] && (max=o['max'].to_f
|
46
|
-
p=o['maxP'].expand
|
47
|
-
d=d.select{|r|r[p].do{|p|(p.class==Array ? p[0] : p).to_f <= max }})
|
48
|
-
o['sort'] && (p=o['sort'].expand
|
49
|
-
_ = d.partition{|r|r[p]}
|
50
|
-
d =_[0].sort_by{|r|r[p]}.concat _[1] rescue d)
|
51
|
-
o['sortN'] && (p=o['sortN'].expand
|
52
|
-
_ = d.partition{|r|r[p]}
|
53
|
-
d =_[0].sort_by{|r|
|
54
|
-
(r[p].class==Array && r[p] || [r[p]])[0].do{|d|
|
55
|
-
d.class==String && d.to_i || d
|
56
|
-
}
|
57
|
-
}.concat _[1])
|
58
|
-
o.has_key?('reverse') && d.reverse!
|
59
|
-
m.clear;d.map{|r|m[r['uri']]=r}}
|
60
|
-
|
61
|
-
def self.filter o,m,r
|
62
|
-
o['filter'].do{|f|f.split(/,/).map{|f|Fn 'filter/'+f,o,m,r}}
|
63
|
-
Fn'filter/basic',o,m,r if o.has_any_key ['reverse','sort','max','min','match']
|
64
|
-
m
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
1
|
+
%w{
|
2
|
+
code
|
3
|
+
css
|
4
|
+
csv
|
5
|
+
du
|
6
|
+
feed
|
7
|
+
filter
|
8
|
+
find
|
9
|
+
fs
|
10
|
+
glob
|
11
|
+
grep
|
12
|
+
groonga
|
13
|
+
html
|
14
|
+
image
|
15
|
+
in
|
16
|
+
index
|
17
|
+
json
|
18
|
+
kv
|
19
|
+
ls
|
20
|
+
mail
|
21
|
+
man
|
22
|
+
mime
|
23
|
+
out
|
24
|
+
pager
|
25
|
+
pdf
|
26
|
+
rdf
|
27
|
+
schema
|
28
|
+
search
|
29
|
+
sh
|
30
|
+
text
|
31
|
+
}.map{|e|require_relative 'Es/'+e}
|
@@ -1,25 +1,21 @@
|
|
1
1
|
class E
|
2
2
|
|
3
|
-
# show available querystring aliases
|
4
|
-
fn '/qs/GET',->e,r{H([H.css('/css/404'),F['?'].html]).hR}
|
5
|
-
|
6
3
|
def triplrSourceCode
|
7
|
-
# MIME strip x-
|
8
4
|
m = mime.split(/\//)[-1].sub(/^x-/,'')
|
9
|
-
|
10
5
|
# show line numbers?
|
11
6
|
n = @r.has_key?('n') && "--line-number-ref=#{uri.sh}"
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
if size < 512e3
|
8
|
+
yield uri,Content,
|
9
|
+
`source-highlight -f html -o STDOUT -i #{sh} -s #{m} #{n}`
|
10
|
+
end
|
11
|
+
end
|
16
12
|
|
17
13
|
fn 'view/code',->d,e{[{_: :style, c: 'body{background-color:white;color:black}'},
|
18
14
|
d.values.map{|r|[r.E.do{|e|[{_: :a,name: e.uri},e.html(e.base,true)]},'<br>',
|
19
15
|
r[Content]]}]}
|
20
16
|
|
21
17
|
# ls /usr/share/source-highlight/*.lang | xargs -i basename {} .lang | tr "\n" " "
|
22
|
-
%w{ada applescript asm awk bat bib bison caml changelog c clipper cobol conf cpp csharp css desktop diff d erlang errors flex fortran function glsl haskell haskell_literate haxe html html_simple java javascript key_string langdef latex ldap lisp log logtalk lsm lua m4 makefile manifest nohilite number outlang oz pascal pc perl php postscript prolog properties proto python ruby scala script_comment sh slang sml spec sql style symbols tcl texinfo todo url vala vbscript xml}
|
18
|
+
%w{ada applescript asm awk bat bib bison caml changelog c clipper cobol conf cpp csharp css desktop diff d erlang errors flex fortran function glsl haskell haskell_literate haxe html html_simple java javascript key_string langdef latex ldap lisp log logtalk lsm lua m4 makefile manifest nohilite number outlang oz pascal pc perl php postscript prolog properties proto python ruby scala script_comment sh shellscript slang sml spec sql style symbols tcl texinfo todo url vala vbscript xml}
|
23
19
|
.map{|l|
|
24
20
|
ma = 'application/' + l
|
25
21
|
mt = 'text/x-' + l
|
data/infod/Es/css.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
class E
|
3
|
+
|
4
|
+
def nokogiri; Nokogiri::HTML.parse read end
|
5
|
+
|
6
|
+
MIMEsource['text/css'] ||= [:triplrSourceCode]
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
class H
|
11
|
+
|
12
|
+
def H.css a,inline=false
|
13
|
+
p = a + '.css'
|
14
|
+
if inline
|
15
|
+
{_: :style, c: p.E.r}
|
16
|
+
else
|
17
|
+
{_: :link, href: p, rel: :stylesheet, type: E::MIME[:css]}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/infod/{W → Es}/csv.rb
RENAMED
File without changes
|
data/infod/Es/du.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
class E
|
2
|
+
|
3
|
+
fn 'protograph/du',->d,_,m{
|
4
|
+
e = [d,d.pathSegment].compact.find &:e
|
5
|
+
m[e.uri] = e if e
|
6
|
+
rand.to_s.h }
|
7
|
+
|
8
|
+
fn 'graph/du',->e,_,m{
|
9
|
+
`du -a #{m.values[0].sh}`.each_line{|l|
|
10
|
+
s,p = l.chomp.split /\t/ # size, path
|
11
|
+
p = p.unpathFs # path -> URI
|
12
|
+
m[p.uri] = {'uri' => p.uri,
|
13
|
+
Stat+'size' => [s.to_i]}}
|
14
|
+
m }
|
15
|
+
|
16
|
+
end
|
data/infod/{W → Es}/feed.rb
RENAMED
@@ -20,16 +20,18 @@ module FeedParse
|
|
20
20
|
#items
|
21
21
|
scan(%r{<(rss:|atom:)?(item|entry)([\s][^>]*)?>(.*?)</\1?\2>}mi){|m|
|
22
22
|
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
# TODO (gu)id field is often unresolvable. maybe use link[rel=alternate] as identifier instead since it's resolvable & HTTP
|
24
|
+
|
25
|
+
# find identifier
|
26
|
+
u = m[2] && (u = m[2].match /about=["']?([^'">\s]+)/) && u[1] ||
|
27
|
+
m[3] && (((u = m[3].match /<(gu)?id[^>]*>([^<]+)/) || (u = m[3].match /<(link)>([^<]+)/)) && u[2])
|
28
|
+
|
29
|
+
yield u, E::Type, (E::SIOC+'Post').E
|
27
30
|
|
28
31
|
#links
|
29
32
|
m[3].scan(%r{<(link|enclosure|media)([^>]+)>}mi){|e|
|
30
|
-
|
31
|
-
|
32
|
-
e[1].match(/(href|url|src)=['"]?([^'">\s]+)/)[2].E)} # o
|
33
|
+
e[1].match(/(href|url|src)=['"]?([^'">\s]+)/).do{|url|
|
34
|
+
yield(u,E::Atom+'/link/'+((r=e[1].match(/rel=['"]?([^'">\s]+)/)) ? r[1] : e[0]), url[2].E)}}
|
33
35
|
|
34
36
|
#elements
|
35
37
|
m[3].scan(%r{<([a-z]+:)?([a-z]+)([\s][^>]*)?>(.*?)</\1?\2>}mi){|e|
|
@@ -61,7 +63,6 @@ class E
|
|
61
63
|
end
|
62
64
|
|
63
65
|
def triplrFeedReddit &f
|
64
|
-
require 'nokogiri'
|
65
66
|
triplrFeed {|s,p,o|
|
66
67
|
p == Content ?
|
67
68
|
Nokogiri::HTML.parse(o).do{|o|
|
@@ -109,8 +110,9 @@ class E
|
|
109
110
|
d[Title].do{|t|{_: :title, c: t}},
|
110
111
|
d[Creator].do{|c|{_: :author, c: c[0]}},
|
111
112
|
{_: :content, type: :xhtml,
|
112
|
-
c: {xmlns:"http://www.w3.org/1999/xhtml",
|
113
|
-
|
114
|
-
|
113
|
+
c: {xmlns:"http://www.w3.org/1999/xhtml",
|
114
|
+
c: d[Content]}}].cr
|
115
|
+
}}.cr
|
116
|
+
]}])}
|
115
117
|
|
116
118
|
end
|
data/infod/Es/filter.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
class E
|
2
|
+
|
3
|
+
# narrow to specified properties
|
4
|
+
fn 'filter/p',->e,m,_{
|
5
|
+
a=Hash[*e['p'].split(/,/).map(&:expand).map{|p|[p,true]}.flatten]
|
6
|
+
m.values.map{|r|
|
7
|
+
r.delete_if{|p,o|!a[p]}}}
|
8
|
+
|
9
|
+
fn 'filter/frag',->e,m,r{
|
10
|
+
f = [r.uri].concat m['frag']['res']
|
11
|
+
m.keys.map{|u|
|
12
|
+
m.delete u unless f.member? u}}
|
13
|
+
|
14
|
+
fn 'filter/basic',->o,m,_{
|
15
|
+
d=m.values
|
16
|
+
o['match'] && (p=o['matchP'].expand
|
17
|
+
d=d.select{|r|r[p].do{|p|(p.class==Array ? p[0] : p).to_s.match o['match']}})
|
18
|
+
o['min'] && (min=o['min'].to_f
|
19
|
+
p=o['minP'].expand
|
20
|
+
d=d.select{|r|r[p].do{|p|(p.class==Array ? p[0] : p).to_f >= min }})
|
21
|
+
o['max'] && (max=o['max'].to_f
|
22
|
+
p=o['maxP'].expand
|
23
|
+
d=d.select{|r|r[p].do{|p|(p.class==Array ? p[0] : p).to_f <= max }})
|
24
|
+
o['sort'] && (p=o['sort'].expand
|
25
|
+
_ = d.partition{|r|r[p]}
|
26
|
+
d =_[0].sort_by{|r|r[p]}.concat _[1] rescue d)
|
27
|
+
o['sortN'] && (p=o['sortN'].expand
|
28
|
+
_ = d.partition{|r|r[p]}
|
29
|
+
d =_[0].sort_by{|r|
|
30
|
+
(r[p].class==Array && r[p] || [r[p]])[0].do{|d|
|
31
|
+
d.class==String && d.to_i || d
|
32
|
+
}
|
33
|
+
}.concat _[1])
|
34
|
+
o.has_key?('reverse') && d.reverse!
|
35
|
+
m.clear;d.map{|r|m[r['uri']]=r}}
|
36
|
+
|
37
|
+
fn 'filter/map',->o,m,_{
|
38
|
+
o.except('filter','graph','view').map{|p,n|
|
39
|
+
p=p.expand
|
40
|
+
n=n.expand
|
41
|
+
p!=n &&
|
42
|
+
m.values.map{|r|
|
43
|
+
r[p].do{|o|
|
44
|
+
r[n]=o
|
45
|
+
r.delete p }}}}
|
46
|
+
|
47
|
+
fn 'view/map',->d,e{
|
48
|
+
[H.js('/js/normal'),(H.once e,:mu,(H.js '/js/mu')),
|
49
|
+
'<style>.b {display:inline-block;font-weight:bold;padding-right:.8em;text-align:right;min-width:12em}
|
50
|
+
.exerpt {display:inline-block;max-height:1em;overflow:hidden;max-width:44em;font-size: .9em} </style>',
|
51
|
+
{_: :form, c:
|
52
|
+
[d.values.map(&:keys).flatten.uniq.-(['uri']).do{|ps|
|
53
|
+
ps.map{|p|
|
54
|
+
[{class: :b, c: p},{_: :select, name: p, c:
|
55
|
+
(ps + [Date,Creator,Content,Title]).map{|q|
|
56
|
+
{_: :option, c: q}.
|
57
|
+
update(p==q ? {selected: :selected}:{})}},
|
58
|
+
{class: :exerpt, c: d.values.map{|r|r[p]}.flatten.uniq.html},
|
59
|
+
'<br>']}},
|
60
|
+
{_: :input, type: :hidden, name: :view, value: :tab},
|
61
|
+
{_: :input, type: :hidden, name: :filter, value: :map},
|
62
|
+
{_: :input, type: :submit}
|
63
|
+
]}]}
|
64
|
+
|
65
|
+
def self.filter o,m,r
|
66
|
+
o['filter'].do{|f|f.split(/,/).map{|f|Fn 'filter/'+f,o,m,r}}
|
67
|
+
Fn'filter/basic',o,m,r if o.has_any_key ['reverse','sort','max','min','match']
|
68
|
+
m
|
69
|
+
end
|
70
|
+
|
71
|
+
def E.graphProperties g
|
72
|
+
g.values.select{|v|v.respond_to? :keys}.map(&:keys).flatten.uniq
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/infod/Es/find.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#watch __FILE__
|
2
|
+
class E
|
3
|
+
|
4
|
+
fn 'set/find',->e,q,m,x=''{
|
5
|
+
q['q'].do{|q|
|
6
|
+
r = '-iregex ' + ('.*' + q + '.*' + x).sh
|
7
|
+
s = q['size'].do{|s| s.match(/^\d+$/) && '-size +' + s + 'M'}
|
8
|
+
t = q['day'].do{|d| d.match(/^\d+$/) && '-ctime -' + d }
|
9
|
+
[e,e.pathSegment].compact.select(&:e).map{|e|
|
10
|
+
`find #{e.sh} #{t} #{s} #{r} | head -n 1000`.
|
11
|
+
lines.map{|l|l.chomp.unpathFs}}.compact.flatten}}
|
12
|
+
|
13
|
+
fn 'view/find',->i,e{
|
14
|
+
{_: :form, method: :GET, action: e['REQUEST_PATH'].t,
|
15
|
+
c: [{_: :input, name: :set, value: :find, type: :hidden},
|
16
|
+
{_: :input, name: :triplr, value: :id, type: :hidden},
|
17
|
+
{_: :input, name: :view, value: :ls, type: :hidden},
|
18
|
+
{_: :input, name: :q, style: 'float: left;font-size:1.3em'}]}}
|
19
|
+
|
20
|
+
end
|
data/infod/Es/fs.rb
CHANGED
@@ -1,154 +1,163 @@
|
|
1
|
+
#watch __FILE__
|
2
|
+
|
3
|
+
%w{date digest/sha1 fileutils json open-uri pathname}.each{|r|require(r)}
|
4
|
+
|
1
5
|
class E
|
2
6
|
|
3
|
-
|
4
|
-
|
7
|
+
def d
|
8
|
+
node.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def node
|
12
|
+
Pathname.new FSbase + path
|
13
|
+
end
|
14
|
+
alias_method :no, :node
|
15
|
+
|
16
|
+
def siblings
|
17
|
+
parent.c
|
18
|
+
end
|
19
|
+
|
20
|
+
def children
|
21
|
+
node.c.map &:E
|
22
|
+
end
|
23
|
+
alias_method :c, :children
|
24
|
+
|
25
|
+
|
26
|
+
# node exists?
|
27
|
+
def exist?
|
28
|
+
node.exist?
|
29
|
+
end
|
30
|
+
alias_method :e, :exist?
|
31
|
+
|
32
|
+
# directory?
|
33
|
+
def d?
|
34
|
+
node.directory?
|
35
|
+
end
|
36
|
+
|
37
|
+
# file?
|
38
|
+
def file?
|
39
|
+
node.file?
|
40
|
+
end
|
41
|
+
alias_method :f, :file?
|
5
42
|
|
6
|
-
#
|
7
|
-
def
|
8
|
-
|
9
|
-
indexEdit E(p),
|
10
|
-
# literal -> URI conversion
|
11
|
-
(o.class == E ? o : E(p).literal(o)),
|
12
|
-
nil
|
43
|
+
# modification time
|
44
|
+
def mtime
|
45
|
+
node.stat.mtime if e
|
13
46
|
end
|
47
|
+
alias_method :m, :mtime
|
14
48
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
49
|
+
def triplrInode children=true
|
50
|
+
e && (d? && (yield uri, Posix + 'dir#parent', parent
|
51
|
+
children && c.map{|c| yield uri, Posix + 'dir#child', c})
|
52
|
+
node.stat.do{|s|[:size,:ftype,:mtime].map{|p| yield uri, Stat+p.to_s, (s.send p)}})
|
53
|
+
end
|
54
|
+
|
55
|
+
def triplrSymlink
|
56
|
+
realpath.do{|t|
|
57
|
+
target = t.to_s.index(FSbase)==0 ? t.E : t.to_s
|
58
|
+
yield uri, '/linkTarget', target }
|
59
|
+
end
|
60
|
+
|
61
|
+
def realpath
|
62
|
+
node.realpath
|
63
|
+
rescue Errno::ENOENT
|
64
|
+
nil
|
19
65
|
end
|
20
|
-
|
21
|
-
|
66
|
+
|
67
|
+
def mk
|
68
|
+
e || FileUtils.mkdir_p(d)
|
22
69
|
self
|
23
70
|
end
|
24
71
|
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
m['prev'] = {'uri' => 'prev', 'url' => desc.url,'d' => 'desc'}
|
33
|
-
m['next'] = {'uri' => 'next', 'url' => asc.url, 'd' => 'asc'}
|
34
|
-
s }}
|
35
|
-
|
36
|
-
# subtree traverse index on p+o cursor
|
37
|
-
fn 'set/index',->d,r,m,f=:rangePO{
|
38
|
-
(# predicate
|
39
|
-
(f == :rangeP ? d : r['p']).expand.E.
|
40
|
-
# query
|
41
|
-
send f,
|
42
|
-
# count
|
43
|
-
(r['c']&&
|
44
|
-
r['c'].to_i.max(808)+1 || 22),
|
45
|
-
# direction
|
46
|
-
(r['d']&&
|
47
|
-
r['d'].match(/^(a|de)sc$/) &&
|
48
|
-
r['d'].to_sym ||
|
49
|
-
:desc),
|
50
|
-
# offset
|
51
|
-
r['offset'],
|
52
|
-
# object
|
53
|
-
(d if f == :rangePO)
|
54
|
-
).do{|s|
|
55
|
-
# pagination pointers
|
56
|
-
a,b = s[0], s.size > 1 && s.pop
|
57
|
-
desc,asc = r['d'] && r['d']=='asc' && [a,b]||[b,a]
|
58
|
-
# insert pointers in response-graph
|
59
|
-
m['prev']={'uri' => 'prev','url' => d.url,'d' => 'desc','offset' => desc.uri} if desc
|
60
|
-
m['next']={'uri' => 'next','url' => d.url,'d' => 'asc', 'offset' => asc.uri} if asc
|
61
|
-
s }}
|
62
|
-
F['set/indexPO']=F['set/index']
|
63
|
-
fn 'set/indexP',->d,r,m{Fn 'set/index',d,r,m,:rangeP}
|
64
|
-
|
65
|
-
# predicate index
|
66
|
-
def pIndex
|
67
|
-
'/index'.E.s self
|
68
|
-
end
|
69
|
-
|
70
|
-
# predicate-object index
|
71
|
-
def poIndex o
|
72
|
-
pIndex.s o
|
73
|
-
end
|
74
|
-
|
75
|
-
# predicate-object index lookup
|
76
|
-
def po o
|
77
|
-
pIndex[o.class == E ? o : literal(o)]
|
78
|
-
end
|
79
|
-
|
80
|
-
# range query - predicate
|
81
|
-
def rangeP n=8,d=:desc,s=nil,o=nil
|
82
|
-
puts "rangeP #{uri} count #{n} dir #{d} cursor #{s}"
|
83
|
-
pIndex.subtree(n,d,s).map &:ro
|
84
|
-
end
|
85
|
-
|
86
|
-
# range query - predicate-object
|
87
|
-
def rangePO n=8,d=:desc,s=nil,o
|
88
|
-
puts "rangePO #{uri} #{o} count #{n} dir #{d} cursor #{s}"
|
89
|
-
poIndex(o).subtree(n,d,s).map &:ro
|
90
|
-
end
|
91
|
-
|
92
|
-
# E -> [node]
|
93
|
-
def subtree *a
|
94
|
-
u.take *a
|
95
|
-
end
|
96
|
-
|
97
|
-
# E -> [E]
|
98
|
-
def take *a
|
99
|
-
no.take(*a).map &:E
|
72
|
+
# create link
|
73
|
+
def ln t
|
74
|
+
t = t.E # cast bare URI/string to resource
|
75
|
+
if !t.e # destination exist?
|
76
|
+
t.dirname.mk
|
77
|
+
FileUtils.link node, t.node
|
78
|
+
end
|
100
79
|
end
|
101
80
|
|
102
|
-
|
81
|
+
# create symlink
|
82
|
+
def ln_s t
|
83
|
+
t = t.E # cast bare URI/string to resource
|
84
|
+
if !t.e # destination exist?
|
85
|
+
t.dirname.mk
|
86
|
+
FileUtils.symlink node, t.node
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def touch
|
91
|
+
FileUtils.touch node
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def deleteNode
|
96
|
+
node.deleteNode if e
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
def size
|
101
|
+
node.size
|
102
|
+
end
|
103
|
+
|
104
|
+
def read
|
105
|
+
f ? r : get
|
106
|
+
end
|
107
|
+
|
108
|
+
def get
|
109
|
+
(open uri).read
|
110
|
+
end
|
111
|
+
|
112
|
+
def r p=false
|
113
|
+
if f
|
114
|
+
p ? (JSON.parse readFile) : readFile
|
115
|
+
else
|
116
|
+
puts "tried to open #{d}"
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
rescue Exception => e
|
120
|
+
puts e
|
121
|
+
end
|
122
|
+
|
123
|
+
def w o,s=false
|
124
|
+
dirname.mk
|
125
|
+
writeFile (s ? o.to_json : o)
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
def writeFile c
|
130
|
+
File.open(d,'w'){|f|f << c}
|
131
|
+
end
|
103
132
|
|
133
|
+
def readFile
|
134
|
+
File.open(d).read
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
104
138
|
|
105
139
|
class Pathname
|
106
140
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# construct offset-path
|
111
|
-
offset = to_s + offset.gsub(/\/+/,'/').E.path if offset
|
112
|
-
|
113
|
-
# in-range indicator
|
114
|
-
ok = false
|
115
|
-
|
116
|
-
# result set
|
117
|
-
set=[]
|
118
|
-
|
119
|
-
# asc/desc operators
|
120
|
-
v,m={asc: [:id,:>=],
|
121
|
-
desc: [:reverse,:<=]}[direction]
|
122
|
-
|
123
|
-
# visitation function
|
124
|
-
visit=->nodes{
|
125
|
-
|
126
|
-
# sort nodes in asc or desc order
|
127
|
-
nodes.sort_by(&:to_s).send(v).each{|n|
|
128
|
-
ns = n.to_s
|
129
|
-
# have we got enough nodes?
|
130
|
-
return if 0 >= count
|
131
|
-
|
132
|
-
# continue if
|
133
|
-
(# already in-range
|
134
|
-
ok ||
|
135
|
-
# no offset specified
|
136
|
-
!offset ||
|
137
|
-
# offset satisfies in-range operator
|
138
|
-
(sz = [ns,offset].map(&:size).min
|
139
|
-
ns[0..sz-1].send(m,offset[0..sz-1]))) && (
|
140
|
-
if !(c = n.c).empty? # has children?
|
141
|
-
visit.(c) # visit children
|
142
|
-
else
|
143
|
-
count = count - 1 # decrement wanted-nodes count
|
144
|
-
set.push n # add node to result-set
|
145
|
-
ok = true # iterator is now within range
|
146
|
-
end )}}
|
147
|
-
|
148
|
-
visit.(c) # start
|
149
|
-
|
150
|
-
# result set
|
151
|
-
set
|
141
|
+
def E
|
142
|
+
to_s.force_encoding('UTF-8').unpathFs
|
152
143
|
end
|
153
144
|
|
145
|
+
def c
|
146
|
+
return [] unless directory?
|
147
|
+
children.delete_if{|n| n.basename.to_s.match /^\./}
|
148
|
+
rescue
|
149
|
+
[]
|
150
|
+
end
|
151
|
+
|
152
|
+
def deleteNode
|
153
|
+
FileUtils.send file? ? :rm : :rmdir, self
|
154
|
+
parent.deleteNode if parent.c.empty?
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
class File::Stat
|
160
|
+
def utime
|
161
|
+
mtime.to_i
|
162
|
+
end
|
154
163
|
end
|