class RDoc::Markup::PreProcess

处理文本块中可能出现的常见指令

:include: filename

可以通过在指令前加上反斜杠来转义指令。

RDoc 插件作者可以使用 RDoc::Markup::PreProcess::register 注册要处理的其他指令。

任何不是 RDoc 内置的指令(包括通过插件注册的指令)都将存储在附加注释的 CodeObject 的元数据哈希中。 有关内置指令列表,请参阅RDoc::Markup 中的指令

属性

options[RW]

一个 RDoc::Options 实例,将用指令中的覆盖信息填充

公共类方法

new(input_file_name, include_path) 点击以切换源代码

input_file_name 创建一个新的预处理器,该预处理器将在 include_path 中查找包含的文件

# File rdoc/markup/pre_process.rb, line 78
def initialize(input_file_name, include_path)
  @input_file_name = input_file_name
  @include_path = include_path
  @options = nil
end
post_process(&block) 点击以切换源代码

为指令添加一个后处理处理程序。 该处理程序将使用结果 RDoc::Comment (或文本字符串) 和注释的代码对象(如果有)调用。

# File rdoc/markup/pre_process.rb, line 30
def self.post_process &block
  @post_processors << block
end
post_processors() 点击以切换源代码

注册的后处理程序

# File rdoc/markup/pre_process.rb, line 37
def self.post_processors
  @post_processors
end
register(directive, &block) 点击以切换源代码

directive 注册为 RDoc 处理的指令。 如果给出了一个代码块,则该指令将被该代码块的结果替换,否则该指令将从处理的文本中删除。

将使用指令名称和指令参数调用该代码块

RDoc::Markup::PreProcess.register 'my-directive' do |directive, param|
  # replace text, etc.
end
# File rdoc/markup/pre_process.rb, line 53
def self.register directive, &block
  @registered[directive] = block
end
registered() 点击以切换源代码

注册的指令

# File rdoc/markup/pre_process.rb, line 60
def self.registered
  @registered
end
reset() 点击以切换源代码

清除所有已注册的指令和后处理程序

# File rdoc/markup/pre_process.rb, line 67
def self.reset
  @post_processors = []
  @registered = {}
end

公共实例方法

find_include_file(name) 点击以切换源代码

在包含当前文件的目录中查找给定文件,然后在 RDOC_INCLUDE 路径中指定的每个目录中查找

# File rdoc/markup/pre_process.rb, line 308
def find_include_file(name)
  to_search = [File.dirname(@input_file_name)].concat @include_path
  to_search.each do |dir|
    full_name = File.join(dir, name)
    stat = File.stat(full_name) rescue next
    return full_name if stat.readable?
  end
  nil
end
handle(text, code_object = nil, &block) 点击以切换源代码

在给定的 text 中查找指令。

我们不处理的选项将被产生。 如果代码块返回 false,则该指令将恢复到文本。 如果代码块返回 nil 或未给出代码块,则根据注册的指令处理该指令。 如果返回 String,则该指令将替换为该字符串。

如果没有注册匹配的指令,则该指令将恢复到文本。

如果给出了 code_object 并且该指令未知,则该指令的参数将设置为 code_object 上的元数据。 有关详细信息,请参阅RDoc::CodeObject#metadata

# File rdoc/markup/pre_process.rb, line 99
def handle text, code_object = nil, &block
  first_line = 1
  if RDoc::Comment === text then
    comment = text
    text = text.text
    first_line = comment.line || 1
  end

  # regexp helper (square brackets for optional)
  # $1      $2  $3        $4      $5
  # [prefix][\]:directive:[spaces][param]newline
  text = text.lines.map.with_index(first_line) do |line, num|
    next line unless line =~ /\A([ \t]*(?:#|\/?\*)?[ \t]*)(\\?):([\w-]+):([ \t]*)(.+)?(\r?\n|$)/
    # skip something like ':toto::'
    next $& if $4.empty? and $5 and $5[0, 1] == ':'

    # skip if escaped
    next "#$1:#$3:#$4#$5\n" unless $2.empty?

    # This is not in handle_directive because I didn't want to pass another
    # argument into it
    if comment and $3 == 'markup' then
      next "#{$1.strip}\n" unless $5
      comment.format = $5.downcase
      next "#{$1.strip}\n"
    end

    handle_directive $1, $3, $5, code_object, text.encoding, num, &block
  end.join

  if comment then
    comment.text = text
  else
    comment = text
  end

  self.class.post_processors.each do |handler|
    handler.call comment, code_object
  end

  text
end
handle_directive(prefix, directive, param, code_object = nil, encoding = nil, line = nil) { |directive, param, line| ... } 点击以切换源代码

执行 directive 及其参数 param 描述的操作。

code_object 用于对类或模块进行操作的指令。 prefix 用于确保处理的指令的替换是正确的。 encoding 用于 include 指令。

有关 RDoc 中的指令列表,请参阅 RDoc::Markup

# File rdoc/markup/pre_process.rb, line 153
  def handle_directive prefix, directive, param, code_object = nil,
                       encoding = nil, line = nil
    blankline = "#{prefix.strip}\n"
    directive = directive.downcase

    case directive
    when 'arg', 'args' then
      return "#{prefix}:#{directive}: #{param}\n" unless code_object && code_object.kind_of?(RDoc::AnyMethod)

      code_object.params = param

      blankline
    when 'category' then
      if RDoc::Context === code_object then
        section = code_object.add_section param
        code_object.temporary_section = section
      elsif RDoc::AnyMethod === code_object then
        code_object.section_title = param
      end

      blankline # ignore category if we're not on an RDoc::Context
    when 'doc' then
      return blankline unless code_object
      code_object.document_self = true
      code_object.force_documentation = true

      blankline
    when 'enddoc' then
      return blankline unless code_object
      code_object.done_documenting = true

      blankline
    when 'include' then
      filename = param.split(' ', 2).first
      include_file filename, prefix, encoding
    when 'main' then
      @options.main_page = param if @options.respond_to? :main_page
      warn <<~MSG
        The :main: directive is deprecated and will be removed in RDoc 7.

        You can use these options to specify the initial page displayed instead:
        - `--main=#{param}` via the command line
        - `rdoc.main = "#{param}"` if you use `RDoc::Task`
        - `main_page: #{param}` in your `.rdoc_options` file
      MSG

      blankline
    when 'nodoc' then
      return blankline unless code_object
      code_object.document_self = nil # notify nodoc
      code_object.document_children = param !~ /all/i

      blankline
    when 'notnew', 'not_new', 'not-new' then
      return blankline unless RDoc::AnyMethod === code_object

      code_object.dont_rename_initialize = true

      blankline
    when 'startdoc' then
      return blankline unless code_object

      code_object.start_doc
      code_object.force_documentation = true

      blankline
    when 'stopdoc' then
      return blankline unless code_object

      code_object.stop_doc

      blankline
    when 'title' then
      @options.default_title = param if @options.respond_to? :default_title=

      warn <<~MSG
        The :title: directive is deprecated and will be removed in RDoc 7.

        You can use these options to specify the title displayed instead:
        - `--title=#{param}` via the command line
        - `rdoc.title = "#{param}"` if you use `RDoc::Task`
        - `title: #{param}` in your `.rdoc_options` file
      MSG

      blankline
    when 'yield', 'yields' then
      return blankline unless code_object
      # remove parameter &block
      code_object.params = code_object.params.sub(/,?\s*&\w+/, '') if code_object.params

      code_object.block_params = param || ''

      blankline
    else
      result = yield directive, param, line if block_given?

      case result
      when nil then
        code_object.metadata[directive] = param if code_object

        if RDoc::Markup::PreProcess.registered.include? directive then
          handler = RDoc::Markup::PreProcess.registered[directive]
          result = handler.call directive, param if handler
        else
          result = "#{prefix}:#{directive}: #{param}\n"
        end
      when false then
        result = "#{prefix}:#{directive}: #{param}\n"
      end

      result
    end
  end
include_file(name, indent, encoding) 点击以切换源代码

处理 :include: filename 指令。

如果包含文件的第一行以“#”开头,并且包含 “coding:” 或 “coding=” 形式的编码信息,则将其删除。

如果包含文件中的所有行都以“#”开头,则在包含之前删除该前导“#”。 包含的内容会像 :include: 指令一样缩进。

# File rdoc/markup/pre_process.rb, line 282
def include_file name, indent, encoding
  full_name = find_include_file name

  unless full_name then
    warn "Couldn't find file to include '#{name}' from #{@input_file_name}"
    return ''
  end

  content = RDoc::Encoding.read_file full_name, encoding, true
  content = RDoc::Encoding.remove_magic_comment content

  # strip magic comment
  content = content.sub(/\A# .*coding[=:].*$/, '').lstrip

  # strip leading '#'s, but only if all lines start with them
  if content =~ /^[^#]/ then
    content.gsub(/^/, indent)
  else
    content.gsub(/^#?/, indent)
  end
end