File: index.rb

package info (click to toggle)
ruby-ronn 0.7.3-2
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 512 kB
  • sloc: ruby: 1,405; makefile: 2
file content (183 lines) | stat: -rw-r--r-- 3,762 bytes parent folder | download | duplicates (3)
1
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
require 'ronn'

module Ronn

  # Maintains a list of links / references to manuals and other resources.
  class Index
    include Enumerable

    attr_reader :path
    attr_reader :references

    # Retrieve an Index for <path>, where <path> is a directory or normal
    # file. The index is loaded from the corresponding index.txt file if
    # one exists.
    def self.[](path)
      (@indexes ||= {})[index_path_for_file(path)] ||=
        Index.new(index_path_for_file(path))
    end

    def self.index_path_for_file(file)
      File.expand_path(
        if File.directory?(file)
          File.join(file, 'index.txt')
        else
          File.join(File.dirname(file), 'index.txt')
        end
      )
    end

    def initialize(path, &bk)
      @path = path
      @references = []
      @manuals    = {}

      if block_given?
        read! yield
      elsif exist?
        read! File.read(path)
      end
    end

    # Determine whether the index file exists.
    def exist?
      File.exist?(path)
    end

    # Load index data from a string.
    def read!(data)
      data.each_line do |line|
        line = line.strip.gsub(/\s*#.*$/, '')
        if !line.empty?
          name, url = line.split(/ +/, 2)
          @references << reference(name, url)
        end
      end
    end

    ##
    # Enumerable and friends

    def each(&bk)
      references.each(&bk)
    end

    def size
      references.size
    end

    def first
      references.first
    end

    def last
      references.last
    end

    def empty?
      references.empty?
    end

    def [](name)
      references.find { |ref| ref.name == name }
    end

    def reference(name, path)
      Reference.new(self, name, path)
    end

    def <<(path)
      raise ArgumentError, "local paths only" if path =~ /(https?|mailto):/
      return self if any? { |ref| ref.path == File.expand_path(path) }
      relative_path = relative_to_index(path)
      @references << \
        if path =~ /\.ronn?$/
          reference manual(path).reference_name, relative_path
        else
          reference File.basename(path), relative_path
        end
      self
    end

    def add_manual(manual)
      @manuals[File.expand_path(manual.path)] = manual
      self << manual.path
    end

    def manual(path)
      @manuals[File.expand_path(path)] ||= Document.new(path)
    end

    def manuals
      select { |ref| ref.relative? && ref.ronn? }.
      map    { |ref| manual(ref.path) }
    end

    ##
    # Converting

    def to_text
      map { |ref| [ref.name, ref.location].join(' ') }.join("\n")
    end

    def to_a
      references
    end

    def to_h
      to_a.map { |doc| doc.to_hash }
    end

    def relative_to_index(path)
      path = File.expand_path(path)
      index_dir = File.dirname(File.expand_path(self.path))
      path.sub(/^#{index_dir}\//, '')
    end
  end

  # An individual index reference. A reference can point to one of a few types
  # of locations:
  #
  #   - URLs: "http://man.cx/crontab(5)"
  #   - Relative paths to ronn manuals: "crontab.5.ronn"
  #
  # The #url method should be used to obtain the href value for HTML.
  class Reference
    attr_reader :name
    attr_reader :location

    def initialize(index, name, location)
      @index = index
      @name = name
      @location = location
    end

    def manual?
      name =~ /\([0-9]\w*\)$/
    end

    def ronn?
      location =~ /\.ronn?$/
    end

    def remote?
      location =~ /^(?:https?|mailto):/
    end

    def relative?
      !remote?
    end

    def url
      if remote?
        location
      else
        location.chomp('.ronn') + '.html'
      end
    end

    def path
      File.expand_path(location, File.dirname(@index.path)) if relative?
    end
  end
end