check-md: verify code example formatting (#7143)

pull/7152/head
Lukas Neubert 2020-12-05 22:54:41 +01:00 committed by GitHub
parent 0d28f12c54
commit 8adb1acf31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 836 additions and 752 deletions

View File

@ -227,7 +227,7 @@ https://github.com/vlang/ui
```v
fn main() {
for i in 0..3 {
for i in 0 .. 3 {
println('Hello from V.js')
}
}

View File

@ -102,7 +102,6 @@ fn eline(file_path string, lnumber int, column int, message string) string {
return btext('$file_path:${lnumber + 1}:${column + 1}:') + btext(rtext(' error: $message'))
}
//
const (
default_command = 'compile'
)
@ -190,16 +189,23 @@ fn (mut f MDFile) check_examples() (int, int) {
vfile := os.join_path(os.temp_dir(), 'check_${fname}_example_${e.sline}__${e.eline}__${uid}.v')
mut should_cleanup_vfile := true
// eprintln('>>> checking example $vfile ...')
vcontent := e.text.join('\n')
vcontent := e.text.join('\n') + '\n'
os.write_file(vfile, vcontent) or { panic(err) }
mut acommands := e.command.split(' ')
nofmt := 'nofmt' in acommands
for command in acommands {
match command {
'compile' {
res := os.system('"$vexe" -w -Wfatal-errors -o x.c $vfile')
os.rm('x.c') or { }
fmt_res := if nofmt { 0 } else { os.system('"$vexe" fmt -verify $vfile') }
if res != 0 || fmt_res != 0 {
if res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example failed to compile'))
}
if fmt_res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example is not formatted'))
}
eprintln(vcontent)
should_cleanup_vfile = false
errors++
@ -209,8 +215,14 @@ fn (mut f MDFile) check_examples() (int, int) {
}
'live' {
res := os.system('"$vexe" -w -Wfatal-errors -live -o x.c $vfile')
fmt_res := if nofmt { 0 } else { os.system('"$vexe" fmt -verify $vfile') }
if res != 0 || fmt_res != 0 {
if res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live'))
}
if fmt_res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example is not formatted'))
}
eprintln(vcontent)
should_cleanup_vfile = false
errors++
@ -232,8 +244,14 @@ fn (mut f MDFile) check_examples() (int, int) {
}
'oksyntax' {
res := os.system('"$vexe" -w -Wfatal-errors -check-syntax $vfile')
fmt_res := if nofmt { 0 } else { os.system('"$vexe" fmt -verify $vfile') }
if res != 0 || fmt_res != 0 {
if res != 0 {
eprintln(eline(f.path, e.sline, 0, '`oksyntax` example with invalid syntax'))
}
if fmt_res != 0 {
eprintln(eline(f.path, e.sline, 0, '`oksyntax` example is not formatted'))
}
eprintln(vcontent)
should_cleanup_vfile = false
errors++
@ -252,6 +270,7 @@ fn (mut f MDFile) check_examples() (int, int) {
}
oks++
}
'nofmt' {}
else {
eprintln(eline(f.path, e.sline, 0, 'unrecognized command: "$command", use one of: wip/ignore/compile/failcompile/oksyntax/badsyntax'))
should_cleanup_vfile = false

File diff suppressed because it is too large Load Diff

View File

@ -75,8 +75,11 @@ pub fn (mut app App) index() vweb.Result {
return vweb.Result{}
}
pub fn (app &App) init() {}
pub fn (app &App) init_once() {}
pub fn (app &App) init() {
}
pub fn (app &App) init_once() {
}
```
Run it with
@ -103,6 +106,8 @@ no routing rules either:
```v oksyntax
import vweb
import time
fn (mut app App) time() vweb.Result {
app.vweb.text(time.now().format())
return vweb.Result{}
@ -341,6 +346,7 @@ Create `new.html`:
```v oksyntax
import vweb
pub fn (mut app App) new_article() vweb.Result {
title := app.vweb.form['title']
text := app.vweb.form['text']
@ -380,6 +386,8 @@ in V is very simple:
```v oksyntax
import vweb
import json
pub fn (mut app App) articles() vweb.Result {
articles := app.find_all_articles()
app.vweb.json(json.encode(articles))

View File

@ -1,42 +1,43 @@
Example usage of this module:
```
```v
import benchmark
mut bmark := benchmark.new_benchmark()
// by default the benchmark will be verbose, i.e. it will include timing information
// if you want it to be silent, set bmark.verbose = false
for {
bmark.step() // call this when you want to advance the benchmark.
// The timing info in bmark.step_message will be measured starting from the last call to bmark.step
....
//bmark.fail() // call this if the step failed
//bmark.step_message(('failed')
// ....
// bmark.fail() // call this if the step failed
// bmark.step_message(('failed')
bmark.ok() // call this when the step succeeded
println( bmark.step_message('ok')
println(bmark.step_message('ok'))
}
bmark.stop() // call when you want to finalize the benchmark
println( bmark.total_message('remarks about the benchmark') )
bmark.stop()
// call when you want to finalize the benchmark
println(bmark.total_message('remarks about the benchmark'))
```
benchmark.start() and b.measure() are convenience methods,
intended to be used in combination. Their goal is to make
benchmarking of small snippets of code as *short*, easy to
write, and then to read and analyze the results, as possible.
Example:
```v
import time
import benchmark
mut b := benchmark.start()
mut b := benchmark.start()
// your code section 1 ...
time.sleep_ms(1500)
b.measure('code_1')
// your code section 2 ...
time.sleep_ms(500)
b.measure('code_2')
```
... which will produce on stdout something like this:
```text
SPENT 1500.063 ms in code_1

View File

@ -5,13 +5,13 @@ import encoding.csv
data := 'x,y\na,b,c\n'
mut parser := csv.new_reader(data)
// read each line
for {
items := parser.read() or {break}
items := parser.read() or { break }
println(items)
}
```
It prints:
```
['x', 'y']

View File

@ -40,9 +40,9 @@ struct ClickEvent {
}
// Example case where publisher sends ClickEvent as args.
fn on_press(receiver voidptr, e &ClickEvent, sender voidptr){
fn on_press(receiver voidptr, e &ClickEvent, sender voidptr) {
println(e.x)
//your code here...
// your code here...
}
```
@ -57,6 +57,7 @@ _Note: As a general rule, you will need to **subscribe before publishing**._
```v oksyntax
module main
import eventbus
// initialize it globally
@ -64,18 +65,18 @@ const (
eb = eventbus.new()
)
fn main(){
fn main() {
// get a mutable reference to the subscriber
mut sub := eb.subscriber
// subscribe to the 'error' event
sub.subscribe("error", on_error)
sub.subscribe('error', on_error)
// start the work
do_work()
}
// the event handler
fn on_error(receiver voidptr, e &Error, work &Work) {
println('error occured on ${work.hours}. Error: ${e.message}')
println('error occured on ${work.hours}. Error: $e.message')
}
```
@ -84,7 +85,7 @@ fn on_error(receiver voidptr, e &Error, work &Work) {
```v oksyntax
module main
struct Work{
struct Work {
hours int
}
@ -92,12 +93,12 @@ struct Error {
message string
}
fn do_work(){
fn do_work() {
work := Work{20}
// get a mutable Params instance & put some data into it
error := &Error{"Error: no internet connection."}
error := &Error{'Error: no internet connection.'}
// publish the event
eb.publish("error", work, error)
eb.publish('error', work, error)
}
```

View File

@ -160,20 +160,17 @@ that is an `[]int` inside the `RE` struct.
**example:**
```v oksyntax
text := "cpaz cpapaz cpapapaz"
query:= r"(c(pa)+z ?)+"
text := 'cpaz cpapaz cpapapaz'
query := r'(c(pa)+z ?)+'
mut re := regex.regex_opt(query) or { panic(err) }
println(re.get_query())
// #0(c#1(pa)+z ?)+ // #0 and #1 are the ids of the groups, are shown if re.debug is 1 or 2
start, end := re.match_string(text)
// [start=0, end=20] match => [cpaz cpapaz cpapapaz]
mut gi := 0
for gi < re.groups.len {
if re.groups[gi] >= 0 {
println("${gi/2} :[${text[re.groups[gi]..re.groups[gi+1]]}]")
println('${gi / 2} :[${text[re.groups[gi]..re.groups[gi + 1]]}]')
}
gi += 2
}
@ -260,43 +257,40 @@ If the space ends no error is raised, further records will not be saved.
```v oksyntax
fn example2() {
test_regex()
text := "tst: 01,23,45 ,56, 78"
query:= r".*:(\s*\d+[\s,]*)+"
text := 'tst: 01,23,45 ,56, 78'
query := r'.*:(\s*\d+[\s,]*)+'
mut re := new() or { panic(err) }
//re.debug = 2
re.group_csave = [-1].repeat(3*20+1) // we expect max 20 records
re.compile_opt(query) or { println(err) return }
// re.debug = 2
re.group_csave = [-1].repeat(3 * 20 + 1) // we expect max 20 records
re.compile_opt(query) or {
println(err)
return
}
q_str := re.get_query()
println("Query: $q_str")
println('Query: $q_str')
start, end := re.match_string(text)
if start < 0 {
println("ERROR : ${re.get_parse_error_string(start)}, $start")
println('ERROR : ${re.get_parse_error_string(start)}, $start')
} else {
println("found in [$start, $end] => [${text[start..end]}]")
println('found in [$start, $end] => [${text[start..end]}]')
}
// groups capture
mut gi := 0
for gi < re.groups.len {
if re.groups[gi] >= 0 {
println("${gi/2} ${re.groups[gi]},${re.groups[gi+1]} :[${text[re.groups[gi]..re.groups[gi+1]]}]")
println('${gi / 2} ${re.groups[gi]},${re.groups[gi + 1]} :[${text[re.groups[gi]..re.groups[gi +
1]]}]')
}
gi += 2
}
// continuous saving
gi = 0
println("num: ${re.group_csave[0]}")
println('num: ${re.group_csave[0]}')
for gi < re.group_csave[0] {
id := re.group_csave[1+gi*3]
st := re.group_csave[1+gi*3+1]
en := re.group_csave[1+gi*3+2]
println("cg id: ${id} [${st}, ${en}] => [${text[st..en]}]")
id := re.group_csave[1 + gi * 3]
st := re.group_csave[1 + gi * 3 + 1]
en := re.group_csave[1 + gi * 3 + 2]
println('cg id: $id [$st, $en] => [${text[st..en]}]')
gi++
}
}
@ -333,62 +327,59 @@ example:
```v ignore
import regex
fn main() {
test_regex()
text := "http://www.ciao.mondo/hello/pippo12_/pera.html"
query:= r"(?P<format>https?)|(?:ftps?)://(?P<token>[\w_]+.)+"
text := 'http://www.ciao.mondo/hello/pippo12_/pera.html'
query := r'(?P<format>https?)|(?:ftps?)://(?P<token>[\w_]+.)+'
mut re := new()
re.debug = 2
// must provide an array of the right size if want the continuos saving of the groups
re.group_csave = [-1].repeat(3*20+1)
re.compile_opt(query) or { println(err) return }
re.group_csave = [-1].repeat(3 * 20 + 1)
re.compile_opt(query) or {
println(err)
return
}
q_str := re.get_query()
println("O.Query: $query")
println("Query : $q_str")
println('O.Query: $query')
println('Query : $q_str')
re.debug = 0
start, end := re.match_string(text)
if start < 0 {
err_str := re.get_parse_error_string(start)
println("ERROR : $err_str, $start")
println('ERROR : $err_str, $start')
} else {
text1 := text[start..end]
println("found in [$start, $end] => [$text1]")
println('found in [$start, $end] => [$text1]')
}
// groups
mut gi := 0
for gi < re.groups.len {
if re.groups[gi] >= 0 {
println("${gi/2} ${re.groups[gi]},${re.groups[gi+1]} :[${text[re.groups[gi]..re.groups[gi+1]]}]")
println('${gi / 2} ${re.groups[gi]},${re.groups[gi + 1]} :[${text[re.groups[gi]..re.groups[gi +
1]]}]')
}
gi += 2
}
// continuous saving
gi = 0
println("num of group item saved: ${re.group_csave[0]}")
println('num of group item saved: ${re.group_csave[0]}')
for gi < re.group_csave[0] {
id := re.group_csave[1+gi*3]
st := re.group_csave[1+gi*3+1]
en := re.group_csave[1+gi*3+2]
println("cg id: ${id} [${st}, ${en}] => [${text[st..en]}]")
id := re.group_csave[1 + gi * 3]
st := re.group_csave[1 + gi * 3 + 1]
en := re.group_csave[1 + gi * 3 + 2]
println('cg id: $id [$st, $en] => [${text[st..en]}]')
gi++
}
println("raw array: ${re.group_csave[0..gi*3+2-1]}")
println('raw array: ${re.group_csave[0..gi * 3 + 2 - 1]}')
// named capturing groups
println("named capturing groups:")
println('named capturing groups:')
for g_name in re.group_map.keys() {
s,e := re.get_group(g_name)
s, e := re.get_group(g_name)
if s >= 0 && e > s {
println("'${g_name}':[$s, $e] => '${text[s..e]}'")
println("'$g_name':[$s, $e] => '${text[s..e]}'")
} else {
println("Group [${g_name}] doesn't exist.")
println("Group [$g_name] doesn't exist.")
}
}
}
@ -530,17 +521,14 @@ This module has few small utilities to help the writing of regex expressions.
the following example code show how to visualize the syntax errors in the compilation phase:
```v oksyntax
query:= r"ciao da ab[ab-]" // there is an error, a range not closed!!
query := r'ciao da ab[ab-]'
// there is an error, a range not closed!!
mut re := new()
re.compile_opt(query) or { println(err) }
// output!!
//query: ciao da ab[ab-]
//err : ----------^
//ERROR: ERR_SYNTAX_ERROR
// query: ciao da ab[ab-]
// err : ----------^
// ERROR: ERR_SYNTAX_ERROR
```
### **Compiled code**
@ -636,12 +624,12 @@ it is possible to provide an alternative output setting a custom output functio
```v oksyntax
// custom print function, the input will be the regex debug string
fn custom_print(txt string) {
println("my log: $txt")
println('my log: $txt')
}
mut re := new()
re.log_func = custom_print // every debug output from now will call this function
re.log_func = custom_print
// every debug output from now will call this function
```
## Example code
@ -655,41 +643,42 @@ struct TestObj {
s int // expected match start index
e int // expected match end index
}
const (
tests = [
TestObj{"this is a good.",r"this (\w+) a",0,9},
TestObj{"this,these,those. over",r"(th[eio]se?[,. ])+",0,17},
TestObj{"test1@post.pip.com, pera",r"[\w]+@([\w]+\.)+\w+",0,18},
TestObj{"cpapaz ole. pippo,",r".*c.+ole.*pi",0,14},
TestObj{"adce aabe",r"(a(ab)+)|(a(dc)+)e",0,4},
]
tests = [
TestObj{'this is a good.', r'this (\w+) a', 0, 9},
TestObj{'this,these,those. over', r'(th[eio]se?[,. ])+', 0, 17},
TestObj{'test1@post.pip.com, pera', r'[\w]+@([\w]+\.)+\w+', 0, 18},
TestObj{'cpapaz ole. pippo,', r'.*c.+ole.*pi', 0, 14},
TestObj{'adce aabe', r'(a(ab)+)|(a(dc)+)e', 0, 4},
]
)
fn example() {
for c,tst in tests {
for c, tst in tests {
mut re := regex.new()
re.compile_opt(tst.query) or { println(err) continue }
re.compile_opt(tst.query) or {
println(err)
continue
}
// print the query parsed with the groups ids
re.debug = 1 // set debug on at minimum level
println("#${c:2d} query parsed: ${re.get_query()}")
println('#${c:2d} query parsed: $re.get_query()')
re.debug = 0
// do the match
start, end := re.match_string(tst.source)
if start >= 0 && end > start {
println("#${c:2d} found in: [$start, $end] => [${tst.source[start..end]}]")
println('#${c:2d} found in: [$start, $end] => [${tst.source[start..end]}]')
}
// print the groups
mut gi := 0
for gi < re.groups.len {
if re.groups[gi] >= 0 {
println("group ${gi/2:2d} :[${tst.source[re.groups[gi]..re.groups[gi+1]]}]")
println('group ${gi / 2:2d} :[${tst.source[re.groups[gi]..re.groups[gi + 1]]}]')
}
gi += 2
}
println("")
println('')
}
}

View File

@ -16,7 +16,6 @@ fn main() {
println('Invalid version')
return
}
println(ver1.gt(ver2))
println(ver2.gt(ver1))
println(ver1.satisfies('>=1.1.0 <2.0.0'))

View File

@ -13,9 +13,10 @@ is replaced by the textual version of the following parameters.
```v
import strconv
fn main() {
a := "World"
s := strconv.v_sprintf("Hello %s!", a)
a := 'World'
s := strconv.v_sprintf('Hello %s!', a)
println(s)
}
```
@ -96,12 +97,12 @@ various types
a0 := u32(10)
b0 := 200
c0 := byte(12)
s0 := "ciAo"
s0 := 'ciAo'
ch0 := `B`
f0 := 0.312345
f1 := 200000.0
sc0 := "ciao: [%-08u] %d %hhd [%8s] [%08X] [%-20.4f] [%-20.4f] [%c]"
temp_s = strconv.v_sprintf(sc0 ,a0 ,b0 ,c0 ,s0, b0 ,f0, f1, ch0)
sc0 := 'ciao: [%-08u] %d %hhd [%8s] [%08X] [%-20.4f] [%-20.4f] [%c]'
temp_s = strconv.v_sprintf(sc0, a0, b0, c0, s0, b0, f0, f1, ch0)
println(temp_s)
```
@ -116,8 +117,8 @@ a := byte(12)
b := i16(13)
c := 14
d := i64(15)
sc1 := "==>%hhd %hd %d %ld"
temp_s = strconv.v_sprintf(sc1, a ,b ,c, d)
sc1 := '==>%hhd %hd %d %ld'
temp_s = strconv.v_sprintf(sc1, a, b, c, d)
println(temp_s)
```
@ -130,10 +131,10 @@ unsigned integer
```v oksyntax
a1 := byte(0xff)
b1 := u16(0xffff)
c1 := u32(0xffff_ffff)
c1 := u32(0xffffffff)
d1 := u64(-1)
sc2 := "%hhu %hu %u %lu"
temp_s = strconv.v_sprintf(sc2, a1 ,b1 ,c1, d1)
sc2 := '%hhu %hu %u %lu'
temp_s = strconv.v_sprintf(sc2, a1, b1, c1, d1)
println(temp_s)
```
@ -146,10 +147,10 @@ hexadecimal
```v oksyntax
a1 := byte(0xff)
b1 := i16(0xffff)
c1 := u32(0xffff_ffff)
c1 := u32(0xffffffff)
d1 := u64(-1)
sc3 := "%hhx %hx %x %lx"
temp_s = strconv.v_sprintf(sc3, a1 ,b1 ,c1, d1)
sc3 := '%hhx %hx %x %lx'
temp_s = strconv.v_sprintf(sc3, a1, b1, c1, d1)
println(temp_s)
```
@ -161,7 +162,7 @@ hexadecimal
```v oksyntax
a2 := 125
sc7 := "[%9x] [%9X] [%-9x] [%-9X] [%09x] [%09X]"
sc7 := '[%9x] [%9X] [%-9x] [%-9X] [%09x] [%09X]'
temp_s = strconv.v_sprintf(sc7, a2, a2, a2, a2, a2, a2)
println(temp_s)
```
@ -177,7 +178,7 @@ f0 := 0.312345
f1 := 200000.0
f2 := -1234.300e6
f3 := 1234.300e-6
sc4 := "[%-20.3e] [%20.3e] [%-020.3e] [%-020.3E] [%-020.3e] [%-020.3e]"
sc4 := '[%-20.3e] [%20.3e] [%-020.3e] [%-020.3E] [%-020.3e] [%-020.3e]'
temp_s = strconv.v_sprintf(sc4, f0, f1, f1, f1, f2, f3)
println(temp_s)
```
@ -191,10 +192,10 @@ float automatic notations
```v oksyntax
mut ft := -1e-7
mut x := 0
sc8 := "[%20g][%20G]|"
sc8 := '[%20g][%20G]|'
for x < 12 {
temp_s = strconv.v_sprintf(sc8, ft, ft)
println("$temp_s\n")
println('$temp_s\n')
ft = ft * 10.0
x++
}
@ -220,7 +221,7 @@ for x < 12 {
The format module also has some utility functions:
```v oksyntax
```v oksyntax nofmt
// calling struct
struct BF_param {
pad_ch byte = ` ` // padding char

View File

@ -20,7 +20,7 @@ fn main() {
term.clear() // clears the content in the terminal
width, height := term.get_terminal_size() // get the size of the terminal
term.set_cursor_position(x: width / 2, y: height / 2) // now we point the cursor to the middle of the terminal
println(term.strikethrough(term.bright_green("hello world"))) // Print green text
println(term.strikethrough(term.bright_green('hello world'))) // Print green text
term.set_cursor_position(x: 0, y: height) // Sets the position of the cursor to the bottom of the terminal
mut var := os.input('press q to quit: ')
// Keep prompting until the user presses the q key
@ -42,55 +42,40 @@ Here are some functions you should be aware of in the `term `module:
```v oksyntax
import term
// returns the height and the width of the terminal
width, height := term.get_terminal_size()
// returns the string as green text to be printed on stdout
term.ok_message('cool')
// returns the string as red text to be printed on stdout
term.fail_message('oh, no')
// returns the string as yellow text to be printed on stdout
term.warning_message('be warned')
//clears the entire terminal and leaves a blank one
// clears the entire terminal and leaves a blank one
term.clear()
// colors the output of the output, the available colors are: black,blue,yellow,green,cyan,gray,bright_blue,bright_green,bright_red,bright_black,bright_cyan
term.yellow('submarine')
// transforms the given string into bold text
term.bold('and beautiful')
// puts a strikethrough into the given string
term.strikethrough('the core of the problem')
// underlines the given string
term.underline('important')
// colors the background of the output following the given color
// the available colors are: black, blue, yellow, green, cyan, gray
term.bg_green('field')
// sets the position of the cursor at a given place in the terminal
term.set_cursor_position(x: 5, y: 10)
// moves the cursor up
term.cursor_up()
// moves the cursor down
term.cursor_down()
// moves the cursor to the right
term.cursor_forward()
// moves the cursor to the left
term.cursor_back()
// shows the cursor
term.show_cursor()
// hides the cursor
term.hide_cursor()
```

View File

@ -4,7 +4,7 @@ A V module for designing terminal UI apps
#### Quickstart
```v
```v nofmt
import term.ui as tui
struct App {

View File

@ -26,16 +26,21 @@ or `Preferences.compile_defines_all` **if any file is defined**.
To parse something a new template is created as the first step:
```v
import v.table
table := table.new_table()
```
a new preference is created:
```v
import v.pref
pref := pref.Preferences{}
```
and a new scope is created:
```v
import v.ast
scope := ast.Scope{
parent: 0
}
@ -46,6 +51,7 @@ after that, you can parse your files.
If you want to parse only text which isn't saved on the disk you can use this function.
```v oksyntax
import v.parser
code := ''
// table, pref and scope needs to be passed as reference
parsed_file := parser.parse_text(code, table, .parse_comments, &pref, &scope)
@ -56,6 +62,7 @@ For parsing files on disk, a path needs to be provided.
The paths are collected one step earlier.
```v oksyntax
import v.parser
path := ''
// table, pref and scope needs to be passed as reference
parsed_file := parser.parse_file(path, table, .parse_comments, &pref, &scope)
@ -66,6 +73,7 @@ If you have a batch of paths available which should be parsed,
there is also a function which does all the work.
```v oksyntax
import v.parser
paths := ['']
// table, pref and scope needs to be passed as reference
parsed_files := parser.parse_files(paths, table, &pref, &scope)
@ -86,6 +94,7 @@ Then all files from that directory are collected and parsed again like the previ
A new checker is created:
```v oksyntax
import v.checker
mut checker := checker.new_checker(table, &pref)
```
@ -105,5 +114,6 @@ checker.check_files(parsed_files)
Generating C code works just as this:
```v oksyntax
import v.gen
res := gen.cgen(parsed_files, table, &pref)
```

View File

@ -4,7 +4,7 @@
`x.json2` is an experimental JSON parser written from scratch on V.
## Usage
```v oksyntax
```v oksyntax nofmt
import x.json2
import net.http