v/cmd/tools/vdoc/files.v

84 lines
2.3 KiB
V

module main
import os
struct IgnoreRules {
mut:
// Ignore patterns use the path with a `.vdocignore` file as a base. E.g.:
// `{'<path>': ['<pattern1>', '<pattern2>'], '<path/subpath>': ['<pattern3>']}`
patterns map[string][]string = {
// Default ignore patterns.
'': ['testdata', 'tests', '*_test.v']
}
paths map[string]bool
}
fn get_modules(path string) []string {
mut ignore_rules := IgnoreRules{}
mut modules := map[string]bool{}
for p in get_paths(path, mut ignore_rules) {
modules[os.dir(p)] = true
}
mut res := modules.keys()
res.sort()
return res
}
fn get_paths(path string, mut ignore_rules IgnoreRules) []string {
mut res := []string{}
outer: for p in os.ls(path) or { return [] } {
ignore_rules.get(path)
fp := os.join_path(path, p)
if fp in ignore_rules.paths {
continue
}
is_dir := os.is_dir(fp)
for ignore_path, patterns in ignore_rules.patterns {
if fp.starts_with(ignore_path) {
if patterns.any(p == it
|| (it.contains('*') && p.ends_with(it.all_after('*')))
|| (is_dir && it.ends_with('/') && fp.ends_with(it.trim_right('/')))
|| (!it.ends_with('/') && it.contains('/') && fp.contains(it)))
{
continue outer
}
}
}
if is_dir {
res << get_paths(fp, mut ignore_rules)
continue
}
if p.ends_with('.v') {
res << fp
}
}
return res
}
fn (mut ignore_rules IgnoreRules) get(path string) {
ignore_content := os.read_file(os.join_path(path, '.vdocignore')) or { return }
if ignore_content.trim_space() == '' {
return
}
rules := ignore_content.split_into_lines().map(it.trim_space())
for rule in rules {
if rule.starts_with('#') {
continue
}
if rule.contains('*.') || rule.contains('**') {
// Skip wildcards that are defined in an ignore file.
// For now, only add a basic implementation in `get_paths`
// that can handle the default `*_test.v` pattern.
eprintln('vdoc: Wildcards in ignore rules are not yet supported.')
continue
}
if rule.starts_with('/') {
// Similar to `.gitignore`, a pattern starting with `/` should only ignore
// the pattern relative to the directory of the `.vdocignore` file.
// `/a` should ignore `/a` but not `/b/a`. While `a` should ignore `/a` and `/b/a`.
ignore_rules.paths[os.join_path(path, rule.trim_left('/'))] = true
} else {
ignore_rules.patterns[path] << rule
}
}
}