infod 0.0.3.1 → 0.0.3.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 +1 -6
- data/infod/404.rb +3 -4
- data/infod/500.rb +3 -2
- data/infod/GET.rb +23 -14
- data/infod/HEAD.rb +1 -1
- data/infod/HTTP.rb +24 -40
- data/infod/POST.rb +18 -16
- data/infod/audio.rb +12 -4
- data/infod/blog.rb +1 -1
- data/infod/code.rb +2 -2
- data/infod/constants.rb +6 -6
- data/infod/csv.rb +27 -4
- data/infod/edit.rb +58 -42
- data/infod/feed.rb +55 -27
- data/infod/fs.rb +6 -4
- data/infod/glob.rb +3 -4
- data/infod/graph.rb +66 -50
- data/infod/grep.rb +12 -9
- data/infod/groonga.rb +35 -50
- data/infod/html.rb +82 -55
- data/infod/image.rb +1 -1
- data/infod/index.rb +23 -73
- data/infod/infod.rb +1 -6
- data/infod/kv.rb +8 -6
- data/infod/lambda.rb +2 -0
- data/infod/ls.rb +21 -15
- data/infod/mail.rb +36 -27
- data/infod/man.rb +3 -3
- data/infod/microblog.rb +3 -3
- data/infod/mime.rb +1 -0
- data/infod/names.rb +28 -92
- data/infod/page.rb +10 -4
- data/infod/rdf.rb +11 -4
- data/infod/ruby.rb +2 -1
- data/infod/schema.rb +4 -20
- data/infod/sh.rb +3 -5
- data/infod/text.rb +5 -3
- data/infod/threads.rb +12 -13
- data/infod/time.rb +16 -14
- data/infod/webid.rb +0 -0
- metadata +3 -7
- data/infod/PATCH.rb +0 -5
- data/infod/css.rb +0 -21
- data/infod/du.rb +0 -16
- data/infod/json.rb +0 -38
- data/infod/search.rb +0 -16
    
        data/infod/groonga.rb
    CHANGED
    
    | @@ -1,66 +1,52 @@ | |
| 1 1 | 
             
            #watch __FILE__
         | 
| 2 2 | 
             
            class E
         | 
| 3 | 
            +
            =begin
         | 
| 4 | 
            +
                  gem install rroonga
         | 
| 5 | 
            +
                  a ruby full-text searcher & column-store
         | 
| 6 | 
            +
                  http://groonga.org/
         | 
| 7 | 
            +
            =end
         | 
| 8 | 
            +
              
         | 
| 9 | 
            +
              fn 'view/'+Search+'Groonga',-> d,e {{_: :form, action: '/', c: [{_: :input, name: :q, style: 'font-size:2em'},{_: :input, type: :hidden, name: :graph, value: :groonga}]}}
         | 
| 3 10 |  | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
              fn 'protograph/roonga',->d,e,m{
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                # groonga engine
         | 
| 11 | 
            -
                ga = E.groonga
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                # search expression
         | 
| 14 | 
            -
                q = e['q']
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                # context
         | 
| 17 | 
            -
                g = e["context"] || d.env['SERVER_NAME']
         | 
| 11 | 
            +
              fn 'protograph/groonga',->d,e,m{
         | 
| 12 | 
            +
                E.groonga.do{|ga|
         | 
| 13 | 
            +
                q = e['q']                               # search expression
         | 
| 14 | 
            +
                g = e["context"] || d.env['SERVER_NAME'] # context
         | 
| 18 15 |  | 
| 19 16 | 
             
                begin
         | 
| 20 | 
            -
                  #  | 
| 21 | 
            -
                  r = (q && !q.empty?) ? ga.select{|r|(r['graph'] == g) & r["content"].match(q)} : # expression if exists
         | 
| 22 | 
            -
                    ga.select{|r| r['graph'] == g} # ordered set (index date-range)
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                  # offset, size
         | 
| 25 | 
            -
                  start = e['start'].do{|c| c.to_i.max(r.size - 1).min 0 } || 0
         | 
| 26 | 
            -
                  c = (e['c']||e['count']).do{|c|c.to_i.max(10000).min(0)} || 8
         | 
| 17 | 
            +
                  m['/'] = {Type => E[Search+'Groonga']} # add a groonga resource to the graph
         | 
| 27 18 |  | 
| 28 | 
            -
                   | 
| 29 | 
            -
             | 
| 30 | 
            -
                  up   = !(start<=0)
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                  # sort results
         | 
| 33 | 
            -
                  r = r.sort(e.has_key?('score') ? [["_score"]] : [["time", "descending"]],:offset => start,:limit => c)
         | 
| 19 | 
            +
                  r = (q && !q.empty?) ? ga.select{|r|(r['graph'] == g) & r["content"].match(q)} : # expression if exists
         | 
| 20 | 
            +
                    ga.select{|r| r['graph'] == g}                                                 # or just an ordered set
         | 
| 34 21 |  | 
| 35 | 
            -
                   | 
| 36 | 
            -
                   | 
| 37 | 
            -
                   | 
| 22 | 
            +
                  start = e['start'].do{|c| c.to_i.max(r.size - 1).min 0 } || 0  # offset
         | 
| 23 | 
            +
                  c = (e['c']||e['count']).do{|c|c.to_i.max(10000).min(0)} || 16 # count
         | 
| 24 | 
            +
                  down = r.size > start+c                                        # prev
         | 
| 25 | 
            +
                  up   = !(start<=0)                                             # next
         | 
| 26 | 
            +
                  r = r.sort(e.has_key?('best') ? [["_score"]]:[["time","descending"]],:offset =>start,:limit =>c) # sort
         | 
| 27 | 
            +
                  r = r.map{|r| r['.uri'].E }                                    # URI
         | 
| 28 | 
            +
                  (r.map &:docs).flatten.uniq.map{|r|m[r.uri] = r.env e}         # set resource thunks
         | 
| 38 29 |  | 
| 39 | 
            -
                  m['#'] = {'uri' => '#',
         | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
                  m['#'][Prev]={'uri' => '/search' + {'q' => q, 'start' => start + c, 'c' => c}.qs} if down
         | 
| 43 | 
            -
                  m['#'][Next]={'uri' => '/search' + {'q' => q, 'start' => start - c, 'c' => c}.qs} if up
         | 
| 44 | 
            -
                  m['/search'] = {Type => E[Search]}
         | 
| 30 | 
            +
                  m['#'] = {'uri' => '#', RDFs+'member' => r, Type=>E[HTTP+'Response']} # add pagination data to request-graph
         | 
| 31 | 
            +
                  m['#'][Prev]={'uri' => '/' + {'graph' => 'groonga', 'q' => q, 'start' => start + c, 'c' => c}.qs} if down
         | 
| 32 | 
            +
                  m['#'][Next]={'uri' => '/' + {'graph' => 'groonga', 'q' => q, 'start' => start - c, 'c' => c}.qs} if up
         | 
| 45 33 |  | 
| 46 34 | 
             
                rescue Groonga::SyntaxError => x
         | 
| 47 | 
            -
                  m[' | 
| 48 | 
            -
                  m['#'] = {
         | 
| 49 | 
            -
                    Type => E[COGS+'Exception'],
         | 
| 50 | 
            -
                    Title => "bad expression",
         | 
| 51 | 
            -
                    Content => CGI.escapeHTML(x.message)}
         | 
| 35 | 
            +
                  m['#'] = {Type => E[COGS+'Exception'], Title => "invalid expr", Content => CGI.escapeHTML(x.message)}
         | 
| 52 36 | 
             
                  e['nocache']=true
         | 
| 53 37 | 
             
                end
         | 
| 54 38 |  | 
| 55 | 
            -
                F['docsID'][m,e]}
         | 
| 39 | 
            +
                F['docsID'][m,e]}}
         | 
| 56 40 |  | 
| 57 41 | 
             
              def E.groonga
         | 
| 58 | 
            -
                @groonga ||= | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 42 | 
            +
                @groonga ||=
         | 
| 43 | 
            +
                  (begin require 'groonga'
         | 
| 44 | 
            +
                     E['/E/groonga'].groonga
         | 
| 45 | 
            +
                     Groonga["E"]
         | 
| 46 | 
            +
                   rescue LoadError => e; end)
         | 
| 61 47 | 
             
              end
         | 
| 62 48 |  | 
| 63 | 
            -
              #  | 
| 49 | 
            +
              # init groongaDB
         | 
| 64 50 | 
             
              def groonga
         | 
| 65 51 | 
             
                return Groonga::Database.open d if e # open db
         | 
| 66 52 | 
             
                dirname.mk                           # create containing dir
         | 
| @@ -78,17 +64,16 @@ class E | |
| 78 64 | 
             
                                              %w{graph content}.map{|c| t.index("E." + c) }}}
         | 
| 79 65 | 
             
              end
         | 
| 80 66 |  | 
| 81 | 
            -
              #  | 
| 67 | 
            +
              # add
         | 
| 82 68 | 
             
              def roonga graph="global", m = self.graph
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                g = E.groonga          # db
         | 
| 69 | 
            +
               E.groonga.do{|g|
         | 
| 85 70 | 
             
                m.map{|u,i|
         | 
| 86 71 | 
             
                  r = g[u] || g.add(u) # create or load entry
         | 
| 87 72 | 
             
                  r.uri = u            # update data
         | 
| 88 73 | 
             
                  r.graph = graph.to_s
         | 
| 89 74 | 
             
                  r.content = i.to_s
         | 
| 90 75 | 
             
                  r.time = i[E::Date].do{|t|t[0].to_time}
         | 
| 91 | 
            -
                }
         | 
| 76 | 
            +
                }}
         | 
| 92 77 | 
             
                self
         | 
| 93 78 | 
             
              end
         | 
| 94 79 |  | 
    
        data/infod/html.rb
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            #watch __FILE__
         | 
| 2 2 |  | 
| 3 | 
            -
            #  | 
| 3 | 
            +
            # (H) templates
         | 
| 4 4 | 
             
            def H _
         | 
| 5 5 | 
             
              case _
         | 
| 6 6 | 
             
              when Hash
         | 
| @@ -20,11 +20,17 @@ class H | |
| 20 20 | 
             
              def H.[] h; H h end
         | 
| 21 21 |  | 
| 22 22 | 
             
              def H.js a,inline=false
         | 
| 23 | 
            -
                p=a+'.js'
         | 
| 23 | 
            +
                p = a + '.js'
         | 
| 24 24 | 
             
                inline ? {_: :script, c: p.E.r} :
         | 
| 25 25 | 
             
                {_: :script, type: "text/javascript", src: p}
         | 
| 26 26 | 
             
              end
         | 
| 27 27 |  | 
| 28 | 
            +
              def H.css a,inline=false
         | 
| 29 | 
            +
                p = a + '.css'
         | 
| 30 | 
            +
                inline ? {_: :style, c: p.E.r} :
         | 
| 31 | 
            +
                {_: :link, href: p, rel: :stylesheet, type: E::MIME[:css]}
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 28 34 | 
             
              def H.once e,n,*h
         | 
| 29 35 | 
             
                return if e[n]
         | 
| 30 36 | 
             
                e[n]=true
         | 
| @@ -33,8 +39,8 @@ class H | |
| 33 39 | 
             
            end
         | 
| 34 40 |  | 
| 35 41 | 
             
            class Array
         | 
| 36 | 
            -
              def html v=nil
         | 
| 37 | 
            -
                map{|e|e.html v}.join ' '
         | 
| 42 | 
            +
              def html v=nil,g=nil
         | 
| 43 | 
            +
                map{|e|e.html v,g}.join ' '
         | 
| 38 44 | 
             
              end
         | 
| 39 45 | 
             
            end
         | 
| 40 46 |  | 
| @@ -54,49 +60,52 @@ class String | |
| 54 60 | 
             
                '<a href="'+self+'">' + (name||abbrURI) + '</a>'
         | 
| 55 61 | 
             
              end
         | 
| 56 62 | 
             
              def abbrURI
         | 
| 57 | 
            -
                sub /(?<scheme>[a-z]+:\/\/)?(?<abbr>.*?)(?<frag>[^#\/] | 
| 58 | 
            -
                '<span class="abbr"><span class="scheme">\k<scheme></span>\k<abbr></span><span class="frag">\k<frag></span>'
         | 
| 63 | 
            +
                sub /(?<scheme>[a-z]+:\/\/)?(?<abbr>.*?)(?<frag>[^#\/]+)\/?$/,'<span class="abbr"><span class="scheme">\k<scheme></span>\k<abbr></span><span class="frag">\k<frag></span>'
         | 
| 59 64 | 
             
              end
         | 
| 60 | 
            -
              def html e=nil
         | 
| 61 | 
            -
            # CGI.escapeHTML self
         | 
| 65 | 
            +
              def html e=nil,g=nil
         | 
| 62 66 | 
             
                self
         | 
| 63 67 | 
             
              end
         | 
| 64 68 | 
             
            end
         | 
| 65 69 |  | 
| 66 70 | 
             
            class Fixnum
         | 
| 67 | 
            -
              def html e=nil; to_s end
         | 
| 71 | 
            +
              def html e=nil,g=nil; to_s end
         | 
| 68 72 | 
             
            end
         | 
| 69 73 |  | 
| 70 74 | 
             
            class Float
         | 
| 71 | 
            -
              def html e=nil; to_s end
         | 
| 75 | 
            +
              def html e=nil,g=nil; to_s end
         | 
| 72 76 | 
             
            end
         | 
| 73 77 |  | 
| 74 78 | 
             
            class TrueClass
         | 
| 75 | 
            -
              def html e=nil; H({_: :input, type: :checkbox, title: :True, checked: :checked}) end
         | 
| 79 | 
            +
              def html e=nil,g=nil; H({_: :input, type: :checkbox, title: :True, checked: :checked}) end
         | 
| 76 80 | 
             
            end
         | 
| 77 81 |  | 
| 78 82 | 
             
            class FalseClass
         | 
| 79 | 
            -
              def html e=nil; H({_: :input, type: :checkbox, title: :False}) end
         | 
| 83 | 
            +
              def html e=nil,g=nil; H({_: :input, type: :checkbox, title: :False}) end
         | 
| 80 84 | 
             
            end
         | 
| 81 85 |  | 
| 86 | 
            +
            IsBnode = /^_:/
         | 
| 87 | 
            +
             | 
| 82 88 | 
             
            class Hash
         | 
| 83 | 
            -
              def html e={'SERVER_NAME'=>'localhost'}, key=true
         | 
| 84 | 
            -
                 | 
| 85 | 
            -
                   | 
| 86 | 
            -
                     | 
| 87 | 
            -
                       | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 89 | 
            +
              def html e={'SERVER_NAME'=>'localhost'}, g={}, key=true
         | 
| 90 | 
            +
                if keys.size == 1 && has_key?('uri')
         | 
| 91 | 
            +
                  if uri.match IsBnode
         | 
| 92 | 
            +
                    g[uri].do{|r|
         | 
| 93 | 
            +
                      r.html e,g,key } || uri.href
         | 
| 94 | 
            +
                  else
         | 
| 95 | 
            +
                    uri.href
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
                else
         | 
| 98 | 
            +
                  H({_: :table, class: :html, c: map{|k,v|
         | 
| 99 | 
            +
                        unless k == 'uri' && (v.match IsBnode)
         | 
| 100 | 
            +
                          {_: :tr, property: k, c:
         | 
| 101 | 
            +
                            [k == E::Content ? {_: :td, class: :val, colspan: 2, c: v} :
         | 
| 102 | 
            +
                             [
         | 
| 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.E.do{|u| {_: :a, id: u, href: u.url, c: v}} : v.html(e,g), class: :val},
         | 
| 105 | 
            +
                             ]]}
         | 
| 106 | 
            +
                        end
         | 
| 107 | 
            +
                      }})
         | 
| 108 | 
            +
                end
         | 
| 100 109 | 
             
              end
         | 
| 101 110 | 
             
            end
         | 
| 102 111 |  | 
| @@ -107,17 +116,21 @@ class E | |
| 107 116 | 
             
              end
         | 
| 108 117 |  | 
| 109 118 | 
             
              fn 'view',->d,e{
         | 
| 110 | 
            -
                d.values. | 
| 111 | 
            -
             | 
| 119 | 
            +
                d.values.select{|r|
         | 
| 120 | 
            +
                  !r.has_key?('uri') || # URI field missing
         | 
| 121 | 
            +
                  !r.uri.match(IsBnode) # blank node
         | 
| 122 | 
            +
                  true
         | 
| 123 | 
            +
                }.
         | 
| 124 | 
            +
                sort_by{|r| r[Date].do{|d| d[0].to_s} || ''}.reverse.
         | 
| 125 | 
            +
                map{|r| Fn 'view/select',r,e,d}}
         | 
| 112 126 |  | 
| 113 | 
            -
              fn 'view/base',->d,e,k=true{
         | 
| 127 | 
            +
              fn 'view/base',->d,e,k=true,graph=nil{
         | 
| 114 128 | 
             
                [H.once(e,'base',H.css('/css/html')),
         | 
| 115 | 
            -
                 d.values.map{|v|v.html e,k}]}
         | 
| 129 | 
            +
                 d.values.map{|v|v.html e,graph,k}]}
         | 
| 116 130 |  | 
| 117 | 
            -
              fn 'view/select',->r,e{
         | 
| 131 | 
            +
              fn 'view/select',->r,e,d{
         | 
| 118 132 | 
             
                graph = {r.uri => r}
         | 
| 119 | 
            -
                view =  | 
| 120 | 
            -
                # find types, skipping malformed/missing info
         | 
| 133 | 
            +
                view = nil
         | 
| 121 134 | 
             
                if r.class == Hash
         | 
| 122 135 | 
             
                  (r[Type].class==Array ? r[Type] : [r[Type]]).do{|types|
         | 
| 123 136 | 
             
                    views = types.map{|t|
         | 
| @@ -131,13 +144,11 @@ class E | |
| 131 144 | 
             
                    flatten.compact
         | 
| 132 145 | 
             
                    view = views[0] unless views.empty?}
         | 
| 133 146 | 
             
                end
         | 
| 134 | 
            -
                view | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
                 | 
| 139 | 
            -
                  vs.split(',').map{|v|
         | 
| 140 | 
            -
                    F['view/'+v].do{|f|f[d,e]}}}}
         | 
| 147 | 
            +
                if !view # default view
         | 
| 148 | 
            +
                  F['view/base'][graph,e,true,d]
         | 
| 149 | 
            +
                else
         | 
| 150 | 
            +
                  view[graph,e]
         | 
| 151 | 
            +
                end}
         | 
| 141 152 |  | 
| 142 153 | 
             
              # enumerate available views
         | 
| 143 154 | 
             
              fn 'view/?',->d,e{
         | 
| @@ -154,10 +165,24 @@ class E | |
| 154 165 | 
             
                yield uri,Content,(f && read).do{|r|enc ? r.force_encoding(enc).to_utf8 : r}.hrefs
         | 
| 155 166 | 
             
              end
         | 
| 156 167 |  | 
| 168 | 
            +
              require 'nokogiri'
         | 
| 169 | 
            +
              def nokogiri;  Nokogiri::HTML.parse read end
         | 
| 170 | 
            +
             | 
| 171 | 
            +
              F['HTMLbody'] = -> b {
         | 
| 172 | 
            +
                b.to_s.split(/<body[^>]*>/)[-1].to_s.split(/<\/body>/)[0] }
         | 
| 173 | 
            +
             | 
| 174 | 
            +
              F['cleanHTML'] = -> b {
         | 
| 175 | 
            +
                h = Nokogiri::HTML.fragment F['HTMLbody'][b]
         | 
| 176 | 
            +
                h.css('iframe').remove
         | 
| 177 | 
            +
                h.css('script').remove
         | 
| 178 | 
            +
                h.xpath("//@*[starts-with(name(),'on')]").remove
         | 
| 179 | 
            +
                h.to_s
         | 
| 180 | 
            +
              }
         | 
| 181 | 
            +
             | 
| 157 182 | 
             
              def contentURIresolve *f
         | 
| 158 183 | 
             
                send(*f){|s,p,o|
         | 
| 159 184 | 
             
                  yield s, p, p == Content ?
         | 
| 160 | 
            -
                  (Nokogiri::HTML. | 
| 185 | 
            +
                  (Nokogiri::HTML.fragment o).do{|o|
         | 
| 161 186 | 
             
                    o.css('a').map{|a|
         | 
| 162 187 | 
             
                      if a.has_attribute? 'href'
         | 
| 163 188 | 
             
                        (a.set_attribute 'href', (URI.join s, (a.attr 'href'))) rescue nil
         | 
| @@ -216,16 +241,18 @@ class E | |
| 216 241 | 
             
                  "table= layout arg required"
         | 
| 217 242 | 
             
                end}
         | 
| 218 243 |  | 
| 219 | 
            -
              fn 'view/table',-> | 
| 220 | 
            -
             | 
| 221 | 
            -
             | 
| 222 | 
            -
                 | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
             | 
| 244 | 
            +
              fn 'view/table',->g,e{
         | 
| 245 | 
            +
                keys = E.graphProperties g
         | 
| 246 | 
            +
                v = g.values
         | 
| 247 | 
            +
                e.q['sort'].do{|p|
         | 
| 248 | 
            +
                  p = p.expand
         | 
| 249 | 
            +
                  v = v.sort_by{|s|
         | 
| 250 | 
            +
                    s[p].do{|o|
         | 
| 251 | 
            +
                      o[0].to_s}||''}} # cast to a single type (String) so sort will work. every class seems to have a #to_s
         | 
| 252 | 
            +
                v = v.reverse if e.q['reverse']
         | 
| 253 | 
            +
                [H.css('/css/table'),
         | 
| 254 | 
            +
                 {_: :table,:class => :tab,
         | 
| 255 | 
            +
                   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.E.html : e[k].html}}}}]}]}
         | 
| 230 257 |  | 
| 231 258 | 
             
            end
         | 
    
        data/infod/image.rb
    CHANGED
    
    | @@ -78,7 +78,7 @@ class E | |
| 78 78 | 
             
                     # view 
         | 
| 79 79 | 
             
                     {uri: s,
         | 
| 80 80 | 
             
                       # img and  link to containing resource
         | 
| 81 | 
            -
                       c: ->{"<a href='#{v.uri | 
| 81 | 
            +
                       c: ->{"<a href='#{v.uri}'><img style='float:left;#{h}' src='#{s}'></a>"}}}}.flatten.map{|i|
         | 
| 82 82 |  | 
| 83 83 | 
             
                   # show and mark as seen
         | 
| 84 84 | 
             
                   !seen[i[:uri]] &&
         | 
    
        data/infod/index.rb
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            watch __FILE__
         | 
| 1 | 
            +
            #watch __FILE__
         | 
| 2 2 | 
             
            class E
         | 
| 3 3 |  | 
| 4 4 | 
             
              # POSIX-fs based index of triples
         | 
| @@ -11,9 +11,9 @@ class E | |
| 11 11 | 
             
              end
         | 
| 12 12 |  | 
| 13 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..
         | 
| 14 15 | 
             
              def indexEdit p,o,a
         | 
| 15 16 | 
             
                return if @noIndex
         | 
| 16 | 
            -
            #    puts "index #{p} #{o} #{a}"
         | 
| 17 17 | 
             
                p.pIndex.noIndex[o,self,a]
         | 
| 18 18 | 
             
              end
         | 
| 19 19 | 
             
              def noIndex
         | 
| @@ -36,79 +36,46 @@ class E | |
| 36 36 | 
             
                g
         | 
| 37 37 | 
             
              end
         | 
| 38 38 |  | 
| 39 | 
            -
              #  | 
| 40 | 
            -
             | 
| 41 | 
            -
                 | 
| 42 | 
            -
                 | 
| 43 | 
            -
             | 
| 44 | 
            -
                 | 
| 45 | 
            -
             | 
| 46 | 
            -
                   | 
| 39 | 
            +
              fn 'set/depth',->d,r,m{ # depth-first
         | 
| 40 | 
            +
                global = !r.has_key?('local')
         | 
| 41 | 
            +
                p = global ? d.pathSegment : d
         | 
| 42 | 
            +
                loc = global ? '' : '&local'
         | 
| 43 | 
            +
                c = ((r['c'].do{|c|c.to_i} || 12) + 1).max(128) # an extra for next-page pointer
         | 
| 44 | 
            +
                o = r['d'] =~ /^a/ ? :asc : :desc            # direction
         | 
| 45 | 
            +
                (p.take c, o, r['offset'].do{|o|o.E}).do{|s| # take subtree
         | 
| 46 | 
            +
                  first, last = s[0], s.size > 1 && s.pop
         | 
| 47 | 
            +
                  desc, asc = o == :asc ? [first,last] : [last,first]
         | 
| 47 48 | 
             
                  u = m['#']
         | 
| 48 49 | 
             
                  u[Type] = E[HTTP+'Response']
         | 
| 49 | 
            -
                  u[Prev] = {'uri' =>  | 
| 50 | 
            -
                  u[Next] = {'uri' =>  | 
| 50 | 
            +
                  u[Prev] = {'uri' => d.uri + "?set=depth&c=#{c-1}&d=desc#{loc}&offset=" + (URI.escape desc.uri)} if desc
         | 
| 51 | 
            +
                  u[Next] = {'uri' => d.uri + "?set=depth&c=#{c-1}&d=asc#{loc}&offset=" + (URI.escape asc.uri)} if asc
         | 
| 51 52 | 
             
                  s }}
         | 
| 52 53 |  | 
| 53 | 
            -
              # subtree traverse index on p+o cursor
         | 
| 54 | 
            -
              fn 'set/index',->d,r,m{
         | 
| 55 | 
            -
                top = r['p'].expand.E
         | 
| 56 | 
            -
                count = r['c'] &&
         | 
| 57 | 
            -
                        r['c'].to_i.max(1000) || 8
         | 
| 58 | 
            -
                dir = r['d'] && r['d'].match(/^(a|de)sc$/) &&
         | 
| 59 | 
            -
                      r['d'].to_sym || :desc
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                (top.rangePO count+1, dir, r['offset'], r['o']).do{|s|
         | 
| 62 | 
            -
                  # orient pagination pointers
         | 
| 63 | 
            -
                  ascending = r['d'].do{|d| d == 'asc' }
         | 
| 64 | 
            -
                  first, last = s[0], s.size > 1 && s.pop
         | 
| 65 | 
            -
                  desc, asc = ascending && [first,last] || [last,first]
         | 
| 66 | 
            -
                  # response description
         | 
| 67 | 
            -
                  u = m['#']
         | 
| 68 | 
            -
                  u[RDFs+'member'] = s
         | 
| 69 | 
            -
                  u[Prev] = {'uri' => '/index/' + r['p'] + '/' + CGI.escape(r['o']) + {'offset' => desc.uri, 'c' => count}.qs } if desc
         | 
| 70 | 
            -
                  u[Next] = {'uri' => '/index/' + r['p'] + '/' + CGI.escape(r['o']) + {'offset' => asc.uri, 'c' => count}.qs } if asc
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                  s.map(&:docs).flatten.uniq }}
         | 
| 73 | 
            -
             | 
| 74 | 
            -
              fn '/index/GET',->e,r{
         | 
| 75 | 
            -
                a = e.pathSegment.uri[7..-1].split '/',2
         | 
| 76 | 
            -
                r.q['set'] = 'index'
         | 
| 77 | 
            -
                r.q['p'] = a[0]
         | 
| 78 | 
            -
                r.q['o'] = CGI.unescape a[1]
         | 
| 79 | 
            -
                e.response}
         | 
| 80 | 
            -
             | 
| 81 | 
            -
              # predicate index
         | 
| 82 54 | 
             
              def pIndex
         | 
| 83 55 | 
             
                shorten.prependURI '/index/'
         | 
| 84 56 | 
             
              end
         | 
| 85 57 |  | 
| 86 | 
            -
              # predicate-object index
         | 
| 87 58 | 
             
              def poIndex o
         | 
| 88 59 | 
             
                pIndex.concatURI o
         | 
| 89 60 | 
             
              end
         | 
| 90 61 |  | 
| 91 | 
            -
              # predicate | 
| 62 | 
            +
              # predicate+object pair lookup
         | 
| 92 63 | 
             
              def po o
         | 
| 93 64 | 
             
                pIndex[o.class == E ? o : literal(o)]
         | 
| 94 65 | 
             
              end
         | 
| 95 66 |  | 
| 96 | 
            -
              # range query - predicate
         | 
| 97 67 | 
             
              def rangeP size=8, dir=:desc, offset=nil, object=nil
         | 
| 98 68 | 
             
                pIndex.subtree(size,dir,offset).map &:ro
         | 
| 99 69 | 
             
              end
         | 
| 100 70 |  | 
| 101 | 
            -
              # range query - predicate-object
         | 
| 102 71 | 
             
              def rangePO n=8,d=:desc,s=nil,o
         | 
| 103 72 | 
             
                poIndex(o).subtree(n,d,s).map &:ro
         | 
| 104 73 | 
             
              end
         | 
| 105 74 |  | 
| 106 | 
            -
              # E -> [node]
         | 
| 107 75 | 
             
              def subtree *a
         | 
| 108 76 | 
             
                u.take *a
         | 
| 109 77 | 
             
              end
         | 
| 110 78 |  | 
| 111 | 
            -
              # E -> [E]
         | 
| 112 79 | 
             
              def take *a
         | 
| 113 80 | 
             
                no.take(*a).map &:E
         | 
| 114 81 | 
             
              end
         | 
| @@ -129,49 +96,32 @@ end | |
| 129 96 |  | 
| 130 97 | 
             
            class Pathname
         | 
| 131 98 |  | 
| 132 | 
            -
              # take N els from fs tree in sorted, depth-first order
         | 
| 133 99 | 
             
              def take count=1000, direction=:desc, offset=nil
         | 
| 100 | 
            +
                offset = offset.d if offset
         | 
| 134 101 |  | 
| 135 | 
            -
                #  | 
| 136 | 
            -
                offset = (to_s + offset).gsub(/\/+/,'/').E.path if offset
         | 
| 137 | 
            -
             | 
| 138 | 
            -
                # in-range indicator
         | 
| 139 | 
            -
                ok = false
         | 
| 140 | 
            -
             | 
| 141 | 
            -
                # result set
         | 
| 102 | 
            +
                ok = false    # in-range mark
         | 
| 142 103 | 
             
                set=[]
         | 
| 143 | 
            -
             | 
| 144 | 
            -
                # asc/desc operators
         | 
| 145 104 | 
             
                v,m={asc:      [:id,:>=],
         | 
| 146 105 | 
             
                    desc: [:reverse,:<=]}[direction]
         | 
| 147 106 |  | 
| 148 | 
            -
                # visitation function
         | 
| 149 107 | 
             
                visit=->nodes{
         | 
| 150 | 
            -
             | 
| 151 | 
            -
                  # sort nodes in asc or desc order
         | 
| 152 108 | 
             
                  nodes.sort_by(&:to_s).send(v).each{|n|
         | 
| 153 109 | 
             
                    ns = n.to_s
         | 
| 154 | 
            -
                    # have we got enough nodes?
         | 
| 155 110 | 
             
                    return if 0 >= count
         | 
| 156 111 |  | 
| 157 | 
            -
                    #  | 
| 158 | 
            -
             | 
| 159 | 
            -
                     ok ||
         | 
| 160 | 
            -
                     # no offset specified
         | 
| 161 | 
            -
                     !offset ||
         | 
| 162 | 
            -
                     # offset satisfies in-range operator
         | 
| 112 | 
            +
                    (ok || # already in-range
         | 
| 113 | 
            +
                     !offset || # no offset required
         | 
| 163 114 | 
             
                     (sz = [ns,offset].map(&:size).min
         | 
| 164 | 
            -
                      ns[0..sz-1].send(m,offset[0..sz-1]))) && | 
| 165 | 
            -
             | 
| 115 | 
            +
                      ns[0..sz-1].send(m,offset[0..sz-1]))) &&
         | 
| 116 | 
            +
                    (if !(c = n.c).empty? # has children?
         | 
| 166 117 | 
             
                       visit.(c)          # visit children
         | 
| 167 118 | 
             
                     else
         | 
| 168 | 
            -
                       count = count - 1 # decrement  | 
| 119 | 
            +
                       count = count - 1 # decrement nodes-left count
         | 
| 169 120 | 
             
                       set.push n        # add node to result-set
         | 
| 170 | 
            -
                       ok = true         # iterator  | 
| 121 | 
            +
                       ok = true         # mark iterator as within range
         | 
| 171 122 | 
             
                    end )}}
         | 
| 172 123 |  | 
| 173 | 
            -
                visit.(c) | 
| 174 | 
            -
                # result set
         | 
| 124 | 
            +
                visit.(c)
         | 
| 175 125 | 
             
                set
         | 
| 176 126 | 
             
              end
         | 
| 177 127 |  |