check-md: verify code example formatting (#7143)
parent
0d28f12c54
commit
8adb1acf31
14
README.md
14
README.md
|
@ -24,7 +24,7 @@
|
||||||
## Key Features of V
|
## Key Features of V
|
||||||
|
|
||||||
- Simplicity: the language can be learned in less than an hour
|
- 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)*
|
≈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
|
- 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)
|
- Performance: as fast as C (V's main backend compiles to human readable C)
|
||||||
|
@ -81,7 +81,7 @@ v up
|
||||||
|
|
||||||
### C compiler
|
### 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.
|
If you are doing development, you most likely already have one of those installed.
|
||||||
|
|
||||||
Otherwise, follow these instructions:
|
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)
|
- [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,
|
However, if none is found when running `make` on Linux or Windows,
|
||||||
TCC would be downloaded and set as an alternative C backend.
|
TCC would be downloaded and set as an alternative C backend.
|
||||||
It's very lightweight (several MB) so this shouldn't take too long.
|
It's very lightweight (several MB) so this shouldn't take too long.
|
||||||
|
|
||||||
### Symlinking
|
### Symlinking
|
||||||
|
@ -227,9 +227,9 @@ https://github.com/vlang/ui
|
||||||
|
|
||||||
```v
|
```v
|
||||||
fn main() {
|
fn main() {
|
||||||
for i in 0..3 {
|
for i in 0 .. 3 {
|
||||||
println('Hello from V.js')
|
println('Hello from V.js')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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'))
|
return btext('$file_path:${lnumber + 1}:${column + 1}:') + btext(rtext(' error: $message'))
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
const (
|
const (
|
||||||
default_command = 'compile'
|
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')
|
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 ...')
|
||||||
vcontent := e.text.join('\n')
|
vcontent := e.text.join('\n') + '\n'
|
||||||
os.write_file(vfile, vcontent) or { panic(err) }
|
os.write_file(vfile, vcontent) or { panic(err) }
|
||||||
mut acommands := e.command.split(' ')
|
mut acommands := e.command.split(' ')
|
||||||
|
nofmt := 'nofmt' in acommands
|
||||||
for command in acommands {
|
for command in acommands {
|
||||||
match command {
|
match command {
|
||||||
'compile' {
|
'compile' {
|
||||||
res := os.system('"$vexe" -w -Wfatal-errors -o x.c $vfile')
|
res := os.system('"$vexe" -w -Wfatal-errors -o x.c $vfile')
|
||||||
os.rm('x.c') or { }
|
os.rm('x.c') or { }
|
||||||
if res != 0 {
|
fmt_res := if nofmt { 0 } else { os.system('"$vexe" fmt -verify $vfile') }
|
||||||
eprintln(eline(f.path, e.sline, 0, 'example failed to compile'))
|
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)
|
eprintln(vcontent)
|
||||||
should_cleanup_vfile = false
|
should_cleanup_vfile = false
|
||||||
errors++
|
errors++
|
||||||
|
@ -209,8 +215,14 @@ fn (mut f MDFile) check_examples() (int, int) {
|
||||||
}
|
}
|
||||||
'live' {
|
'live' {
|
||||||
res := os.system('"$vexe" -w -Wfatal-errors -live -o x.c $vfile')
|
res := os.system('"$vexe" -w -Wfatal-errors -live -o x.c $vfile')
|
||||||
if res != 0 {
|
fmt_res := if nofmt { 0 } else { os.system('"$vexe" fmt -verify $vfile') }
|
||||||
eprintln(eline(f.path, e.sline, 0, 'example failed to compile with -live'))
|
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)
|
eprintln(vcontent)
|
||||||
should_cleanup_vfile = false
|
should_cleanup_vfile = false
|
||||||
errors++
|
errors++
|
||||||
|
@ -232,8 +244,14 @@ fn (mut f MDFile) check_examples() (int, int) {
|
||||||
}
|
}
|
||||||
'oksyntax' {
|
'oksyntax' {
|
||||||
res := os.system('"$vexe" -w -Wfatal-errors -check-syntax $vfile')
|
res := os.system('"$vexe" -w -Wfatal-errors -check-syntax $vfile')
|
||||||
if res != 0 {
|
fmt_res := if nofmt { 0 } else { os.system('"$vexe" fmt -verify $vfile') }
|
||||||
eprintln(eline(f.path, e.sline, 0, '`oksyntax` example with invalid syntax'))
|
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)
|
eprintln(vcontent)
|
||||||
should_cleanup_vfile = false
|
should_cleanup_vfile = false
|
||||||
errors++
|
errors++
|
||||||
|
@ -252,6 +270,7 @@ fn (mut f MDFile) check_examples() (int, int) {
|
||||||
}
|
}
|
||||||
oks++
|
oks++
|
||||||
}
|
}
|
||||||
|
'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/failcompile/oksyntax/badsyntax'))
|
||||||
should_cleanup_vfile = false
|
should_cleanup_vfile = false
|
||||||
|
|
995
doc/docs.md
995
doc/docs.md
File diff suppressed because it is too large
Load Diff
|
@ -75,8 +75,11 @@ pub fn (mut app App) index() vweb.Result {
|
||||||
return vweb.Result{}
|
return vweb.Result{}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (app &App) init() {}
|
pub fn (app &App) init() {
|
||||||
pub fn (app &App) init_once() {}
|
}
|
||||||
|
|
||||||
|
pub fn (app &App) init_once() {
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Run it with
|
Run it with
|
||||||
|
@ -103,6 +106,8 @@ no routing rules either:
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
import vweb
|
import vweb
|
||||||
|
import time
|
||||||
|
|
||||||
fn (mut app App) time() vweb.Result {
|
fn (mut app App) time() vweb.Result {
|
||||||
app.vweb.text(time.now().format())
|
app.vweb.text(time.now().format())
|
||||||
return vweb.Result{}
|
return vweb.Result{}
|
||||||
|
@ -341,10 +346,11 @@ Create `new.html`:
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
import vweb
|
import vweb
|
||||||
|
|
||||||
pub fn (mut app App) new_article() vweb.Result {
|
pub fn (mut app App) new_article() vweb.Result {
|
||||||
title := app.vweb.form['title']
|
title := app.vweb.form['title']
|
||||||
text := app.vweb.form['text']
|
text := app.vweb.form['text']
|
||||||
if title == '' || text == '' {
|
if title == '' || text == '' {
|
||||||
app.vweb.text('Empty text/title')
|
app.vweb.text('Empty text/title')
|
||||||
return vweb.Result{}
|
return vweb.Result{}
|
||||||
}
|
}
|
||||||
|
@ -380,6 +386,8 @@ in V is very simple:
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
import vweb
|
import vweb
|
||||||
|
import json
|
||||||
|
|
||||||
pub fn (mut app App) articles() vweb.Result {
|
pub fn (mut app App) articles() vweb.Result {
|
||||||
articles := app.find_all_articles()
|
articles := app.find_all_articles()
|
||||||
app.vweb.json(json.encode(articles))
|
app.vweb.json(json.encode(articles))
|
||||||
|
|
|
@ -1,42 +1,43 @@
|
||||||
Example usage of this module:
|
Example usage of this module:
|
||||||
```
|
```v
|
||||||
import benchmark
|
import benchmark
|
||||||
|
|
||||||
mut bmark := benchmark.new_benchmark()
|
mut bmark := benchmark.new_benchmark()
|
||||||
// by default the benchmark will be verbose, i.e. it will include timing information
|
// 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
|
// if you want it to be silent, set bmark.verbose = false
|
||||||
for {
|
for {
|
||||||
bmark.step() // call this when you want to advance the benchmark.
|
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
|
// 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.fail() // call this if the step failed
|
// bmark.step_message(('failed')
|
||||||
//bmark.step_message(('failed')
|
bmark.ok() // call this when the step succeeded
|
||||||
|
println(bmark.step_message('ok'))
|
||||||
bmark.ok() // call this when the step succeeded
|
|
||||||
println( bmark.step_message('ok')
|
|
||||||
}
|
}
|
||||||
bmark.stop() // call when you want to finalize the benchmark
|
bmark.stop()
|
||||||
println( bmark.total_message('remarks about the benchmark') )
|
// call when you want to finalize the benchmark
|
||||||
|
println(bmark.total_message('remarks about the benchmark'))
|
||||||
```
|
```
|
||||||
|
|
||||||
benchmark.start() and b.measure() are convenience methods,
|
benchmark.start() and b.measure() are convenience methods,
|
||||||
intended to be used in combination. Their goal is to make
|
intended to be used in combination. Their goal is to make
|
||||||
benchmarking of small snippets of code as *short*, easy to
|
benchmarking of small snippets of code as *short*, easy to
|
||||||
write, and then to read and analyze the results, as possible.
|
write, and then to read and analyze the results, as possible.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```v
|
```v
|
||||||
import time
|
import time
|
||||||
import benchmark
|
import benchmark
|
||||||
mut b := benchmark.start()
|
|
||||||
|
|
||||||
|
mut b := benchmark.start()
|
||||||
// your code section 1 ...
|
// your code section 1 ...
|
||||||
time.sleep_ms(1500)
|
time.sleep_ms(1500)
|
||||||
b.measure('code_1')
|
b.measure('code_1')
|
||||||
|
|
||||||
// your code section 2 ...
|
// your code section 2 ...
|
||||||
time.sleep_ms(500)
|
time.sleep_ms(500)
|
||||||
b.measure('code_2')
|
b.measure('code_2')
|
||||||
```
|
```
|
||||||
|
|
||||||
... which will produce on stdout something like this:
|
... which will produce on stdout something like this:
|
||||||
```text
|
```text
|
||||||
SPENT 1500.063 ms in code_1
|
SPENT 1500.063 ms in code_1
|
||||||
|
|
|
@ -5,13 +5,13 @@ import encoding.csv
|
||||||
|
|
||||||
data := 'x,y\na,b,c\n'
|
data := 'x,y\na,b,c\n'
|
||||||
mut parser := csv.new_reader(data)
|
mut parser := csv.new_reader(data)
|
||||||
|
|
||||||
// read each line
|
// read each line
|
||||||
for {
|
for {
|
||||||
items := parser.read() or {break}
|
items := parser.read() or { break }
|
||||||
println(items)
|
println(items)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
It prints:
|
It prints:
|
||||||
```
|
```
|
||||||
['x', 'y']
|
['x', 'y']
|
||||||
|
|
|
@ -35,20 +35,20 @@ fn cb(receiver voidptr, args voidptr, sender voidptr) {
|
||||||
|
|
||||||
// Since V can map structs to voidptr, this also works
|
// Since V can map structs to voidptr, this also works
|
||||||
struct ClickEvent {
|
struct ClickEvent {
|
||||||
x int
|
x int
|
||||||
y int
|
y int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example case where publisher sends ClickEvent as args.
|
// 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)
|
println(e.x)
|
||||||
//your code here...
|
// your code here...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
For **usage across modules**
|
For **usage across modules**
|
||||||
[check the example](https://github.com/vlang/v/tree/master/examples/eventbus).
|
[check the example](https://github.com/vlang/v/tree/master/examples/eventbus).
|
||||||
|
|
||||||
_Note: As a general rule, you will need to **subscribe before publishing**._
|
_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
|
```v oksyntax
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import eventbus
|
import eventbus
|
||||||
|
|
||||||
// initialize it globally
|
// initialize it globally
|
||||||
const (
|
const (
|
||||||
eb = eventbus.new()
|
eb = eventbus.new()
|
||||||
)
|
)
|
||||||
|
|
||||||
fn main(){
|
fn main() {
|
||||||
// get a mutable reference to the subscriber
|
// get a mutable reference to the subscriber
|
||||||
mut sub := eb.subscriber
|
mut sub := eb.subscriber
|
||||||
// subscribe to the 'error' event
|
// subscribe to the 'error' event
|
||||||
sub.subscribe("error", on_error)
|
sub.subscribe('error', on_error)
|
||||||
// start the work
|
// start the work
|
||||||
do_work()
|
do_work()
|
||||||
}
|
}
|
||||||
|
|
||||||
// the event handler
|
// the event handler
|
||||||
fn on_error(receiver voidptr, e &Error, work &Work) {
|
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
|
```v oksyntax
|
||||||
module main
|
module main
|
||||||
|
|
||||||
struct Work{
|
struct Work {
|
||||||
hours int
|
hours int
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Error {
|
struct Error {
|
||||||
message string
|
message string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_work(){
|
fn do_work() {
|
||||||
work := Work{20}
|
work := Work{20}
|
||||||
// get a mutable Params instance & put some data into it
|
// 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
|
// publish the event
|
||||||
eb.publish("error", work, error)
|
eb.publish('error', work, error)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -160,20 +160,17 @@ that is an `[]int` inside the `RE` struct.
|
||||||
**example:**
|
**example:**
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
text := "cpaz cpapaz cpapapaz"
|
text := 'cpaz cpapaz cpapapaz'
|
||||||
query:= r"(c(pa)+z ?)+"
|
query := r'(c(pa)+z ?)+'
|
||||||
mut re := regex.regex_opt(query) or { panic(err) }
|
mut re := regex.regex_opt(query) or { panic(err) }
|
||||||
|
|
||||||
println(re.get_query())
|
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
|
// #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, end := re.match_string(text)
|
||||||
// [start=0, end=20] match => [cpaz cpapaz cpapapaz]
|
// [start=0, end=20] match => [cpaz cpapaz cpapapaz]
|
||||||
|
|
||||||
mut gi := 0
|
mut gi := 0
|
||||||
for gi < re.groups.len {
|
for gi < re.groups.len {
|
||||||
if re.groups[gi] >= 0 {
|
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
|
gi += 2
|
||||||
}
|
}
|
||||||
|
@ -260,45 +257,42 @@ If the space ends no error is raised, further records will not be saved.
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
fn example2() {
|
fn example2() {
|
||||||
test_regex()
|
test_regex()
|
||||||
|
text := 'tst: 01,23,45 ,56, 78'
|
||||||
text := "tst: 01,23,45 ,56, 78"
|
query := r'.*:(\s*\d+[\s,]*)+'
|
||||||
query:= r".*:(\s*\d+[\s,]*)+"
|
|
||||||
|
|
||||||
mut re := new() or { panic(err) }
|
mut re := new() or { panic(err) }
|
||||||
//re.debug = 2
|
// re.debug = 2
|
||||||
re.group_csave = [-1].repeat(3*20+1) // we expect max 20 records
|
re.group_csave = [-1].repeat(3 * 20 + 1) // we expect max 20 records
|
||||||
|
re.compile_opt(query) or {
|
||||||
re.compile_opt(query) or { println(err) return }
|
println(err)
|
||||||
|
return
|
||||||
q_str := re.get_query()
|
}
|
||||||
println("Query: $q_str")
|
q_str := re.get_query()
|
||||||
|
println('Query: $q_str')
|
||||||
start, end := re.match_string(text)
|
start, end := re.match_string(text)
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
println("ERROR : ${re.get_parse_error_string(start)}, $start")
|
println('ERROR : ${re.get_parse_error_string(start)}, $start')
|
||||||
} else {
|
} else {
|
||||||
println("found in [$start, $end] => [${text[start..end]}]")
|
println('found in [$start, $end] => [${text[start..end]}]')
|
||||||
}
|
}
|
||||||
|
// groups capture
|
||||||
// groups capture
|
mut gi := 0
|
||||||
mut gi := 0
|
for gi < re.groups.len {
|
||||||
for gi < re.groups.len {
|
if re.groups[gi] >= 0 {
|
||||||
if re.groups[gi] >= 0 {
|
println('${gi / 2} ${re.groups[gi]},${re.groups[gi + 1]} :[${text[re.groups[gi]..re.groups[gi +
|
||||||
println("${gi/2} ${re.groups[gi]},${re.groups[gi+1]} :[${text[re.groups[gi]..re.groups[gi+1]]}]")
|
1]]}]')
|
||||||
}
|
}
|
||||||
gi += 2
|
gi += 2
|
||||||
}
|
}
|
||||||
|
// continuous saving
|
||||||
// continuous saving
|
gi = 0
|
||||||
gi = 0
|
println('num: ${re.group_csave[0]}')
|
||||||
println("num: ${re.group_csave[0]}")
|
for gi < re.group_csave[0] {
|
||||||
for gi < re.group_csave[0] {
|
id := re.group_csave[1 + gi * 3]
|
||||||
id := re.group_csave[1+gi*3]
|
st := re.group_csave[1 + gi * 3 + 1]
|
||||||
st := re.group_csave[1+gi*3+1]
|
en := re.group_csave[1 + gi * 3 + 2]
|
||||||
en := re.group_csave[1+gi*3+2]
|
println('cg id: $id [$st, $en] => [${text[st..en]}]')
|
||||||
println("cg id: ${id} [${st}, ${en}] => [${text[st..en]}]")
|
gi++
|
||||||
gi++
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -333,64 +327,61 @@ example:
|
||||||
|
|
||||||
```v ignore
|
```v ignore
|
||||||
import regex
|
import regex
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
test_regex()
|
test_regex()
|
||||||
|
text := 'http://www.ciao.mondo/hello/pippo12_/pera.html'
|
||||||
text := "http://www.ciao.mondo/hello/pippo12_/pera.html"
|
query := r'(?P<format>https?)|(?:ftps?)://(?P<token>[\w_]+.)+'
|
||||||
query:= r"(?P<format>https?)|(?:ftps?)://(?P<token>[\w_]+.)+"
|
|
||||||
|
|
||||||
mut re := new()
|
mut re := new()
|
||||||
re.debug = 2
|
re.debug = 2
|
||||||
|
|
||||||
// must provide an array of the right size if want the continuos saving of the groups
|
// 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.group_csave = [-1].repeat(3 * 20 + 1)
|
||||||
|
re.compile_opt(query) or {
|
||||||
re.compile_opt(query) or { println(err) return }
|
println(err)
|
||||||
|
return
|
||||||
q_str := re.get_query()
|
}
|
||||||
println("O.Query: $query")
|
q_str := re.get_query()
|
||||||
println("Query : $q_str")
|
println('O.Query: $query')
|
||||||
|
println('Query : $q_str')
|
||||||
re.debug = 0
|
re.debug = 0
|
||||||
start, end := re.match_string(text)
|
start, end := re.match_string(text)
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
err_str := re.get_parse_error_string(start)
|
err_str := re.get_parse_error_string(start)
|
||||||
println("ERROR : $err_str, $start")
|
println('ERROR : $err_str, $start')
|
||||||
} else {
|
} else {
|
||||||
text1 := text[start..end]
|
text1 := text[start..end]
|
||||||
println("found in [$start, $end] => [$text1]")
|
println('found in [$start, $end] => [$text1]')
|
||||||
}
|
}
|
||||||
|
// groups
|
||||||
// groups
|
mut gi := 0
|
||||||
mut gi := 0
|
for gi < re.groups.len {
|
||||||
for gi < re.groups.len {
|
if re.groups[gi] >= 0 {
|
||||||
if re.groups[gi] >= 0 {
|
println('${gi / 2} ${re.groups[gi]},${re.groups[gi + 1]} :[${text[re.groups[gi]..re.groups[gi +
|
||||||
println("${gi/2} ${re.groups[gi]},${re.groups[gi+1]} :[${text[re.groups[gi]..re.groups[gi+1]]}]")
|
1]]}]')
|
||||||
}
|
}
|
||||||
gi += 2
|
gi += 2
|
||||||
}
|
}
|
||||||
// continuous saving
|
// continuous saving
|
||||||
gi = 0
|
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] {
|
for gi < re.group_csave[0] {
|
||||||
id := re.group_csave[1+gi*3]
|
id := re.group_csave[1 + gi * 3]
|
||||||
st := re.group_csave[1+gi*3+1]
|
st := re.group_csave[1 + gi * 3 + 1]
|
||||||
en := re.group_csave[1+gi*3+2]
|
en := re.group_csave[1 + gi * 3 + 2]
|
||||||
println("cg id: ${id} [${st}, ${en}] => [${text[st..en]}]")
|
println('cg id: $id [$st, $en] => [${text[st..en]}]')
|
||||||
gi++
|
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
|
||||||
// named capturing groups
|
println('named capturing groups:')
|
||||||
println("named capturing groups:")
|
for g_name in re.group_map.keys() {
|
||||||
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 {
|
||||||
if s >= 0 && e > s {
|
println("'$g_name':[$s, $e] => '${text[s..e]}'")
|
||||||
println("'${g_name}':[$s, $e] => '${text[s..e]}'")
|
} else {
|
||||||
} 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:
|
the following example code show how to visualize the syntax errors in the compilation phase:
|
||||||
|
|
||||||
```v oksyntax
|
```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()
|
mut re := new()
|
||||||
|
|
||||||
re.compile_opt(query) or { println(err) }
|
re.compile_opt(query) or { println(err) }
|
||||||
|
|
||||||
// output!!
|
// output!!
|
||||||
|
// query: ciao da ab[ab-]
|
||||||
//query: ciao da ab[ab-]
|
// err : ----------^
|
||||||
//err : ----------^
|
// ERROR: ERR_SYNTAX_ERROR
|
||||||
//ERROR: ERR_SYNTAX_ERROR
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### **Compiled code**
|
### **Compiled code**
|
||||||
|
@ -636,12 +624,12 @@ it is possible to provide an alternative output setting a custom output functio
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
// custom print function, the input will be the regex debug string
|
// custom print function, the input will be the regex debug string
|
||||||
fn custom_print(txt string) {
|
fn custom_print(txt string) {
|
||||||
println("my log: $txt")
|
println('my log: $txt')
|
||||||
}
|
}
|
||||||
|
|
||||||
mut re := new()
|
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
|
## Example code
|
||||||
|
@ -652,44 +640,45 @@ Here there is a simple code to perform some basically match of strings
|
||||||
struct TestObj {
|
struct TestObj {
|
||||||
source string // source string to parse
|
source string // source string to parse
|
||||||
query string // regex query string
|
query string // regex query string
|
||||||
s int // expected match start index
|
s int // expected match start index
|
||||||
e int // expected match end index
|
e int // expected match end index
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tests = [
|
tests = [
|
||||||
TestObj{"this is a good.",r"this (\w+) a",0,9},
|
TestObj{'this is a good.', r'this (\w+) a', 0, 9},
|
||||||
TestObj{"this,these,those. over",r"(th[eio]se?[,. ])+",0,17},
|
TestObj{'this,these,those. over', r'(th[eio]se?[,. ])+', 0, 17},
|
||||||
TestObj{"test1@post.pip.com, pera",r"[\w]+@([\w]+\.)+\w+",0,18},
|
TestObj{'test1@post.pip.com, pera', r'[\w]+@([\w]+\.)+\w+', 0, 18},
|
||||||
TestObj{"cpapaz ole. pippo,",r".*c.+ole.*pi",0,14},
|
TestObj{'cpapaz ole. pippo,', r'.*c.+ole.*pi', 0, 14},
|
||||||
TestObj{"adce aabe",r"(a(ab)+)|(a(dc)+)e",0,4},
|
TestObj{'adce aabe', r'(a(ab)+)|(a(dc)+)e', 0, 4},
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
fn example() {
|
fn example() {
|
||||||
for c,tst in tests {
|
for c, tst in tests {
|
||||||
mut re := regex.new()
|
mut re := regex.new()
|
||||||
re.compile_opt(tst.query) or { println(err) continue }
|
re.compile_opt(tst.query) or {
|
||||||
|
println(err)
|
||||||
// print the query parsed with the groups ids
|
continue
|
||||||
re.debug = 1 // set debug on at minimum level
|
}
|
||||||
println("#${c:2d} query parsed: ${re.get_query()}")
|
// print the query parsed with the groups ids
|
||||||
re.debug = 0
|
re.debug = 1 // set debug on at minimum level
|
||||||
|
println('#${c:2d} query parsed: $re.get_query()')
|
||||||
// do the match
|
re.debug = 0
|
||||||
start, end := re.match_string(tst.source)
|
// do the match
|
||||||
if start >= 0 && end > start {
|
start, end := re.match_string(tst.source)
|
||||||
println("#${c:2d} found in: [$start, $end] => [${tst.source[start..end]}]")
|
if start >= 0 && end > start {
|
||||||
}
|
println('#${c:2d} found in: [$start, $end] => [${tst.source[start..end]}]')
|
||||||
|
}
|
||||||
// print the groups
|
// print the groups
|
||||||
mut gi := 0
|
mut gi := 0
|
||||||
for gi < re.groups.len {
|
for gi < re.groups.len {
|
||||||
if re.groups[gi] >= 0 {
|
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
|
gi += 2
|
||||||
}
|
}
|
||||||
println("")
|
println('')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,20 +8,19 @@ A library for working with versions in [semver][semver] format.
|
||||||
import semver
|
import semver
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
ver1 := semver.from('1.2.4') or {
|
ver1 := semver.from('1.2.4') or {
|
||||||
println('Invalid version')
|
println('Invalid version')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ver2 := semver.from('2.3.4') or {
|
ver2 := semver.from('2.3.4') or {
|
||||||
println('Invalid version')
|
println('Invalid version')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
println(ver1.gt(ver2))
|
||||||
println(ver1.gt(ver2))
|
println(ver2.gt(ver1))
|
||||||
println(ver2.gt(ver1))
|
println(ver1.satisfies('>=1.1.0 <2.0.0'))
|
||||||
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'))
|
println(ver2.satisfies('>=1.1.0 <2.0.0 || >2.2.0'))
|
||||||
println(ver2.satisfies('>=1.1.0 <2.0.0 || >2.2.0'))
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,10 @@ is replaced by the textual version of the following parameters.
|
||||||
|
|
||||||
```v
|
```v
|
||||||
import strconv
|
import strconv
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
a := "World"
|
a := 'World'
|
||||||
s := strconv.v_sprintf("Hello %s!", a)
|
s := strconv.v_sprintf('Hello %s!', a)
|
||||||
println(s)
|
println(s)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -49,16 +50,16 @@ The Flags field may be zero or more (in any order) of:
|
||||||
|
|
||||||
#### Width field
|
#### Width field
|
||||||
|
|
||||||
The Width field specifies a *maximum* number of characters to output,
|
The Width field specifies a *maximum* number of characters to output,
|
||||||
and is typically used to pad fixed-width fields in tabulated output,
|
and is typically used to pad fixed-width fields in tabulated output,
|
||||||
it causes truncation of oversized fields.
|
it causes truncation of oversized fields.
|
||||||
|
|
||||||
The width field may be omitted, or it may be a numeric integer value,
|
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 `*`.
|
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,
|
For example, `v_printf("%*.s", 5, my_string)` will result in ` mystring` being printed,
|
||||||
with a total width of 5 characters.
|
with a total width of 5 characters.
|
||||||
|
|
||||||
#### Length field
|
#### Length field
|
||||||
|
|
||||||
The Length field can be omitted or be any of:
|
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:
|
The Type field can be any of:
|
||||||
|
|
||||||
|
@ -93,15 +94,15 @@ The Type field can be any of:
|
||||||
various types
|
various types
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
a0 := u32(10)
|
a0 := u32(10)
|
||||||
b0 := 200
|
b0 := 200
|
||||||
c0 := byte(12)
|
c0 := byte(12)
|
||||||
s0 := "ciAo"
|
s0 := 'ciAo'
|
||||||
ch0 := `B`
|
ch0 := `B`
|
||||||
f0 := 0.312345
|
f0 := 0.312345
|
||||||
f1 := 200000.0
|
f1 := 200000.0
|
||||||
sc0 := "ciao: [%-08u] %d %hhd [%8s] [%08X] [%-20.4f] [%-20.4f] [%c]"
|
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)
|
temp_s = strconv.v_sprintf(sc0, a0, b0, c0, s0, b0, f0, f1, ch0)
|
||||||
println(temp_s)
|
println(temp_s)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -116,8 +117,8 @@ a := byte(12)
|
||||||
b := i16(13)
|
b := i16(13)
|
||||||
c := 14
|
c := 14
|
||||||
d := i64(15)
|
d := i64(15)
|
||||||
sc1 := "==>%hhd %hd %d %ld"
|
sc1 := '==>%hhd %hd %d %ld'
|
||||||
temp_s = strconv.v_sprintf(sc1, a ,b ,c, d)
|
temp_s = strconv.v_sprintf(sc1, a, b, c, d)
|
||||||
println(temp_s)
|
println(temp_s)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -130,10 +131,10 @@ unsigned integer
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
a1 := byte(0xff)
|
a1 := byte(0xff)
|
||||||
b1 := u16(0xffff)
|
b1 := u16(0xffff)
|
||||||
c1 := u32(0xffff_ffff)
|
c1 := u32(0xffffffff)
|
||||||
d1 := u64(-1)
|
d1 := u64(-1)
|
||||||
sc2 := "%hhu %hu %u %lu"
|
sc2 := '%hhu %hu %u %lu'
|
||||||
temp_s = strconv.v_sprintf(sc2, a1 ,b1 ,c1, d1)
|
temp_s = strconv.v_sprintf(sc2, a1, b1, c1, d1)
|
||||||
println(temp_s)
|
println(temp_s)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -146,10 +147,10 @@ hexadecimal
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
a1 := byte(0xff)
|
a1 := byte(0xff)
|
||||||
b1 := i16(0xffff)
|
b1 := i16(0xffff)
|
||||||
c1 := u32(0xffff_ffff)
|
c1 := u32(0xffffffff)
|
||||||
d1 := u64(-1)
|
d1 := u64(-1)
|
||||||
sc3 := "%hhx %hx %x %lx"
|
sc3 := '%hhx %hx %x %lx'
|
||||||
temp_s = strconv.v_sprintf(sc3, a1 ,b1 ,c1, d1)
|
temp_s = strconv.v_sprintf(sc3, a1, b1, c1, d1)
|
||||||
println(temp_s)
|
println(temp_s)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -161,7 +162,7 @@ hexadecimal
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
a2 := 125
|
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)
|
temp_s = strconv.v_sprintf(sc7, a2, a2, a2, a2, a2, a2)
|
||||||
println(temp_s)
|
println(temp_s)
|
||||||
```
|
```
|
||||||
|
@ -173,11 +174,11 @@ println(temp_s)
|
||||||
floating points
|
floating points
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
f0 := 0.312345
|
f0 := 0.312345
|
||||||
f1 := 200000.0
|
f1 := 200000.0
|
||||||
f2 := -1234.300e6
|
f2 := -1234.300e6
|
||||||
f3 := 1234.300e-6
|
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)
|
temp_s = strconv.v_sprintf(sc4, f0, f1, f1, f1, f2, f3)
|
||||||
println(temp_s)
|
println(temp_s)
|
||||||
```
|
```
|
||||||
|
@ -190,11 +191,11 @@ float automatic notations
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
mut ft := -1e-7
|
mut ft := -1e-7
|
||||||
mut x := 0
|
mut x := 0
|
||||||
sc8 := "[%20g][%20G]|"
|
sc8 := '[%20g][%20G]|'
|
||||||
for x < 12 {
|
for x < 12 {
|
||||||
temp_s = strconv.v_sprintf(sc8, ft, ft)
|
temp_s = strconv.v_sprintf(sc8, ft, ft)
|
||||||
println("$temp_s\n")
|
println('$temp_s\n')
|
||||||
ft = ft * 10.0
|
ft = ft * 10.0
|
||||||
x++
|
x++
|
||||||
}
|
}
|
||||||
|
@ -220,13 +221,13 @@ for x < 12 {
|
||||||
|
|
||||||
The format module also has some utility functions:
|
The format module also has some utility functions:
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax nofmt
|
||||||
// calling struct
|
// calling struct
|
||||||
struct BF_param {
|
struct BF_param {
|
||||||
pad_ch byte = ` ` // padding char
|
pad_ch byte = ` ` // padding char
|
||||||
len0 int = -1 // default len for whole the number or string
|
len0 int = -1 // default len for whole the number or string
|
||||||
len1 int = 6 // number of decimal digits, if needed
|
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
|
sign_flag bool = false // flag for print sign as prefix in padding
|
||||||
allign Align_text = .right // alignment of the string
|
allign Align_text = .right // alignment of the string
|
||||||
rm_tail_zero bool = false // remove the tail zeros from floats
|
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_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.
|
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.
|
||||||
|
|
|
@ -17,20 +17,20 @@ import term
|
||||||
import os
|
import os
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
term.clear() // clears the content in the terminal
|
term.clear() // clears the content in the terminal
|
||||||
width, height := term.get_terminal_size() // get the size of 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
|
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
|
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: ')
|
mut var := os.input('press q to quit: ')
|
||||||
// Keep prompting until the user presses the q key
|
// Keep prompting until the user presses the q key
|
||||||
for {
|
for {
|
||||||
if var == 'q' {
|
if var == 'q' {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
var = os.input('press q to quit: ')
|
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
|
```v oksyntax
|
||||||
import term
|
import term
|
||||||
|
|
||||||
// returns the height and the width of the terminal
|
// returns the height and the width of the terminal
|
||||||
width, height := term.get_terminal_size()
|
width, height := term.get_terminal_size()
|
||||||
|
|
||||||
// returns the string as green text to be printed on stdout
|
// returns the string as green text to be printed on stdout
|
||||||
term.ok_message('cool')
|
term.ok_message('cool')
|
||||||
|
|
||||||
// returns the string as red text to be printed on stdout
|
// returns the string as red text to be printed on stdout
|
||||||
term.fail_message('oh, no')
|
term.fail_message('oh, no')
|
||||||
|
|
||||||
// returns the string as yellow text to be printed on stdout
|
// returns the string as yellow text to be printed on stdout
|
||||||
term.warning_message('be warned')
|
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()
|
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
|
// 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')
|
term.yellow('submarine')
|
||||||
|
|
||||||
// transforms the given string into bold text
|
// transforms the given string into bold text
|
||||||
term.bold('and beautiful')
|
term.bold('and beautiful')
|
||||||
|
|
||||||
// puts a strikethrough into the given string
|
// puts a strikethrough into the given string
|
||||||
term.strikethrough('the core of the problem')
|
term.strikethrough('the core of the problem')
|
||||||
|
|
||||||
// underlines the given string
|
// underlines the given string
|
||||||
term.underline('important')
|
term.underline('important')
|
||||||
|
|
||||||
// colors the background of the output following the given color
|
// colors the background of the output following the given color
|
||||||
// the available colors are: black, blue, yellow, green, cyan, gray
|
// the available colors are: black, blue, yellow, green, cyan, gray
|
||||||
term.bg_green('field')
|
term.bg_green('field')
|
||||||
|
|
||||||
// sets the position of the cursor at a given place in the terminal
|
// sets the position of the cursor at a given place in the terminal
|
||||||
term.set_cursor_position(x: 5, y: 10)
|
term.set_cursor_position(x: 5, y: 10)
|
||||||
|
|
||||||
// moves the cursor up
|
// moves the cursor up
|
||||||
term.cursor_up()
|
term.cursor_up()
|
||||||
|
|
||||||
// moves the cursor down
|
// moves the cursor down
|
||||||
term.cursor_down()
|
term.cursor_down()
|
||||||
|
|
||||||
// moves the cursor to the right
|
// moves the cursor to the right
|
||||||
term.cursor_forward()
|
term.cursor_forward()
|
||||||
|
|
||||||
// moves the cursor to the left
|
// moves the cursor to the left
|
||||||
term.cursor_back()
|
term.cursor_back()
|
||||||
|
|
||||||
// shows the cursor
|
// shows the cursor
|
||||||
term.show_cursor()
|
term.show_cursor()
|
||||||
|
|
||||||
// hides the cursor
|
// hides the cursor
|
||||||
term.hide_cursor()
|
term.hide_cursor()
|
||||||
```
|
```
|
||||||
|
|
|
@ -4,7 +4,7 @@ A V module for designing terminal UI apps
|
||||||
|
|
||||||
#### Quickstart
|
#### Quickstart
|
||||||
|
|
||||||
```v
|
```v nofmt
|
||||||
import term.ui as tui
|
import term.ui as tui
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
|
|
|
@ -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:
|
To parse something a new template is created as the first step:
|
||||||
```v
|
```v
|
||||||
import v.table
|
import v.table
|
||||||
|
|
||||||
table := table.new_table()
|
table := table.new_table()
|
||||||
```
|
```
|
||||||
|
|
||||||
a new preference is created:
|
a new preference is created:
|
||||||
```v
|
```v
|
||||||
import v.pref
|
import v.pref
|
||||||
|
|
||||||
pref := pref.Preferences{}
|
pref := pref.Preferences{}
|
||||||
```
|
```
|
||||||
|
|
||||||
and a new scope is created:
|
and a new scope is created:
|
||||||
```v
|
```v
|
||||||
import v.ast
|
import v.ast
|
||||||
|
|
||||||
scope := ast.Scope{
|
scope := ast.Scope{
|
||||||
parent: 0
|
parent: 0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
after that, you can parse your files.
|
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.
|
If you want to parse only text which isn't saved on the disk you can use this function.
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
import v.parser
|
import v.parser
|
||||||
|
|
||||||
code := ''
|
code := ''
|
||||||
// table, pref and scope needs to be passed as reference
|
// table, pref and scope needs to be passed as reference
|
||||||
parsed_file := parser.parse_text(code, table, .parse_comments, &pref, &scope)
|
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.
|
The paths are collected one step earlier.
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
import v.parser
|
import v.parser
|
||||||
|
|
||||||
path := ''
|
path := ''
|
||||||
// table, pref and scope needs to be passed as reference
|
// table, pref and scope needs to be passed as reference
|
||||||
parsed_file := parser.parse_file(path, table, .parse_comments, &pref, &scope)
|
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.
|
there is also a function which does all the work.
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
import v.parser
|
import v.parser
|
||||||
|
|
||||||
paths := ['']
|
paths := ['']
|
||||||
// table, pref and scope needs to be passed as reference
|
// table, pref and scope needs to be passed as reference
|
||||||
parsed_files := parser.parse_files(paths, table, &pref, &scope)
|
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:
|
A new checker is created:
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
import v.checker
|
import v.checker
|
||||||
|
|
||||||
mut checker := checker.new_checker(table, &pref)
|
mut checker := checker.new_checker(table, &pref)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -105,5 +114,6 @@ checker.check_files(parsed_files)
|
||||||
Generating C code works just as this:
|
Generating C code works just as this:
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
import v.gen
|
import v.gen
|
||||||
|
|
||||||
res := gen.cgen(parsed_files, table, &pref)
|
res := gen.cgen(parsed_files, table, &pref)
|
||||||
```
|
```
|
||||||
|
|
|
@ -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.
|
> 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.
|
`x.json2` is an experimental JSON parser written from scratch on V.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
```v oksyntax
|
```v oksyntax nofmt
|
||||||
import x.json2
|
import x.json2
|
||||||
import net.http
|
import net.http
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ fn main() {
|
||||||
```
|
```
|
||||||
|
|
||||||
## Using struct tags
|
## 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.
|
`json` module by using the comp-time `$for` for structs.
|
||||||
|
|
||||||
```v ignore
|
```v ignore
|
||||||
|
@ -115,7 +115,7 @@ fn (mut p Person) from_json(f json2.Any) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match field.name {
|
match field.name {
|
||||||
'name' { p.name = mp[js_field_name].str() }
|
'name' { p.name = mp[js_field_name].str() }
|
||||||
'age' { u.age = mp[js_field_name].int() }
|
'age' { u.age = mp[js_field_name].int() }
|
||||||
|
@ -153,9 +153,9 @@ fn (mut p Person) from_json(f json2.Any) {
|
||||||
|
|
||||||
```v oksyntax
|
```v oksyntax
|
||||||
fn (mut p Person) to_json() string {
|
fn (mut p Person) to_json() string {
|
||||||
obj := f.as_map()
|
obj := f.as_map()
|
||||||
obj['nickname'] = p.name
|
obj['nickname'] = p.name
|
||||||
return obj.str()
|
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.
|
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.
|
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.
|
JSON string representation of the value.
|
||||||
4. Casting non-numeric values to int/float (`int()`/`i64()`/`f32()`/`f64()`) will return zero.
|
4. Casting non-numeric values to int/float (`int()`/`i64()`/`f32()`/`f64()`) will return zero.
|
||||||
|
|
Loading…
Reference in New Issue