textadeptdoc.rb 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. # Copyright 2007-2017 Mitchell mitchell.att.foicica.com. See LICENSE.
  2. require 'rdoc/generator'
  3. ##
  4. # Textadept format for RDoc.
  5. # This class is used by RDoc to create an Textadept autocompletions and
  6. # documentation for Ruby with a "fake" ctags file and an api file.
  7. # In addition to the normal ctags kinds for Ruby, the kind 'C' is recognized as
  8. # a constant and 'a' as an attribute.
  9. #
  10. # Requires Ruby 1.9.
  11. #
  12. # Install this file to your `rdoc/generator/` folder and add it to the bottom of
  13. # `rdoc/rdoc.rb`.
  14. #
  15. # Usage: rdoc -f textadept [files]
  16. # Two files are generated in the output directory: `tags` and `api`.
  17. class RDoc::Generator::TEXTADEPT
  18. CTAGS_FMT = "%s\t_\t0;\"\t%s\t%s\n"
  19. RDoc::RDoc.add_generator self
  20. def self.for(options) new(options) end
  21. def initialize(options)
  22. @options = options
  23. @generated = {}
  24. @tags = File.new(options.op_dir + '/tags', 'wb')
  25. @api = File.new(options.op_dir + '/api', 'wb')
  26. end
  27. ##
  28. # Called by RDoc to process context objects.
  29. def generate(toplevels)
  30. RDoc::TopLevel.all_classes_and_modules.each { |c| process_context c }
  31. @tags.close
  32. @api.close
  33. end
  34. ##
  35. # Process the context.
  36. # @param context The RDoc context to process.
  37. def process_context(context)
  38. ext_fields = Array.new
  39. # Determine inheritence (if any).
  40. inherits = Array.new
  41. superclass = context.superclass unless context.module?
  42. inherits << superclass unless superclass.nil? or superclass !~ /^[\w:]+$/
  43. context.includes.each { |i| inherits << i.full_name }
  44. inherits << 'Object' unless inherits.include?('Object')
  45. ext_fields << 'inherits:' + inherits.join(',') unless inherits.empty?
  46. # Determine the parent class/module (if any).
  47. parent = (context.full_name.scan(/^.+::/).first || '')[0...-2]
  48. #ext_fields << 'class:' + parent unless parent.empty?
  49. # Write the ctag.
  50. write_tag(@tags, context.full_name, context.module? ? 'm' : 'c', ext_fields)
  51. write_tag(@tags, context.name, 'C', 'class:' + parent) unless parent.empty?
  52. # Write ctags for all methods.
  53. context.each_method do |m|
  54. next if m.name !~ /^\w/
  55. ext_fields = 'class:' + context.full_name
  56. ext_fields += ',' + inherits.join(',') unless inherits.empty?
  57. write_tag(@tags, m.name, 'f', ext_fields)
  58. write_method_apidoc(@api, context, m)
  59. end
  60. # Write ctags for all constants.
  61. context.each_constant do |c|
  62. ext_fields = 'class:' + context.full_name
  63. ext_fields = '' if context.full_name.to_sym == :Object
  64. write_tag(@tags, c.name, 'C', ext_fields)
  65. end
  66. # Write ctags for all attributes.
  67. context.each_attribute do |a|
  68. write_tag(@tags, a.name, 'a', 'class:' + context.full_name)
  69. end
  70. end
  71. ##
  72. # Writes a ctag.
  73. # @param file The file to write to.
  74. # @param name The name of the tag.
  75. # @param k The kind of ctag. This generator uses 5 kinds: m Module, c Class,
  76. # f Method, C Constant, a Attribute.
  77. # @param ext_fields The ext_fields for the ctag.
  78. def write_tag(file, name, k, ext_fields)
  79. ext_fields = ext_fields.join("\t") if ext_fields.class == Array
  80. file << sprintf(CTAGS_FMT, name, k, ext_fields)
  81. end
  82. ##
  83. # Returns a formatted comment.
  84. # @param comment The comment to format.
  85. def format(comment)
  86. return comment.gsub(/^\s*#+/, '').gsub(/<\/?code>/, '`').
  87. gsub("\\n", "\\\\\\\\n")
  88. end
  89. ##
  90. # Write a method apidoc.
  91. # @param file The file to write to.
  92. # @param c The RDoc class object.
  93. # @param m The RDoc method object.
  94. def write_method_apidoc(file, c, m)
  95. doc = %x(
  96. fmt -s -w 80 <<"EOF"
  97. #{c.full_name + '.' + m.name + m.params}
  98. #{format(m.comment)}
  99. EOF).gsub("\n", "\\\\n")
  100. file << m.name + ' ' + doc << "\n"
  101. end
  102. end