tomdoc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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.
@@ -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
+ ![pattern](http://img.skitch.com/20100408-mnyxuxb4xrrg5x4pnpsmuth4mu.png)
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
+ ![html](http://img.skitch.com/20100408-dbhtc4mef2q3ygmn63csxgh14w.png)
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
@@ -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
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'tomdoc'
4
+
5
+ # Process options
6
+ TomDoc::CLI.parse_options(ARGV)
@@ -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
@@ -0,0 +1,14 @@
1
+ module TomDoc
2
+ class Arg
3
+ attr_accessor :name, :description
4
+
5
+ def initialize(name, description = '')
6
+ @name = name.to_s.intern
7
+ @description = description
8
+ end
9
+
10
+ def optional?
11
+ @description.downcase.include? 'optional'
12
+ end
13
+ end
14
+ end
@@ -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