diff options
Diffstat (limited to 'examples/redis-unstable/utils/generate-module-api-doc.rb')
| -rwxr-xr-x | examples/redis-unstable/utils/generate-module-api-doc.rb | 195 |
1 files changed, 0 insertions, 195 deletions
diff --git a/examples/redis-unstable/utils/generate-module-api-doc.rb b/examples/redis-unstable/utils/generate-module-api-doc.rb deleted file mode 100755 index cd45c93..0000000 --- a/examples/redis-unstable/utils/generate-module-api-doc.rb +++ /dev/null | |||
| @@ -1,195 +0,0 @@ | |||
| 1 | #!/usr/bin/env ruby | ||
| 2 | # coding: utf-8 | ||
| 3 | # gendoc.rb -- Converts the top-comments inside module.c to modules API | ||
| 4 | # reference documentation in markdown format. | ||
| 5 | |||
| 6 | # Convert the C comment to markdown | ||
| 7 | def markdown(s) | ||
| 8 | s = s.gsub(/\*\/$/,"") | ||
| 9 | s = s.gsub(/^ ?\* ?/,"") | ||
| 10 | s = s.gsub(/^\/\*\*? ?/,"") | ||
| 11 | s.chop! while s[-1] == "\n" || s[-1] == " " | ||
| 12 | lines = s.split("\n") | ||
| 13 | newlines = [] | ||
| 14 | # Fix some markdown | ||
| 15 | lines.each{|l| | ||
| 16 | # Rewrite RM_Xyz() to RedisModule_Xyz(). | ||
| 17 | l = l.gsub(/(?<![A-Z_])RM_(?=[A-Z])/, 'RedisModule_') | ||
| 18 | # Fix more markdown, except in code blocks indented by 4 spaces, which we | ||
| 19 | # don't want to mess with. | ||
| 20 | if not l.start_with?(' ') | ||
| 21 | # Add backquotes around RedisModule functions and type where missing. | ||
| 22 | l = l.gsub(/(?<!`)RedisModule[A-z]+(?:\*?\(\))?/){|x| "`#{x}`"} | ||
| 23 | # Add backquotes around c functions like malloc() where missing. | ||
| 24 | l = l.gsub(/(?<![`A-z.])[a-z_]+\(\)/, '`\0`') | ||
| 25 | # Add backquotes around macro and var names containing underscores. | ||
| 26 | l = l.gsub(/(?<![`A-z\*])[A-Za-z]+_[A-Za-z0-9_]+/){|x| "`#{x}`"} | ||
| 27 | # Link URLs preceded by space or newline (not already linked) | ||
| 28 | l = l.gsub(/(^| )(https?:\/\/[A-Za-z0-9_\/\.\-]+[A-Za-z0-9\/])/, | ||
| 29 | '\1[\2](\2)') | ||
| 30 | # Replace double-dash with unicode ndash | ||
| 31 | l = l.gsub(/ -- /, ' – ') | ||
| 32 | end | ||
| 33 | # Link function names to their definition within the page | ||
| 34 | l = l.gsub(/`(RedisModule_[A-z0-9]+)[()]*`/) {|x| | ||
| 35 | $index[$1] ? "[#{x}](\##{$1})" : x | ||
| 36 | } | ||
| 37 | newlines << l | ||
| 38 | } | ||
| 39 | return newlines.join("\n") | ||
| 40 | end | ||
| 41 | |||
| 42 | # Linebreak a prototype longer than 80 characters on the commas, but only | ||
| 43 | # between balanced parentheses so that we don't linebreak args which are | ||
| 44 | # function pointers, and then aligning each arg under each other. | ||
| 45 | def linebreak_proto(proto, indent) | ||
| 46 | if proto.bytesize <= 80 | ||
| 47 | return proto | ||
| 48 | end | ||
| 49 | parts = proto.split(/,\s*/); | ||
| 50 | if parts.length == 1 | ||
| 51 | return proto; | ||
| 52 | end | ||
| 53 | align_pos = proto.index("(") + 1; | ||
| 54 | align = " " * align_pos | ||
| 55 | result = parts.shift; | ||
| 56 | bracket_balance = 0; | ||
| 57 | parts.each{|part| | ||
| 58 | if bracket_balance == 0 | ||
| 59 | result += ",\n" + indent + align | ||
| 60 | else | ||
| 61 | result += ", " | ||
| 62 | end | ||
| 63 | result += part | ||
| 64 | bracket_balance += part.count("(") - part.count(")") | ||
| 65 | } | ||
| 66 | return result; | ||
| 67 | end | ||
| 68 | |||
| 69 | # Given the source code array and the index at which an exported symbol was | ||
| 70 | # detected, extracts and outputs the documentation. | ||
| 71 | def docufy(src,i) | ||
| 72 | m = /RM_[A-z0-9]+/.match(src[i]) | ||
| 73 | name = m[0] | ||
| 74 | name = name.sub("RM_","RedisModule_") | ||
| 75 | proto = src[i].sub("{","").strip+";\n" | ||
| 76 | proto = proto.sub("RM_","RedisModule_") | ||
| 77 | proto = linebreak_proto(proto, " "); | ||
| 78 | # Add a link target with the function name. (We don't trust the exact id of | ||
| 79 | # the generated one, which depends on the Markdown implementation.) | ||
| 80 | puts "<span id=\"#{name}\"></span>\n\n" | ||
| 81 | puts "### `#{name}`\n\n" | ||
| 82 | puts " #{proto}\n" | ||
| 83 | puts "**Available since:** #{$since[name] or "unreleased"}\n\n" | ||
| 84 | comment = "" | ||
| 85 | while true | ||
| 86 | i = i-1 | ||
| 87 | comment = src[i]+comment | ||
| 88 | break if src[i] =~ /\/\*/ | ||
| 89 | end | ||
| 90 | comment = markdown(comment) | ||
| 91 | puts comment+"\n\n" | ||
| 92 | end | ||
| 93 | |||
| 94 | # Print a comment from line until */ is found, as markdown. | ||
| 95 | def section_doc(src, i) | ||
| 96 | name = get_section_heading(src, i) | ||
| 97 | comment = "<span id=\"#{section_name_to_id(name)}\"></span>\n\n" | ||
| 98 | while true | ||
| 99 | # append line, except if it's a horizontal divider | ||
| 100 | comment = comment + src[i] if src[i] !~ /^[\/ ]?\*{1,2} ?-{50,}/ | ||
| 101 | break if src[i] =~ /\*\// | ||
| 102 | i = i+1 | ||
| 103 | end | ||
| 104 | comment = markdown(comment) | ||
| 105 | puts comment+"\n\n" | ||
| 106 | end | ||
| 107 | |||
| 108 | # generates an id suitable for links within the page | ||
| 109 | def section_name_to_id(name) | ||
| 110 | return "section-" + | ||
| 111 | name.strip.downcase.gsub(/[^a-z0-9]+/, '-').gsub(/^-+|-+$/, '') | ||
| 112 | end | ||
| 113 | |||
| 114 | # Returns the name of the first section heading in the comment block for which | ||
| 115 | # is_section_doc(src, i) is true | ||
| 116 | def get_section_heading(src, i) | ||
| 117 | if src[i] =~ /^\/\*\*? \#+ *(.*)/ | ||
| 118 | heading = $1 | ||
| 119 | elsif src[i+1] =~ /^ ?\* \#+ *(.*)/ | ||
| 120 | heading = $1 | ||
| 121 | end | ||
| 122 | return heading.gsub(' -- ', ' – ') | ||
| 123 | end | ||
| 124 | |||
| 125 | # Returns true if the line is the start of a generic documentation section. Such | ||
| 126 | # section must start with the # symbol, i.e. a markdown heading, on the first or | ||
| 127 | # the second line. | ||
| 128 | def is_section_doc(src, i) | ||
| 129 | return src[i] =~ /^\/\*\*? \#/ || | ||
| 130 | (src[i] =~ /^\/\*/ && src[i+1] =~ /^ ?\* \#/) | ||
| 131 | end | ||
| 132 | |||
| 133 | def is_func_line(src, i) | ||
| 134 | line = src[i] | ||
| 135 | return line =~ /RM_/ && | ||
| 136 | line[0] != ' ' && line[0] != '#' && line[0] != '/' && | ||
| 137 | src[i-1] =~ /\*\// | ||
| 138 | end | ||
| 139 | |||
| 140 | puts "<!-- This file is generated from module.c using\n" | ||
| 141 | puts " redis/redis:utils/generate-module-api-doc.rb -->\n\n" | ||
| 142 | src = File.open(File.dirname(__FILE__) ++ "/../src/module.c").to_a | ||
| 143 | |||
| 144 | # Build function index | ||
| 145 | $index = {} | ||
| 146 | src.each_with_index do |line,i| | ||
| 147 | if is_func_line(src, i) | ||
| 148 | line =~ /RM_([A-z0-9]+)/ | ||
| 149 | name = "RedisModule_#{$1}" | ||
| 150 | $index[name] = true | ||
| 151 | end | ||
| 152 | end | ||
| 153 | |||
| 154 | # Populate the 'since' map (name => version) if we're in a git repo. | ||
| 155 | $since = {} | ||
| 156 | git_dir = File.dirname(__FILE__) ++ "/../.git" | ||
| 157 | if File.directory?(git_dir) && `which git` != "" | ||
| 158 | `git --git-dir="#{git_dir}" tag --sort=v:refname`.each_line do |version| | ||
| 159 | next if version !~ /^(\d+)\.\d+\.\d+?$/ || $1.to_i < 4 | ||
| 160 | version.chomp! | ||
| 161 | `git --git-dir="#{git_dir}" cat-file blob "#{version}:src/module.c"`.each_line do |line| | ||
| 162 | if line =~ /^\w.*[ \*]RM_([A-z0-9]+)/ | ||
| 163 | name = "RedisModule_#{$1}" | ||
| 164 | if ! $since[name] | ||
| 165 | $since[name] = version | ||
| 166 | end | ||
| 167 | end | ||
| 168 | end | ||
| 169 | end | ||
| 170 | end | ||
| 171 | |||
| 172 | # Print TOC | ||
| 173 | puts "## Sections\n\n" | ||
| 174 | src.each_with_index do |_line,i| | ||
| 175 | if is_section_doc(src, i) | ||
| 176 | name = get_section_heading(src, i) | ||
| 177 | puts "* [#{name}](\##{section_name_to_id(name)})\n" | ||
| 178 | end | ||
| 179 | end | ||
| 180 | puts "* [Function index](#section-function-index)\n\n" | ||
| 181 | |||
| 182 | # Docufy: Print function prototype and markdown docs | ||
| 183 | src.each_with_index do |_line,i| | ||
| 184 | if is_func_line(src, i) | ||
| 185 | docufy(src, i) | ||
| 186 | elsif is_section_doc(src, i) | ||
| 187 | section_doc(src, i) | ||
| 188 | end | ||
| 189 | end | ||
| 190 | |||
| 191 | # Print function index | ||
| 192 | puts "<span id=\"section-function-index\"></span>\n\n" | ||
| 193 | puts "## Function index\n\n" | ||
| 194 | $index.keys.sort.each{|x| puts "* [`#{x}`](\##{x})\n"} | ||
| 195 | puts "\n" | ||
