lib/fdoc.fy in fancy-0.7.0 vs lib/fdoc.fy in fancy-0.8.0

- old
+ new

@@ -1,11 +1,14 @@ # Load all of fancy. +require: "rbx/documentation" +require: "fdoc_hook" require: "boot" +require: "option_parser" +require: "fancy_spec" class Fancy FDoc { """ - FDoc is a tool to generate API documentation from Fancy source. Works as follows: 1. We setup a handler to be invoked every time an object is set documentation @@ -16,45 +19,86 @@ which can possibly load any file/directory you specify and optionally run specs, effectively associating them with documented objects. 4. Generate output file. Currently the plan is to output a json formatted object. To be loaded by an html file and use jquery to build a GUI from it. - """ OUTPUT_DIR = "doc/api/" + FANCY_ROOT_DIR = __FILE__ relative_path: "../" def self main { """ - FDoc will load all .fy files you give to it, and optionally run - any specified FancySpec, and later produce documentation output. + FDoc will load all .fy files you give to it, and optionally run + any specified FancySpec, and later produce documentation output. """ output_dir = OUTPUT_DIR - ARGV for_option: "-o" do: |d| { output_dir = d } + with_stdlib = false + add_github_links = false + github_repo = "bakkdoor/fancy" + + OptionParser new: @{ + remove_after_parsed: true + banner: "Usage: fdoc [options] [source_files]\nOptions:" + + with: "-o [output_dir]" doc: "Sets output directory of generated documentation page, defaults to #{output_dir}" do: |dir| { + output_dir = dir + } + + with: "-github-repo [repo_url]" doc: "Sets the Github repository to link to method definitions. Example: -github-repo bakkdoor/redis.fy" do: |url| { + github_repo = url + add_github_links = true + } + + with: "--with-stdlib" doc: "Include Fancy's standard library in generated documentation" do: { + with_stdlib = true + } + } . parse: ARGV + + output_dir = File absolute_path: output_dir . + "/" + require("fileutils") FileUtils mkdir_p(output_dir) + # check if we're in Fancy's root dir + # if not, copy fdoc related files over to output_dir + if: (output_dir relative_path: "../" == FANCY_ROOT_DIR) then: { + # add stdlib by default when in FANCY_ROOT_DIR + with_stdlib = true + add_github_links = true + } else: { + files = Dir list: "#{FANCY_ROOT_DIR}/doc/api/*" . reject: |f| { f =~ /fancy\.jsonp$/ } + FileUtils cp(files, output_dir) + } + + if: with_stdlib then: { + @objects_to_remove = <[]> + } else: { + @objects_to_remove = @documented_objects dup + } + # Currently we just load any files given on ARGV. ARGV each: |file| { Fancy CodeLoader load_compiled_file(file) } + @documented_objects = @documented_objects select_keys: |k| { @objects_to_remove includes?: k . not } + # by now simply produce a apidoc/fancy.jsonp file. - json = JSON new: @documented_objects + json = JSON new: @documented_objects add_github_links: add_github_links github_repo: github_repo json write: (File expand_path("fancy.jsonp", output_dir)) - ["Open your browser at " ++ output_dir ++ "index.html.", + ["Open your browser at " ++ output_dir ++ "index.html ", " " ++ (json classes size) ++ " classes. ", " " ++ (json methods size) ++ " methods. ", " " ++ (json objects size) ++ " other objects. "] println } class JSON { - read_slots: ['classes, 'methods, 'blocks, 'objects] - def initialize: documented { + def initialize: documented add_github_links: @add_github_links github_repo: @github_repo { @documented_objects = documented is_class = |o| { o kind_of?: Module } is_method = |o| { o kind_of?: Rubinius CompiledMethod } is_block = |o| { o kind_of?: Rubinius BlockEnvironment } @@ -66,13 +110,18 @@ @methods = @documented_objects keys select: is_method @blocks = @documented_objects keys select: is_block @objects = @documented_objects keys select: all_other } - def string_to_json: obj { obj to_s inspect } - def symbol_to_json: obj { obj to_s } + def string_to_json: obj { + obj to_s inspect + } + def symbol_to_json: obj { + obj to_s + } + def array_to_json: obj { str = ["["] obj each: |i| { str << $ to_json: i } in_between: { str << ", " } str << ["]"] str join @@ -123,11 +172,11 @@ relative_file = relative_file to_s gsub(/.*lib/, "lib") lines = exec lines() to_a() mattr['file]: $ relative_file # TODO calculate line numbers from compiled method # right now we only use the first line of code in the body. - mattr['lines]: $ [lines[3], lines[3]] + mattr['lines]: $ [exec definition_line, exec last_line] } attr[(type ++ "s") intern()] [n]: mattr } } @@ -168,42 +217,38 @@ } map } - def write: filename call: name ("fancy.fdoc") { map = generate_map json = to_json: map - js = "(function() { " ++ name ++ "(" ++ json ++ "); })();" + js = "(function() { #{name}(#{@add_github_links}, #{@github_repo inspect}, #{json}); })();" File open: filename modes: ['write] with: |out| { out print: js } } - } - class Formatter { """ A documentation formater intended to be used by @FDoc@. This formatter makes some transformations on a docstring and then converts it to html using markdown. """ Fancy Documentation formatter: 'fdoc is: |d| { format: d } - def self format: doc { str = doc to_s tags = <[ ]> str = str skip_leading_indentation str = remove_tags: str into: tags str = create_tags: str with: tags str = create_class_references: str str = create_method_references: str - str = create_code: str str = htmlize: str + str = create_code: str str } def self create_class_references: str { """ @@ -238,10 +283,11 @@ @Fancy::Package::Installer#initialize:version:install_path:@ A singleton method: @Fancy::FDoc::Formatter~format:@ """ + str gsub(/@[A-Z][^\r\n\s]+?@/) |cstr| { names = cstr slice(1, cstr size() - 2) split("::") refs = [] names each_with_index() |name, idx| { n = name split(/[\#\~]/) @@ -294,22 +340,39 @@ } ary compact join("\n") } def self create_tags: str with: map { + max_width = map map: @{ first size } . max tags = map map: |pair| { name = pair[0] value = pair[1] - "<div class=\"doctag\"><label> @" ++ name ++ . - " </label><div>" ++ value ++ "</div></div>" + # make argument names all align nicely: + name = name + ("&nbsp;" * (max_width - (name size))) + "<div class=\"doctag\"><label> @#{name} </label><div>#{value}</div></div>" } str ++ "\n<div class=\"doctags\">" ++ (tags join()) ++ "</div>" } def self create_code: str { - str gsub(/@([^\s,\]\)\{\}\.]+)/, - "<code data-lang=\"fancy\">\\1</code>") + md = /<pre>/ match: str + if: md then: { + md = /<pre>/ match: str + pre_code = md pre_match + md = /</pre>/ match: $ md post_match + code, post_code = md pre_match, md post_match + + pre_code = pre_code gsub(/@([^\s,@\]\)\{\}\.]+)/, + "<code data-lang=\"fancy\">\\1</code>") + post_code = post_code gsub(/@([^\s,@\]\)\{\}\.]+)/, + "<code data-lang=\"fancy\">\\1</code>") + + "#{pre_code}<pre>#{code}</pre>#{post_code}" + } else: { + str gsub(/@([^\s,@\]\)\{\}\.]+)/, + "<code data-lang=\"fancy\">\\1</code>") + } } def self htmlize: str { require("rubygems") require("rdiscount") @@ -322,11 +385,9 @@ "<code data-lang=\"fancy\" data-method=\"\\1\" class=\"selectable\">\\1</code>") . # fancy methods starting with : (argless fancy methods) gsub(/@:([a-z_]+)@/, "<code data-lang=\"fancy\" data-method=\":\\1\" class=\"selectable\">\\1</code>") } - } - } Fancy FDoc main