docs: improve the docs by provide better examples and describe module publishing (#12308)
parent
579d5ae649
commit
81b95ece51
371
doc/docs.md
371
doc/docs.md
|
@ -102,8 +102,6 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
|
||||||
* [Builtin functions](#builtin-functions)
|
* [Builtin functions](#builtin-functions)
|
||||||
* [Printing custom types](#printing-custom-types)
|
* [Printing custom types](#printing-custom-types)
|
||||||
* [Modules](#modules)
|
* [Modules](#modules)
|
||||||
* [Manage Packages](#manage-packages)
|
|
||||||
* [Publish package](#publish-package)
|
|
||||||
* [Type Declarations](#type-declarations)
|
* [Type Declarations](#type-declarations)
|
||||||
* [Interfaces](#interfaces)
|
* [Interfaces](#interfaces)
|
||||||
* [Enums](#enums)
|
* [Enums](#enums)
|
||||||
|
@ -127,6 +125,8 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
|
||||||
* [Tools](#tools)
|
* [Tools](#tools)
|
||||||
* [v fmt](#v-fmt)
|
* [v fmt](#v-fmt)
|
||||||
* [Profiling](#profiling)
|
* [Profiling](#profiling)
|
||||||
|
* [Package Management](#package-management)
|
||||||
|
* [Publish package](#publish-package)
|
||||||
* [Advanced Topics](#advanced-topics)
|
* [Advanced Topics](#advanced-topics)
|
||||||
* [Dumping expressions at runtime](#dumping-expressions-at-runtime)
|
* [Dumping expressions at runtime](#dumping-expressions-at-runtime)
|
||||||
* [Memory-unsafe code](#memory-unsafe-code)
|
* [Memory-unsafe code](#memory-unsafe-code)
|
||||||
|
@ -479,7 +479,18 @@ windows_newline := '\r\n' // escape special characters like in C
|
||||||
assert windows_newline.len == 2
|
assert windows_newline.len == 2
|
||||||
```
|
```
|
||||||
|
|
||||||
In V, a string is a read-only array of bytes. String data is encoded using UTF-8.
|
In V, a string is a read-only array of bytes. String data is encoded using UTF-8:
|
||||||
|
```v
|
||||||
|
s := 'hello 🌎' // emoji takes 4 bytes
|
||||||
|
assert s.len == 10
|
||||||
|
|
||||||
|
arr := s.bytes() // convert `string` to `[]byte`
|
||||||
|
assert arr.len == 10
|
||||||
|
|
||||||
|
s2 := arr.bytestr() // convert `[]byte` to `string`
|
||||||
|
assert s2 == s
|
||||||
|
```
|
||||||
|
|
||||||
String values are immutable. You cannot mutate elements:
|
String values are immutable. You cannot mutate elements:
|
||||||
|
|
||||||
```v failcompile
|
```v failcompile
|
||||||
|
@ -1041,7 +1052,7 @@ println(typeof(fnums).name) // => [3]int
|
||||||
|
|
||||||
fnums2 := [1, 10, 100]! // short init syntax that does the same (the syntax will probably change)
|
fnums2 := [1, 10, 100]! // short init syntax that does the same (the syntax will probably change)
|
||||||
|
|
||||||
anums := fnums[0..fnums.len]
|
anums := fnums[..] // same as `anums := fnums[0..fnums.len]`
|
||||||
println(anums) // => [1, 10, 100]
|
println(anums) // => [1, 10, 100]
|
||||||
println(typeof(anums).name) // => []int
|
println(typeof(anums).name) // => []int
|
||||||
```
|
```
|
||||||
|
@ -1832,7 +1843,6 @@ mut p := Point{
|
||||||
x: 10
|
x: 10
|
||||||
y: 20
|
y: 20
|
||||||
}
|
}
|
||||||
// you can omit the struct name when it's already known
|
|
||||||
p = Point{
|
p = Point{
|
||||||
x: 30
|
x: 30
|
||||||
y: 4
|
y: 4
|
||||||
|
@ -2065,16 +2075,14 @@ println(nums)
|
||||||
Note, that you have to add `mut` before `nums` when calling this function. This makes
|
Note, that you have to add `mut` before `nums` when calling this function. This makes
|
||||||
it clear that the function being called will modify the value.
|
it clear that the function being called will modify the value.
|
||||||
|
|
||||||
It is preferable to return values instead of modifying arguments.
|
It is preferable to return values instead of modifying arguments,
|
||||||
|
e.g. `user = register(user)` (or `user.register()`) instead of `register(mut user)`.
|
||||||
Modifying arguments should only be done in performance-critical parts of your application
|
Modifying arguments should only be done in performance-critical parts of your application
|
||||||
to reduce allocations and copying.
|
to reduce allocations and copying.
|
||||||
|
|
||||||
For this reason V doesn't allow the modification of arguments with primitive types (e.g. integers).
|
For this reason V doesn't allow the modification of arguments with primitive types (e.g. integers).
|
||||||
Only more complex types such as arrays and maps may be modified.
|
Only more complex types such as arrays and maps may be modified.
|
||||||
|
|
||||||
Use `user.register()` or `user = register(user)`
|
|
||||||
instead of `register(mut user)`.
|
|
||||||
|
|
||||||
#### Struct update syntax
|
#### Struct update syntax
|
||||||
|
|
||||||
V makes it easy to return a modified version of an object:
|
V makes it easy to return a modified version of an object:
|
||||||
|
@ -2486,156 +2494,6 @@ fn init() {
|
||||||
The `init` function cannot be public - it will be called automatically. This feature is
|
The `init` function cannot be public - it will be called automatically. This feature is
|
||||||
particularly useful for initializing a C library.
|
particularly useful for initializing a C library.
|
||||||
|
|
||||||
### Manage Packages
|
|
||||||
|
|
||||||
Briefly:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
v [module option] [param]
|
|
||||||
```
|
|
||||||
|
|
||||||
###### module options:
|
|
||||||
|
|
||||||
```
|
|
||||||
install Install a module from VPM.
|
|
||||||
remove Remove a module that was installed from VPM.
|
|
||||||
search Search for a module from VPM.
|
|
||||||
update Update an installed module from VPM.
|
|
||||||
upgrade Upgrade all the outdated modules.
|
|
||||||
list List all installed modules.
|
|
||||||
outdated Show installed modules that need updates.
|
|
||||||
```
|
|
||||||
|
|
||||||
Read more:
|
|
||||||
|
|
||||||
You can also install modules already created by someone else with [VPM](https://vpm.vlang.io/):
|
|
||||||
```powershell
|
|
||||||
v install [module]
|
|
||||||
```
|
|
||||||
**Example:**
|
|
||||||
```powershell
|
|
||||||
v install ui
|
|
||||||
```
|
|
||||||
|
|
||||||
Modules could install directly from git or mercurial repositories.
|
|
||||||
```powershell
|
|
||||||
v install [--git|--hg] [url]
|
|
||||||
```
|
|
||||||
**Example:**
|
|
||||||
```powershell
|
|
||||||
v install --git https://github.com/vlang/markdown
|
|
||||||
```
|
|
||||||
|
|
||||||
Removing a module with v:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
v remove [module]
|
|
||||||
```
|
|
||||||
**Example:**
|
|
||||||
```powershell
|
|
||||||
v remove ui
|
|
||||||
```
|
|
||||||
|
|
||||||
Updating an installed module from [VPM](https://vpm.vlang.io/):
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
v update [module]
|
|
||||||
```
|
|
||||||
**Example:**
|
|
||||||
```powershell
|
|
||||||
v update ui
|
|
||||||
```
|
|
||||||
|
|
||||||
Or you can update all your modules:
|
|
||||||
```powershell
|
|
||||||
v update
|
|
||||||
```
|
|
||||||
|
|
||||||
To see all the modules you have installed, you can use:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
v list
|
|
||||||
```
|
|
||||||
**Example:**
|
|
||||||
```powershell
|
|
||||||
> v list
|
|
||||||
Installed modules:
|
|
||||||
markdown
|
|
||||||
ui
|
|
||||||
```
|
|
||||||
|
|
||||||
To see all the modules that need updates:
|
|
||||||
```powershell
|
|
||||||
v outdated
|
|
||||||
```
|
|
||||||
**Example:**
|
|
||||||
```powershell
|
|
||||||
> v outdated
|
|
||||||
Modules are up to date.
|
|
||||||
```
|
|
||||||
|
|
||||||
### Publish package
|
|
||||||
|
|
||||||
1. Put a `v.mod` file inside the toplevel folder of your module (if you
|
|
||||||
created your module with the command `v new mymodule` or `v init` you already have a v.mod file).
|
|
||||||
|
|
||||||
```sh
|
|
||||||
v new mymodule
|
|
||||||
Input your project description: My nice module.
|
|
||||||
Input your project version: (0.0.0) 0.0.1
|
|
||||||
Input your project license: (MIT)
|
|
||||||
Initialising ...
|
|
||||||
Complete!
|
|
||||||
```
|
|
||||||
|
|
||||||
Example `v.mod`:
|
|
||||||
```v ignore
|
|
||||||
Module {
|
|
||||||
name: 'mymodule'
|
|
||||||
description: 'My nice module.'
|
|
||||||
version: '0.0.1'
|
|
||||||
license: 'MIT'
|
|
||||||
dependencies: []
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Minimal file structure:
|
|
||||||
```
|
|
||||||
v.mod
|
|
||||||
mymodule.v
|
|
||||||
```
|
|
||||||
|
|
||||||
Check that your module name is used in `mymodule.v`:
|
|
||||||
```v
|
|
||||||
module mymodule
|
|
||||||
|
|
||||||
pub fn hello_world() {
|
|
||||||
println('Hello World!')
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Create a git repository in the folder with the `v.mod` file
|
|
||||||
(this is not required if you used `v new` or `v init`):
|
|
||||||
```sh
|
|
||||||
git init
|
|
||||||
git add .
|
|
||||||
git commit -m "INIT"
|
|
||||||
````
|
|
||||||
|
|
||||||
3. Create a public repository on github.com.
|
|
||||||
4. Connect your local repository to the remote repository and push the changes.
|
|
||||||
5. Add your module to the public V module registry VPM:
|
|
||||||
https://vpm.vlang.io/new
|
|
||||||
|
|
||||||
You will have to login with your Github account to register the module.
|
|
||||||
**Warning:** _Currently it is not possibility to edit your entry after submiting.
|
|
||||||
Check your module name and github url twice as this cannot be changed by you later._
|
|
||||||
6. The final module name is a combination of your github account and
|
|
||||||
the module name you provided e.g. `mygithubname.mymodule`.
|
|
||||||
|
|
||||||
**Optional:** tag your V module with `vlang` and `vlang-module` on github.com
|
|
||||||
to allow for a better search experience.
|
|
||||||
|
|
||||||
## Type Declarations
|
## Type Declarations
|
||||||
|
|
||||||
### Interfaces
|
### Interfaces
|
||||||
|
@ -3573,7 +3431,7 @@ fn main() {
|
||||||
|
|
||||||
The timeout branch is optional. If it is absent `select` waits for an unlimited amount of time.
|
The timeout branch is optional. If it is absent `select` waits for an unlimited amount of time.
|
||||||
It is also possible to proceed immediately if no channel is ready in the moment `select` is called
|
It is also possible to proceed immediately if no channel is ready in the moment `select` is called
|
||||||
by adding an `else { ... }` branch. `else` and `> timeout` are mutually exclusive.
|
by adding an `else { ... }` branch. `else` and `<timeout>` are mutually exclusive.
|
||||||
|
|
||||||
The `select` command can be used as an *expression* of type `bool`
|
The `select` command can be used as an *expression* of type `bool`
|
||||||
that becomes `false` if all channels are closed:
|
that becomes `false` if all channels are closed:
|
||||||
|
@ -4287,6 +4145,153 @@ fn main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Package management
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
v [module option] [param]
|
||||||
|
```
|
||||||
|
|
||||||
|
###### module options:
|
||||||
|
|
||||||
|
```
|
||||||
|
install Install a module from VPM.
|
||||||
|
remove Remove a module that was installed from VPM.
|
||||||
|
search Search for a module from VPM.
|
||||||
|
update Update an installed module from VPM.
|
||||||
|
upgrade Upgrade all the outdated modules.
|
||||||
|
list List all installed modules.
|
||||||
|
outdated Show installed modules that need updates.
|
||||||
|
```
|
||||||
|
|
||||||
|
You can install modules already created by someone else with [VPM](https://vpm.vlang.io/):
|
||||||
|
```powershell
|
||||||
|
v install [module]
|
||||||
|
```
|
||||||
|
**Example:**
|
||||||
|
```powershell
|
||||||
|
v install ui
|
||||||
|
```
|
||||||
|
|
||||||
|
Modules can be installed directly from git or mercurial repositories.
|
||||||
|
```powershell
|
||||||
|
v install [--git|--hg] [url]
|
||||||
|
```
|
||||||
|
**Example:**
|
||||||
|
```powershell
|
||||||
|
v install --git https://github.com/vlang/markdown
|
||||||
|
```
|
||||||
|
|
||||||
|
Removing a module with v:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
v remove [module]
|
||||||
|
```
|
||||||
|
**Example:**
|
||||||
|
```powershell
|
||||||
|
v remove ui
|
||||||
|
```
|
||||||
|
|
||||||
|
Updating an installed module from [VPM](https://vpm.vlang.io/):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
v update [module]
|
||||||
|
```
|
||||||
|
**Example:**
|
||||||
|
```powershell
|
||||||
|
v update ui
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can update all your modules:
|
||||||
|
```powershell
|
||||||
|
v update
|
||||||
|
```
|
||||||
|
|
||||||
|
To see all the modules you have installed, you can use:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
v list
|
||||||
|
```
|
||||||
|
**Example:**
|
||||||
|
```powershell
|
||||||
|
> v list
|
||||||
|
Installed modules:
|
||||||
|
markdown
|
||||||
|
ui
|
||||||
|
```
|
||||||
|
|
||||||
|
To see all the modules that need updates:
|
||||||
|
```powershell
|
||||||
|
v outdated
|
||||||
|
```
|
||||||
|
**Example:**
|
||||||
|
```powershell
|
||||||
|
> v outdated
|
||||||
|
Modules are up to date.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Publish package
|
||||||
|
|
||||||
|
1. Put a `v.mod` file inside the toplevel folder of your module (if you
|
||||||
|
created your module with the command `v new mymodule` or `v init` you already have a v.mod file).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
v new mymodule
|
||||||
|
Input your project description: My nice module.
|
||||||
|
Input your project version: (0.0.0) 0.0.1
|
||||||
|
Input your project license: (MIT)
|
||||||
|
Initialising ...
|
||||||
|
Complete!
|
||||||
|
```
|
||||||
|
|
||||||
|
Example `v.mod`:
|
||||||
|
```v ignore
|
||||||
|
Module {
|
||||||
|
name: 'mymodule'
|
||||||
|
description: 'My nice module.'
|
||||||
|
version: '0.0.1'
|
||||||
|
license: 'MIT'
|
||||||
|
dependencies: []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Minimal file structure:
|
||||||
|
```
|
||||||
|
v.mod
|
||||||
|
mymodule.v
|
||||||
|
```
|
||||||
|
|
||||||
|
The name of your module should be used with the `module` directive
|
||||||
|
at the top of all files in your module. For `mymodule.v`:
|
||||||
|
```v
|
||||||
|
module mymodule
|
||||||
|
|
||||||
|
pub fn hello_world() {
|
||||||
|
println('Hello World!')
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Create a git repository in the folder with the `v.mod` file
|
||||||
|
(this is not required if you used `v new` or `v init`):
|
||||||
|
```sh
|
||||||
|
git init
|
||||||
|
git add .
|
||||||
|
git commit -m "INIT"
|
||||||
|
````
|
||||||
|
|
||||||
|
3. Create a public repository on github.com.
|
||||||
|
4. Connect your local repository to the remote repository and push the changes.
|
||||||
|
5. Add your module to the public V module registry VPM:
|
||||||
|
https://vpm.vlang.io/new
|
||||||
|
|
||||||
|
You will have to login with your Github account to register the module.
|
||||||
|
**Warning:** _Currently it is not possible to edit your entry after submiting.
|
||||||
|
Check your module name and github url twice as this cannot be changed by you later._
|
||||||
|
6. The final module name is a combination of your github account and
|
||||||
|
the module name you provided e.g. `mygithubname.mymodule`.
|
||||||
|
|
||||||
|
**Optional:** tag your V module with `vlang` and `vlang-module` on github.com
|
||||||
|
to allow for a better search experience.
|
||||||
|
|
||||||
# Advanced Topics
|
# Advanced Topics
|
||||||
|
|
||||||
## Dumping expressions at runtime
|
## Dumping expressions at runtime
|
||||||
|
@ -4953,13 +4958,13 @@ V can embed arbitrary files into the executable with the `$embed_file(<path>)`
|
||||||
compile time call. Paths can be absolute or relative to the source file.
|
compile time call. Paths can be absolute or relative to the source file.
|
||||||
|
|
||||||
When you do not use `-prod`, the file will not be embedded. Instead, it will
|
When you do not use `-prod`, the file will not be embedded. Instead, it will
|
||||||
be loaded *the first time* your program calls `f.data()` at runtime, making
|
be loaded *the first time* your program calls `embedded_file.data()` at runtime, making
|
||||||
it easier to change in external editor programs, without needing to recompile
|
it easier to change in external editor programs, without needing to recompile
|
||||||
your executable.
|
your executable.
|
||||||
|
|
||||||
When you compile with `-prod`, the file *will be embedded inside* your
|
When you compile with `-prod`, the file *will be embedded inside* your
|
||||||
executable, increasing your binary size, but making it more self contained
|
executable, increasing your binary size, but making it more self contained
|
||||||
and thus easier to distribute. In this case, `f.data()` will cause *no IO*,
|
and thus easier to distribute. In this case, `embedded_file.data()` will cause *no IO*,
|
||||||
and it will always return the same data.
|
and it will always return the same data.
|
||||||
|
|
||||||
#### `$tmpl` for embedding and parsing V template files
|
#### `$tmpl` for embedding and parsing V template files
|
||||||
|
@ -5154,39 +5159,27 @@ the boolean expression is highly improbable. In the JS backend, that does nothin
|
||||||
Having built-in JSON support is nice, but V also allows you to create efficient
|
Having built-in JSON support is nice, but V also allows you to create efficient
|
||||||
serializers for any data format. V has compile-time `if` and `for` constructs:
|
serializers for any data format. V has compile-time `if` and `for` constructs:
|
||||||
|
|
||||||
```v wip
|
```v
|
||||||
// TODO: not fully implemented
|
|
||||||
|
|
||||||
struct User {
|
struct User {
|
||||||
name string
|
name string
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: T should be passed a struct name only
|
fn main() {
|
||||||
fn decode<T>(data string) T {
|
$for field in User.fields {
|
||||||
mut result := T{}
|
$if field.typ is string {
|
||||||
// compile-time `for` loop
|
println('$field.name is of type string')
|
||||||
// T.fields gives an array of a field metadata type
|
}
|
||||||
$for field in T.fields {
|
}
|
||||||
$if field.typ is string {
|
|
||||||
// $(string_expr) produces an identifier
|
|
||||||
result.$(field.name) = get_string(data, field.name)
|
|
||||||
} $else $if field.typ is int {
|
|
||||||
result.$(field.name) = get_int(data, field.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// `decode<User>` generates:
|
// Output:
|
||||||
fn decode_User(data string) User {
|
// name is of type string
|
||||||
mut result := User{}
|
|
||||||
result.name = get_string(data, 'name')
|
|
||||||
result.age = get_int(data, 'age')
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
See [`examples/compiletime/reflection.v`](/examples/compiletime/reflection.v)
|
||||||
|
for a more complete example.
|
||||||
|
|
||||||
## Limited operator overloading
|
## Limited operator overloading
|
||||||
|
|
||||||
```v
|
```v
|
||||||
|
@ -5234,7 +5227,7 @@ To improve safety and maintainability, operator overloading is limited:
|
||||||
- `!=`, `>`, `<=` and `>=` are auto generated when `==` and `<` are defined.
|
- `!=`, `>`, `<=` and `>=` are auto generated when `==` and `<` are defined.
|
||||||
- Both arguments must have the same type (just like with all operators in V).
|
- Both arguments must have the same type (just like with all operators in V).
|
||||||
- Assignment operators (`*=`, `+=`, `/=`, etc)
|
- Assignment operators (`*=`, `+=`, `/=`, etc)
|
||||||
are auto generated when the operators are defined though they must return the same type.
|
are auto generated when the corresponding operators are defined and operands are of the same type.
|
||||||
|
|
||||||
## Inline assembly
|
## Inline assembly
|
||||||
<!-- ignore because it doesn't pass fmt test (why?) -->
|
<!-- ignore because it doesn't pass fmt test (why?) -->
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
// An example deserializer implementation
|
||||||
|
|
||||||
|
struct User {
|
||||||
|
name string
|
||||||
|
age int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
data := 'name=Alice\nage=18'
|
||||||
|
user := decode<User>(data)
|
||||||
|
println(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode<T>(data string) T {
|
||||||
|
mut result := T{}
|
||||||
|
// compile-time `for` loop
|
||||||
|
// T.fields gives an array of a field metadata type
|
||||||
|
$for field in T.fields {
|
||||||
|
$if field.typ is string {
|
||||||
|
// $(string_expr) produces an identifier
|
||||||
|
result.$(field.name) = get_string(data, field.name)
|
||||||
|
} $else $if field.typ is int {
|
||||||
|
result.$(field.name) = get_int(data, field.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_string(data string, field_name string) string {
|
||||||
|
for line in data.split_into_lines() {
|
||||||
|
key_val := line.split('=')
|
||||||
|
if key_val[0] == field_name {
|
||||||
|
return key_val[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_int(data string, field string) int {
|
||||||
|
return get_string(data, field).int()
|
||||||
|
}
|
||||||
|
|
||||||
|
// `decode<User>` generates:
|
||||||
|
// fn decode_User(data string) User {
|
||||||
|
// mut result := User{}
|
||||||
|
// result.name = get_string(data, 'name')
|
||||||
|
// result.age = get_int(data, 'age')
|
||||||
|
// return result
|
||||||
|
// }
|
Loading…
Reference in New Issue