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 os
import v.doc import v.doc
import term
import v.table
import v.scanner
import v.token
import strings
import v.pref
[inline] [inline]
fn slug(title string) string { 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()' time_str := '$generated_time.day $generated_time.smonth() $generated_time.year $generated_time.hhmmss()'
return '$footer_text Generated on: $time_str' 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.pref
import v.vmod import v.vmod
import json import json
import term
const ( const (
allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm'] allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm']
@ -44,6 +45,7 @@ struct Config {
mut: mut:
pub_only bool = true pub_only bool = true
show_loc bool // for plaintext show_loc bool // for plaintext
is_color bool
is_multi bool is_multi bool
is_vlib bool is_vlib bool
is_verbose 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 { fn (vd VDoc) gen_plaintext(d doc.Doc) string {
cfg := vd.cfg cfg := vd.cfg
mut pw := strings.new_builder(200) 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 { comments := if cfg.include_examples {
d.head.merge_comments() d.head.merge_comments()
} else { } else {
@ -103,7 +110,11 @@ fn (vd VDoc) write_plaintext_content(contents []doc.DocNode, mut pw strings.Buil
cfg := vd.cfg cfg := vd.cfg
for cn in contents { for cn in contents {
if cn.content.len > 0 { 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 { if cn.comments.len > 0 && !cfg.pub_only {
comments := if cfg.include_examples { comments := if cfg.include_examples {
cn.merge_comments() cn.merge_comments()
@ -369,6 +380,7 @@ fn (vd VDoc) vprintln(str string) {
fn parse_arguments(args []string) Config { fn parse_arguments(args []string) Config {
mut cfg := Config{} mut cfg := Config{}
cfg.is_color = term.can_show_color_on_stdout()
for i := 0; i < args.len; i++ { for i := 0; i < args.len; i++ {
arg := args[i] arg := args[i]
current_args := 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) cfg.output_type = set_output_type_from_str(format)
i++ i++
} }
'-color' {
cfg.is_color = true
}
'-no-color' {
cfg.is_color = false
}
'-inline-assets' { '-inline-assets' {
cfg.inline_assets = true cfg.inline_assets = true
} }

View File

@ -4,6 +4,7 @@ Usage:
Examples: Examples:
v doc os v doc os
v doc os File v doc os File
v doc -no-color os
v doc -o math.html math v doc -o math.html math
v doc -m -f html vlib/ v doc -m -f html vlib/
@ -20,6 +21,8 @@ Options:
-o Specifies the output file/folder path where to store the generated docs. -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 Set it to "stdout" to print the output instead of saving the contents
to a file. 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. -readme Include README.md to docs if present.
-v Enables verbose logging. For debugging purposes. -v Enables verbose logging. For debugging purposes.
-no-timestamp Omits the timestamp in the output file. -no-timestamp Omits the timestamp in the output file.