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 + (" " * (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