File: ronn

package info (click to toggle)
ruby-ronn 0.8.0-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 760 kB
  • sloc: ruby: 1,554; makefile: 6
file content (241 lines) | stat: -rwxr-xr-x 6,434 bytes parent folder | download | duplicates (2)
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#!/usr/bin/env ruby
# / Usage: ronn <options> <file>...
# /        ronn -m|--man <file>
# /        ronn -S|--server <file> ...
# /        ronn --pipe [<file>...]
# / Convert ronn source <file>s to roff or HTML manpage. In the first synopsis form,
# / build HTML and roff output files based on the input file names.
# /
# / Mode options alter the default behavior of generating files:
# /       --pipe                write to standard output instead of generating files
# /   -m, --man                 show manual like with man(1)
# /   -S, --server              serve <file>s at http://localhost:1207/
# /       --port <port>         run server at specified port instead of 1207
# /   -o, --output-dir <dir>    write generated files to specified directory
# /
# / Format options control which files / formats are generated:
# /   -r, --roff                generate roff output
# /   -5, --html                generate entire HTML page with layout
# /   -f, --fragment            generate HTML fragment
# /       --markdown            generate post-processed markdown output
# /
# / Document attributes:
# /       --date=<date>          published date in YYYY-MM-DD format (bottom-center)
# /       --manual=<name>        name of the manual (top-center)
# /       --organization=<name>  publishing group or individual (bottom-left)
# /
# / Misc options:
# /   -w, --warnings            show troff warnings on stderr
# /   -W                        disable previously enabled troff warnings
# /       --version             show ronn version and exit
# /       --help                show this help message
# /
# / A <file> named example.1.ronn generates example.1.html (HTML manpage)
# / and example.1 (roff manpage) by default.
require 'date'
require 'optparse'

def usage
  puts File.readlines(__FILE__)
           .grep(/^# \/.*/)
           .map { |line| line.chomp[4..-1] }
           .join("\n")
end

##
# Libraries and LOAD_PATH shenanigans

begin
  require 'rdiscount'
  require 'nokogiri'
  require 'ronn'
rescue LoadError => boom
  if boom.to_s =~ /ronn/
    libdir = File.expand_path('../lib', __dir__).sub(%r{^#{Dir.pwd}/}, './')
    if File.directory?(libdir) && !$LOAD_PATH.include?(libdir)
      # warn "warn: #{boom}. adding #{libdir} to RUBYLIB ..."
      $LOAD_PATH.unshift libdir
      retry
    end
  elsif !defined?(Gem)
    warn "warn: #{boom}. loading rubygems ..."
    require 'rubygems'
    retry
  end
  abort boom.to_s
end

##
# Argument defaults

build   = true
view    = false
server  = false
port_arg = nil
formats = nil
options = {}
write_index = false
styles  = %w[man]
groff   = 'groff -Wall -mtty-char -mandoc -Tascii -t'
pager   = ENV['MANPAGER'] || ENV['PAGER'] || 'more -is'
output_dir = nil

##
# Environment variables

%w[manual organization date].each do |attribute|
  value = ENV["RONN_#{attribute.upcase}"]
  next if value.nil? || value.empty?

  options[attribute] = value
end

##
# Argument parsing

ARGV.options do |argv|
  # modes
  argv.on('--pipe')           { build = server = false }
  argv.on('-b', '--build')    { build = true; server = false }
  argv.on('-m', '--man')      { build = server = false; view = true }
  argv.on('-S', '--server')   { build = view = false; server = true }
  argv.on('-i', '--index')    { write_index = true }
  argv.on('-o', '--output-dir=V') { |val| output_dir = val }
  argv.on('--port=V')         { |val| port_arg = val }

  # format options
  argv.on('-r', '--roff')     { (formats ||= []) << 'roff' }
  argv.on('-5', '--html')     { (formats ||= []) << 'html' }
  argv.on('-f', '--fragment') { (formats ||= []) << 'html_fragment' }
  argv.on('--markdown')       { (formats ||= []) << 'markdown' }
  argv.on('--yaml')           { (formats ||= []) << 'yaml' }

  # html output options
  argv.on('-s', '--style=V')  { |val| styles += val.split(/[, \n]+/) }

  # manual attribute options
  %w[name section manual organization date].each do |attribute|
    argv.on("--#{attribute}=VALUE") { |val| options[attribute] = val }
  end

  # misc
  argv.on('-w', '--warnings') { groff += ' -ww' }
  argv.on('-W')               { groff += ' -Ww' }
  argv.on('-v', '--version')  do
    require 'ronn'
    if Ronn.release?
      printf "Ronn-NG v%s\n", Ronn::VERSION
    else
      printf "Ronn-NG v%s (%s)\n", Ronn::VERSION, Ronn::REV
    end
    printf "http://github.com/apjanke/ronn-ng/tree/%s\n", Ronn.revision
    exit 0
  end
  argv.on_tail('--help') { usage; exit 0 }
  argv.parse!
end

##
# Modes, Formats, Options

if ARGV.empty? && $stdin.tty?
  usage
  exit 2
elsif ARGV.empty? && !server
  ARGV.push '-'
  build = false
  formats ||= %w[roff]
elsif view
  formats ||= %w[roff]
elsif build
  formats ||= %w[roff html]
end
formats ||= []
formats.delete('html') if formats.include?('html_fragment')

options['date'] &&= Date.strptime(options['date'], '%Y-%m-%d')
options['styles'] = styles
options['outdir'] = output_dir

unless port_arg.nil?
  begin
    options['port'] = Integer(port_arg)
  rescue ArgumentError
    warn "Error: invalid port number: '#{port_arg}'"
    exit 1
  end
end

##
# Server

if server
  require 'ronn/server'
  Ronn::Server.run(ARGV, options)
  exit 0
end

##
# Build Pipeline

pid = nil
wr = STDOUT
documents = ARGV.map { |file| Ronn::Document.new(file, options) }
documents.each do |doc|
  # setup the man pipeline if the --man option was specified
  if view && !build
    rd, wr = IO.pipe
    pid = fork
    if pid
      rd.close
    else
      wr.close
      STDIN.reopen rd
      exec "#{groff} | #{pager}"
    end
  end

  # write output for each format
  formats.each do |fmt|
    if build
      path = doc.path_for(fmt)
      case fmt
      when 'html'
        warn format('%9s: %-43s%15s', fmt, path, '+' + doc.styles.join(','))
      when 'roff', 'html_fragment', 'markdown'
        warn format('%9s: %-43s', fmt, path)
      end

      output = doc.convert(fmt)
      File.open(path, 'wb') { |f| f.puts(output) }

      if fmt == 'roff'
        if view
          system "man #{path}"
        else
          system "#{groff} <#{path} >/dev/null"
        end
      end
    else
      output = doc.convert(fmt)
      wr.puts(output)
    end
  end

  # wait for children to exit
  if pid
    wr.close
    Process.wait
  end
end

# Write index.txt files

if write_index
  indexes = documents.map(&:index).uniq
  indexes.each do |index|
    File.open(index.path, 'wb') do |fd|
      fd.puts(index.to_text)
    end
  end
end