Skip to content

Commit

Permalink
Add YardoptsCommand to abstract commands that read .yardopts
Browse files Browse the repository at this point in the history
Graph and Yardoc commands now subclass YardoptsCommand. Moved
all yardopts/document handling into that class.

Fixes #583
Closes #585, #589
  • Loading branch information
lsegal committed Oct 15, 2012
1 parent f28f760 commit 59ed93b
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 97 deletions.
27 changes: 14 additions & 13 deletions lib/yard/autoload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ def __p(path) File.join(YARD::ROOT, 'yard', *path.split('/')); end

module YARD
module CLI # Namespace for command-line interface components
autoload :Command, __p('cli/command')
autoload :CommandParser, __p('cli/command_parser')
autoload :Config, __p('cli/config')
autoload :Diff, __p('cli/diff')
autoload :Gems, __p('cli/gems')
autoload :Graph, __p('cli/graph')
autoload :Help, __p('cli/help')
autoload :List, __p('cli/list')
autoload :Server, __p('cli/server')
autoload :Stats, __p('cli/stats')
autoload :Yardoc, __p('cli/yardoc')
autoload :YRI, __p('cli/yri')
autoload :I18n, __p('cli/i18n')
autoload :Command, __p('cli/command')
autoload :CommandParser, __p('cli/command_parser')
autoload :Config, __p('cli/config')
autoload :Diff, __p('cli/diff')
autoload :Gems, __p('cli/gems')
autoload :Graph, __p('cli/graph')
autoload :Help, __p('cli/help')
autoload :List, __p('cli/list')
autoload :Server, __p('cli/server')
autoload :Stats, __p('cli/stats')
autoload :Yardoc, __p('cli/yardoc')
autoload :YardoptsCommand, __p('cli/yardopts_command')
autoload :YRI, __p('cli/yri')
autoload :I18n, __p('cli/i18n')
end

# A "code object" is defined as any entity in the Ruby language.
Expand Down
10 changes: 9 additions & 1 deletion lib/yard/cli/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def common_options(opts)
def parse_options(opts, args)
opts.parse!(args)
rescue OptionParser::ParseError => err
log.warn "Unrecognized/#{err.message}"
unrecognized_option(err)
args.shift if args.first && args.first[0,1] != '-'
retry
end
Expand All @@ -71,6 +71,14 @@ def load_script(file)
log.error "The file `#{file}' could not be loaded:\n#{load_exception}"
exit
end

# Callback when an unrecognize option is parsed
#
# @param [OptionParser::ParseError] err the exception raised by the
# option parser
def unrecognized_option(err)
log.warn "Unrecognized/#{err.message}"
end
end
end
end
7 changes: 5 additions & 2 deletions lib/yard/cli/graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class GraphOptions < Templates::TemplateOptions
#
# @see Graph#run
# @since 0.6.0
class Graph < Command
class Graph < YardoptsCommand
# The options parsed out of the commandline.
# Default options are:
# :format => :dot
Expand All @@ -32,6 +32,7 @@ class Graph < Command
# Creates a new instance of the command-line utility
def initialize
super
@use_document_file = false
@options = GraphOptions.new
options.reset_defaults
options.serializer = YARD::Serializers::StdoutSerializer.new
Expand All @@ -48,8 +49,8 @@ def description
# grapher.run('--private')
# @param [Array<String>] args each tokenized argument
def run(*args)
parse_arguments(*args)
Registry.load
optparse(*args)

contents = objects.map do |o|
o.format(options.merge(:serialize => false))
Expand All @@ -61,6 +62,8 @@ def run(*args)

private

def unrecognized_option(err) end

# Parses commandline options.
# @param [Array<String>] args each tokenized argument
def optparse(*args)
Expand Down
77 changes: 2 additions & 75 deletions lib/yard/cli/yardoc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,7 @@ class YardocOptions < Templates::TemplateOptions
#
# @since 0.2.1
# @see Verifier
class Yardoc < Command
# The configuration filename to load extra options from
DEFAULT_YARDOPTS_FILE = ".yardopts"

class Yardoc < YardoptsCommand
# @return [Hash] the hash of options passed to the template.
# @see Templates::Engine#render
attr_reader :options
Expand All @@ -158,12 +155,6 @@ class Yardoc < Command
# parse only changed files.
attr_accessor :use_cache

# @return [Boolean] whether to parse options from .yardopts
attr_accessor :use_yardopts_file

# @return [Boolean] whether to parse options from .document
attr_accessor :use_document_file

# @return [Boolean] whether objects should be serialized to .yardoc db
attr_accessor :save_yardoc

Expand All @@ -174,10 +165,6 @@ class Yardoc < Command
# @since 0.5.5
attr_accessor :list

# The options file name (defaults to {DEFAULT_YARDOPTS_FILE})
# @return [String] the filename to load extra options from
attr_accessor :options_file

# Keep track of which visibilities are to be shown
# @return [Array<Symbol>] a list of visibilities
# @since 0.5.6
Expand Down Expand Up @@ -216,10 +203,7 @@ def initialize
@files = []
@hidden_tags = []
@use_cache = false
@use_yardopts_file = true
@use_document_file = true
@generate = true
@options_file = DEFAULT_YARDOPTS_FILE
@statistics = true
@list = false
@save_yardoc = true
Expand Down Expand Up @@ -279,12 +263,7 @@ def run(*args)
# @return [Boolean] whether or not arguments are valid
# @since 0.5.6
def parse_arguments(*args)
parse_yardopts_options(*args)

# Parse files and then command line arguments
optparse(*support_rdoc_document_file!) if use_document_file
optparse(*yardopts) if use_yardopts_file
optparse(*args)
super(*args)

# Last minute modifications
self.files = ['{lib,app}/**/*.rb', 'ext/**/*.c'] if self.files.empty?
Expand Down Expand Up @@ -324,15 +303,6 @@ def all_objects
Registry.all(:root, :module, :class)
end

# Parses the .yardopts file for default yard options
# @return [Array<String>] an array of options parsed from .yardopts
def yardopts
return [] unless use_yardopts_file
File.read_binary(options_file).shell_split
rescue Errno::ENOENT
[]
end

private

# Generates output for objects
Expand Down Expand Up @@ -409,30 +379,6 @@ def print_list
end
end

# Parses out the yardopts/document options
def parse_yardopts_options(*args)
opts = OptionParser.new
opts.base.long.clear # HACK: why are --help and --version defined?
yardopts_options(opts)
begin
opts.parse(args)
rescue OptionParser::ParseError => err
idx = args.index(err.args.first)
args = args[(idx+1)..-1]
args.shift while args.first && args.first[0,1] != '-'
retry
end
end

# Reads a .document file in the directory to get source file globs
# @return [Array<String>] an array of files parsed from .document
def support_rdoc_document_file!
return [] unless use_document_file
File.read(".document").gsub(/^[ \t]*#.+/m, '').split(/\s+/)
rescue Errno::ENOENT
[]
end

# Adds a set of extra documentation files to be processed
# @param [Array<String>] files the set of documentation files
def add_extra_files(*files)
Expand Down Expand Up @@ -580,25 +526,6 @@ def general_options(opts)
end
end

# Adds --[no-]yardopts / --[no-]document
def yardopts_options(opts)
opts.on('--[no-]yardopts [FILE]',
"If arguments should be read from FILE",
" (defaults to yes, FILE defaults to .yardopts)") do |use_yardopts|
if use_yardopts.is_a?(String)
self.options_file = use_yardopts
self.use_yardopts_file = true
else
self.use_yardopts_file = (use_yardopts != false)
end
end

opts.on('--[no-]document', "If arguments should be read from .document file. ",
" (defaults to yes)") do |use_document|
self.use_document_file = use_document
end
end

# Adds output options
def output_options(opts)
opts.separator ""
Expand Down
109 changes: 109 additions & 0 deletions lib/yard/cli/yardopts_command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
require 'optparse'

module YARD
module CLI
# Abstract base class for command that reads .yardopts file
#
# @abstract
# @since 0.8.3
class YardoptsCommand < Command
# The configuration filename to load extra options from
DEFAULT_YARDOPTS_FILE = ".yardopts"

# @return [Boolean] whether to parse options from .yardopts
attr_accessor :use_yardopts_file

# @return [Boolean] whether to parse options from .document
attr_accessor :use_document_file

# The options file name (defaults to {DEFAULT_YARDOPTS_FILE})
# @return [String] the filename to load extra options from
attr_accessor :options_file

# Creates a new command that reads .yardopts
def initialize
super
@options_file = DEFAULT_YARDOPTS_FILE
@use_yardopts_file = true
@use_document_file = true
end

# Parses commandline arguments
# @param [Array<String>] args the list of arguments
# @return [Boolean] whether or not arguments are valid
# @since 0.5.6
def parse_arguments(*args)
parse_yardopts_options(*args)

# Parse files and then command line arguments
parse_rdoc_document_file
parse_yardopts
optparse(*args)
end

protected

# Adds --[no-]yardopts / --[no-]document
def yardopts_options(opts)
opts.on('--[no-]yardopts [FILE]',
"If arguments should be read from FILE",
" (defaults to yes, FILE defaults to .yardopts)") do |use_yardopts|
if use_yardopts.is_a?(String)
self.options_file = use_yardopts
self.use_yardopts_file = true
else
self.use_yardopts_file = (use_yardopts != false)
end
end

opts.on('--[no-]document', "If arguments should be read from .document file. ",
" (defaults to yes)") do |use_document|
self.use_document_file = use_document
end
end

private

# Parses the .yardopts file for default yard options
# @return [Array<String>] an array of options parsed from .yardopts
def yardopts(file = options_file)
return [] unless use_yardopts_file
File.read_binary(file).shell_split
rescue Errno::ENOENT
[]
end

# Parses out the yardopts/document options
def parse_yardopts_options(*args)
opts = OptionParser.new
opts.base.long.clear # HACK: why are --help and --version defined?
yardopts_options(opts)
begin
opts.parse(args)
rescue OptionParser::ParseError => err
idx = args.index(err.args.first)
args = args[(idx+1)..-1]
args.shift while args.first && args.first[0,1] != '-'
retry
end
end

def parse_rdoc_document_file(file = '.document')
optparse(*support_rdoc_document_file!(file)) if use_document_file
end

def parse_yardopts(file = options_file)
optparse(*yardopts(file)) if use_yardopts_file
end

# Reads a .document file in the directory to get source file globs
# @return [Array<String>] an array of files parsed from .document
def support_rdoc_document_file!(file = '.document')
return [] unless use_document_file
File.read(file).gsub(/^[ \t]*#.+/m, '').split(/\s+/)
rescue Errno::ENOENT
[]
end
end
end
end
17 changes: 12 additions & 5 deletions spec/cli/graph_spec.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
require File.dirname(__FILE__) + '/../spec_helper'

describe YARD::CLI::Yardoc do
describe YARD::CLI::Graph do
it "should serialize output" do
Registry.should_receive(:load)
@graph = YARD::CLI::Graph.new
@graph.options.serializer.should_receive(:serialize).once
@graph.run
Registry.should_receive(:load).at_least(1).times
subject.stub(:yardopts) { [] }
subject.options.serializer.should_receive(:serialize).once
subject.run
end

it 'should read yardoc file from .yardopts' do
subject.stub(:yardopts) { %w(--db /path/to/db) }
subject.options.serializer.should_receive(:serialize).once
subject.run
Registry.yardoc_file.should == '/path/to/db'
end
end
3 changes: 2 additions & 1 deletion spec/cli/server_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Server::WebrickAdapter; def start; end end
end

def new_cli
@cli = YARD::CLI::Server.new
@cli = subject
end

def rack_required
Expand Down Expand Up @@ -85,6 +85,7 @@ def mock_file(filename, content = nil)

describe 'when .yardopts file exists' do
before :each do
Registry.yardoc_file = Registry::DEFAULT_YARDOC_FILE
Dir.stub!(:pwd).and_return('/path/to/bar')
@name = 'bar'
end
Expand Down

0 comments on commit 59ed93b

Please sign in to comment.