diff --git a/TESTS.md b/TESTS.md
index a2d20a1bce..c3803cdde1 100644
--- a/TESTS.md
+++ b/TESTS.md
@@ -185,3 +185,11 @@ tests in the main V repository, for example:
* `v vet vlib/v` - run a style checker.
* `v test-self` (run self tests) in various compilation modes.
+
+> **Note**
+The VDOC test vdoc_file_test.v now also supports VAUTOFIX, which is
+useful, if you change anything inside cmd/tools/vdoc or vlib/v/doc/,
+or inside the modules that it depends on (like markdown).
+After such changes, just run this command *2 times*, and commit the
+resulting changes in `cmd/tools/vdoc/tests/testdata` as well:
+`VAUTOFIX=1 ./v cmd/tools/vdoc/tests/vdoc_file_test.v`
diff --git a/cmd/tools/vdoc/.gitattributes b/cmd/tools/vdoc/.gitattributes
new file mode 100644
index 0000000000..c05b8c16fd
--- /dev/null
+++ b/cmd/tools/vdoc/.gitattributes
@@ -0,0 +1,3 @@
+*.ansi text eol=lf
+*.text text eol=lf
+*.html text eol=lf
diff --git a/cmd/tools/vdoc/html.v b/cmd/tools/vdoc/html.v
index 2c7e60c325..677121827a 100644
--- a/cmd/tools/vdoc/html.v
+++ b/cmd/tools/vdoc/html.v
@@ -198,11 +198,14 @@ fn (vd VDoc) gen_html(d doc.Doc) string {
}
for cn in dcs_contents {
vd.write_content(&cn, &d, mut contents)
- write_toc(cn, mut symbols_toc)
- } // write head
+ write_toc(cn, mut symbols_toc) // write head
+ }
+ if cfg.html_only_contents {
+ // no need for theming, styling etc, useful for testing and for external documentation generators
+ return contents.str()
+ }
+
// write css
- mut version := if vd.manifest.version.len != 0 { vd.manifest.version } else { '' }
- version = [version, @VCURRENTHASH].join(' ')
header_name := if cfg.is_multi && vd.docs.len > 1 {
os.file_name(os.real_path(cfg.input_path))
} else {
@@ -249,33 +252,65 @@ fn (vd VDoc) gen_html(d doc.Doc) string {
}
modules_toc_str := modules_toc.str()
symbols_toc_str := symbols_toc.str()
- result := (os.read_file(os.join_path(cfg.theme_dir, 'index.html')) or { panic(err) }).replace('{{ title }}',
- d.head.name).replace('{{ head_name }}', header_name).replace('{{ version }}',
- version).replace('{{ light_icon }}', vd.assets['light_icon']).replace('{{ dark_icon }}',
- vd.assets['dark_icon']).replace('{{ menu_icon }}', vd.assets['menu_icon']).replace('{{ head_assets }}',
- if cfg.inline_assets {
- '
+ mut result := os.read_file(os.join_path(cfg.theme_dir, 'index.html')) or { panic(err) }
+ if cfg.html_no_vhash {
+ result = result.replace('{{ version }}', 'latest')
+ } else {
+ mut version := if vd.manifest.version.len != 0 { vd.manifest.version } else { '' }
+ version = [version, @VCURRENTHASH].join(' ')
+ result = result.replace('{{ version }}', version)
+ }
+ result = result.replace('{{ title }}', d.head.name)
+ result = result.replace('{{ head_name }}', header_name)
+ result = result.replace('{{ light_icon }}', vd.assets['light_icon'])
+ result = result.replace('{{ dark_icon }}', vd.assets['dark_icon'])
+ result = result.replace('{{ menu_icon }}', vd.assets['menu_icon'])
+ if cfg.html_no_assets {
+ result = result.replace('{{ head_assets }}', '')
+ } else {
+ result = result.replace('{{ head_assets }}', if cfg.inline_assets {
+ '
${tabs(2)}
${tabs(2)}'
- } else {
- '
+ } else {
+ '
${tabs(2)}
${tabs(2)}'
- }).replace('{{ toc_links }}', if cfg.is_multi || vd.docs.len > 1 {
- modules_toc_str
+ })
+ }
+ if cfg.html_no_toc_urls {
+ result = result.replace('{{ toc_links }}', '')
} else {
- symbols_toc_str
- }).replace('{{ contents }}', contents.str()).replace('{{ right_content }}', if cfg.is_multi
- && d.head.name != 'README' {
- '
'
+ result = result.replace('{{ toc_links }}', if cfg.is_multi || vd.docs.len > 1 {
+ modules_toc_str
+ } else {
+ symbols_toc_str
+ })
+ }
+ result = result.replace('{{ contents }}', contents.str())
+ if cfg.html_no_right {
+ result = result.replace('{{ right_content }}', '')
} else {
- ''
- }).replace('{{ footer_content }}', gen_footer_text(d, !cfg.no_timestamp)).replace('{{ footer_assets }}',
- if cfg.inline_assets {
- ''
+ result = result.replace('{{ right_content }}', if cfg.is_multi && d.head.name != 'README' {
+ ''
+ } else {
+ ''
+ })
+ }
+ if cfg.html_no_footer {
+ result = result.replace('{{ footer_content }}', '')
} else {
- ''
- })
+ result = result.replace('{{ footer_content }}', gen_footer_text(d, !cfg.no_timestamp))
+ }
+ if cfg.html_no_assets {
+ result = result.replace('{{ footer_assets }}', '')
+ } else {
+ result = result.replace('{{ footer_assets }}', if cfg.inline_assets {
+ ''
+ } else {
+ ''
+ })
+ }
return result
}
diff --git a/cmd/tools/vdoc/main.v b/cmd/tools/vdoc/main.v
index 14667faad0..ff12199d73 100644
--- a/cmd/tools/vdoc/main.v
+++ b/cmd/tools/vdoc/main.v
@@ -10,7 +10,36 @@ const vexe = os.getenv_opt('VEXE') or { @VEXE }
const vroot = os.dir(vexe)
-const allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm']
+const allowed_formats = ['md', 'markdown', 'json', 'text', 'ansi', 'html', 'htm']
+
+struct Config {
+mut:
+ pub_only bool = true
+ show_loc bool // for plaintext
+ is_color bool
+ is_multi bool
+ is_vlib bool
+ is_verbose bool
+ include_readme bool
+ include_examples bool = true
+ include_comments bool // for plaintext
+ inline_assets bool
+ theme_dir string = default_theme
+ no_timestamp bool
+ output_path string
+ output_type OutputType = .unset
+ input_path string
+ symbol_name string
+ platform doc.Platform
+ run_examples bool // `-run-examples` will run all `// Example: assert mod.abc() == y` comments in the processed modules
+ // The options below are useful for generating a more stable HMTL, that is easier to regression test:
+ html_only_contents bool // `-html-only-contents` will produce only the content of any given page, without styling tags etc.
+ html_no_vhash bool // `-html-no-vhash` will remove the version hash from the generated html
+ html_no_assets bool // `-html-no-assets` will not include CSS and JS asset tags in the generated html
+ html_no_right bool // `-html-no-right` will not add the doc-toc right panel in the generated html
+ html_no_toc_urls bool // `-html-no-toc-urls` will not add the toc_links panel in the generated html
+ html_no_footer bool // `-html-no-footer` will not add the footer panel in the generated html
+}
fn main() {
if os.args.len < 2 || '-h' in os.args || '-help' in os.args || '--help' in os.args
@@ -27,9 +56,7 @@ fn main() {
// Config is immutable from this point on
mut vd := &VDoc{
cfg: cfg
- manifest: vmod.Manifest{
- repo_url: ''
- }
+ manifest: vmod.Manifest{}
}
vd.vprintln('Setting output type to "${cfg.output_type}"')
vd.generate_docs_from_file()
@@ -50,6 +77,7 @@ fn main() {
fn parse_arguments(args []string) Config {
mut cfg := Config{}
cfg.is_color = term.can_show_color_on_stdout()
+ mut is_color_was_set_explicitly := false
for i := 0; i < args.len; i++ {
arg := args[i]
current_args := args[i..]
@@ -69,9 +97,11 @@ fn parse_arguments(args []string) Config {
}
'-color' {
cfg.is_color = true
+ is_color_was_set_explicitly = true
}
'-no-color' {
cfg.is_color = false
+ is_color_was_set_explicitly = true
}
'-inline-assets' {
cfg.inline_assets = true
@@ -90,7 +120,7 @@ fn parse_arguments(args []string) Config {
}
'-o' {
opath := cmdline.option(current_args, '-o', '')
- cfg.output_path = if opath == 'stdout' { opath } else { os.real_path(opath) }
+ cfg.output_path = if opath in ['stdout', '-'] { opath } else { os.real_path(opath) }
i++
}
'-os' {
@@ -115,6 +145,26 @@ fn parse_arguments(args []string) Config {
'-no-examples' {
cfg.include_examples = false
}
+ //
+ '-html-only-contents' {
+ cfg.html_only_contents = true
+ }
+ '-html-no-vhash' {
+ cfg.html_no_vhash = true
+ }
+ '-html-no-assets' {
+ cfg.html_no_assets = true
+ }
+ '-html-no-right' {
+ cfg.html_no_right = true
+ }
+ '-html-no-toc-urls' {
+ cfg.html_no_toc_urls = true
+ }
+ '-html-no-footer' {
+ cfg.html_no_footer = true
+ }
+ //
'-readme' {
cfg.include_readme = true
}
@@ -135,28 +185,42 @@ fn parse_arguments(args []string) Config {
}
}
}
- // Correct from configuration from user input
- if cfg.output_path == 'stdout' && cfg.output_type == .html {
- cfg.inline_assets = true
+
+ if cfg.output_type == .html {
+ // quirks specific to *just* the html output mode:
+ if cfg.output_path in ['stdout', '-'] {
+ cfg.inline_assets = true
+ }
}
- $if windows {
- cfg.input_path = cfg.input_path.replace('/', os.path_separator)
- } $else {
- cfg.input_path = cfg.input_path.replace('\\', os.path_separator)
+
+ if !is_color_was_set_explicitly {
+ if cfg.output_type == .plaintext {
+ cfg.is_color = false
+ } else if cfg.output_type == .ansi {
+ cfg.is_color = true
+ }
}
- is_path := cfg.input_path.ends_with('.v') || cfg.input_path.split(os.path_separator).len > 1
+
+ if cfg.is_color {
+ os.setenv('VCOLORS', 'always', true)
+ } else {
+ os.setenv('VCOLORS', 'never', true)
+ }
+
+ cfg.input_path = cfg.input_path.replace('\\', '/')
+ is_path := cfg.input_path.ends_with('.v') || cfg.input_path.split('/').len > 1
|| cfg.input_path == '.'
if cfg.input_path.trim_right('/') == 'vlib' {
cfg.is_vlib = true
cfg.is_multi = true
cfg.input_path = os.join_path(vroot, 'vlib')
} else if !is_path {
- // TODO vd.vprintln('Input "$cfg.input_path" is not a valid path. Looking for modules named "$cfg.input_path"...')
mod_path := doc.lookup_module(cfg.input_path) or {
eprintln('vdoc: ${err}')
exit(1)
}
cfg.input_path = mod_path
}
+ cfg.input_path = cfg.input_path.replace('/', os.path_separator)
return cfg
}
diff --git a/cmd/tools/vdoc/tests/testdata/newlines/main.comments.out b/cmd/tools/vdoc/tests/testdata/newlines/main.comments.out
index a789d11bb6..d25b9bff24 100644
--- a/cmd/tools/vdoc/tests/testdata/newlines/main.comments.out
+++ b/cmd/tools/vdoc/tests/testdata/newlines/main.comments.out
@@ -19,4 +19,4 @@ fn funky()
| foo bar | yes |
|-----------|--------|
- | working | yup |
\ No newline at end of file
+ | working | yup |
diff --git a/cmd/tools/vdoc/tests/testdata/newlines/main.out b/cmd/tools/vdoc/tests/testdata/newlines/main.out
index 02bcce98fe..b8602997f7 100644
--- a/cmd/tools/vdoc/tests/testdata/newlines/main.out
+++ b/cmd/tools/vdoc/tests/testdata/newlines/main.out
@@ -1,3 +1,3 @@
module main
-fn funky()
\ No newline at end of file
+fn funky()
diff --git a/cmd/tools/vdoc/tests/testdata/output_formats/main.ansi b/cmd/tools/vdoc/tests/testdata/output_formats/main.ansi
new file mode 100644
index 0000000000..16afcacf36
--- /dev/null
+++ b/cmd/tools/vdoc/tests/testdata/output_formats/main.ansi
@@ -0,0 +1,36 @@
+
+[94mmodule[39m [32mmain[39m
+
+[94mconst[39m omega = [94m3[39m [90m// should be first[39m
+[94mconst[39m alpha = [94m5[39m [90m// should be in the middle[39m
+[94mconst[39m beta = [94m2[39m [90m// should be at the end[39m
+[94mfn[39m [36mabc[39m()
+ abc - should be last
+[94mfn[39m [36mdef[39m()
+ def - should be first
+[94mfn[39m [36mxyz[39m()
+ xyz - should be in the middle
+[94mfn[39m [32mMyXMLDocument[39m.[36mabc[39m(text [32mstring[39m) ?([32mstring[39m, [32mint[39m)
+ MyXMLDocument.abc does something too... I just do not know what.
+[94mfn[39m [32mMyXMLDocument[39m.[36mfrom_file[39m(path [32mstring[39m) ![32mMyXMLDocument[39m
+ MyXMLDocument.from_text processes the file path, and returns an error
+[94mfn[39m [32mMyXMLDocument[39m.[36mfrom_text[39m(text [32mstring[39m) ?[32mMyXMLDocument[39m
+ MyXMLDocument.from_text processes text and produces none
+[94mstruct[39m [32mMyXMLDocument[39m {
+ path [32mstring[39m
+}
+ MyXMLDocument is here just to test the different combinations of methods/output types
+[94mfn[39m (x &[32mMyXMLDocument[39m) [36minstance_from_file[39m(path [32mstring[39m) ![32mMyXMLDocument[39m
+ instance_from_file does stuff with path
+[94mfn[39m (x &[32mMyXMLDocument[39m) [36minstance_from_text[39m(text [32mstring[39m) ?[32mMyXMLDocument[39m
+ instance_from_text does stuff with text
+[94mfn[39m (x &[32mMyXMLDocument[39m) [36minstance_abc[39m(text [32mstring[39m) ?([32mstring[39m, [32mint[39m)
+ instance_abc does stuff too
+[94mfn[39m (x &[32mMyXMLDocument[39m) [36minstance_void[39m()
+ instance_void does stuff too
+[94mfn[39m (x &[32mMyXMLDocument[39m) [36minstance_int[39m() [32mint[39m
+ instance_int does stuff too
+[94mfn[39m (x &[32mMyXMLDocument[39m) [36minstance_result[39m() !
+ instance_error does stuff too
+[94mfn[39m (x &[32mMyXMLDocument[39m) [36minstance_option[39m() ?
+ instance_option does stuff too
diff --git a/cmd/tools/vdoc/tests/testdata/output_formats/main.html b/cmd/tools/vdoc/tests/testdata/output_formats/main.html
new file mode 100644
index 0000000000..522ae1976b
--- /dev/null
+++ b/cmd/tools/vdoc/tests/testdata/output_formats/main.html
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+ fn abc()
+abc - should be last
+
+
+
+ fn def()
+def - should be first
+
+
+
+ fn xyz()
+xyz - should be in the middle
+
+
+
+ fn MyXMLDocument.abc(text string) ?(string, int)
+MyXMLDocument.abc does something too... I just do not know what.
+
+
+
+ fn MyXMLDocument.from_file #
fn MyXMLDocument.from_file(path string) !MyXMLDocument
+MyXMLDocument.from_text processes the file path, and returns an error
+
+
+
+ fn MyXMLDocument.from_text #
fn MyXMLDocument.from_text(text string) ?MyXMLDocument
+MyXMLDocument.from_text processes text and produces none
+
+
+
+ struct MyXMLDocument {
+ path string
+}
+MyXMLDocument is here just to test the different combinations of methods/output types
+
+
+
+ fn (MyXMLDocument) instance_from_file #
fn (x &MyXMLDocument) instance_from_file(path string) !MyXMLDocument
+instance_from_file does stuff with path
+
+
+
+ fn (MyXMLDocument) instance_from_text #
fn (x &MyXMLDocument) instance_from_text(text string) ?MyXMLDocument
+instance_from_text does stuff with text
+
+
+
+ fn (MyXMLDocument) instance_abc #
fn (x &MyXMLDocument) instance_abc(text string) ?(string, int)
+instance_abc does stuff too
+
+
+
+ fn (MyXMLDocument) instance_void #
fn (x &MyXMLDocument) instance_void()
+instance_void does stuff too
+
+
+
+ fn (MyXMLDocument) instance_int #
fn (x &MyXMLDocument) instance_int() int
+instance_int does stuff too
+
+
+
+ fn (MyXMLDocument) instance_result #
fn (x &MyXMLDocument) instance_result() !
+instance_error does stuff too
+
+
+
+ fn (MyXMLDocument) instance_option #
fn (x &MyXMLDocument) instance_option() ?
+instance_option does stuff too
+
+
diff --git a/cmd/tools/vdoc/tests/testdata/output_formats/main.text b/cmd/tools/vdoc/tests/testdata/output_formats/main.text
new file mode 100644
index 0000000000..cf1cd8a93a
--- /dev/null
+++ b/cmd/tools/vdoc/tests/testdata/output_formats/main.text
@@ -0,0 +1,35 @@
+module main
+
+const omega = 3 // should be first
+const alpha = 5 // should be in the middle
+const beta = 2 // should be at the end
+fn abc()
+ abc - should be last
+fn def()
+ def - should be first
+fn xyz()
+ xyz - should be in the middle
+fn MyXMLDocument.abc(text string) ?(string, int)
+ MyXMLDocument.abc does something too... I just do not know what.
+fn MyXMLDocument.from_file(path string) !MyXMLDocument
+ MyXMLDocument.from_text processes the file path, and returns an error
+fn MyXMLDocument.from_text(text string) ?MyXMLDocument
+ MyXMLDocument.from_text processes text and produces none
+struct MyXMLDocument {
+ path string
+}
+ MyXMLDocument is here just to test the different combinations of methods/output types
+fn (x &MyXMLDocument) instance_from_file(path string) !MyXMLDocument
+ instance_from_file does stuff with path
+fn (x &MyXMLDocument) instance_from_text(text string) ?MyXMLDocument
+ instance_from_text does stuff with text
+fn (x &MyXMLDocument) instance_abc(text string) ?(string, int)
+ instance_abc does stuff too
+fn (x &MyXMLDocument) instance_void()
+ instance_void does stuff too
+fn (x &MyXMLDocument) instance_int() int
+ instance_int does stuff too
+fn (x &MyXMLDocument) instance_result() !
+ instance_error does stuff too
+fn (x &MyXMLDocument) instance_option() ?
+ instance_option does stuff too
diff --git a/cmd/tools/vdoc/tests/testdata/output_formats/main.v b/cmd/tools/vdoc/tests/testdata/output_formats/main.v
new file mode 100644
index 0000000000..791928b382
--- /dev/null
+++ b/cmd/tools/vdoc/tests/testdata/output_formats/main.v
@@ -0,0 +1,75 @@
+pub const omega = 3 // should be first
+
+pub const alpha = 5 // should be in the middle
+
+pub const beta = 2 // should be at the end
+
+// def - should be first
+pub fn def() {
+ println(1)
+}
+
+// xyz - should be in the middle
+pub fn xyz() {
+ println(2)
+}
+
+// abc - should be last
+pub fn abc() {
+ println(3)
+}
+
+// MyXMLDocument is here just to test the different combinations of methods/output types
+pub struct MyXMLDocument {
+ path string
+}
+
+// MyXMLDocument.from_text processes the file path, and returns an error
+pub fn MyXMLDocument.from_file(path string) !MyXMLDocument {
+ return error('TODO')
+}
+
+// MyXMLDocument.from_text processes text and produces none
+pub fn MyXMLDocument.from_text(text string) ?MyXMLDocument {
+ return none
+}
+
+// MyXMLDocument.abc does something too... I just do not know what.
+pub fn MyXMLDocument.abc(text string) ?(string, int) {
+ return 'xyz', 123
+}
+
+// instance_from_file does stuff with path
+pub fn (x &MyXMLDocument) instance_from_file(path string) !MyXMLDocument {
+ return error('TODO')
+}
+
+// instance_from_text does stuff with text
+pub fn (x &MyXMLDocument) instance_from_text(text string) ?MyXMLDocument {
+ return none
+}
+
+// instance_abc does stuff too
+pub fn (x &MyXMLDocument) instance_abc(text string) ?(string, int) {
+ return 'xyz', 123
+}
+
+// instance_void does stuff too
+pub fn (x &MyXMLDocument) instance_void() {
+ return 123
+}
+
+// instance_int does stuff too
+pub fn (x &MyXMLDocument) instance_int() int {
+ return 123
+}
+
+// instance_error does stuff too
+pub fn (x &MyXMLDocument) instance_result() ! {
+ return 123
+}
+
+// instance_option does stuff too
+pub fn (x &MyXMLDocument) instance_option() ? {
+ return 123
+}
diff --git a/cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.comments.out b/cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.comments.out
index fd82920d6f..8b0207f2fa 100644
--- a/cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.comments.out
+++ b/cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.comments.out
@@ -1,3 +1,3 @@
module foo
-fn bar()
\ No newline at end of file
+fn bar()
diff --git a/cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.readme.comments.out b/cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.readme.comments.out
index e4c69b8253..e426e3ec2f 100644
--- a/cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.readme.comments.out
+++ b/cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.readme.comments.out
@@ -1,4 +1,4 @@
hello from readme
module foo
-fn bar()
\ No newline at end of file
+fn bar()
diff --git a/cmd/tools/vdoc/tests/vdoc_file_test.v b/cmd/tools/vdoc/tests/vdoc_file_test.v
index a1a3ddfe72..7db54ff91c 100644
--- a/cmd/tools/vdoc/tests/vdoc_file_test.v
+++ b/cmd/tools/vdoc/tests/vdoc_file_test.v
@@ -10,6 +10,8 @@ const vroot = @VMODROOT
const diff_cmd = find_diff_cmd()
+const should_autofix = os.getenv('VAUTOFIX') != ''
+
fn find_diff_cmd() string {
return diff.find_working_diff_command() or { '' }
}
@@ -82,6 +84,23 @@ fn check_path(vexe string, dir string, tests []string) int {
cmd: '${os.quoted_path(vexe)} doc -readme -comments ${os.quoted_path(program)}'
out_filename: 'main.readme.comments.out'
)
+ // test the main 3 different formats:
+ fails += check_output(
+ program: program
+ cmd: '${os.quoted_path(vexe)} doc -f html -o - -html-only-contents -readme -comments ${os.quoted_path(program)}'
+ out_filename: 'main.html'
+ )
+ fails += check_output(
+ program: program
+ cmd: '${os.quoted_path(vexe)} doc -f ansi -o - -html-only-contents -readme -comments ${os.quoted_path(program)}'
+ out_filename: 'main.ansi'
+ )
+ fails += check_output(
+ program: program
+ cmd: '${os.quoted_path(vexe)} doc -f text -o - -html-only-contents -readme -comments ${os.quoted_path(program)}'
+ out_filename: 'main.text'
+ )
+ //
total_fails += fails
if fails == 0 {
println(term.green('OK'))
@@ -141,9 +160,13 @@ fn check_output(params CheckOutputParams) int {
found := clean_line_endings(res.output)
if expected != found {
print_compare(expected, found)
- eprintln('>>> out_file_path: ${out_file_path}')
eprintln('>>> cmd: VDOC_SORT=${params.should_sort} ${params.cmd}')
+ eprintln('>>> out_file_path: `${out_file_path}`')
+ eprintln('>>> fix: VDOC_SORT=${params.should_sort} ${params.cmd} > ${out_file_path}')
fails++
}
+ if should_autofix {
+ os.write_file(out_file_path, res.output) or {}
+ }
return fails
}
diff --git a/cmd/tools/vdoc/utils.v b/cmd/tools/vdoc/utils.v
index 5251af071d..1ab5bfbafb 100644
--- a/cmd/tools/vdoc/utils.v
+++ b/cmd/tools/vdoc/utils.v
@@ -60,14 +60,14 @@ fn trim_doc_node_description(description string) string {
}
fn set_output_type_from_str(format string) OutputType {
- output_type := match format {
+ return match format {
'htm', 'html' { OutputType.html }
- 'md', 'markdown' { OutputType.markdown }
- 'json' { OutputType.json }
- 'stdout' { OutputType.stdout }
- else { OutputType.plaintext }
+ 'md', 'markdown' { .markdown }
+ 'json' { .json }
+ 'text' { .plaintext }
+ 'ansi' { .ansi }
+ else { .ansi }
}
- return output_type
}
fn get_ignore_paths(path string) ![]string {
@@ -213,10 +213,13 @@ fn color_highlight(code string, tb &ast.Table) string {
} else if
(next_tok.kind in [.lcbr, .rpar, .eof, .comma, .pipe, .name, .rcbr, .assign, .key_pub, .key_mut, .pipe, .comma, .comment, .lt, .lsbr]
&& next_tok.lit !in builtin)
- && (prev.kind in [.name, .amp, .lcbr, .rsbr, .key_type, .assign, .dot, .question, .rpar, .key_struct, .key_enum, .pipe, .key_interface, .comment, .ellipsis]
+ && (prev.kind in [.name, .amp, .lcbr, .rsbr, .key_type, .assign, .dot, .not, .question, .rpar, .key_struct, .key_enum, .pipe, .key_interface, .comment, .ellipsis, .comma]
&& prev.lit !in builtin) && ((tok.lit != '' && tok.lit[0].is_capital())
|| prev_prev.lit in ['C', 'JS']) {
tok_typ = .symbol
+ } else if tok.lit[0].is_capital() && prev.kind == .lpar
+ && next_tok.kind == .comma {
+ tok_typ = .symbol
} else if next_tok.kind == .lpar
|| (!(tok.lit != '' && tok.lit[0].is_capital())
&& next_tok.kind in [.lt, .lsbr] && next_tok.pos == tok.pos + tok.lit.len) {
diff --git a/cmd/tools/vdoc/vdoc.v b/cmd/tools/vdoc/vdoc.v
index 8189694575..3950867a7c 100644
--- a/cmd/tools/vdoc/vdoc.v
+++ b/cmd/tools/vdoc/vdoc.v
@@ -17,8 +17,8 @@ enum OutputType {
html
markdown
json
+ ansi // text with ANSI color escapes
plaintext
- stdout
}
@[heap]
@@ -36,28 +36,6 @@ mut:
example_oks int // how many ok examples were found when `-run-examples` was passed, that compiled and finished with 0 exit code.
}
-struct Config {
-mut:
- pub_only bool = true
- show_loc bool // for plaintext
- is_color bool
- is_multi bool
- is_vlib bool
- is_verbose bool
- include_readme bool
- include_examples bool = true
- include_comments bool // for plaintext
- inline_assets bool
- theme_dir string = default_theme
- no_timestamp bool
- output_path string
- output_type OutputType = .unset
- input_path string
- symbol_name string
- platform doc.Platform
- run_examples bool // `-run-examples` will run all `// Example: assert mod.abc() == y` comments in the processed modules
-}
-
//
struct Output {
mut:
@@ -279,7 +257,7 @@ fn (mut vd VDoc) generate_docs_from_file() {
}
if out.path.len == 0 {
if cfg.output_type == .unset {
- out.typ = .stdout
+ out.typ = .ansi
} else {
vd.vprintln('No output path has detected. Using input path instead.')
out.path = cfg.input_path
@@ -289,7 +267,7 @@ fn (mut vd VDoc) generate_docs_from_file() {
ext := os.file_ext(out.path)
out.typ = set_output_type_from_str(ext.all_after('.'))
}
- if cfg.include_readme && out.typ !in [.html, .stdout] {
+ if cfg.include_readme && out.typ !in [.html, .ansi, .plaintext] {
eprintln('vdoc: Including README.md for doc generation is supported on HTML output, or when running directly in the terminal.')
exit(1)
}
@@ -312,7 +290,7 @@ fn (mut vd VDoc) generate_docs_from_file() {
comment := doc.DocComment{
text: readme_contents
}
- if out.typ == .stdout {
+ if out.typ == .ansi {
println(markdown.to_plain(readme_contents))
} else if out.typ == .html && cfg.is_multi {
vd.docs << doc.Doc{
@@ -365,7 +343,7 @@ fn (mut vd VDoc) generate_docs_from_file() {
exit(1)
}
vd.vprintln('Rendering docs...')
- if out.path.len == 0 || out.path == 'stdout' {
+ if out.path.len == 0 || out.path == 'stdout' || out.path == '-' {
if out.typ == .html {
vd.render_static_html(out)
}
diff --git a/vlib/v/help/common/doc.txt b/vlib/v/help/common/doc.txt
index 7683f92b89..bbdf91d613 100644
--- a/vlib/v/help/common/doc.txt
+++ b/vlib/v/help/common/doc.txt
@@ -11,22 +11,20 @@ Examples:
v doc -m -f html vlib/
Generates the documentation of a given MODULE, DIRECTORY, or FILE
- and prints or saves them to its desired format. It can generate HTML, JSON,
- or Markdown format.
+ and prints or saves them to its desired format: HTML, JSON,
+ TEXT, ANSI or Markdown.
Options:
-all Includes private and public functions/methods/structs/consts/enums.
+ -color Forces the use of ANSI escape sequences to make the output colorful.
+ -no-color Forces plain text output, without ANSI colors.
+ Note: -color is on for -f ansi .
-f Specifies the output format to be used.
- Available formats are:
- md/markdown, json, text, stdout and html/htm
+ Available formats are: md/markdown, json, text, ansi and html/htm.
-h, -help Prints this help text.
-m Generate docs for modules listed in that folder.
- -o Specifies the output file/folder path where to store the
- generated docs.
- Set it to "stdout" to print the output instead of saving
- the contents to a file.
- -color Forces stdout colorize output.
- -no-color Forces plain text output, without ANSI colors.
+ -o The output file/folder path where to store the docs. Use `-o stdout`
+ or `-o -', to print the output instead of saving it to a file.
-readme Include README.md to docs if present.
-v Enables verbose logging. For debugging purposes.
-no-timestamp Omits the timestamp in the output file.
@@ -36,7 +34,18 @@ For HTML mode:
webpage directly.
-theme-dir The directory for doc theme template
-For plain text mode:
+The following options are useful for tests, that need stable output.
+They will omit generating text that is prone to changes, due to styling,
+but that otherwise do not affect the content.
+ -html-only-contents Produce just the main content of the page,
+ without theming, styling, CSS and JS tags etc.
+ -html-no-vhash Omits the version hash.
+ -html-no-assets Omits the CSS and JS asset tags.
+ -html-no-right Omits the doc-toc right panel.
+ -html-no-toc-urls Omits the toc_links panel
+ -html-no-footer Omits the footer panel.
+
+For the text and ansi modes:
-l Shows the locations of the generated signatures.
-comments Includes comments in the output.