1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

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

This commit is contained in:
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

@ -24,7 +24,7 @@
## Key Features of V
- Simplicity: the language can be learned in less than an hour
- Fast compilation: ≈80k loc/s with a Clang backend,
- Fast compilation: ≈80k loc/s with a Clang backend,
≈1 million loc/s with x64 and tcc backends *(Intel i5-7500, SSD, no optimization)*
- Easy to develop: V compiles itself in less than a second
- Performance: as fast as C (V's main backend compiles to human readable C)
@ -81,7 +81,7 @@ v up
### C compiler
It's recommended to use Clang or GCC or Visual Studio.
It's recommended to use Clang or GCC or Visual Studio.
If you are doing development, you most likely already have one of those installed.
Otherwise, follow these instructions:
@ -90,8 +90,8 @@ Otherwise, follow these instructions:
- [Installing a C compiler on Windows](https://github.com/vlang/v/wiki/Installing-a-C-compiler-on-Windows)
However, if none is found when running `make` on Linux or Windows,
TCC would be downloaded and set as an alternative C backend.
However, if none is found when running `make` on Linux or Windows,
TCC would be downloaded and set as an alternative C backend.
It's very lightweight (several MB) so this shouldn't take too long.
### Symlinking
@ -227,9 +227,9 @@ https://github.com/vlang/ui
```v
fn main() {
for i in 0..3 {
println('Hello from V.js')
}
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 { }
if res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example failed to compile'))
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')
if res != 0 {
eprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live'))
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')
if res != 0 {
eprintln(eline(f.path, e.sline, 0, '`oksyntax` example with invalid syntax'))
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,10 +346,11 @@ 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']
if title == '' || text == '' {
if title == '' || text == '' {
app.vweb.text('Empty text/title')
return vweb.Result{}
}
@ -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.ok() // call this when the step succeeded
println( bmark.step_message('ok')
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.ok() // call this when the step succeeded
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}
println(items)
items := parser.read() or { break }
println(items)
}
```
It prints:
```
['x', 'y']

View File

@ -35,20 +35,20 @@ fn cb(receiver voidptr, args voidptr, sender voidptr) {
// Since V can map structs to voidptr, this also works
struct ClickEvent {
x int
y int
x int
y int
}
// Example case where publisher sends ClickEvent as args.
fn on_press(receiver voidptr, e &ClickEvent, sender voidptr){
println(e.x)
//your code here...
fn on_press(receiver voidptr, e &ClickEvent, sender voidptr) {
println(e.x)
// your code here...
}
```
## Usage
For **usage across modules**
For **usage across modules**
[check the example](https://github.com/vlang/v/tree/master/examples/eventbus).
_Note: As a general rule, you will need to **subscribe before publishing**._
@ -57,25 +57,26 @@ _Note: As a general rule, you will need to **subscribe before publishing**._
```v oksyntax
module main
import eventbus
// initialize it globally
const (
eb = eventbus.new()
eb = eventbus.new()
)
fn main(){
// get a mutable reference to the subscriber
fn main() {
// get a mutable reference to the subscriber
mut sub := eb.subscriber
// subscribe to the 'error' event
sub.subscribe("error", on_error)
// start the work
// subscribe to the 'error' event
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,20 +85,20 @@ fn on_error(receiver voidptr, e &Error, work &Work) {
```v oksyntax
module main
struct Work{
hours int
struct Work {
hours int
}
struct Error {
message string
message string
}
fn do_work(){
work := Work{20}
// get a mutable Params instance & put some data into it
error := &Error{"Error: no internet connection."}
// publish the event
eb.publish("error", work, error)
fn do_work() {
work := Work{20}
// get a mutable Params instance & put some data into it
error := &Error{'Error: no internet connection.'}
// publish the event
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,45 +257,42 @@ 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 }
q_str := re.get_query()
println("Query: $q_str")
start, end := re.match_string(text)
if start < 0 {
println("ERROR : ${re.get_parse_error_string(start)}, $start")
} else {
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]]}]")
}
gi += 2
}
// continuous saving
gi = 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]}]")
gi++
}
// 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')
start, end := re.match_string(text)
if start < 0 {
println('ERROR : ${re.get_parse_error_string(start)}, $start')
} else {
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]]}]')
}
gi += 2
}
// continuous saving
gi = 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]}]')
gi++
}
}
```
@ -333,64 +327,61 @@ 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 }
q_str := re.get_query()
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")
} else {
text1 := text[start..end]
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]]}]")
}
gi += 2
}
// continuous saving
gi = 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]}]")
gi++
}
println("raw array: ${re.group_csave[0..gi*3+2-1]}")
// named capturing groups
println("named capturing groups:")
for g_name in re.group_map.keys() {
s,e := re.get_group(g_name)
if s >= 0 && e > s {
println("'${g_name}':[$s, $e] => '${text[s..e]}'")
} else {
println("Group [${g_name}] doesn't exist.")
}
}
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')
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')
} else {
text1 := text[start..end]
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]]}]')
}
gi += 2
}
// continuous saving
gi = 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]}]')
gi++
}
println('raw array: ${re.group_csave[0..gi * 3 + 2 - 1]}')
// named capturing groups
println('named capturing groups:')
for g_name in re.group_map.keys() {
s, e := re.get_group(g_name)
if s >= 0 && e > s {
println("'$g_name':[$s, $e] => '${text[s..e]}'")
} else {
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
@ -652,44 +640,45 @@ Here there is a simple code to perform some basically match of strings
struct TestObj {
source string // source string to parse
query string // regex query string
s int // expected match start index
e int // expected match end index
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 }
// 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()}")
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]}]")
}
// 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]]}]")
}
gi += 2
}
println("")
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()')
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]}]')
}
// 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]]}]')
}
gi += 2
}
println('')
}
}

View File

@ -8,20 +8,19 @@ A library for working with versions in [semver][semver] format.
import semver
fn main() {
ver1 := semver.from('1.2.4') or {
println('Invalid version')
return
}
ver2 := semver.from('2.3.4') or {
println('Invalid version')
return
}
println(ver1.gt(ver2))
println(ver2.gt(ver1))
println(ver1.satisfies('>=1.1.0 <2.0.0'))
println(ver2.satisfies('>=1.1.0 <2.0.0'))
println(ver2.satisfies('>=1.1.0 <2.0.0 || >2.2.0'))
ver1 := semver.from('1.2.4') or {
println('Invalid version')
return
}
ver2 := semver.from('2.3.4') or {
println('Invalid version')
return
}
println(ver1.gt(ver2))
println(ver2.gt(ver1))
println(ver1.satisfies('>=1.1.0 <2.0.0'))
println(ver2.satisfies('>=1.1.0 <2.0.0'))
println(ver2.satisfies('>=1.1.0 <2.0.0 || >2.2.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)
}
```
@ -49,16 +50,16 @@ The Flags field may be zero or more (in any order) of:
#### Width field
The Width field specifies a *maximum* number of characters to output,
and is typically used to pad fixed-width fields in tabulated output,
The Width field specifies a *maximum* number of characters to output,
and is typically used to pad fixed-width fields in tabulated output,
it causes truncation of oversized fields.
The width field may be omitted, or it may be a numeric integer value,
or may also be specified by a parameter when indicated by an asterisk `*`.
For example, `v_printf("%*.s", 5, my_string)` will result in ` mystring` being printed,
The width field may be omitted, or it may be a numeric integer value,
or may also be specified by a parameter when indicated by an asterisk `*`.
For example, `v_printf("%*.s", 5, my_string)` will result in ` mystring` being printed,
with a total width of 5 characters.
#### Length field
#### Length field
The Length field can be omitted or be any of:
@ -71,7 +72,7 @@ The Length field can be omitted or be any of:
| | |
| | |
#### Type field
#### Type field
The Type field can be any of:
@ -93,15 +94,15 @@ The Type field can be any of:
various types
```v oksyntax
a0 := u32(10)
b0 := 200
c0 := byte(12)
s0 := "ciAo"
a0 := u32(10)
b0 := 200
c0 := byte(12)
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)
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)
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)
```
@ -173,11 +174,11 @@ println(temp_s)
floating points
```v oksyntax
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]"
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]'
temp_s = strconv.v_sprintf(sc4, f0, f1, f1, f1, f2, f3)
println(temp_s)
```
@ -190,11 +191,11 @@ float automatic notations
```v oksyntax
mut ft := -1e-7
mut x := 0
sc8 := "[%20g][%20G]|"
mut x := 0
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,13 +221,13 @@ 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
len0 int = -1 // default len for whole the number or string
len1 int = 6 // number of decimal digits, if needed
positive bool = true // mandatory: the sign of the number passed
positive bool = true // mandatory: the sign of the number passed
sign_flag bool = false // flag for print sign as prefix in padding
allign Align_text = .right // alignment of the string
rm_tail_zero bool = false // remove the tail zeros from floats
@ -243,7 +244,7 @@ fn remove_tail_zeros(s string) string
`format_fl` format a float number in normal notation using the parameters in the `BF_param` struct.
`format_es format a float number in scientific notation using the parameters in the BF_param`
`format_es format a float number in scientific notation using the parameters in the BF_param`
struct.
`remove_tail_zeros` removes the tailing zeros from a floating point number as string.
`remove_tail_zeros` removes the tailing zeros from a floating point number as string.

View File

@ -17,20 +17,20 @@ import term
import os
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
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
for {
if var == 'q' {
break
} else {
var = os.input('press q to quit: ')
}
}
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
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
for {
if var == 'q' {
break
} else {
var = os.input('press q to quit: ')
}
}
}
```
@ -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,18 +26,23 @@ 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
parent: 0
}
```
after that, you can parse your files.
@ -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

@ -1,10 +1,10 @@
> The name `json2` was chosen to avoid any unwanted potential conflicts with the
> The name `json2` was chosen to avoid any unwanted potential conflicts with the
> existing codegen tailored for the main `json` module which is powered by CJSON.
`x.json2` is an experimental JSON parser written from scratch on V.
## Usage
```v oksyntax
```v oksyntax nofmt
import x.json2
import net.http
@ -99,7 +99,7 @@ fn main() {
```
## Using struct tags
`x.json2` can access and use the struct field tags similar to the
`x.json2` can access and use the struct field tags similar to the
`json` module by using the comp-time `$for` for structs.
```v ignore
@ -115,7 +115,7 @@ fn (mut p Person) from_json(f json2.Any) {
break
}
}
match field.name {
'name' { p.name = mp[js_field_name].str() }
'age' { u.age = mp[js_field_name].int() }
@ -153,9 +153,9 @@ fn (mut p Person) from_json(f json2.Any) {
```v oksyntax
fn (mut p Person) to_json() string {
obj := f.as_map()
obj['nickname'] = p.name
return obj.str()
obj := f.as_map()
obj['nickname'] = p.name
return obj.str()
}
```
@ -170,6 +170,6 @@ The following list shows the possible outputs when casting a value to an incompa
1. Casting non-array values as array (`arr()`) will return an array with the value as the content.
2. Casting non-map values as map (`as_map()`) will return a map with the value as the content.
3. Casting non-string values to string (`str()`) will return the
3. Casting non-string values to string (`str()`) will return the
JSON string representation of the value.
4. Casting non-numeric values to int/float (`int()`/`i64()`/`f32()`/`f64()`) will return zero.