Skip to content

Commit

Permalink
New line-oriented .document file format
Browse files Browse the repository at this point in the history
Introduce the new format similar to the `.gitignore` file by starting
with the comment `rdoc.document: 1`.

- one pattern per line
- negative pattern starting with `!`
- escaping space and `#` by a backslash
  • Loading branch information
nobu authored and hsbt committed Mar 15, 2024
1 parent 9ed530b commit 083f0df
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 5 deletions.
62 changes: 57 additions & 5 deletions lib/rdoc/rdoc.rb
Expand Up @@ -245,15 +245,67 @@ def output_flag_file(op_dir)
# The .document file contains a list of file and directory name patterns,
# representing candidates for documentation. It may also contain comments
# (starting with '#')
#
# If the first line is the comment starts with +rdoc.document:+
# (case-insensitive) followed by a version string, the file is
# parsed as per the version. If a version is not written, it is
# defaulted to 0.
#
# version 0::
#
# The file will be parsed as white-space separated glob patterns.
#
# - A <tt>#</tt> in middle starts a comment.
#
# - Multiple patterns can be in a single line.
#
# - That means patterns cannot contain white-spaces and <tt>#</tt>
# marks.
#
# version 1::
#
# The file will be parsed as single glob pattern per each line.
#
# - Only lines starting with <tt>#</tt> at the first colmun are
# comments. A <tt>#</tt> in middle is a part of the pattern.
#
# - Patterns starting with <tt>#</tt> need to be prefixed with a
# backslash (<tt>\\</tt>).
#
# - Leading spaces are not stripped while trailing spaces which
# are not escaped with a backslash are stripped.
#
# - The pattern starting with <tt>!</tt> is a negative pattern,
# which rejects matching files.

def parse_dot_doc_file in_dir, filename
# read and strip comments
patterns = File.read(filename).gsub(/#.*/, '')

result = {}
patterns = rejects = nil

content = File.read(filename)
version = content[/\A#+\s*rdoc\.document:\s*\K\S+/i]&.to_i || 0
if version >= 1
content.each_line(chomp: true) do |line|
next if line.start_with?("#") # skip comments
line.sub!(/(?<!\\)\s*$/, "") # rstrip unescaped trailing spaces
(line.sub!(/\A!/, "") ? (rejects ||= []) : (patterns ||= [])) << line
end
else
# read and strip comments
patterns = content.gsub(/#.*/, '').split(' ')
end

patterns.split(' ').each do |patt|
candidates = Dir.glob(File.join(in_dir, patt))
if patterns
patterns.each {|patt| patt.sub!(/\A\/+/, "")}
candidates = Dir.glob(patterns, base: in_dir)
if rejects
rejects.each {|patt| patt.sub!(/\A\/+/, "")}
flag = File::FNM_PATHNAME
candidates.delete_if do |name|
rejects.any? {|patt| File.fnmatch?(patt, name, flag)}
end
end
candidates.map! {|name| File.join(in_dir, name)}
result.update normalized_file_list(candidates, false, @options.exclude)
end

Expand Down
43 changes: 43 additions & 0 deletions test/rdoc/test_rdoc_rdoc.rb
Expand Up @@ -177,6 +177,49 @@ def test_normalized_file_list_with_dot_doc
assert_equal expected_files, files
end

def test_normalized_file_list_with_dot_doc_version_1
expected_files = []
files = temp_dir do |dir|
a = 'a.rb'
b = 'b.rb'
a_b = 'a.rb b.rb'
FileUtils.touch a
FileUtils.touch b
FileUtils.touch a_b

File.open('.document', 'w') do |f|
f.puts '# rdoc.document: 1'
f.puts a_b
end
expected_files << File.expand_path(a_b, dir)

@rdoc.normalized_file_list [dir]
end

assert_equal expected_files, files.keys
end

def test_normalized_file_list_with_dot_doc_negative_pattern
expected_files = []
files = temp_dir do |dir|
a = 'a.rb'
b = 'b.rb'
FileUtils.touch a
FileUtils.touch b

File.open('.document', 'w') do |f|
f.puts '# rdoc.document: 1'
f.puts '*.rb'
f.puts '!b.rb'
end
expected_files << File.expand_path(a, dir)

@rdoc.normalized_file_list [dir]
end

assert_equal expected_files, files.keys
end

def test_normalized_file_list_with_dot_doc_overridden_by_exclude_option
expected_files = []
files = temp_dir do |dir|
Expand Down

0 comments on commit 083f0df

Please sign in to comment.