mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
Compare commits
57 Commits
d53d95991d
...
428fd7f57f
Author | SHA1 | Date | |
---|---|---|---|
|
428fd7f57f | ||
|
453137384e | ||
|
6a4bfef2c5 | ||
|
9f5e9ba1cf | ||
|
ef5c3cdb73 | ||
|
5ec7ee916a | ||
|
b556f1302f | ||
|
fe9bdd4168 | ||
|
8ee1667a9a | ||
|
1d9835f0e4 | ||
|
6b978a6b5a | ||
|
43800a05e8 | ||
|
ecca3b155e | ||
|
600f891d3a | ||
|
b6d6d4b037 | ||
|
ecf8fcd45a | ||
|
177bb30013 | ||
|
367e38d7d1 | ||
|
def0161281 | ||
|
a1aca4c578 | ||
|
5061aeee64 | ||
|
f4c2ecfaa9 | ||
|
9be80198fc | ||
|
a609d6c9d1 | ||
|
fd81bae361 | ||
|
8861538c66 | ||
|
0f861db9b0 | ||
|
9750061d70 | ||
|
81e99a2af3 | ||
|
367289a1f1 | ||
|
2cd5b8a86d | ||
|
618961fab5 | ||
|
d97423d385 | ||
|
30d4e25385 | ||
|
32114a679a | ||
|
37e7d5f5ae | ||
|
8735694d13 | ||
|
77049600e6 | ||
|
b622dca915 | ||
|
e78e468d5f | ||
|
1c2b4e76dc | ||
|
112a1278bb | ||
|
8586f18383 | ||
|
a61a2fd328 | ||
|
c4a679186f | ||
|
490a014bf6 | ||
|
4ed9703e22 | ||
|
c881e7284d | ||
|
2f2dde8ad0 | ||
|
2fa177e310 | ||
|
2266ccecf3 | ||
|
b25288338c | ||
|
e0aba77cc5 | ||
|
c7f708e64d | ||
|
aa3d560b05 | ||
|
76e3b7dff8 | ||
|
fe87d20f20 |
@ -6,7 +6,7 @@ end_of_line = lf
|
|||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.v]
|
[*.{v,js,css}]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
||||||
[*.{bat,cmd}]
|
[*.{bat,cmd}]
|
||||||
|
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@ -1,7 +1,6 @@
|
|||||||
name: 🐛 Bug Report
|
name: 🐛 Bug Report
|
||||||
description: Report a bug
|
description: Report a bug
|
||||||
title: (bug report summary)
|
labels: [Bug]
|
||||||
labels: Bug
|
|
||||||
body:
|
body:
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
|
3
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
3
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@ -1,7 +1,6 @@
|
|||||||
name: 🚀 Feature Request
|
name: 🚀 Feature Request
|
||||||
description: Suggest an idea for this project
|
description: Suggest an idea for this project
|
||||||
title: (feature request summary)
|
labels: [Feature Request]
|
||||||
labels: Feature Request
|
|
||||||
body:
|
body:
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: description
|
id: description
|
||||||
|
2
.github/workflows/c2v_ci.yml
vendored
2
.github/workflows/c2v_ci.yml
vendored
@ -60,7 +60,7 @@ jobs:
|
|||||||
doom-regressions:
|
doom-regressions:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||||
timeout-minutes: 10
|
timeout-minutes: 20
|
||||||
env:
|
env:
|
||||||
VFLAGS: -cc tcc
|
VFLAGS: -cc tcc
|
||||||
DISPLAY: :99
|
DISPLAY: :99
|
||||||
|
2
.github/workflows/gg_regressions_ci.yml
vendored
2
.github/workflows/gg_regressions_ci.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
gg-regressions:
|
gg-regressions:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||||
timeout-minutes: 10
|
timeout-minutes: 20
|
||||||
env:
|
env:
|
||||||
VFLAGS: -cc tcc
|
VFLAGS: -cc tcc
|
||||||
DISPLAY: :99
|
DISPLAY: :99
|
||||||
|
19
.github/workflows/module_docs_lint.yml
vendored
Normal file
19
.github/workflows/module_docs_lint.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: Code CI vlib modules
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- '**/cmd/tools/vdoc/theme/**'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '**/cmd/tools/vdoc/theme/**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-module-docs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Check Formatting
|
||||||
|
uses: actionsx/prettier@v2
|
||||||
|
with:
|
||||||
|
args: --check cmd/tools/vdoc/theme
|
2
.github/workflows/other_ci.yml
vendored
2
.github/workflows/other_ci.yml
vendored
@ -63,7 +63,7 @@ jobs:
|
|||||||
- name: Repeat -o hw.c examples/hello_world.v
|
- name: Repeat -o hw.c examples/hello_world.v
|
||||||
run: cmd/tools/repeat --max_time 251 --series 3 --count 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -show-timings -o hw.c examples/hello_world.v' . ./vmaster
|
run: cmd/tools/repeat --max_time 251 --series 3 --count 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -show-timings -o hw.c examples/hello_world.v' . ./vmaster
|
||||||
- name: Repeat -o v.c cmd/v
|
- name: Repeat -o v.c cmd/v
|
||||||
run: cmd/tools/repeat --max_time 1701 --series 3 --count 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -show-timings -o v.c cmd/v' . ./vmaster
|
run: cmd/tools/repeat --max_time 1731 --series 3 --count 20 --nmins 2 --nmaxs 5 --warmup 3 --fail_percent 10 -t 'cd {T} ; ./v -show-timings -o v.c cmd/v' . ./vmaster
|
||||||
|
|
||||||
misc-tooling:
|
misc-tooling:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
2
.github/workflows/vab_ci.yml
vendored
2
.github/workflows/vab_ci.yml
vendored
@ -52,7 +52,7 @@ jobs:
|
|||||||
v-compiles-os-android:
|
v-compiles-os-android:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
if: github.event_name != 'push' || github.event.ref == 'refs/heads/master' || github.event.repository.full_name != 'vlang/v'
|
||||||
timeout-minutes: 10
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Build V
|
- name: Build V
|
||||||
|
31
README.md
31
README.md
@ -201,34 +201,23 @@ cd v
|
|||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installing editor/IDE plugin
|
## Editor/IDE Plugins
|
||||||
|
|
||||||
V has plugins for many editors:
|
To bring IDE functions for the V programming languages to your editor, check out
|
||||||
|
[v-analyzer](https://github.com/v-analyzer/v-analyzer). It provides a
|
||||||
|
[VS Code extension](https://marketplace.visualstudio.com/items?itemName=VOSCA.vscode-v-analyzer)
|
||||||
|
and language server capabilities for other editors.
|
||||||
|
|
||||||
|
The plugin for JetBrains IDEs (IntelliJ, CLion, GoLand, etc.) also offers a great development
|
||||||
|
experience with V. You can find all features in [its documentation](https://plugins.jetbrains.com/plugin/20287-vlang/docs/syntax-highlighting.html).
|
||||||
|
|
||||||
|
Other Plugins:
|
||||||
|
|
||||||
- [VS Code plugin](https://github.com/vlang/vscode-vlang)
|
|
||||||
- [JetBrains IDE plugin](https://plugins.jetbrains.com/plugin/20287-vlang/docs/quick-start-guide.html)
|
|
||||||
- [Vim plugins](https://github.com/vlang/awesome-v#vim)
|
- [Vim plugins](https://github.com/vlang/awesome-v#vim)
|
||||||
- [Emacs plugins](https://github.com/vlang/awesome-v#emacs)
|
- [Emacs plugins](https://github.com/vlang/awesome-v#emacs)
|
||||||
- [Sublime Text 3 plugins](https://github.com/vlang/awesome-v#sublime-text-3)
|
- [Sublime Text 3 plugins](https://github.com/vlang/awesome-v#sublime-text-3)
|
||||||
- [Atom plugins](https://github.com/vlang/awesome-v#atom)
|
- [Atom plugins](https://github.com/vlang/awesome-v#atom)
|
||||||
|
|
||||||
### IntelliSense
|
|
||||||
|
|
||||||
V has a Language Server:
|
|
||||||
[VLS](https://github.com/vlang/vls).
|
|
||||||
The VS Code plugin provides built-in support for VLS.
|
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> VLS may be unstable at the moment.
|
|
||||||
> If you encounter any problem, please create a new
|
|
||||||
> [issue](https://github.com/vlang/vls/issues).
|
|
||||||
|
|
||||||
The plugin for JetBrains IDE (IntelliJ, CLion, GoLand, etc) at the moment is
|
|
||||||
the best choice if you want a great V development experience.
|
|
||||||
You can see all its features in
|
|
||||||
[its documentation](https://plugins.jetbrains.com/plugin/20287-vlang/docs/syntax-highlighting.html).
|
|
||||||
|
|
||||||
## Testing and running the examples
|
## Testing and running the examples
|
||||||
|
|
||||||
Make sure V can compile itself:
|
Make sure V can compile itself:
|
||||||
|
@ -12,7 +12,7 @@ import term
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
base_os = 'linux'
|
base_os = 'linux'
|
||||||
os_names = ['linux', 'macos', 'windows']
|
os_names = ['linux', 'macos', 'windows', 'freebsd', 'openbsd', 'solaris', 'termux']
|
||||||
skip_modules = [
|
skip_modules = [
|
||||||
'builtin.bare',
|
'builtin.bare',
|
||||||
'builtin.linux_bare.old',
|
'builtin.linux_bare.old',
|
||||||
@ -103,7 +103,7 @@ fn (app App) gen_api_for_module_in_os(mod_name string, os_name string) string {
|
|||||||
for s in f.stmts {
|
for s in f.stmts {
|
||||||
if s is ast.FnDecl {
|
if s is ast.FnDecl {
|
||||||
if s.is_pub {
|
if s.is_pub {
|
||||||
fn_signature := s.stringify_fn_decl(b.table, mod_name, map[string]string{})
|
fn_signature := b.table.stringify_fn_decl(&s, mod_name, map[string]string{})
|
||||||
fn_mod := s.modname()
|
fn_mod := s.modname()
|
||||||
if fn_mod == mod_name {
|
if fn_mod == mod_name {
|
||||||
fline := '${fn_mod}: ${fn_signature}'
|
fline := '${fn_mod}: ${fn_signature}'
|
||||||
|
@ -10,6 +10,7 @@ import v.ast
|
|||||||
import v.token
|
import v.token
|
||||||
import v.doc
|
import v.doc
|
||||||
import v.pref
|
import v.pref
|
||||||
|
import v.util { tabs }
|
||||||
|
|
||||||
const (
|
const (
|
||||||
css_js_assets = ['doc.css', 'normalize.css', 'doc.js', 'dark-mode.js']
|
css_js_assets = ['doc.css', 'normalize.css', 'doc.js', 'dark-mode.js']
|
||||||
@ -249,27 +250,27 @@ fn (vd VDoc) gen_html(d doc.Doc) string {
|
|||||||
version).replace('{{ light_icon }}', vd.assets['light_icon']).replace('{{ dark_icon }}',
|
version).replace('{{ light_icon }}', vd.assets['light_icon']).replace('{{ dark_icon }}',
|
||||||
vd.assets['dark_icon']).replace('{{ menu_icon }}', vd.assets['menu_icon']).replace('{{ head_assets }}',
|
vd.assets['dark_icon']).replace('{{ menu_icon }}', vd.assets['menu_icon']).replace('{{ head_assets }}',
|
||||||
if cfg.inline_assets {
|
if cfg.inline_assets {
|
||||||
'\n${tabs[0]}<style>' + vd.assets['doc_css'] + '</style>\n${tabs[0]}<style>' +
|
'<style>${vd.assets['doc_css']}</style>
|
||||||
vd.assets['normalize_css'] + '</style>\n${tabs[0]}<script>' +
|
${tabs(2)}<style>${vd.assets['normalize_css']}</style>
|
||||||
vd.assets['dark_mode_js'] + '</script>'
|
${tabs(2)}<script>${vd.assets['dark_mode_js']}</script>'
|
||||||
} else {
|
} else {
|
||||||
'\n${tabs[0]}<link rel="stylesheet" href="' + vd.assets['doc_css'] +
|
'<link rel="stylesheet" href="${vd.assets['doc_css']}" />
|
||||||
'" />\n${tabs[0]}<link rel="stylesheet" href="' + vd.assets['normalize_css'] +
|
${tabs(2)}<link rel="stylesheet" href="${vd.assets['normalize_css']}" />
|
||||||
'" />\n${tabs[0]}<script src="' + vd.assets['dark_mode_js'] + '"></script>'
|
${tabs(2)}<script src="${vd.assets['dark_mode_js']}"></script>'
|
||||||
}).replace('{{ toc_links }}', if cfg.is_multi || vd.docs.len > 1 {
|
}).replace('{{ toc_links }}', if cfg.is_multi || vd.docs.len > 1 {
|
||||||
modules_toc_str
|
modules_toc_str
|
||||||
} else {
|
} else {
|
||||||
symbols_toc_str
|
symbols_toc_str
|
||||||
}).replace('{{ contents }}', contents.str()).replace('{{ right_content }}', if cfg.is_multi
|
}).replace('{{ contents }}', contents.str()).replace('{{ right_content }}', if cfg.is_multi
|
||||||
&& vd.docs.len > 1 && d.head.name != 'README' {
|
&& d.head.name != 'README' {
|
||||||
'<div class="doc-toc"><ul>' + symbols_toc_str + '</ul></div>'
|
'<div class="doc-toc"><ul>${symbols_toc_str}</ul></div>'
|
||||||
} else {
|
} else {
|
||||||
''
|
''
|
||||||
}).replace('{{ footer_content }}', gen_footer_text(d, !cfg.no_timestamp)).replace('{{ footer_assets }}',
|
}).replace('{{ footer_content }}', gen_footer_text(d, !cfg.no_timestamp)).replace('{{ footer_assets }}',
|
||||||
if cfg.inline_assets {
|
if cfg.inline_assets {
|
||||||
'<script>' + vd.assets['doc_js'] + '</script>'
|
'<script>${vd.assets['doc_js']}</script>'
|
||||||
} else {
|
} else {
|
||||||
'<script src="' + vd.assets['doc_js'] + '"></script>'
|
'<script src="${vd.assets['doc_js']}"></script>'
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -407,12 +408,12 @@ fn doc_node_html(dn doc.DocNode, link string, head bool, include_examples bool,
|
|||||||
node_id = 'readme_${node_id}'
|
node_id = 'readme_${node_id}'
|
||||||
hash_link = ' <a href="#${node_id}">#</a>'
|
hash_link = ' <a href="#${node_id}">#</a>'
|
||||||
}
|
}
|
||||||
dnw.writeln('${tabs[1]}<section id="${node_id}" class="doc-node${node_class}">')
|
dnw.writeln('${tabs(2)}<section id="${node_id}" class="doc-node${node_class}">')
|
||||||
if dn.name.len > 0 {
|
if dn.name.len > 0 {
|
||||||
if dn.kind == .const_group {
|
if dn.kind == .const_group {
|
||||||
dnw.write_string('${tabs[2]}<div class="title"><${head_tag}>${sym_name}${hash_link}</${head_tag}>')
|
dnw.write_string('${tabs(3)}<div class="title"><${head_tag}>${sym_name}${hash_link}</${head_tag}>')
|
||||||
} else {
|
} else {
|
||||||
dnw.write_string('${tabs[2]}<div class="title"><${head_tag}>${dn.kind} ${sym_name}${hash_link}</${head_tag}>')
|
dnw.write_string('${tabs(3)}<div class="title"><${head_tag}>${dn.kind} ${sym_name}${hash_link}</${head_tag}>')
|
||||||
}
|
}
|
||||||
if link.len != 0 {
|
if link.len != 0 {
|
||||||
dnw.write_string('<a class="link" rel="noreferrer" target="_blank" href="${link}">${link_svg}</a>')
|
dnw.write_string('<a class="link" rel="noreferrer" target="_blank" href="${link}">${link_svg}</a>')
|
||||||
|
1
cmd/tools/vdoc/tests/testdata/readme_in_project_root/README.md
vendored
Normal file
1
cmd/tools/vdoc/tests/testdata/readme_in_project_root/README.md
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
hello from readme
|
3
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.comments.out
vendored
Normal file
3
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.comments.out
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module foo
|
||||||
|
|
||||||
|
fn bar()
|
4
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.readme.comments.out
vendored
Normal file
4
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.readme.comments.out
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
hello from readme
|
||||||
|
module foo
|
||||||
|
|
||||||
|
fn bar()
|
3
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.v
vendored
Normal file
3
cmd/tools/vdoc/tests/testdata/readme_in_project_root/src/main.v
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module foo
|
||||||
|
|
||||||
|
pub fn bar() {}
|
0
cmd/tools/vdoc/tests/testdata/readme_in_project_root/v.mod
vendored
Normal file
0
cmd/tools/vdoc/tests/testdata/readme_in_project_root/v.mod
vendored
Normal file
@ -52,6 +52,11 @@ fn check_path(vexe string, dir string, tests []string) int {
|
|||||||
cmd: '${os.quoted_path(vexe)} doc -comments ${os.quoted_path(program)}'
|
cmd: '${os.quoted_path(vexe)} doc -comments ${os.quoted_path(program)}'
|
||||||
out_filename: 'main.comments.out'
|
out_filename: 'main.comments.out'
|
||||||
)
|
)
|
||||||
|
fails += check_output(
|
||||||
|
program: program
|
||||||
|
cmd: '${os.quoted_path(vexe)} doc -readme -comments ${os.quoted_path(program)}'
|
||||||
|
out_filename: 'main.readme.comments.out'
|
||||||
|
)
|
||||||
total_fails += fails
|
total_fails += fails
|
||||||
if fails == 0 {
|
if fails == 0 {
|
||||||
println(term.green('OK'))
|
println(term.green('OK'))
|
||||||
@ -71,7 +76,7 @@ fn print_compare(expected string, found string) {
|
|||||||
println(found)
|
println(found)
|
||||||
println('============\n')
|
println('============\n')
|
||||||
println('diff:')
|
println('diff:')
|
||||||
println(diff.color_compare_strings(diff_cmd, rand.ulid(), found, expected))
|
println(diff.color_compare_strings(diff_cmd, rand.ulid(), expected, found))
|
||||||
println('============\n')
|
println('============\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
cmd/tools/vdoc/theme/.prettierrc
Normal file
5
cmd/tools/vdoc/theme/.prettierrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"useTabs": true,
|
||||||
|
"printWidth": 100,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
(function() {
|
(function () {
|
||||||
var html = document.getElementsByTagName('html')[0];
|
if (localStorage.getItem('dark-mode') === 'true') {
|
||||||
if (localStorage.getItem('dark-mode') === 'true') {
|
document.querySelector('html').classList.add('dark');
|
||||||
html.classList.add('dark');
|
}
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,235 +1,204 @@
|
|||||||
(function () {
|
(function () {
|
||||||
if (document.body.scrollIntoView) {
|
const docnav = document.querySelector('.doc-nav');
|
||||||
var docnav = document.querySelector('.doc-nav');
|
const active = docnav.querySelector('li.active');
|
||||||
var active = docnav.querySelector('li.active');
|
active?.scrollIntoView({ block: 'center', inline: 'nearest' });
|
||||||
if (active) {
|
setupMobileToggle();
|
||||||
active.scrollIntoView({ block: 'center', inline: 'nearest' });
|
setupDarkMode();
|
||||||
}
|
setupScrollSpy();
|
||||||
}
|
setupSearch();
|
||||||
setupScrollSpy();
|
setupCollapse();
|
||||||
setupMobileToggle();
|
|
||||||
setupDarkMode();
|
|
||||||
setupSearch();
|
|
||||||
setupCollapse();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function setupScrollSpy() {
|
function setupScrollSpy() {
|
||||||
var sectionPositions = [];
|
const sections = document.querySelectorAll('section');
|
||||||
var sections = document.querySelectorAll('section');
|
const sectionPositions = Array.from(sections).map((section) => section.offsetTop);
|
||||||
sections.forEach(function (section) {
|
let scrollPos = 0;
|
||||||
sectionPositions.push(section.offsetTop);
|
window.addEventListener('scroll', () => {
|
||||||
});
|
const toc = document.querySelector('.doc-toc');
|
||||||
var scrollPos = 0;
|
// Reset classes
|
||||||
window.addEventListener('scroll', function (_) {
|
toc.querySelectorAll('a[class="active"]').forEach((link) => link.classList.remove('active'));
|
||||||
// Reset classes
|
// Set current menu link as active
|
||||||
document.querySelectorAll('.doc-toc a[class="active"]').forEach(function (link) {
|
let scrollPosition = document.documentElement.scrollTop || document.body.scrollTop;
|
||||||
link.classList.remove('active');
|
for (const [i, position] of sectionPositions.entries()) {
|
||||||
});
|
if (position >= scrollPosition) {
|
||||||
// Set current menu link as active
|
const section = sections[i];
|
||||||
var scrollPosition = document.documentElement.scrollTop || document.body.scrollTop;
|
const link = toc.querySelector('a[href="#' + section.id + '"]');
|
||||||
for (var i = 0; i < sectionPositions.length; i++) {
|
if (link) {
|
||||||
var section = sections[i];
|
link.classList.add('active');
|
||||||
var position = sectionPositions[i];
|
const tocHeight = toc.clientHeight;
|
||||||
if (position >= scrollPosition) {
|
const scrollTop = toc.scrollTop;
|
||||||
var link = document.querySelector('.doc-toc a[href="#' + section.id + '"]');
|
if (
|
||||||
if (link) {
|
document.body.getBoundingClientRect().top < scrollPos &&
|
||||||
link.classList.add('active');
|
scrollTop < link.offsetTop - 10
|
||||||
var docToc = document.querySelector('.doc-toc');
|
) {
|
||||||
var tocHeight = docToc.clientHeight;
|
toc.scrollTop = link.clientHeight + link.offsetTop - tocHeight + 10;
|
||||||
var scrollTop = docToc.scrollTop;
|
} else if (scrollTop > link.offsetTop - 10) {
|
||||||
if ((document.body.getBoundingClientRect()).top < scrollPos && scrollTop < link.offsetTop - 10) {
|
toc.scrollTop = link.offsetTop - 10;
|
||||||
docToc.scrollTop = link.clientHeight + link.offsetTop - tocHeight + 10;
|
}
|
||||||
} else if (scrollTop > link.offsetTop - 10) {
|
}
|
||||||
docToc.scrollTop = link.offsetTop - 10;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
scrollPos = document.body.getBoundingClientRect().top;
|
||||||
}
|
});
|
||||||
}
|
|
||||||
scrollPos = (document.body.getBoundingClientRect()).top;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupMobileToggle() {
|
function setupMobileToggle() {
|
||||||
var toggle = document.getElementById('toggle-menu');
|
document.getElementById('toggle-menu').addEventListener('click', () => {
|
||||||
toggle.addEventListener('click', function (_) {
|
const docNav = document.querySelector('.doc-nav');
|
||||||
var docNav = document.querySelector('.doc-nav');
|
const isHidden = docNav.classList.contains('hidden');
|
||||||
var isHidden = docNav.classList.contains('hidden');
|
docNav.classList.toggle('hidden');
|
||||||
docNav.classList.toggle('hidden');
|
const search = docNav.querySelector('.search');
|
||||||
var search = document.querySelector('.doc-nav > .search');
|
// console.log(search);
|
||||||
console.log(search);
|
const searchHasResults = search.classList.contains('has-results');
|
||||||
var searchHasResults = search.classList.contains('has-results');
|
if (isHidden && searchHasResults) {
|
||||||
if (isHidden && searchHasResults) {
|
search.classList.remove('mobile-hidden');
|
||||||
search.classList.remove('mobile-hidden');
|
} else {
|
||||||
} else {
|
search.classList.add('mobile-hidden');
|
||||||
search.classList.add('mobile-hidden');
|
}
|
||||||
}
|
const content = docNav.querySelector('.content');
|
||||||
var content = document.querySelector('.doc-nav .content');
|
content.classList.toggle('hidden');
|
||||||
content.classList.toggle('hidden');
|
content.classList.toggle('show');
|
||||||
content.classList.toggle('show');
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupDarkMode() {
|
function setupDarkMode() {
|
||||||
var html = document.getElementsByTagName('html')[0];
|
const html = document.querySelector('html');
|
||||||
var darkModeToggle = document.getElementById('dark-mode-toggle');
|
const darkModeToggle = document.getElementById('dark-mode-toggle');
|
||||||
darkModeToggle.addEventListener('click', function () {
|
darkModeToggle.addEventListener('click', () => {
|
||||||
html.classList.toggle('dark');
|
html.classList.toggle('dark');
|
||||||
var isDarkModeEnabled = html.classList.contains('dark');
|
const isDarkModeEnabled = html.classList.contains('dark');
|
||||||
localStorage.setItem('dark-mode', isDarkModeEnabled);
|
localStorage.setItem('dark-mode', isDarkModeEnabled);
|
||||||
darkModeToggle.setAttribute('aria-checked', isDarkModeEnabled)
|
darkModeToggle.setAttribute('aria-checked', isDarkModeEnabled);
|
||||||
});
|
});
|
||||||
// Check if css var() is supported and enable dark mode toggle
|
|
||||||
if (window.CSS && CSS.supports('color', 'var(--fake-var)')) {
|
|
||||||
darkModeToggle.style.visibility = 'unset';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupSearch() {
|
function setupSearch() {
|
||||||
var searchInput = document.getElementById('search');
|
const searchInput = document.getElementById('search');
|
||||||
var onInputChange = debounce(function (e) {
|
const onInputChange = debounce((e) => {
|
||||||
var searchValue = e.target.value.toLowerCase();
|
const searchValue = e.target.value.toLowerCase();
|
||||||
var menu = document.querySelector('.doc-nav > .content');
|
const docNav = document.querySelector('.doc-nav');
|
||||||
var search = document.querySelector('.doc-nav > .search');
|
const menu = docNav.querySelector('.content');
|
||||||
if (searchValue === '') {
|
const search = docNav.querySelector('.search');
|
||||||
// reset to default
|
if (searchValue === '') {
|
||||||
menu.style.display = '';
|
// reset to default
|
||||||
if (!search.classList.contains('hidden')) {
|
menu.style.display = '';
|
||||||
search.classList.add('hidden');
|
if (!search.classList.contains('hidden')) {
|
||||||
search.classList.remove('has-results');
|
search.classList.add('hidden');
|
||||||
}
|
search.classList.remove('has-results');
|
||||||
} else if (searchValue.length >= 2) {
|
}
|
||||||
// search for less than 2 characters can display too much results
|
} else if (searchValue.length >= 2) {
|
||||||
search.innerHTML = '';
|
// search for less than 2 characters can display too much results
|
||||||
menu.style.display = 'none';
|
search.innerHTML = '';
|
||||||
if (search.classList.contains('hidden')) {
|
menu.style.display = 'none';
|
||||||
search.classList.remove('hidden');
|
if (search.classList.contains('hidden')) {
|
||||||
search.classList.remove('mobile-hidden');
|
search.classList.remove('hidden');
|
||||||
search.classList.add('has-results');
|
search.classList.remove('mobile-hidden');
|
||||||
}
|
search.classList.add('has-results');
|
||||||
// cache length for performance
|
}
|
||||||
var foundModule = false;
|
// cache length for performance
|
||||||
var searchModuleIndexLength = searchModuleIndex.length;
|
let foundModule = false;
|
||||||
var ul = document.createElement('ul');
|
const ul = document.createElement('ul');
|
||||||
search.appendChild(ul);
|
search.appendChild(ul);
|
||||||
for (var i = 0; i < searchModuleIndexLength; i++) {
|
for (const [i, title] of searchModuleIndex.entries()) {
|
||||||
// no toLowerCase needed because modules are always lowercase
|
// no toLowerCase needed because modules are always lowercase
|
||||||
var title = searchModuleIndex[i];
|
if (title.indexOf(searchValue) === -1) {
|
||||||
if (title.indexOf(searchValue) === -1) {
|
continue;
|
||||||
continue
|
}
|
||||||
}
|
foundModule = true;
|
||||||
foundModule = true;
|
// [description, link]
|
||||||
// [description, link]
|
const data = searchModuleData[i];
|
||||||
var data = searchModuleData[i];
|
const el = createSearchResult({
|
||||||
var description = data[0];
|
badge: 'module',
|
||||||
var link = data[1];
|
description: data[0],
|
||||||
var el = createSearchResult({
|
link: data[1],
|
||||||
link: link,
|
title: title,
|
||||||
title: title,
|
});
|
||||||
description: description,
|
ul.appendChild(el);
|
||||||
badge: 'module',
|
}
|
||||||
});
|
if (foundModule) {
|
||||||
ul.appendChild(el);
|
const hr = document.createElement('hr');
|
||||||
}
|
hr.classList.add('separator');
|
||||||
if (foundModule) {
|
search.appendChild(hr);
|
||||||
var hr = document.createElement('hr');
|
}
|
||||||
hr.classList.add('separator');
|
let results = [];
|
||||||
search.appendChild(hr);
|
for (const [i, title] of searchIndex.entries()) {
|
||||||
}
|
if (title.toLowerCase().indexOf(searchValue) === -1) {
|
||||||
var searchIndexLength = searchIndex.length;
|
continue;
|
||||||
var results = [];
|
}
|
||||||
for (var i = 0; i < searchIndexLength; i++) {
|
// [badge, description, link]
|
||||||
var title = searchIndex[i];
|
const data = searchData[i];
|
||||||
if (title.toLowerCase().indexOf(searchValue) === -1) {
|
results.push({
|
||||||
continue
|
badge: data[0],
|
||||||
}
|
description: data[1],
|
||||||
// [badge, description, link]
|
link: data[2],
|
||||||
var data = searchData[i];
|
title: data[3] + ' ' + title,
|
||||||
var badge = data[0];
|
});
|
||||||
var description = data[1];
|
}
|
||||||
var link = data[2];
|
results.sort((a, b) => (a.title < b.title ? -1 : a.title > b.title ? 1 : 0));
|
||||||
var prefix = data[3];
|
const ul_ = document.createElement('ul');
|
||||||
results.push({
|
search.appendChild(ul_);
|
||||||
badge: badge,
|
results.forEach((result) => {
|
||||||
description: description,
|
const el = createSearchResult(result);
|
||||||
link: link,
|
ul_.appendChild(el);
|
||||||
title: prefix + ' ' + title,
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
results.sort(function (a, b) {
|
searchInput.addEventListener('input', onInputChange);
|
||||||
if (a.title < b.title) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.title > b.title) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
var ul = document.createElement('ul');
|
|
||||||
search.appendChild(ul);
|
|
||||||
for (var i = 0; i < results.length; i++) {
|
|
||||||
var result = results[i];
|
|
||||||
var el = createSearchResult(result);
|
|
||||||
ul.appendChild(el);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
searchInput.addEventListener('input', onInputChange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSearchResult(data) {
|
function createSearchResult(data) {
|
||||||
var li = document.createElement('li');
|
const li = document.createElement('li');
|
||||||
li.classList.add('result');
|
li.classList.add('result');
|
||||||
var a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.href = data.link;
|
a.href = data.link;
|
||||||
a.classList.add('link');
|
a.classList.add('link');
|
||||||
li.appendChild(a);
|
li.appendChild(a);
|
||||||
var defintion = document.createElement('div');
|
const defintion = document.createElement('div');
|
||||||
defintion.classList.add('definition');
|
defintion.classList.add('definition');
|
||||||
a.appendChild(defintion);
|
a.appendChild(defintion);
|
||||||
if (data.description) {
|
if (data.description) {
|
||||||
var description = document.createElement('div');
|
const description = document.createElement('div');
|
||||||
description.classList.add('description');
|
description.classList.add('description');
|
||||||
description.textContent = data.description;
|
description.textContent = data.description;
|
||||||
a.appendChild(description);
|
a.appendChild(description);
|
||||||
}
|
}
|
||||||
var title = document.createElement('span');
|
const title = document.createElement('span');
|
||||||
title.classList.add('title');
|
title.classList.add('title');
|
||||||
title.textContent = data.title;
|
title.textContent = data.title;
|
||||||
defintion.appendChild(title);
|
defintion.appendChild(title);
|
||||||
var badge = document.createElement('badge');
|
const badge = document.createElement('badge');
|
||||||
badge.classList.add('badge');
|
badge.classList.add('badge');
|
||||||
badge.textContent = data.badge;
|
badge.textContent = data.badge;
|
||||||
defintion.appendChild(badge);
|
defintion.appendChild(badge);
|
||||||
return li;
|
return li;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupCollapse() {
|
function setupCollapse() {
|
||||||
var dropdownArrows = document.querySelectorAll('.dropdown-arrow');
|
const dropdownArrows = document.querySelectorAll('.dropdown-arrow');
|
||||||
for (var i = 0; i < dropdownArrows.length; i++) {
|
dropdownArrows.forEach((arrow) => {
|
||||||
var dropdownArrow = dropdownArrows[i];
|
arrow.addEventListener('click', (e) => {
|
||||||
dropdownArrow.addEventListener('click', function (e) {
|
const parent = e.target.parentElement.parentElement.parentElement;
|
||||||
var parent = e.target.parentElement.parentElement.parentElement;
|
parent.classList.toggle('open');
|
||||||
parent.classList.toggle('open');
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function debounce(func, timeout) {
|
function debounce(func, timeout) {
|
||||||
var timer;
|
let timer;
|
||||||
return (...args) => {
|
return (...args) => {
|
||||||
const next = () => func(...args);
|
const next = () => func(...args);
|
||||||
if (timer) {
|
if (timer) {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
}
|
}
|
||||||
timer = setTimeout(next, timeout > 0 ? timeout : 300);
|
timer = setTimeout(next, timeout > 0 ? timeout : 300);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('keypress', (ev) => {
|
document.addEventListener('keypress', (ev) => {
|
||||||
if (ev.key == '/') {
|
if (ev.key == '/') {
|
||||||
let search = document.getElementById('search');
|
const search = document.getElementById('search');
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
search.focus();
|
search.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"name": "",
|
"name": "",
|
||||||
"short_name": "",
|
"short_name": "",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-512x512.png",
|
"src": "/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#ffffff",
|
"theme_color": "#ffffff",
|
||||||
"background_color": "#ffffff",
|
"background_color": "#ffffff",
|
||||||
"display": "standalone"
|
"display": "standalone"
|
||||||
}
|
}
|
||||||
|
@ -1,63 +1,72 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="x-ua-compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>{{ title }} | vdoc</title>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Jost:wght@300;400;500;600;700&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png" />
|
||||||
|
<link rel="manifest" href="site.webmanifest" />
|
||||||
|
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5" />
|
||||||
|
<meta name="msapplication-TileColor" content="#da532c" />
|
||||||
|
<meta name="theme-color" content="#ffffff" />
|
||||||
|
{{ head_assets }}
|
||||||
|
</head>
|
||||||
|
|
||||||
<head>
|
<body>
|
||||||
<meta charset="UTF-8">
|
<div><a id="skip-to-content-link" href="#main-content">Skip to content</a></div>
|
||||||
<meta http-equiv="x-ua-compatible" content="IE=edge" />
|
<div id="page">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<header class="doc-nav hidden">
|
||||||
<title>{{ title }} | vdoc</title>
|
<div class="heading-container">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<div class="heading">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<div class="info">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Jost:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
<div class="module">{{ head_name }}</div>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap" rel="stylesheet">
|
<div class="toggle-version-container">
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
|
<span>{{ version }}</span>
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
|
<div
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
|
id="dark-mode-toggle"
|
||||||
<link rel="manifest" href="site.webmanifest">
|
role="switch"
|
||||||
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5">
|
aria-checked="false"
|
||||||
<meta name="msapplication-TileColor" content="#da532c">
|
aria-label="Toggle dark mode"
|
||||||
<meta name="theme-color" content="#ffffff">
|
>
|
||||||
{{ head_assets }}
|
{{ light_icon }}{{ dark_icon }}
|
||||||
</head>
|
</div>
|
||||||
|
</div>
|
||||||
<body>
|
{{ menu_icon }}
|
||||||
<div><a id="skip-to-content-link" href="#main-content">Skip to content</a></div>
|
</div>
|
||||||
<div id="page">
|
<input type="text" id="search" placeholder="Search... (beta)" autocomplete="off" />
|
||||||
<header class="doc-nav hidden">
|
</div>
|
||||||
<div class="heading-container">
|
</div>
|
||||||
<div class="heading">
|
<nav class="search hidden"></nav>
|
||||||
<div class="info">
|
<nav class="content hidden">
|
||||||
<div class="module">{{ head_name }}</div>
|
<ul>
|
||||||
<div class="toggle-version-container">
|
{{ toc_links }}
|
||||||
<span>{{ version }}</span>
|
</ul>
|
||||||
<div id="dark-mode-toggle" role="switch" aria-checked="false" aria-label="Toggle dark mode">{{ light_icon }}{{ dark_icon }}</div>
|
</nav>
|
||||||
</div>
|
</header>
|
||||||
{{ menu_icon }}
|
<div class="doc-scrollview" id="main-content">
|
||||||
</div>
|
<div class="doc-container">
|
||||||
<input type="text" id="search" placeholder="Search... (beta)" autocomplete="off">
|
<div class="doc-content">
|
||||||
</div>
|
{{ contents }}
|
||||||
</div>
|
<div class="footer">{{ footer_content }}</div>
|
||||||
<nav class="search hidden"></nav>
|
</div>
|
||||||
<nav class="content hidden">
|
{{ right_content }}
|
||||||
<ul>
|
</div>
|
||||||
{{ toc_links }}
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
</nav>
|
{{ footer_assets }}
|
||||||
</header>
|
<script async src="search_index.js"></script>
|
||||||
<div class="doc-scrollview" id="main-content">
|
</body>
|
||||||
<div class="doc-container">
|
|
||||||
<div class="doc-content">
|
|
||||||
{{ contents }}
|
|
||||||
<div class="footer">
|
|
||||||
{{ footer_content }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ right_content }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ footer_assets }}
|
|
||||||
<script async src="search_index.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
30
cmd/tools/vdoc/theme/normalize.css
vendored
30
cmd/tools/vdoc/theme/normalize.css
vendored
@ -91,24 +91,24 @@ select {
|
|||||||
}
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
[type="button"],
|
[type='button'],
|
||||||
[type="reset"],
|
[type='reset'],
|
||||||
[type="submit"] {
|
[type='submit'] {
|
||||||
-webkit-appearance: button;
|
-webkit-appearance: button;
|
||||||
}
|
}
|
||||||
|
|
||||||
button::-moz-focus-inner,
|
button::-moz-focus-inner,
|
||||||
[type="button"]::-moz-focus-inner,
|
[type='button']::-moz-focus-inner,
|
||||||
[type="reset"]::-moz-focus-inner,
|
[type='reset']::-moz-focus-inner,
|
||||||
[type="submit"]::-moz-focus-inner {
|
[type='submit']::-moz-focus-inner {
|
||||||
border-style: none;
|
border-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:-moz-focusring,
|
button:-moz-focusring,
|
||||||
[type="button"]:-moz-focusring,
|
[type='button']:-moz-focusring,
|
||||||
[type="reset"]:-moz-focusring,
|
[type='reset']:-moz-focusring,
|
||||||
[type="submit"]:-moz-focusring {
|
[type='submit']:-moz-focusring {
|
||||||
outline: 1px dotted ButtonText;
|
outline: 1px dotted ButtonText;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,23 +133,23 @@ textarea {
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type="checkbox"],
|
[type='checkbox'],
|
||||||
[type="radio"] {
|
[type='radio'] {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type="number"]::-webkit-inner-spin-button,
|
[type='number']::-webkit-inner-spin-button,
|
||||||
[type="number"]::-webkit-outer-spin-button {
|
[type='number']::-webkit-outer-spin-button {
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type="search"] {
|
[type='search'] {
|
||||||
-webkit-appearance: textfield;
|
-webkit-appearance: textfield;
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type="search"]::-webkit-search-decoration {
|
[type='search']::-webkit-search-decoration {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ const (
|
|||||||
allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm']
|
allowed_formats = ['md', 'markdown', 'json', 'text', 'stdout', 'html', 'htm']
|
||||||
vexe = os.getenv_opt('VEXE') or { @VEXE }
|
vexe = os.getenv_opt('VEXE') or { @VEXE }
|
||||||
vroot = os.dir(vexe)
|
vroot = os.dir(vexe)
|
||||||
tabs = ['\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t']
|
|
||||||
)
|
)
|
||||||
|
|
||||||
enum OutputType {
|
enum OutputType {
|
||||||
@ -233,6 +232,9 @@ fn (vd VDoc) get_readme(path string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fname == '' {
|
if fname == '' {
|
||||||
|
if path.all_after_last(os.path_separator) == 'src' {
|
||||||
|
return vd.get_readme(path.all_before_last(os.path_separator))
|
||||||
|
}
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
readme_path := os.join_path(path, '${fname}.md')
|
readme_path := os.join_path(path, '${fname}.md')
|
||||||
|
@ -312,7 +312,7 @@ fn run_repl(workdir string, vrepl_prefix string) int {
|
|||||||
if line == '' && oline.ends_with('\n') {
|
if line == '' && oline.ends_with('\n') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if line.len <= -1 || line == '' || line == 'exit' {
|
if line.len <= -1 || line == 'exit' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if exit_pos := line.index('exit') {
|
if exit_pos := line.index('exit') {
|
||||||
|
@ -180,6 +180,15 @@ fn get_all_commands() []Command {
|
|||||||
okmsg: 'V can compile 2048 with -skip-unused.'
|
okmsg: 'V can compile 2048 with -skip-unused.'
|
||||||
rmfile: 'examples/2048/2048'
|
rmfile: 'examples/2048/2048'
|
||||||
}
|
}
|
||||||
|
if _ := os.find_abs_path_of_executable('emcc') {
|
||||||
|
res << Command{
|
||||||
|
line: '${vexe} -os wasm32_emscripten examples/2048'
|
||||||
|
okmsg: 'V can compile 2048 with -os wasm32_emscripten, using emcc.'
|
||||||
|
rmfile: 'examples/2048/2048'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println('> emcc not found, skipping `v -os wasm32_emscripten examples/2048`.')
|
||||||
|
}
|
||||||
res << Command{
|
res << Command{
|
||||||
line: '${vexe} -skip-unused -live examples/hot_reload/bounce.v'
|
line: '${vexe} -skip-unused -live examples/hot_reload/bounce.v'
|
||||||
okmsg: 'V can compile the hot code reloading bounce.v example with both: -skip-unused -live'
|
okmsg: 'V can compile the hot code reloading bounce.v example with both: -skip-unused -live'
|
||||||
|
@ -52,7 +52,7 @@ fn check_path(vexe string, dir string, tests []string) int {
|
|||||||
println(found)
|
println(found)
|
||||||
println('============\n')
|
println('============\n')
|
||||||
println('diff:')
|
println('diff:')
|
||||||
println(diff.color_compare_strings(diff_cmd, rand.ulid(), found, expected))
|
println(diff.color_compare_strings(diff_cmd, rand.ulid(), expected, found))
|
||||||
println('============\n')
|
println('============\n')
|
||||||
nb_fail++
|
nb_fail++
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,150 +1,148 @@
|
|||||||
# Serve
|
# JS DOM Cube
|
||||||
|
|
||||||
This project has a no dependence serve in `./server.js` path.
|
## Compiling
|
||||||
That can be run with `node` command after build.
|
|
||||||
|
|
||||||
or just run: `npm run start`
|
|
||||||
|
|
||||||
To install node, you can access node [download page](https://nodejs.org/en/download/)
|
|
||||||
or [package manager](https://nodejs.org/en/download/package-manager)
|
|
||||||
Drawing with mouse events using DOM API. Adopted from MDN examples.
|
|
||||||
|
|
||||||
# Compiling
|
|
||||||
```
|
```
|
||||||
v -b js_browser examples/js_dom_cube/cube.js.v
|
v -b js_browser examples/js_dom_cube/cube.js.v
|
||||||
```
|
```
|
||||||
|
|
||||||
Drawing with mouse events using DOM API. Adopted from MDN examples.
|
Then you can open `index.html` in your favorite browser.
|
||||||
Then you can open `index.html` with your favourite browser.
|
|
||||||
# Serve examples
|
|
||||||
|
|
||||||
### JS server
|
## Serve Examples
|
||||||
After run `npm init -y` code and genared `./package.json`
|
|
||||||
You can put `start` and `build` at script in jason leaf.
|
### JS Server
|
||||||
`path './package.json'`
|
|
||||||
```json
|
> **NOTE**\
|
||||||
"scripts": {
|
> The JS server example in the following steps requires Node.js.
|
||||||
"start": "npm run build && node server.js",
|
> To install Node, please refer to the [download page](https://nodejs.org/en/download/)
|
||||||
"build":"v -b js_browser cube.js.v"
|
> or the installation via your operating systems [package manager](https://nodejs.org/en/download/package-manager).
|
||||||
},
|
|
||||||
|
Initialize the example as a Node project
|
||||||
|
|
||||||
```
|
```
|
||||||
here is the pure javascript server code
|
cd examples/js_dom_cube/
|
||||||
`path './server.js'`
|
npm init -y
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a `start` and `build` script to the generated `./package.json` file.
|
||||||
|
|
||||||
|
```json
|
||||||
|
"scripts": {
|
||||||
|
...
|
||||||
|
"start": "npm run build && node server.js",
|
||||||
|
"build": "v -b js_browser cube.js.v"
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
Below is an example of a Node.js server without external dependencies.
|
||||||
|
You can use it for `./server.js`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const http = require("http");
|
const http = require('http');
|
||||||
const fs = require("fs");
|
const fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
const host = "localhost";
|
const host = 'localhost';
|
||||||
const port = 3000;
|
const port = 3000;
|
||||||
|
|
||||||
const reqListener = function (req, res) {
|
const reqListener = function (req, res) {
|
||||||
console.log('[route] - ', req.url);
|
console.log('[route] - ', req.url);
|
||||||
|
|
||||||
var filePath = '.' + req.url;
|
var filePath = '.' + req.url;
|
||||||
if (filePath == './') {
|
if (filePath == './') {
|
||||||
filePath = './index.html';
|
filePath = './index.html';
|
||||||
}
|
}
|
||||||
|
|
||||||
var extname = String(path.extname(filePath)).toLowerCase();
|
var extname = String(path.extname(filePath)).toLowerCase();
|
||||||
var mimeTypes = {
|
var mimeTypes = {
|
||||||
'.html': 'text/html',
|
'.html': 'text/html',
|
||||||
'.js': 'text/javascript',
|
'.js': 'text/javascript',
|
||||||
'.css': 'text/css',
|
'.css': 'text/css',
|
||||||
'.json': 'application/json',
|
'.json': 'application/json',
|
||||||
'.png': 'image/png',
|
'.png': 'image/png',
|
||||||
'.jpg': 'image/jpg',
|
'.jpg': 'image/jpg',
|
||||||
'.gif': 'image/gif',
|
'.gif': 'image/gif',
|
||||||
'.svg': 'image/svg+xml',
|
'.svg': 'image/svg+xml',
|
||||||
'.wav': 'audio/wav',
|
'.wav': 'audio/wav',
|
||||||
'.mp4': 'video/mp4',
|
'.mp4': 'video/mp4',
|
||||||
'.woff': 'application/font-woff',
|
'.woff': 'application/font-woff',
|
||||||
'.ttf': 'application/font-ttf',
|
'.ttf': 'application/font-ttf',
|
||||||
'.eot': 'application/vnd.ms-fontobject',
|
'.eot': 'application/vnd.ms-fontobject',
|
||||||
'.otf': 'application/font-otf',
|
'.otf': 'application/font-otf',
|
||||||
'.wasm': 'application/wasm'
|
'.wasm': 'application/wasm',
|
||||||
};
|
};
|
||||||
|
|
||||||
var contentType = mimeTypes[extname] || 'application/octet-stream';
|
var contentType = mimeTypes[extname] || 'application/octet-stream';
|
||||||
|
|
||||||
fs.readFile(filePath, function(error, content) {
|
fs.readFile(filePath, function (error, content) {
|
||||||
if (error) {
|
if (error) {
|
||||||
if(error.code == 'ENOENT') {
|
if (error.code == 'ENOENT') {
|
||||||
fs.readFile('./404.html', function(error, content) {
|
fs.readFile('./404.html', function (error, content) {
|
||||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||||
res.end(content, 'utf-8');
|
res.end(content, 'utf-8');
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
res.writeHead(500);
|
||||||
res.writeHead(500);
|
res.end('Sorry, check with the site admin for error: ' + error.code + ' ..\n');
|
||||||
res.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
|
}
|
||||||
}
|
} else {
|
||||||
}
|
res.writeHead(200, { 'Content-Type': contentType });
|
||||||
else {
|
res.end(content, 'utf-8');
|
||||||
res.writeHead(200, { 'Content-Type': contentType });
|
}
|
||||||
res.end(content, 'utf-8');
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const server = http.createServer(reqListener);
|
const server = http.createServer(reqListener);
|
||||||
server.listen(port, host, () => {
|
server.listen(port, host, () => {
|
||||||
console.log(`Server is running on http://${host}:${port}`);
|
console.log(`Server is running on http://${host}:${port}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This project has a no dependence serve in `./server.js` path.
|
Now you can build and run the project with the added scripts.
|
||||||
That can be run with `node` command after build.
|
|
||||||
|
|
||||||
or just run: `npm run start`
|
|
||||||
|
|
||||||
To install node, you can access node [download page](https://nodejs.org/en/download/)
|
|
||||||
or [package manager](https://nodejs.org/en/download/package-manager)
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
npm run start
|
||||||
```
|
```
|
||||||
$ cd examples/js_dom_draw/
|
|
||||||
$ npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### V server
|
### V server
|
||||||
```v ignore
|
|
||||||
|
The example below uses `vweb` to serve the project.
|
||||||
|
|
||||||
|
```v
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import vweb
|
import vweb
|
||||||
import os
|
import os
|
||||||
|
|
||||||
const (
|
const (
|
||||||
http_port = 3001
|
http_port = 3001
|
||||||
)
|
)
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
vweb.Context
|
vweb.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
vweb.run(new_app(), http_port)
|
vweb.run(new_app(), http_port)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut app App) before_request() {
|
pub fn (mut app App) before_request() {
|
||||||
// This build server json files
|
// Build the cube.js javascript file
|
||||||
os.execute_or_panic('v -b js_browser cube.js.v ')
|
os.execute_or_panic('v -b js_browser cube.js.v ')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_app() &App {
|
fn new_app() &App {
|
||||||
mut app := &App{}
|
mut app := &App{}
|
||||||
app.serve_static('/favicon.ico', 'favicon.ico')
|
app.serve_static('/favicon.ico', 'favicon.ico')
|
||||||
app.serve_static('/cube.js', 'cube.js')
|
app.serve_static('/cube.js', 'cube.js')
|
||||||
app.mount_static_folder_at(os.resource_abs_path('.'), '/')
|
app.mount_static_folder_at(os.resource_abs_path('.'), '/')
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
['/'; get]
|
['/'; get]
|
||||||
pub fn (mut app App) controller_get_all_task() vweb.Result {
|
pub fn (mut app App) controller_get_all_task() vweb.Result {
|
||||||
file :=os.read_file('./index.html') or { panic(err) }
|
file := os.read_file('./index.html') or { panic(err) }
|
||||||
return app.html(file)
|
return app.html(file)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -1,140 +1,150 @@
|
|||||||
Drawing with mouse events using DOM API. Adopted from MDN examples.
|
# JS DOM Draw
|
||||||
|
|
||||||
# Compiling
|
Drawing with mouse events using the DOM API. Adopted from MDN examples.
|
||||||
```
|
|
||||||
|
## Compiling
|
||||||
|
|
||||||
|
```sh
|
||||||
v -b js_browser examples/js_dom_draw/draw.js.v
|
v -b js_browser examples/js_dom_draw/draw.js.v
|
||||||
```
|
```
|
||||||
|
|
||||||
Then you can open `index.html` with your favourite browser.
|
Then you can open `index.html` in your favorite browser.
|
||||||
# Serve examples
|
|
||||||
|
|
||||||
### JS server
|
## Serve Examples
|
||||||
After run `npm init -y` code and genared `./package.json`
|
|
||||||
You can put `start` and `build` at script in jason leaf.
|
### JS Server
|
||||||
`path './package.json'`
|
|
||||||
```json
|
> **NOTE**\
|
||||||
"scripts": {
|
> The JS server example in the following steps requires Node.js.
|
||||||
"start": "npm run build && node server.js",
|
> To install Node, please refer to the [download page](https://nodejs.org/en/download/)
|
||||||
"build":"v -b js_browser draw.js.v"
|
> or the installation via your operating systems [package manager](https://nodejs.org/en/download/package-manager).
|
||||||
},
|
|
||||||
|
Initialize the example as a Node project
|
||||||
|
|
||||||
```
|
```
|
||||||
here is the pure javascript server code
|
cd examples/js_dom_draw/
|
||||||
`path './server.js'`
|
npm init -y
|
||||||
|
```
|
||||||
|
|
||||||
|
Add a `start` and `build` script to the generated `./package.json` file.
|
||||||
|
|
||||||
|
```json
|
||||||
|
"scripts": {
|
||||||
|
...
|
||||||
|
"start": "npm run build && node server.js",
|
||||||
|
"build": "v -b js_browser draw.js.v"
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
Below is an example of a Node.js server without external dependencies.
|
||||||
|
You can use it for `./server.js`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const http = require("http");
|
const http = require('http');
|
||||||
const fs = require("fs");
|
const fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
const host = "localhost";
|
const host = 'localhost';
|
||||||
const port = 3000;
|
const port = 3000;
|
||||||
|
|
||||||
const reqListener = function (req, res) {
|
const reqListener = function (req, res) {
|
||||||
console.log('[route] - ', req.url);
|
console.log('[route] - ', req.url);
|
||||||
|
|
||||||
var filePath = '.' + req.url;
|
var filePath = '.' + req.url;
|
||||||
if (filePath == './') {
|
if (filePath == './') {
|
||||||
filePath = './index.html';
|
filePath = './index.html';
|
||||||
}
|
}
|
||||||
|
|
||||||
var extname = String(path.extname(filePath)).toLowerCase();
|
var extname = String(path.extname(filePath)).toLowerCase();
|
||||||
var mimeTypes = {
|
var mimeTypes = {
|
||||||
'.html': 'text/html',
|
'.html': 'text/html',
|
||||||
'.js': 'text/javascript',
|
'.js': 'text/javascript',
|
||||||
'.css': 'text/css',
|
'.css': 'text/css',
|
||||||
'.json': 'application/json',
|
'.json': 'application/json',
|
||||||
'.png': 'image/png',
|
'.png': 'image/png',
|
||||||
'.jpg': 'image/jpg',
|
'.jpg': 'image/jpg',
|
||||||
'.gif': 'image/gif',
|
'.gif': 'image/gif',
|
||||||
'.svg': 'image/svg+xml',
|
'.svg': 'image/svg+xml',
|
||||||
'.wav': 'audio/wav',
|
'.wav': 'audio/wav',
|
||||||
'.mp4': 'video/mp4',
|
'.mp4': 'video/mp4',
|
||||||
'.woff': 'application/font-woff',
|
'.woff': 'application/font-woff',
|
||||||
'.ttf': 'application/font-ttf',
|
'.ttf': 'application/font-ttf',
|
||||||
'.eot': 'application/vnd.ms-fontobject',
|
'.eot': 'application/vnd.ms-fontobject',
|
||||||
'.otf': 'application/font-otf',
|
'.otf': 'application/font-otf',
|
||||||
'.wasm': 'application/wasm'
|
'.wasm': 'application/wasm',
|
||||||
};
|
};
|
||||||
|
|
||||||
var contentType = mimeTypes[extname] || 'application/octet-stream';
|
var contentType = mimeTypes[extname] || 'application/octet-stream';
|
||||||
|
|
||||||
fs.readFile(filePath, function(error, content) {
|
fs.readFile(filePath, function (error, content) {
|
||||||
if (error) {
|
if (error) {
|
||||||
if(error.code == 'ENOENT') {
|
if (error.code == 'ENOENT') {
|
||||||
fs.readFile('./404.html', function(error, content) {
|
fs.readFile('./404.html', function (error, content) {
|
||||||
res.writeHead(404, { 'Content-Type': 'text/html' });
|
res.writeHead(404, { 'Content-Type': 'text/html' });
|
||||||
res.end(content, 'utf-8');
|
res.end(content, 'utf-8');
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
res.writeHead(500);
|
||||||
res.writeHead(500);
|
res.end('Sorry, check with the site admin for error: ' + error.code + ' ..\n');
|
||||||
res.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
|
}
|
||||||
}
|
} else {
|
||||||
}
|
res.writeHead(200, { 'Content-Type': contentType });
|
||||||
else {
|
res.end(content, 'utf-8');
|
||||||
res.writeHead(200, { 'Content-Type': contentType });
|
}
|
||||||
res.end(content, 'utf-8');
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const server = http.createServer(reqListener);
|
const server = http.createServer(reqListener);
|
||||||
server.listen(port, host, () => {
|
server.listen(port, host, () => {
|
||||||
console.log(`Server is running on http://${host}:${port}`);
|
console.log(`Server is running on http://${host}:${port}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This project has a no dependence serve in `./server.js` path.
|
Now you can build and run the project with the added scripts.
|
||||||
That can be run with `node` command after build.
|
|
||||||
|
|
||||||
or just run: `npm run start`
|
|
||||||
|
|
||||||
To install node, you can access node [download page](https://nodejs.org/en/download/)
|
|
||||||
or [package manager](https://nodejs.org/en/download/package-manager)
|
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
npm run start
|
||||||
```
|
```
|
||||||
$ cd examples/js_dom_draw/
|
|
||||||
$ npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### V server
|
### V server
|
||||||
```v ignore
|
|
||||||
|
The example below uses `vweb` to serve the project.
|
||||||
|
|
||||||
|
```v
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import vweb
|
import vweb
|
||||||
import os
|
import os
|
||||||
|
|
||||||
const (
|
const (
|
||||||
http_port = 3001
|
http_port = 3001
|
||||||
)
|
)
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
vweb.Context
|
vweb.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
vweb.run(new_app(), http_port)
|
vweb.run(new_app(), http_port)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut app App) before_request() {
|
pub fn (mut app App) before_request() {
|
||||||
// This build server json files
|
// Build the draw.js javascript file
|
||||||
os.execute_or_panic('v -b js_browser draw.js.v ')
|
os.execute_or_panic('v -b js_browser draw.js.v ')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_app() &App {
|
fn new_app() &App {
|
||||||
mut app := &App{}
|
mut app := &App{}
|
||||||
app.serve_static('/favicon.ico', 'favicon.ico')
|
app.serve_static('/favicon.ico', 'favicon.ico')
|
||||||
app.serve_static('/draw.js', 'draw.js')
|
app.serve_static('/draw.js', 'draw.js')
|
||||||
app.mount_static_folder_at(os.resource_abs_path('.'), '/')
|
app.mount_static_folder_at(os.resource_abs_path('.'), '/')
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
['/'; get]
|
['/'; get]
|
||||||
pub fn (mut app App) controller_get_all_task() vweb.Result {
|
pub fn (mut app App) controller_get_all_task() vweb.Result {
|
||||||
file :=os.read_file('./index.html') or { panic(err) }
|
file := os.read_file('./index.html') or { panic(err) }
|
||||||
return app.html(file)
|
return app.html(file)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -1,35 +1,57 @@
|
|||||||
|
# JS DOM Benchmark Chart
|
||||||
|
|
||||||
![image](https://user-images.githubusercontent.com/63821277/186010833-2ea36f3a-4738-4025-9b23-ac62afe74b81.png)
|
![image](https://user-images.githubusercontent.com/63821277/186010833-2ea36f3a-4738-4025-9b23-ac62afe74b81.png)
|
||||||
|
|
||||||
# To run app
|
## Running the App
|
||||||
## From root
|
|
||||||
- run typescript project
|
|
||||||
`npm i --prefix examples/js_dom_draw_bechmark_chart/typescript_vanilla_typeorm`
|
|
||||||
`npm run start:dev --prefix examples/js_dom_draw_bechmark_chart/typescript_vanilla_typeorm`
|
|
||||||
|
|
||||||
- run v project
|
> **NOTE**\
|
||||||
`v run examples/js_dom_draw_bechmark_chart/v_vweb_orm `
|
> The following steps require Node.js.
|
||||||
|
> To install Node, please refer to the [download page](https://nodejs.org/en/download/)
|
||||||
|
> or the installation via your operating systems [package manager](https://nodejs.org/en/download/package-manager).
|
||||||
|
|
||||||
- running v chart
|
The steps below assume that your current directory path is the examples project directory.
|
||||||
`cd examples/js_dom_draw_bechmark_chart/chart && v run .`
|
|
||||||
|
|
||||||
Dockerfile
|
```
|
||||||
[docker build]=> Docker image
|
cd examples/js_dom_draw_bechmark_chart
|
||||||
[docker run]=> Docker container
|
```
|
||||||
|
|
||||||
`sudo docker build -t <name> .`
|
Execute the following commands in separate terminal instances.
|
||||||
|
|
||||||
`sudo docker run --name <container name> --interactive --tty --publish 3001:3001 <name>`
|
Run the Benchmarks Typescript Part
|
||||||
|
|
||||||
`v run .`
|
```sh
|
||||||
|
npm i --prefix typescript_vanilla_typeorm
|
||||||
|
npm run start:dev --prefix typescript_vanilla_typeorm
|
||||||
|
```
|
||||||
|
|
||||||
A message like `[Vweb] Running app on http://localhost:3001/` should appear
|
Run the Benchmarks V Part
|
||||||
|
|
||||||
`exit`
|
```sh
|
||||||
|
v run v_vweb_orm
|
||||||
|
```
|
||||||
|
|
||||||
# To implement new benchmarks in v
|
Run the Chart
|
||||||
|
|
||||||
In `examples/js_dom_draw_bechmark_chart/v_vweb_orm/src/main.v` path
|
```
|
||||||
Create a route returning a `Response` struct like:
|
cd chart/ && v run .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dockerfile
|
||||||
|
|
||||||
|
> [docker build] => Docker image\
|
||||||
|
> [docker run] => Docker container
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo docker build -t <name> .
|
||||||
|
sudo docker run --name <container name> --interactive --tty --publish 3001:3001 <name>
|
||||||
|
v run .
|
||||||
|
# A message like `[Vweb] Running app on http://localhost:3001/` should appear
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementing New Benchmarks in V
|
||||||
|
|
||||||
|
In `v_vweb_orm/src/main.v`, create a route that returns a `Response` struct.
|
||||||
|
|
||||||
```v ignore
|
```v ignore
|
||||||
['/sqlite-memory/:count']
|
['/sqlite-memory/:count']
|
||||||
@ -65,18 +87,17 @@ pub fn (mut app App) sqlite_memory(count int) vweb.Result {
|
|||||||
}!
|
}!
|
||||||
|
|
||||||
response := Response{
|
response := Response{
|
||||||
insert: insert_stopwatchs
|
insert: insert_stopwatchs
|
||||||
@select:select_stopwatchs
|
@select: select_stopwatchs
|
||||||
update: update_stopwatchs
|
update: update_stopwatchs
|
||||||
}
|
}
|
||||||
return app.json(response)
|
return app.json(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
In `examples/chart/services.v` path
|
In `chart/main.v`, create a service to request the benchmark data and decode the response as
|
||||||
Create a service to request the benchmarks data by http
|
`FrameworkBenchmarkResponse`.
|
||||||
Decode the info to `FrameworkBenchmarkResponse`
|
|
||||||
```v ignore
|
```v ignore
|
||||||
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
||||||
url := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'
|
url := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'
|
||||||
@ -86,26 +107,13 @@ fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In `examples/chart/main.v` path
|
Then update `insert_framework_benchmark_times()`, `select_framework_benchmark_times()` and
|
||||||
Create a service to request the benchmarks data by http
|
`update_framework_benchmark_times()` to include the `numbers := FrameworkPlatform{` for the newly
|
||||||
Decode the info to `FrameworkBenchmarkResponse`
|
added function.
|
||||||
```v ignore
|
|
||||||
fn typescript_sqlite_memory() ?FrameworkBenchmarkResponse {
|
|
||||||
url := 'http://localhost:3000/sqlite-memory/${benchmark_loop_length}'
|
|
||||||
res := http.get(url) or { panic(err) }
|
|
||||||
framework_benchmark_response := json.decode(FrameworkBenchmarkResponse, res.body)!
|
|
||||||
return framework_benchmark_response
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Then, update:
|
|
||||||
`insert_framework_benchmark_times()`;
|
|
||||||
`select_framework_benchmark_times()`;
|
|
||||||
`update_framework_benchmark_times()`.
|
|
||||||
with the new function
|
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
|
||||||
# ROADMAP
|
|
||||||
02/09/2022
|
02/09/2022
|
||||||
|
|
||||||
- [ ] select bench (easy)
|
- [ ] select bench (easy)
|
||||||
- [ ] vsql (easy)
|
- [ ] vsql (easy)
|
||||||
|
21
examples/ssl_server/cert/ca.crt
Normal file
21
examples/ssl_server/cert/ca.crt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDbTCCAlWgAwIBAgIUTbcFMmB84wg6eqDRJbmo49aOTdMwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||||
|
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMzA3MzAxNzM0MThaGA8yMDUw
|
||||||
|
MTIxNDE3MzQxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
|
||||||
|
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
|
||||||
|
AQEBBQADggEPADCCAQoCggEBANPfvg3G/3+j2NX5qDf0gw9iSnCiUa1T1inxlnfP
|
||||||
|
vMVINDkH22yUSeValyuIrpF94m23ANo0yOXQJxbIt8PbwaRYTq1EzxlGkkXUHob3
|
||||||
|
m1qJLH1qLacJeLMPj3J7kUXVWL65Qb7d2gtwMvegJ5I5U4ntLjXAmIV4z4PpZ2tP
|
||||||
|
MsERacj/alb0EDS77P4JcbRzYvP/3FyFokel5TF/nLV3hXc5Eu6LjCzbEEus1MLd
|
||||||
|
rgcpODUlw8Gf0M0nAjxijVpXAVo6XYRQ/00+zjPaKxjtQ/ds/O7zRTNxnUVvh1oH
|
||||||
|
Pnif9rkVBLkVjmSU/C7jvAKqrWPU9b24hXpnfSIirkn3tO8CAwEAAaNTMFEwHQYD
|
||||||
|
VR0OBBYEFPx8Ivgj5Gi4XyHFZ/zGgZU4kGc7MB8GA1UdIwQYMBaAFPx8Ivgj5Gi4
|
||||||
|
XyHFZ/zGgZU4kGc7MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
|
||||||
|
AJYSckwJSZlj8baEMvAJLs55Bm5wR1QZaj7mz8tBxK8zd9PdW3fTebil6jtGLpXT
|
||||||
|
CHi+vaa5HsM2QXnYaZCSlawD3WWZ+LZ9lJVuWC+iWfRq6TC/gEd+3zCE70CeeAAu
|
||||||
|
0pZC2Luvvgm5a6qfKoA4lEvlB2Yr0pX2GhXYOGvIeSMWpohKyKmiJEi83kJvzjnl
|
||||||
|
BsFIR6FB1wO2+nrfLCzmjwPQx0ie2h+fPwf5Y2C0pPBYVwXpP94EEZW+lQgPXx5I
|
||||||
|
6X8HPVNMtu4lToe746ctQlA4YDwge5mmiGUgF95Y3/O9Z2vjPqeN826oR89YFFZF
|
||||||
|
JFtrrBskGW5fOzKOXLc96pE=
|
||||||
|
-----END CERTIFICATE-----
|
24
examples/ssl_server/cert/client.crt
Normal file
24
examples/ssl_server/cert/client.crt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEEzCCAvsCFG64Q2g46jZb3kRbDOJWX/BwjSp5MA0GCSqGSIb3DQEBCwUAMEUx
|
||||||
|
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
|
||||||
|
cm5ldCBXaWRnaXRzIFB0eSBMdGQwIBcNMjMwNzMwMTczNDQzWhgPMjA1MDEyMTQx
|
||||||
|
NzM0NDNaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD
|
||||||
|
VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEBAQUA
|
||||||
|
A4ICDwAwggIKAoICAQDqDmHNMesBQ6S/ZU+xW4sO18Q+WfvXEaMdEfN5D8wyazP3
|
||||||
|
mA7VTsNjliHrLFDiaTX9dR9Js+SwqmLpZTZoxBzn6wDuuM9fswvISnVERgZZdFas
|
||||||
|
lkgci4iXVE2TREEqh6Ak4CAUyGiBhHm1CaT7txvq7wTghs+cgDR5hItK7EpxD7gv
|
||||||
|
jc1sNco9Ha1GecUB0L4fCmp3ss88vvDU4ta4eLTsW/SZbTKRMawih4hp00d0v83s
|
||||||
|
Of5iIP6kWsM9X5Oe2Fm5XaObMlCdWHIBP2aB5i2ZqYUKTl8uKExpeobcsmpvHiSb
|
||||||
|
tAAaeFo/5shyCAXx/i55KYA2oRm71XeIBnllIBMEfKPV3AReO6p+MZFnioPxUWY0
|
||||||
|
gWqlSzsoLJ6NxHYWeC15OQhKQ6jEO7u3SAivacG5VVEywQ7EiY3b+ncwcZt9QK8q
|
||||||
|
UckwwnbWHZJwJcp0vHj3/Mmvawm1dWR3CVauFW3ze/l3Ik92wJBDkULhv6r07zfv
|
||||||
|
SlL2Am7+wPWfeOomx+Kh/rnGcXATcH17dVFH/mjhTjclOuM38e7oGoQhm9lZ9kaD
|
||||||
|
wIuu1X0+XutuY55uze9yVY9qRSIJraBuZ9mreVIVj9FG0kpVplrTr7oBlGA1Nc3i
|
||||||
|
1IuilE36T4qmP50WzJ6Yy38+J7My23bUyyOXIFhX/LTpPVjhZq5tVH+WmmqW0wID
|
||||||
|
AQABMA0GCSqGSIb3DQEBCwUAA4IBAQAbD+EVc4Ev7uXKUQV0s3nETp2odz1G8eZ/
|
||||||
|
drAVnWJpZEeWW98ZeVfyYglqWc9G8McYpiKeac9WF+gga8F2Cn3RjMvufqr0Ggcy
|
||||||
|
byytgJeLolukhTV/JJk8o+CUAB2xgk8+DVEiZ+7G4L/4V613VmL1B+jRHWknO/Js
|
||||||
|
uArppuSduvmkakWOGMBGLUPUcep/vIepHByjOeq1czsdrsLokjBXjMAwXAVRSkBs
|
||||||
|
mazD9yK95R5oG0KDmIPpfDddwvp7Xq4t3pTtMwXPYaDG+sPovsGsGYRkTnouOlKh
|
||||||
|
ae4/jRb8ut9AqOxZRUsBzT8MJXg4cFec8qrhPe3abzxN4amqOxlj
|
||||||
|
-----END CERTIFICATE-----
|
51
examples/ssl_server/cert/client.key
Normal file
51
examples/ssl_server/cert/client.key
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIJKAIBAAKCAgEA6g5hzTHrAUOkv2VPsVuLDtfEPln71xGjHRHzeQ/MMmsz95gO
|
||||||
|
1U7DY5Yh6yxQ4mk1/XUfSbPksKpi6WU2aMQc5+sA7rjPX7MLyEp1REYGWXRWrJZI
|
||||||
|
HIuIl1RNk0RBKoegJOAgFMhogYR5tQmk+7cb6u8E4IbPnIA0eYSLSuxKcQ+4L43N
|
||||||
|
bDXKPR2tRnnFAdC+Hwpqd7LPPL7w1OLWuHi07Fv0mW0ykTGsIoeIadNHdL/N7Dn+
|
||||||
|
YiD+pFrDPV+TnthZuV2jmzJQnVhyAT9mgeYtmamFCk5fLihMaXqG3LJqbx4km7QA
|
||||||
|
GnhaP+bIcggF8f4ueSmANqEZu9V3iAZ5ZSATBHyj1dwEXjuqfjGRZ4qD8VFmNIFq
|
||||||
|
pUs7KCyejcR2FngteTkISkOoxDu7t0gIr2nBuVVRMsEOxImN2/p3MHGbfUCvKlHJ
|
||||||
|
MMJ21h2ScCXKdLx49/zJr2sJtXVkdwlWrhVt83v5dyJPdsCQQ5FC4b+q9O8370pS
|
||||||
|
9gJu/sD1n3jqJsfiof65xnFwE3B9e3VRR/5o4U43JTrjN/Hu6BqEIZvZWfZGg8CL
|
||||||
|
rtV9Pl7rbmOebs3vclWPakUiCa2gbmfZq3lSFY/RRtJKVaZa06+6AZRgNTXN4tSL
|
||||||
|
opRN+k+Kpj+dFsyemMt/PiezMtt21MsjlyBYV/y06T1Y4WaubVR/lppqltMCAwEA
|
||||||
|
AQKCAgBCiqQzeiWdzmVgJKVrfuMh7SXVtC9tDY6aDShzGpKrIt87XPeanTHfdide
|
||||||
|
fNLiC5dV355tjb9OmqJUSHoXfunY5W72b4RFaNnIr6J3LpFPjUu29WK6+tBydX04
|
||||||
|
iQcd2EEnOrDkN7W+XLNdTMii54QAXsO8MZeEns5MXepb+qGPUzDCFEZ6pTBB/9Xr
|
||||||
|
W2MvCPGEUanDLgrM8lv1qifxeh+1ss7vb6QYs06E4pNdwrtl7cHVjwdLTqYWg9dN
|
||||||
|
84Y8erXHhV+mF7/je+mtgSDbfV0pepBgRbe5n6tZsYP16qNnw+IUgjAlVmISGMKT
|
||||||
|
6MQH8IO13p6c6WAvjpjVC0IoBd5htPzP8Il4bACKLr4IbLyAcdQvkWGUD2AfXmsM
|
||||||
|
QB8zQA+HzFPLuoN6Yijp0ZUA3e+WN+fns9tHrrdrlBUUp39OwpOtx6S+DpN+AAmW
|
||||||
|
8HPgESRJJ6b+mIrw60PLhGmpn/4tNk6c57EoqVM056uQcMCjhZRC3dKZl2LYhg9n
|
||||||
|
Ndtld2kb11iMuspbKKqBcizBye8nUxlvpa/HJfi5SoLxgaR5AfNgCekAE1TKHrDs
|
||||||
|
a51qhe0M4QRBnnlQl5Rxy4qUOZ+dwo+8nlZeDnCBKhWoBr3zNUie0YGO2g39zUzh
|
||||||
|
l2DbL6tTVznhM69mgHi8T2uBUhxB2UYyfPqk0yLXlc8DNQs+QQKCAQEA90LY21jg
|
||||||
|
nixJMXn/EMXvAEFoQul42iQuqyQLb9wLGmvA4Dqh+f+AWUlN8o7nLBGNv9ioDib6
|
||||||
|
wDMv2gAFr0K5+5TvO0LvsBEuUgdX8wcmF30pJboETmj/fvTDp1BXTh2TfXD4toS7
|
||||||
|
ANWLERH68GGYFd9pMaxUALnqpJkcnAxRQjpof3ZgzWng4X7tGDwM6fZcf2Ahq/0J
|
||||||
|
5qzP0VJgkkX6YvOF9+gIsyIWn2hiNlKtDITA+BqDg2Dx3XBrJQ9PDIfzspywFOw+
|
||||||
|
a1QdF5RHyzvLO5BMrg48GwGUQQurfA8HcPtLqoOKcHiuULn6pNF4lkqK+6Wuyg9L
|
||||||
|
hPGPvP6T6wnvrwKCAQEA8lQPZTnSZaQnYV3EcHD+tmzGc7B5Qvn5MjG02XIZAZtc
|
||||||
|
SstZK3HMi60NoK0UmAjtYIQWruhKCK31gRMhkrKXDoympwhRu965APglzNRyhNPg
|
||||||
|
Q1Qr8Ux+QjccBbtmzc1H3EvGVLxUSBXB6gk4MzAF0W9FU2HU+0VnFjT6YbjbFuEB
|
||||||
|
+2knKUIFc1O2v9B6MOc8HvXA2YqpSx9e60QOIxrBpPX5GDS2yEQbf9PLe4hY9RWT
|
||||||
|
0tV7xMqrM5gyTmG4zwD9c3+QgDY9aoffcsqTCLPwzY+jpB8V2p6eno/sFhHtRqn3
|
||||||
|
BxSlyiBTvWuqqa0C+4XjIbRiTp01Z2czpiRx+giQHQKCAQAmaz2Uv3ePPCRXSrRm
|
||||||
|
H8smCAOyOeKsSmjx8JTSWadkAJAkhxe554hC11AEO04SG9whjgF2yXm2uX1a6xv3
|
||||||
|
AnAxdg/B7oGdot3Goxt4SIkTpz/oe8HFiS0BxfhMnAAkxBWxrQcIHRGNbKDCE0Ah
|
||||||
|
b5iY9XC75iHbRwf9cUjvuj46AydPfs5FvIjToMwoMtRy2fO/WumAdr2+GOXliV41
|
||||||
|
/CeOjnYncedAJjDLrgVsmWYIBuyQ4FXE6SBLnvcW+Az5TnqAKzZ02cxNEvG+Qyzw
|
||||||
|
mCbY52/yr4WJULJ/dNe9W/x1AqbcJLozBZ1YL72RNHb/Ky/zL+g7vyqlyn7iB9Bl
|
||||||
|
+dJDAoIBAQCB2vfRB7YuT1PnAidVFcf4m7uQnR2t/WRDOI2wBEtQKB/B2Mw00quI
|
||||||
|
obhuxLEHc6k4ki/RlJqvogCwJT9VbCw0WLypP3UFFqnO0ir3Y1Tmxt8jVUSi7pmu
|
||||||
|
A/gZPj4txHZgn55tI+qKIlaigkRCcdZ8T4M31nIaICvIo6UUnsmQrgyw271nh4CC
|
||||||
|
N3bzvNTtxcvaz1iDeqGTpwDnU7W7rAfezQypov3bvVt7GVSuIveAhgqL7WiAoRYy
|
||||||
|
9Ljodcdh7ibjMJWPjwFESAE+cz1taXd9wB4xwZKlb2CSmY8qmHqs5kGA4tigwsf8
|
||||||
|
9mgiupqhjDKViiMv+2B1w8DSpC8LjHElAoIBAHd9s9Dp7yjHQyMuJmpSxI2kowi0
|
||||||
|
XF23xWgu9i0p2THGwHZW44KwNOjkKcj2jQqQY0xXj3Q6M4xTvNqVW+JxTnXhzyJJ
|
||||||
|
C+xJfX+uWndyd3EKq7Bpzr0xAOW1g3n+Vfagul82kR2xf5QneObAXIpMqXWHvyYv
|
||||||
|
RPQxZWilluRPKGek3N5W8/IHvARnqs/4vetWyL1BXjr6LmdCjhVCR+NMatdSfAJJ
|
||||||
|
tEz+mVWfFzGaKJu16veh8i6iDG9LQ+/i6iNoHUovggb5Mt2QagIo6yaMqDNTQm7V
|
||||||
|
ZTHGSFjWif70uphM+JXSU5WcFEBsufVTFJKEnBf6c9hl8g5zqmxKwuGox1g=
|
||||||
|
-----END RSA PRIVATE KEY-----
|
26
examples/ssl_server/cert/server.crt
Normal file
26
examples/ssl_server/cert/server.crt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
No extensions in certificate
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEOTCCAyECFG64Q2g46jZb3kRbDOJWX/BwjSp4MA0GCSqGSIb3DQEBCwUAMEUx
|
||||||
|
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
|
||||||
|
cm5ldCBXaWRnaXRzIFB0eSBMdGQwIBcNMjMwNzMwMTczNDE4WhgPMjA1MDEyMTQx
|
||||||
|
NzM0MThaMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYD
|
||||||
|
VQQHDAtMb3MgQW5nZWxlczEdMBsGA1UECgwUQ2F0YWx5c3QgRGV2ZWxvcG1lbnQx
|
||||||
|
EjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
|
||||||
|
ggIBAKUcJ5cizbhreUlC0plQngCeE+/ysZJo8TmnhEF4cFnTVCHmvzz7f5w7/Zma
|
||||||
|
4maRzE3KT52qSA2PkX6Wr9RgnM93K93a3dfiUHaZ+DbWFnb1w/gp7TG5bgvwfjcb
|
||||||
|
KVnkP+BIMbT90kQrLI0H89LrouvCHDvl74EvAdyYgupLTdjZ5Q5Xe9P5rUhLajw6
|
||||||
|
iN8+NtfrQh2hDOWnbg9nQK/zjIVvvvjMQOUzda9Rq4ViAphiLNufojQhHJrlIpkP
|
||||||
|
oR+YENiDXRcaire5RVWjzfoQGDbTJLJL8fNV1HMjJArUuCg8yIyL1wooe+XWqscg
|
||||||
|
MzJoiCjSdai5zTF+lzcBLrm0olqB7YDCHS3x3K4C3DDRSoyFSEHRQpbSQbc6jTo6
|
||||||
|
TuWcC9o/5fIMzzHrahqoRZG7syFyHYNtezhsFobqMX4E15gV6tBf6CMpTlXMH3ss
|
||||||
|
DreZl900n1UcNtp7aQw2JIdRrLMW2I6UAit1o/FBYjkg/QCqPL7lw1nv0COraI74
|
||||||
|
CU+I7opYJJgEalOkZciapB6ARMgWD1/J9qO4q98H0jETP1bh78lwLPxRe1W5fukD
|
||||||
|
YCazJONIt4Bgdff8C2r+KhEoWQxK5VnjIdbL9E1nxscPr/4U77siCmHKdPINCrsD
|
||||||
|
CWqxUHiuyJmkw9NCrerZoIxTBFAUc+sdibvq1M528jf1IvXXAgMBAAEwDQYJKoZI
|
||||||
|
hvcNAQELBQADggEBAGoxRyyY+YraVOlFMzmyf+TeCQVibOJvKmY/HUjqCujgoj6o
|
||||||
|
7UwYDAPyfzuVerDj2IzJ9bFB818iOIQUaO8Gw70EOzDifZFCm9/pET3SD7aGd4Kk
|
||||||
|
DjCbjml/MNidVezPXNcdAM+XJ56jd2owk/pB4jaw3bkNcmn0aSnFg421fZibrTcS
|
||||||
|
VRPCHIvV8gSqJk9ENO5EGIGU1VmTR909aIYB2fYyyW/1fyP/gn7d1Afy8CimZ1uD
|
||||||
|
mUl5qQ5/CY378MmnODiGhsHJeH+ws77yLPwnh8eVtISwYMu9qfNRYFnotK7a5mxU
|
||||||
|
CWpoSR77NmCUCQOarzb34soL2zZlIK9Lx+4VQPo=
|
||||||
|
-----END CERTIFICATE-----
|
51
examples/ssl_server/cert/server.key
Normal file
51
examples/ssl_server/cert/server.key
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
-----END RSA PRIVATE KEY-----
|
17
examples/ssl_server/client.v
Normal file
17
examples/ssl_server/client.v
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import io
|
||||||
|
import os
|
||||||
|
import net.mbedtls
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut client := mbedtls.new_ssl_conn(mbedtls.SSLConnectConfig{
|
||||||
|
verify: os.resource_abs_path('cert/ca.crt')
|
||||||
|
cert: os.resource_abs_path('cert/client.crt')
|
||||||
|
cert_key: os.resource_abs_path('cert/client.key')
|
||||||
|
validate: true
|
||||||
|
})!
|
||||||
|
|
||||||
|
client.dial('localhost', 8443)!
|
||||||
|
client.write_string('GET / HTTP/1.1\r\n\r\n')!
|
||||||
|
mut reader := io.new_buffered_reader(reader: client)
|
||||||
|
println(reader.read_line()!)
|
||||||
|
}
|
20
examples/ssl_server/server.v
Normal file
20
examples/ssl_server/server.v
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import io
|
||||||
|
import os
|
||||||
|
import net.mbedtls
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut server := mbedtls.new_ssl_listener('0.0.0.0:8443', mbedtls.SSLConnectConfig{
|
||||||
|
verify: os.resource_abs_path('cert/ca.crt')
|
||||||
|
cert: os.resource_abs_path('cert/server.crt')
|
||||||
|
cert_key: os.resource_abs_path('cert/server.key')
|
||||||
|
validate: true // mTLS
|
||||||
|
})!
|
||||||
|
|
||||||
|
mut client := server.accept()!
|
||||||
|
mut reader := io.new_buffered_reader(reader: client)
|
||||||
|
mut request := reader.read_line()!
|
||||||
|
println(request)
|
||||||
|
client.write_string('HTTP/1.1 200 OK\r\n')!
|
||||||
|
client.shutdown()!
|
||||||
|
server.shutdown()!
|
||||||
|
}
|
@ -49,7 +49,7 @@ V projects can be created anywhere and don't need to have a certain structure:
|
|||||||
```bash
|
```bash
|
||||||
mkdir blog
|
mkdir blog
|
||||||
cd blog
|
cd blog
|
||||||
v init
|
touch blog.v
|
||||||
```
|
```
|
||||||
|
|
||||||
First, let's create a simple hello world website:
|
First, let's create a simple hello world website:
|
||||||
@ -203,11 +203,11 @@ since a DB connection doesn't have to be set up for each request.
|
|||||||
// blog.v
|
// blog.v
|
||||||
fn main() {
|
fn main() {
|
||||||
mut app := App{
|
mut app := App{
|
||||||
db: sqlite.connect(':memory:') or { panic(err) }
|
db: sqlite.connect(':memory:')!
|
||||||
}
|
}
|
||||||
sql app.db {
|
sql app.db {
|
||||||
create table Article
|
create table Article
|
||||||
}
|
}!
|
||||||
|
|
||||||
first_article := Article{
|
first_article := Article{
|
||||||
title: 'Hello, world!'
|
title: 'Hello, world!'
|
||||||
@ -222,7 +222,7 @@ fn main() {
|
|||||||
sql app.db {
|
sql app.db {
|
||||||
insert first_article into Article
|
insert first_article into Article
|
||||||
insert second_article into Article
|
insert second_article into Article
|
||||||
}
|
}!
|
||||||
vweb.run(app, 8080)
|
vweb.run(app, 8080)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -242,7 +242,7 @@ struct Article {
|
|||||||
pub fn (app &App) find_all_articles() []Article {
|
pub fn (app &App) find_all_articles() []Article {
|
||||||
return sql app.db {
|
return sql app.db {
|
||||||
select from Article
|
select from Article
|
||||||
}
|
} or { panic(err) }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -289,7 +289,7 @@ For example, if we only wanted to find articles with ids between 100 and 200, we
|
|||||||
|
|
||||||
return sql app.db {
|
return sql app.db {
|
||||||
select from Article where id >= 100 && id <= 200
|
select from Article where id >= 100 && id <= 200
|
||||||
}
|
} or { panic(err) }
|
||||||
```
|
```
|
||||||
|
|
||||||
Retrieving a single article is very simple:
|
Retrieving a single article is very simple:
|
||||||
@ -299,7 +299,7 @@ Retrieving a single article is very simple:
|
|||||||
pub fn (app &App) retrieve_article() ?Article {
|
pub fn (app &App) retrieve_article() ?Article {
|
||||||
return sql app.db {
|
return sql app.db {
|
||||||
select from Article limit 1
|
select from Article limit 1
|
||||||
}
|
} or { panic(err) }[0]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -308,9 +308,8 @@ bad queries will always be handled by the developer:
|
|||||||
|
|
||||||
```v ignore
|
```v ignore
|
||||||
// article.v
|
// article.v
|
||||||
article := app.retrieve_article(10) or {
|
article := app.retrieve_article() or {
|
||||||
app.text('Article not found')
|
return app.text('Article not found')
|
||||||
return
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -349,7 +348,7 @@ pub fn (mut app App) new_article(title string, text string) vweb.Result {
|
|||||||
println(article)
|
println(article)
|
||||||
sql app.db {
|
sql app.db {
|
||||||
insert article into Article
|
insert article into Article
|
||||||
}
|
} or { panic(err) }
|
||||||
return app.redirect('/')
|
return app.redirect('/')
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -402,7 +401,7 @@ If one wants to persist data they need to use a file instead of memory SQLite Da
|
|||||||
Replace the db setup code with this instead:
|
Replace the db setup code with this instead:
|
||||||
|
|
||||||
```
|
```
|
||||||
db: sqlite.connect('blog.db') or { panic(err) }
|
db: sqlite.connect('blog.db')!
|
||||||
```
|
```
|
||||||
|
|
||||||
As we can see it attempts to open a file in the current directory named `blog.db`.
|
As we can see it attempts to open a file in the current directory named `blog.db`.
|
||||||
|
@ -865,7 +865,7 @@ pub fn (s string) split_nth(delim string, nth int) []string {
|
|||||||
i = 1
|
i = 1
|
||||||
for ch in s {
|
for ch in s {
|
||||||
if nth > 0 && i >= nth {
|
if nth > 0 && i >= nth {
|
||||||
res << s[i..]
|
res << s[i - 1..]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
res << ch.ascii_str()
|
res << ch.ascii_str()
|
||||||
@ -938,7 +938,7 @@ pub fn (s string) rsplit_nth(delim string, nth int) []string {
|
|||||||
0 {
|
0 {
|
||||||
for i >= 0 {
|
for i >= 0 {
|
||||||
if nth > 0 && res.len == nth - 1 {
|
if nth > 0 && res.len == nth - 1 {
|
||||||
res << s[..i]
|
res << s[..i + 1]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
res << s[i].ascii_str()
|
res << s[i].ascii_str()
|
||||||
|
@ -183,6 +183,15 @@ fn test_split_nth() {
|
|||||||
assert e.split_nth(',,', 3).len == 3
|
assert e.split_nth(',,', 3).len == 3
|
||||||
assert e.split_nth(',', -1).len == 12
|
assert e.split_nth(',', -1).len == 12
|
||||||
assert e.split_nth(',', 3).len == 3
|
assert e.split_nth(',', 3).len == 3
|
||||||
|
f := '1:2:3'
|
||||||
|
assert f.split_nth(':', 2) == ['1', '2:3']
|
||||||
|
assert f.rsplit_nth(':', 2) == ['3', '1:2']
|
||||||
|
g := '123'
|
||||||
|
assert g.split_nth('', 2) == ['1', '23']
|
||||||
|
assert g.rsplit_nth('', 2) == ['3', '12']
|
||||||
|
h := ''
|
||||||
|
assert h.split_nth('', 2) == []
|
||||||
|
assert h.rsplit_nth('', 2) == []
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_rsplit_nth() {
|
fn test_rsplit_nth() {
|
||||||
|
@ -18,9 +18,9 @@ pub mut:
|
|||||||
description string
|
description string
|
||||||
man_description string
|
man_description string
|
||||||
version string
|
version string
|
||||||
pre_execute FnCommandCallback
|
pre_execute FnCommandCallback = unsafe { nil }
|
||||||
execute FnCommandCallback
|
execute FnCommandCallback = unsafe { nil }
|
||||||
post_execute FnCommandCallback
|
post_execute FnCommandCallback = unsafe { nil }
|
||||||
disable_help bool
|
disable_help bool
|
||||||
disable_man bool
|
disable_man bool
|
||||||
disable_version bool
|
disable_version bool
|
||||||
|
@ -151,17 +151,17 @@ pub fn new() &Digest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// new512_224 returns a new Digest (implementing hash.Hash) computing the SHA-512/224 checksum.
|
// new512_224 returns a new Digest (implementing hash.Hash) computing the SHA-512/224 checksum.
|
||||||
fn new512_224() &Digest {
|
pub fn new512_224() &Digest {
|
||||||
return new_digest(.sha512_224)
|
return new_digest(.sha512_224)
|
||||||
}
|
}
|
||||||
|
|
||||||
// new512_256 returns a new Digest (implementing hash.Hash) computing the SHA-512/256 checksum.
|
// new512_256 returns a new Digest (implementing hash.Hash) computing the SHA-512/256 checksum.
|
||||||
fn new512_256() &Digest {
|
pub fn new512_256() &Digest {
|
||||||
return new_digest(.sha512_256)
|
return new_digest(.sha512_256)
|
||||||
}
|
}
|
||||||
|
|
||||||
// new384 returns a new Digest (implementing hash.Hash) computing the SHA-384 checksum.
|
// new384 returns a new Digest (implementing hash.Hash) computing the SHA-384 checksum.
|
||||||
fn new384() &Digest {
|
pub fn new384() &Digest {
|
||||||
return new_digest(.sha384)
|
return new_digest(.sha384)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,13 +4,22 @@ module datatypes
|
|||||||
|
|
||||||
[heap]
|
[heap]
|
||||||
struct BloomFilter[T] {
|
struct BloomFilter[T] {
|
||||||
hash_func fn (T) u32 // hash function, input [T] , output u32
|
// TODO V bug
|
||||||
table_size int // every entry is one-bit, packed into `table`
|
hash_func fn (T) u32 = unsafe { nil } // hash function, input [T] , output u32
|
||||||
num_functions int // 1~16
|
// hash_func fn (T) u32 = empty_cb // hash function, input [T] , output u32
|
||||||
|
table_size int // every entry is one-bit, packed into `table`
|
||||||
|
num_functions int // 1~16
|
||||||
mut:
|
mut:
|
||||||
table []u8
|
table []u8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO maybe allow pointing to generic fns?
|
||||||
|
fn empty_cb[T](x T) u32 {
|
||||||
|
panic('empty BloomFilter.hash_func callback')
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Salt values(random values). These salts are XORed with the output of the hash function to give multiple unique hashes.
|
// Salt values(random values). These salts are XORed with the output of the hash function to give multiple unique hashes.
|
||||||
salts = [
|
salts = [
|
||||||
|
@ -51,3 +51,14 @@ Read this section to learn how to install and connect to PostgreSQL
|
|||||||
[*Windows*](https://www.postgresqltutorial.com/install-postgresql);
|
[*Windows*](https://www.postgresqltutorial.com/install-postgresql);
|
||||||
[*Linux*](https://www.postgresqltutorial.com/postgresql-getting-started/install-postgresql-linux);
|
[*Linux*](https://www.postgresqltutorial.com/postgresql-getting-started/install-postgresql-linux);
|
||||||
[*macOS*](https://www.postgresqltutorial.com/postgresql-getting-started/install-postgresql-macos).
|
[*macOS*](https://www.postgresqltutorial.com/postgresql-getting-started/install-postgresql-macos).
|
||||||
|
|
||||||
|
## Using Parameterized Queries
|
||||||
|
|
||||||
|
Parameterized queries (exec_param, etc.) in V require the use of the following syntax: ($n).
|
||||||
|
|
||||||
|
The number following the $ specifies which parameter from the argument array to use.
|
||||||
|
|
||||||
|
```v ignore
|
||||||
|
db.exec_param_many('INSERT INTO users (username, password) VALUES ($1, $2)', ['tom', 'securePassword']) or { panic(err) }
|
||||||
|
db.exec_param('SELECT * FROM users WHERE username = ($1) limit 1', 'tom') or { panic(err) }
|
||||||
|
```
|
||||||
|
@ -251,7 +251,7 @@ pub fn (db DB) exec_one(query string) !Row {
|
|||||||
return row
|
return row
|
||||||
}
|
}
|
||||||
|
|
||||||
// exec_param_many executes a query with the provided parameters
|
// exec_param_many executes a query with the parameters provided as ($1), ($2), ($n)
|
||||||
pub fn (db DB) exec_param_many(query string, params []string) ![]Row {
|
pub fn (db DB) exec_param_many(query string, params []string) ![]Row {
|
||||||
unsafe {
|
unsafe {
|
||||||
mut param_vals := []&char{len: params.len}
|
mut param_vals := []&char{len: params.len}
|
||||||
@ -265,12 +265,12 @@ pub fn (db DB) exec_param_many(query string, params []string) ![]Row {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// exec_param2 executes a query with 1 parameter, and returns either an error on failure, or the full result set on success
|
// exec_param2 executes a query with 1 parameter ($1), and returns either an error on failure, or the full result set on success
|
||||||
pub fn (db DB) exec_param(query string, param string) ![]Row {
|
pub fn (db DB) exec_param(query string, param string) ![]Row {
|
||||||
return db.exec_param_many(query, [param])
|
return db.exec_param_many(query, [param])
|
||||||
}
|
}
|
||||||
|
|
||||||
// exec_param2 executes a query with 2 parameters, and returns either an error on failure, or the full result set on success
|
// exec_param2 executes a query with 2 parameters ($1) and ($2), and returns either an error on failure, or the full result set on success
|
||||||
pub fn (db DB) exec_param2(query string, param string, param2 string) ![]Row {
|
pub fn (db DB) exec_param2(query string, param string, param2 string) ![]Row {
|
||||||
return db.exec_param_many(query, [param, param2])
|
return db.exec_param_many(query, [param, param2])
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ mut:
|
|||||||
|
|
||||||
struct EventHandler[T] {
|
struct EventHandler[T] {
|
||||||
name T
|
name T
|
||||||
handler EventHandlerFn
|
handler EventHandlerFn = unsafe { nil }
|
||||||
receiver voidptr = unsafe { nil }
|
receiver voidptr = unsafe { nil }
|
||||||
once bool
|
once bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,15 +6,15 @@ pub struct C.FONSparams {
|
|||||||
flags char
|
flags char
|
||||||
userPtr voidptr
|
userPtr voidptr
|
||||||
// int (*renderCreate)(void* uptr, int width, int height)
|
// int (*renderCreate)(void* uptr, int width, int height)
|
||||||
renderCreate fn (uptr voidptr, width int, height int) int
|
renderCreate fn (uptr voidptr, width int, height int) int = unsafe { nil }
|
||||||
// int (*renderResize)(void* uptr, int width, int height)
|
// int (*renderResize)(void* uptr, int width, int height)
|
||||||
renderResize fn (uptr voidptr, width int, height int) int
|
renderResize fn (uptr voidptr, width int, height int) int = unsafe { nil }
|
||||||
// void (*renderUpdate)(void* uptr, int* rect, const unsigned char* data)
|
// void (*renderUpdate)(void* uptr, int* rect, const unsigned char* data)
|
||||||
renderUpdate fn (uptr voidptr, rect &int, data &u8)
|
renderUpdate fn (uptr voidptr, rect &int, data &u8) = unsafe { nil }
|
||||||
// void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts)
|
// void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts)
|
||||||
renderDraw fn (uptr voidptr, verts &f32, tcoords &f32, colors &u32, nverts int)
|
renderDraw fn (uptr voidptr, verts &f32, tcoords &f32, colors &u32, nverts int) = unsafe { nil }
|
||||||
// void (*renderDelete)(void* uptr)
|
// void (*renderDelete)(void* uptr)
|
||||||
renderDelete fn (uptr voidptr)
|
renderDelete fn (uptr voidptr) = unsafe { nil }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct C.FONSquad {
|
pub struct C.FONSquad {
|
||||||
|
@ -25,15 +25,25 @@ pub mut:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create_image creates an `Image` from `file`.
|
// create_image creates an `Image` from `file`.
|
||||||
pub fn (ctx &Context) create_image(file string) !Image {
|
pub fn (mut ctx Context) create_image(file string) !Image {
|
||||||
// println('\ncreate_image("$file")')
|
|
||||||
if !os.exists(file) {
|
if !os.exists(file) {
|
||||||
return error('image file "${file}" not found')
|
$if android {
|
||||||
|
image_data := os.read_apk_asset(file)!
|
||||||
|
mut image := ctx.create_image_from_byte_array(image_data)!
|
||||||
|
|
||||||
|
image.path = file
|
||||||
|
|
||||||
|
return image
|
||||||
|
} $else {
|
||||||
|
return error('image file "${file}" not found')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$if macos {
|
$if macos {
|
||||||
if ctx.native_rendering {
|
if ctx.native_rendering {
|
||||||
// return C.darwin_create_image(file)
|
// return C.darwin_create_image(file)
|
||||||
mut img := C.darwin_create_image(file)
|
mut img := C.darwin_create_image(file)
|
||||||
|
|
||||||
// println('created macos image: $img.path w=$img.width')
|
// println('created macos image: $img.path w=$img.width')
|
||||||
// C.printf('p = %p\n', img.data)
|
// C.printf('p = %p\n', img.data)
|
||||||
img.id = ctx.image_cache.len
|
img.id = ctx.image_cache.len
|
||||||
@ -43,6 +53,7 @@ pub fn (ctx &Context) create_image(file string) !Image {
|
|||||||
return img
|
return img
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !gfx.is_valid() {
|
if !gfx.is_valid() {
|
||||||
// Sokol is not initialized yet, add stbi object to a queue/cache
|
// Sokol is not initialized yet, add stbi object to a queue/cache
|
||||||
// ctx.image_queue << file
|
// ctx.image_queue << file
|
||||||
|
@ -382,7 +382,7 @@ pub fn (u_ Uint256) str() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// uint256_from_dec_str creates a new `unsigned.Uint256` from the given string if possible
|
// uint256_from_dec_str creates a new `unsigned.Uint256` from the given string if possible
|
||||||
pub fn uint256_from_dec_str(value string) ?Uint256 {
|
pub fn uint256_from_dec_str(value string) !Uint256 {
|
||||||
mut res := unsigned.uint256_zero
|
mut res := unsigned.uint256_zero
|
||||||
for b_ in value.bytes() {
|
for b_ in value.bytes() {
|
||||||
b := b_ - '0'.bytes()[0]
|
b := b_ - '0'.bytes()[0]
|
||||||
|
@ -170,7 +170,12 @@ fn C.mbedtls_pk_parse_keyfile(&C.mbedtls_pk_context, &char, &char, voidptr, void
|
|||||||
|
|
||||||
fn C.mbedtls_net_connect(&C.mbedtls_net_context, &u8, &u8, int) int
|
fn C.mbedtls_net_connect(&C.mbedtls_net_context, &u8, &u8, int) int
|
||||||
|
|
||||||
fn C.mbedtls_ssl_conf_own_cert(&C.mbedtls_ssl_config, &C.mbedtls_x509_crt, &C.mbedtls_pk_context)
|
fn C.mbedtls_net_bind(&C.mbedtls_net_context, voidptr, &u8, int) int
|
||||||
|
fn C.mbedtls_net_accept(&C.mbedtls_net_context, &C.mbedtls_net_context, voidptr, int, voidptr) int
|
||||||
|
fn C.mbedtls_ssl_session_reset(&C.mbedtls_ssl_context)
|
||||||
|
fn C.mbedtls_ssl_conf_authmode(&C.mbedtls_ssl_config, int)
|
||||||
|
|
||||||
|
fn C.mbedtls_ssl_conf_own_cert(&C.mbedtls_ssl_config, &C.mbedtls_x509_crt, &C.mbedtls_pk_context) int
|
||||||
fn C.mbedtls_ssl_conf_authmode(&C.mbedtls_ssl_config, int)
|
fn C.mbedtls_ssl_conf_authmode(&C.mbedtls_ssl_config, int)
|
||||||
fn C.mbedtls_ssl_conf_ca_chain(&C.mbedtls_ssl_config, &C.mbedtls_x509_crt, &C.mbedtls_x509_crl)
|
fn C.mbedtls_ssl_conf_ca_chain(&C.mbedtls_ssl_config, &C.mbedtls_x509_crt, &C.mbedtls_x509_crl)
|
||||||
fn C.mbedtls_ssl_conf_rng(&C.mbedtls_ssl_config, voidptr, &C.mbedtls_ctr_drbg_context)
|
fn C.mbedtls_ssl_conf_rng(&C.mbedtls_ssl_config, voidptr, &C.mbedtls_ctr_drbg_context)
|
||||||
|
@ -45,6 +45,172 @@ mut:
|
|||||||
owns_socket bool
|
owns_socket bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SSLListener listens on a TCP port and accepts connection secured with TLS
|
||||||
|
pub struct SSLListener {
|
||||||
|
saddr string
|
||||||
|
config SSLConnectConfig
|
||||||
|
mut:
|
||||||
|
server_fd C.mbedtls_net_context
|
||||||
|
ssl C.mbedtls_ssl_context
|
||||||
|
conf C.mbedtls_ssl_config
|
||||||
|
certs &SSLCerts = unsafe { nil }
|
||||||
|
opened bool
|
||||||
|
// handle int
|
||||||
|
// duration time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new SSLListener binding to `saddr`
|
||||||
|
pub fn new_ssl_listener(saddr string, config SSLConnectConfig) !&SSLListener {
|
||||||
|
mut listener := &SSLListener{
|
||||||
|
saddr: saddr
|
||||||
|
config: config
|
||||||
|
}
|
||||||
|
listener.init()!
|
||||||
|
listener.opened = true
|
||||||
|
return listener
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish the listener and clean up resources
|
||||||
|
pub fn (mut l SSLListener) shutdown() ! {
|
||||||
|
$if trace_ssl ? {
|
||||||
|
eprintln(@METHOD)
|
||||||
|
}
|
||||||
|
if unsafe { l.certs != nil } {
|
||||||
|
C.mbedtls_x509_crt_free(&l.certs.cacert)
|
||||||
|
C.mbedtls_x509_crt_free(&l.certs.client_cert)
|
||||||
|
C.mbedtls_pk_free(&l.certs.client_key)
|
||||||
|
}
|
||||||
|
C.mbedtls_ssl_free(&l.ssl)
|
||||||
|
C.mbedtls_ssl_config_free(&l.conf)
|
||||||
|
if l.opened {
|
||||||
|
C.mbedtls_net_free(&l.server_fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal function to init and bind the listener
|
||||||
|
fn (mut l SSLListener) init() ! {
|
||||||
|
$if trace_ssl ? {
|
||||||
|
eprintln(@METHOD)
|
||||||
|
}
|
||||||
|
|
||||||
|
lhost, lport := net.split_address(l.saddr)!
|
||||||
|
if l.config.cert == '' || l.config.cert_key == '' {
|
||||||
|
return error('No certificate or key provided')
|
||||||
|
}
|
||||||
|
if l.config.validate && l.config.verify == '' {
|
||||||
|
return error('No root CA provided')
|
||||||
|
}
|
||||||
|
C.mbedtls_net_init(&l.server_fd)
|
||||||
|
C.mbedtls_ssl_init(&l.ssl)
|
||||||
|
C.mbedtls_ssl_config_init(&l.conf)
|
||||||
|
l.certs = &SSLCerts{}
|
||||||
|
C.mbedtls_x509_crt_init(&l.certs.client_cert)
|
||||||
|
C.mbedtls_pk_init(&l.certs.client_key)
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
C.mbedtls_ssl_conf_rng(&l.conf, C.mbedtls_ctr_drbg_random, &mbedtls.ctr_drbg)
|
||||||
|
}
|
||||||
|
|
||||||
|
mut ret := 0
|
||||||
|
|
||||||
|
if l.config.in_memory_verification {
|
||||||
|
if l.config.verify != '' {
|
||||||
|
ret = C.mbedtls_x509_crt_parse(&l.certs.cacert, l.config.verify.str, l.config.verify.len)
|
||||||
|
}
|
||||||
|
if l.config.cert != '' {
|
||||||
|
ret = C.mbedtls_x509_crt_parse(&l.certs.client_cert, l.config.cert.str, l.config.cert.len)
|
||||||
|
}
|
||||||
|
if l.config.cert_key != '' {
|
||||||
|
unsafe {
|
||||||
|
ret = C.mbedtls_pk_parse_key(&l.certs.client_key, l.config.cert_key.str,
|
||||||
|
l.config.cert_key.len, 0, 0, C.mbedtls_ctr_drbg_random, &mbedtls.ctr_drbg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if l.config.verify != '' {
|
||||||
|
ret = C.mbedtls_x509_crt_parse_file(&l.certs.cacert, &char(l.config.verify.str))
|
||||||
|
}
|
||||||
|
ret = C.mbedtls_x509_crt_parse_file(&l.certs.client_cert, &char(l.config.cert.str))
|
||||||
|
unsafe {
|
||||||
|
ret = C.mbedtls_pk_parse_keyfile(&l.certs.client_key, &char(l.config.cert_key.str),
|
||||||
|
0, C.mbedtls_ctr_drbg_random, &mbedtls.ctr_drbg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.config.validate {
|
||||||
|
C.mbedtls_ssl_conf_authmode(&l.conf, C.MBEDTLS_SSL_VERIFY_REQUIRED)
|
||||||
|
}
|
||||||
|
|
||||||
|
mut bind_ip := unsafe { nil }
|
||||||
|
if lhost != '' {
|
||||||
|
bind_ip = voidptr(lhost.str)
|
||||||
|
}
|
||||||
|
bind_port := lport.str()
|
||||||
|
|
||||||
|
ret = C.mbedtls_net_bind(&l.server_fd, bind_ip, voidptr(bind_port.str), C.MBEDTLS_NET_PROTO_TCP)
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return error_with_code("can't bind to ${l.saddr}", ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = C.mbedtls_ssl_config_defaults(&l.conf, C.MBEDTLS_SSL_IS_SERVER, C.MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||||
|
C.MBEDTLS_SSL_PRESET_DEFAULT)
|
||||||
|
if ret != 0 {
|
||||||
|
return error_with_code("can't to set config defaults", ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
C.mbedtls_ssl_conf_ca_chain(&l.conf, &l.certs.cacert, unsafe { nil })
|
||||||
|
ret = C.mbedtls_ssl_conf_own_cert(&l.conf, &l.certs.client_cert, &l.certs.client_key)
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return error_with_code("can't load certificate", ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = C.mbedtls_ssl_setup(&l.ssl, &l.conf)
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return error_with_code("can't setup ssl", ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// accepts a new connection and returns a SSLConn of the connected client
|
||||||
|
pub fn (mut l SSLListener) accept() !&SSLConn {
|
||||||
|
mut conn := &SSLConn{
|
||||||
|
conf: l.conf
|
||||||
|
config: l.config
|
||||||
|
opened: true
|
||||||
|
owns_socket: true
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: save the client's IP address somewhere (maybe add a field to SSLConn ?)
|
||||||
|
mut ret := C.mbedtls_net_accept(&l.server_fd, &conn.server_fd, unsafe { nil }, 0,
|
||||||
|
unsafe { nil })
|
||||||
|
if ret != 0 {
|
||||||
|
return error_with_code("can't accept connection", ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
C.mbedtls_ssl_init(&conn.ssl)
|
||||||
|
C.mbedtls_ssl_config_init(&conn.conf)
|
||||||
|
ret = C.mbedtls_ssl_setup(&conn.ssl, &l.conf)
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return error_with_code('SSL setup failed', ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
C.mbedtls_ssl_set_bio(&conn.ssl, &conn.server_fd, C.mbedtls_net_send, C.mbedtls_net_recv,
|
||||||
|
unsafe { nil })
|
||||||
|
|
||||||
|
ret = C.mbedtls_ssl_handshake(&conn.ssl)
|
||||||
|
for ret != 0 {
|
||||||
|
if ret != C.MBEDTLS_ERR_SSL_WANT_READ && ret != C.MBEDTLS_ERR_SSL_WANT_WRITE {
|
||||||
|
return error_with_code('SSL handshake failed', ret)
|
||||||
|
}
|
||||||
|
ret = C.mbedtls_ssl_handshake(&conn.ssl)
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
pub struct SSLConnectConfig {
|
pub struct SSLConnectConfig {
|
||||||
verify string // the path to a rootca.pem file, containing trusted CA certificate(s)
|
verify string // the path to a rootca.pem file, containing trusted CA certificate(s)
|
||||||
|
@ -284,20 +284,27 @@ mut:
|
|||||||
accept_deadline time.Time
|
accept_deadline time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen_tcp(family AddrFamily, saddr string) !&TcpListener {
|
[params]
|
||||||
s := new_tcp_socket(family) or { return error('${err.msg()}; could not create new socket') }
|
pub struct ListenOptions {
|
||||||
|
pub:
|
||||||
|
dualstack bool = true
|
||||||
|
backlog int = 128
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn listen_tcp(family AddrFamily, saddr string, options ListenOptions) !&TcpListener {
|
||||||
|
mut s := new_tcp_socket(family) or { return error('${err.msg()}; could not create new socket') }
|
||||||
|
s.set_dualstack(options.dualstack) or {}
|
||||||
|
|
||||||
addrs := resolve_addrs(saddr, family, .tcp) or {
|
addrs := resolve_addrs(saddr, family, .tcp) or {
|
||||||
return error('${err.msg()}; could not resolve address ${saddr}')
|
return error('${err.msg()}; could not resolve address ${saddr}')
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(logic to pick here)
|
// TODO(logic to pick here)
|
||||||
addr := addrs[0]
|
addr := addrs[0]
|
||||||
|
|
||||||
// cast to the correct type
|
// cast to the correct type
|
||||||
alen := addr.len()
|
alen := addr.len()
|
||||||
socket_error_message(C.bind(s.handle, voidptr(&addr), alen), 'binding to ${saddr} failed')!
|
socket_error_message(C.bind(s.handle, voidptr(&addr), alen), 'binding to ${saddr} failed')!
|
||||||
socket_error_message(C.listen(s.handle, 128), 'listening on ${saddr} failed')!
|
socket_error_message(C.listen(s.handle, options.backlog), 'listening on ${saddr} with maximum backlog pending queue of ${options.backlog}, failed')!
|
||||||
return &TcpListener{
|
return &TcpListener{
|
||||||
sock: s
|
sock: s
|
||||||
accept_deadline: no_deadline
|
accept_deadline: no_deadline
|
||||||
|
@ -150,9 +150,7 @@ pub fn (mut ws Client) listen() ! {
|
|||||||
ws.debug_log('got message: ${msg.opcode}')
|
ws.debug_log('got message: ${msg.opcode}')
|
||||||
match msg.opcode {
|
match msg.opcode {
|
||||||
.text_frame {
|
.text_frame {
|
||||||
log_msg = 'read: text'
|
ws.debug_log('read: text')
|
||||||
ws.debug_log(log_msg)
|
|
||||||
unsafe { log_msg.free() }
|
|
||||||
ws.send_message_event(msg)
|
ws.send_message_event(msg)
|
||||||
unsafe { msg.free() }
|
unsafe { msg.free() }
|
||||||
}
|
}
|
||||||
@ -184,9 +182,7 @@ pub fn (mut ws Client) listen() ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.close {
|
.close {
|
||||||
log_msg = 'read: close'
|
ws.debug_log('read: close')
|
||||||
ws.debug_log(log_msg)
|
|
||||||
unsafe { log_msg.free() }
|
|
||||||
defer {
|
defer {
|
||||||
ws.manage_clean_close()
|
ws.manage_clean_close()
|
||||||
}
|
}
|
||||||
|
@ -13,17 +13,15 @@ pub fn input_password(prompt string) !string {
|
|||||||
if termios.tcgetattr(0, mut old_state) != 0 {
|
if termios.tcgetattr(0, mut old_state) != 0 {
|
||||||
return last_error()
|
return last_error()
|
||||||
}
|
}
|
||||||
defer {
|
|
||||||
termios.tcsetattr(0, C.TCSANOW, mut old_state)
|
|
||||||
println('')
|
|
||||||
}
|
|
||||||
|
|
||||||
mut new_state := old_state
|
mut new_state := old_state
|
||||||
|
new_state.disable_echo()
|
||||||
new_state.c_lflag &= termios.invert(C.ECHO) // Disable echoing of characters
|
termios.set_state(0, new_state)
|
||||||
termios.tcsetattr(0, C.TCSANOW, mut new_state)
|
|
||||||
|
|
||||||
password := input_opt(prompt) or { return error('Failed to read password') }
|
password := input_opt(prompt) or { return error('Failed to read password') }
|
||||||
|
|
||||||
|
termios.set_state(0, old_state)
|
||||||
|
|
||||||
|
println('')
|
||||||
return password
|
return password
|
||||||
}
|
}
|
||||||
|
@ -106,8 +106,6 @@ fn (mut pv Picoev) del(fd int) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pv.update_events(fd, picoev.picoev_del) != 0 {
|
if pv.update_events(fd, picoev.picoev_del) != 0 {
|
||||||
target.loop_id = -1
|
|
||||||
target.fd = 0
|
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,15 +147,20 @@ fn (mut pv Picoev) set_timeout(fd int, secs int) {
|
|||||||
// timeout event
|
// timeout event
|
||||||
[direct_array_access; inline]
|
[direct_array_access; inline]
|
||||||
fn (mut pv Picoev) handle_timeout() {
|
fn (mut pv Picoev) handle_timeout() {
|
||||||
|
mut to_remove := []int{}
|
||||||
|
|
||||||
for fd, timeout in pv.timeouts {
|
for fd, timeout in pv.timeouts {
|
||||||
if timeout <= pv.loop.now {
|
if timeout <= pv.loop.now {
|
||||||
target := pv.file_descriptors[fd]
|
to_remove << fd
|
||||||
assert target.loop_id == pv.loop.id
|
|
||||||
|
|
||||||
pv.timeouts.delete(fd)
|
|
||||||
unsafe { target.cb(fd, picoev.picoev_timeout, &pv) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for fd in to_remove {
|
||||||
|
target := pv.file_descriptors[fd]
|
||||||
|
assert target.loop_id == pv.loop.id
|
||||||
|
pv.timeouts.delete(fd)
|
||||||
|
unsafe { target.cb(fd, picoev.picoev_timeout, &pv) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// accept_callback accepts a new connection from `listen_fd` and adds it to the loop
|
// accept_callback accepts a new connection from `listen_fd` and adds it to the loop
|
||||||
|
@ -248,7 +248,7 @@ mut:
|
|||||||
// counters for quantifier check (repetitions)
|
// counters for quantifier check (repetitions)
|
||||||
rep int
|
rep int
|
||||||
// validator function pointer
|
// validator function pointer
|
||||||
validator FnValidator
|
validator FnValidator = unsafe { nil }
|
||||||
// groups variables
|
// groups variables
|
||||||
group_neg bool // negation flag for the group, 0 => no negation > 0 => negataion
|
group_neg bool // negation flag for the group, 0 => no negation > 0 => negataion
|
||||||
group_rep int // repetition of the group
|
group_rep int // repetition of the group
|
||||||
@ -376,7 +376,7 @@ fn (mut re RE) reset_src() {
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
struct BslsStruct {
|
struct BslsStruct {
|
||||||
ch rune // meta char
|
ch rune // meta char
|
||||||
validator FnValidator // validator function pointer
|
validator FnValidator = unsafe { nil } // validator function pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -463,7 +463,7 @@ mut:
|
|||||||
cc_type int // type of cc token
|
cc_type int // type of cc token
|
||||||
ch0 rune // first char of the interval a-b a in this case
|
ch0 rune // first char of the interval a-b a in this case
|
||||||
ch1 rune // second char of the interval a-b b in this case
|
ch1 rune // second char of the interval a-b b in this case
|
||||||
validator FnValidator // validator function pointer
|
validator FnValidator = unsafe { nil } // validator function pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CharClass_parse_state {
|
enum CharClass_parse_state {
|
||||||
|
@ -6,10 +6,21 @@ pub const used_import = 1
|
|||||||
#flag -I @VEXEROOT/thirdparty/sokol/util
|
#flag -I @VEXEROOT/thirdparty/sokol/util
|
||||||
#flag freebsd -I /usr/local/include
|
#flag freebsd -I /usr/local/include
|
||||||
#flag darwin -fobjc-arc
|
#flag darwin -fobjc-arc
|
||||||
|
|
||||||
#flag linux -lX11 -lGL -lXcursor -lXi -lpthread
|
#flag linux -lX11 -lGL -lXcursor -lXi -lpthread
|
||||||
#flag freebsd -L/usr/local/lib -lX11 -lGL -lXcursor -lXi
|
#flag freebsd -L/usr/local/lib -lX11 -lGL -lXcursor -lXi
|
||||||
#flag openbsd -L/usr/X11R6/lib -lX11 -lGL -lXcursor -lXi
|
#flag openbsd -L/usr/X11R6/lib -lX11 -lGL -lXcursor -lXi
|
||||||
#flag windows -lgdi32
|
#flag windows -lgdi32
|
||||||
|
|
||||||
|
// Note that -lm is needed *only* for sokol_gl.h's usage of sqrtf(),
|
||||||
|
// but without -lm, this fails:
|
||||||
|
// `v -cc gcc ~/.vmodules/sdl/examples/sdl_opengl_and_sokol/`
|
||||||
|
// With tcc, this succeeds with or without -lm:
|
||||||
|
// `v ~/.vmodules/sdl/examples/sdl_opengl_and_sokol/`
|
||||||
|
$if !tinyc {
|
||||||
|
#flag linux -lm
|
||||||
|
}
|
||||||
|
|
||||||
// METAL
|
// METAL
|
||||||
$if macos {
|
$if macos {
|
||||||
$if darwin_sokol_glcore33 ? {
|
$if darwin_sokol_glcore33 ? {
|
||||||
@ -19,10 +30,6 @@ $if macos {
|
|||||||
#flag -framework Metal -framework Cocoa -framework MetalKit -framework QuartzCore
|
#flag -framework Metal -framework Cocoa -framework MetalKit -framework QuartzCore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$if linux {
|
|
||||||
#flag -D SOKOL_GLCORE33
|
|
||||||
}
|
|
||||||
|
|
||||||
$if ios {
|
$if ios {
|
||||||
#flag -DSOKOL_METAL
|
#flag -DSOKOL_METAL
|
||||||
#flag -framework Foundation -framework Metal -framework MetalKit -framework UIKit
|
#flag -framework Foundation -framework Metal -framework MetalKit -framework UIKit
|
||||||
|
@ -5,14 +5,14 @@ import sokol.memory
|
|||||||
[typedef]
|
[typedef]
|
||||||
pub struct C.sg_allocator {
|
pub struct C.sg_allocator {
|
||||||
pub mut:
|
pub mut:
|
||||||
alloc memory.FnAllocatorAlloc
|
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||||
free memory.FnAllocatorFree
|
free memory.FnAllocatorFree = unsafe { nil }
|
||||||
user_data voidptr
|
user_data voidptr
|
||||||
}
|
}
|
||||||
|
|
||||||
[typedef]
|
[typedef]
|
||||||
pub struct C.sg_logger {
|
pub struct C.sg_logger {
|
||||||
pub mut:
|
pub mut:
|
||||||
log_cb memory.FnLogCb
|
log_cb memory.FnLogCb = unsafe { nil }
|
||||||
user_data voidptr
|
user_data voidptr
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,8 @@ pub type GLContextDesc = C.sg_gl_context_desc
|
|||||||
|
|
||||||
struct C.sg_metal_context_desc {
|
struct C.sg_metal_context_desc {
|
||||||
device voidptr
|
device voidptr
|
||||||
renderpass_descriptor_cb fn () voidptr
|
renderpass_descriptor_cb fn () voidptr = unsafe { nil }
|
||||||
drawable_cb fn () voidptr
|
drawable_cb fn () voidptr = unsafe { nil }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MetalContextDesc = C.sg_metal_context_desc
|
pub type MetalContextDesc = C.sg_metal_context_desc
|
||||||
@ -55,8 +55,8 @@ pub type MetalContextDesc = C.sg_metal_context_desc
|
|||||||
struct C.sg_d3d11_context_desc {
|
struct C.sg_d3d11_context_desc {
|
||||||
device voidptr
|
device voidptr
|
||||||
device_context voidptr
|
device_context voidptr
|
||||||
render_target_view_cb fn () voidptr
|
render_target_view_cb fn () voidptr = unsafe { nil }
|
||||||
depth_stencil_view_cb fn () voidptr
|
depth_stencil_view_cb fn () voidptr = unsafe { nil }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type D3D11ContextDesc = C.sg_d3d11_context_desc
|
pub type D3D11ContextDesc = C.sg_d3d11_context_desc
|
||||||
|
@ -5,14 +5,14 @@ import sokol.memory
|
|||||||
[typedef]
|
[typedef]
|
||||||
pub struct C.sapp_allocator {
|
pub struct C.sapp_allocator {
|
||||||
pub mut:
|
pub mut:
|
||||||
alloc memory.FnAllocatorAlloc
|
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||||
free memory.FnAllocatorFree
|
free memory.FnAllocatorFree = unsafe { nil }
|
||||||
user_data voidptr
|
user_data voidptr
|
||||||
}
|
}
|
||||||
|
|
||||||
[typedef]
|
[typedef]
|
||||||
pub struct C.sapp_logger {
|
pub struct C.sapp_logger {
|
||||||
pub mut:
|
pub mut:
|
||||||
log_cb memory.FnLogCb
|
log_cb memory.FnLogCb = unsafe { nil }
|
||||||
user_data voidptr
|
user_data voidptr
|
||||||
}
|
}
|
||||||
|
@ -37,18 +37,19 @@ pub type IconDesc = C.sapp_icon_desc
|
|||||||
[typedef]
|
[typedef]
|
||||||
pub struct C.sapp_desc {
|
pub struct C.sapp_desc {
|
||||||
pub:
|
pub:
|
||||||
init_cb fn () // these are the user-provided callbacks without user data
|
// these are the user-provided callbacks without user data
|
||||||
frame_cb fn ()
|
init_cb fn () = unsafe { nil }
|
||||||
cleanup_cb fn ()
|
frame_cb fn () = unsafe { nil }
|
||||||
event_cb fn (&Event) //&sapp_event)
|
cleanup_cb fn () = unsafe { nil }
|
||||||
fail_cb fn (&u8)
|
event_cb fn (&Event) = unsafe { nil } // &sapp_event
|
||||||
|
fail_cb fn (&u8) = unsafe { nil }
|
||||||
|
|
||||||
user_data voidptr // these are the user-provided callbacks with user data
|
user_data voidptr // these are the user-provided callbacks with user data
|
||||||
init_userdata_cb fn (voidptr)
|
init_userdata_cb fn (voidptr) = unsafe { nil }
|
||||||
frame_userdata_cb fn (voidptr)
|
frame_userdata_cb fn (voidptr) = unsafe { nil }
|
||||||
cleanup_userdata_cb fn (voidptr)
|
cleanup_userdata_cb fn (voidptr) = unsafe { nil }
|
||||||
event_userdata_cb fn (&Event, voidptr)
|
event_userdata_cb fn (&Event, voidptr) = unsafe { nil }
|
||||||
fail_userdata_cb fn (&char, voidptr)
|
fail_userdata_cb fn (&char, voidptr) = unsafe { nil }
|
||||||
|
|
||||||
width int // the preferred width of the window / canvas
|
width int // the preferred width of the window / canvas
|
||||||
height int // the preferred height of the window / canvas
|
height int // the preferred height of the window / canvas
|
||||||
|
@ -6,8 +6,8 @@ import sokol.memory
|
|||||||
[typedef]
|
[typedef]
|
||||||
pub struct C.sfons_allocator_t {
|
pub struct C.sfons_allocator_t {
|
||||||
pub:
|
pub:
|
||||||
alloc memory.FnAllocatorAlloc
|
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||||
free memory.FnAllocatorFree
|
free memory.FnAllocatorFree = unsafe { nil }
|
||||||
user_data voidptr
|
user_data voidptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,14 +5,14 @@ import sokol.memory
|
|||||||
[typedef]
|
[typedef]
|
||||||
pub struct C.sgl_allocator_t {
|
pub struct C.sgl_allocator_t {
|
||||||
pub mut:
|
pub mut:
|
||||||
alloc memory.FnAllocatorAlloc
|
alloc memory.FnAllocatorAlloc = unsafe { nil }
|
||||||
free memory.FnAllocatorFree
|
free memory.FnAllocatorFree = unsafe { nil }
|
||||||
user_data voidptr
|
user_data voidptr
|
||||||
}
|
}
|
||||||
|
|
||||||
[typedef]
|
[typedef]
|
||||||
pub struct C.sgl_logger_t {
|
pub struct C.sgl_logger_t {
|
||||||
pub mut:
|
pub mut:
|
||||||
log_cb memory.FnLogCb
|
log_cb memory.FnLogCb = unsafe { nil }
|
||||||
user_data voidptr
|
user_data voidptr
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ mut:
|
|||||||
nxt &Subscription = unsafe { nil }
|
nxt &Subscription = unsafe { nil }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Direction {
|
pub enum Direction {
|
||||||
pop
|
pop
|
||||||
push
|
push
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,15 @@ mut:
|
|||||||
|
|
||||||
pub type ThreadCB = fn (mut p PoolProcessor, idx int, task_id int) voidptr
|
pub type ThreadCB = fn (mut p PoolProcessor, idx int, task_id int) voidptr
|
||||||
|
|
||||||
|
fn empty_cb(mut p PoolProcessor, idx int, task_id int) voidptr {
|
||||||
|
unsafe {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PoolProcessorConfig {
|
pub struct PoolProcessorConfig {
|
||||||
maxjobs int
|
maxjobs int
|
||||||
callback ThreadCB
|
callback ThreadCB = empty_cb
|
||||||
}
|
}
|
||||||
|
|
||||||
// new_pool_processor returns a new PoolProcessor instance.
|
// new_pool_processor returns a new PoolProcessor instance.
|
||||||
|
@ -176,7 +176,7 @@ pub fn (mut sem Semaphore) timed_wait(timeout time.Duration) bool {
|
|||||||
C.GetSystemTimeAsFileTime(&ft_start)
|
C.GetSystemTimeAsFileTime(&ft_start)
|
||||||
time_end := ((u64(ft_start.dwHighDateTime) << 32) | ft_start.dwLowDateTime) +
|
time_end := ((u64(ft_start.dwHighDateTime) << 32) | ft_start.dwLowDateTime) +
|
||||||
u64(timeout / (100 * time.nanosecond))
|
u64(timeout / (100 * time.nanosecond))
|
||||||
mut t_ms := timeout.sys_milliseconds()
|
mut t_ms := u32(timeout.sys_milliseconds())
|
||||||
C.AcquireSRWLockExclusive(&sem.mtx)
|
C.AcquireSRWLockExclusive(&sem.mtx)
|
||||||
mut res := 0
|
mut res := 0
|
||||||
c = C.atomic_load_u32(&sem.count)
|
c = C.atomic_load_u32(&sem.count)
|
||||||
|
@ -17,7 +17,8 @@ pub fn get_terminal_size() (int, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clear clears current terminal screen.
|
// clear clears current terminal screen.
|
||||||
pub fn clear() {
|
pub fn clear() bool {
|
||||||
print('\x1b[2J')
|
print('\x1b[2J')
|
||||||
print('\x1b[H')
|
print('\x1b[H')
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ pub fn set_tab_title(title string) bool {
|
|||||||
|
|
||||||
// clear clears current terminal screen.
|
// clear clears current terminal screen.
|
||||||
// Implementation taken from https://docs.microsoft.com/en-us/windows/console/clearing-the-screen#example-2.
|
// Implementation taken from https://docs.microsoft.com/en-us/windows/console/clearing-the-screen#example-2.
|
||||||
pub fn clear() {
|
pub fn clear() bool {
|
||||||
hconsole := C.GetStdHandle(C.STD_OUTPUT_HANDLE)
|
hconsole := C.GetStdHandle(C.STD_OUTPUT_HANDLE)
|
||||||
mut csbi := C.CONSOLE_SCREEN_BUFFER_INFO{}
|
mut csbi := C.CONSOLE_SCREEN_BUFFER_INFO{}
|
||||||
mut scrollrect := C.SMALL_RECT{}
|
mut scrollrect := C.SMALL_RECT{}
|
||||||
@ -106,7 +106,7 @@ pub fn clear() {
|
|||||||
|
|
||||||
// Get the number of character cells in the current buffer.
|
// Get the number of character cells in the current buffer.
|
||||||
if !C.GetConsoleScreenBufferInfo(hconsole, &csbi) {
|
if !C.GetConsoleScreenBufferInfo(hconsole, &csbi) {
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
// Scroll the rectangle of the entire buffer.
|
// Scroll the rectangle of the entire buffer.
|
||||||
scrollrect.Left = 0
|
scrollrect.Left = 0
|
||||||
@ -130,4 +130,5 @@ pub fn clear() {
|
|||||||
csbi.dwCursorPosition.Y = 0
|
csbi.dwCursorPosition.Y = 0
|
||||||
|
|
||||||
C.SetConsoleCursorPosition(hconsole, csbi.dwCursorPosition)
|
C.SetConsoleCursorPosition(hconsole, csbi.dwCursorPosition)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ fn C.ioctl(fd int, request u64, arg voidptr) int
|
|||||||
// for the underlying C.termios structure
|
// for the underlying C.termios structure
|
||||||
[inline]
|
[inline]
|
||||||
pub fn flag(value int) TcFlag {
|
pub fn flag(value int) TcFlag {
|
||||||
return int(value)
|
return TcFlag(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
||||||
@ -86,3 +86,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
|||||||
return C.ioctl(fd, request, arg)
|
return C.ioctl(fd, request, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
mut x := new_state
|
||||||
|
return tcsetattr(0, C.TCSANOW, mut x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed,
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
t.c_lflag &= invert(C.ECHO)
|
||||||
|
}
|
||||||
|
@ -84,3 +84,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
|||||||
return C.ioctl(fd, request, arg)
|
return C.ioctl(fd, request, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
mut x := new_state
|
||||||
|
return tcsetattr(0, C.TCSANOW, mut x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed,
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
t.c_lflag &= invert(C.ECHO)
|
||||||
|
}
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
//
|
|
||||||
// TODO Mac version needs to be implemented
|
|
||||||
// Will serve as more advanced input method
|
|
||||||
// based on the work of https://github.com/AmokHuginnsson/replxx
|
|
||||||
//
|
|
||||||
|
|
||||||
module termios
|
module termios
|
||||||
|
|
||||||
// not used but needed for function declarations
|
// not used but needed for function declarations
|
||||||
@ -14,45 +8,68 @@ type TcFlag = int
|
|||||||
type Speed = int
|
type Speed = int
|
||||||
type Cc = u8
|
type Cc = u8
|
||||||
|
|
||||||
// flag provides a termios flag of the correct size
|
// Termios definitions
|
||||||
// for the underlying C.termios structure
|
|
||||||
// It is only implemented for Unix like OSes
|
|
||||||
pub fn flag(value int) TcFlag {
|
|
||||||
$compile_error('feature not available')
|
|
||||||
}
|
|
||||||
|
|
||||||
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
|
||||||
// as its length varies across platforms
|
|
||||||
// It is only implemented for Unix like OSes
|
|
||||||
pub fn invert(value TcFlag) TcFlag {
|
|
||||||
$compile_error('feature not available')
|
|
||||||
}
|
|
||||||
|
|
||||||
// termios definitions
|
|
||||||
// Linux https://github.com/lattera/glibc/blob/master/sysdeps/unix/sysv/linux/bits/termios.h
|
// Linux https://github.com/lattera/glibc/blob/master/sysdeps/unix/sysv/linux/bits/termios.h
|
||||||
// OpenBSD https://github.com/openbsd/src/blob/master/sys/sys/termios.h
|
// OpenBSD https://github.com/openbsd/src/blob/master/sys/sys/termios.h
|
||||||
// FreeBSD https://web.mit.edu/freebsd/head/sys/sys/_termios.h
|
// FreeBSD https://web.mit.edu/freebsd/head/sys/sys/_termios.h
|
||||||
// Solaris https://github.com/omniti-labs/illumos-omnios/blob/master/usr/src/uts/common/sys/termios.h
|
// Solaris https://github.com/omniti-labs/illumos-omnios/blob/master/usr/src/uts/common/sys/termios.h
|
||||||
// DragonFly https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/sys/_termios.h
|
// DragonFly https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/sys/_termios.h
|
||||||
// QNX https://github.com/vocho/openqnx/blob/master/trunk/lib/c/public/termios.h
|
// QNX https://github.com/vocho/openqnx/blob/master/trunk/lib/c/public/termios.h
|
||||||
|
|
||||||
pub struct Termios {
|
pub struct Termios {
|
||||||
|
pub mut:
|
||||||
|
c_iflag TcFlag
|
||||||
|
c_oflag TcFlag
|
||||||
|
c_cflag TcFlag
|
||||||
|
c_lflag TcFlag
|
||||||
|
c_line Cc
|
||||||
|
c_cc [32]Cc
|
||||||
|
c_ispeed Speed
|
||||||
|
c_ospeed Speed
|
||||||
|
}
|
||||||
|
|
||||||
|
// flag provides a termios flag of the correct size
|
||||||
|
// for the underlying C.termios structure
|
||||||
|
pub fn flag(value int) TcFlag {
|
||||||
|
return TcFlag(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
||||||
|
// as its length varies across platforms
|
||||||
|
// It is only implemented for Unix like OSes
|
||||||
|
pub fn invert(value TcFlag) TcFlag {
|
||||||
|
return TcFlag(~int(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
|
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
|
||||||
// It is only implemented for Unix like OSes
|
// It is only implemented for Unix like OSes
|
||||||
pub fn tcgetattr(fd int, mut termios_p Termios) int {
|
pub fn tcgetattr(fd int, mut t Termios) int {
|
||||||
$compile_error('feature not available')
|
$compile_warn('termios.tcgetattr is not implemented on the platform')
|
||||||
|
eprintln('tcgetattr, fd: ${fd}, t: ${t}')
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
|
// tcsetattr is an unsafe wrapper around C.termios and keeps its semantic
|
||||||
// It is only implemented for Unix like OSes
|
// It is only implemented for Unix like OSes
|
||||||
pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
|
pub fn tcsetattr(fd int, optional_actions int, mut t Termios) int {
|
||||||
$compile_error('feature not available')
|
eprintln('tcsetattr, fd: ${fd}, optional_actions: ${optional_actions}, t: ${t}')
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
|
// ioctl is an unsafe wrapper around C.ioctl and keeps its semantic
|
||||||
[inline]
|
// It is only implemented for Unix like OSes
|
||||||
pub fn ioctl(fd int, request u64, arg voidptr) int {
|
pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||||
$compile_error('feature not available')
|
eprintln('ioctl, fd: ${fd}, request: ${request}, arg: ${arg}')
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
eprintln('set_state, fd: ${fd} | new_state: ${new_state}')
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
t.c_lflag &= invert(8)
|
||||||
}
|
}
|
||||||
|
@ -84,3 +84,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
|||||||
return C.ioctl(fd, request, arg)
|
return C.ioctl(fd, request, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
mut x := new_state
|
||||||
|
return tcsetattr(0, C.TCSANOW, mut x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed,
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
t.c_lflag &= invert(C.ECHO)
|
||||||
|
}
|
||||||
|
@ -84,3 +84,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
|||||||
return C.ioctl(fd, request, arg)
|
return C.ioctl(fd, request, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
mut x := new_state
|
||||||
|
return tcsetattr(0, C.TCSANOW, mut x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed,
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
t.c_lflag &= invert(C.ECHO)
|
||||||
|
}
|
||||||
|
@ -41,7 +41,7 @@ fn C.ioctl(fd int, request u64, arg voidptr) int
|
|||||||
// for the underlying C.termios structure
|
// for the underlying C.termios structure
|
||||||
[inline]
|
[inline]
|
||||||
pub fn flag(value int) TcFlag {
|
pub fn flag(value int) TcFlag {
|
||||||
return int(value)
|
return TcFlag(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
// invert is a platform dependant way to bitwise NOT (~) TcFlag
|
||||||
@ -86,3 +86,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
|||||||
return C.ioctl(fd, request, arg)
|
return C.ioctl(fd, request, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
mut x := new_state
|
||||||
|
return tcsetattr(0, C.TCSANOW, mut x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed,
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
t.c_lflag &= invert(C.ECHO)
|
||||||
|
}
|
||||||
|
@ -84,3 +84,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
|||||||
return C.ioctl(fd, request, arg)
|
return C.ioctl(fd, request, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
mut x := new_state
|
||||||
|
return tcsetattr(0, C.TCSANOW, mut x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed,
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
t.c_lflag &= invert(C.ECHO)
|
||||||
|
}
|
||||||
|
@ -86,3 +86,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
|||||||
return C.ioctl(fd, request, arg)
|
return C.ioctl(fd, request, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
mut x := new_state
|
||||||
|
return tcsetattr(0, C.TCSANOW, mut x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed,
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
t.c_lflag &= invert(C.ECHO)
|
||||||
|
}
|
||||||
|
@ -80,3 +80,15 @@ pub fn ioctl(fd int, request u64, arg voidptr) int {
|
|||||||
return C.ioctl(fd, request, arg)
|
return C.ioctl(fd, request, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
mut x := new_state
|
||||||
|
return tcsetattr(0, C.TCSANOW, mut x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed,
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
t.c_lflag &= invert(C.ECHO)
|
||||||
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
module termios
|
|
||||||
|
|
||||||
fn test_termios() {
|
|
||||||
mut original_term := Termios{}
|
|
||||||
tcgetattr(0, mut original_term)
|
|
||||||
println(original_term)
|
|
||||||
|
|
||||||
mut silent_term := original_term
|
|
||||||
silent_term.c_lflag &= invert(C.ECHO)
|
|
||||||
tcsetattr(0, C.TCSANOW, mut silent_term)
|
|
||||||
|
|
||||||
mut check_term := Termios{}
|
|
||||||
tcgetattr(0, mut check_term)
|
|
||||||
assert check_term.c_lflag == silent_term.c_lflag
|
|
||||||
|
|
||||||
tcsetattr(0, C.TCSANOW, mut orginal_term)
|
|
||||||
|
|
||||||
tcgetattr(0, mut check_term)
|
|
||||||
assert check_term.c_lflag == orginal_term.c_lflag
|
|
||||||
}
|
|
35
vlib/term/termios/termios_test.v
Normal file
35
vlib/term/termios/termios_test.v
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
module termios
|
||||||
|
|
||||||
|
fn test_portable() {
|
||||||
|
assert 123 == int(flag(123))
|
||||||
|
o := Termios{
|
||||||
|
c_lflag: flag(0xFFFF)
|
||||||
|
} // assume c_lflag exists everywhere
|
||||||
|
// dump( o.c_lflag )
|
||||||
|
mut n := o
|
||||||
|
n.c_lflag &= invert(1)
|
||||||
|
// dump( n.c_lflag )
|
||||||
|
assert n.c_lflag != o.c_lflag
|
||||||
|
n.disable_echo() // just assume it exists, and can be called everywhere
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
|
||||||
|
[if !windows]
|
||||||
|
fn test_termios() {
|
||||||
|
mut original_term := Termios{}
|
||||||
|
tcgetattr(0, mut original_term)
|
||||||
|
println(original_term)
|
||||||
|
|
||||||
|
mut silent_term := original_term
|
||||||
|
silent_term.c_lflag &= invert(C.ECHO)
|
||||||
|
tcsetattr(0, C.TCSANOW, mut silent_term)
|
||||||
|
|
||||||
|
mut check_term := Termios{}
|
||||||
|
tcgetattr(0, mut check_term)
|
||||||
|
assert check_term.c_lflag == silent_term.c_lflag
|
||||||
|
|
||||||
|
tcsetattr(0, C.TCSANOW, mut original_term)
|
||||||
|
|
||||||
|
tcgetattr(0, mut check_term)
|
||||||
|
assert check_term.c_lflag == original_term.c_lflag
|
||||||
|
}
|
@ -27,6 +27,15 @@ pub fn invert(value TcFlag) TcFlag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Termios {
|
pub struct Termios {
|
||||||
|
pub mut:
|
||||||
|
c_iflag TcFlag
|
||||||
|
c_oflag TcFlag
|
||||||
|
c_cflag TcFlag
|
||||||
|
c_lflag TcFlag
|
||||||
|
c_line Cc
|
||||||
|
c_cc [32]Cc
|
||||||
|
c_ispeed Speed
|
||||||
|
c_ospeed Speed
|
||||||
}
|
}
|
||||||
|
|
||||||
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
|
// tcgetattr is an unsafe wrapper around C.termios and keeps its semantic
|
||||||
@ -47,3 +56,13 @@ pub fn tcsetattr(fd int, optional_actions int, mut termios_p Termios) int {
|
|||||||
pub fn ioctl(fd int, request u64, arg voidptr) int {
|
pub fn ioctl(fd int, request u64, arg voidptr) int {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set_state applies the flags in the `new_state` to the descriptor `fd`.
|
||||||
|
pub fn set_state(fd int, new_state Termios) int {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable_echo disables echoing characters as they are typed,
|
||||||
|
// when that Termios state is later set with termios.set_state(fd,t)
|
||||||
|
pub fn (mut t Termios) disable_echo() {
|
||||||
|
}
|
||||||
|
@ -135,3 +135,15 @@ pub fn (t Time) strftime(fmt string) string {
|
|||||||
C.strftime(&buf[0], usize(sizeof(buf)), fmt_c, tm)
|
C.strftime(&buf[0], usize(sizeof(buf)), fmt_c, tm)
|
||||||
return unsafe { cstring_to_vstring(&char(&buf[0])) }
|
return unsafe { cstring_to_vstring(&char(&buf[0])) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// some *nix system functions (e.g. `C.poll()`, C.epoll_wait()) accept an `int`
|
||||||
|
// value as *timeout in milliseconds* with the special value `-1` meaning "infinite"
|
||||||
|
pub fn (d Duration) sys_milliseconds() int {
|
||||||
|
if d > 2147483647 * millisecond { // treat 2147483647000001 .. C.INT64_MAX as "infinite"
|
||||||
|
return -1
|
||||||
|
} else if d <= 0 {
|
||||||
|
return 0 // treat negative timeouts as 0 - consistent with Unix behaviour
|
||||||
|
} else {
|
||||||
|
return int(d / millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -88,11 +88,11 @@ fn darwin_utc() Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn solaris_now() Time {
|
fn solaris_now() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn solaris_utc() Time {
|
fn solaris_utc() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
@ -6,21 +6,21 @@ fn sys_mono_now_darwin() u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// darwin_now - dummy fn to compile on all platforms/compilers
|
// darwin_now - dummy fn to compile on all platforms/compilers
|
||||||
pub fn darwin_now() Time {
|
fn darwin_now() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// solaris_now - dummy fn to compile on all platforms/compilers
|
// solaris_now - dummy fn to compile on all platforms/compilers
|
||||||
pub fn solaris_now() Time {
|
fn solaris_now() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// darwin_utc - dummy fn to compile on all platforms/compilers
|
// darwin_utc - dummy fn to compile on all platforms/compilers
|
||||||
pub fn darwin_utc() Time {
|
fn darwin_utc() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// solaris_utc - dummy fn to compile on all platforms/compilers
|
// solaris_utc - dummy fn to compile on all platforms/compilers
|
||||||
pub fn solaris_utc() Time {
|
fn solaris_utc() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
@ -95,12 +95,12 @@ fn linux_utc() Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn win_now() Time {
|
fn win_now() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn win_utc() Time {
|
fn win_utc() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,15 +125,6 @@ pub fn (d Duration) timespec() C.timespec {
|
|||||||
return ts
|
return ts
|
||||||
}
|
}
|
||||||
|
|
||||||
// zero_timespec returns the calendar time in seconds and nanoseconds of the beginning of the Unix epoch.
|
|
||||||
pub fn zero_timespec() C.timespec {
|
|
||||||
ts := C.timespec{
|
|
||||||
tv_sec: 0
|
|
||||||
tv_nsec: 0
|
|
||||||
}
|
|
||||||
return ts
|
|
||||||
}
|
|
||||||
|
|
||||||
// sleep suspends the execution of the calling thread for a given duration (in nanoseconds).
|
// sleep suspends the execution of the calling thread for a given duration (in nanoseconds).
|
||||||
pub fn sleep(duration Duration) {
|
pub fn sleep(duration Duration) {
|
||||||
mut req := C.timespec{duration / second, duration % second}
|
mut req := C.timespec{duration / second, duration % second}
|
||||||
@ -147,15 +138,3 @@ pub fn sleep(duration Duration) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// some *nix system functions (e.g. `C.poll()`, C.epoll_wait()) accept an `int`
|
|
||||||
// value as *timeout in milliseconds* with the special value `-1` meaning "infinite"
|
|
||||||
pub fn (d Duration) sys_milliseconds() int {
|
|
||||||
if d > C.INT32_MAX * millisecond { // treat 2147483647000001 .. C.INT64_MAX as "infinite"
|
|
||||||
return -1
|
|
||||||
} else if d <= 0 {
|
|
||||||
return 0 // treat negative timeouts as 0 - consistent with Unix behaviour
|
|
||||||
} else {
|
|
||||||
return int(d / millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -22,11 +22,11 @@ fn solaris_utc() Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn darwin_now() Time {
|
fn darwin_now() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn darwin_utc() Time {
|
fn darwin_utc() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ fn win_utc() Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unix_time returns Unix time.
|
// unix_time returns Unix time.
|
||||||
pub fn (st SystemTime) unix_time() i64 {
|
fn (st SystemTime) unix_time() i64 {
|
||||||
tt := C.tm{
|
tt := C.tm{
|
||||||
tm_sec: st.second
|
tm_sec: st.second
|
||||||
tm_min: st.minute
|
tm_min: st.minute
|
||||||
@ -184,32 +184,32 @@ pub fn (st SystemTime) unix_time() i64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn darwin_now() Time {
|
fn darwin_now() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn linux_now() Time {
|
fn linux_now() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn solaris_now() Time {
|
fn solaris_now() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn darwin_utc() Time {
|
fn darwin_utc() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn linux_utc() Time {
|
fn linux_utc() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummy to compile with all compilers
|
// dummy to compile with all compilers
|
||||||
pub fn solaris_utc() Time {
|
fn solaris_utc() Time {
|
||||||
return Time{}
|
return Time{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,15 +223,3 @@ pub struct C.timeval {
|
|||||||
pub fn sleep(duration Duration) {
|
pub fn sleep(duration Duration) {
|
||||||
C.Sleep(int(duration / millisecond))
|
C.Sleep(int(duration / millisecond))
|
||||||
}
|
}
|
||||||
|
|
||||||
// some Windows system functions (e.g. `C.WaitForSingleObject()`) accept an `u32`
|
|
||||||
// value as *timeout in milliseconds* with the special value `u32(-1)` meaning "infinite"
|
|
||||||
pub fn (d Duration) sys_milliseconds() u32 {
|
|
||||||
if d >= u32(-1) * millisecond { // treat 4294967295000000 .. C.INT64_MAX as "infinite"
|
|
||||||
return u32(-1)
|
|
||||||
} else if d <= 0 {
|
|
||||||
return 0 // treat negative timeouts as 0 - consistent with Unix behaviour
|
|
||||||
} else {
|
|
||||||
return u32(d / millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -15,7 +15,7 @@ pub interface Modifier {
|
|||||||
pub type InspectorFn = fn (value &ast.Value, data voidptr) !
|
pub type InspectorFn = fn (value &ast.Value, data voidptr) !
|
||||||
|
|
||||||
struct Inspector {
|
struct Inspector {
|
||||||
inspector_callback InspectorFn
|
inspector_callback InspectorFn = unsafe { nil }
|
||||||
mut:
|
mut:
|
||||||
data voidptr
|
data voidptr
|
||||||
}
|
}
|
||||||
|
@ -381,6 +381,7 @@ pub:
|
|||||||
language Language
|
language Language
|
||||||
is_union bool
|
is_union bool
|
||||||
attrs []Attr
|
attrs []Attr
|
||||||
|
pre_comments []Comment
|
||||||
end_comments []Comment
|
end_comments []Comment
|
||||||
embeds []Embed
|
embeds []Embed
|
||||||
pub mut:
|
pub mut:
|
||||||
@ -531,10 +532,11 @@ pub:
|
|||||||
method_idx int
|
method_idx int
|
||||||
rec_mut bool // is receiver mutable
|
rec_mut bool // is receiver mutable
|
||||||
rec_share ShareType
|
rec_share ShareType
|
||||||
language Language // V, C, JS
|
language Language // V, C, JS
|
||||||
file_mode Language // whether *the file*, where a function was a '.c.v', '.js.v' etc.
|
file_mode Language // whether *the file*, where a function was a '.c.v', '.js.v' etc.
|
||||||
no_body bool // just a definition `fn C.malloc()`
|
no_body bool // just a definition `fn C.malloc()`
|
||||||
is_builtin bool // this function is defined in builtin/strconv
|
is_builtin bool // this function is defined in builtin/strconv
|
||||||
|
name_pos token.Pos
|
||||||
body_pos token.Pos // function bodys position
|
body_pos token.Pos // function bodys position
|
||||||
file string
|
file string
|
||||||
generic_names []string
|
generic_names []string
|
||||||
@ -633,7 +635,8 @@ pub:
|
|||||||
type_pos token.Pos
|
type_pos token.Pos
|
||||||
is_hidden bool // interface first arg
|
is_hidden bool // interface first arg
|
||||||
pub mut:
|
pub mut:
|
||||||
typ Type
|
typ Type
|
||||||
|
comments []Comment
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p &Param) specifier() string {
|
pub fn (p &Param) specifier() string {
|
||||||
@ -1194,6 +1197,7 @@ pub:
|
|||||||
val_var string
|
val_var string
|
||||||
is_range bool
|
is_range bool
|
||||||
pos token.Pos
|
pos token.Pos
|
||||||
|
kv_pos token.Pos
|
||||||
comments []Comment
|
comments []Comment
|
||||||
val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array
|
val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array
|
||||||
// and the array cannot be indexed inside the loop
|
// and the array cannot be indexed inside the loop
|
||||||
|
@ -59,7 +59,7 @@ pub fn (node &CallExpr) fkey() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// These methods are used only by vfmt, vdoc, and for debugging.
|
// These methods are used only by vfmt, vdoc, and for debugging.
|
||||||
pub fn (node &AnonFn) stringify_anon_decl(t &Table, cur_mod string, m2a map[string]string) string {
|
pub fn (t &Table) stringify_anon_decl(node &AnonFn, cur_mod string, m2a map[string]string) string {
|
||||||
mut f := strings.new_builder(30)
|
mut f := strings.new_builder(30)
|
||||||
f.write_string('fn ')
|
f.write_string('fn ')
|
||||||
if node.inherited_vars.len > 0 {
|
if node.inherited_vars.len > 0 {
|
||||||
@ -79,11 +79,11 @@ pub fn (node &AnonFn) stringify_anon_decl(t &Table, cur_mod string, m2a map[stri
|
|||||||
}
|
}
|
||||||
f.write_string('] ')
|
f.write_string('] ')
|
||||||
}
|
}
|
||||||
stringify_fn_after_name(node.decl, mut f, t, cur_mod, m2a)
|
t.stringify_fn_after_name(node.decl, mut f, cur_mod, m2a)
|
||||||
return f.str()
|
return f.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (node &FnDecl) stringify_fn_decl(t &Table, cur_mod string, m2a map[string]string) string {
|
pub fn (t &Table) stringify_fn_decl(node &FnDecl, cur_mod string, m2a map[string]string) string {
|
||||||
mut f := strings.new_builder(30)
|
mut f := strings.new_builder(30)
|
||||||
if node.is_pub {
|
if node.is_pub {
|
||||||
f.write_string('pub ')
|
f.write_string('pub ')
|
||||||
@ -120,11 +120,11 @@ pub fn (node &FnDecl) stringify_fn_decl(t &Table, cur_mod string, m2a map[string
|
|||||||
if name in ['+', '-', '*', '/', '%', '<', '>', '==', '!=', '>=', '<='] {
|
if name in ['+', '-', '*', '/', '%', '<', '>', '==', '!=', '>=', '<='] {
|
||||||
f.write_string(' ')
|
f.write_string(' ')
|
||||||
}
|
}
|
||||||
stringify_fn_after_name(node, mut f, t, cur_mod, m2a)
|
t.stringify_fn_after_name(node, mut f, cur_mod, m2a)
|
||||||
return f.str()
|
return f.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mod string, m2a map[string]string) {
|
fn (t &Table) stringify_fn_after_name(node &FnDecl, mut f strings.Builder, cur_mod string, m2a map[string]string) {
|
||||||
mut add_para_types := true
|
mut add_para_types := true
|
||||||
if node.generic_names.len > 0 {
|
if node.generic_names.len > 0 {
|
||||||
if node.is_method {
|
if node.is_method {
|
||||||
@ -149,27 +149,26 @@ fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
f.write_string('(')
|
f.write_string('(')
|
||||||
for i, arg in node.params {
|
for i, param in node.params {
|
||||||
// skip receiver
|
// skip receiver
|
||||||
// if (node.is_method || node.is_interface) && i == 0 {
|
|
||||||
if node.is_method && i == 0 {
|
if node.is_method && i == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if arg.is_hidden {
|
if param.is_hidden {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
is_last_arg := i == node.params.len - 1
|
is_last_param := i == node.params.len - 1
|
||||||
is_type_only := arg.name == ''
|
is_type_only := param.name == ''
|
||||||
should_add_type := true // is_last_arg || is_type_only || node.params[i + 1].typ != arg.typ ||
|
should_add_type := true // is_last_param || is_type_only || node.params[i + 1].typ != param.typ ||
|
||||||
// (node.is_variadic && i == node.params.len - 2)
|
// (node.is_variadic && i == node.params.len - 2)
|
||||||
if arg.is_mut {
|
if param.is_mut {
|
||||||
f.write_string(arg.typ.share().str() + ' ')
|
f.write_string(param.typ.share().str() + ' ')
|
||||||
}
|
}
|
||||||
f.write_string(arg.name)
|
f.write_string(param.name)
|
||||||
arg_sym := t.sym(arg.typ)
|
param_sym := t.sym(param.typ)
|
||||||
if arg_sym.kind == .struct_ && (arg_sym.info as Struct).is_anon {
|
if param_sym.kind == .struct_ && (param_sym.info as Struct).is_anon {
|
||||||
f.write_string(' struct {')
|
f.write_string(' struct {')
|
||||||
struct_ := arg_sym.info as Struct
|
struct_ := param_sym.info as Struct
|
||||||
for field in struct_.fields {
|
for field in struct_.fields {
|
||||||
f.write_string(' ${field.name} ${t.type_to_str(field.typ)}')
|
f.write_string(' ${field.name} ${t.type_to_str(field.typ)}')
|
||||||
if field.has_default_expr {
|
if field.has_default_expr {
|
||||||
@ -181,9 +180,9 @@ fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mo
|
|||||||
}
|
}
|
||||||
f.write_string('}')
|
f.write_string('}')
|
||||||
} else {
|
} else {
|
||||||
mut s := t.type_to_str(arg.typ.clear_flag(.shared_f))
|
mut s := t.type_to_str(param.typ.clear_flag(.shared_f))
|
||||||
if arg.is_mut {
|
if param.is_mut {
|
||||||
if s.starts_with('&') && ((!arg_sym.is_number() && arg_sym.kind != .bool)
|
if s.starts_with('&') && ((!param_sym.is_number() && param_sym.kind != .bool)
|
||||||
|| node.language != .v) {
|
|| node.language != .v) {
|
||||||
s = s[1..]
|
s = s[1..]
|
||||||
}
|
}
|
||||||
@ -194,13 +193,13 @@ fn stringify_fn_after_name(node &FnDecl, mut f strings.Builder, t &Table, cur_mo
|
|||||||
if !is_type_only {
|
if !is_type_only {
|
||||||
f.write_string(' ')
|
f.write_string(' ')
|
||||||
}
|
}
|
||||||
if node.is_variadic && is_last_arg {
|
if node.is_variadic && is_last_param {
|
||||||
f.write_string('...')
|
f.write_string('...')
|
||||||
}
|
}
|
||||||
f.write_string(s)
|
f.write_string(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !is_last_arg {
|
if !is_last_param {
|
||||||
f.write_string(', ')
|
f.write_string(', ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +217,7 @@ struct StringifyModReplacement {
|
|||||||
weight int
|
weight int
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shorten_full_name_based_on_aliases(input string, m2a map[string]string) string {
|
pub fn shorten_full_name_based_on_aliases(input string, m2a map[string]string) string {
|
||||||
if m2a.len == 0 || -1 == input.index_u8(`.`) {
|
if m2a.len == 0 || -1 == input.index_u8(`.`) {
|
||||||
// a simple typename, like `string` or `[]bool`; no module aliasings apply,
|
// a simple typename, like `string` or `[]bool`; no module aliasings apply,
|
||||||
// (or there just are not any mappings)
|
// (or there just are not any mappings)
|
||||||
|
@ -10,8 +10,12 @@ mut:
|
|||||||
|
|
||||||
pub type InspectorFn = fn (node &ast.Node, data voidptr) bool
|
pub type InspectorFn = fn (node &ast.Node, data voidptr) bool
|
||||||
|
|
||||||
|
fn empty_callback(node &ast.Node, data voidptr) bool {
|
||||||
|
panic('empty ast.walker')
|
||||||
|
}
|
||||||
|
|
||||||
struct Inspector {
|
struct Inspector {
|
||||||
inspector_callback InspectorFn
|
inspector_callback InspectorFn = empty_callback
|
||||||
mut:
|
mut:
|
||||||
data voidptr
|
data voidptr
|
||||||
}
|
}
|
||||||
|
@ -590,7 +590,7 @@ pub fn (mut b Builder) print_warnings_and_errors() {
|
|||||||
for stmt in file.stmts {
|
for stmt in file.stmts {
|
||||||
if stmt is ast.FnDecl {
|
if stmt is ast.FnDecl {
|
||||||
if stmt.name == fn_name {
|
if stmt.name == fn_name {
|
||||||
fheader := stmt.stringify_fn_decl(b.table, 'main', map[string]string{})
|
fheader := b.table.stringify_fn_decl(&stmt, 'main', map[string]string{})
|
||||||
redefines << FunctionRedefinition{
|
redefines << FunctionRedefinition{
|
||||||
fpath: file.path
|
fpath: file.path
|
||||||
fline: stmt.pos.line_nr
|
fline: stmt.pos.line_nr
|
||||||
|
@ -777,7 +777,7 @@ fn (mut b Builder) cc_linux_cross() {
|
|||||||
verror(res.output)
|
verror(res.output)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println(out_name + ' has been successfully compiled')
|
println(out_name + ' has been successfully cross compiled for linux.')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Builder) cc_windows_cross() {
|
fn (mut c Builder) cc_windows_cross() {
|
||||||
@ -795,10 +795,9 @@ fn (mut c Builder) cc_windows_cross() {
|
|||||||
if !c.pref.out_name.to_lower().ends_with('.exe') {
|
if !c.pref.out_name.to_lower().ends_with('.exe') {
|
||||||
c.pref.out_name += '.exe'
|
c.pref.out_name += '.exe'
|
||||||
}
|
}
|
||||||
c.pref.out_name = os.quoted_path(c.pref.out_name)
|
|
||||||
mut args := []string{}
|
mut args := []string{}
|
||||||
args << '${c.pref.cflags}'
|
args << '${c.pref.cflags}'
|
||||||
args << '-o ${c.pref.out_name}'
|
args << '-o ${os.quoted_path(c.pref.out_name)}'
|
||||||
args << '-w -L.'
|
args << '-w -L.'
|
||||||
//
|
//
|
||||||
cflags := c.get_os_cflags()
|
cflags := c.get_os_cflags()
|
||||||
@ -839,21 +838,6 @@ fn (mut c Builder) cc_windows_cross() {
|
|||||||
} else {
|
} else {
|
||||||
args << cflags.c_options_after_target()
|
args << cflags.c_options_after_target()
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
winroot := '${pref.default_module_path}/winroot'
|
|
||||||
if !os.is_dir(winroot) {
|
|
||||||
winroot_url := 'https://github.com/vlang/v/releases/download/v0.1.10/winroot.zip'
|
|
||||||
println('"$winroot" not found.')
|
|
||||||
println('Download it from $winroot_url and save it in ${pref.default_module_path}')
|
|
||||||
println('Unzip it afterwards.\n')
|
|
||||||
println('winroot.zip contains all library and header files needed ' + 'to cross-compile for Windows.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
mut obj_name := c.out_name
|
|
||||||
obj_name = obj_name.replace('.exe', '')
|
|
||||||
obj_name = obj_name.replace('.o.o', '.o')
|
|
||||||
include := '-I $winroot/include '
|
|
||||||
*/
|
|
||||||
if os.user_os() !in ['macos', 'linux', 'termux'] {
|
if os.user_os() !in ['macos', 'linux', 'termux'] {
|
||||||
println(os.user_os())
|
println(os.user_os())
|
||||||
panic('your platform is not supported yet')
|
panic('your platform is not supported yet')
|
||||||
@ -883,20 +867,7 @@ fn (mut c Builder) cc_windows_cross() {
|
|||||||
}
|
}
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
/*
|
println(c.pref.out_name + ' has been successfully cross compiled for windows.')
|
||||||
if c.pref.build_mode != .build_module {
|
|
||||||
link_cmd := 'lld-link $obj_name $winroot/lib/libcmt.lib ' + '$winroot/lib/libucrt.lib $winroot/lib/kernel32.lib $winroot/lib/libvcruntime.lib ' + '$winroot/lib/uuid.lib'
|
|
||||||
if c.pref.show_cc {
|
|
||||||
println(link_cmd)
|
|
||||||
}
|
|
||||||
if os.system(link_cmd) != 0 {
|
|
||||||
println('Cross compilation for Windows failed. Make sure you have lld linker installed.')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
// os.rm(obj_name)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
println(c.pref.out_name + ' has been successfully compiled')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut b Builder) build_thirdparty_obj_files() {
|
fn (mut b Builder) build_thirdparty_obj_files() {
|
||||||
|
@ -173,7 +173,7 @@ fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if expected.has_flag(.generic) {
|
if expected.has_flag(.generic) && !got.has_flag(.generic) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -39,46 +39,49 @@ pub const (
|
|||||||
pub struct Checker {
|
pub struct Checker {
|
||||||
pref &pref.Preferences = unsafe { nil } // Preferences shared from V struct
|
pref &pref.Preferences = unsafe { nil } // Preferences shared from V struct
|
||||||
pub mut:
|
pub mut:
|
||||||
table &ast.Table = unsafe { nil }
|
table &ast.Table = unsafe { nil }
|
||||||
file &ast.File = unsafe { nil }
|
file &ast.File = unsafe { nil }
|
||||||
nr_errors int
|
nr_errors int
|
||||||
nr_warnings int
|
nr_warnings int
|
||||||
nr_notices int
|
nr_notices int
|
||||||
errors []errors.Error
|
errors []errors.Error
|
||||||
warnings []errors.Warning
|
warnings []errors.Warning
|
||||||
notices []errors.Notice
|
notices []errors.Notice
|
||||||
error_lines []int // to avoid printing multiple errors for the same line
|
error_lines []int // to avoid printing multiple errors for the same line
|
||||||
expected_type ast.Type
|
expected_type ast.Type
|
||||||
expected_or_type ast.Type // fn() or { 'this type' } eg. string. expected or block type
|
expected_or_type ast.Type // fn() or { 'this type' } eg. string. expected or block type
|
||||||
expected_expr_type ast.Type // if/match is_expr: expected_type
|
expected_expr_type ast.Type // if/match is_expr: expected_type
|
||||||
mod string // current module name
|
mod string // current module name
|
||||||
const_var &ast.ConstField = unsafe { nil } // the current constant, when checking const declarations
|
const_var &ast.ConstField = unsafe { nil } // the current constant, when checking const declarations
|
||||||
const_deps []string
|
const_deps []string
|
||||||
const_names []string
|
const_names []string
|
||||||
global_names []string
|
global_names []string
|
||||||
locked_names []string // vars that are currently locked
|
locked_names []string // vars that are currently locked
|
||||||
rlocked_names []string // vars that are currently read-locked
|
rlocked_names []string // vars that are currently read-locked
|
||||||
in_for_count int // if checker is currently in a for loop
|
in_for_count int // if checker is currently in a for loop
|
||||||
should_abort bool // when too many errors/warnings/notices are accumulated, .should_abort becomes true. It is checked in statement/expression loops, so the checker can return early, instead of wasting time.
|
should_abort bool // when too many errors/warnings/notices are accumulated, .should_abort becomes true. It is checked in statement/expression loops, so the checker can return early, instead of wasting time.
|
||||||
returns bool
|
returns bool
|
||||||
scope_returns bool
|
scope_returns bool
|
||||||
is_builtin_mod bool // true inside the 'builtin', 'os' or 'strconv' modules; TODO: remove the need for special casing this
|
is_builtin_mod bool // true inside the 'builtin', 'os' or 'strconv' modules; TODO: remove the need for special casing this
|
||||||
is_just_builtin_mod bool // true only inside 'builtin'
|
is_just_builtin_mod bool // true only inside 'builtin'
|
||||||
is_generated bool // true for `[generated] module xyz` .v files
|
is_generated bool // true for `[generated] module xyz` .v files
|
||||||
inside_unsafe bool // true inside `unsafe {}` blocks
|
inside_unsafe bool // true inside `unsafe {}` blocks
|
||||||
inside_const bool // true inside `const ( ... )` blocks
|
inside_const bool // true inside `const ( ... )` blocks
|
||||||
inside_anon_fn bool // true inside `fn() { ... }()`
|
inside_anon_fn bool // true inside `fn() { ... }()`
|
||||||
inside_ref_lit bool // true inside `a := &something`
|
inside_ref_lit bool // true inside `a := &something`
|
||||||
inside_defer bool // true inside `defer {}` blocks
|
inside_defer bool // true inside `defer {}` blocks
|
||||||
inside_fn_arg bool // `a`, `b` in `a.f(b)`
|
inside_fn_arg bool // `a`, `b` in `a.f(b)`
|
||||||
inside_ct_attr bool // true inside `[if expr]`
|
inside_ct_attr bool // true inside `[if expr]`
|
||||||
inside_x_is_type bool // true inside the Type expression of `if x is Type {`
|
inside_x_is_type bool // true inside the Type expression of `if x is Type {`
|
||||||
inside_comptime_for_field bool
|
inside_comptime_for_field bool
|
||||||
skip_flags bool // should `#flag` and `#include` be skipped
|
inside_generic_struct_init bool
|
||||||
fn_level int // 0 for the top level, 1 for `fn abc() {}`, 2 for a nested fn, etc
|
cur_struct_generic_types []ast.Type
|
||||||
smartcast_mut_pos token.Pos // match mut foo, if mut foo is Foo
|
cur_struct_concrete_types []ast.Type
|
||||||
smartcast_cond_pos token.Pos // match cond
|
skip_flags bool // should `#flag` and `#include` be skipped
|
||||||
ct_cond_stack []ast.Expr
|
fn_level int // 0 for the top level, 1 for `fn abc() {}`, 2 for a nested fn, etc
|
||||||
|
smartcast_mut_pos token.Pos // match mut foo, if mut foo is Foo
|
||||||
|
smartcast_cond_pos token.Pos // match cond
|
||||||
|
ct_cond_stack []ast.Expr
|
||||||
mut:
|
mut:
|
||||||
stmt_level int // the nesting level inside each stmts list;
|
stmt_level int // the nesting level inside each stmts list;
|
||||||
// .stmt_level is used to check for `evaluated but not used` ExprStmts like `1 << 1`
|
// .stmt_level is used to check for `evaluated but not used` ExprStmts like `1 << 1`
|
||||||
@ -2438,11 +2441,19 @@ fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type {
|
fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type {
|
||||||
if typ.has_flag(.generic) && c.table.cur_fn != unsafe { nil } {
|
if typ.has_flag(.generic) {
|
||||||
if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_fn.generic_names,
|
if c.inside_generic_struct_init {
|
||||||
c.table.cur_concrete_types)
|
generic_names := c.cur_struct_generic_types.map(c.table.sym(it).name)
|
||||||
{
|
if t_typ := c.table.resolve_generic_to_concrete(typ, generic_names, c.cur_struct_concrete_types) {
|
||||||
return t_typ
|
return t_typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.table.cur_fn != unsafe { nil } {
|
||||||
|
if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_fn.generic_names,
|
||||||
|
c.table.cur_concrete_types)
|
||||||
|
{
|
||||||
|
return t_typ
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return typ
|
return typ
|
||||||
@ -3329,7 +3340,9 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
|||||||
if func := c.table.find_fn(node.name) {
|
if func := c.table.find_fn(node.name) {
|
||||||
if func.generic_names.len > 0 {
|
if func.generic_names.len > 0 {
|
||||||
concrete_types := node.concrete_types.map(c.unwrap_generic(it))
|
concrete_types := node.concrete_types.map(c.unwrap_generic(it))
|
||||||
c.table.register_fn_concrete_types(func.fkey(), concrete_types)
|
if concrete_types.all(!it.has_flag(.generic)) {
|
||||||
|
c.table.register_fn_concrete_types(func.fkey(), concrete_types)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return info.typ
|
return info.typ
|
||||||
@ -3493,7 +3506,9 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
|||||||
concrete_types)
|
concrete_types)
|
||||||
{
|
{
|
||||||
fn_type = typ_
|
fn_type = typ_
|
||||||
c.table.register_fn_concrete_types(func.fkey(), concrete_types)
|
if concrete_types.all(!it.has_flag(.generic)) {
|
||||||
|
c.table.register_fn_concrete_types(func.fkey(), concrete_types)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.name = name
|
node.name = name
|
||||||
|
@ -1654,6 +1654,26 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
|||||||
}
|
}
|
||||||
node.return_type = left_sym.info.return_type
|
node.return_type = left_sym.info.return_type
|
||||||
return left_sym.info.return_type
|
return left_sym.info.return_type
|
||||||
|
} else if final_left_sym.info is ast.ArrayFixed && method_name == 'wait' {
|
||||||
|
elem_sym := c.table.sym(final_left_sym.info.elem_type)
|
||||||
|
if elem_sym.kind == .thread {
|
||||||
|
if node.args.len != 0 {
|
||||||
|
c.error('`.wait()` does not have any arguments', node.args[0].pos)
|
||||||
|
}
|
||||||
|
thread_ret_type := c.unwrap_generic(elem_sym.thread_info().return_type)
|
||||||
|
if thread_ret_type.has_flag(.option) {
|
||||||
|
c.error('`.wait()` cannot be called for an array when thread functions return options. Iterate over the arrays elements instead and handle each returned option with `or`.',
|
||||||
|
node.pos)
|
||||||
|
} else if thread_ret_type.has_flag(.result) {
|
||||||
|
c.error('`.wait()` cannot be called for an array when thread functions return results. Iterate over the arrays elements instead and handle each returned result with `or`.',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
node.return_type = c.table.find_or_register_array(thread_ret_type)
|
||||||
|
return node.return_type
|
||||||
|
} else {
|
||||||
|
c.error('`${left_sym.name}` has no method `wait()` (only thread handles and arrays of them have)',
|
||||||
|
node.left.pos())
|
||||||
|
}
|
||||||
} else if left_sym.kind == .char && left_type.nr_muls() == 0 && method_name == 'str' {
|
} else if left_sym.kind == .char && left_type.nr_muls() == 0 && method_name == 'str' {
|
||||||
c.error('calling `.str()` on type `char` is not allowed, use its address or cast it to an integer instead',
|
c.error('calling `.str()` on type `char` is not allowed, use its address or cast it to an integer instead',
|
||||||
node.left.pos().extend(node.pos))
|
node.left.pos().extend(node.pos))
|
||||||
@ -2304,7 +2324,7 @@ fn (mut c Checker) check_expected_arg_count(mut node ast.CallExpr, f &ast.Fn) !
|
|||||||
has_decompose := node.args.filter(it.expr is ast.ArrayDecompose).len > 0
|
has_decompose := node.args.filter(it.expr is ast.ArrayDecompose).len > 0
|
||||||
if has_decompose {
|
if has_decompose {
|
||||||
// if call(...args) is present
|
// if call(...args) is present
|
||||||
min_required_params = nr_args
|
min_required_params = nr_args - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if min_required_params < 0 {
|
if min_required_params < 0 {
|
||||||
|
@ -70,6 +70,19 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Do not allow uninitialized `fn` fields, or force `?fn`
|
||||||
|
// (allow them in `C.` structs)
|
||||||
|
if !c.is_builtin_mod && node.language == .v {
|
||||||
|
sym := c.table.sym(field.typ)
|
||||||
|
if sym.kind == .function {
|
||||||
|
if !field.typ.has_flag(.option) && !field.has_default_expr
|
||||||
|
&& field.attrs.filter(it.name == 'required').len == 0 {
|
||||||
|
error_msg := 'uninitialized `fn` struct fields are not allowed, since they can result in segfaults; use `?fn` or initialize the field with `=` (if you absolutely want to have unsafe function pointers, use `= unsafe { nil }`)'
|
||||||
|
c.note(error_msg, field.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if field.has_default_expr {
|
if field.has_default_expr {
|
||||||
c.expected_type = field.typ
|
c.expected_type = field.typ
|
||||||
field.default_expr_typ = c.expr(mut field.default_expr)
|
field.default_expr_typ = c.expr(mut field.default_expr)
|
||||||
@ -155,6 +168,9 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
|||||||
true)
|
true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if c.table.final_sym(field.typ).kind == .function
|
||||||
|
&& field.default_expr_typ.is_pointer() {
|
||||||
|
continue
|
||||||
} else {
|
} else {
|
||||||
c.error('incompatible initializer for field `${field.name}`: ${err.msg()}',
|
c.error('incompatible initializer for field `${field.name}`: ${err.msg()}',
|
||||||
field.default_expr.pos())
|
field.default_expr.pos())
|
||||||
@ -315,6 +331,9 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct_sym := c.table.sym(node.typ)
|
struct_sym := c.table.sym(node.typ)
|
||||||
|
mut old_inside_generic_struct_init := false
|
||||||
|
mut old_cur_struct_generic_types := []ast.Type{}
|
||||||
|
mut old_cur_struct_concrete_types := []ast.Type{}
|
||||||
if struct_sym.info is ast.Struct {
|
if struct_sym.info is ast.Struct {
|
||||||
// check if the generic param types have been defined
|
// check if the generic param types have been defined
|
||||||
for ct in struct_sym.info.concrete_types {
|
for ct in struct_sym.info.concrete_types {
|
||||||
@ -352,6 +371,20 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
|||||||
c.error('a non generic struct `${node.typ_str}` used like a generic struct',
|
c.error('a non generic struct `${node.typ_str}` used like a generic struct',
|
||||||
node.name_pos)
|
node.name_pos)
|
||||||
}
|
}
|
||||||
|
if struct_sym.info.generic_types.len > 0
|
||||||
|
&& struct_sym.info.generic_types.len == struct_sym.info.concrete_types.len {
|
||||||
|
old_inside_generic_struct_init = c.inside_generic_struct_init
|
||||||
|
old_cur_struct_generic_types = c.cur_struct_generic_types.clone()
|
||||||
|
old_cur_struct_concrete_types = c.cur_struct_concrete_types.clone()
|
||||||
|
c.inside_generic_struct_init = true
|
||||||
|
c.cur_struct_generic_types = struct_sym.info.generic_types.clone()
|
||||||
|
c.cur_struct_concrete_types = struct_sym.info.concrete_types.clone()
|
||||||
|
defer {
|
||||||
|
c.inside_generic_struct_init = old_inside_generic_struct_init
|
||||||
|
c.cur_struct_generic_types = old_cur_struct_generic_types
|
||||||
|
c.cur_struct_concrete_types = old_cur_struct_concrete_types
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if struct_sym.info is ast.Alias {
|
} else if struct_sym.info is ast.Alias {
|
||||||
parent_sym := c.table.sym(struct_sym.info.parent_type)
|
parent_sym := c.table.sym(struct_sym.info.parent_type)
|
||||||
// e.g. ´x := MyMapAlias{}´, should be a cast to alias type ´x := MyMapAlias(map[...]...)´
|
// e.g. ´x := MyMapAlias{}´, should be a cast to alias type ´x := MyMapAlias(map[...]...)´
|
||||||
@ -613,10 +646,10 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
|||||||
// and the second part is all fields embedded in the structure
|
// and the second part is all fields embedded in the structure
|
||||||
// If the return value data composition form in `c.table.struct_fields()` is modified,
|
// If the return value data composition form in `c.table.struct_fields()` is modified,
|
||||||
// need to modify here accordingly.
|
// need to modify here accordingly.
|
||||||
fields := c.table.struct_fields(type_sym)
|
mut fields := c.table.struct_fields(type_sym)
|
||||||
mut checked_types := []ast.Type{}
|
mut checked_types := []ast.Type{}
|
||||||
|
|
||||||
for i, field in fields {
|
for i, mut field in fields {
|
||||||
if field.name in inited_fields {
|
if field.name in inited_fields {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -628,7 +661,7 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
|||||||
}
|
}
|
||||||
if field.has_default_expr {
|
if field.has_default_expr {
|
||||||
if i < info.fields.len && field.default_expr_typ == 0 {
|
if i < info.fields.len && field.default_expr_typ == 0 {
|
||||||
if field.default_expr is ast.StructInit {
|
if mut field.default_expr is ast.StructInit {
|
||||||
idx := c.table.find_type_idx(field.default_expr.typ_str)
|
idx := c.table.find_type_idx(field.default_expr.typ_str)
|
||||||
if idx != 0 {
|
if idx != 0 {
|
||||||
info.fields[i].default_expr_typ = ast.new_type(idx)
|
info.fields[i].default_expr_typ = ast.new_type(idx)
|
||||||
@ -637,6 +670,9 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
|||||||
if field.typ.is_any_kind_of_pointer() {
|
if field.typ.is_any_kind_of_pointer() {
|
||||||
info.fields[i].default_expr_typ = field.typ
|
info.fields[i].default_expr_typ = field.typ
|
||||||
}
|
}
|
||||||
|
} else if field.default_expr is ast.Ident
|
||||||
|
&& field.default_expr.info is ast.IdentFn {
|
||||||
|
c.expr(mut field.default_expr)
|
||||||
} else {
|
} else {
|
||||||
if const_field := c.table.global_scope.find_const('${field.default_expr}') {
|
if const_field := c.table.global_scope.find_const('${field.default_expr}') {
|
||||||
info.fields[i].default_expr_typ = const_field.typ
|
info.fields[i].default_expr_typ = const_field.typ
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
struct St{
|
struct St {
|
||||||
attr fn()
|
attr fn () = unsafe { nil }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (s St) attr() {}
|
fn (s St) attr() {}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
vlib/v/checker/tests/fn_array_decompose_arg_mismatch_err_c.vv:2:6: error: expected 0 arguments, but got 1
|
||||||
|
1 | fn main() {
|
||||||
|
2 | foo(...args)
|
||||||
|
| ~~~~~~~
|
||||||
|
3 | }
|
||||||
|
4 |
|
@ -0,0 +1,6 @@
|
|||||||
|
fn main() {
|
||||||
|
foo(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() {
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user