tomdoc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.md +104 -0
- data/Rakefile +80 -0
- data/bin/tomdoc +6 -0
- data/lib/tomdoc.rb +25 -0
- data/lib/tomdoc/arg.rb +14 -0
- data/lib/tomdoc/cli.rb +150 -0
- data/lib/tomdoc/generator.rb +138 -0
- data/lib/tomdoc/generators/console.rb +68 -0
- data/lib/tomdoc/generators/html.rb +42 -0
- data/lib/tomdoc/method.rb +21 -0
- data/lib/tomdoc/scope.rb +46 -0
- data/lib/tomdoc/source_parser.rb +145 -0
- data/lib/tomdoc/tomdoc.rb +133 -0
- data/lib/tomdoc/version.rb +3 -0
- data/man/tomdoc.5 +320 -0
- data/man/tomdoc.5.html +285 -0
- data/man/tomdoc.5.ronn +203 -0
- data/test/console_generator_test.rb +20 -0
- data/test/fixtures/chimney.rb +711 -0
- data/test/fixtures/multiplex.rb +47 -0
- data/test/fixtures/simple.rb +10 -0
- data/test/generator_test.rb +47 -0
- data/test/helper.rb +21 -0
- data/test/html_generator_test.rb +18 -0
- data/test/source_parser_test.rb +66 -0
- data/test/tomdoc_parser_test.rb +127 -0
- metadata +143 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Tom Preston-Werner, Chris Wanstrath
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
Software), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
TomDoc
|
2
|
+
======
|
3
|
+
|
4
|
+
TomDoc is documentation for humans. Using a few simple rules and zero
|
5
|
+
special syntax you can produce great looking documentation for both humans
|
6
|
+
and machines.
|
7
|
+
|
8
|
+
Just follow these four easy steps:
|
9
|
+
|
10
|
+
1. Describe your method
|
11
|
+
2. Optionally list and describe its arguments
|
12
|
+
3. Optionally list some examples
|
13
|
+
4. Explain what your method returns
|
14
|
+
|
15
|
+
Like this:
|
16
|
+
|
17
|
+
# Duplicate some text an abitrary number of times.
|
18
|
+
#
|
19
|
+
# text - The String to be duplicated.
|
20
|
+
# count - The Integer number of times to duplicate the text.
|
21
|
+
#
|
22
|
+
# Examples
|
23
|
+
# multiplex('Tom', 4)
|
24
|
+
# # => 'TomTomTomTom'
|
25
|
+
#
|
26
|
+
# Returns the duplicated String.
|
27
|
+
def multiplex(text, count)
|
28
|
+
text * count
|
29
|
+
end
|
30
|
+
|
31
|
+
See [the manual][man] or [the spec][spec] for a more in-depth
|
32
|
+
analysis.
|
33
|
+
|
34
|
+
|
35
|
+
tomdoc.rb
|
36
|
+
---------
|
37
|
+
|
38
|
+
This repository contains tomdoc.rb, a Ruby library for parsing
|
39
|
+
TomDoc and generating pretty documentation from it.
|
40
|
+
|
41
|
+
|
42
|
+
Installation
|
43
|
+
------------
|
44
|
+
|
45
|
+
easy_install Pygments
|
46
|
+
gem install tomdoc
|
47
|
+
|
48
|
+
tomdoc.rb has been tested with Ruby 1.8.7.
|
49
|
+
|
50
|
+
|
51
|
+
Usage
|
52
|
+
-----
|
53
|
+
|
54
|
+
$ tomdoc file.rb
|
55
|
+
# Prints colored documentation of file.rb.
|
56
|
+
|
57
|
+
$ tomdoc file.rb -n STRING
|
58
|
+
# Prints methods or classes in file.rb matching STRING.
|
59
|
+
|
60
|
+
$ tomdoc fileA.rb fileB.rb ...
|
61
|
+
# Prints colored documentation of multiple files.
|
62
|
+
|
63
|
+
$ tomdoc -f html file.rb
|
64
|
+
# Prints HTML documentation of file.rb.
|
65
|
+
|
66
|
+
$ tomdoc -i file.rb
|
67
|
+
# Ignore TomDoc validation, print any methods we find.
|
68
|
+
|
69
|
+
$ tomdoc -h
|
70
|
+
# Displays more options.
|
71
|
+
|
72
|
+
|
73
|
+
Ruby API
|
74
|
+
--------
|
75
|
+
|
76
|
+
Fully TomDoc'd. Well, it will be.
|
77
|
+
|
78
|
+
For now:
|
79
|
+
|
80
|
+
$ tomdoc lib/tomdoc/source_parser.rb
|
81
|
+
|
82
|
+
|
83
|
+
Formats
|
84
|
+
-------
|
85
|
+
|
86
|
+
### Console
|
87
|
+
|
88
|
+
tomdoc lib/tomdoc/source_parser.rb -n token
|
89
|
+
|
90
|
+

|
91
|
+
|
92
|
+
### HTML
|
93
|
+
|
94
|
+
tomdoc -f html lib/tomdoc/source_parser.rb | browser
|
95
|
+
|
96
|
+
or
|
97
|
+
|
98
|
+
tomdoc -f html lib/tomdoc/source_parser.rb > doc.html
|
99
|
+
open doc.html
|
100
|
+
|
101
|
+

|
102
|
+
|
103
|
+
[man]: https://github.com/defunkt/tomdoc/blob/tomdoc.rb/man/tomdoc.5.ronn
|
104
|
+
[spec]: https://github.com/defunkt/tomdoc/blob/tomdoc.rb/tomdoc.md
|
data/Rakefile
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
def command?(command)
|
4
|
+
system("type #{command} > /dev/null 2>&1")
|
5
|
+
end
|
6
|
+
|
7
|
+
#
|
8
|
+
# Manual
|
9
|
+
#
|
10
|
+
|
11
|
+
if command? :ronn
|
12
|
+
desc "Build and display the manual."
|
13
|
+
task :man => "man:build" do
|
14
|
+
exec "man man/tomdoc.5"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Build and display the manual in your browser."
|
18
|
+
task "man:html" => "man:build" do
|
19
|
+
sh "open man/tomdoc.5.html"
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Build the manual"
|
23
|
+
task "man:build" do
|
24
|
+
sh "ronn -br5 --organization=MOJOMBO --manual='TomDoc Manual' man/*.ronn"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
#
|
30
|
+
# Tests
|
31
|
+
#
|
32
|
+
|
33
|
+
task :default => :test
|
34
|
+
|
35
|
+
if command? :turn
|
36
|
+
desc "Run tests"
|
37
|
+
task :test do
|
38
|
+
suffix = "-n #{ENV['TEST']}" if ENV['TEST']
|
39
|
+
sh "turn test/*.rb #{suffix}"
|
40
|
+
end
|
41
|
+
else
|
42
|
+
Rake::TestTask.new do |t|
|
43
|
+
t.libs << 'lib'
|
44
|
+
t.pattern = 'test/**/*_test.rb'
|
45
|
+
t.verbose = false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
#
|
51
|
+
# Development
|
52
|
+
#
|
53
|
+
|
54
|
+
desc "Drop to irb."
|
55
|
+
task :console do
|
56
|
+
exec "irb -I lib -rtomdoc"
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
#
|
61
|
+
# Gems
|
62
|
+
#
|
63
|
+
|
64
|
+
begin
|
65
|
+
require 'tomdoc/version'
|
66
|
+
require 'mg'
|
67
|
+
MG.new("tomdoc.gemspec")
|
68
|
+
|
69
|
+
desc "Push a new version to Gemcutter and publish docs."
|
70
|
+
task :publish => "gem:publish" do
|
71
|
+
require File.dirname(__FILE__) + '/lib/tomdoc/version'
|
72
|
+
|
73
|
+
sh "git tag v#{TomDoc::VERSION}"
|
74
|
+
sh "git push origin master --tags"
|
75
|
+
sh "git clean -fd"
|
76
|
+
end
|
77
|
+
rescue LoadError
|
78
|
+
warn "mg not available."
|
79
|
+
warn "Install it with: gem i mg"
|
80
|
+
end
|
data/bin/tomdoc
ADDED
data/lib/tomdoc.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
require 'ruby_parser'
|
4
|
+
require 'colored'
|
5
|
+
|
6
|
+
module TomDoc
|
7
|
+
autoload :Open3, 'open3'
|
8
|
+
|
9
|
+
autoload :CLI, 'tomdoc/cli'
|
10
|
+
|
11
|
+
autoload :Scope, 'tomdoc/scope'
|
12
|
+
autoload :Method, 'tomdoc/method'
|
13
|
+
autoload :Arg, 'tomdoc/arg'
|
14
|
+
autoload :TomDoc, 'tomdoc/tomdoc'
|
15
|
+
|
16
|
+
autoload :SourceParser, 'tomdoc/source_parser'
|
17
|
+
autoload :Generator, 'tomdoc/generator'
|
18
|
+
|
19
|
+
autoload :VERSION, 'tomdoc/version'
|
20
|
+
|
21
|
+
module Generators
|
22
|
+
autoload :Console, 'tomdoc/generators/console'
|
23
|
+
autoload :HTML, 'tomdoc/generators/html'
|
24
|
+
end
|
25
|
+
end
|
data/lib/tomdoc/arg.rb
ADDED
data/lib/tomdoc/cli.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module TomDoc
|
4
|
+
class CLI
|
5
|
+
#
|
6
|
+
# DSL Magics
|
7
|
+
#
|
8
|
+
|
9
|
+
def self.options(&block)
|
10
|
+
block ? (@options = block) : @options
|
11
|
+
end
|
12
|
+
|
13
|
+
def options
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
opts.instance_eval(&self.class.options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def pp(*args)
|
20
|
+
require 'pp'
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
#
|
26
|
+
# Define Options
|
27
|
+
#
|
28
|
+
|
29
|
+
options do
|
30
|
+
@options = {}
|
31
|
+
|
32
|
+
self.banner = "Usage: tomdoc [options] FILE1 FILE2 ..."
|
33
|
+
|
34
|
+
separator " "
|
35
|
+
separator "Examples:"
|
36
|
+
separator <<example
|
37
|
+
$ tomdoc file.rb
|
38
|
+
# Prints colored documentation of file.rb.
|
39
|
+
|
40
|
+
$ tomdoc file.rb -n STRING
|
41
|
+
# Prints methods or classes in file.rb matching STRING.
|
42
|
+
|
43
|
+
$ tomdoc -f html file.rb
|
44
|
+
# Prints HTML documentation of file.rb.
|
45
|
+
example
|
46
|
+
|
47
|
+
separator " "
|
48
|
+
separator "Options:"
|
49
|
+
|
50
|
+
on "-c", "--colored", "Pass -p, -s, or -t output to Pygments." do
|
51
|
+
ARGV.delete('-c') || ARGV.delete('--colored')
|
52
|
+
exec "#{$0} #{ARGV * ' '} | pygmentize -l ruby"
|
53
|
+
end
|
54
|
+
|
55
|
+
on "-t", "--tokens", "Parse FILE and print the tokenized form." do
|
56
|
+
sexp = SourceParser.new.sexp(argf.read)
|
57
|
+
pp SourceParser.new.tokenize(sexp)
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
|
61
|
+
on "-s", "--sexp", "Parse FILE and print the AST's sexps." do
|
62
|
+
pp RubyParser.new.parse(argf.read).to_a
|
63
|
+
exit
|
64
|
+
end
|
65
|
+
|
66
|
+
on "-n", "--pattern=PATTERN",
|
67
|
+
"Limit results to strings matching PATTERN." do |pattern|
|
68
|
+
|
69
|
+
@options[:pattern] = pattern
|
70
|
+
end
|
71
|
+
|
72
|
+
on "-f", "--format=FORMAT",
|
73
|
+
"Parse FILE and print the TomDoc as FORMAT." do |format|
|
74
|
+
|
75
|
+
if format.to_s.downcase == "html"
|
76
|
+
puts Generators::HTML.new(@options).generate(argf.read)
|
77
|
+
exit
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
on "-i", "--ignore",
|
82
|
+
"Ignore validation, print all methods we find with comments.." do
|
83
|
+
|
84
|
+
@options[:validate] = false
|
85
|
+
end
|
86
|
+
|
87
|
+
separator " "
|
88
|
+
separator "Common Options:"
|
89
|
+
|
90
|
+
on "-v", "--version", "Print the version" do
|
91
|
+
puts "TomDoc v#{VERSION}"
|
92
|
+
exit
|
93
|
+
end
|
94
|
+
|
95
|
+
on "-h", "--help", "Show this message" do
|
96
|
+
puts self
|
97
|
+
exit
|
98
|
+
end
|
99
|
+
|
100
|
+
on_tail do
|
101
|
+
puts Generators::Console.new(@options).generate(argf.read)
|
102
|
+
exit
|
103
|
+
end
|
104
|
+
|
105
|
+
separator ""
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
#
|
110
|
+
# Actions
|
111
|
+
#
|
112
|
+
|
113
|
+
def self.parse_options(args)
|
114
|
+
new.parse_options(args)
|
115
|
+
end
|
116
|
+
|
117
|
+
def parse_options(args)
|
118
|
+
options.parse(args)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
class OptionParser
|
124
|
+
# ARGF faker.
|
125
|
+
def argf
|
126
|
+
buffer = ''
|
127
|
+
|
128
|
+
ARGV.select { |arg| File.exists?(arg) }.each do |file|
|
129
|
+
buffer << File.read(file)
|
130
|
+
end
|
131
|
+
|
132
|
+
require 'stringio'
|
133
|
+
StringIO.new(buffer)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
#
|
139
|
+
# Main
|
140
|
+
#
|
141
|
+
|
142
|
+
# Help is the default.
|
143
|
+
ARGV << '-h' if ARGV.empty? && $stdin.tty?
|
144
|
+
|
145
|
+
# Process options
|
146
|
+
TomDoc::CLI.parse_options(ARGV) if $stdin.tty?
|
147
|
+
|
148
|
+
# Still here - process ARGF
|
149
|
+
TomDoc::CLI.process_files(ARGF)
|
150
|
+
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module TomDoc
|
2
|
+
class Generator
|
3
|
+
attr_reader :options, :scopes
|
4
|
+
|
5
|
+
# Creates a Generator.
|
6
|
+
#
|
7
|
+
# options - Optional Symbol-keyed Hash:
|
8
|
+
# :validate - Whether or not to validate TomDoc.
|
9
|
+
#
|
10
|
+
# scopes - Optional Symbol-keyed Hash.
|
11
|
+
#
|
12
|
+
# Returns an instance of TomDoc::Generator
|
13
|
+
def initialize(options = {}, scopes = {})
|
14
|
+
@options = {
|
15
|
+
:validate => true
|
16
|
+
}
|
17
|
+
@options.update(options)
|
18
|
+
|
19
|
+
@scopes = {}
|
20
|
+
@buffer = ''
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.generate(text_or_sexp)
|
24
|
+
new.generate(text_or_sexp)
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate(text_or_sexp)
|
28
|
+
if text_or_sexp.is_a?(String)
|
29
|
+
sexp = SourceParser.parse(text_or_sexp)
|
30
|
+
else
|
31
|
+
sexp = text_or_sexp
|
32
|
+
end
|
33
|
+
|
34
|
+
process(sexp)
|
35
|
+
end
|
36
|
+
|
37
|
+
def process(scopes = {}, prefix = nil)
|
38
|
+
old_scopes = @scopes
|
39
|
+
@scopes = scopes
|
40
|
+
scopes.each do |name, scope|
|
41
|
+
write_scope(scope, prefix)
|
42
|
+
process(scope, "#{name}::")
|
43
|
+
end
|
44
|
+
|
45
|
+
@buffer
|
46
|
+
ensure
|
47
|
+
@scopes = old_scopes || {}
|
48
|
+
end
|
49
|
+
|
50
|
+
def write_scope(scope, prefix)
|
51
|
+
write_scope_header(scope, prefix)
|
52
|
+
write_class_methods(scope, prefix)
|
53
|
+
write_instance_methods(scope, prefix)
|
54
|
+
write_scope_footer(scope, prefix)
|
55
|
+
end
|
56
|
+
|
57
|
+
def write_scope_header(scope, prefix)
|
58
|
+
end
|
59
|
+
|
60
|
+
def write_scope_footer(scope, prefix)
|
61
|
+
end
|
62
|
+
|
63
|
+
def write_class_methods(scope, prefix = nil)
|
64
|
+
prefix ="#{prefix}#{scope.name}."
|
65
|
+
|
66
|
+
scope.class_methods.map do |method|
|
67
|
+
next if !valid?(method, prefix)
|
68
|
+
write_method(method, prefix)
|
69
|
+
end.compact
|
70
|
+
end
|
71
|
+
|
72
|
+
def write_instance_methods(scope, prefix = nil)
|
73
|
+
prefix = "#{prefix}#{scope.name}#"
|
74
|
+
|
75
|
+
scope.instance_methods.map do |method|
|
76
|
+
next if !valid?(method, prefix)
|
77
|
+
write_method(method, prefix)
|
78
|
+
end.compact
|
79
|
+
end
|
80
|
+
|
81
|
+
def write_method(method, prefix = '')
|
82
|
+
end
|
83
|
+
|
84
|
+
def write(*things)
|
85
|
+
things.each do |thing|
|
86
|
+
@buffer << "#{thing}\n"
|
87
|
+
end
|
88
|
+
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
|
92
|
+
def pygments(text, *args)
|
93
|
+
out = ''
|
94
|
+
|
95
|
+
Open3.popen3("pygmentize", *args) do |stdin, stdout, stderr|
|
96
|
+
stdin.puts text
|
97
|
+
stdin.close
|
98
|
+
out = stdout.read.chomp
|
99
|
+
end
|
100
|
+
|
101
|
+
out
|
102
|
+
end
|
103
|
+
|
104
|
+
def constant?(const)
|
105
|
+
const = const.split('::').first if const.include?('::')
|
106
|
+
constant_names.include?(const.intern) || Object.const_defined?(const)
|
107
|
+
end
|
108
|
+
|
109
|
+
def constant_names
|
110
|
+
name = @scopes.name if @scopes.respond_to?(:name)
|
111
|
+
[ :Boolean, :Test, name ].compact + @scopes.keys
|
112
|
+
end
|
113
|
+
|
114
|
+
def valid?(object, prefix)
|
115
|
+
matches_pattern?(prefix, object.name) && valid_tomdoc?(object.tomdoc)
|
116
|
+
end
|
117
|
+
|
118
|
+
def matches_pattern?(prefix, name)
|
119
|
+
if pattern = options[:pattern]
|
120
|
+
# "-n hey" vs "-n /he.+y/"
|
121
|
+
if pattern =~ /^\/.+\/$/
|
122
|
+
pattern = pattern.sub(/^\//, '').sub(/\/$/, '')
|
123
|
+
regexp = Regexp.new(pattern)
|
124
|
+
else
|
125
|
+
regexp = Regexp.new(Regexp.escape(pattern))
|
126
|
+
end
|
127
|
+
|
128
|
+
regexp =~ name.to_s || regexp =~ prefix.to_s
|
129
|
+
else
|
130
|
+
true
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def valid_tomdoc?(comment)
|
135
|
+
options[:validate] ? TomDoc.valid?(comment) : true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|