tools: implement `cgen` tag for Markdown examples in `v check-md` (#13332)
							parent
							
								
									b34860e39b
								
							
						
					
					
						commit
						db50e79d26
					
				| 
						 | 
					@ -21,6 +21,7 @@ const (
 | 
				
			||||||
	hide_warnings                  = '-hide-warnings' in os.args || '-w' in os.args
 | 
						hide_warnings                  = '-hide-warnings' in os.args || '-w' in os.args
 | 
				
			||||||
	show_progress                  = os.getenv('GITHUB_JOB') == '' && '-silent' !in os.args
 | 
						show_progress                  = os.getenv('GITHUB_JOB') == '' && '-silent' !in os.args
 | 
				
			||||||
	non_option_args                = cmdline.only_non_options(os.args[2..])
 | 
						non_option_args                = cmdline.only_non_options(os.args[2..])
 | 
				
			||||||
 | 
						is_verbose                     = os.getenv('VERBOSE') != ''
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct CheckResult {
 | 
					struct CheckResult {
 | 
				
			||||||
| 
						 | 
					@ -75,7 +76,7 @@ fn main() {
 | 
				
			||||||
		res += mdfile.check()
 | 
							res += mdfile.check()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if res.errors == 0 && show_progress {
 | 
						if res.errors == 0 && show_progress {
 | 
				
			||||||
		term.clear_previous_line()
 | 
							clear_previous_line()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if res.warnings > 0 || res.errors > 0 || res.oks > 0 {
 | 
						if res.warnings > 0 || res.errors > 0 || res.oks > 0 {
 | 
				
			||||||
		println('\nWarnings: $res.warnings | Errors: $res.errors | OKs: $res.oks')
 | 
							println('\nWarnings: $res.warnings | Errors: $res.errors | OKs: $res.oks')
 | 
				
			||||||
| 
						 | 
					@ -131,9 +132,7 @@ fn eline(file_path string, lnumber int, column int, message string) string {
 | 
				
			||||||
	return btext('$file_path:${lnumber + 1}:${column + 1}:') + btext(rtext(' error: $message'))
 | 
						return btext('$file_path:${lnumber + 1}:${column + 1}:') + btext(rtext(' error: $message'))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const default_command = 'compile'
 | 
				
			||||||
	default_command = 'compile'
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct VCodeExample {
 | 
					struct VCodeExample {
 | 
				
			||||||
mut:
 | 
					mut:
 | 
				
			||||||
| 
						 | 
					@ -160,7 +159,7 @@ mut:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn (mut f MDFile) progress(message string) {
 | 
					fn (mut f MDFile) progress(message string) {
 | 
				
			||||||
	if show_progress {
 | 
						if show_progress {
 | 
				
			||||||
		term.clear_previous_line()
 | 
							clear_previous_line()
 | 
				
			||||||
		println('File: ${f.path:-30s}, Lines: ${f.lines.len:5}, $message')
 | 
							println('File: ${f.path:-30s}, Lines: ${f.lines.len:5}, $message')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -394,6 +393,7 @@ fn (mut f MDFile) debug() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn cmdexecute(cmd string) int {
 | 
					fn cmdexecute(cmd string) int {
 | 
				
			||||||
 | 
						verbose_println(cmd)
 | 
				
			||||||
	res := os.execute(cmd)
 | 
						res := os.execute(cmd)
 | 
				
			||||||
	if res.exit_code < 0 {
 | 
						if res.exit_code < 0 {
 | 
				
			||||||
		return 1
 | 
							return 1
 | 
				
			||||||
| 
						 | 
					@ -405,6 +405,7 @@ fn cmdexecute(cmd string) int {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn silent_cmdexecute(cmd string) int {
 | 
					fn silent_cmdexecute(cmd string) int {
 | 
				
			||||||
 | 
						verbose_println(cmd)
 | 
				
			||||||
	res := os.execute(cmd)
 | 
						res := os.execute(cmd)
 | 
				
			||||||
	return res.exit_code
 | 
						return res.exit_code
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -426,6 +427,7 @@ fn (mut f MDFile) check_examples() CheckResult {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		fname := os.base(f.path).replace('.md', '_md')
 | 
							fname := os.base(f.path).replace('.md', '_md')
 | 
				
			||||||
		uid := rand.ulid()
 | 
							uid := rand.ulid()
 | 
				
			||||||
 | 
							cfile := os.join_path(os.temp_dir(), '${uid}.c')
 | 
				
			||||||
		vfile := os.join_path(os.temp_dir(), 'check_${fname}_example_${e.sline}__${e.eline}__${uid}.v')
 | 
							vfile := os.join_path(os.temp_dir(), 'check_${fname}_example_${e.sline}__${e.eline}__${uid}.v')
 | 
				
			||||||
		mut should_cleanup_vfile := true
 | 
							mut should_cleanup_vfile := true
 | 
				
			||||||
		// eprintln('>>> checking example $vfile ...')
 | 
							// eprintln('>>> checking example $vfile ...')
 | 
				
			||||||
| 
						 | 
					@ -438,8 +440,7 @@ fn (mut f MDFile) check_examples() CheckResult {
 | 
				
			||||||
			fmt_res := if nofmt { 0 } else { get_fmt_exit_code(vfile, vexe) }
 | 
								fmt_res := if nofmt { 0 } else { get_fmt_exit_code(vfile, vexe) }
 | 
				
			||||||
			match command {
 | 
								match command {
 | 
				
			||||||
				'compile' {
 | 
									'compile' {
 | 
				
			||||||
					res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o x.c ${os.quoted_path(vfile)}')
 | 
										res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors ${os.quoted_path(vfile)}')
 | 
				
			||||||
					os.rm('x.c') or {}
 | 
					 | 
				
			||||||
					if res != 0 || fmt_res != 0 {
 | 
										if res != 0 || fmt_res != 0 {
 | 
				
			||||||
						if res != 0 {
 | 
											if res != 0 {
 | 
				
			||||||
							eprintln(eline(f.path, e.sline, 0, 'example failed to compile'))
 | 
												eprintln(eline(f.path, e.sline, 0, 'example failed to compile'))
 | 
				
			||||||
| 
						 | 
					@ -454,9 +455,26 @@ fn (mut f MDFile) check_examples() CheckResult {
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					oks++
 | 
										oks++
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
									'cgen' {
 | 
				
			||||||
 | 
										res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
 | 
				
			||||||
 | 
										os.rm(cfile) or {}
 | 
				
			||||||
 | 
										if res != 0 || fmt_res != 0 {
 | 
				
			||||||
 | 
											if res != 0 {
 | 
				
			||||||
 | 
												eprintln(eline(f.path, e.sline, 0, 'example failed to generate C code'))
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											if fmt_res != 0 {
 | 
				
			||||||
 | 
												eprintln(eline(f.path, e.sline, 0, 'example is not formatted'))
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											eprintln(vcontent)
 | 
				
			||||||
 | 
											should_cleanup_vfile = false
 | 
				
			||||||
 | 
											errors++
 | 
				
			||||||
 | 
											continue
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										oks++
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				'globals' {
 | 
									'globals' {
 | 
				
			||||||
					res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -enable-globals -o x.c ${os.quoted_path(vfile)}')
 | 
										res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -enable-globals -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
 | 
				
			||||||
					os.rm('x.c') or {}
 | 
										os.rm(cfile) or {}
 | 
				
			||||||
					if res != 0 || fmt_res != 0 {
 | 
										if res != 0 || fmt_res != 0 {
 | 
				
			||||||
						if res != 0 {
 | 
											if res != 0 {
 | 
				
			||||||
							eprintln(eline(f.path, e.sline, 0, '`example failed to compile with -enable-globals'))
 | 
												eprintln(eline(f.path, e.sline, 0, '`example failed to compile with -enable-globals'))
 | 
				
			||||||
| 
						 | 
					@ -472,7 +490,8 @@ fn (mut f MDFile) check_examples() CheckResult {
 | 
				
			||||||
					oks++
 | 
										oks++
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				'live' {
 | 
									'live' {
 | 
				
			||||||
					res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -live -o x.c ${os.quoted_path(vfile)}')
 | 
										res := cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -live -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
 | 
				
			||||||
 | 
										os.rm(cfile) or {}
 | 
				
			||||||
					if res != 0 || fmt_res != 0 {
 | 
										if res != 0 || fmt_res != 0 {
 | 
				
			||||||
						if res != 0 {
 | 
											if res != 0 {
 | 
				
			||||||
							eprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live'))
 | 
												eprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live'))
 | 
				
			||||||
| 
						 | 
					@ -488,8 +507,8 @@ fn (mut f MDFile) check_examples() CheckResult {
 | 
				
			||||||
					oks++
 | 
										oks++
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				'failcompile' {
 | 
									'failcompile' {
 | 
				
			||||||
					res := silent_cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o x.c ${os.quoted_path(vfile)}')
 | 
										res := silent_cmdexecute('${os.quoted_path(vexe)} -w -Wfatal-errors -o ${os.quoted_path(cfile)} ${os.quoted_path(vfile)}')
 | 
				
			||||||
					os.rm('x.c') or {}
 | 
										os.rm(cfile) or {}
 | 
				
			||||||
					if res == 0 || fmt_res != 0 {
 | 
										if res == 0 || fmt_res != 0 {
 | 
				
			||||||
						if res == 0 {
 | 
											if res == 0 {
 | 
				
			||||||
							eprintln(eline(f.path, e.sline, 0, '`failcompile` example compiled'))
 | 
												eprintln(eline(f.path, e.sline, 0, '`failcompile` example compiled'))
 | 
				
			||||||
| 
						 | 
					@ -533,7 +552,7 @@ fn (mut f MDFile) check_examples() CheckResult {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				'nofmt' {}
 | 
									'nofmt' {}
 | 
				
			||||||
				else {
 | 
									else {
 | 
				
			||||||
					eprintln(eline(f.path, e.sline, 0, 'unrecognized command: "$command", use one of: wip/ignore/compile/failcompile/oksyntax/badsyntax'))
 | 
										eprintln(eline(f.path, e.sline, 0, 'unrecognized command: "$command", use one of: wip/ignore/compile/cgen/failcompile/oksyntax/badsyntax/nofmt'))
 | 
				
			||||||
					should_cleanup_vfile = false
 | 
										should_cleanup_vfile = false
 | 
				
			||||||
					errors++
 | 
										errors++
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -548,3 +567,16 @@ fn (mut f MDFile) check_examples() CheckResult {
 | 
				
			||||||
		oks: oks
 | 
							oks: oks
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn verbose_println(message string) {
 | 
				
			||||||
 | 
						if is_verbose {
 | 
				
			||||||
 | 
							println(message)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn clear_previous_line() {
 | 
				
			||||||
 | 
						if is_verbose {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						term.clear_previous_line()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ Flags:
 | 
				
			||||||
NB: There are several special keywords, which you can put after the code fences for v.
 | 
					NB: There are several special keywords, which you can put after the code fences for v.
 | 
				
			||||||
These are:
 | 
					These are:
 | 
				
			||||||
	compile      - Default, can be omitted. The example will be compiled and formatting is verified.
 | 
						compile      - Default, can be omitted. The example will be compiled and formatting is verified.
 | 
				
			||||||
 | 
						cgen         - The example produces C code, which may not be compilable (when external libs are not installed). Formatting is verified.
 | 
				
			||||||
	live         - Compile hot reload examples with the ´-live´ flag set and verify formatting.
 | 
						live         - Compile hot reload examples with the ´-live´ flag set and verify formatting.
 | 
				
			||||||
	ignore       - Ignore the example, useful for examples that just use the syntax highlighting
 | 
						ignore       - Ignore the example, useful for examples that just use the syntax highlighting
 | 
				
			||||||
	failcompile  - Known failing compilation. Useful for examples demonstrating compiler errors.
 | 
						failcompile  - Known failing compilation. Useful for examples demonstrating compiler errors.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,7 +163,7 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<!--
 | 
					<!--
 | 
				
			||||||
NB: there are several special keywords, which you can put after the code fences for v:
 | 
					NB: there are several special keywords, which you can put after the code fences for v:
 | 
				
			||||||
compile, live, ignore, failcompile, oksyntax, badsyntax, wip, nofmt
 | 
					compile, cgen, live, ignore, failcompile, oksyntax, badsyntax, wip, nofmt
 | 
				
			||||||
For more details, do: `v check-md`
 | 
					For more details, do: `v check-md`
 | 
				
			||||||
-->
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1393,7 +1393,7 @@ println(s)
 | 
				
			||||||
You can check the current type of a sum type using `is` and its negated form `!is`.
 | 
					You can check the current type of a sum type using `is` and its negated form `!is`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can do it either in an `if`:
 | 
					You can do it either in an `if`:
 | 
				
			||||||
```v
 | 
					```v cgen
 | 
				
			||||||
struct Abc {
 | 
					struct Abc {
 | 
				
			||||||
	val string
 | 
						val string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -5102,6 +5102,7 @@ For all supported options check the latest help:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `$if` condition
 | 
					#### `$if` condition
 | 
				
			||||||
```v
 | 
					```v
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
	// Support for multiple conditions in one branch
 | 
						// Support for multiple conditions in one branch
 | 
				
			||||||
	$if ios || android {
 | 
						$if ios || android {
 | 
				
			||||||
		println('Running on a mobile device!')
 | 
							println('Running on a mobile device!')
 | 
				
			||||||
| 
						 | 
					@ -5137,6 +5138,7 @@ $if prod {
 | 
				
			||||||
	$if option ? {
 | 
						$if option ? {
 | 
				
			||||||
		println('custom option')
 | 
							println('custom option')
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you want an `if` to be evaluated at compile time it must be prefixed with a `$` sign.
 | 
					If you want an `if` to be evaluated at compile time it must be prefixed with a `$` sign.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ user's keyboard/mouse input.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Example:
 | 
					## Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```v
 | 
					```v cgen
 | 
				
			||||||
module main
 | 
					module main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import gg
 | 
					import gg
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ Each `.h` file in the sokol source code is well-documented as can be seen here:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Example from `@VROOTDIR/examples/sokol/sounds/simple_sin_tones.v`:
 | 
					## Example from `@VROOTDIR/examples/sokol/sounds/simple_sin_tones.v`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```v
 | 
					```v cgen
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
import math
 | 
					import math
 | 
				
			||||||
import sokol.audio
 | 
					import sokol.audio
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue