v doc: implement color highlighting for the stdout format, enable it by default (#9312)

pull/9314/head
Swastik Baranwal 2021-03-15 16:51:19 +05:30 committed by GitHub
parent 2d2e4610e7
commit 26138f98af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 132 additions and 2 deletions

View File

@ -2,6 +2,12 @@ module main
import os
import v.doc
import term
import v.table
import v.scanner
import v.token
import strings
import v.pref
[inline]
fn slug(title string) string {
@ -130,3 +136,106 @@ fn gen_footer_text(d &doc.Doc, include_timestamp bool) string {
time_str := '$generated_time.day $generated_time.smonth() $generated_time.year $generated_time.hhmmss()'
return '$footer_text Generated on: $time_str'
}
fn color_highlight(code string, tb &table.Table) string {
builtin := ['bool', 'string', 'i8', 'i16', 'int', 'i64', 'i128', 'byte', 'u16', 'u32', 'u64',
'u128', 'rune', 'f32', 'f64', 'int_literal', 'float_literal', 'byteptr', 'voidptr', 'any']
highlight_code := fn (tok token.Token, typ HighlightTokenTyp) string {
lit := match typ {
.unone, .operator, .punctuation {
tok.kind.str()
}
.string {
term.yellow("'$tok.lit'")
}
.char {
term.yellow('`$tok.lit`')
}
.keyword {
term.blue(tok.lit)
}
.builtin, .symbol {
term.green(tok.lit)
}
.function {
term.cyan(tok.lit)
}
.number {
term.bright_blue(tok.lit)
}
else {
tok.lit
}
}
return lit
}
mut s := scanner.new_scanner(code, .parse_comments, &pref.Preferences{})
mut prev := token.Token{}
mut tok := s.scan()
mut next_tok := s.scan()
mut buf := strings.new_builder(200)
mut i := 0
for i < code.len {
if i == tok.pos {
mut tok_typ := HighlightTokenTyp.unone
match tok.kind {
.name {
if (tok.lit in builtin || tb.known_type(tok.lit))
&& (next_tok.kind != .lpar || prev.kind != .key_fn) {
tok_typ = .builtin
} else if next_tok.kind in [.lcbr, .rpar, .eof]
&& (next_tok.kind != .rpar || prev.kind in [.name, .amp]) {
tok_typ = .symbol
} else if next_tok.kind in [.lpar, .lt] {
tok_typ = .function
} else {
tok_typ = .name
}
}
.comment {
tok_typ = .comment
}
.chartoken {
tok_typ = .char
}
.string {
tok_typ = .string
}
.number {
tok_typ = .number
}
.key_true, .key_false {
tok_typ = .boolean
}
.lpar, .lcbr, .rpar, .rcbr, .lsbr, .rsbr, .semicolon, .colon, .comma, .dot {
tok_typ = .punctuation
}
else {
if token.is_key(tok.lit) || token.is_decl(tok.kind) {
tok_typ = .keyword
} else if tok.kind == .decl_assign || tok.kind.is_assign() || tok.is_unary()
|| tok.kind.is_relational() || tok.kind.is_infix() {
tok_typ = .operator
}
}
}
buf.write_string(highlight_code(tok, tok_typ))
if prev.kind != .eof {
prev = tok
} else {
break
}
if next_tok.kind != .eof {
i = tok.pos + tok.len
tok = next_tok
next_tok = s.scan()
} else {
break
}
} else {
buf.write_b(code[i])
i++
}
}
return buf.str()
}

View File

@ -11,6 +11,7 @@ import v.doc
import v.pref
import v.vmod
import json
import term
const (
allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm']
@ -44,6 +45,7 @@ struct Config {
mut:
pub_only bool = true
show_loc bool // for plaintext
is_color bool
is_multi bool
is_vlib bool
is_verbose bool
@ -86,7 +88,12 @@ fn (vd VDoc) gen_json(d doc.Doc) string {
fn (vd VDoc) gen_plaintext(d doc.Doc) string {
cfg := vd.cfg
mut pw := strings.new_builder(200)
pw.writeln('$d.head.content\n')
if cfg.is_color {
content_arr := d.head.content.split(' ')
pw.writeln('${term.blue(content_arr[0])} ${term.green(content_arr[1])}\n')
} else {
pw.writeln('$d.head.content\n')
}
comments := if cfg.include_examples {
d.head.merge_comments()
} else {
@ -103,7 +110,11 @@ fn (vd VDoc) write_plaintext_content(contents []doc.DocNode, mut pw strings.Buil
cfg := vd.cfg
for cn in contents {
if cn.content.len > 0 {
pw.writeln(cn.content)
if cfg.is_color {
pw.writeln(color_highlight(cn.content, vd.docs[0].table))
} else {
pw.writeln(cn.content)
}
if cn.comments.len > 0 && !cfg.pub_only {
comments := if cfg.include_examples {
cn.merge_comments()
@ -369,6 +380,7 @@ fn (vd VDoc) vprintln(str string) {
fn parse_arguments(args []string) Config {
mut cfg := Config{}
cfg.is_color = term.can_show_color_on_stdout()
for i := 0; i < args.len; i++ {
arg := args[i]
current_args := args[i..]
@ -386,6 +398,12 @@ fn parse_arguments(args []string) Config {
cfg.output_type = set_output_type_from_str(format)
i++
}
'-color' {
cfg.is_color = true
}
'-no-color' {
cfg.is_color = false
}
'-inline-assets' {
cfg.inline_assets = true
}

View File

@ -4,6 +4,7 @@ Usage:
Examples:
v doc os
v doc os File
v doc -no-color os
v doc -o math.html math
v doc -m -f html vlib/
@ -20,6 +21,8 @@ Options:
-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 Force stdout colorize output.
-no-color Force plain text output, without ANSI colors.
-readme Include README.md to docs if present.
-v Enables verbose logging. For debugging purposes.
-no-timestamp Omits the timestamp in the output file.