infod 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|