module Md2Man::Roff

Constants

ENGINE
ENTITY_TO_UNICODE

see www.w3.org/TR/xhtml1/dtds.html#h-A2 see www.w3.org/TR/html4/sgml/entities.html

TABLE_CELL_DELIM
TABLE_COL_DELIM
TABLE_ROW_DELIM
UNICODE_TO_GLYPH

see groff_char(7) and “Special Characters” in groff(7)

Public Instance Methods

block_code(code, language) click to toggle source
Calls superclass method Md2Man::Document#block_code
# File lib/md2man/roff.rb, line 45
def block_code code, language
  code = escape(super, true)
  block_quote "\n.nf\n#{code.chomp}\n.fi\n"
end
block_html(html) click to toggle source
# File lib/md2man/roff.rb, line 54
def block_html html
  warn "md2man/roff: block_html not implemented: #{html.inspect}"
end
block_quote(quote) click to toggle source
# File lib/md2man/roff.rb, line 50
def block_quote quote
  "\n.PP\n.RS\n#{remove_leading_pp(quote).chomp}\n.RE\n"
end
codespan(code) click to toggle source
Calls superclass method Md2Man::Document#codespan
# File lib/md2man/roff.rb, line 165
def codespan code
  code = escape(super, true)
  # NOTE: this double font sequence gives us the best of both worlds:
  # man(1) shows it in bold and `groff -Thtml` shows it in monospace
  "\\fB\\fC#{code}\\fR"
end
double_emphasis(text) click to toggle source
# File lib/md2man/roff.rb, line 149
def double_emphasis text
  "\\fB#{text}\\fP"
end
emphasis(text) click to toggle source
# File lib/md2man/roff.rb, line 145
def emphasis text
  "\\fI#{text}\\fP"
end
entity(text) click to toggle source
# File lib/md2man/roff.rb, line 201
def entity text
  if unicode = entity_to_unicode(text)
    unicode_to_glyph unicode
  else
    warn "md2man/roff: entity not implemented: #{text.inspect}"
  end
end
header(text, level, _=nil) click to toggle source
# File lib/md2man/roff.rb, line 58
def header text, level, _=nil
  macro =
    case level
    when 1
      if @h1_seen
        :SH
      else
        @h1_seen = true
        :TH
      end
    when 2 then :SH
    else :SS
    end
  "\n.#{macro} #{text.chomp}\n"
end
hrule() click to toggle source
# File lib/md2man/roff.rb, line 74
def hrule
  "\n.ti 0\n\\l'\\n(.lu'\n"
end
image(link, title, alt_text) click to toggle source
# File lib/md2man/roff.rb, line 185
def image link, title, alt_text
  warn "md2man/roff: image not implemented: #{link.inspect}"
end
indented_paragraph(text) click to toggle source
# File lib/md2man/roff.rb, line 33
def indented_paragraph text
  "\n.IP\n#{text}\n"
end
linebreak() click to toggle source
# File lib/md2man/roff.rb, line 141
def linebreak
  "\n.br\n"
end
list(contents, list_type) click to toggle source
# File lib/md2man/roff.rb, line 78
def list contents, list_type
  result = []

  if list_type == :ordered
    result << ".nr step#{@ordered_list_id} 0 1"
    contents.gsub!(/^\.IP \\n\+\[step_tbd\]$/, ".IP \\n+[step#{@ordered_list_id}]")
    @ordered_list_id += 1
  end

  result << ".RS\n#{contents}\n.RE\n"
  result.join("\n")
end
list_item(text, list_type) click to toggle source
# File lib/md2man/roff.rb, line 91
def list_item text, list_type
  designator =
    case list_type
    when :ordered
      "\\n+[step_tbd]"
    when :unordered
      "\\(bu 2"
    end

  ".IP #{designator}\n#{remove_leading_pp(text).lstrip.chomp}\n"
end
normal_paragraph(text) click to toggle source
# File lib/md2man/roff.rb, line 41
def normal_paragraph text
  "\n.PP\n#{text}\n"
end
normal_text(text) click to toggle source
# File lib/md2man/roff.rb, line 197
def normal_text text
  escape text, false if text
end
postprocess(document) click to toggle source
Calls superclass method Md2Man::Document#postprocess
# File lib/md2man/roff.rb, line 18
def postprocess document
  super.

  # strip newlines from the beginning, before the very first roff directive
  lstrip.

  # squeeze newlines between roff directives to prevent double-spaced output
  # and also at the end of the document, after the very last roff directive
  gsub(/(\n){2,}(?=\.|\z)/, '\1')
end
preprocess(document) click to toggle source
Calls superclass method Md2Man::Document#preprocess
# File lib/md2man/roff.rb, line 11
def preprocess document
  @ordered_list_id = 0
  @table_cells = {}
  @h1_seen = false
  super
end
raw_html(html) click to toggle source
# File lib/md2man/roff.rb, line 189
def raw_html html
  warn "md2man/roff: raw_html not implemented: #{html.inspect}"
end
reference(input_match, output_match) click to toggle source
# File lib/md2man/roff.rb, line 137
def reference input_match, output_match
  "\n.BR #{input_match[:page]} (#{input_match[:section]})#{output_match[:addendum]}\n"
end
strikethrough(text) click to toggle source
# File lib/md2man/roff.rb, line 157
def strikethrough text
  warn "md2man/roff: strikethrough not implemented: #{text.inspect}"
end
superscript(text) click to toggle source
# File lib/md2man/roff.rb, line 161
def superscript text
  warn "md2man/roff: superscript not implemented: #{text.inspect}"
end
table(header, body) click to toggle source
# File lib/md2man/roff.rb, line 103
def table header, body
  head_rows = decode_table_rows(header)
  body_rows = decode_table_rows(body)

  ".TS\nallbox;\n#{
    [
      head_rows.map do |row|
        (['cb'] * row.length).join(TABLE_COL_DELIM)
      end,
      body_rows.map do |row|
        row.map do |content, alignment|
          (alignment || :left).to_s[0,1]
        end.join(TABLE_COL_DELIM)
      end
    ].join(TABLE_ROW_DELIM)
  }\n.\n#{
    (head_rows + body_rows).map do |row|
      row.map(&:first).join(TABLE_CELL_DELIM)
    end.join(TABLE_ROW_DELIM)
  }\n.TE\n"
end
table_cell(content, alignment) click to toggle source
# File lib/md2man/roff.rb, line 129
def table_cell content, alignment
  encode_table_cell [content, alignment]
end
table_row(content) click to toggle source
# File lib/md2man/roff.rb, line 125
def table_row content
  encode_table_row content
end
tagged_paragraph(text) click to toggle source
# File lib/md2man/roff.rb, line 37
def tagged_paragraph text
  "\n.TP\n#{text}\n"
end
triple_emphasis(text) click to toggle source
# File lib/md2man/roff.rb, line 153
def triple_emphasis text
  "\\s+2#{double_emphasis text}\\s-2"
end

Private Instance Methods

decode_table_rows(rows) click to toggle source
# File lib/md2man/roff.rb, line 233
def decode_table_rows rows
  rows.split(TABLE_ROW_DELIM).map do |row|
    row.split(TABLE_CELL_DELIM).map do |cell|
      @table_cells.delete cell
    end
  end
end
encode_table_cell(cell) click to toggle source
# File lib/md2man/roff.rb, line 245
def encode_table_cell cell
  key = encode(cell)
  @table_cells[key] = cell
  key + TABLE_CELL_DELIM
end
encode_table_row(row) click to toggle source
# File lib/md2man/roff.rb, line 241
def encode_table_row row
  row + TABLE_ROW_DELIM
end
entity_to_unicode(entity) click to toggle source
# File lib/md2man/roff.rb, line 251
def entity_to_unicode entity
  if ENTITY_TO_UNICODE.key? entity
    ENTITY_TO_UNICODE[entity]
  elsif entity =~ /^&#(\d+);$/
    $1.to_i
  elsif entity =~ /^&#x(\h+);$/
    $1.to_i(16)
  end
end
escape(text, literally) click to toggle source
# File lib/md2man/roff.rb, line 211
def escape text, literally
  text.

  # escape backslashes so that they appear in the printable output
  gsub('\\', literally ? '\&\&' : '\\[rs]').

  # escape soft-hyphens so that they appear in the printable output
  gsub('-', '\\-').

  # escape line-beginning control characters (period and single quote)
  # by prefixing a non-printable, zero-width glyph (backslash ampersand)
  gsub(/^(?=[.'])/, '\\\\&')
end
remove_leading_pp(text) click to toggle source
# File lib/md2man/roff.rb, line 225
def remove_leading_pp text
  text.sub(/\A\n\.PP\n/, '')
end
unicode_to_glyph(unicode) click to toggle source
# File lib/md2man/roff.rb, line 261
def unicode_to_glyph unicode
  if UNICODE_TO_GLYPH.key? unicode
    UNICODE_TO_GLYPH[unicode]
  elsif unicode < 256
    '\\[char%d]' % unicode
  else
    '\\[u%04x]' % unicode
  end
end