all: require calling `optfn() ?` / `optfn() or {...}` for `fn optfn() ? {}`
parent
97103f680a
commit
e5a84719ca
|
@ -70,7 +70,8 @@ fn main() {
|
||||||
date := time.unix(commit_date.int())
|
date := time.unix(commit_date.int())
|
||||||
mut out := os.create('table.html') ?
|
mut out := os.create('table.html') ?
|
||||||
// Place the new row on top
|
// Place the new row on top
|
||||||
table = '<tr>
|
table =
|
||||||
|
'<tr>
|
||||||
<td>$date.format()</td>
|
<td>$date.format()</td>
|
||||||
<td><a target=_blank href="https://github.com/vlang/v/commit/$commit">$commit</a></td>
|
<td><a target=_blank href="https://github.com/vlang/v/commit/$commit">$commit</a></td>
|
||||||
<td>$message</td>
|
<td>$message</td>
|
||||||
|
@ -80,15 +81,15 @@ fn main() {
|
||||||
<td>${diff4}ms</td>
|
<td>${diff4}ms</td>
|
||||||
</tr>\n' +
|
</tr>\n' +
|
||||||
table.trim_space()
|
table.trim_space()
|
||||||
out.writeln(table)
|
out.writeln(table) ?
|
||||||
out.close()
|
out.close()
|
||||||
// Regenerate index.html
|
// Regenerate index.html
|
||||||
header := os.read_file('header.html') ?
|
header := os.read_file('header.html') ?
|
||||||
footer := os.read_file('footer.html') ?
|
footer := os.read_file('footer.html') ?
|
||||||
mut res := os.create('index.html') ?
|
mut res := os.create('index.html') ?
|
||||||
res.writeln(header)
|
res.writeln(header) ?
|
||||||
res.writeln(table)
|
res.writeln(table) ?
|
||||||
res.writeln(footer)
|
res.writeln(footer) ?
|
||||||
res.close()
|
res.close()
|
||||||
}
|
}
|
||||||
exec('git checkout master')
|
exec('git checkout master')
|
||||||
|
@ -96,9 +97,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec(s string) string {
|
fn exec(s string) string {
|
||||||
e := os.exec(s) or {
|
e := os.exec(s) or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return e.output.trim_right('\r\n')
|
return e.output.trim_right('\r\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,21 +12,20 @@ pub fn set_verbose(on bool) {
|
||||||
// but V does not have globals normally.
|
// but V does not have globals normally.
|
||||||
if on {
|
if on {
|
||||||
os.setenv('VERBOSE', '1', true)
|
os.setenv('VERBOSE', '1', true)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
os.unsetenv('VERBOSE')
|
os.unsetenv('VERBOSE')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cprintln(message string) {
|
pub fn cprintln(message string) {
|
||||||
mut omessage := message
|
mut omessage := message
|
||||||
omessage = if term_colors { term.green(omessage) } else { omessage }
|
omessage = if scripting.term_colors { term.green(omessage) } else { omessage }
|
||||||
println(omessage)
|
println(omessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verbose_trace(label string, message string) {
|
pub fn verbose_trace(label string, message string) {
|
||||||
if os.getenv('VERBOSE').len > 0 {
|
if os.getenv('VERBOSE').len > 0 {
|
||||||
slabel := 'scripting.${label}'
|
slabel := 'scripting.$label'
|
||||||
cprintln('# ${slabel:-25s} : $message')
|
cprintln('# ${slabel:-25s} : $message')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,9 +53,9 @@ pub fn rmrf(path string) {
|
||||||
verbose_trace(@FN, 'rm -rf $path')
|
verbose_trace(@FN, 'rm -rf $path')
|
||||||
if os.exists(path) {
|
if os.exists(path) {
|
||||||
if os.is_dir(path) {
|
if os.is_dir(path) {
|
||||||
os.rmdir_all(path)
|
os.rmdir_all(path) or { panic(err) }
|
||||||
} else {
|
} else {
|
||||||
os.rm(path)
|
os.rm(path) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,7 +210,7 @@ pub fn (mut ts TestSession) test() {
|
||||||
// cleanup generated .tmp.c files after successfull tests:
|
// cleanup generated .tmp.c files after successfull tests:
|
||||||
if ts.benchmark.nfail == 0 {
|
if ts.benchmark.nfail == 0 {
|
||||||
if ts.rm_binaries {
|
if ts.rm_binaries {
|
||||||
os.rmdir_all(ts.vtmp_dir)
|
os.rmdir_all(ts.vtmp_dir) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ fn worker_trunner(mut p sync.PoolProcessor, idx int, thread_id int) voidptr {
|
||||||
generated_binary_fpath := os.join_path(tmpd, generated_binary_fname)
|
generated_binary_fpath := os.join_path(tmpd, generated_binary_fname)
|
||||||
if os.exists(generated_binary_fpath) {
|
if os.exists(generated_binary_fpath) {
|
||||||
if ts.rm_binaries {
|
if ts.rm_binaries {
|
||||||
os.rm(generated_binary_fpath)
|
os.rm(generated_binary_fpath) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut cmd_options := [ts.vargs]
|
mut cmd_options := [ts.vargs]
|
||||||
|
@ -294,7 +294,7 @@ fn worker_trunner(mut p sync.PoolProcessor, idx int, thread_id int) voidptr {
|
||||||
}
|
}
|
||||||
if os.exists(generated_binary_fpath) {
|
if os.exists(generated_binary_fpath) {
|
||||||
if ts.rm_binaries {
|
if ts.rm_binaries {
|
||||||
os.rm(generated_binary_fpath)
|
os.rm(generated_binary_fpath) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sync.no_result
|
return sync.no_result
|
||||||
|
@ -422,7 +422,7 @@ pub fn header(msg string) {
|
||||||
pub fn setup_new_vtmp_folder() string {
|
pub fn setup_new_vtmp_folder() string {
|
||||||
now := time.sys_mono_now()
|
now := time.sys_mono_now()
|
||||||
new_vtmp_dir := os.join_path(os.temp_dir(), 'v', 'test_session_$now')
|
new_vtmp_dir := os.join_path(os.temp_dir(), 'v', 'test_session_$now')
|
||||||
os.mkdir_all(new_vtmp_dir)
|
os.mkdir_all(new_vtmp_dir) or { panic(err) }
|
||||||
os.setenv('VTMP', new_vtmp_dir, true)
|
os.setenv('VTMP', new_vtmp_dir, true)
|
||||||
return new_vtmp_dir
|
return new_vtmp_dir
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,26 +28,26 @@ fn get_vexe_path() string {
|
||||||
fn new_tdir() string {
|
fn new_tdir() string {
|
||||||
tdir_ := os.join_path(os.temp_dir(), rand.ulid())
|
tdir_ := os.join_path(os.temp_dir(), rand.ulid())
|
||||||
if os.exists(tdir_) {
|
if os.exists(tdir_) {
|
||||||
os.rmdir(tdir_)
|
os.rmdir(tdir_) or { panic(err) }
|
||||||
}
|
}
|
||||||
os.mkdir(tdir_)
|
os.mkdir(tdir_) or { panic(err) }
|
||||||
C.atexit(cleanup_tdir)
|
C.atexit(cleanup_tdir)
|
||||||
return tdir_
|
return tdir_
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cleanup_tdir() {
|
fn cleanup_tdir() {
|
||||||
println('... removing tdir: $tdir')
|
println('... removing tdir: $tdir')
|
||||||
os.rmdir_all(tdir)
|
os.rmdir_all(tdir) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println('> vroot: $vroot | vexe: $vexe | tdir: $tdir')
|
println('> vroot: $vroot | vexe: $vexe | tdir: $tdir')
|
||||||
ok_fpath := os.join_path(tdir, 'single_test.v')
|
ok_fpath := os.join_path(tdir, 'single_test.v')
|
||||||
os.write_file(ok_fpath, 'fn test_ok(){ assert true }')
|
os.write_file(ok_fpath, 'fn test_ok(){ assert true }') ?
|
||||||
check_ok('"$vexe" $ok_fpath')
|
check_ok('"$vexe" $ok_fpath')
|
||||||
check_ok('"$vexe" test $ok_fpath')
|
check_ok('"$vexe" test $ok_fpath')
|
||||||
fail_fpath := os.join_path(tdir, 'failing_test.v')
|
fail_fpath := os.join_path(tdir, 'failing_test.v')
|
||||||
os.write_file(fail_fpath, 'fn test_fail(){ assert 1 == 2 }')
|
os.write_file(fail_fpath, 'fn test_fail(){ assert 1 == 2 }') ?
|
||||||
check_fail('"$vexe" $fail_fpath')
|
check_fail('"$vexe" $fail_fpath')
|
||||||
check_fail('"$vexe" test $fail_fpath')
|
check_fail('"$vexe" test $fail_fpath')
|
||||||
check_fail('"$vexe" test $tdir')
|
check_fail('"$vexe" test $tdir')
|
||||||
|
|
|
@ -68,7 +68,6 @@ fn (context Context) file2v(bname string, fbytes []byte, bn_max int) string {
|
||||||
sb.write('$b, ')
|
sb.write('$b, ')
|
||||||
line_len += b.len + 2
|
line_len += b.len + 2
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
sb.write(']!\n')
|
sb.write(']!\n')
|
||||||
return sb.str()
|
return sb.str()
|
||||||
|
@ -76,8 +75,8 @@ fn (context Context) file2v(bname string, fbytes []byte, bn_max int) string {
|
||||||
|
|
||||||
fn (context Context) bname_and_bytes(file string) ?(string, []byte) {
|
fn (context Context) bname_and_bytes(file string) ?(string, []byte) {
|
||||||
fname := os.file_name(file)
|
fname := os.file_name(file)
|
||||||
fname_escpaed := fname.replace_each(['.', '_', '-', '_'])
|
fname_escaped := fname.replace_each(['.', '_', '-', '_'])
|
||||||
byte_name := '$context.prefix$fname_escpaed'.to_lower()
|
byte_name := '$context.prefix$fname_escaped'.to_lower()
|
||||||
fbytes := os.read_bytes(file) or { return error('Error: $err') }
|
fbytes := os.read_bytes(file) or { return error('Error: $err') }
|
||||||
return byte_name, fbytes
|
return byte_name, fbytes
|
||||||
}
|
}
|
||||||
|
@ -131,12 +130,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
max_bname := context.max_bname_len(file_byte_map.keys())
|
max_bname := context.max_bname_len(file_byte_map.keys())
|
||||||
if context.write_file.len > 0 {
|
if context.write_file.len > 0 {
|
||||||
mut out_file := os.create(context.write_file) or { panic(err) }
|
mut out_file := os.create(context.write_file) ?
|
||||||
out_file.write_str(context.header())
|
out_file.write_str(context.header()) ?
|
||||||
for bname, fbytes in file_byte_map {
|
for bname, fbytes in file_byte_map {
|
||||||
out_file.write_str(context.file2v(bname, fbytes, max_bname))
|
out_file.write_str(context.file2v(bname, fbytes, max_bname)) ?
|
||||||
}
|
}
|
||||||
out_file.write_str(context.footer())
|
out_file.write_str(context.footer()) ?
|
||||||
} else {
|
} else {
|
||||||
print(context.header())
|
print(context.header())
|
||||||
for bname, fbytes in file_byte_map {
|
for bname, fbytes in file_byte_map {
|
||||||
|
|
|
@ -55,9 +55,14 @@ fn main() {
|
||||||
//
|
//
|
||||||
tpath := os.join_path(session.vtmp_dir, texe)
|
tpath := os.join_path(session.vtmp_dir, texe)
|
||||||
if tname in tools_in_subfolders {
|
if tname in tools_in_subfolders {
|
||||||
os.mv_by_cp(tpath, os.join_path(tfolder, tname, texe))
|
os.mv_by_cp(tpath, os.join_path(tfolder, tname, texe)) or { panic(err) }
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
os.mv_by_cp(tpath, os.join_path(tfolder, texe)) or {
|
||||||
|
if !err.contains('vbuild-tools') {
|
||||||
|
eprintln(err)
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
os.mv_by_cp(tpath, os.join_path(tfolder, texe))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ fn (c &Create) write_vmod(new bool) {
|
||||||
cerror(err)
|
cerror(err)
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
vmod.write_str(vmod_content(c.name, c.description))
|
vmod.write_str(vmod_content(c.name, c.description)) or { panic(err) }
|
||||||
vmod.close()
|
vmod.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +67,12 @@ fn (c &Create) write_main(new bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
main_path := if new { '$c.name/${c.name}.v' } else { '${c.name}.v' }
|
main_path := if new { '$c.name/${c.name}.v' } else { '${c.name}.v' }
|
||||||
mut main := os.create(main_path) or {
|
mut mainfile := os.create(main_path) or {
|
||||||
cerror(err)
|
cerror(err)
|
||||||
exit(2)
|
exit(2)
|
||||||
}
|
}
|
||||||
main.write_str(main_content())
|
mainfile.write_str(main_content()) or { panic(err) }
|
||||||
main.close()
|
mainfile.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (c &Create) create_git_repo(dir string) {
|
fn (c &Create) create_git_repo(dir string) {
|
||||||
|
@ -87,7 +87,7 @@ fn (c &Create) create_git_repo(dir string) {
|
||||||
// We don't really need a .gitignore, it's just a nice-to-have
|
// We don't really need a .gitignore, it's just a nice-to-have
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fl.write_str(gen_gitignore(c.name))
|
fl.write_str(gen_gitignore(c.name)) or { panic(err) }
|
||||||
fl.close()
|
fl.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,9 +110,7 @@ fn create() {
|
||||||
}
|
}
|
||||||
c.description = os.input('Input your project description: ')
|
c.description = os.input('Input your project description: ')
|
||||||
println('Initialising ...')
|
println('Initialising ...')
|
||||||
os.mkdir(c.name) or {
|
os.mkdir(c.name) or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
c.write_vmod(true)
|
c.write_vmod(true)
|
||||||
c.write_main(true)
|
c.write_main(true)
|
||||||
c.create_git_repo(c.name)
|
c.create_git_repo(c.name)
|
||||||
|
|
|
@ -126,7 +126,7 @@ fn (vd VDoc) render_search_index(out Output) {
|
||||||
js_search_index.writeln('];')
|
js_search_index.writeln('];')
|
||||||
js_search_data.writeln('];')
|
js_search_data.writeln('];')
|
||||||
out_file_path := os.join_path(out.path, 'search_index.js')
|
out_file_path := os.join_path(out.path, 'search_index.js')
|
||||||
os.write_file(out_file_path, js_search_index.str() + js_search_data.str())
|
os.write_file(out_file_path, js_search_index.str() + js_search_data.str()) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut vd VDoc) render_static_html(out Output) {
|
fn (mut vd VDoc) render_static_html(out Output) {
|
||||||
|
@ -162,7 +162,7 @@ fn (vd VDoc) get_resource(name string, out Output) string {
|
||||||
output_path := os.join_path(out.path, name)
|
output_path := os.join_path(out.path, name)
|
||||||
if !os.exists(output_path) {
|
if !os.exists(output_path) {
|
||||||
println('Generating $out.typ in "$output_path"')
|
println('Generating $out.typ in "$output_path"')
|
||||||
os.write_file(output_path, res)
|
os.write_file(output_path, res) or { panic(err) }
|
||||||
}
|
}
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,7 @@ fn (vd VDoc) work_processor(mut work sync.Channel, mut wg sync.WaitGroup) {
|
||||||
file_name, content := vd.render_doc(pdoc.d, pdoc.out)
|
file_name, content := vd.render_doc(pdoc.d, pdoc.out)
|
||||||
output_path := os.join_path(pdoc.out.path, file_name)
|
output_path := os.join_path(pdoc.out.path, file_name)
|
||||||
println('Generating $pdoc.out.typ in "$output_path"')
|
println('Generating $pdoc.out.typ in "$output_path"')
|
||||||
os.write_file(output_path, content)
|
os.write_file(output_path, content) or { panic(err) }
|
||||||
}
|
}
|
||||||
wg.done()
|
wg.done()
|
||||||
}
|
}
|
||||||
|
@ -358,7 +358,7 @@ fn (mut vd VDoc) generate_docs_from_file() {
|
||||||
os.mkdir(out.path) or { panic(err) }
|
os.mkdir(out.path) or { panic(err) }
|
||||||
} else {
|
} else {
|
||||||
for fname in css_js_assets {
|
for fname in css_js_assets {
|
||||||
os.rm(os.join_path(out.path, fname))
|
os.rm(os.join_path(out.path, fname)) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,7 +376,7 @@ fn (mut vd VDoc) generate_docs_from_file() {
|
||||||
for favicon in favicons {
|
for favicon in favicons {
|
||||||
favicon_path := os.join_path(favicons_path, favicon)
|
favicon_path := os.join_path(favicons_path, favicon)
|
||||||
destination_path := os.join_path(out.path, favicon)
|
destination_path := os.join_path(out.path, favicon)
|
||||||
os.cp(favicon_path, destination_path)
|
os.cp(favicon_path, destination_path) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,7 @@ fn (foptions &FormatOptions) format_file(file string) {
|
||||||
file_name := os.file_name(file)
|
file_name := os.file_name(file)
|
||||||
ulid := rand.ulid()
|
ulid := rand.ulid()
|
||||||
vfmt_output_path := os.join_path(vtmp_folder, 'vfmt_${ulid}_$file_name')
|
vfmt_output_path := os.join_path(vtmp_folder, 'vfmt_${ulid}_$file_name')
|
||||||
os.write_file(vfmt_output_path, formatted_content)
|
os.write_file(vfmt_output_path, formatted_content) or { panic(err) }
|
||||||
if foptions.is_verbose {
|
if foptions.is_verbose {
|
||||||
eprintln('fmt.fmt worked and $formatted_content.len bytes were written to $vfmt_output_path .')
|
eprintln('fmt.fmt worked and $formatted_content.len bytes were written to $vfmt_output_path .')
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,8 @@ fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (f FormatOptions) str() string {
|
fn (f FormatOptions) str() string {
|
||||||
return 'FormatOptions{ is_l: $f.is_l, is_w: $f.is_w, is_diff: $f.is_diff, is_verbose: $f.is_verbose,' +
|
return
|
||||||
|
'FormatOptions{ is_l: $f.is_l, is_w: $f.is_w, is_diff: $f.is_diff, is_verbose: $f.is_verbose,' +
|
||||||
' is_all: $f.is_all, is_worker: $f.is_worker, is_debug: $f.is_debug, is_noerror: $f.is_noerror,' +
|
' is_all: $f.is_all, is_worker: $f.is_worker, is_debug: $f.is_debug, is_noerror: $f.is_noerror,' +
|
||||||
' is_verify: $f.is_verify" }'
|
' is_verify: $f.is_verify" }'
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,9 +71,7 @@ fn main() {
|
||||||
'install' {
|
'install' {
|
||||||
if module_names.len == 0 && os.exists('./v.mod') {
|
if module_names.len == 0 && os.exists('./v.mod') {
|
||||||
println('Detected v.mod file inside the project directory. Using it...')
|
println('Detected v.mod file inside the project directory. Using it...')
|
||||||
manifest := vmod.from_file('./v.mod') or {
|
manifest := vmod.from_file('./v.mod') or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
module_names = manifest.dependencies
|
module_names = manifest.dependencies
|
||||||
}
|
}
|
||||||
vpm_install(module_names)
|
vpm_install(module_names)
|
||||||
|
@ -227,15 +225,11 @@ fn vpm_update(m []string) {
|
||||||
}
|
}
|
||||||
mut errors := 0
|
mut errors := 0
|
||||||
for name in module_names {
|
for name in module_names {
|
||||||
final_module_path := valid_final_path_of_existing_module(name) or {
|
final_module_path := valid_final_path_of_existing_module(name) or { continue }
|
||||||
continue
|
|
||||||
}
|
|
||||||
os.chdir(final_module_path)
|
os.chdir(final_module_path)
|
||||||
println('Updating module "$name"...')
|
println('Updating module "$name"...')
|
||||||
verbose_println(' work folder: $final_module_path')
|
verbose_println(' work folder: $final_module_path')
|
||||||
vcs := vcs_used_in_dir(final_module_path) or {
|
vcs := vcs_used_in_dir(final_module_path) or { continue }
|
||||||
continue
|
|
||||||
}
|
|
||||||
vcs_cmd := supported_vcs_update_cmds[vcs[0]]
|
vcs_cmd := supported_vcs_update_cmds[vcs[0]]
|
||||||
verbose_println(' command: $vcs_cmd')
|
verbose_println(' command: $vcs_cmd')
|
||||||
vcs_res := os.exec('$vcs_cmd') or {
|
vcs_res := os.exec('$vcs_cmd') or {
|
||||||
|
@ -265,13 +259,9 @@ fn get_outdated() ?[]string {
|
||||||
module_names := get_installed_modules()
|
module_names := get_installed_modules()
|
||||||
mut outdated := []string{}
|
mut outdated := []string{}
|
||||||
for name in module_names {
|
for name in module_names {
|
||||||
final_module_path := valid_final_path_of_existing_module(name) or {
|
final_module_path := valid_final_path_of_existing_module(name) or { continue }
|
||||||
continue
|
|
||||||
}
|
|
||||||
os.chdir(final_module_path)
|
os.chdir(final_module_path)
|
||||||
vcs := vcs_used_in_dir(final_module_path) or {
|
vcs := vcs_used_in_dir(final_module_path) or { continue }
|
||||||
continue
|
|
||||||
}
|
|
||||||
vcs_cmd_steps := supported_vcs_outdated_steps[vcs[0]]
|
vcs_cmd_steps := supported_vcs_outdated_steps[vcs[0]]
|
||||||
mut outputs := []string{}
|
mut outputs := []string{}
|
||||||
for step in vcs_cmd_steps {
|
for step in vcs_cmd_steps {
|
||||||
|
@ -296,9 +286,7 @@ fn get_outdated() ?[]string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vpm_upgrade() {
|
fn vpm_upgrade() {
|
||||||
outdated := get_outdated() or {
|
outdated := get_outdated() or { exit(1) }
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
if outdated.len > 0 {
|
if outdated.len > 0 {
|
||||||
vpm_update(outdated)
|
vpm_update(outdated)
|
||||||
} else {
|
} else {
|
||||||
|
@ -307,9 +295,7 @@ fn vpm_upgrade() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vpm_outdated() {
|
fn vpm_outdated() {
|
||||||
outdated := get_outdated() or {
|
outdated := get_outdated() or { exit(1) }
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
if outdated.len > 0 {
|
if outdated.len > 0 {
|
||||||
println('Outdated modules:')
|
println('Outdated modules:')
|
||||||
for m in outdated {
|
for m in outdated {
|
||||||
|
@ -342,18 +328,16 @@ fn vpm_remove(module_names []string) {
|
||||||
exit(2)
|
exit(2)
|
||||||
}
|
}
|
||||||
for name in module_names {
|
for name in module_names {
|
||||||
final_module_path := valid_final_path_of_existing_module(name) or {
|
final_module_path := valid_final_path_of_existing_module(name) or { continue }
|
||||||
continue
|
|
||||||
}
|
|
||||||
println('Removing module "$name"...')
|
println('Removing module "$name"...')
|
||||||
verbose_println('removing folder $final_module_path')
|
verbose_println('removing folder $final_module_path')
|
||||||
os.rmdir_all(final_module_path)
|
os.rmdir_all(final_module_path) or { panic(err) }
|
||||||
// delete author directory if it is empty
|
// delete author directory if it is empty
|
||||||
author := name.split('.')[0]
|
author := name.split('.')[0]
|
||||||
author_dir := os.real_path(os.join_path(settings.vmodules_path, author))
|
author_dir := os.real_path(os.join_path(settings.vmodules_path, author))
|
||||||
if os.is_dir_empty(author_dir) {
|
if os.is_dir_empty(author_dir) {
|
||||||
verbose_println('removing author folder $author_dir')
|
verbose_println('removing author folder $author_dir')
|
||||||
os.rmdir(author_dir)
|
os.rmdir(author_dir) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,9 +364,7 @@ fn valid_final_path_of_existing_module(name string) ?string {
|
||||||
fn ensure_vmodules_dir_exist() {
|
fn ensure_vmodules_dir_exist() {
|
||||||
if !os.is_dir(settings.vmodules_path) {
|
if !os.is_dir(settings.vmodules_path) {
|
||||||
println('Creating $settings.vmodules_path/ ...')
|
println('Creating $settings.vmodules_path/ ...')
|
||||||
os.mkdir(settings.vmodules_path) or {
|
os.mkdir(settings.vmodules_path) or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,9 +387,7 @@ fn vcs_used_in_dir(dir string) ?[]string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_installed_modules() []string {
|
fn get_installed_modules() []string {
|
||||||
dirs := os.ls(settings.vmodules_path) or {
|
dirs := os.ls(settings.vmodules_path) or { return [] }
|
||||||
return []
|
|
||||||
}
|
|
||||||
mut modules := []string{}
|
mut modules := []string{}
|
||||||
for dir in dirs {
|
for dir in dirs {
|
||||||
adir := os.join_path(settings.vmodules_path, dir)
|
adir := os.join_path(settings.vmodules_path, dir)
|
||||||
|
@ -420,13 +400,9 @@ fn get_installed_modules() []string {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
author := dir
|
author := dir
|
||||||
mods := os.ls(adir) or {
|
mods := os.ls(adir) or { continue }
|
||||||
continue
|
|
||||||
}
|
|
||||||
for m in mods {
|
for m in mods {
|
||||||
vcs_used_in_dir(os.join_path(adir, m)) or {
|
vcs_used_in_dir(os.join_path(adir, m)) or { continue }
|
||||||
continue
|
|
||||||
}
|
|
||||||
modules << '${author}.$m'
|
modules << '${author}.$m'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -435,9 +411,7 @@ fn get_installed_modules() []string {
|
||||||
|
|
||||||
fn get_all_modules() []string {
|
fn get_all_modules() []string {
|
||||||
url := get_working_server_url()
|
url := get_working_server_url()
|
||||||
r := http.get(url) or {
|
r := http.get(url) or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if r.status_code != 200 {
|
if r.status_code != 200 {
|
||||||
println('Failed to search vpm.vlang.io. Status code: $r.status_code')
|
println('Failed to search vpm.vlang.io. Status code: $r.status_code')
|
||||||
exit(1)
|
exit(1)
|
||||||
|
@ -476,9 +450,7 @@ fn resolve_dependencies(name string, module_path string, module_names []string)
|
||||||
if !os.exists(vmod_path) {
|
if !os.exists(vmod_path) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data := os.read_file(vmod_path) or {
|
data := os.read_file(vmod_path) or { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
vmod := parse_vmod(data)
|
vmod := parse_vmod(data)
|
||||||
mut deps := []string{}
|
mut deps := []string{}
|
||||||
// filter out dependencies that were already specified by the user
|
// filter out dependencies that were already specified by the user
|
||||||
|
@ -502,9 +474,7 @@ fn parse_vmod(data string) Vmod {
|
||||||
'deps': ''
|
'deps': ''
|
||||||
}
|
}
|
||||||
for key in keys {
|
for key in keys {
|
||||||
mut key_index := data.index('$key:') or {
|
mut key_index := data.index('$key:') or { continue }
|
||||||
continue
|
|
||||||
}
|
|
||||||
key_index += key.len + 1
|
key_index += key.len + 1
|
||||||
m[key] = data[key_index..data.index_after('\n', key_index)].trim_space().replace("'",
|
m[key] = data[key_index..data.index_after('\n', key_index)].trim_space().replace("'",
|
||||||
'').replace('[', '').replace(']', '')
|
'').replace('[', '').replace(']', '')
|
||||||
|
@ -519,7 +489,11 @@ fn parse_vmod(data string) Vmod {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_working_server_url() string {
|
fn get_working_server_url() string {
|
||||||
server_urls := if settings.server_urls.len > 0 { settings.server_urls } else { default_vpm_server_urls }
|
server_urls := if settings.server_urls.len > 0 {
|
||||||
|
settings.server_urls
|
||||||
|
} else {
|
||||||
|
default_vpm_server_urls
|
||||||
|
}
|
||||||
for url in server_urls {
|
for url in server_urls {
|
||||||
verbose_println('Trying server url: $url')
|
verbose_println('Trying server url: $url')
|
||||||
http.head(url) or {
|
http.head(url) or {
|
||||||
|
@ -572,13 +546,11 @@ fn get_module_meta_info(name string) ?Mod {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if r.status_code == 404 || r.text.contains('404') {
|
if r.status_code == 404 || r.text.contains('404') {
|
||||||
errors <<
|
errors << 'Skipping module "$name", since $server_url reported that "$name" does not exist.'
|
||||||
'Skipping module "$name", since $server_url reported that "$name" does not exist.'
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if r.status_code != 200 {
|
if r.status_code != 200 {
|
||||||
errors <<
|
errors << 'Skipping module "$name", since $server_url responded with $r.status_code http status code. Please try again later.'
|
||||||
'Skipping module "$name", since $server_url responded with $r.status_code http status code. Please try again later.'
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s := r.text
|
s := r.text
|
||||||
|
|
|
@ -109,21 +109,7 @@ fn run_repl(workdir string, vrepl_prefix string) {
|
||||||
if !is_stdin_a_pipe {
|
if !is_stdin_a_pipe {
|
||||||
println('')
|
println('')
|
||||||
}
|
}
|
||||||
os.rm(file)
|
cleanup_files([file, temp_file])
|
||||||
os.rm(temp_file)
|
|
||||||
$if windows {
|
|
||||||
os.rm(file[..file.len - 2] + '.exe')
|
|
||||||
os.rm(temp_file[..temp_file.len - 2] + '.exe')
|
|
||||||
$if msvc {
|
|
||||||
os.rm(file[..file.len - 2] + '.ilk')
|
|
||||||
os.rm(file[..file.len - 2] + '.pdb')
|
|
||||||
os.rm(temp_file[..temp_file.len - 2] + '.ilk')
|
|
||||||
os.rm(temp_file[..temp_file.len - 2] + '.pdb')
|
|
||||||
}
|
|
||||||
} $else {
|
|
||||||
os.rm(file[..file.len - 2])
|
|
||||||
os.rm(temp_file[..temp_file.len - 2])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mut r := new_repl()
|
mut r := new_repl()
|
||||||
vexe := os.getenv('VEXE')
|
vexe := os.getenv('VEXE')
|
||||||
|
@ -198,7 +184,7 @@ fn run_repl(workdir string, vrepl_prefix string) {
|
||||||
}
|
}
|
||||||
if r.line.starts_with('print') {
|
if r.line.starts_with('print') {
|
||||||
source_code := r.current_source_code(false) + '\n$r.line\n'
|
source_code := r.current_source_code(false) + '\n$r.line\n'
|
||||||
os.write_file(file, source_code)
|
os.write_file(file, source_code) or { panic(err) }
|
||||||
s := os.exec('"$vexe" -repl run "$file"') or {
|
s := os.exec('"$vexe" -repl run "$file"') or {
|
||||||
rerror(err)
|
rerror(err)
|
||||||
return
|
return
|
||||||
|
@ -208,7 +194,7 @@ fn run_repl(workdir string, vrepl_prefix string) {
|
||||||
mut temp_line := r.line
|
mut temp_line := r.line
|
||||||
mut temp_flag := false
|
mut temp_flag := false
|
||||||
func_call := r.function_call(r.line)
|
func_call := r.function_call(r.line)
|
||||||
filter_line := r.line.replace(r.line.find_between("\'", "\'"), '').replace(r.line.find_between('"',
|
filter_line := r.line.replace(r.line.find_between("'", "'"), '').replace(r.line.find_between('"',
|
||||||
'"'), '')
|
'"'), '')
|
||||||
possible_statement_patterns := [
|
possible_statement_patterns := [
|
||||||
'=',
|
'=',
|
||||||
|
@ -268,7 +254,7 @@ fn run_repl(workdir string, vrepl_prefix string) {
|
||||||
}
|
}
|
||||||
temp_source_code = r.current_source_code(true) + '\n$temp_line\n'
|
temp_source_code = r.current_source_code(true) + '\n$temp_line\n'
|
||||||
}
|
}
|
||||||
os.write_file(temp_file, temp_source_code)
|
os.write_file(temp_file, temp_source_code) or { panic(err) }
|
||||||
s := os.exec('"$vexe" -repl run "$temp_file"') or {
|
s := os.exec('"$vexe" -repl run "$temp_file"') or {
|
||||||
rerror(err)
|
rerror(err)
|
||||||
return
|
return
|
||||||
|
@ -355,3 +341,18 @@ fn (mut r Repl) get_one_line(prompt string) ?string {
|
||||||
rline := r.readline.read_line(prompt) or { return none }
|
rline := r.readline.read_line(prompt) or { return none }
|
||||||
return rline
|
return rline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cleanup_files(files []string) {
|
||||||
|
for file in files {
|
||||||
|
os.rm(file) or { }
|
||||||
|
$if windows {
|
||||||
|
os.rm(file[..file.len - 2] + '.exe') or { }
|
||||||
|
$if msvc {
|
||||||
|
os.rm(file[..file.len - 2] + '.ilk') or { }
|
||||||
|
os.rm(file[..file.len - 2] + '.pdb') or { }
|
||||||
|
}
|
||||||
|
} $else {
|
||||||
|
os.rm(file[..file.len - 2]) or { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import v.pref
|
||||||
$if windows {
|
$if windows {
|
||||||
$if tinyc {
|
$if tinyc {
|
||||||
#flag -lAdvapi32
|
#flag -lAdvapi32
|
||||||
|
|
||||||
#flag -lUser32
|
#flag -lUser32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,20 +20,16 @@ fn main() {
|
||||||
fn setup_symlink(vexe string) {
|
fn setup_symlink(vexe string) {
|
||||||
link_dir := '/usr/local/bin'
|
link_dir := '/usr/local/bin'
|
||||||
if !os.exists(link_dir) {
|
if !os.exists(link_dir) {
|
||||||
os.mkdir_all(link_dir)
|
os.mkdir_all(link_dir) or { panic(err) }
|
||||||
}
|
}
|
||||||
mut link_path := link_dir + '/v'
|
mut link_path := link_dir + '/v'
|
||||||
mut ret := os.exec('ln -sf $vexe $link_path') or {
|
mut ret := os.exec('ln -sf $vexe $link_path') or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if ret.exit_code == 0 {
|
if ret.exit_code == 0 {
|
||||||
println('Symlink "$link_path" has been created')
|
println('Symlink "$link_path" has been created')
|
||||||
} else if os.system("uname -o | grep -q \'[A/a]ndroid\'") == 0 {
|
} else if os.system("uname -o | grep -q '[A/a]ndroid'") == 0 {
|
||||||
println('Failed to create symlink "$link_path". Trying again with Termux path for Android.')
|
println('Failed to create symlink "$link_path". Trying again with Termux path for Android.')
|
||||||
link_path = '/data/data/com.termux/files/usr/bin/v'
|
link_path = '/data/data/com.termux/files/usr/bin/v'
|
||||||
ret = os.exec('ln -sf $vexe $link_path') or {
|
ret = os.exec('ln -sf $vexe $link_path') or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if ret.exit_code == 0 {
|
if ret.exit_code == 0 {
|
||||||
println('Symlink "$link_path" has been created')
|
println('Symlink "$link_path" has been created')
|
||||||
} else {
|
} else {
|
||||||
|
@ -52,9 +49,9 @@ fn setup_symlink_windows(vexe string) {
|
||||||
vsymlinkdir := os.join_path(vdir, '.bin')
|
vsymlinkdir := os.join_path(vdir, '.bin')
|
||||||
mut vsymlink := os.join_path(vsymlinkdir, 'v.exe')
|
mut vsymlink := os.join_path(vsymlinkdir, 'v.exe')
|
||||||
if !os.exists(vsymlinkdir) {
|
if !os.exists(vsymlinkdir) {
|
||||||
os.mkdir_all(vsymlinkdir) // will panic if fails
|
os.mkdir_all(vsymlinkdir) or { panic(err) } // will panic if fails
|
||||||
} else {
|
} else {
|
||||||
os.rm(vsymlink)
|
os.rm(vsymlink) or { panic(err) }
|
||||||
}
|
}
|
||||||
// First, try to create a native symlink at .\.bin\v.exe
|
// First, try to create a native symlink at .\.bin\v.exe
|
||||||
os.symlink(vsymlink, vexe) or {
|
os.symlink(vsymlink, vexe) or {
|
||||||
|
@ -64,9 +61,9 @@ fn setup_symlink_windows(vexe string) {
|
||||||
eprintln('Creating a batch file instead...')
|
eprintln('Creating a batch file instead...')
|
||||||
vsymlink = os.join_path(vsymlinkdir, 'v.bat')
|
vsymlink = os.join_path(vsymlinkdir, 'v.bat')
|
||||||
if os.exists(vsymlink) {
|
if os.exists(vsymlink) {
|
||||||
os.rm(vsymlink)
|
os.rm(vsymlink) or { panic(err) }
|
||||||
}
|
}
|
||||||
os.write_file(vsymlink, '@echo off\n$vexe %*')
|
os.write_file(vsymlink, '@echo off\n$vexe %*') or { panic(err) }
|
||||||
eprintln('$vsymlink file written.')
|
eprintln('$vsymlink file written.')
|
||||||
}
|
}
|
||||||
if !os.exists(vsymlink) {
|
if !os.exists(vsymlink) {
|
||||||
|
@ -83,9 +80,7 @@ fn setup_symlink_windows(vexe string) {
|
||||||
// C.RegCloseKey(reg_sys_env_handle)
|
// C.RegCloseKey(reg_sys_env_handle)
|
||||||
// }
|
// }
|
||||||
// if the above succeeded, and we cannot get the value, it may simply be empty
|
// if the above succeeded, and we cannot get the value, it may simply be empty
|
||||||
sys_env_path := get_reg_value(reg_sys_env_handle, 'Path') or {
|
sys_env_path := get_reg_value(reg_sys_env_handle, 'Path') or { '' }
|
||||||
''
|
|
||||||
}
|
|
||||||
current_sys_paths := sys_env_path.split(os.path_delimiter).map(it.trim('/$os.path_separator'))
|
current_sys_paths := sys_env_path.split(os.path_delimiter).map(it.trim('/$os.path_separator'))
|
||||||
mut new_paths := [vsymlinkdir]
|
mut new_paths := [vsymlinkdir]
|
||||||
for p in current_sys_paths {
|
for p in current_sys_paths {
|
||||||
|
@ -171,8 +166,7 @@ fn set_reg_value(reg_key voidptr, key string, value string) ?bool {
|
||||||
// letting them know that the system environment has changed and should be reloaded
|
// letting them know that the system environment has changed and should be reloaded
|
||||||
fn send_setting_change_msg(message_data string) ?bool {
|
fn send_setting_change_msg(message_data string) ?bool {
|
||||||
$if windows {
|
$if windows {
|
||||||
if C.SendMessageTimeout(os.hwnd_broadcast, os.wm_settingchange, 0, message_data.to_wide(), os.smto_abortifhung, 5000, 0) ==
|
if C.SendMessageTimeout(os.hwnd_broadcast, os.wm_settingchange, 0, message_data.to_wide(), os.smto_abortifhung, 5000, 0) == 0 {
|
||||||
0 {
|
|
||||||
return error('Could not broadcast WM_SETTINGCHANGE')
|
return error('Could not broadcast WM_SETTINGCHANGE')
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -108,9 +108,9 @@ fn (app App) show_current_v_version() {
|
||||||
fn (app App) backup(file string) {
|
fn (app App) backup(file string) {
|
||||||
backup_file := '${file}_old.exe'
|
backup_file := '${file}_old.exe'
|
||||||
if os.exists(backup_file) {
|
if os.exists(backup_file) {
|
||||||
os.rm(backup_file)
|
os.rm(backup_file) or { panic(err) }
|
||||||
}
|
}
|
||||||
os.mv(file, backup_file)
|
os.mv(file, backup_file) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (app App) git_command(command string) {
|
fn (app App) git_command(command string) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ fn main() {
|
||||||
mut cm := vcache.new_cache_manager([])
|
mut cm := vcache.new_cache_manager([])
|
||||||
cpath := cm.basepath
|
cpath := cm.basepath
|
||||||
if os.exists(cpath) && os.is_dir(cpath) {
|
if os.exists(cpath) && os.is_dir(cpath) {
|
||||||
os.rmdir_all(cpath)
|
os.rmdir_all(cpath) or { }
|
||||||
}
|
}
|
||||||
println('V cache folder $cpath was wiped.')
|
println('V cache folder $cpath was wiped.')
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,9 @@ import io
|
||||||
fn main() {
|
fn main() {
|
||||||
// Make a new connection
|
// Make a new connection
|
||||||
mut conn := net.dial_tcp('google.com:80') ?
|
mut conn := net.dial_tcp('google.com:80') ?
|
||||||
defer { conn.close() }
|
defer {
|
||||||
|
conn.close() or { }
|
||||||
|
}
|
||||||
// Simple http HEAD request for a file
|
// Simple http HEAD request for a file
|
||||||
conn.write_str('HEAD /index.html HTTP/1.0\r\n\r\n') ?
|
conn.write_str('HEAD /index.html HTTP/1.0\r\n\r\n') ?
|
||||||
// Read all the data that is waiting
|
// Read all the data that is waiting
|
||||||
|
|
|
@ -35,7 +35,7 @@ const (
|
||||||
f_0 = 0.0
|
f_0 = 0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
/***************************** 3D Vector utility struct **********************/
|
//**************************** 3D Vector utility struct *********************
|
||||||
struct Vec {
|
struct Vec {
|
||||||
mut:
|
mut:
|
||||||
x f64 = 0.0
|
x f64 = 0.0
|
||||||
|
@ -70,11 +70,7 @@ fn (v Vec) mult_s (b f64) Vec{
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
fn (v Vec) cross(b Vec) Vec {
|
fn (v Vec) cross(b Vec) Vec {
|
||||||
return Vec{
|
return Vec{v.y * b.z - v.z * b.y, v.z * b.x - v.x * b.z, v.x * b.y - v.y * b.x}
|
||||||
v.y * b.z - v.z * b.y,
|
|
||||||
v.z * b.x - v.x * b.z,
|
|
||||||
v.x * b.y - v.y * b.x
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -83,7 +79,7 @@ fn (v Vec) norm () Vec {
|
||||||
return Vec{v.x * tmp_norm, v.y * tmp_norm, v.z * tmp_norm}
|
return Vec{v.x * tmp_norm, v.y * tmp_norm, v.z * tmp_norm}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************Image***************************************/
|
//********************************Image**************************************
|
||||||
struct Image {
|
struct Image {
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
|
@ -93,8 +89,8 @@ struct Image {
|
||||||
fn new_image(w int, h int) Image {
|
fn new_image(w int, h int) Image {
|
||||||
vecsize := int(sizeof(Vec))
|
vecsize := int(sizeof(Vec))
|
||||||
return Image{
|
return Image{
|
||||||
width: w,
|
width: w
|
||||||
height: h,
|
height: h
|
||||||
data: &Vec(vcalloc(vecsize * w * h))
|
data: &Vec(vcalloc(vecsize * w * h))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,19 +99,19 @@ fn new_image(w int, h int) Image {
|
||||||
fn (image Image) save_as_ppm(file_name string) {
|
fn (image Image) save_as_ppm(file_name string) {
|
||||||
npixels := image.width * image.height
|
npixels := image.width * image.height
|
||||||
mut f_out := os.create(file_name) or { panic(err) }
|
mut f_out := os.create(file_name) or { panic(err) }
|
||||||
f_out.writeln('P3')
|
f_out.writeln('P3') or { panic(err) }
|
||||||
f_out.writeln('${image.width} ${image.height}')
|
f_out.writeln('$image.width $image.height') or { panic(err) }
|
||||||
f_out.writeln('255')
|
f_out.writeln('255') or { panic(err) }
|
||||||
for i in 0 .. npixels {
|
for i in 0 .. npixels {
|
||||||
c_r := to_int(unsafe { image.data[i] }.x)
|
c_r := to_int(unsafe { image.data[i] }.x)
|
||||||
c_g := to_int(unsafe { image.data[i] }.y)
|
c_g := to_int(unsafe { image.data[i] }.y)
|
||||||
c_b := to_int(unsafe { image.data[i] }.z)
|
c_b := to_int(unsafe { image.data[i] }.z)
|
||||||
f_out.write_str('$c_r $c_g $c_b ')
|
f_out.write_str('$c_r $c_g $c_b ') or { panic(err) }
|
||||||
}
|
}
|
||||||
f_out.close()
|
f_out.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************** Ray *************************************/
|
//********************************** Ray ************************************
|
||||||
struct Ray {
|
struct Ray {
|
||||||
o Vec
|
o Vec
|
||||||
d Vec
|
d Vec
|
||||||
|
@ -128,7 +124,7 @@ enum Refl_t {
|
||||||
refr
|
refr
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************* Sphere ************************************/
|
//******************************** Sphere ***********************************
|
||||||
struct Sphere {
|
struct Sphere {
|
||||||
rad f64 = 0.0 // radius
|
rad f64 = 0.0 // radius
|
||||||
p Vec // position
|
p Vec // position
|
||||||
|
@ -169,48 +165,147 @@ fn (sp Sphere) intersect (r Ray) f64 {
|
||||||
const (
|
const (
|
||||||
cen = Vec{50, 40.8, -860} // used by scene 1
|
cen = Vec{50, 40.8, -860} // used by scene 1
|
||||||
spheres = [
|
spheres = [
|
||||||
[// scene 0 cornnel box
|
[/* scene 0 cornnel box */ Sphere{
|
||||||
Sphere{rad: 1e+5, p: Vec{ 1e+5 +1,40.8,81.6} , e: Vec{} , c: Vec{.75,.25,.25} , refl: .diff},//Left
|
rad: 1e+5
|
||||||
Sphere{rad: 1e+5, p: Vec{-1e+5 +99,40.8,81.6}, e: Vec{} , c: Vec{.25,.25,.75} , refl: .diff},//Rght
|
p: Vec{1e+5 + 1, 40.8, 81.6}
|
||||||
Sphere{rad: 1e+5, p: Vec{50,40.8, 1e+5} , e: Vec{} , c: Vec{.75,.75,.75} , refl: .diff},//Back
|
e: Vec{}
|
||||||
Sphere{rad: 1e+5, p: Vec{50,40.8,-1e+5 +170} , e: Vec{} , c: Vec{} , refl: .diff},//Frnt
|
c: Vec{.75, .25, .25}
|
||||||
Sphere{rad: 1e+5, p: Vec{50, 1e+5, 81.6} , e: Vec{} , c: Vec{.75,.75,.75} , refl: .diff},//Botm
|
refl: .diff
|
||||||
Sphere{rad: 1e+5, p: Vec{50,-1e+5 +81.6,81.6}, e: Vec{} , c: Vec{.75,.75,.75} , refl: .diff},//Top
|
}, /* Left */ Sphere{
|
||||||
Sphere{rad: 16.5, p: Vec{27,16.5,47} , e: Vec{} , c: Vec{1,1,1}.mult_s(.999) , refl: .spec},//Mirr
|
rad: 1e+5
|
||||||
Sphere{rad: 16.5, p: Vec{73,16.5,78} , e: Vec{} , c: Vec{1,1,1}.mult_s(.999) , refl: .refr},//Glas
|
p: Vec{-1e+5 + 99, 40.8, 81.6}
|
||||||
Sphere{rad: 600 , p: Vec{50,681.6-.27,81.6} , e: Vec{12,12,12}, c: Vec{}, refl: .diff} //Lite
|
e: Vec{}
|
||||||
],
|
c: Vec{.25, .25, .75}
|
||||||
|
refl: .diff
|
||||||
[// scene 1 sunset
|
}, /* Rght */ Sphere{
|
||||||
Sphere{rad: 1600, p: Vec{1.0,0.0,2.0}.mult_s(3000), e: Vec{1.0,.9,.8}.mult_s(1.2e+1*1.56*2) , c: Vec{} , refl: .diff}, // sun
|
rad: 1e+5
|
||||||
Sphere{rad: 1560, p: Vec{1,0,2}.mult_s(3500) , e: Vec{1.0,.5,.05}.mult_s(4.8e+1*1.56*2) , c: Vec{} , refl: .diff}, // horizon sun2
|
p: Vec{50, 40.8, 1e+5}
|
||||||
Sphere{rad: 10000, p: cen+Vec{0,0,-200}, e: Vec{0.00063842, 0.02001478, 0.28923243}.mult_s(6e-2*8), c: Vec{.7,.7,1}.mult_s(.25), refl: .diff}, // sky
|
e: Vec{}
|
||||||
|
c: Vec{.75, .75, .75}
|
||||||
Sphere{rad: 100000, p: Vec{50, -100000, 0} , e: Vec{} , c: Vec{.3,.3,.3} , refl: .diff}, // grnd
|
refl: .diff
|
||||||
Sphere{rad: 110000, p: Vec{50, -110048.5, 0} , e: Vec{.9,.5,.05}.mult_s(4) , c: Vec{}, refl: .diff},// horizon brightener
|
}, /* Back */ Sphere{
|
||||||
Sphere{rad: 4e+4 , p: Vec{50, -4e+4-30, -3000}, e: Vec{} , c: Vec{.2,.2,.2} , refl: .diff},// mountains
|
rad: 1e+5
|
||||||
|
p: Vec{50, 40.8, -1e+5 + 170}
|
||||||
Sphere{rad: 26.5, p: Vec{22,26.5,42}, e: Vec{}, c: Vec{1,1,1}.mult_s(.596) , refl: .spec}, // white Mirr
|
e: Vec{}
|
||||||
Sphere{rad: 13, p: Vec{75,13,82 }, e: Vec{}, c: Vec{.96,.96,.96}.mult_s(.96), refl: .refr},// Glas
|
c: Vec{}
|
||||||
Sphere{rad: 22, p: Vec{87,22,24 }, e: Vec{}, c: Vec{.6,.6,.6}.mult_s(.696) , refl: .refr} // Glas2
|
refl: .diff
|
||||||
],
|
}, /* Frnt */ Sphere{
|
||||||
|
rad: 1e+5
|
||||||
|
p: Vec{50, 1e+5, 81.6}
|
||||||
[// scene 3 Psychedelic
|
e: Vec{}
|
||||||
Sphere{rad: 150, p: Vec{50+75,28,62}, e: Vec{1,1,1}.mult_s(0e-3), c: Vec{1,.9,.8}.mult_s(.93), refl: .refr},
|
c: Vec{.75, .75, .75}
|
||||||
Sphere{rad: 28 , p: Vec{50+5,-28,62}, e: Vec{1,1,1}.mult_s(1e+1), c: Vec{1,1,1}.mult_s(0) , refl: .diff},
|
refl: .diff
|
||||||
Sphere{rad: 300, p: Vec{50,28,62} , e: Vec{1,1,1}.mult_s(0e-3), c: Vec{1,1,1}.mult_s(.93) , refl: .spec}
|
}, /* Botm */ Sphere{
|
||||||
]
|
rad: 1e+5
|
||||||
|
p: Vec{50, -1e+5 + 81.6, 81.6}
|
||||||
|
e: Vec{}
|
||||||
|
c: Vec{.75, .75, .75}
|
||||||
|
refl: .diff
|
||||||
|
}, /* Top */ Sphere{
|
||||||
|
rad: 16.5
|
||||||
|
p: Vec{27, 16.5, 47}
|
||||||
|
e: Vec{}
|
||||||
|
c: Vec{1, 1, 1}.mult_s(.999)
|
||||||
|
refl: .spec
|
||||||
|
}, /* Mirr */ Sphere{
|
||||||
|
rad: 16.5
|
||||||
|
p: Vec{73, 16.5, 78}
|
||||||
|
e: Vec{}
|
||||||
|
c: Vec{1, 1, 1}.mult_s(.999)
|
||||||
|
refl: .refr
|
||||||
|
}, /* Glas */ Sphere{
|
||||||
|
rad: 600
|
||||||
|
p: Vec{50, 681.6 - .27, 81.6}
|
||||||
|
e: Vec{12, 12, 12}
|
||||||
|
c: Vec{}
|
||||||
|
refl: .diff
|
||||||
|
} /* Lite */],
|
||||||
|
[/* scene 1 sunset */ Sphere{
|
||||||
|
rad: 1600
|
||||||
|
p: Vec{1.0, 0.0, 2.0}.mult_s(3000)
|
||||||
|
e: Vec{1.0, .9, .8}.mult_s(1.2e+1 * 1.56 * 2)
|
||||||
|
c: Vec{}
|
||||||
|
refl: .diff
|
||||||
|
}, /* sun */ Sphere{
|
||||||
|
rad: 1560
|
||||||
|
p: Vec{1, 0, 2}.mult_s(3500)
|
||||||
|
e: Vec{1.0, .5, .05}.mult_s(4.8e+1 * 1.56 * 2)
|
||||||
|
c: Vec{}
|
||||||
|
refl: .diff
|
||||||
|
}, /* horizon sun2 */ Sphere{
|
||||||
|
rad: 10000
|
||||||
|
p: cen + Vec{0, 0, -200}
|
||||||
|
e: Vec{0.00063842, 0.02001478, 0.28923243}.mult_s(6e-2 * 8)
|
||||||
|
c: Vec{.7, .7, 1}.mult_s(.25)
|
||||||
|
refl: .diff
|
||||||
|
}, /* sky */ Sphere{
|
||||||
|
rad: 100000
|
||||||
|
p: Vec{50, -100000, 0}
|
||||||
|
e: Vec{}
|
||||||
|
c: Vec{.3, .3, .3}
|
||||||
|
refl: .diff
|
||||||
|
}, /* grnd */ Sphere{
|
||||||
|
rad: 110000
|
||||||
|
p: Vec{50, -110048.5, 0}
|
||||||
|
e: Vec{.9, .5, .05}.mult_s(4)
|
||||||
|
c: Vec{}
|
||||||
|
refl: .diff
|
||||||
|
}, /* horizon brightener */ Sphere{
|
||||||
|
rad: 4e+4
|
||||||
|
p: Vec{50, -4e+4 - 30, -3000}
|
||||||
|
e: Vec{}
|
||||||
|
c: Vec{.2, .2, .2}
|
||||||
|
refl: .diff
|
||||||
|
}, /* mountains */ Sphere{
|
||||||
|
rad: 26.5
|
||||||
|
p: Vec{22, 26.5, 42}
|
||||||
|
e: Vec{}
|
||||||
|
c: Vec{1, 1, 1}.mult_s(.596)
|
||||||
|
refl: .spec
|
||||||
|
}, /* white Mirr */ Sphere{
|
||||||
|
rad: 13
|
||||||
|
p: Vec{75, 13, 82}
|
||||||
|
e: Vec{}
|
||||||
|
c: Vec{.96, .96, .96}.mult_s(.96)
|
||||||
|
refl: .refr
|
||||||
|
}, /* Glas */ Sphere{
|
||||||
|
rad: 22
|
||||||
|
p: Vec{87, 22, 24}
|
||||||
|
e: Vec{}
|
||||||
|
c: Vec{.6, .6, .6}.mult_s(.696)
|
||||||
|
refl: .refr
|
||||||
|
} /* Glas2 */],
|
||||||
|
[/* scene 3 Psychedelic */ Sphere{
|
||||||
|
rad: 150
|
||||||
|
p: Vec{50 + 75, 28, 62}
|
||||||
|
e: Vec{1, 1, 1}.mult_s(0e-3)
|
||||||
|
c: Vec{1, .9, .8}.mult_s(.93)
|
||||||
|
refl: .refr
|
||||||
|
}, Sphere{
|
||||||
|
rad: 28
|
||||||
|
p: Vec{50 + 5, -28, 62}
|
||||||
|
e: Vec{1, 1, 1}.mult_s(1e+1)
|
||||||
|
c: Vec{1, 1, 1}.mult_s(0)
|
||||||
|
refl: .diff
|
||||||
|
}, Sphere{
|
||||||
|
rad: 300
|
||||||
|
p: Vec{50, 28, 62}
|
||||||
|
e: Vec{1, 1, 1}.mult_s(0e-3)
|
||||||
|
c: Vec{1, 1, 1}.mult_s(.93)
|
||||||
|
refl: .spec
|
||||||
|
}],
|
||||||
] // end of scene array
|
] // end of scene array
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*********************************** Utilities *******************************/
|
//********************************** Utilities ******************************
|
||||||
[inline]
|
[inline]
|
||||||
fn clamp(x f64) f64 {
|
fn clamp(x f64) f64 {
|
||||||
if x < 0 { return 0 }
|
if x < 0 {
|
||||||
if x > 1 { return 1 }
|
return 0
|
||||||
|
}
|
||||||
|
if x > 1 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,12 +357,12 @@ fn new_tabs() Cache {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
/************* Cache for sin/cos speed-up table and scene selector ***********/
|
//************ Cache for sin/cos speed-up table and scene selector **********
|
||||||
const (
|
const (
|
||||||
tabs = new_tabs()
|
tabs = new_tabs()
|
||||||
)
|
)
|
||||||
|
|
||||||
/******************* main function for the radiance calculation **************/
|
//****************** main function for the radiance calculation *************
|
||||||
fn radiance(r Ray, depthi int, scene_id int) Vec {
|
fn radiance(r Ray, depthi int, scene_id int) Vec {
|
||||||
if depthi > 1024 {
|
if depthi > 1024 {
|
||||||
eprintln('depthi: $depthi')
|
eprintln('depthi: $depthi')
|
||||||
|
@ -284,7 +379,10 @@ fn radiance(r Ray, depthi int, scene_id int) Vec {
|
||||||
scene := spheres[scene_id]
|
scene := spheres[scene_id]
|
||||||
// res, t, id = intersect(r, id, tb.scene)
|
// res, t, id = intersect(r, id, tb.scene)
|
||||||
res, t, id = intersect(r, scene.data, scene.len)
|
res, t, id = intersect(r, scene.data, scene.len)
|
||||||
if !res { return Vec{} } //if miss, return black
|
if !res {
|
||||||
|
return Vec{}
|
||||||
|
}
|
||||||
|
// if miss, return black
|
||||||
|
|
||||||
obj := scene[id] // the hit object
|
obj := scene[id] // the hit object
|
||||||
|
|
||||||
|
@ -326,11 +424,7 @@ fn radiance(r Ray, depthi int, scene_id int) Vec {
|
||||||
|
|
||||||
w := nl
|
w := nl
|
||||||
|
|
||||||
mut u := if math.abs(w.x) > f64(0.1) {
|
mut u := if math.abs(w.x) > f64(0.1) { Vec{0, 1, 0} } else { Vec{1, 0, 0} }
|
||||||
Vec{0, 1, 0}
|
|
||||||
} else {
|
|
||||||
Vec{1, 0, 0}
|
|
||||||
}
|
|
||||||
u = u.cross(w).norm()
|
u = u.cross(w).norm()
|
||||||
|
|
||||||
v := w.cross(u)
|
v := w.cross(u)
|
||||||
|
@ -339,7 +433,8 @@ fn radiance(r Ray, depthi int, scene_id int) Vec {
|
||||||
// d := (u.mult_s(math.cos(r1) * r2s) + v.mult_s(math.sin(r1) * r2s) + w.mult_s(1.0 - r2)).norm()
|
// d := (u.mult_s(math.cos(r1) * r2s) + v.mult_s(math.sin(r1) * r2s) + w.mult_s(1.0 - r2)).norm()
|
||||||
|
|
||||||
// tabbed speed-up
|
// tabbed speed-up
|
||||||
d := (u.mult_s(tabs.cos_tab[r1] * r2s) + v.mult_s(tabs.sin_tab[r1] * r2s) + w.mult_s(math.sqrt(f64(1.0) - r2))).norm()
|
d := (u.mult_s(tabs.cos_tab[r1] * r2s) + v.mult_s(tabs.sin_tab[r1] * r2s) +
|
||||||
|
w.mult_s(math.sqrt(f64(1.0) - r2))).norm()
|
||||||
|
|
||||||
return obj.e + f * radiance(Ray{x, d}, depth, scene_id)
|
return obj.e + f * radiance(Ray{x, d}, depth, scene_id)
|
||||||
} else {
|
} else {
|
||||||
|
@ -379,18 +474,16 @@ fn radiance(r Ray, depthi int, scene_id int) Vec {
|
||||||
mut tmp := Vec{}
|
mut tmp := Vec{}
|
||||||
if depth > 2 {
|
if depth > 2 {
|
||||||
// Russian roulette
|
// Russian roulette
|
||||||
tmp = if rand_f64() < pp {
|
tmp = if rand_f64() < pp { radiance(refl_ray, depth, scene_id).mult_s(rp) } else { radiance(Ray{x, tdir},
|
||||||
radiance(refl_ray, depth, scene_id).mult_s(rp)
|
depth, scene_id).mult_s(tp) }
|
||||||
} else {
|
} else {
|
||||||
radiance(Ray{x, tdir}, depth, scene_id).mult_s(tp)
|
tmp = (radiance(refl_ray, depth, scene_id).mult_s(re)) +
|
||||||
}
|
(radiance(Ray{x, tdir}, depth, scene_id).mult_s(tr))
|
||||||
} else {
|
|
||||||
tmp = (radiance(refl_ray, depth, scene_id).mult_s(re)) + (radiance( Ray{x, tdir}, depth, scene_id).mult_s(tr))
|
|
||||||
}
|
}
|
||||||
return obj.e + (f * tmp)
|
return obj.e + (f * tmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************ beam scan routine **********************************/
|
//*********************** beam scan routine *********************************
|
||||||
fn ray_trace(w int, h int, samps int, file_name string, scene_id int) Image {
|
fn ray_trace(w int, h int, samps int, file_name string, scene_id int) Image {
|
||||||
image := new_image(w, h)
|
image := new_image(w, h)
|
||||||
|
|
||||||
|
@ -410,9 +503,8 @@ fn ray_trace(w int, h int, samps int, file_name string, scene_id int) Image {
|
||||||
|
|
||||||
// OpenMP injection point! #pragma omp parallel for schedule(dynamic, 1) shared(c)
|
// OpenMP injection point! #pragma omp parallel for schedule(dynamic, 1) shared(c)
|
||||||
for y := 0; y < h; y++ {
|
for y := 0; y < h; y++ {
|
||||||
eprint("\rRendering (${samps * 4} spp) ${(100.0 * f64(y)) / (f64(h) - 1.0):5.2f}%")
|
eprint('\rRendering (${samps * 4} spp) ${(100.0 * f64(y)) / (f64(h) - 1.0):5.2f}%')
|
||||||
for x in 0 .. w {
|
for x in 0 .. w {
|
||||||
|
|
||||||
i := (h - y - 1) * w + x
|
i := (h - y - 1) * w + x
|
||||||
mut ivec := unsafe { &image.data[i] }
|
mut ivec := unsafe { &image.data[i] }
|
||||||
// we use sx and sy to perform a square subsampling of 4 samples
|
// we use sx and sy to perform a square subsampling of 4 samples
|
||||||
|
@ -428,7 +520,8 @@ fn ray_trace(w int, h int, samps int, file_name string, scene_id int) Image {
|
||||||
|
|
||||||
d := cx.mult_s(((f64(sx) + 0.5 + dx) * 0.5 + f64(x)) * w1 - .5) +
|
d := cx.mult_s(((f64(sx) + 0.5 + dx) * 0.5 + f64(x)) * w1 - .5) +
|
||||||
cy.mult_s(((f64(sy) + 0.5 + dy) * 0.5 + f64(y)) * h1 - .5) + cam.d
|
cy.mult_s(((f64(sy) + 0.5 + dy) * 0.5 + f64(y)) * h1 - .5) + cam.d
|
||||||
r = r + radiance(Ray{cam.o+d.mult_s(140.0), d.norm()}, 0, scene_id).mult_s(samps1)
|
r = r + radiance(Ray{cam.o +
|
||||||
|
d.mult_s(140.0), d.norm()}, 0, scene_id).mult_s(samps1)
|
||||||
}
|
}
|
||||||
tmp_vec := Vec{clamp(r.x), clamp(r.y), clamp(r.z)}.mult_s(.25)
|
tmp_vec := Vec{clamp(r.x), clamp(r.y), clamp(r.z)}.mult_s(.25)
|
||||||
(*ivec) = *ivec + tmp_vec
|
(*ivec) = *ivec + tmp_vec
|
||||||
|
@ -465,7 +558,6 @@ fn main() {
|
||||||
if os.args.len == 6 {
|
if os.args.len == 6 {
|
||||||
height = os.args[5].int()
|
height = os.args[5].int()
|
||||||
}
|
}
|
||||||
|
|
||||||
// change the seed for a different result
|
// change the seed for a different result
|
||||||
rand.seed([u32(2020), 0])
|
rand.seed([u32(2020), 0])
|
||||||
|
|
||||||
|
@ -474,11 +566,10 @@ fn main() {
|
||||||
image := ray_trace(width, height, samples, file_name, scene_id)
|
image := ray_trace(width, height, samples, file_name, scene_id)
|
||||||
t2 := time.ticks()
|
t2 := time.ticks()
|
||||||
|
|
||||||
|
|
||||||
eprintln('\nRendering finished. Took: ${(t2 - t1):5}ms')
|
eprintln('\nRendering finished. Took: ${(t2 - t1):5}ms')
|
||||||
|
|
||||||
image.save_as_ppm(file_name)
|
image.save_as_ppm(file_name)
|
||||||
t3 := time.ticks()
|
t3 := time.ticks()
|
||||||
|
|
||||||
eprintln('Image saved as [${file_name}]. Took: ${(t3-t2):5}ms')
|
eprintln('Image saved as [$file_name]. Took: ${(t3 - t2):5}ms')
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@ import term.ui as tui
|
||||||
|
|
||||||
const (
|
const (
|
||||||
colors = [
|
colors = [
|
||||||
tui.Color{33, 150, 243}
|
tui.Color{33, 150, 243},
|
||||||
tui.Color{0, 150, 136}
|
tui.Color{0, 150, 136},
|
||||||
tui.Color{205, 220, 57}
|
tui.Color{205, 220, 57},
|
||||||
tui.Color{255, 152, 0}
|
tui.Color{255, 152, 0},
|
||||||
tui.Color{244, 67, 54}
|
tui.Color{244, 67, 54},
|
||||||
tui.Color{156, 39, 176}
|
tui.Color{156, 39, 176},
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -66,27 +66,33 @@ fn event(e &tui.Event, x voidptr) {
|
||||||
}
|
}
|
||||||
.space, .enter {
|
.space, .enter {
|
||||||
app.color_idx++
|
app.color_idx++
|
||||||
if app.color_idx == colors.len { app.color_idx = 0 }
|
if app.color_idx == colors.len {
|
||||||
app.color = colors[app.color_idx]
|
app.color_idx = 0
|
||||||
} else {}
|
|
||||||
}
|
}
|
||||||
} .mouse_move, .mouse_drag, .mouse_down {
|
app.color = colors[app.color_idx]
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mouse_move, .mouse_drag, .mouse_down {
|
||||||
app.points << Point{e.x, e.y}
|
app.points << Point{e.x, e.y}
|
||||||
} .mouse_scroll {
|
}
|
||||||
|
.mouse_scroll {
|
||||||
d := if e.direction == .up { 0.1 } else { -0.1 }
|
d := if e.direction == .up { 0.1 } else { -0.1 }
|
||||||
app.cut_rate += d
|
app.cut_rate += d
|
||||||
if app.cut_rate < 1 { app.cut_rate = 1 }
|
if app.cut_rate < 1 {
|
||||||
} else {}
|
app.cut_rate = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mut app := &App{}
|
mut app := &App{}
|
||||||
app.tui = tui.init(
|
app.tui = tui.init(
|
||||||
user_data: app,
|
user_data: app
|
||||||
frame_fn: frame,
|
frame_fn: frame
|
||||||
event_fn: event,
|
event_fn: event
|
||||||
|
|
||||||
hide_cursor: true
|
hide_cursor: true
|
||||||
)
|
)
|
||||||
|
app.tui.run() ?
|
||||||
app.tui.run()
|
|
||||||
|
|
|
@ -11,29 +11,35 @@ fn event(e &tui.Event, x voidptr) {
|
||||||
app.tui.set_cursor_position(0, 0)
|
app.tui.set_cursor_position(0, 0)
|
||||||
app.tui.write('V term.input event viewer (press `esc` to exit)\n\n')
|
app.tui.write('V term.input event viewer (press `esc` to exit)\n\n')
|
||||||
app.tui.write('$e')
|
app.tui.write('$e')
|
||||||
app.tui.write('\n\nRaw event bytes: "${e.utf8.bytes().hex()}" = ${e.utf8.bytes()}')
|
app.tui.write('\n\nRaw event bytes: "$e.utf8.bytes().hex()" = $e.utf8.bytes()')
|
||||||
if e.modifiers != 0 {
|
if e.modifiers != 0 {
|
||||||
app.tui.write('\nModifiers: $e.modifiers = ')
|
app.tui.write('\nModifiers: $e.modifiers = ')
|
||||||
if e.modifiers & tui.ctrl != 0 { app.tui.write('ctrl. ') }
|
if e.modifiers & tui.ctrl != 0 {
|
||||||
if e.modifiers & tui.shift != 0 { app.tui.write('shift ') }
|
app.tui.write('ctrl. ')
|
||||||
if e.modifiers & tui.alt != 0 { app.tui.write('alt. ') }
|
}
|
||||||
|
if e.modifiers & tui.shift != 0 {
|
||||||
|
app.tui.write('shift ')
|
||||||
|
}
|
||||||
|
if e.modifiers & tui.alt != 0 {
|
||||||
|
app.tui.write('alt. ')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
app.tui.flush()
|
app.tui.flush()
|
||||||
|
|
||||||
if e.typ == .key_down && e.code == .escape { exit(0) }
|
if e.typ == .key_down && e.code == .escape {
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mut app := &App{}
|
mut app := &App{}
|
||||||
app.tui = tui.init(
|
app.tui = tui.init(
|
||||||
user_data: app,
|
user_data: app
|
||||||
event_fn: event
|
event_fn: event
|
||||||
|
|
||||||
window_title: 'V term.ui event viewer'
|
window_title: 'V term.ui event viewer'
|
||||||
hide_cursor: true
|
hide_cursor: true
|
||||||
capture_events: true
|
capture_events: true
|
||||||
frame_rate: 60
|
frame_rate: 60
|
||||||
use_alternate_buffer: false
|
use_alternate_buffer: false
|
||||||
)
|
)
|
||||||
|
|
||||||
println('V term.ui event viewer (press `esc` to exit)\n\n')
|
println('V term.ui event viewer (press `esc` to exit)\n\n')
|
||||||
app.tui.run()
|
app.tui.run() ?
|
||||||
|
|
|
@ -35,10 +35,10 @@ fn (mut a App) init() {
|
||||||
a.width = w
|
a.width = w
|
||||||
a.height = h
|
a.height = h
|
||||||
term.erase_del_clear()
|
term.erase_del_clear()
|
||||||
term.set_cursor_position({
|
term.set_cursor_position(
|
||||||
x: 0
|
x: 0
|
||||||
y: 0
|
y: 0
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut a App) start_game() {
|
fn (mut a App) start_game() {
|
||||||
|
@ -66,10 +66,10 @@ fn (mut a App) quit() {
|
||||||
a.game.quit()
|
a.game.quit()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
term.set_cursor_position({
|
term.set_cursor_position(
|
||||||
x: 0
|
x: 0
|
||||||
y: 0
|
y: 0
|
||||||
})
|
)
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,7 +482,7 @@ fn event(e &ui.Event, x voidptr) {
|
||||||
|
|
||||||
// main
|
// main
|
||||||
mut app := &App{}
|
mut app := &App{}
|
||||||
app.tui = ui.init({
|
app.tui = ui.init(
|
||||||
user_data: app
|
user_data: app
|
||||||
init_fn: init
|
init_fn: init
|
||||||
frame_fn: frame
|
frame_fn: frame
|
||||||
|
@ -492,5 +492,5 @@ app.tui = ui.init({
|
||||||
capture_events: true
|
capture_events: true
|
||||||
hide_cursor: true
|
hide_cursor: true
|
||||||
frame_rate: 60
|
frame_rate: 60
|
||||||
})
|
)
|
||||||
app.tui.run()
|
app.tui.run() ?
|
||||||
|
|
|
@ -43,20 +43,28 @@ fn event(e &tui.Event, x voidptr) {
|
||||||
.mouse_drag {
|
.mouse_drag {
|
||||||
app.cur_rect.x2 = e.x
|
app.cur_rect.x2 = e.x
|
||||||
app.cur_rect.y2 = e.y
|
app.cur_rect.y2 = e.y
|
||||||
} .mouse_up {
|
}
|
||||||
|
.mouse_up {
|
||||||
app.rects << app.cur_rect
|
app.rects << app.cur_rect
|
||||||
app.is_drag = false
|
app.is_drag = false
|
||||||
} .key_down {
|
}
|
||||||
if e.code == .c { app.rects.clear() }
|
.key_down {
|
||||||
else if e.code == .escape { exit(0) }
|
if e.code == .c {
|
||||||
} else {}
|
app.rects.clear()
|
||||||
|
} else if e.code == .escape {
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
}
|
}
|
||||||
app.redraw = true
|
app.redraw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame(x voidptr) {
|
fn frame(x voidptr) {
|
||||||
mut app := &App(x)
|
mut app := &App(x)
|
||||||
if !app.redraw { return }
|
if !app.redraw {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
app.tui.clear()
|
app.tui.clear()
|
||||||
|
|
||||||
|
@ -76,15 +84,12 @@ fn frame(x voidptr) {
|
||||||
app.redraw = false
|
app.redraw = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mut app := &App{}
|
mut app := &App{}
|
||||||
app.tui = tui.init(
|
app.tui = tui.init(
|
||||||
user_data: app,
|
user_data: app
|
||||||
event_fn: event,
|
event_fn: event
|
||||||
frame_fn: frame
|
frame_fn: frame
|
||||||
|
|
||||||
hide_cursor: true
|
hide_cursor: true
|
||||||
frame_rate: 60
|
frame_rate: 60
|
||||||
)
|
)
|
||||||
|
app.tui.run() ?
|
||||||
app.tui.run()
|
|
||||||
|
|
|
@ -3,73 +3,73 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import term.ui as tui
|
import term.ui
|
||||||
|
|
||||||
// The color palette, taken from Google's Material design
|
// The color palette, taken from Google's Material design
|
||||||
const (
|
const (
|
||||||
colors = [
|
colors = [
|
||||||
[
|
[
|
||||||
tui.Color{239, 154, 154},
|
ui.Color{239, 154, 154},
|
||||||
tui.Color{244, 143, 177},
|
ui.Color{244, 143, 177},
|
||||||
tui.Color{206, 147, 216},
|
ui.Color{206, 147, 216},
|
||||||
tui.Color{179, 157, 219},
|
ui.Color{179, 157, 219},
|
||||||
tui.Color{159, 168, 218},
|
ui.Color{159, 168, 218},
|
||||||
tui.Color{144, 202, 249},
|
ui.Color{144, 202, 249},
|
||||||
tui.Color{129, 212, 250},
|
ui.Color{129, 212, 250},
|
||||||
tui.Color{128, 222, 234},
|
ui.Color{128, 222, 234},
|
||||||
tui.Color{128, 203, 196},
|
ui.Color{128, 203, 196},
|
||||||
tui.Color{165, 214, 167},
|
ui.Color{165, 214, 167},
|
||||||
tui.Color{197, 225, 165},
|
ui.Color{197, 225, 165},
|
||||||
tui.Color{230, 238, 156},
|
ui.Color{230, 238, 156},
|
||||||
tui.Color{255, 245, 157},
|
ui.Color{255, 245, 157},
|
||||||
tui.Color{255, 224, 130},
|
ui.Color{255, 224, 130},
|
||||||
tui.Color{255, 204, 128},
|
ui.Color{255, 204, 128},
|
||||||
tui.Color{255, 171, 145},
|
ui.Color{255, 171, 145},
|
||||||
tui.Color{188, 170, 164},
|
ui.Color{188, 170, 164},
|
||||||
tui.Color{238, 238, 238},
|
ui.Color{238, 238, 238},
|
||||||
tui.Color{176, 190, 197},
|
ui.Color{176, 190, 197},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
tui.Color{244, 67, 54},
|
ui.Color{244, 67, 54},
|
||||||
tui.Color{233, 30, 99},
|
ui.Color{233, 30, 99},
|
||||||
tui.Color{156, 39, 176},
|
ui.Color{156, 39, 176},
|
||||||
tui.Color{103, 58, 183},
|
ui.Color{103, 58, 183},
|
||||||
tui.Color{63, 81, 181},
|
ui.Color{63, 81, 181},
|
||||||
tui.Color{33, 150, 243},
|
ui.Color{33, 150, 243},
|
||||||
tui.Color{3, 169, 244},
|
ui.Color{3, 169, 244},
|
||||||
tui.Color{0, 188, 212},
|
ui.Color{0, 188, 212},
|
||||||
tui.Color{0, 150, 136},
|
ui.Color{0, 150, 136},
|
||||||
tui.Color{76, 175, 80},
|
ui.Color{76, 175, 80},
|
||||||
tui.Color{139, 195, 74},
|
ui.Color{139, 195, 74},
|
||||||
tui.Color{205, 220, 57},
|
ui.Color{205, 220, 57},
|
||||||
tui.Color{255, 235, 59},
|
ui.Color{255, 235, 59},
|
||||||
tui.Color{255, 193, 7},
|
ui.Color{255, 193, 7},
|
||||||
tui.Color{255, 152, 0},
|
ui.Color{255, 152, 0},
|
||||||
tui.Color{255, 87, 34},
|
ui.Color{255, 87, 34},
|
||||||
tui.Color{121, 85, 72},
|
ui.Color{121, 85, 72},
|
||||||
tui.Color{120, 120, 120},
|
ui.Color{120, 120, 120},
|
||||||
tui.Color{96, 125, 139},
|
ui.Color{96, 125, 139},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
tui.Color{198, 40, 40},
|
ui.Color{198, 40, 40},
|
||||||
tui.Color{173, 20, 87},
|
ui.Color{173, 20, 87},
|
||||||
tui.Color{106, 27, 154},
|
ui.Color{106, 27, 154},
|
||||||
tui.Color{69, 39, 160},
|
ui.Color{69, 39, 160},
|
||||||
tui.Color{40, 53, 147},
|
ui.Color{40, 53, 147},
|
||||||
tui.Color{21, 101, 192},
|
ui.Color{21, 101, 192},
|
||||||
tui.Color{2, 119, 189},
|
ui.Color{2, 119, 189},
|
||||||
tui.Color{0, 131, 143},
|
ui.Color{0, 131, 143},
|
||||||
tui.Color{0, 105, 92},
|
ui.Color{0, 105, 92},
|
||||||
tui.Color{46, 125, 50},
|
ui.Color{46, 125, 50},
|
||||||
tui.Color{85, 139, 47},
|
ui.Color{85, 139, 47},
|
||||||
tui.Color{158, 157, 36},
|
ui.Color{158, 157, 36},
|
||||||
tui.Color{249, 168, 37},
|
ui.Color{249, 168, 37},
|
||||||
tui.Color{255, 143, 0},
|
ui.Color{255, 143, 0},
|
||||||
tui.Color{239, 108, 0},
|
ui.Color{239, 108, 0},
|
||||||
tui.Color{216, 67, 21},
|
ui.Color{216, 67, 21},
|
||||||
tui.Color{78, 52, 46},
|
ui.Color{78, 52, 46},
|
||||||
tui.Color{33, 33, 33},
|
ui.Color{33, 33, 33},
|
||||||
tui.Color{55, 71, 79},
|
ui.Color{55, 71, 79},
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -90,17 +90,17 @@ const (
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
mut:
|
mut:
|
||||||
tui &tui.Context = 0
|
ui &ui.Context = 0
|
||||||
header_text []string
|
header_text []string
|
||||||
mouse_pos Point
|
mouse_pos Point
|
||||||
msg string
|
msg string
|
||||||
msg_hide_tick int
|
msg_hide_tick int
|
||||||
primary_color tui.Color = colors[1][6]
|
primary_color ui.Color = colors[1][6]
|
||||||
secondary_color tui.Color = colors[1][9]
|
secondary_color ui.Color = colors[1][9]
|
||||||
primary_color_idx int = 25
|
primary_color_idx int = 25
|
||||||
secondary_color_idx int = 28
|
secondary_color_idx int = 28
|
||||||
bg_color tui.Color = tui.Color{0, 0, 0}
|
bg_color ui.Color = ui.Color{0, 0, 0}
|
||||||
drawing [][]tui.Color = [][]tui.Color{len: h, init: []tui.Color{len: w}}
|
drawing [][]ui.Color = [][]ui.Color{len: h, init: []ui.Color{len: w}}
|
||||||
size int = 1
|
size int = 1
|
||||||
should_redraw bool = true
|
should_redraw bool = true
|
||||||
is_dragging bool
|
is_dragging bool
|
||||||
|
@ -114,24 +114,24 @@ mut:
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
mut app := &App{}
|
mut app := &App{}
|
||||||
app.tui = tui.init({
|
app.ui = ui.init(
|
||||||
user_data: app
|
user_data: app
|
||||||
frame_fn: frame
|
frame_fn: frame
|
||||||
event_fn: event
|
event_fn: event
|
||||||
frame_rate: frame_rate
|
frame_rate: frame_rate
|
||||||
hide_cursor: true
|
hide_cursor: true
|
||||||
window_title: 'V terminal pixelart drawing app'
|
window_title: 'V terminal pixelart drawing app'
|
||||||
})
|
)
|
||||||
app.mouse_pos.x = 40
|
app.mouse_pos.x = 40
|
||||||
app.mouse_pos.y = 15
|
app.mouse_pos.y = 15
|
||||||
app.tui.clear()
|
app.ui.clear()
|
||||||
app.tui.run()
|
app.ui.run() ?
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frame(x voidptr) {
|
fn frame(x voidptr) {
|
||||||
mut app := &App(x)
|
mut app := &App(x)
|
||||||
mut redraw := app.should_redraw
|
mut redraw := app.should_redraw
|
||||||
if app.msg != '' && app.tui.frame_count >= app.msg_hide_tick {
|
if app.msg != '' && app.ui.frame_count >= app.msg_hide_tick {
|
||||||
app.msg = ''
|
app.msg = ''
|
||||||
redraw = true
|
redraw = true
|
||||||
}
|
}
|
||||||
|
@ -141,12 +141,12 @@ fn frame(x voidptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event(event &tui.Event, x voidptr) {
|
fn event(event &ui.Event, x voidptr) {
|
||||||
mut app := &App(x)
|
mut app := &App(x)
|
||||||
match event.typ {
|
match event.typ {
|
||||||
.mouse_down {
|
.mouse_down {
|
||||||
app.is_dragging = true
|
app.is_dragging = true
|
||||||
if app.tui.window_height - event.y < 5 {
|
if app.ui.window_height - event.y < 5 {
|
||||||
app.footer_click(event)
|
app.footer_click(event)
|
||||||
} else {
|
} else {
|
||||||
app.paint(event)
|
app.paint(event)
|
||||||
|
@ -174,8 +174,8 @@ fn event(event &tui.Event, x voidptr) {
|
||||||
y: event.y
|
y: event.y
|
||||||
}
|
}
|
||||||
d := event.direction == .down
|
d := event.direction == .down
|
||||||
if event.modifiers & tui.ctrl != 0 {
|
if event.modifiers & ui.ctrl != 0 {
|
||||||
p := event.modifiers & tui.shift == 0
|
p := event.modifiers & ui.shift == 0
|
||||||
c := if d {
|
c := if d {
|
||||||
if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 }
|
if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 }
|
||||||
} else {
|
} else {
|
||||||
|
@ -183,53 +183,72 @@ fn event(event &tui.Event, x voidptr) {
|
||||||
}
|
}
|
||||||
app.select_color(p, c)
|
app.select_color(p, c)
|
||||||
} else {
|
} else {
|
||||||
if d { app.inc_size() } else { app.dec_size() }
|
if d {
|
||||||
|
app.inc_size()
|
||||||
|
} else {
|
||||||
|
app.dec_size()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.key_down {
|
.key_down {
|
||||||
match event.code {
|
match event.code {
|
||||||
.f1, ._1 {
|
.f1, ._1 {
|
||||||
oevent := *event
|
oevent := *event
|
||||||
nevent := tui.Event{ ...oevent, button: tui.MouseButton.left, x: app.mouse_pos.x , y: app.mouse_pos.y }
|
nevent := ui.Event{
|
||||||
|
...oevent
|
||||||
|
button: ui.MouseButton.left
|
||||||
|
x: app.mouse_pos.x
|
||||||
|
y: app.mouse_pos.y
|
||||||
|
}
|
||||||
app.paint(nevent)
|
app.paint(nevent)
|
||||||
}
|
}
|
||||||
.f2, ._2 {
|
.f2, ._2 {
|
||||||
oevent := *event
|
oevent := *event
|
||||||
nevent := tui.Event{ ...oevent, button: tui.MouseButton.right, x: app.mouse_pos.x , y: app.mouse_pos.y }
|
nevent := ui.Event{
|
||||||
|
...oevent
|
||||||
|
button: ui.MouseButton.right
|
||||||
|
x: app.mouse_pos.x
|
||||||
|
y: app.mouse_pos.y
|
||||||
|
}
|
||||||
app.paint(nevent)
|
app.paint(nevent)
|
||||||
}
|
}
|
||||||
.space {
|
.space {
|
||||||
oevent := *event
|
oevent := *event
|
||||||
nevent := tui.Event{ ...oevent, button: tui.MouseButton.middle, x: app.mouse_pos.x , y: app.mouse_pos.y }
|
nevent := ui.Event{
|
||||||
|
...oevent
|
||||||
|
button: ui.MouseButton.middle
|
||||||
|
x: app.mouse_pos.x
|
||||||
|
y: app.mouse_pos.y
|
||||||
|
}
|
||||||
app.paint(nevent)
|
app.paint(nevent)
|
||||||
}
|
}
|
||||||
.j, .down {
|
.j, .down {
|
||||||
if event.modifiers & tui.shift != 0 {
|
if event.modifiers & ui.shift != 0 {
|
||||||
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
||||||
}
|
}
|
||||||
app.mouse_pos.y++
|
app.mouse_pos.y++
|
||||||
}
|
}
|
||||||
.k, .up {
|
.k, .up {
|
||||||
if event.modifiers & tui.shift != 0 {
|
if event.modifiers & ui.shift != 0 {
|
||||||
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
||||||
}
|
}
|
||||||
app.mouse_pos.y--
|
app.mouse_pos.y--
|
||||||
}
|
}
|
||||||
.h, .left {
|
.h, .left {
|
||||||
if event.modifiers & tui.shift != 0 {
|
if event.modifiers & ui.shift != 0 {
|
||||||
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
||||||
}
|
}
|
||||||
app.mouse_pos.x -= 2
|
app.mouse_pos.x -= 2
|
||||||
}
|
}
|
||||||
.l, .right {
|
.l, .right {
|
||||||
if event.modifiers & tui.shift != 0 {
|
if event.modifiers & ui.shift != 0 {
|
||||||
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
||||||
}
|
}
|
||||||
app.mouse_pos.x += 2
|
app.mouse_pos.x += 2
|
||||||
}
|
}
|
||||||
.t {
|
.t {
|
||||||
p := event.modifiers & tui.alt == 0
|
p := event.modifiers & ui.alt == 0
|
||||||
c := if event.modifiers & tui.shift != 0 {
|
c := if event.modifiers & ui.shift != 0 {
|
||||||
if p { app.primary_color_idx - 19 } else { app.secondary_color_idx - 19 }
|
if p { app.primary_color_idx - 19 } else { app.secondary_color_idx - 19 }
|
||||||
} else {
|
} else {
|
||||||
if p { app.primary_color_idx + 19 } else { app.secondary_color_idx + 19 }
|
if p { app.primary_color_idx + 19 } else { app.secondary_color_idx + 19 }
|
||||||
|
@ -237,8 +256,8 @@ fn event(event &tui.Event, x voidptr) {
|
||||||
app.select_color(p, c)
|
app.select_color(p, c)
|
||||||
}
|
}
|
||||||
.r {
|
.r {
|
||||||
p := event.modifiers & tui.alt == 0
|
p := event.modifiers & ui.alt == 0
|
||||||
c := if event.modifiers & tui.shift != 0 {
|
c := if event.modifiers & ui.shift != 0 {
|
||||||
if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 }
|
if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 }
|
||||||
} else {
|
} else {
|
||||||
if p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 }
|
if p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 }
|
||||||
|
@ -252,7 +271,7 @@ fn event(event &tui.Event, x voidptr) {
|
||||||
app.dec_size()
|
app.dec_size()
|
||||||
}
|
}
|
||||||
.c {
|
.c {
|
||||||
app.drawing = [][]tui.Color{len: h, init: []tui.Color{len: w}}
|
app.drawing = [][]ui.Color{len: h, init: []ui.Color{len: w}}
|
||||||
}
|
}
|
||||||
.q, .escape {
|
.q, .escape {
|
||||||
app.render(true)
|
app.render(true)
|
||||||
|
@ -267,14 +286,14 @@ fn event(event &tui.Event, x voidptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) render(paint_only bool) {
|
fn (mut app App) render(paint_only bool) {
|
||||||
app.tui.clear()
|
app.ui.clear()
|
||||||
app.draw_header()
|
app.draw_header()
|
||||||
app.draw_content()
|
app.draw_content()
|
||||||
if !paint_only {
|
if !paint_only {
|
||||||
app.draw_footer()
|
app.draw_footer()
|
||||||
app.draw_cursor()
|
app.draw_cursor()
|
||||||
}
|
}
|
||||||
app.tui.flush()
|
app.ui.flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) select_color(primary bool, idx int) {
|
fn (mut app App) select_color(primary bool, idx int) {
|
||||||
|
@ -293,10 +312,10 @@ fn (mut app App) select_color(primary bool, idx int) {
|
||||||
app.show_msg('set $c_str color idx: $idx', 1)
|
app.show_msg('set $c_str color idx: $idx', 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) set_pixel(x_ int, y_ int, c tui.Color) {
|
fn (mut app App) set_pixel(x_ int, y_ int, c ui.Color) {
|
||||||
// Term coords start at 1, and adjust for the header
|
// Term coords start at 1, and adjust for the header
|
||||||
x, y := x_ - 1, y_ - 4
|
x, y := x_ - 1, y_ - 4
|
||||||
if y < 0 || app.tui.window_height - y < 3 {
|
if y < 0 || app.ui.window_height - y < 3 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if y >= app.drawing.len || x < 0 || x >= app.drawing[0].len {
|
if y >= app.drawing.len || x < 0 || x >= app.drawing[0].len {
|
||||||
|
@ -305,8 +324,8 @@ fn (mut app App) set_pixel(x_ int, y_ int, c tui.Color) {
|
||||||
app.drawing[y][x] = c
|
app.drawing[y][x] = c
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) paint(event &tui.Event) {
|
fn (mut app App) paint(event &ui.Event) {
|
||||||
if event.y < 4 || app.tui.window_height - event.y < 4 {
|
if event.y < 4 || app.ui.window_height - event.y < 4 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
x_start, y_start := int(f32((event.x - 1) / 2) - app.size / 2 + 1), event.y - app.size / 2
|
x_start, y_start := int(f32((event.x - 1) / 2) - app.size / 2 + 1), event.y - app.size / 2
|
||||||
|
@ -323,38 +342,38 @@ fn (mut app App) paint(event &tui.Event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) draw_content() {
|
fn (mut app App) draw_content() {
|
||||||
w_, mut h_ := app.tui.window_width / 2, app.tui.window_height - 8
|
w_, mut h_ := app.ui.window_width / 2, app.ui.window_height - 8
|
||||||
if h_ > app.drawing.len {
|
if h_ > app.drawing.len {
|
||||||
h_ = app.drawing.len
|
h_ = app.drawing.len
|
||||||
}
|
}
|
||||||
for row_idx, row in app.drawing[..h_] {
|
for row_idx, row in app.drawing[..h_] {
|
||||||
app.tui.set_cursor_position(0, row_idx + 4)
|
app.ui.set_cursor_position(0, row_idx + 4)
|
||||||
mut last := tui.Color{0, 0, 0}
|
mut last := ui.Color{0, 0, 0}
|
||||||
for cell in row[..w_] {
|
for cell in row[..w_] {
|
||||||
if cell.r == 0 && cell.g == 0 && cell.b == 0 {
|
if cell.r == 0 && cell.g == 0 && cell.b == 0 {
|
||||||
if !(cell.r == last.r && cell.g == last.g && cell.b == last.b) {
|
if !(cell.r == last.r && cell.g == last.g && cell.b == last.b) {
|
||||||
app.tui.reset()
|
app.ui.reset()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !(cell.r == last.r && cell.g == last.g && cell.b == last.b) {
|
if !(cell.r == last.r && cell.g == last.g && cell.b == last.b) {
|
||||||
app.tui.set_bg_color(cell)
|
app.ui.set_bg_color(cell)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.tui.write(spaces)
|
app.ui.write(spaces)
|
||||||
last = cell
|
last = cell
|
||||||
}
|
}
|
||||||
app.tui.reset()
|
app.ui.reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) draw_cursor() {
|
fn (mut app App) draw_cursor() {
|
||||||
if app.mouse_pos.y in [3, app.tui.window_height - 5] {
|
if app.mouse_pos.y in [3, app.ui.window_height - 5] {
|
||||||
// inside the horizontal separators
|
// inside the horizontal separators
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cursor_color := if app.is_dragging { tui.Color{220, 220, 220} } else { tui.Color{160, 160, 160} }
|
cursor_color := if app.is_dragging { ui.Color{220, 220, 220} } else { ui.Color{160, 160, 160} }
|
||||||
app.tui.set_bg_color(cursor_color)
|
app.ui.set_bg_color(cursor_color)
|
||||||
if app.mouse_pos.y >= 3 && app.mouse_pos.y <= app.tui.window_height - 4 {
|
if app.mouse_pos.y >= 3 && app.mouse_pos.y <= app.ui.window_height - 4 {
|
||||||
// inside the main content
|
// inside the main content
|
||||||
mut x_start := int(f32((app.mouse_pos.x - 1) / 2) - app.size / 2 + 1) * 2 - 1
|
mut x_start := int(f32((app.mouse_pos.x - 1) / 2) - app.size / 2 + 1) * 2 - 1
|
||||||
mut y_start := app.mouse_pos.y - app.size / 2
|
mut y_start := app.mouse_pos.y - app.size / 2
|
||||||
|
@ -366,70 +385,71 @@ fn (mut app App) draw_cursor() {
|
||||||
if y_start < 4 {
|
if y_start < 4 {
|
||||||
y_start = 4
|
y_start = 4
|
||||||
}
|
}
|
||||||
if x_end > app.tui.window_width {
|
if x_end > app.ui.window_width {
|
||||||
x_end = app.tui.window_width
|
x_end = app.ui.window_width
|
||||||
}
|
}
|
||||||
if y_end > app.tui.window_height - 5 {
|
if y_end > app.ui.window_height - 5 {
|
||||||
y_end = app.tui.window_height - 5
|
y_end = app.ui.window_height - 5
|
||||||
}
|
}
|
||||||
app.tui.draw_rect(x_start, y_start, x_end, y_end)
|
app.ui.draw_rect(x_start, y_start, x_end, y_end)
|
||||||
} else {
|
} else {
|
||||||
app.tui.draw_text(app.mouse_pos.x, app.mouse_pos.y, space)
|
app.ui.draw_text(app.mouse_pos.x, app.mouse_pos.y, space)
|
||||||
}
|
}
|
||||||
app.tui.reset()
|
app.ui.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) draw_header() {
|
fn (mut app App) draw_header() {
|
||||||
if app.msg != '' {
|
if app.msg != '' {
|
||||||
app.tui.set_color({
|
app.ui.set_color(
|
||||||
r: 0
|
r: 0
|
||||||
g: 0
|
g: 0
|
||||||
b: 0
|
b: 0
|
||||||
})
|
)
|
||||||
app.tui.set_bg_color({
|
app.ui.set_bg_color(
|
||||||
r: 220
|
r: 220
|
||||||
g: 220
|
g: 220
|
||||||
b: 220
|
b: 220
|
||||||
})
|
)
|
||||||
app.tui.draw_text(0, 0, ' $app.msg ')
|
app.ui.draw_text(0, 0, ' $app.msg ')
|
||||||
app.tui.reset()
|
app.ui.reset()
|
||||||
}
|
}
|
||||||
app.tui.draw_text(3, 2, /* 'tick: $app.tui.frame_count | ' + */ 'terminal size: ($app.tui.window_width, $app.tui.window_height) | primary color: $app.primary_color.hex() | secondary color: $app.secondary_color.hex()')
|
//'tick: $app.ui.frame_count | ' +
|
||||||
app.tui.horizontal_separator(3)
|
app.ui.draw_text(3, 2, 'terminal size: ($app.ui.window_width, $app.ui.window_height) | primary color: $app.primary_color.hex() | secondary color: $app.secondary_color.hex()')
|
||||||
|
app.ui.horizontal_separator(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) draw_footer() {
|
fn (mut app App) draw_footer() {
|
||||||
_, wh := app.tui.window_width, app.tui.window_height
|
_, wh := app.ui.window_width, app.ui.window_height
|
||||||
app.tui.horizontal_separator(wh - 4)
|
app.ui.horizontal_separator(wh - 4)
|
||||||
for i, color_row in colors {
|
for i, color_row in colors {
|
||||||
for j, color in color_row {
|
for j, color in color_row {
|
||||||
x := j * 3 + 19
|
x := j * 3 + 19
|
||||||
y := wh - 3 + i
|
y := wh - 3 + i
|
||||||
app.tui.set_bg_color(color)
|
app.ui.set_bg_color(color)
|
||||||
if app.primary_color_idx == j + (i * 19) {
|
if app.primary_color_idx == j + (i * 19) {
|
||||||
app.tui.set_color(r: 0, g: 0, b: 0)
|
app.ui.set_color(r: 0, g: 0, b: 0)
|
||||||
app.tui.draw_text(x, y, '><')
|
app.ui.draw_text(x, y, '><')
|
||||||
app.tui.reset_color()
|
app.ui.reset_color()
|
||||||
} else if app.secondary_color_idx == j + (i * 19) {
|
} else if app.secondary_color_idx == j + (i * 19) {
|
||||||
app.tui.set_color(r: 255, g: 255, b: 255)
|
app.ui.set_color(r: 255, g: 255, b: 255)
|
||||||
app.tui.draw_text(x, y, '><')
|
app.ui.draw_text(x, y, '><')
|
||||||
app.tui.reset_color()
|
app.ui.reset_color()
|
||||||
} else {
|
} else {
|
||||||
app.tui.draw_rect(x, y, x + 1, y)
|
app.ui.draw_rect(x, y, x + 1, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.tui.reset_bg_color()
|
app.ui.reset_bg_color()
|
||||||
app.tui.draw_text(3, wh - 3, select_color)
|
app.ui.draw_text(3, wh - 3, select_color)
|
||||||
app.tui.bold()
|
app.ui.bold()
|
||||||
app.tui.draw_text(3, wh - 1, '$select_size $app.size')
|
app.ui.draw_text(3, wh - 1, '$select_size $app.size')
|
||||||
app.tui.reset()
|
app.ui.reset()
|
||||||
|
|
||||||
// TODO: help button
|
// TODO: help button
|
||||||
// if ww >= 90 {
|
// if ww >= 90 {
|
||||||
// app.tui.draw_text(80, wh - 3, help_1)
|
// app.ui.draw_text(80, wh - 3, help_1)
|
||||||
// app.tui.draw_text(80, wh - 2, help_2)
|
// app.ui.draw_text(80, wh - 2, help_2)
|
||||||
// app.tui.draw_text(80, wh - 1, help_3)
|
// app.ui.draw_text(80, wh - 1, help_3)
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,8 +469,8 @@ fn (mut app App) dec_size() {
|
||||||
app.show_msg('dec. size: $app.size', 1)
|
app.show_msg('dec. size: $app.size', 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut app App) footer_click(event &tui.Event) {
|
fn (mut app App) footer_click(event &ui.Event) {
|
||||||
footer_y := 3 - (app.tui.window_height - event.y)
|
footer_y := 3 - (app.ui.window_height - event.y)
|
||||||
match event.x {
|
match event.x {
|
||||||
8...11 {
|
8...11 {
|
||||||
app.inc_size()
|
app.inc_size()
|
||||||
|
@ -464,7 +484,9 @@ fn (mut app App) footer_click(event &tui.Event) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
idx := footer_y * 19 - 6 + event.x / 3
|
idx := footer_y * 19 - 6 + event.x / 3
|
||||||
if idx < 0 || idx > 56 { return }
|
if idx < 0 || idx > 56 {
|
||||||
|
return
|
||||||
|
}
|
||||||
app.select_color(event.button == .left, idx)
|
app.select_color(event.button == .left, idx)
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
|
@ -473,6 +495,6 @@ fn (mut app App) footer_click(event &tui.Event) {
|
||||||
|
|
||||||
fn (mut app App) show_msg(text string, time int) {
|
fn (mut app App) show_msg(text string, time int) {
|
||||||
frames := time * frame_rate
|
frames := time * frame_rate
|
||||||
app.msg_hide_tick = if time > 0 { int(app.tui.frame_count) + frames } else { -1 }
|
app.msg_hide_tick = if time > 0 { int(app.ui.frame_count) + frames } else { -1 }
|
||||||
app.msg = text
|
app.msg = text
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ fn (mut a App) set_status(msg string, duration_ms int) {
|
||||||
fn (mut a App) save() {
|
fn (mut a App) save() {
|
||||||
if a.cfile().len > 0 {
|
if a.cfile().len > 0 {
|
||||||
b := a.ed
|
b := a.ed
|
||||||
os.write_file(a.cfile(), b.raw())
|
os.write_file(a.cfile(), b.raw()) or { panic(err) }
|
||||||
a.set_status('Saved', 2000)
|
a.set_status('Saved', 2000)
|
||||||
} else {
|
} else {
|
||||||
a.set_status('No file loaded', 4000)
|
a.set_status('No file loaded', 4000)
|
||||||
|
@ -79,7 +79,6 @@ fn (mut a App) visit_next_file() {
|
||||||
a.init_file()
|
a.init_file()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn (mut a App) footer() {
|
fn (mut a App) footer() {
|
||||||
w, h := a.tui.window_width, a.tui.window_height
|
w, h := a.tui.window_width, a.tui.window_height
|
||||||
mut b := a.ed
|
mut b := a.ed
|
||||||
|
@ -99,16 +98,16 @@ fn (mut a App) footer() {
|
||||||
if a.t <= 0 {
|
if a.t <= 0 {
|
||||||
status = ''
|
status = ''
|
||||||
} else {
|
} else {
|
||||||
a.tui.set_bg_color({
|
a.tui.set_bg_color(
|
||||||
r: 200
|
r: 200
|
||||||
g: 200
|
g: 200
|
||||||
b: 200
|
b: 200
|
||||||
})
|
)
|
||||||
a.tui.set_color({
|
a.tui.set_color(
|
||||||
r: 0
|
r: 0
|
||||||
g: 0
|
g: 0
|
||||||
b: 0
|
b: 0
|
||||||
})
|
)
|
||||||
a.tui.draw_text((w + 4 - status.len) / 2, h - 1, ' $status ')
|
a.tui.draw_text((w + 4 - status.len) / 2, h - 1, ' $status ')
|
||||||
a.tui.reset()
|
a.tui.reset()
|
||||||
a.t -= 33
|
a.t -= 33
|
||||||
|
@ -374,9 +373,15 @@ fn (mut b Buffer) move_to_word(movement Movement) {
|
||||||
x = 0
|
x = 0
|
||||||
}
|
}
|
||||||
// first, move past all non-`a-zA-Z0-9_` characters
|
// first, move past all non-`a-zA-Z0-9_` characters
|
||||||
for x+a >= 0 && x+a < line.len && !(line[x+a].is_letter() || line[x+a].is_digit() || line[x+a] == `_`) { x += a }
|
for x + a >= 0 && x + a < line.len && !(line[x + a].is_letter()
|
||||||
|
|| line[x + a].is_digit()|| line[x + a] == `_`) {
|
||||||
|
x += a
|
||||||
|
}
|
||||||
// then, move past all the letters and numbers
|
// then, move past all the letters and numbers
|
||||||
for x+a >= 0 && x+a < line.len && (line[x+a].is_letter() || line[x+a].is_digit() || line[x+a] == `_`) { x += a }
|
for x + a >= 0 && x + a < line.len && (line[x + a].is_letter()
|
||||||
|
|| line[x + a].is_digit()|| line[x + a] == `_`) {
|
||||||
|
x += a
|
||||||
|
}
|
||||||
// if the cursor is out of bounds, move it to the next/previous line
|
// if the cursor is out of bounds, move it to the next/previous line
|
||||||
if x + a >= 0 && x + a <= line.len {
|
if x + a >= 0 && x + a <= line.len {
|
||||||
x += a
|
x += a
|
||||||
|
@ -388,11 +393,19 @@ fn (mut b Buffer) move_to_word(movement Movement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn imax(x int, y int) int {
|
fn imax(x int, y int) int {
|
||||||
return if x < y { y } else { x }
|
return if x < y {
|
||||||
|
y
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn imin(x int, y int) int {
|
fn imin(x int, y int) int {
|
||||||
return if x < y { x } else { y }
|
return if x < y {
|
||||||
|
x
|
||||||
|
} else {
|
||||||
|
y
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Cursor {
|
struct Cursor {
|
||||||
|
@ -443,9 +456,7 @@ fn (mut a App) init_file() {
|
||||||
// 'vico: ' +
|
// 'vico: ' +
|
||||||
a.tui.set_window_title(a.files[a.current_file])
|
a.tui.set_window_title(a.files[a.current_file])
|
||||||
mut b := a.ed
|
mut b := a.ed
|
||||||
content := os.read_file(a.files[a.current_file]) or {
|
content := os.read_file(a.files[a.current_file]) or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
b.put(content)
|
b.put(content)
|
||||||
a.ed.cursor.pos_x = init_x
|
a.ed.cursor.pos_x = init_x
|
||||||
a.ed.cursor.pos_y = init_y
|
a.ed.cursor.pos_y = init_y
|
||||||
|
@ -573,12 +584,12 @@ fn main() {
|
||||||
mut a := &App{
|
mut a := &App{
|
||||||
files: files
|
files: files
|
||||||
}
|
}
|
||||||
a.tui = tui.init({
|
a.tui = tui.init(
|
||||||
user_data: a
|
user_data: a
|
||||||
init_fn: init
|
init_fn: init
|
||||||
frame_fn: frame
|
frame_fn: frame
|
||||||
event_fn: event
|
event_fn: event
|
||||||
capture_events: true
|
capture_events: true
|
||||||
})
|
)
|
||||||
a.tui.run()
|
a.tui.run() ?
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,8 +125,16 @@ fn (mut s Snake) move() {
|
||||||
piece.facing = s.direction
|
piece.facing = s.direction
|
||||||
new_x := piece.pos.x + s.velocity.x
|
new_x := piece.pos.x + s.velocity.x
|
||||||
new_y := piece.pos.y + s.velocity.y
|
new_y := piece.pos.y + s.velocity.y
|
||||||
piece.pos.x += if new_x > block_size && new_x < width - block_size { s.velocity.x } else { 0 }
|
piece.pos.x += if new_x > block_size && new_x < width - block_size {
|
||||||
piece.pos.y += if new_y > block_size && new_y < height - block_size { s.velocity.y } else { 0 }
|
s.velocity.x
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
piece.pos.y += if new_y > block_size && new_y < height - block_size {
|
||||||
|
s.velocity.y
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.body[i] = piece
|
s.body[i] = piece
|
||||||
}
|
}
|
||||||
|
@ -205,10 +213,10 @@ fn (s Snake) check_overlap() bool {
|
||||||
|
|
||||||
fn (s Snake) check_out_of_bounds() bool {
|
fn (s Snake) check_out_of_bounds() bool {
|
||||||
h := s.get_head()
|
h := s.get_head()
|
||||||
return h.pos.x + s.velocity.x <= block_size ||
|
return h.pos.x + s.velocity.x <= block_size
|
||||||
h.pos.x + s.velocity.x > s.app.width - s.velocity.x || h.pos.y + s.velocity.y <= block_size ||
|
|| h.pos.x + s.velocity.x > s.app.width - s.velocity.x
|
||||||
h.pos.y + s.velocity.y >
|
|| h.pos.y + s.velocity.y <= block_size
|
||||||
s.app.height - block_size - s.velocity.y
|
|| h.pos.y + s.velocity.y > s.app.height - block_size - s.velocity.y
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw draws the parts of the snake
|
// draw draws the parts of the snake
|
||||||
|
@ -244,8 +252,8 @@ mut:
|
||||||
|
|
||||||
// randomize spawn the rat in a new spot within the playable field
|
// randomize spawn the rat in a new spot within the playable field
|
||||||
fn (mut r Rat) randomize() {
|
fn (mut r Rat) randomize() {
|
||||||
r.pos.randomize(2 * block_size + buffer, 2 * block_size + buffer, r.app.width - block_size -
|
r.pos.randomize(2 * block_size + buffer, 2 * block_size + buffer, r.app.width - block_size - buffer,
|
||||||
buffer, r.app.height - block_size - buffer)
|
r.app.height - block_size - buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
|
@ -387,9 +395,8 @@ fn (mut a App) move_snake(direction Orientation) {
|
||||||
fn (a App) check_capture() bool {
|
fn (a App) check_capture() bool {
|
||||||
snake_pos := a.snake.get_head().pos
|
snake_pos := a.snake.get_head().pos
|
||||||
rat_pos := a.rat.pos
|
rat_pos := a.rat.pos
|
||||||
return snake_pos.x <= rat_pos.x + block_size &&
|
return snake_pos.x <= rat_pos.x + block_size && snake_pos.x + block_size >= rat_pos.x
|
||||||
snake_pos.x + block_size >= rat_pos.x && snake_pos.y <= rat_pos.y + block_size && snake_pos.y +
|
&& snake_pos.y <= rat_pos.y + block_size&& snake_pos.y + block_size >= rat_pos.y
|
||||||
block_size >= rat_pos.y
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut a App) draw_snake() {
|
fn (mut a App) draw_snake() {
|
||||||
|
@ -454,12 +461,12 @@ fn (mut a App) draw_gameover() {
|
||||||
}
|
}
|
||||||
|
|
||||||
mut app := &App{}
|
mut app := &App{}
|
||||||
app.termui = termui.init({
|
app.termui = termui.init(
|
||||||
user_data: app
|
user_data: app
|
||||||
event_fn: event
|
event_fn: event
|
||||||
frame_fn: frame
|
frame_fn: frame
|
||||||
init_fn: init
|
init_fn: init
|
||||||
hide_cursor: true
|
hide_cursor: true
|
||||||
frame_rate: 10
|
frame_rate: 10
|
||||||
})
|
)
|
||||||
app.termui.run()
|
app.termui.run() ?
|
||||||
|
|
|
@ -16,11 +16,9 @@ fn main() {
|
||||||
if line == '' {
|
if line == '' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ws.write_str(line)
|
ws.write_str(line) ?
|
||||||
}
|
|
||||||
ws.close(1000, 'normal') or {
|
|
||||||
println(term.red('panicing $err'))
|
|
||||||
}
|
}
|
||||||
|
ws.close(1000, 'normal') or { println(term.red('panicing $err')) }
|
||||||
unsafe {
|
unsafe {
|
||||||
ws.free()
|
ws.free()
|
||||||
}
|
}
|
||||||
|
@ -49,12 +47,8 @@ fn start_client() ?&websocket.Client {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
ws.connect() or {
|
ws.connect() or { println(term.red('error on connect: $err')) }
|
||||||
println(term.red('error on connect: $err'))
|
|
||||||
}
|
|
||||||
|
|
||||||
go ws.listen() or {
|
go ws.listen() or { println(term.red('error on listen $err')) }
|
||||||
println(term.red('error on listen $err'))
|
|
||||||
}
|
|
||||||
return ws
|
return ws
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,7 +259,7 @@ fn (cmd Command) check_version_flag() {
|
||||||
version_flag := cmd.flags.get_bool('version') or { return } // ignore error and handle command normally
|
version_flag := cmd.flags.get_bool('version') or { return } // ignore error and handle command normally
|
||||||
if version_flag {
|
if version_flag {
|
||||||
version_cmd := cmd.commands.get('version') or { return } // ignore error and handle command normally
|
version_cmd := cmd.commands.get('version') or { return } // ignore error and handle command normally
|
||||||
version_cmd.execute(version_cmd)
|
version_cmd.execute(version_cmd) or { panic(err) }
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,7 +280,7 @@ fn (cmd Command) check_required_flags() {
|
||||||
pub fn (cmd Command) execute_help() {
|
pub fn (cmd Command) execute_help() {
|
||||||
if cmd.commands.contains('help') {
|
if cmd.commands.contains('help') {
|
||||||
help_cmd := cmd.commands.get('help') or { return } // ignore error and handle command normally
|
help_cmd := cmd.commands.get('help') or { return } // ignore error and handle command normally
|
||||||
help_cmd.execute(help_cmd)
|
help_cmd.execute(help_cmd) or { panic(err) }
|
||||||
} else {
|
} else {
|
||||||
print(cmd.help_message())
|
print(cmd.help_message())
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ fn test_vexe() {
|
||||||
|
|
||||||
fn test_can_compile_library() {
|
fn test_can_compile_library() {
|
||||||
os.chdir(cfolder)
|
os.chdir(cfolder)
|
||||||
os.rm(library_file_name)
|
os.rm(library_file_name) or { }
|
||||||
res := v_compile('-d no_backtrace -o library -shared library.v')
|
res := v_compile('-d no_backtrace -o library -shared library.v')
|
||||||
eprintln('res: $res')
|
eprintln('res: $res')
|
||||||
assert os.is_file(library_file_name)
|
assert os.is_file(library_file_name)
|
||||||
|
@ -34,7 +34,7 @@ fn test_can_compile_main_program() {
|
||||||
result := v_compile('run use.v')
|
result := v_compile('run use.v')
|
||||||
eprintln('result: $result')
|
eprintln('result: $result')
|
||||||
assert result.output.contains('res: 4')
|
assert result.output.contains('res: 4')
|
||||||
os.rm(library_file_name)
|
os.rm(library_file_name) or { }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn v_compile(vopts string) os.Result {
|
fn v_compile(vopts string) os.Result {
|
||||||
|
|
|
@ -10,16 +10,16 @@ const (
|
||||||
|
|
||||||
fn testsuite_begin() {
|
fn testsuite_begin() {
|
||||||
eprintln('testsuite_begin, tfolder = $tfolder')
|
eprintln('testsuite_begin, tfolder = $tfolder')
|
||||||
os.rmdir_all(tfolder)
|
os.rmdir_all(tfolder) or { }
|
||||||
assert !os.is_dir(tfolder)
|
assert !os.is_dir(tfolder)
|
||||||
os.mkdir_all(tfolder)
|
os.mkdir_all(tfolder) or { panic(err) }
|
||||||
os.chdir(tfolder)
|
os.chdir(tfolder)
|
||||||
assert os.is_dir(tfolder)
|
assert os.is_dir(tfolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testsuite_end() {
|
fn testsuite_end() {
|
||||||
os.chdir(os.wd_at_startup)
|
os.chdir(os.wd_at_startup)
|
||||||
os.rmdir_all(tfolder)
|
os.rmdir_all(tfolder) or { }
|
||||||
assert !os.is_dir(tfolder)
|
assert !os.is_dir(tfolder)
|
||||||
// eprintln('testsuite_end , tfolder = $tfolder removed.')
|
// eprintln('testsuite_end , tfolder = $tfolder removed.')
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,9 @@ fn test_temp_file() {
|
||||||
assert f.is_opened
|
assert f.is_opened
|
||||||
// Test pattern
|
// Test pattern
|
||||||
f.close()
|
f.close()
|
||||||
f, path = util.temp_file({
|
f, path = util.temp_file(
|
||||||
pattern: 'some_*_test.file'
|
pattern: 'some_*_test.file'
|
||||||
}) or {
|
) or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -58,9 +58,9 @@ fn test_temp_file() {
|
||||||
// Test custom path
|
// Test custom path
|
||||||
prev_path = path
|
prev_path = path
|
||||||
f.close()
|
f.close()
|
||||||
f, path = util.temp_file({
|
f, path = util.temp_file(
|
||||||
path: tfolder
|
path: tfolder
|
||||||
}) or {
|
) or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -88,9 +88,9 @@ fn test_temp_dir() {
|
||||||
assert writable
|
assert writable
|
||||||
mut prev_path := path
|
mut prev_path := path
|
||||||
// Test pattern
|
// Test pattern
|
||||||
path = util.temp_dir({
|
path = util.temp_dir(
|
||||||
pattern: 'some_*_test_dir'
|
pattern: 'some_*_test_dir'
|
||||||
}) or {
|
) or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -106,9 +106,9 @@ fn test_temp_dir() {
|
||||||
}
|
}
|
||||||
// Test custom path
|
// Test custom path
|
||||||
prev_path = path
|
prev_path = path
|
||||||
path = util.temp_dir({
|
path = util.temp_dir(
|
||||||
path: tfolder
|
path: tfolder
|
||||||
}) or {
|
) or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ pub fn (mut l Log) close() {
|
||||||
fn (mut l Log) log_file(s string, level Level) {
|
fn (mut l Log) log_file(s string, level Level) {
|
||||||
timestamp := time.now().format_ss()
|
timestamp := time.now().format_ss()
|
||||||
e := tag_to_file(level)
|
e := tag_to_file(level)
|
||||||
l.ofile.writeln('$timestamp [$e] $s')
|
l.ofile.writeln('$timestamp [$e] $s') or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// log_cli writes log line `s` with `level` to stdout.
|
// log_cli writes log line `s` with `level` to stdout.
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub fn socket_error(potential_code int) ?int {
|
||||||
pub fn wrap_error(error_code int) ? {
|
pub fn wrap_error(error_code int) ? {
|
||||||
$if windows {
|
$if windows {
|
||||||
enum_error := wsa_error(error_code)
|
enum_error := wsa_error(error_code)
|
||||||
return error_with_code('socket error: $enum_error', error_code)
|
return error_with_code('net: socket error: $enum_error', error_code)
|
||||||
}
|
}
|
||||||
$else {
|
$else {
|
||||||
if error_code == 0 {
|
if error_code == 0 {
|
||||||
|
|
|
@ -36,7 +36,7 @@ const (
|
||||||
|
|
||||||
struct DTP {
|
struct DTP {
|
||||||
mut:
|
mut:
|
||||||
conn net.TcpConn
|
conn &net.TcpConn
|
||||||
reader io.BufferedReader
|
reader io.BufferedReader
|
||||||
ip string
|
ip string
|
||||||
port int
|
port int
|
||||||
|
@ -56,31 +56,31 @@ fn (mut dtp DTP) read() ?[]byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut dtp DTP) close() {
|
fn (mut dtp DTP) close() {
|
||||||
dtp.conn.close()
|
dtp.conn.close() or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FTP {
|
struct FTP {
|
||||||
mut:
|
mut:
|
||||||
conn net.TcpConn
|
conn &net.TcpConn
|
||||||
reader io.BufferedReader
|
reader io.BufferedReader
|
||||||
buffer_size int
|
buffer_size int
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() FTP {
|
pub fn new() FTP {
|
||||||
mut f := FTP{}
|
mut f := FTP{ conn: 0 }
|
||||||
f.buffer_size = 1024
|
f.buffer_size = 1024
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut ftp FTP) write(data string) ? {
|
fn (mut zftp FTP) write(data string) ? {
|
||||||
$if debug {
|
$if debug {
|
||||||
println('FTP.v >>> $data')
|
println('FTP.v >>> $data')
|
||||||
}
|
}
|
||||||
ftp.conn.write('$data\r\n'.bytes()) ?
|
zftp.conn.write('$data\r\n'.bytes()) ?
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut ftp FTP) read() ?(int, string) {
|
fn (mut zftp FTP) read() ?(int, string) {
|
||||||
mut data := ftp.reader.read_line() ?
|
mut data := zftp.reader.read_line() ?
|
||||||
$if debug {
|
$if debug {
|
||||||
println('FTP.v <<< $data')
|
println('FTP.v <<< $data')
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ fn (mut ftp FTP) read() ?(int, string) {
|
||||||
code := data[..3].int()
|
code := data[..3].int()
|
||||||
if data[3] == `-` {
|
if data[3] == `-` {
|
||||||
for {
|
for {
|
||||||
data = ftp.reader.read_line() ?
|
data = zftp.reader.read_line() ?
|
||||||
if data[..3].int() == code && data[3] != `-` {
|
if data[..3].int() == code && data[3] != `-` {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -99,51 +99,51 @@ fn (mut ftp FTP) read() ?(int, string) {
|
||||||
return code, data
|
return code, data
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut ftp FTP) connect(ip string) ?bool {
|
pub fn (mut zftp FTP) connect(ip string) ?bool {
|
||||||
ftp.conn = net.dial_tcp('$ip:21') ?
|
zftp.conn = net.dial_tcp('$ip:21') ?
|
||||||
ftp.reader = io.new_buffered_reader(reader: io.make_reader(ftp.conn))
|
zftp.reader = io.new_buffered_reader(reader: io.make_reader(zftp.conn))
|
||||||
code, _ := ftp.read() ?
|
code, _ := zftp.read() ?
|
||||||
if code == connected {
|
if code == ftp.connected {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut ftp FTP) login(user string, passwd string) ?bool {
|
pub fn (mut zftp FTP) login(user string, passwd string) ?bool {
|
||||||
ftp.write('USER $user') or {
|
zftp.write('USER $user') or {
|
||||||
$if debug {
|
$if debug {
|
||||||
println('ERROR sending user')
|
println('ERROR sending user')
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
mut code, _ := ftp.read() ?
|
mut code, _ := zftp.read() ?
|
||||||
if code == logged_in {
|
if code == ftp.logged_in {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if code != specify_password {
|
if code != ftp.specify_password {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
ftp.write('PASS $passwd') or {
|
zftp.write('PASS $passwd') or {
|
||||||
$if debug {
|
$if debug {
|
||||||
println('ERROR sending password')
|
println('ERROR sending password')
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
code, _ = ftp.read() ?
|
code, _ = zftp.read() ?
|
||||||
if code == logged_in {
|
if code == ftp.logged_in {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut ftp FTP) close() ? {
|
pub fn (mut zftp FTP) close() ? {
|
||||||
ftp.write('QUIT') ?
|
zftp.write('QUIT') ?
|
||||||
ftp.conn.close()
|
zftp.conn.close() ?
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut ftp FTP) pwd() ?string {
|
pub fn (mut zftp FTP) pwd() ?string {
|
||||||
ftp.write('PWD') ?
|
zftp.write('PWD') ?
|
||||||
_, data := ftp.read() ?
|
_, data := zftp.read() ?
|
||||||
spl := data.split('"') // "
|
spl := data.split('"') // "
|
||||||
if spl.len >= 2 {
|
if spl.len >= 2 {
|
||||||
return spl[1]
|
return spl[1]
|
||||||
|
@ -151,17 +151,17 @@ pub fn (mut ftp FTP) pwd() ?string {
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut ftp FTP) cd(dir string) ? {
|
pub fn (mut zftp FTP) cd(dir string) ? {
|
||||||
ftp.write('CWD $dir') or { return }
|
zftp.write('CWD $dir') or { return }
|
||||||
mut code, mut data := ftp.read() ?
|
mut code, mut data := zftp.read() ?
|
||||||
match int(code) {
|
match int(code) {
|
||||||
denied {
|
ftp.denied {
|
||||||
$if debug {
|
$if debug {
|
||||||
println('CD $dir denied!')
|
println('CD $dir denied!')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
complete {
|
ftp.complete {
|
||||||
code, data = ftp.read() ?
|
code, data = zftp.read() ?
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
@ -178,6 +178,7 @@ fn new_dtp(msg string) ?&DTP {
|
||||||
mut dtp := &DTP{
|
mut dtp := &DTP{
|
||||||
ip: ip
|
ip: ip
|
||||||
port: port
|
port: port
|
||||||
|
conn: 0
|
||||||
}
|
}
|
||||||
conn := net.dial_tcp('$ip:$port') or { return error('Cannot connect to the data channel') }
|
conn := net.dial_tcp('$ip:$port') or { return error('Cannot connect to the data channel') }
|
||||||
dtp.conn = conn
|
dtp.conn = conn
|
||||||
|
@ -185,32 +186,32 @@ fn new_dtp(msg string) ?&DTP {
|
||||||
return dtp
|
return dtp
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut ftp FTP) pasv() ?&DTP {
|
fn (mut zftp FTP) pasv() ?&DTP {
|
||||||
ftp.write('PASV') ?
|
zftp.write('PASV') ?
|
||||||
code, data := ftp.read() ?
|
code, data := zftp.read() ?
|
||||||
$if debug {
|
$if debug {
|
||||||
println('pass: $data')
|
println('pass: $data')
|
||||||
}
|
}
|
||||||
if code != passive_mode {
|
if code != ftp.passive_mode {
|
||||||
return error('pasive mode not allowed')
|
return error('pasive mode not allowed')
|
||||||
}
|
}
|
||||||
dtp := new_dtp(data) ?
|
dtp := new_dtp(data) ?
|
||||||
return dtp
|
return dtp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut ftp FTP) dir() ?[]string {
|
pub fn (mut zftp FTP) dir() ?[]string {
|
||||||
mut dtp := ftp.pasv() or { return error('Cannot establish data connection') }
|
mut dtp := zftp.pasv() or { return error('Cannot establish data connection') }
|
||||||
ftp.write('LIST') ?
|
zftp.write('LIST') ?
|
||||||
code, _ := ftp.read() ?
|
code, _ := zftp.read() ?
|
||||||
if code == denied {
|
if code == ftp.denied {
|
||||||
return error('`LIST` denied')
|
return error('`LIST` denied')
|
||||||
}
|
}
|
||||||
if code != open_data_connection {
|
if code != ftp.open_data_connection {
|
||||||
return error('Data channel empty')
|
return error('Data channel empty')
|
||||||
}
|
}
|
||||||
list_dir := dtp.read() ?
|
list_dir := dtp.read() ?
|
||||||
result, _ := ftp.read() ?
|
result, _ := zftp.read() ?
|
||||||
if result != close_data_connection {
|
if result != ftp.close_data_connection {
|
||||||
println('`LIST` not ok')
|
println('`LIST` not ok')
|
||||||
}
|
}
|
||||||
dtp.close()
|
dtp.close()
|
||||||
|
@ -225,14 +226,14 @@ pub fn (mut ftp FTP) dir() ?[]string {
|
||||||
return dir
|
return dir
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut ftp FTP) get(file string) ?[]byte {
|
pub fn (mut zftp FTP) get(file string) ?[]byte {
|
||||||
mut dtp := ftp.pasv() or { return error('Cannot stablish data connection') }
|
mut dtp := zftp.pasv() or { return error('Cannot stablish data connection') }
|
||||||
ftp.write('RETR $file') ?
|
zftp.write('RETR $file') ?
|
||||||
code, _ := ftp.read() ?
|
code, _ := zftp.read() ?
|
||||||
if code == denied {
|
if code == ftp.denied {
|
||||||
return error('Permission denied')
|
return error('Permission denied')
|
||||||
}
|
}
|
||||||
if code != open_data_connection {
|
if code != ftp.open_data_connection {
|
||||||
return error('Data connection not ready')
|
return error('Data connection not ready')
|
||||||
}
|
}
|
||||||
blob := dtp.read() ?
|
blob := dtp.read() ?
|
||||||
|
|
|
@ -1,42 +1,49 @@
|
||||||
import net.ftp
|
import net.ftp
|
||||||
|
|
||||||
|
fn test_ftp_cleint() {
|
||||||
|
$if !network ? {
|
||||||
|
return
|
||||||
|
}
|
||||||
// NB: this function makes network calls to external servers,
|
// NB: this function makes network calls to external servers,
|
||||||
// that is why it is not a very good idea to run it in CI.
|
// that is why it is not a very good idea to run it in CI.
|
||||||
// If you want to run it manually, use `v -d network vlib/net/ftp/ftp_test.v`
|
// If you want to run it manually, use:
|
||||||
fn ftp_client_test_inside() ? {
|
// `v -d network vlib/net/ftp/ftp_test.v`
|
||||||
$if !network ? { return }
|
ftp_client_test_inside() or { panic(err) }
|
||||||
mut ftp := ftp.new()
|
|
||||||
defer {
|
|
||||||
ftp.close()
|
|
||||||
}
|
}
|
||||||
connect_result := ftp.connect('ftp.redhat.com')?
|
|
||||||
|
fn ftp_client_test_inside() ? {
|
||||||
|
mut zftp := ftp.new()
|
||||||
|
// eprintln(zftp)
|
||||||
|
defer {
|
||||||
|
zftp.close() or { panic(err) }
|
||||||
|
}
|
||||||
|
connect_result := zftp.connect('ftp.redhat.com') ?
|
||||||
assert connect_result
|
assert connect_result
|
||||||
login_result := ftp.login('ftp', 'ftp')?
|
login_result := zftp.login('ftp', 'ftp') ?
|
||||||
assert login_result
|
assert login_result
|
||||||
pwd := ftp.pwd()?
|
pwd := zftp.pwd() ?
|
||||||
assert pwd.len > 0
|
assert pwd.len > 0
|
||||||
ftp.cd('/')
|
zftp.cd('/') or {
|
||||||
dir_list1 := ftp.dir() or {
|
assert false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dir_list1 := zftp.dir() or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert dir_list1.len > 0
|
assert dir_list1.len > 0
|
||||||
ftp.cd('/suse/linux/enterprise/11Server/en/SAT-TOOLS/SRPMS/')
|
zftp.cd('/suse/linux/enterprise/11Server/en/SAT-TOOLS/SRPMS/') or {
|
||||||
dir_list2 := ftp.dir() or {
|
assert false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dir_list2 := zftp.dir() or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert dir_list2.len > 0
|
assert dir_list2.len > 0
|
||||||
blob := ftp.get('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') or {
|
blob := zftp.get('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert blob.len > 0
|
assert blob.len > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn test_ftp_cleint() {
|
|
||||||
ftp_client_test_inside() or {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,9 +9,7 @@ pub fn download_file(url string, out string)? {
|
||||||
$if debug_http ? {
|
$if debug_http ? {
|
||||||
println('download file url=$url out=$out')
|
println('download file url=$url out=$out')
|
||||||
}
|
}
|
||||||
s := get(url) or {
|
s := get(url) or { return error(err) }
|
||||||
return error(err)
|
os.write_file(out, s.text) ?
|
||||||
}
|
|
||||||
os.write_file(out, s.text)
|
|
||||||
// download_file_with_progress(url, out, empty, empty)
|
// download_file_with_progress(url, out, empty, empty)
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,33 +67,48 @@ pub fn get(url string) ?Response {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post(url string, data string) ?Response {
|
pub fn post(url string, data string) ?Response {
|
||||||
return fetch_with_method(.post, url, data: data, headers: {
|
return fetch_with_method(.post, url,
|
||||||
'Content-Type': content_type_default
|
data: data
|
||||||
})
|
headers: {
|
||||||
|
'Content-Type': http.content_type_default
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_json(url string, data string) ?Response {
|
pub fn post_json(url string, data string) ?Response {
|
||||||
return fetch_with_method(.post, url, data: data, headers: {
|
return fetch_with_method(.post, url,
|
||||||
|
data: data
|
||||||
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_form(url string, data map[string]string) ?Response {
|
pub fn post_form(url string, data map[string]string) ?Response {
|
||||||
return fetch_with_method(.post, url, headers: {
|
return fetch_with_method(.post, url,
|
||||||
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
}, data: url_encode_form_data(data))
|
}
|
||||||
|
data: url_encode_form_data(data)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(url string, data string) ?Response {
|
pub fn put(url string, data string) ?Response {
|
||||||
return fetch_with_method(.put, url, data: data, headers: {
|
return fetch_with_method(.put, url,
|
||||||
'Content-Type': content_type_default
|
data: data
|
||||||
})
|
headers: {
|
||||||
|
'Content-Type': http.content_type_default
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn patch(url string, data string) ?Response {
|
pub fn patch(url string, data string) ?Response {
|
||||||
return fetch_with_method(.patch, url, data: data, headers: {
|
return fetch_with_method(.patch, url,
|
||||||
'Content-Type': content_type_default
|
data: data
|
||||||
})
|
headers: {
|
||||||
|
'Content-Type': http.content_type_default
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn head(url string) ?Response {
|
pub fn head(url string) ?Response {
|
||||||
|
@ -199,8 +214,8 @@ pub fn (req &Request) do() ?Response {
|
||||||
mut resp := Response{}
|
mut resp := Response{}
|
||||||
mut no_redirects := 0
|
mut no_redirects := 0
|
||||||
for {
|
for {
|
||||||
if no_redirects == max_redirects {
|
if no_redirects == http.max_redirects {
|
||||||
return error('http.request.do: maximum number of redirects reached ($max_redirects)')
|
return error('http.request.do: maximum number of redirects reached ($http.max_redirects)')
|
||||||
}
|
}
|
||||||
qresp := req.method_and_url_to_response(req.method, rurl) ?
|
qresp := req.method_and_url_to_response(req.method, rurl) ?
|
||||||
resp = qresp
|
resp = qresp
|
||||||
|
@ -366,7 +381,7 @@ fn (req &Request) http_do(host string, method Method, path string) ?Response {
|
||||||
// TODO this really needs to be exposed somehow
|
// TODO this really needs to be exposed somehow
|
||||||
client.write(s.bytes()) ?
|
client.write(s.bytes()) ?
|
||||||
mut bytes := io.read_all(reader: client) ?
|
mut bytes := io.read_all(reader: client) ?
|
||||||
client.close()
|
client.close() ?
|
||||||
return parse_response(bytes.bytestr())
|
return parse_response(bytes.bytestr())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,8 +96,8 @@ pub fn (mut c Client) send(config Mail) ? {
|
||||||
|
|
||||||
// quit closes the connection to the server
|
// quit closes the connection to the server
|
||||||
pub fn (mut c Client) quit() ? {
|
pub fn (mut c Client) quit() ? {
|
||||||
c.send_str('QUIT\r\n')
|
c.send_str('QUIT\r\n') ?
|
||||||
c.expect_reply(.close)
|
c.expect_reply(.close) ?
|
||||||
c.conn.close() ?
|
c.conn.close() ?
|
||||||
c.is_open = false
|
c.is_open = false
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ fn (mut c Client) send_mailto(to string) ? {
|
||||||
|
|
||||||
fn (mut c Client) send_data() ? {
|
fn (mut c Client) send_data() ? {
|
||||||
c.send_str('DATA\r\n') ?
|
c.send_str('DATA\r\n') ?
|
||||||
c.expect_reply(.mail_start)
|
c.expect_reply(.mail_start) ?
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Client) send_body(cfg Mail) ? {
|
fn (mut c Client) send_body(cfg Mail) ? {
|
||||||
|
|
|
@ -22,8 +22,8 @@ pub fn dial_tcp(address string) ?&TcpConn {
|
||||||
s.connect(address) ?
|
s.connect(address) ?
|
||||||
return &TcpConn{
|
return &TcpConn{
|
||||||
sock: s
|
sock: s
|
||||||
read_timeout: tcp_default_read_timeout
|
read_timeout: net.tcp_default_read_timeout
|
||||||
write_timeout: tcp_default_write_timeout
|
write_timeout: net.tcp_default_write_timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,8 @@ pub fn (mut c TcpConn) close() ? {
|
||||||
// write_ptr blocks and attempts to write all data
|
// write_ptr blocks and attempts to write all data
|
||||||
pub fn (mut c TcpConn) write_ptr(b byteptr, len int) ? {
|
pub fn (mut c TcpConn) write_ptr(b byteptr, len int) ? {
|
||||||
$if trace_tcp ? {
|
$if trace_tcp ? {
|
||||||
eprintln('>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
|
eprintln(
|
||||||
|
'>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
|
||||||
unsafe { b.vstring_with_len(len) })
|
unsafe { b.vstring_with_len(len) })
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -48,7 +49,7 @@ pub fn (mut c TcpConn) write_ptr(b byteptr, len int) ? {
|
||||||
if sent < 0 {
|
if sent < 0 {
|
||||||
code := error_code()
|
code := error_code()
|
||||||
if code == int(error_ewouldblock) {
|
if code == int(error_ewouldblock) {
|
||||||
c.wait_for_write()
|
c.wait_for_write() ?
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
wrap_error(code) ?
|
wrap_error(code) ?
|
||||||
|
@ -164,9 +165,9 @@ pub fn (c &TcpConn) peer_ip() ?string {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c &TcpConn) str() string {
|
pub fn (c TcpConn) str() string {
|
||||||
// TODO
|
s := c.sock.str().replace('\n', ' ').replace(' ', ' ')
|
||||||
return 'TcpConn {write_deadline: $c.write_deadline, read_deadline: $c.read_deadline, read_timeout: $c.read_timeout, write_timeout: $c.write_timeout, sock: $c.sock}'
|
return 'TcpConn{ write_deadline: $c.write_deadline, read_deadline: $c.read_deadline, read_timeout: $c.read_timeout, write_timeout: $c.write_timeout, sock: $s }'
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TcpListener {
|
pub struct TcpListener {
|
||||||
|
@ -213,8 +214,8 @@ pub fn (mut l TcpListener) accept() ?&TcpConn {
|
||||||
new_sock := tcp_socket_from_handle(new_handle) ?
|
new_sock := tcp_socket_from_handle(new_handle) ?
|
||||||
return &TcpConn{
|
return &TcpConn{
|
||||||
sock: new_sock
|
sock: new_sock
|
||||||
read_timeout: tcp_default_read_timeout
|
read_timeout: net.tcp_default_read_timeout
|
||||||
write_timeout: tcp_default_write_timeout
|
write_timeout: net.tcp_default_write_timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +267,7 @@ fn new_tcp_socket() ?TcpSocket {
|
||||||
t := true
|
t := true
|
||||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t)) ?
|
socket_error(C.ioctlsocket(sockfd, fionbio, &t)) ?
|
||||||
} $else {
|
} $else {
|
||||||
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK))
|
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK)) ?
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -281,7 +282,7 @@ fn tcp_socket_from_handle(sockfd int) ?TcpSocket {
|
||||||
t := true
|
t := true
|
||||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t)) ?
|
socket_error(C.ioctlsocket(sockfd, fionbio, &t)) ?
|
||||||
} $else {
|
} $else {
|
||||||
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK))
|
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK)) ?
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -322,12 +323,12 @@ fn (mut s TcpSocket) connect(a string) ? {
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
_ := error_code()
|
_ := error_code()
|
||||||
write_result := s.@select(.write, connect_timeout) ?
|
write_result := s.@select(.write, net.connect_timeout) ?
|
||||||
if write_result {
|
if write_result {
|
||||||
// succeeded
|
// succeeded
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
except_result := s.@select(.except, connect_timeout) ?
|
except_result := s.@select(.except, net.connect_timeout) ?
|
||||||
if except_result {
|
if except_result {
|
||||||
return err_connect_failed
|
return err_connect_failed
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,10 @@ fn test_socket_write_and_read() {
|
||||||
message1 := 'a message 1'
|
message1 := 'a message 1'
|
||||||
socket.write_str(message1) or { assert false }
|
socket.write_str(message1) or { assert false }
|
||||||
mut rbuf := []byte{len: message1.len}
|
mut rbuf := []byte{len: message1.len}
|
||||||
client.read(mut rbuf)
|
client.read(mut rbuf) or {
|
||||||
|
assert false
|
||||||
|
return
|
||||||
|
}
|
||||||
line := rbuf.bytestr()
|
line := rbuf.bytestr()
|
||||||
assert line == message1
|
assert line == message1
|
||||||
}
|
}
|
||||||
|
@ -127,8 +130,14 @@ fn test_socket_read_line_long_line_without_eol() {
|
||||||
cleanup(mut server, mut client, mut socket)
|
cleanup(mut server, mut client, mut socket)
|
||||||
}
|
}
|
||||||
message := strings.repeat_string('123', 400)
|
message := strings.repeat_string('123', 400)
|
||||||
socket.write_str(message)
|
socket.write_str(message) or {
|
||||||
socket.write_str('\n')
|
assert false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
socket.write_str('\n') or {
|
||||||
|
assert false
|
||||||
|
return
|
||||||
|
}
|
||||||
line := reader.read_line() or {
|
line := reader.read_line() or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
|
|
|
@ -33,8 +33,8 @@ pub fn dial_udp(laddr string, raddr string) ?&UdpConn {
|
||||||
}
|
}
|
||||||
return &UdpConn{
|
return &UdpConn{
|
||||||
sock: sock
|
sock: sock
|
||||||
read_timeout: udp_default_read_timeout
|
read_timeout: net.udp_default_read_timeout
|
||||||
write_timeout: udp_default_write_timeout
|
write_timeout: net.udp_default_write_timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,8 +162,8 @@ pub fn listen_udp(port int) ?&UdpConn {
|
||||||
s := new_udp_socket(port) ?
|
s := new_udp_socket(port) ?
|
||||||
return &UdpConn{
|
return &UdpConn{
|
||||||
sock: s
|
sock: s
|
||||||
read_timeout: udp_default_read_timeout
|
read_timeout: net.udp_default_read_timeout
|
||||||
write_timeout: udp_default_write_timeout
|
write_timeout: net.udp_default_write_timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ fn new_udp_socket(local_port int) ?&UdpSocket {
|
||||||
t := true
|
t := true
|
||||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t)) ?
|
socket_error(C.ioctlsocket(sockfd, fionbio, &t)) ?
|
||||||
} $else {
|
} $else {
|
||||||
socket_error(C.fcntl(sockfd, C.F_SETFD, C.O_NONBLOCK))
|
socket_error(C.fcntl(sockfd, C.F_SETFD, C.O_NONBLOCK)) ?
|
||||||
}
|
}
|
||||||
// In UDP we always have to bind to a port
|
// In UDP we always have to bind to a port
|
||||||
validate_port(local_port) ?
|
validate_port(local_port) ?
|
||||||
|
|
|
@ -53,8 +53,8 @@ fn should_escape(c byte, mode EncodingMode) bool {
|
||||||
// we could possibly allow, and parse will reject them if we
|
// we could possibly allow, and parse will reject them if we
|
||||||
// escape them (because hosts can`t use %-encoding for
|
// escape them (because hosts can`t use %-encoding for
|
||||||
// ASCII bytes).
|
// ASCII bytes).
|
||||||
if c in
|
if
|
||||||
[`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] {
|
c in [`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ fn unescape(s_ string, mode EncodingMode) ?string {
|
||||||
if s.len > 3 {
|
if s.len > 3 {
|
||||||
s = s[..3]
|
s = s[..3]
|
||||||
}
|
}
|
||||||
return error(error_msg(err_msg_escape, s))
|
return error(error_msg(urllib.err_msg_escape, s))
|
||||||
}
|
}
|
||||||
// Per https://tools.ietf.org/html/rfc3986#page-21
|
// Per https://tools.ietf.org/html/rfc3986#page-21
|
||||||
// in the host component %-encoding can only be used
|
// in the host component %-encoding can only be used
|
||||||
|
@ -171,7 +171,7 @@ fn unescape(s_ string, mode EncodingMode) ?string {
|
||||||
// introduces %25 being allowed to escape a percent sign
|
// introduces %25 being allowed to escape a percent sign
|
||||||
// in IPv6 scoped-address literals. Yay.
|
// in IPv6 scoped-address literals. Yay.
|
||||||
if mode == .encode_host && unhex(s[i + 1]) < 8 && s[i..i + 3] != '%25' {
|
if mode == .encode_host && unhex(s[i + 1]) < 8 && s[i..i + 3] != '%25' {
|
||||||
return error(error_msg(err_msg_escape, s[i..i + 3]))
|
return error(error_msg(urllib.err_msg_escape, s[i..i + 3]))
|
||||||
}
|
}
|
||||||
if mode == .encode_zone {
|
if mode == .encode_zone {
|
||||||
// RFC 6874 says basically 'anything goes' for zone identifiers
|
// RFC 6874 says basically 'anything goes' for zone identifiers
|
||||||
|
@ -183,7 +183,7 @@ fn unescape(s_ string, mode EncodingMode) ?string {
|
||||||
// But Windows puts spaces here! Yay.
|
// But Windows puts spaces here! Yay.
|
||||||
v := ((unhex(s[i + 1]) << byte(4)) | unhex(s[i + 2]))
|
v := ((unhex(s[i + 1]) << byte(4)) | unhex(s[i + 2]))
|
||||||
if s[i..i + 3] != '%25' && v != ` ` && should_escape(v, .encode_host) {
|
if s[i..i + 3] != '%25' && v != ` ` && should_escape(v, .encode_host) {
|
||||||
error(error_msg(err_msg_escape, s[i..i + 3]))
|
error(error_msg(urllib.err_msg_escape, s[i..i + 3]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i += 3
|
i += 3
|
||||||
|
@ -193,9 +193,8 @@ fn unescape(s_ string, mode EncodingMode) ?string {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (mode == .encode_host ||
|
if (mode == .encode_host || mode == .encode_zone) && s[i] < 0x80
|
||||||
mode == .encode_zone) &&
|
&& should_escape(s[i], mode) {
|
||||||
s[i] < 0x80 && should_escape(s[i], mode) {
|
|
||||||
error(error_msg('unescape: invalid character in host name', s[i..i + 1]))
|
error(error_msg('unescape: invalid character in host name', s[i..i + 1]))
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
|
@ -429,11 +428,12 @@ fn split(s string, sep byte, cutc bool) (string, string) {
|
||||||
pub fn parse(rawurl string) ?URL {
|
pub fn parse(rawurl string) ?URL {
|
||||||
// Cut off #frag
|
// Cut off #frag
|
||||||
u, frag := split(rawurl, `#`, true)
|
u, frag := split(rawurl, `#`, true)
|
||||||
mut url := parse_url(u, false) or { return error(error_msg(err_msg_parse, u)) }
|
mut url := parse_url(u, false) or { return error(error_msg(urllib.err_msg_parse, u)) }
|
||||||
if frag == '' {
|
if frag == '' {
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
f := unescape(frag, .encode_fragment) or { return error(error_msg(err_msg_parse, u)) }
|
f := unescape(frag, .encode_fragment) or { return error(error_msg(urllib.err_msg_parse,
|
||||||
|
u)) }
|
||||||
url.fragment = f
|
url.fragment = f
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
@ -570,7 +570,7 @@ fn parse_host(host string) ?string {
|
||||||
// parse an IP-Literal in RFC 3986 and RFC 6874.
|
// parse an IP-Literal in RFC 3986 and RFC 6874.
|
||||||
// E.g., '[fe80::1]', '[fe80::1%25en0]', '[fe80::1]:80'.
|
// E.g., '[fe80::1]', '[fe80::1%25en0]', '[fe80::1]:80'.
|
||||||
mut i := host.last_index(']') or {
|
mut i := host.last_index(']') or {
|
||||||
return error(error_msg("parse_host: missing \']\' in host", ''))
|
return error(error_msg("parse_host: missing ']' in host", ''))
|
||||||
}
|
}
|
||||||
mut colon_port := host[i + 1..]
|
mut colon_port := host[i + 1..]
|
||||||
if !valid_optional_port(colon_port) {
|
if !valid_optional_port(colon_port) {
|
||||||
|
@ -785,7 +785,7 @@ pub fn parse_query(query string) ?Values {
|
||||||
// but any errors will be silent
|
// but any errors will be silent
|
||||||
fn parse_query_silent(query string) Values {
|
fn parse_query_silent(query string) Values {
|
||||||
mut m := new_values()
|
mut m := new_values()
|
||||||
parse_query_values(mut m, query)
|
parse_query_values(mut m, query) or { }
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1029,7 +1029,8 @@ pub fn valid_userinfo(s string) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
match r {
|
match r {
|
||||||
`-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`, `@` {
|
`-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`,
|
||||||
|
`@` {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -9,16 +9,16 @@ const (
|
||||||
|
|
||||||
fn testsuite_begin() {
|
fn testsuite_begin() {
|
||||||
eprintln('testsuite_begin, tfolder = $tfolder')
|
eprintln('testsuite_begin, tfolder = $tfolder')
|
||||||
os.rmdir_all(tfolder)
|
os.rmdir_all(tfolder) or { }
|
||||||
assert !os.is_dir(tfolder)
|
assert !os.is_dir(tfolder)
|
||||||
os.mkdir_all(tfolder)
|
os.mkdir_all(tfolder) or { panic(err) }
|
||||||
os.chdir(tfolder)
|
os.chdir(tfolder)
|
||||||
assert os.is_dir(tfolder)
|
assert os.is_dir(tfolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testsuite_end() {
|
fn testsuite_end() {
|
||||||
os.chdir(os.wd_at_startup)
|
os.chdir(os.wd_at_startup)
|
||||||
os.rmdir_all(tfolder)
|
os.rmdir_all(tfolder) or { panic(err) }
|
||||||
assert !os.is_dir(tfolder)
|
assert !os.is_dir(tfolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ fn test_inode_file_type() {
|
||||||
mut file := os.open_file(filename, 'w', 0o600) or { return }
|
mut file := os.open_file(filename, 'w', 0o600) or { return }
|
||||||
file.close()
|
file.close()
|
||||||
mode := os.inode(filename)
|
mode := os.inode(filename)
|
||||||
os.rm(filename)
|
os.rm(filename) or { panic(err) }
|
||||||
assert mode.typ == .regular
|
assert mode.typ == .regular
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ fn test_inode_file_owner_permission() {
|
||||||
mut file := os.open_file(filename, 'w', 0o600) or { return }
|
mut file := os.open_file(filename, 'w', 0o600) or { return }
|
||||||
file.close()
|
file.close()
|
||||||
mode := os.inode(filename)
|
mode := os.inode(filename)
|
||||||
os.rm(filename)
|
os.rm(filename) or { }
|
||||||
assert mode.owner.read
|
assert mode.owner.read
|
||||||
assert mode.owner.write
|
assert mode.owner.write
|
||||||
assert !mode.owner.execute
|
assert !mode.owner.execute
|
||||||
|
|
10
vlib/os/os.v
10
vlib/os/os.v
|
@ -46,7 +46,7 @@ pub fn cp_all(src string, dst string, overwrite bool) ? {
|
||||||
}
|
}
|
||||||
if exists(adjusted_path) {
|
if exists(adjusted_path) {
|
||||||
if overwrite {
|
if overwrite {
|
||||||
rm(adjusted_path)
|
rm(adjusted_path) ?
|
||||||
} else {
|
} else {
|
||||||
return error('Destination file path already exist')
|
return error('Destination file path already exist')
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ pub fn cp_all(src string, dst string, overwrite bool) ? {
|
||||||
mkdir(dp) ?
|
mkdir(dp) ?
|
||||||
}
|
}
|
||||||
cp_all(sp, dp, overwrite) or {
|
cp_all(sp, dp, overwrite) or {
|
||||||
rmdir(dp)
|
rmdir(dp) or { return error(err) }
|
||||||
return error(err)
|
return error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ pub fn file_exists(_path string) bool {
|
||||||
[deprecated]
|
[deprecated]
|
||||||
pub fn rmdir_recursive(path string) {
|
pub fn rmdir_recursive(path string) {
|
||||||
eprintln('warning: `os.rmdir_recursive` has been deprecated, use `os.rmdir_all` instead')
|
eprintln('warning: `os.rmdir_recursive` has been deprecated, use `os.rmdir_all` instead')
|
||||||
rmdir_all(path)
|
rmdir_all(path) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// rmdir_all recursively removes the specified directory.
|
// rmdir_all recursively removes the specified directory.
|
||||||
|
@ -154,7 +154,7 @@ pub fn rmdir_all(path string) ? {
|
||||||
for item in items {
|
for item in items {
|
||||||
fullpath := join_path(path, item)
|
fullpath := join_path(path, item)
|
||||||
if is_dir(fullpath) {
|
if is_dir(fullpath) {
|
||||||
rmdir_all(fullpath)
|
rmdir_all(fullpath) or { ret_err = err }
|
||||||
}
|
}
|
||||||
rm(fullpath) or { ret_err = err }
|
rm(fullpath) or { ret_err = err }
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,7 @@ pub fn home_dir() string {
|
||||||
// write_file writes `text` data to a file in `path`.
|
// write_file writes `text` data to a file in `path`.
|
||||||
pub fn write_file(path string, text string) ? {
|
pub fn write_file(path string, text string) ? {
|
||||||
mut f := create(path) ?
|
mut f := create(path) ?
|
||||||
f.write(text.bytes())
|
f.write(text.bytes()) ?
|
||||||
f.close()
|
f.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -280,7 +280,7 @@ pub fn is_writable_folder(folder string) ?bool {
|
||||||
}
|
}
|
||||||
C.close(x)
|
C.close(x)
|
||||||
}
|
}
|
||||||
rm(tmp_perm_check)
|
rm(tmp_perm_check) ?
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ const args_at_start = os.args.clone()
|
||||||
|
|
||||||
fn testsuite_begin() {
|
fn testsuite_begin() {
|
||||||
eprintln('testsuite_begin, tfolder = $tfolder')
|
eprintln('testsuite_begin, tfolder = $tfolder')
|
||||||
os.rmdir_all(tfolder)
|
os.rmdir_all(tfolder) or { }
|
||||||
assert !os.is_dir(tfolder)
|
assert !os.is_dir(tfolder)
|
||||||
os.mkdir_all(tfolder)
|
os.mkdir_all(tfolder) or { panic(err) }
|
||||||
os.chdir(tfolder)
|
os.chdir(tfolder)
|
||||||
assert os.is_dir(tfolder)
|
assert os.is_dir(tfolder)
|
||||||
// println('args_at_start: $args_at_start')
|
// println('args_at_start: $args_at_start')
|
||||||
|
@ -25,7 +25,7 @@ fn testsuite_begin() {
|
||||||
|
|
||||||
fn testsuite_end() {
|
fn testsuite_end() {
|
||||||
os.chdir(os.wd_at_startup)
|
os.chdir(os.wd_at_startup)
|
||||||
os.rmdir_all(tfolder)
|
os.rmdir_all(tfolder) or { }
|
||||||
assert !os.is_dir(tfolder)
|
assert !os.is_dir(tfolder)
|
||||||
// eprintln('testsuite_end , tfolder = $tfolder removed.')
|
// eprintln('testsuite_end , tfolder = $tfolder removed.')
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,12 @@ fn test_open_file() {
|
||||||
os.File{}
|
os.File{}
|
||||||
}
|
}
|
||||||
mut file := os.open_file(filename, 'w+', 0o666) or { panic(err) }
|
mut file := os.open_file(filename, 'w+', 0o666) or { panic(err) }
|
||||||
file.write_str(hello)
|
file.write_str(hello) or { panic(err) }
|
||||||
file.close()
|
file.close()
|
||||||
assert hello.len == os.file_size(filename)
|
assert hello.len == os.file_size(filename)
|
||||||
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
||||||
assert hello == read_hello
|
assert hello == read_hello
|
||||||
os.rm(filename)
|
os.rm(filename) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_open_file_binary() {
|
fn test_open_file_binary() {
|
||||||
|
@ -60,7 +60,7 @@ fn test_open_file_binary() {
|
||||||
assert hello.len == os.file_size(filename)
|
assert hello.len == os.file_size(filename)
|
||||||
read_hello := os.read_bytes(filename) or { panic('error reading file $filename') }
|
read_hello := os.read_bytes(filename) or { panic('error reading file $filename') }
|
||||||
assert bytes == read_hello
|
assert bytes == read_hello
|
||||||
os.rm(filename)
|
os.rm(filename) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn test_file_get_line() {
|
// fn test_file_get_line() {
|
||||||
|
@ -87,23 +87,23 @@ fn test_create_file() {
|
||||||
filename := './test1.txt'
|
filename := './test1.txt'
|
||||||
hello := 'hello world!'
|
hello := 'hello world!'
|
||||||
mut f := os.create(filename) or { panic(err) }
|
mut f := os.create(filename) or { panic(err) }
|
||||||
f.write_str(hello)
|
f.write_str(hello) or { panic(err) }
|
||||||
f.close()
|
f.close()
|
||||||
assert hello.len == os.file_size(filename)
|
assert hello.len == os.file_size(filename)
|
||||||
os.rm(filename)
|
os.rm(filename) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_is_file() {
|
fn test_is_file() {
|
||||||
// Setup
|
// Setup
|
||||||
work_dir := os.join_path(os.getwd(), 'is_file_test')
|
work_dir := os.join_path(os.getwd(), 'is_file_test')
|
||||||
os.mkdir_all(work_dir)
|
os.mkdir_all(work_dir) or { panic(err) }
|
||||||
tfile := os.join_path(work_dir, 'tmp_file')
|
tfile := os.join_path(work_dir, 'tmp_file')
|
||||||
// Test things that shouldn't be a file
|
// Test things that shouldn't be a file
|
||||||
assert os.is_file(work_dir) == false
|
assert os.is_file(work_dir) == false
|
||||||
assert os.is_file('non-existent_file.tmp') == false
|
assert os.is_file('non-existent_file.tmp') == false
|
||||||
// Test file
|
// Test file
|
||||||
tfile_content := 'temporary file'
|
tfile_content := 'temporary file'
|
||||||
os.write_file(tfile, tfile_content)
|
os.write_file(tfile, tfile_content) or { panic(err) }
|
||||||
assert os.is_file(tfile)
|
assert os.is_file(tfile)
|
||||||
// Test dir symlinks
|
// Test dir symlinks
|
||||||
$if windows {
|
$if windows {
|
||||||
|
@ -126,11 +126,11 @@ fn test_is_file() {
|
||||||
fn test_write_and_read_string_to_file() {
|
fn test_write_and_read_string_to_file() {
|
||||||
filename := './test1.txt'
|
filename := './test1.txt'
|
||||||
hello := 'hello world!'
|
hello := 'hello world!'
|
||||||
os.write_file(filename, hello)
|
os.write_file(filename, hello) or { panic(err) }
|
||||||
assert hello.len == os.file_size(filename)
|
assert hello.len == os.file_size(filename)
|
||||||
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
||||||
assert hello == read_hello
|
assert hello == read_hello
|
||||||
os.rm(filename)
|
os.rm(filename) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// test_write_and_read_bytes checks for regressions made in the functions
|
// test_write_and_read_bytes checks for regressions made in the functions
|
||||||
|
@ -166,7 +166,7 @@ fn test_write_and_read_bytes() {
|
||||||
assert nread == 0
|
assert nread == 0
|
||||||
file_read.close()
|
file_read.close()
|
||||||
// We finally delete the test file.
|
// We finally delete the test file.
|
||||||
os.rm(file_name)
|
os.rm(file_name) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_create_and_delete_folder() {
|
fn test_create_and_delete_folder() {
|
||||||
|
@ -175,7 +175,7 @@ fn test_create_and_delete_folder() {
|
||||||
assert os.is_dir(folder)
|
assert os.is_dir(folder)
|
||||||
folder_contents := os.ls(folder) or { panic(err) }
|
folder_contents := os.ls(folder) or { panic(err) }
|
||||||
assert folder_contents.len == 0
|
assert folder_contents.len == 0
|
||||||
os.rmdir(folder)
|
os.rmdir(folder) or { panic(err) }
|
||||||
folder_exists := os.is_dir(folder)
|
folder_exists := os.is_dir(folder)
|
||||||
assert folder_exists == false
|
assert folder_exists == false
|
||||||
}
|
}
|
||||||
|
@ -191,61 +191,61 @@ fn test_walk() {
|
||||||
folder := 'test_walk'
|
folder := 'test_walk'
|
||||||
os.mkdir(folder) or { panic(err) }
|
os.mkdir(folder) or { panic(err) }
|
||||||
file1 := folder + os.path_separator + 'test1'
|
file1 := folder + os.path_separator + 'test1'
|
||||||
os.write_file(file1, 'test-1')
|
os.write_file(file1, 'test-1') or { panic(err) }
|
||||||
os.walk(folder, walk_callback)
|
os.walk(folder, walk_callback)
|
||||||
os.rm(file1)
|
os.rm(file1) or { panic(err) }
|
||||||
os.rmdir(folder)
|
os.rmdir(folder) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_cp() {
|
fn test_cp() {
|
||||||
old_file_name := 'cp_example.txt'
|
old_file_name := 'cp_example.txt'
|
||||||
new_file_name := 'cp_new_example.txt'
|
new_file_name := 'cp_new_example.txt'
|
||||||
os.write_file(old_file_name, 'Test data 1 2 3, V is awesome #$%^[]!~⭐')
|
os.write_file(old_file_name, 'Test data 1 2 3, V is awesome #$%^[]!~⭐') or { panic(err) }
|
||||||
os.cp(old_file_name, new_file_name) or { panic('$err: errcode: $errcode') }
|
os.cp(old_file_name, new_file_name) or { panic('$err: errcode: $errcode') }
|
||||||
old_file := os.read_file(old_file_name) or { panic(err) }
|
old_file := os.read_file(old_file_name) or { panic(err) }
|
||||||
new_file := os.read_file(new_file_name) or { panic(err) }
|
new_file := os.read_file(new_file_name) or { panic(err) }
|
||||||
assert old_file == new_file
|
assert old_file == new_file
|
||||||
os.rm(old_file_name)
|
os.rm(old_file_name) or { panic(err) }
|
||||||
os.rm(new_file_name)
|
os.rm(new_file_name) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_mv() {
|
fn test_mv() {
|
||||||
work_dir := os.join_path(os.getwd(), 'mv_test')
|
work_dir := os.join_path(os.getwd(), 'mv_test')
|
||||||
os.mkdir_all(work_dir)
|
os.mkdir_all(work_dir) or { panic(err) }
|
||||||
// Setup test files
|
// Setup test files
|
||||||
tfile1 := os.join_path(work_dir, 'file')
|
tfile1 := os.join_path(work_dir, 'file')
|
||||||
tfile2 := os.join_path(work_dir, 'file.test')
|
tfile2 := os.join_path(work_dir, 'file.test')
|
||||||
tfile3 := os.join_path(work_dir, 'file.3')
|
tfile3 := os.join_path(work_dir, 'file.3')
|
||||||
tfile_content := 'temporary file'
|
tfile_content := 'temporary file'
|
||||||
os.write_file(tfile1, tfile_content)
|
os.write_file(tfile1, tfile_content) or { panic(err) }
|
||||||
os.write_file(tfile2, tfile_content)
|
os.write_file(tfile2, tfile_content) or { panic(err) }
|
||||||
// Setup test dirs
|
// Setup test dirs
|
||||||
tdir1 := os.join_path(work_dir, 'dir')
|
tdir1 := os.join_path(work_dir, 'dir')
|
||||||
tdir2 := os.join_path(work_dir, 'dir2')
|
tdir2 := os.join_path(work_dir, 'dir2')
|
||||||
tdir3 := os.join_path(work_dir, 'dir3')
|
tdir3 := os.join_path(work_dir, 'dir3')
|
||||||
mkdir(tdir1)
|
os.mkdir(tdir1) or { panic(err) }
|
||||||
mkdir(tdir2)
|
os.mkdir(tdir2) or { panic(err) }
|
||||||
// Move file with no extension to dir
|
// Move file with no extension to dir
|
||||||
os.mv(tfile1, tdir1)
|
os.mv(tfile1, tdir1) or { panic(err) }
|
||||||
mut expected := os.join_path(tdir1, 'file')
|
mut expected := os.join_path(tdir1, 'file')
|
||||||
assert os.exists(expected) && !is_dir(expected) == true
|
assert os.exists(expected) && !is_dir(expected) == true
|
||||||
// Move dir with contents to other dir
|
// Move dir with contents to other dir
|
||||||
os.mv(tdir1, tdir2)
|
os.mv(tdir1, tdir2) or { panic(err) }
|
||||||
expected = os.join_path(tdir2, 'dir')
|
expected = os.join_path(tdir2, 'dir')
|
||||||
assert os.exists(expected) && is_dir(expected) == true
|
assert os.exists(expected) && is_dir(expected) == true
|
||||||
expected = os.join_path(tdir2, 'dir', 'file')
|
expected = os.join_path(tdir2, 'dir', 'file')
|
||||||
assert os.exists(expected) && !is_dir(expected) == true
|
assert os.exists(expected) && !is_dir(expected) == true
|
||||||
// Move dir with contents to other dir (by renaming)
|
// Move dir with contents to other dir (by renaming)
|
||||||
os.mv(os.join_path(tdir2, 'dir'), tdir3)
|
os.mv(os.join_path(tdir2, 'dir'), tdir3) or { panic(err) }
|
||||||
expected = tdir3
|
expected = tdir3
|
||||||
assert os.exists(expected) && is_dir(expected) == true
|
assert os.exists(expected) && is_dir(expected) == true
|
||||||
assert os.is_dir_empty(tdir2) == true
|
assert os.is_dir_empty(tdir2) == true
|
||||||
// Move file with extension to dir
|
// Move file with extension to dir
|
||||||
os.mv(tfile2, tdir2)
|
os.mv(tfile2, tdir2) or { panic(err) }
|
||||||
expected = os.join_path(tdir2, 'file.test')
|
expected = os.join_path(tdir2, 'file.test')
|
||||||
assert os.exists(expected) && !is_dir(expected) == true
|
assert os.exists(expected) && !is_dir(expected) == true
|
||||||
// Move file to dir (by renaming)
|
// Move file to dir (by renaming)
|
||||||
os.mv(os.join_path(tdir2, 'file.test'), tfile3)
|
os.mv(os.join_path(tdir2, 'file.test'), tfile3) or { panic(err) }
|
||||||
expected = tfile3
|
expected = tfile3
|
||||||
assert os.exists(expected) && !is_dir(expected) == true
|
assert os.exists(expected) && !is_dir(expected) == true
|
||||||
}
|
}
|
||||||
|
@ -253,14 +253,14 @@ fn test_mv() {
|
||||||
fn test_cp_r() {
|
fn test_cp_r() {
|
||||||
// fileX -> dir/fileX
|
// fileX -> dir/fileX
|
||||||
// NB: clean up of the files happens inside the cleanup_leftovers function
|
// NB: clean up of the files happens inside the cleanup_leftovers function
|
||||||
os.write_file('ex1.txt', 'wow!')
|
os.write_file('ex1.txt', 'wow!') or { panic(err) }
|
||||||
os.mkdir('ex') or { panic(err) }
|
os.mkdir('ex') or { panic(err) }
|
||||||
os.cp_all('ex1.txt', 'ex', false) or { panic(err) }
|
os.cp_all('ex1.txt', 'ex', false) or { panic(err) }
|
||||||
old := os.read_file('ex1.txt') or { panic(err) }
|
old := os.read_file('ex1.txt') or { panic(err) }
|
||||||
new := os.read_file('ex/ex1.txt') or { panic(err) }
|
new := os.read_file('ex/ex1.txt') or { panic(err) }
|
||||||
assert old == new
|
assert old == new
|
||||||
os.mkdir('ex/ex2') or { panic(err) }
|
os.mkdir('ex/ex2') or { panic(err) }
|
||||||
os.write_file('ex2.txt', 'great!')
|
os.write_file('ex2.txt', 'great!') or { panic(err) }
|
||||||
os.cp_all('ex2.txt', 'ex/ex2', false) or { panic(err) }
|
os.cp_all('ex2.txt', 'ex/ex2', false) or { panic(err) }
|
||||||
old2 := os.read_file('ex2.txt') or { panic(err) }
|
old2 := os.read_file('ex2.txt') or { panic(err) }
|
||||||
new2 := os.read_file('ex/ex2/ex2.txt') or { panic(err) }
|
new2 := os.read_file('ex/ex2/ex2.txt') or { panic(err) }
|
||||||
|
@ -274,12 +274,12 @@ fn test_tmpdir() {
|
||||||
assert t.len > 0
|
assert t.len > 0
|
||||||
assert os.is_dir(t)
|
assert os.is_dir(t)
|
||||||
tfile := t + os.path_separator + 'tmpfile.txt'
|
tfile := t + os.path_separator + 'tmpfile.txt'
|
||||||
os.rm(tfile) // just in case
|
os.rm(tfile) or { } // just in case
|
||||||
tfile_content := 'this is a temporary file'
|
tfile_content := 'this is a temporary file'
|
||||||
os.write_file(tfile, tfile_content)
|
os.write_file(tfile, tfile_content) or { panic(err) }
|
||||||
tfile_content_read := os.read_file(tfile) or { panic(err) }
|
tfile_content_read := os.read_file(tfile) or { panic(err) }
|
||||||
assert tfile_content_read == tfile_content
|
assert tfile_content_read == tfile_content
|
||||||
os.rm(tfile)
|
os.rm(tfile) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_is_writable_folder() {
|
fn test_is_writable_folder() {
|
||||||
|
@ -299,15 +299,15 @@ fn test_make_symlink_check_is_link_and_remove_symlink() {
|
||||||
}
|
}
|
||||||
folder := 'tfolder'
|
folder := 'tfolder'
|
||||||
symlink := 'tsymlink'
|
symlink := 'tsymlink'
|
||||||
os.rm(symlink)
|
os.rm(symlink) or { }
|
||||||
os.rm(folder)
|
os.rm(folder) or { }
|
||||||
os.mkdir(folder) or { panic(err) }
|
os.mkdir(folder) or { panic(err) }
|
||||||
folder_contents := os.ls(folder) or { panic(err) }
|
folder_contents := os.ls(folder) or { panic(err) }
|
||||||
assert folder_contents.len == 0
|
assert folder_contents.len == 0
|
||||||
os.system('ln -s $folder $symlink')
|
os.system('ln -s $folder $symlink')
|
||||||
assert os.is_link(symlink) == true
|
assert os.is_link(symlink) == true
|
||||||
os.rm(symlink)
|
os.rm(symlink) or { panic(err) }
|
||||||
os.rm(folder)
|
os.rm(folder) or { panic(err) }
|
||||||
folder_exists := os.is_dir(folder)
|
folder_exists := os.is_dir(folder)
|
||||||
assert folder_exists == false
|
assert folder_exists == false
|
||||||
symlink_exists := os.is_link(symlink)
|
symlink_exists := os.is_link(symlink)
|
||||||
|
@ -343,8 +343,8 @@ fn test_symlink() {
|
||||||
os.symlink('symlink', 'symlink2') or { panic(err) }
|
os.symlink('symlink', 'symlink2') or { panic(err) }
|
||||||
assert os.exists('symlink2')
|
assert os.exists('symlink2')
|
||||||
// cleanup
|
// cleanup
|
||||||
os.rm('symlink')
|
os.rm('symlink') or { panic(err) }
|
||||||
os.rm('symlink2')
|
os.rm('symlink2') or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_is_executable_writable_readable() {
|
fn test_is_executable_writable_readable() {
|
||||||
|
@ -367,7 +367,7 @@ fn test_is_executable_writable_readable() {
|
||||||
assert os.is_executable(file_name)
|
assert os.is_executable(file_name)
|
||||||
}
|
}
|
||||||
// We finally delete the test file.
|
// We finally delete the test file.
|
||||||
os.rm(file_name)
|
os.rm(file_name) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_ext() {
|
fn test_ext() {
|
||||||
|
@ -438,7 +438,7 @@ fn test_write_file_array_bytes() {
|
||||||
for i in 0 .. maxn {
|
for i in 0 .. maxn {
|
||||||
arr[i] = 65 + byte(i)
|
arr[i] = 65 + byte(i)
|
||||||
}
|
}
|
||||||
os.write_file_array(fpath, arr)
|
os.write_file_array(fpath, arr) or { panic(err) }
|
||||||
rarr := os.read_bytes(fpath) or { panic(err) }
|
rarr := os.read_bytes(fpath) or { panic(err) }
|
||||||
assert arr == rarr
|
assert arr == rarr
|
||||||
// eprintln(arr.str())
|
// eprintln(arr.str())
|
||||||
|
@ -451,7 +451,7 @@ fn test_write_file_array_structs() {
|
||||||
for i in 0 .. maxn {
|
for i in 0 .. maxn {
|
||||||
arr[i] = IntPoint{65 + i, 65 + i + 10}
|
arr[i] = IntPoint{65 + i, 65 + i + 10}
|
||||||
}
|
}
|
||||||
os.write_file_array(fpath, arr)
|
os.write_file_array(fpath, arr) or { panic(err) }
|
||||||
rarr := os.read_file_array<IntPoint>(fpath)
|
rarr := os.read_file_array<IntPoint>(fpath)
|
||||||
assert rarr == arr
|
assert rarr == arr
|
||||||
assert rarr.len == maxn
|
assert rarr.len == maxn
|
||||||
|
@ -519,6 +519,6 @@ fn test_posix_set_bit() {
|
||||||
}
|
}
|
||||||
mode = u32(s.st_mode) & 0o7777
|
mode = u32(s.st_mode) & 0o7777
|
||||||
assert mode == 0o0755
|
assert mode == 0o0755
|
||||||
rm(fpath)
|
rm(fpath) or { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,10 @@ import time
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
fn C.tcgetattr()
|
fn C.tcgetattr()
|
||||||
|
|
||||||
fn C.tcsetattr()
|
fn C.tcsetattr()
|
||||||
|
|
||||||
fn C.ioctl(fd int, request u64, arg voidptr) int
|
fn C.ioctl(fd int, request u64, arg voidptr) int
|
||||||
|
|
||||||
struct C.termios {
|
struct C.termios {
|
||||||
|
@ -103,7 +104,6 @@ fn (mut ctx Context) termios_setup() ? {
|
||||||
// feature-test rgb (truecolor) support
|
// feature-test rgb (truecolor) support
|
||||||
ctx.enable_rgb = supports_truecolor()
|
ctx.enable_rgb = supports_truecolor()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent stdin from blocking by making its read time 0
|
// Prevent stdin from blocking by making its read time 0
|
||||||
termios.c_cc[C.VTIME] = 0
|
termios.c_cc[C.VTIME] = 0
|
||||||
termios.c_cc[C.VMIN] = 0
|
termios.c_cc[C.VMIN] = 0
|
||||||
|
@ -124,7 +124,7 @@ fn (mut ctx Context) termios_setup() ? {
|
||||||
os.signal(C.SIGCONT, fn () {
|
os.signal(C.SIGCONT, fn () {
|
||||||
mut c := ctx_ptr
|
mut c := ctx_ptr
|
||||||
if c != 0 {
|
if c != 0 {
|
||||||
c.termios_setup()
|
c.termios_setup() or { panic(err) }
|
||||||
c.window_height, c.window_width = get_terminal_size()
|
c.window_height, c.window_width = get_terminal_size()
|
||||||
mut event := &Event{
|
mut event := &Event{
|
||||||
typ: .resized
|
typ: .resized
|
||||||
|
@ -166,10 +166,14 @@ fn get_cursor_position() (int, int) {
|
||||||
print('\033[6n')
|
print('\033[6n')
|
||||||
buf := malloc(25)
|
buf := malloc(25)
|
||||||
len := C.read(C.STDIN_FILENO, buf, 24)
|
len := C.read(C.STDIN_FILENO, buf, 24)
|
||||||
unsafe { buf[len] = 0 }
|
unsafe {
|
||||||
|
buf[len] = 0
|
||||||
|
}
|
||||||
s := tos(buf, len)
|
s := tos(buf, len)
|
||||||
a := s[2..].split(';')
|
a := s[2..].split(';')
|
||||||
if a.len != 2 { return -1, -1 }
|
if a.len != 2 {
|
||||||
|
return -1, -1
|
||||||
|
}
|
||||||
return a[0].int(), a[1].int()
|
return a[0].int(), a[1].int()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,14 +188,16 @@ fn supports_truecolor() bool {
|
||||||
print('\x1bP\$qm\x1b\\')
|
print('\x1bP\$qm\x1b\\')
|
||||||
buf := malloc(25)
|
buf := malloc(25)
|
||||||
len := C.read(C.STDIN_FILENO, buf, 24)
|
len := C.read(C.STDIN_FILENO, buf, 24)
|
||||||
unsafe { buf[len] = 0 }
|
unsafe {
|
||||||
|
buf[len] = 0
|
||||||
|
}
|
||||||
s := tos(buf, len)
|
s := tos(buf, len)
|
||||||
return '1:2:3' in s
|
return '1:2:3' in s
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn termios_reset() {
|
fn termios_reset() {
|
||||||
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH /* C.TCSANOW ?? */, &termios_at_startup)
|
// C.TCSANOW ??
|
||||||
|
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &ui.termios_at_startup)
|
||||||
print('\x1b[?1003l\x1b[?1006l\x1b[?25h')
|
print('\x1b[?1003l\x1b[?1006l\x1b[?25h')
|
||||||
c := ctx_ptr
|
c := ctx_ptr
|
||||||
if c != 0 && c.cfg.use_alternate_buffer {
|
if c != 0 && c.cfg.use_alternate_buffer {
|
||||||
|
@ -201,7 +207,6 @@ fn termios_reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
// TODO: do multiple sleep/read cycles, rather than one big one
|
// TODO: do multiple sleep/read cycles, rather than one big one
|
||||||
fn (mut ctx Context) termios_loop() {
|
fn (mut ctx Context) termios_loop() {
|
||||||
frame_time := 1_000_000 / ctx.cfg.frame_rate
|
frame_time := 1_000_000 / ctx.cfg.frame_rate
|
||||||
|
@ -221,7 +226,8 @@ fn (mut ctx Context) termios_loop() {
|
||||||
sw.restart()
|
sw.restart()
|
||||||
if ctx.cfg.event_fn != voidptr(0) {
|
if ctx.cfg.event_fn != voidptr(0) {
|
||||||
unsafe {
|
unsafe {
|
||||||
len := C.read(C.STDIN_FILENO, byteptr(ctx.read_buf.data) + ctx.read_buf.len, ctx.read_buf.cap - ctx.read_buf.len)
|
len := C.read(C.STDIN_FILENO, byteptr(ctx.read_buf.data) + ctx.read_buf.len,
|
||||||
|
ctx.read_buf.cap - ctx.read_buf.len)
|
||||||
ctx.resize_arr(ctx.read_buf.len + len)
|
ctx.resize_arr(ctx.read_buf.len + len)
|
||||||
}
|
}
|
||||||
if ctx.read_buf.len > 0 {
|
if ctx.read_buf.len > 0 {
|
||||||
|
@ -243,7 +249,9 @@ fn (mut ctx Context) parse_events() {
|
||||||
mut nr_iters := 0
|
mut nr_iters := 0
|
||||||
for ctx.read_buf.len > 0 {
|
for ctx.read_buf.len > 0 {
|
||||||
nr_iters++
|
nr_iters++
|
||||||
if nr_iters > 100 { ctx.shift(1) }
|
if nr_iters > 100 {
|
||||||
|
ctx.shift(1)
|
||||||
|
}
|
||||||
mut event := &Event(0)
|
mut event := &Event(0)
|
||||||
if ctx.read_buf[0] == 0x1b {
|
if ctx.read_buf[0] == 0x1b {
|
||||||
e, len := escape_sequence(ctx.read_buf.bytestr())
|
e, len := escape_sequence(ctx.read_buf.bytestr())
|
||||||
|
@ -272,30 +280,39 @@ fn single_char(buf string) &Event {
|
||||||
|
|
||||||
match ch {
|
match ch {
|
||||||
// special handling for `ctrl + letter`
|
// special handling for `ctrl + letter`
|
||||||
|
|
||||||
// TODO: Fix assoc in V and remove this workaround :/
|
// TODO: Fix assoc in V and remove this workaround :/
|
||||||
// 1 ... 26 { event = Event{ ...event, code: KeyCode(96 | ch), modifiers: ctrl } }
|
// 1 ... 26 { event = Event{ ...event, code: KeyCode(96 | ch), modifiers: ctrl } }
|
||||||
// 65 ... 90 { event = Event{ ...event, code: KeyCode(32 | ch), modifiers: shift } }
|
// 65 ... 90 { event = Event{ ...event, code: KeyCode(32 | ch), modifiers: shift } }
|
||||||
|
|
||||||
|
|
||||||
// The bit `or`s here are really just `+`'s, just written in this way for a tiny performance improvement
|
// The bit `or`s here are really just `+`'s, just written in this way for a tiny performance improvement
|
||||||
// don't treat tab, enter as ctrl+i, ctrl+j
|
// don't treat tab, enter as ctrl+i, ctrl+j
|
||||||
1 ... 8, 11 ... 26 { event = &Event{ typ: event.typ, ascii: event.ascii, utf8: event.utf8, code: KeyCode(96 | ch), modifiers: ctrl } }
|
1...8, 11...26 { event = &Event{
|
||||||
65 ... 90 { event = &Event{ typ: event.typ, ascii: event.ascii, utf8: event.utf8, code: KeyCode(32 | ch), modifiers: shift } }
|
typ: event.typ
|
||||||
|
ascii: event.ascii
|
||||||
|
utf8: event.utf8
|
||||||
|
code: KeyCode(96 | ch)
|
||||||
|
modifiers: ctrl
|
||||||
|
} }
|
||||||
|
65...90 { event = &Event{
|
||||||
|
typ: event.typ
|
||||||
|
ascii: event.ascii
|
||||||
|
utf8: event.utf8
|
||||||
|
code: KeyCode(32 | ch)
|
||||||
|
modifiers: shift
|
||||||
|
} }
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
|
||||||
// Gets an entire, independent escape sequence from the buffer
|
// Gets an entire, independent escape sequence from the buffer
|
||||||
// Normally, this just means reading until the first letter, but there are some exceptions...
|
// Normally, this just means reading until the first letter, but there are some exceptions...
|
||||||
fn escape_end(buf string) int {
|
fn escape_end(buf string) int {
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for {
|
for {
|
||||||
if i + 1 == buf.len { return buf.len }
|
if i + 1 == buf.len {
|
||||||
|
return buf.len
|
||||||
|
}
|
||||||
|
|
||||||
if buf[i].is_letter() || buf[i] == `~` {
|
if buf[i].is_letter() || buf[i] == `~` {
|
||||||
if buf[i] == `O` && i + 2 <= buf.len {
|
if buf[i] == `O` && i + 2 <= buf.len {
|
||||||
|
@ -306,7 +323,9 @@ fn escape_end(buf string) int {
|
||||||
}
|
}
|
||||||
return i + 1
|
return i + 1
|
||||||
// escape hatch to avoid potential issues/crashes, although ideally this should never eval to true
|
// escape hatch to avoid potential issues/crashes, although ideally this should never eval to true
|
||||||
} else if buf[i + 1] == 0x1b { return i + 1 }
|
} else if buf[i + 1] == 0x1b {
|
||||||
|
return i + 1
|
||||||
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
// this point should be unreachable
|
// this point should be unreachable
|
||||||
|
@ -339,32 +358,49 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
||||||
modifiers: c.modifiers | alt
|
modifiers: c.modifiers | alt
|
||||||
}, 2
|
}, 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------
|
// ----------------
|
||||||
// Mouse events
|
// Mouse events
|
||||||
// ----------------
|
// ----------------
|
||||||
|
|
||||||
// Documentation: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
// Documentation: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||||
if buf.len > 2 && buf[1] == `<` {
|
if buf.len > 2 && buf[1] == `<` {
|
||||||
split := buf[2..].split(';')
|
split := buf[2..].split(';')
|
||||||
if split.len < 3 { return &Event(0), 0 }
|
if split.len < 3 {
|
||||||
|
return &Event(0), 0
|
||||||
|
}
|
||||||
|
|
||||||
typ, x, y := split[0].int(), split[1].int(), split[2].int()
|
typ, x, y := split[0].int(), split[1].int(), split[2].int()
|
||||||
lo := typ & 0b00011
|
lo := typ & 0b00011
|
||||||
hi := typ & 0b11100
|
hi := typ & 0b11100
|
||||||
|
|
||||||
mut modifiers := u32(0)
|
mut modifiers := u32(0)
|
||||||
if hi & 4 != 0 { modifiers |= shift }
|
if hi & 4 != 0 {
|
||||||
if hi & 8 != 0 { modifiers |= alt }
|
modifiers |= shift
|
||||||
if hi & 16 != 0 { modifiers |= ctrl }
|
}
|
||||||
|
if hi & 8 != 0 {
|
||||||
|
modifiers |= alt
|
||||||
|
}
|
||||||
|
if hi & 16 != 0 {
|
||||||
|
modifiers |= ctrl
|
||||||
|
}
|
||||||
|
|
||||||
match typ {
|
match typ {
|
||||||
0...31 {
|
0...31 {
|
||||||
last := buf[buf.len - 1]
|
last := buf[buf.len - 1]
|
||||||
button := if lo < 3 { MouseButton(lo + 1) } else { MouseButton.unknown }
|
button := if lo < 3 { MouseButton(lo + 1) } else { MouseButton.unknown }
|
||||||
event := if last == `m` || lo == 3 { EventType.mouse_up } else { EventType.mouse_down }
|
event := if last == `m` || lo == 3 {
|
||||||
|
EventType.mouse_up
|
||||||
|
} else {
|
||||||
|
EventType.mouse_down
|
||||||
|
}
|
||||||
|
|
||||||
return &Event{ typ: event, x: x, y: y, button: button, modifiers: modifiers utf8: single }, end
|
return &Event{
|
||||||
|
typ: event
|
||||||
|
x: x
|
||||||
|
y: y
|
||||||
|
button: button
|
||||||
|
modifiers: modifiers
|
||||||
|
utf8: single
|
||||||
|
}, end
|
||||||
}
|
}
|
||||||
32...63 {
|
32...63 {
|
||||||
button, event := if lo < 3 {
|
button, event := if lo < 3 {
|
||||||
|
@ -373,17 +409,34 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
||||||
MouseButton.unknown, EventType.mouse_move
|
MouseButton.unknown, EventType.mouse_move
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Event{ typ: event, x: x, y: y, button: button, modifiers: modifiers, utf8: single }, end
|
return &Event{
|
||||||
|
typ: event
|
||||||
|
x: x
|
||||||
|
y: y
|
||||||
|
button: button
|
||||||
|
modifiers: modifiers
|
||||||
|
utf8: single
|
||||||
|
}, end
|
||||||
}
|
}
|
||||||
64...95 {
|
64...95 {
|
||||||
direction := if typ & 1 == 0 { Direction.down } else { Direction.up }
|
direction := if typ & 1 == 0 { Direction.down } else { Direction.up }
|
||||||
return &Event{ typ: .mouse_scroll, x: x, y: y, direction: direction, modifiers: modifiers, utf8: single }, end
|
return &Event{
|
||||||
} else {
|
typ: .mouse_scroll
|
||||||
return &Event{ typ: .unknown, utf8: single }, end
|
x: x
|
||||||
|
y: y
|
||||||
|
direction: direction
|
||||||
|
modifiers: modifiers
|
||||||
|
utf8: single
|
||||||
|
}, end
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return &Event{
|
||||||
|
typ: .unknown
|
||||||
|
utf8: single
|
||||||
|
}, end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
// Special key combinations
|
// Special key combinations
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
|
@ -455,5 +508,10 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Event{ typ: .key_down, code: code, utf8: single, modifiers: modifiers }, end
|
return &Event{
|
||||||
|
typ: .key_down
|
||||||
|
code: code
|
||||||
|
utf8: single
|
||||||
|
modifiers: modifiers
|
||||||
|
}, end
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub fn (mut b Builder) build_c(v_files []string, out_file string) {
|
||||||
b.info('build_c($out_file)')
|
b.info('build_c($out_file)')
|
||||||
output2 := b.gen_c(v_files)
|
output2 := b.gen_c(v_files)
|
||||||
mut f := os.create(out_file) or { panic(err) }
|
mut f := os.create(out_file) or { panic(err) }
|
||||||
f.writeln(output2)
|
f.writeln(output2) or { panic(err) }
|
||||||
f.close()
|
f.close()
|
||||||
// os.write_file(out_file, b.gen_c(v_files))
|
// os.write_file(out_file, b.gen_c(v_files))
|
||||||
}
|
}
|
||||||
|
@ -75,9 +75,9 @@ pub fn (mut b Builder) compile_c() {
|
||||||
bundle_name := b.pref.out_name.split('/').last()
|
bundle_name := b.pref.out_name.split('/').last()
|
||||||
bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' }
|
bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' }
|
||||||
display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name }
|
display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name }
|
||||||
os.mkdir('${display_name}.app')
|
os.mkdir('${display_name}.app') or { panic(err) }
|
||||||
os.write_file('${display_name}.app/Info.plist', make_ios_plist(display_name, bundle_id,
|
os.write_file('${display_name}.app/Info.plist', make_ios_plist(display_name, bundle_id,
|
||||||
bundle_name, 1))
|
bundle_name, 1)) or { panic(err) }
|
||||||
}
|
}
|
||||||
b.cc()
|
b.cc()
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ fn (mut v Builder) post_process_c_compiler_output(res os.Result) {
|
||||||
if v.pref.is_verbose {
|
if v.pref.is_verbose {
|
||||||
eprintln('>> remove tmp file: $tmpfile')
|
eprintln('>> remove tmp file: $tmpfile')
|
||||||
}
|
}
|
||||||
os.rm(tmpfile)
|
os.rm(tmpfile) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -414,7 +414,9 @@ fn (mut v Builder) setup_output_name() {
|
||||||
if v.pref.is_verbose {
|
if v.pref.is_verbose {
|
||||||
println('Building $v.pref.path to $v.pref.out_name ...')
|
println('Building $v.pref.path to $v.pref.out_name ...')
|
||||||
}
|
}
|
||||||
v.pref.cache_manager.save('.description.txt', v.pref.path, '${v.pref.path:-30} @ $v.pref.cache_manager.vopts\n')
|
v.pref.cache_manager.save('.description.txt', v.pref.path, '${v.pref.path:-30} @ $v.pref.cache_manager.vopts\n') or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
// println('v.table.imports:')
|
// println('v.table.imports:')
|
||||||
// println(v.table.imports)
|
// println(v.table.imports)
|
||||||
}
|
}
|
||||||
|
@ -734,7 +736,7 @@ fn (mut b Builder) cc_linux_cross() {
|
||||||
b.setup_output_name()
|
b.setup_output_name()
|
||||||
parent_dir := os.vmodules_dir()
|
parent_dir := os.vmodules_dir()
|
||||||
if !os.exists(parent_dir) {
|
if !os.exists(parent_dir) {
|
||||||
os.mkdir(parent_dir)
|
os.mkdir(parent_dir) or { panic(err) }
|
||||||
}
|
}
|
||||||
sysroot := os.join_path(os.vmodules_dir(), 'linuxroot')
|
sysroot := os.join_path(os.vmodules_dir(), 'linuxroot')
|
||||||
if !os.is_dir(sysroot) {
|
if !os.is_dir(sysroot) {
|
||||||
|
@ -917,7 +919,7 @@ fn (mut v Builder) build_thirdparty_obj_file(path string, moduleflags []cflag.CF
|
||||||
// for example thirdparty\tcc\lib\openlibm.o
|
// for example thirdparty\tcc\lib\openlibm.o
|
||||||
// the best we can do for them is just copy them,
|
// the best we can do for them is just copy them,
|
||||||
// and hope that they work with any compiler...
|
// and hope that they work with any compiler...
|
||||||
os.cp(obj_path, opath)
|
os.cp(obj_path, opath) or { panic(err) }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println('$obj_path not found, building it in $opath ...')
|
println('$obj_path not found, building it in $opath ...')
|
||||||
|
@ -943,7 +945,9 @@ fn (mut v Builder) build_thirdparty_obj_file(path string, moduleflags []cflag.CF
|
||||||
verror(res.output)
|
verror(res.output)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v.pref.cache_manager.save('.description.txt', obj_path, '${obj_path:-30} @ $cmd\n')
|
v.pref.cache_manager.save('.description.txt', obj_path, '${obj_path:-30} @ $cmd\n') or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
println(res.output)
|
println(res.output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,12 +93,12 @@ fn (mut b Builder) run_compiled_executable_and_exit() {
|
||||||
}
|
}
|
||||||
if b.pref.os == .ios {
|
if b.pref.os == .ios {
|
||||||
device := '"iPhone SE (2nd generation)"'
|
device := '"iPhone SE (2nd generation)"'
|
||||||
os.exec('xcrun simctl boot $device')
|
os.exec('xcrun simctl boot $device') or { panic(err) }
|
||||||
bundle_name := b.pref.out_name.split('/').last()
|
bundle_name := b.pref.out_name.split('/').last()
|
||||||
display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name }
|
display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name }
|
||||||
os.exec('xcrun simctl install $device ${display_name}.app')
|
os.exec('xcrun simctl install $device ${display_name}.app') or { panic(err) }
|
||||||
bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' }
|
bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' }
|
||||||
os.exec('xcrun simctl launch $device $bundle_id')
|
os.exec('xcrun simctl launch $device $bundle_id') or { panic(err) }
|
||||||
} else {
|
} else {
|
||||||
exefile := os.real_path(b.pref.out_name)
|
exefile := os.real_path(b.pref.out_name)
|
||||||
mut cmd := '"$exefile"'
|
mut cmd := '"$exefile"'
|
||||||
|
@ -133,7 +133,7 @@ fn (mut v Builder) cleanup_run_executable_after_exit(exefile string) {
|
||||||
}
|
}
|
||||||
if os.is_file(exefile) {
|
if os.is_file(exefile) {
|
||||||
v.pref.vrun_elog('remove run executable: $exefile')
|
v.pref.vrun_elog('remove run executable: $exefile')
|
||||||
os.rm(exefile)
|
os.rm(exefile) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub fn (mut b Builder) build_js(v_files []string, out_file string) {
|
||||||
b.info('build_js($out_file)')
|
b.info('build_js($out_file)')
|
||||||
output := b.gen_js(v_files)
|
output := b.gen_js(v_files)
|
||||||
mut f := os.create(out_file) or { panic(err) }
|
mut f := os.create(out_file) or { panic(err) }
|
||||||
f.writeln(output)
|
f.writeln(output) or { panic(err) }
|
||||||
f.close()
|
f.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ pub fn (mut v Builder) cc_msvc() {
|
||||||
// println(res)
|
// println(res)
|
||||||
// println('C OUTPUT:')
|
// println('C OUTPUT:')
|
||||||
// Always remove the object file - it is completely unnecessary
|
// Always remove the object file - it is completely unnecessary
|
||||||
os.rm(out_name_obj)
|
os.rm(out_name_obj) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut v Builder) build_thirdparty_obj_file_with_msvc(path string, moduleflags []cflag.CFlag) {
|
fn (mut v Builder) build_thirdparty_obj_file_with_msvc(path string, moduleflags []cflag.CFlag) {
|
||||||
|
|
|
@ -1930,10 +1930,8 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) t
|
||||||
if expr is ast.CallExpr {
|
if expr is ast.CallExpr {
|
||||||
if expr.return_type.has_flag(.optional) {
|
if expr.return_type.has_flag(.optional) {
|
||||||
if expr.or_block.kind == .absent {
|
if expr.or_block.kind == .absent {
|
||||||
if ret_type != table.void_type {
|
c.error('${expr.name}() returns an option, so it should have either an `or {}` block, or `?` at the end',
|
||||||
c.error('${expr.name}() returns an option but is missing an `or {}` block',
|
|
||||||
expr.pos)
|
expr.pos)
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
c.check_or_expr(expr.or_block, ret_type, expr.return_type.clear_flag(.optional))
|
c.check_or_expr(expr.or_block, ret_type, expr.return_type.clear_flag(.optional))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/optional_method_err.vv:17:10: error: inc_to_limit() returns an option but is missing an `or {}` block
|
vlib/v/checker/tests/optional_method_err.vv:17:10: error: inc_to_limit() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
15 | mut a := Abc{}
|
15 | mut a := Abc{}
|
||||||
16 | for _ in 0 .. 4 {
|
16 | for _ in 0 .. 4 {
|
||||||
17 | _ := a.inc_to_limit(2)
|
17 | _ := a.inc_to_limit(2)
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
vlib/v/checker/tests/optional_void_called_as_normal.vv:7:2: error: foo() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||||
|
5 | fn main() {
|
||||||
|
6 | // Calling foo() without ? or an or block, should be an error.
|
||||||
|
7 | foo()
|
||||||
|
| ~~~~~
|
||||||
|
8 | }
|
|
@ -0,0 +1,8 @@
|
||||||
|
fn foo() ? {
|
||||||
|
println('foo is called')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Calling foo() without ? or an or block, should be an error.
|
||||||
|
foo()
|
||||||
|
}
|
|
@ -179,7 +179,7 @@ fn (mut task TaskDescription) execute() {
|
||||||
res := os.exec(cli_cmd) or { panic(err) }
|
res := os.exec(cli_cmd) or { panic(err) }
|
||||||
expected_out_path := program.replace('.vv', '') + task.result_extension
|
expected_out_path := program.replace('.vv', '') + task.result_extension
|
||||||
if should_autofix && !os.exists(expected_out_path) {
|
if should_autofix && !os.exists(expected_out_path) {
|
||||||
os.write_file(expected_out_path, '')
|
os.write_file(expected_out_path, '') or { panic(err) }
|
||||||
}
|
}
|
||||||
mut expected := os.read_file(expected_out_path) or { panic(err) }
|
mut expected := os.read_file(expected_out_path) or { panic(err) }
|
||||||
task.expected = clean_line_endings(expected)
|
task.expected = clean_line_endings(expected)
|
||||||
|
@ -192,7 +192,7 @@ fn (mut task TaskDescription) execute() {
|
||||||
if task.expected != task.found___ {
|
if task.expected != task.found___ {
|
||||||
task.is_error = true
|
task.is_error = true
|
||||||
if should_autofix {
|
if should_autofix {
|
||||||
os.write_file(expected_out_path, res.output)
|
os.write_file(expected_out_path, res.output) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ fn test_fmt() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename')
|
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename')
|
||||||
os.write_file(vfmt_result_file, result_ocontent)
|
os.write_file(vfmt_result_file, result_ocontent) or { panic(err) }
|
||||||
eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file))
|
eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ fn test_fmt() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename')
|
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename')
|
||||||
os.write_file(vfmt_result_file, result_ocontent)
|
os.write_file(vfmt_result_file, result_ocontent) or { panic(err) }
|
||||||
eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file))
|
eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ fn test_vlib_fmt() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename')
|
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename')
|
||||||
os.write_file(vfmt_result_file, result_ocontent)
|
os.write_file(vfmt_result_file, result_ocontent) or { panic(err) }
|
||||||
eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file))
|
eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
fn testsuite_end() {
|
fn testsuite_end() {
|
||||||
os.rmdir_all(main.output_dir)
|
os.rmdir_all(output_dir) or { }
|
||||||
}
|
}
|
||||||
|
|
||||||
const there_is_node_available = is_nodejs_working()
|
const there_is_node_available = is_nodejs_working()
|
||||||
|
@ -15,22 +15,22 @@ const there_is_node_available = is_nodejs_working()
|
||||||
fn test_example_compilation() {
|
fn test_example_compilation() {
|
||||||
vexe := os.getenv('VEXE')
|
vexe := os.getenv('VEXE')
|
||||||
os.chdir(os.dir(vexe))
|
os.chdir(os.dir(vexe))
|
||||||
os.mkdir_all(main.output_dir)
|
os.mkdir_all(output_dir) or { panic(err) }
|
||||||
files := find_test_files()
|
files := find_test_files()
|
||||||
for file in files {
|
for file in files {
|
||||||
path := os.join_path(main.test_dir, file)
|
path := os.join_path(test_dir, file)
|
||||||
println('Testing $file')
|
println('Testing $file')
|
||||||
v_code := os.system('$vexe $main.v_options -o $main.output_dir${file}.js $path')
|
v_code := os.system('$vexe $v_options -o $output_dir${file}.js $path')
|
||||||
if v_code != 0 {
|
if v_code != 0 {
|
||||||
assert false
|
assert false
|
||||||
}
|
}
|
||||||
// Compilation failed
|
// Compilation failed
|
||||||
assert v_code == 0
|
assert v_code == 0
|
||||||
if !main.there_is_node_available {
|
if !there_is_node_available {
|
||||||
println(' ... skipping running $file, there is no NodeJS present')
|
println(' ... skipping running $file, there is no NodeJS present')
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
js_code := os.system('node $main.output_dir${file}.js')
|
js_code := os.system('node $output_dir${file}.js')
|
||||||
if js_code != 0 {
|
if js_code != 0 {
|
||||||
assert false
|
assert false
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ fn test_example_compilation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_test_files() []string {
|
fn find_test_files() []string {
|
||||||
files := os.ls(main.test_dir) or { panic(err) }
|
files := os.ls(test_dir) or { panic(err) }
|
||||||
// The life example never exits, so tests would hang with it, skip
|
// The life example never exits, so tests would hang with it, skip
|
||||||
mut tests := files.filter(it.ends_with('.v')).filter(it != 'life.v')
|
mut tests := files.filter(it.ends_with('.v')).filter(it != 'life.v')
|
||||||
tests.sort()
|
tests.sort()
|
||||||
|
|
|
@ -15,12 +15,10 @@ fn test_x64() {
|
||||||
vexe := os.getenv('VEXE')
|
vexe := os.getenv('VEXE')
|
||||||
vroot := os.dir(vexe)
|
vroot := os.dir(vexe)
|
||||||
dir := os.join_path(vroot, 'vlib/v/gen/x64/tests')
|
dir := os.join_path(vroot, 'vlib/v/gen/x64/tests')
|
||||||
files := os.ls(dir) or {
|
files := os.ls(dir) or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
wrkdir := os.join_path(os.temp_dir(), 'vtests', 'x64')
|
wrkdir := os.join_path(os.temp_dir(), 'vtests', 'x64')
|
||||||
os.mkdir_all(wrkdir)
|
os.mkdir_all(wrkdir) or { panic(err) }
|
||||||
os.chdir(wrkdir)
|
os.chdir(wrkdir)
|
||||||
tests := files.filter(it.ends_with('.vv'))
|
tests := files.filter(it.ends_with('.vv'))
|
||||||
if tests.len == 0 {
|
if tests.len == 0 {
|
||||||
|
@ -48,9 +46,7 @@ fn test_x64() {
|
||||||
eprintln(res.output)
|
eprintln(res.output)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mut expected := os.read_file('$dir/${test}.out') or {
|
mut expected := os.read_file('$dir/${test}.out') or { panic(err) }
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
expected = expected.trim_right('\r\n').replace('\r\n', '\n')
|
expected = expected.trim_right('\r\n').replace('\r\n', '\n')
|
||||||
mut found := res.output.trim_right('\r\n').replace('\r\n', '\n')
|
mut found := res.output.trim_right('\r\n').replace('\r\n', '\n')
|
||||||
found = found.trim_space()
|
found = found.trim_space()
|
||||||
|
|
|
@ -127,7 +127,7 @@ fn protected_load_lib(mut r live.LiveReloadInfo, new_lib_path string) {
|
||||||
elog(r, '> load_lib OK, new live_lib: $r.live_lib')
|
elog(r, '> load_lib OK, new live_lib: $r.live_lib')
|
||||||
// removing the .so file from the filesystem after dlopen-ing
|
// removing the .so file from the filesystem after dlopen-ing
|
||||||
// it is safe, since it will still be mapped in memory
|
// it is safe, since it will still be mapped in memory
|
||||||
os.rm(new_lib_path)
|
os.rm(new_lib_path) or { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: r.reloader() is executed in a new, independent thread
|
// NB: r.reloader() is executed in a new, independent thread
|
||||||
|
|
|
@ -60,8 +60,8 @@ fn atomic_write_source(source string) {
|
||||||
// NB: here wrtiting is done in 2 steps, since os.write_file can take some time,
|
// NB: here wrtiting is done in 2 steps, since os.write_file can take some time,
|
||||||
// during which the file will be modified, but it will still be not completely written.
|
// during which the file will be modified, but it will still be not completely written.
|
||||||
// The os.mv after that, guarantees that the reloader will see a complete valid V program.
|
// The os.mv after that, guarantees that the reloader will see a complete valid V program.
|
||||||
os.write_file(tmp_file, source)
|
os.write_file(tmp_file, source) or { panic(err) }
|
||||||
os.mv(tmp_file, source_file)
|
os.mv(tmp_file, source_file) or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -75,7 +75,7 @@ fn testsuite_begin() {
|
||||||
for f in [tmp_file, source_file, output_file, res_original_file, res_changed_file, res_another_file,
|
for f in [tmp_file, source_file, output_file, res_original_file, res_changed_file, res_another_file,
|
||||||
res_stop_file,
|
res_stop_file,
|
||||||
] {
|
] {
|
||||||
os.rm(f)
|
os.rm(f) or { }
|
||||||
}
|
}
|
||||||
atomic_write_source(live_program_source)
|
atomic_write_source(live_program_source)
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ fn testsuite_end() {
|
||||||
assert histogram['CHANGED'] + histogram['ANOTHER'] > 0
|
assert histogram['CHANGED'] + histogram['ANOTHER'] > 0
|
||||||
// assert histogram['END'] > 0
|
// assert histogram['END'] > 0
|
||||||
for tfile in cleanup_files {
|
for tfile in cleanup_files {
|
||||||
os.rm(tfile)
|
os.rm(tfile) or { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,10 @@ fn append_to_file(fname string, s string) {
|
||||||
println('>>>> could not open file $fname for appending, err: $err ')
|
println('>>>> could not open file $fname for appending, err: $err ')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f.writeln(s)
|
f.writeln(s) or {
|
||||||
|
println('>>>> could not write to $fname, err: $err ')
|
||||||
|
return
|
||||||
|
}
|
||||||
// info := live.info()
|
// info := live.info()
|
||||||
// f.writeln('>>> reloads: ${info.reloads} | ok reloads: ${info.reloads_ok}')
|
// f.writeln('>>> reloads: ${info.reloads} | ok reloads: ${info.reloads_ok}')
|
||||||
f.close()
|
f.close()
|
||||||
|
@ -29,6 +32,7 @@ fn pmessage() string {
|
||||||
const (
|
const (
|
||||||
delay = 20
|
delay = 20
|
||||||
)
|
)
|
||||||
|
|
||||||
fn edefault(name string, default string) string {
|
fn edefault(name string, default string) string {
|
||||||
res := os.getenv(name)
|
res := os.getenv(name)
|
||||||
if res == '' {
|
if res == '' {
|
||||||
|
@ -36,6 +40,7 @@ fn edefault(name string, default string) string {
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
mut info := live.info()
|
mut info := live.info()
|
||||||
info.recheck_period_ms = 5
|
info.recheck_period_ms = 5
|
||||||
|
|
|
@ -112,7 +112,10 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
||||||
if op == .decl_assign {
|
if op == .decl_assign {
|
||||||
// a, b := a + 1, b
|
// a, b := a + 1, b
|
||||||
for r in right {
|
for r in right {
|
||||||
p.check_undefined_variables(left, r)
|
p.check_undefined_variables(left, r) or {
|
||||||
|
p.error('check_undefined_variables failed')
|
||||||
|
return ast.Stmt{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if left.len > 1 {
|
} else if left.len > 1 {
|
||||||
// a, b = b, a
|
// a, b = b, a
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub fn (mut m Main) run() ?string {
|
||||||
res += pcdep.description
|
res += pcdep.description
|
||||||
}
|
}
|
||||||
if pc != 0 {
|
if pc != 0 {
|
||||||
pc.extend(pcdep)
|
pc.extend(pcdep) ?
|
||||||
} else {
|
} else {
|
||||||
pc = pcdep
|
pc = pcdep
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ fn (mut pc PkgConfig) resolve(pkgname string) ?string {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn atleast(v string) bool {
|
pub fn atleast(v string) bool {
|
||||||
v0 := semver.from(version) or { return false }
|
v0 := semver.from(pkgconfig.version) or { return false }
|
||||||
v1 := semver.from(v) or { return false }
|
v1 := semver.from(v) or { return false }
|
||||||
return v0.gt(v1)
|
return v0.gt(v1)
|
||||||
}
|
}
|
||||||
|
@ -207,8 +207,8 @@ fn (mut pc PkgConfig) load_require(dep string) ? {
|
||||||
if !pcdep.parse(depfile) {
|
if !pcdep.parse(depfile) {
|
||||||
return error('required file "$depfile" could not be parsed')
|
return error('required file "$depfile" could not be parsed')
|
||||||
}
|
}
|
||||||
pcdep.load_requires() or { return error(err) }
|
pcdep.load_requires() ?
|
||||||
pc.extend(pcdep)
|
pc.extend(pcdep) ?
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut pc PkgConfig) add_path(path string) {
|
fn (mut pc PkgConfig) add_path(path string) {
|
||||||
|
@ -223,7 +223,7 @@ fn (mut pc PkgConfig) add_path(path string) {
|
||||||
|
|
||||||
fn (mut pc PkgConfig) load_paths() {
|
fn (mut pc PkgConfig) load_paths() {
|
||||||
if pc.options.use_default_paths {
|
if pc.options.use_default_paths {
|
||||||
for path in default_paths {
|
for path in pkgconfig.default_paths {
|
||||||
pc.add_path(path)
|
pc.add_path(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -474,10 +474,10 @@ pub fn parse_args(args []string) (&Preferences, string) {
|
||||||
//
|
//
|
||||||
if output_option.len != 0 {
|
if output_option.len != 0 {
|
||||||
res.vrun_elog('remove tmp exe file: $tmp_exe_file_path')
|
res.vrun_elog('remove tmp exe file: $tmp_exe_file_path')
|
||||||
os.rm(tmp_exe_file_path)
|
os.rm(tmp_exe_file_path) or { }
|
||||||
}
|
}
|
||||||
res.vrun_elog('remove tmp v file: $tmp_v_file_path')
|
res.vrun_elog('remove tmp v file: $tmp_v_file_path')
|
||||||
os.rm(tmp_v_file_path)
|
os.rm(tmp_v_file_path) or { panic(err) }
|
||||||
exit(tmp_result)
|
exit(tmp_result)
|
||||||
}
|
}
|
||||||
must_exist(res.path)
|
must_exist(res.path)
|
||||||
|
|
|
@ -33,13 +33,13 @@ fn test_all() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
$if windows {
|
$if windows {
|
||||||
os.rm('./test.exe')
|
os.rm('./test.exe') or { }
|
||||||
$if msvc {
|
$if msvc {
|
||||||
os.rm('./test.ilk')
|
os.rm('./test.ilk') or { }
|
||||||
os.rm('./test.pdb')
|
os.rm('./test.pdb') or { }
|
||||||
}
|
}
|
||||||
} $else {
|
} $else {
|
||||||
os.rm('./test')
|
os.rm('./test') or { }
|
||||||
}
|
}
|
||||||
// println('============')
|
// println('============')
|
||||||
// println(res.output)
|
// println(res.output)
|
||||||
|
|
|
@ -64,7 +64,7 @@ fn worker_repl(mut p sync.PoolProcessor, idx int, thread_id int) voidptr {
|
||||||
tls_bench.cstep = idx
|
tls_bench.cstep = idx
|
||||||
tfolder := os.join_path(cdir, 'vrepl_tests_$idx')
|
tfolder := os.join_path(cdir, 'vrepl_tests_$idx')
|
||||||
if os.is_dir(tfolder) {
|
if os.is_dir(tfolder) {
|
||||||
os.rmdir_all(tfolder)
|
os.rmdir_all(tfolder) or { panic(err) }
|
||||||
}
|
}
|
||||||
os.mkdir(tfolder) or { panic(err) }
|
os.mkdir(tfolder) or { panic(err) }
|
||||||
file := p.get_string_item(idx)
|
file := p.get_string_item(idx)
|
||||||
|
@ -73,14 +73,14 @@ fn worker_repl(mut p sync.PoolProcessor, idx int, thread_id int) voidptr {
|
||||||
fres := runner.run_repl_file(tfolder, session.options.vexec, file) or {
|
fres := runner.run_repl_file(tfolder, session.options.vexec, file) or {
|
||||||
session.bmark.fail()
|
session.bmark.fail()
|
||||||
tls_bench.fail()
|
tls_bench.fail()
|
||||||
os.rmdir_all(tfolder)
|
os.rmdir_all(tfolder) or { panic(err) }
|
||||||
eprintln(tls_bench.step_message_fail(err))
|
eprintln(tls_bench.step_message_fail(err))
|
||||||
assert false
|
assert false
|
||||||
return sync.no_result
|
return sync.no_result
|
||||||
}
|
}
|
||||||
session.bmark.ok()
|
session.bmark.ok()
|
||||||
tls_bench.ok()
|
tls_bench.ok()
|
||||||
os.rmdir_all(tfolder)
|
os.rmdir_all(tfolder) or { panic(err) }
|
||||||
println(tls_bench.step_message_ok(fres))
|
println(tls_bench.step_message_ok(fres))
|
||||||
assert true
|
assert true
|
||||||
return sync.no_result
|
return sync.no_result
|
||||||
|
|
|
@ -35,37 +35,34 @@ pub fn full_path_to_v(dirs_in int) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn diff_files(file_result string, file_expected string) string {
|
fn diff_files(file_result string, file_expected string) string {
|
||||||
diffcmd := util.find_working_diff_command() or {
|
diffcmd := util.find_working_diff_command() or { return err }
|
||||||
return err
|
|
||||||
}
|
|
||||||
return util.color_compare_files(diffcmd, file_result, file_expected)
|
return util.color_compare_files(diffcmd, file_result, file_expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_repl_file(wd string, vexec string, file string) ?string {
|
pub fn run_repl_file(wd string, vexec string, file string) ?string {
|
||||||
vexec_folder := os.dir(vexec) + os.path_separator
|
vexec_folder := os.dir(vexec) + os.path_separator
|
||||||
fcontent := os.read_file(file) or {
|
fcontent := os.read_file(file) or { return error('Could not read file $file') }
|
||||||
return error('Could not read file $file')
|
|
||||||
}
|
|
||||||
content := fcontent.replace('\r', '')
|
content := fcontent.replace('\r', '')
|
||||||
input := content.all_before('===output===\n')
|
input := content.all_before('===output===\n')
|
||||||
output := content.all_after('===output===\n').trim_right('\n\r')
|
output := content.all_after('===output===\n').trim_right('\n\r')
|
||||||
fname := os.file_name(file)
|
fname := os.file_name(file)
|
||||||
input_temporary_filename := os.real_path(os.join_path(wd, 'input_temporary_filename.txt'))
|
input_temporary_filename := os.real_path(os.join_path(wd, 'input_temporary_filename.txt'))
|
||||||
os.write_file(input_temporary_filename, input)
|
os.write_file(input_temporary_filename, input) or { panic(err) }
|
||||||
os.write_file(os.real_path(os.join_path(wd, 'original.txt')), fcontent)
|
os.write_file(os.real_path(os.join_path(wd, 'original.txt')), fcontent) or { panic(err) }
|
||||||
rcmd := '"$vexec" repl -replfolder "$wd" -replprefix "${fname}." < $input_temporary_filename'
|
rcmd := '"$vexec" repl -replfolder "$wd" -replprefix "${fname}." < $input_temporary_filename'
|
||||||
r := os.exec(rcmd) or {
|
r := os.exec(rcmd) or {
|
||||||
os.rm(input_temporary_filename)
|
os.rm(input_temporary_filename) or { panic(err) }
|
||||||
return error('Could not execute: $rcmd')
|
return error('Could not execute: $rcmd')
|
||||||
}
|
}
|
||||||
os.rm(input_temporary_filename)
|
os.rm(input_temporary_filename) or { panic(err) }
|
||||||
result := r.output.replace('\r', '').replace('>>> ', '').replace('>>>', '').replace('... ',
|
result := r.output.replace('\r', '').replace('>>> ', '').replace('>>>', '').replace('... ',
|
||||||
'').replace(wd + os.path_separator, '').replace(vexec_folder, '').replace('\\', '/').trim_right('\n\r')
|
'').replace(wd + os.path_separator, '').replace(vexec_folder, '').replace('\\',
|
||||||
|
'/').trim_right('\n\r')
|
||||||
if result != output {
|
if result != output {
|
||||||
file_result := '${file}.result.txt'
|
file_result := '${file}.result.txt'
|
||||||
file_expected := '${file}.expected.txt'
|
file_expected := '${file}.expected.txt'
|
||||||
os.write_file(file_result, result)
|
os.write_file(file_result, result) or { panic(err) }
|
||||||
os.write_file(file_expected, output)
|
os.write_file(file_expected, output) or { panic(err) }
|
||||||
diff := diff_files(file_result, file_expected)
|
diff := diff_files(file_result, file_expected)
|
||||||
return error('Difference found in REPL file: $file
|
return error('Difference found in REPL file: $file
|
||||||
====> Got :
|
====> Got :
|
||||||
|
@ -87,16 +84,14 @@ pub fn run_prod_file(wd string, vexec string, file string) ?string {
|
||||||
}
|
}
|
||||||
expected_content := f_expected_content.replace('\r', '')
|
expected_content := f_expected_content.replace('\r', '')
|
||||||
cmd := '"$vexec" -prod run "$file"'
|
cmd := '"$vexec" -prod run "$file"'
|
||||||
r := os.exec(cmd) or {
|
r := os.exec(cmd) or { return error('Could not execute: $cmd') }
|
||||||
return error('Could not execute: $cmd')
|
|
||||||
}
|
|
||||||
if r.exit_code != 0 {
|
if r.exit_code != 0 {
|
||||||
return error('$cmd return exit code: $r.exit_code')
|
return error('$cmd return exit code: $r.exit_code')
|
||||||
}
|
}
|
||||||
result := r.output.replace('\r', '')
|
result := r.output.replace('\r', '')
|
||||||
if result != expected_content {
|
if result != expected_content {
|
||||||
file_result := '${file}.result.txt'
|
file_result := '${file}.result.txt'
|
||||||
os.write_file(file_result, result)
|
os.write_file(file_result, result) or { panic(err) }
|
||||||
diff := diff_files(file_result, file_expected)
|
diff := diff_files(file_result, file_expected)
|
||||||
return error('Difference found in test: $file
|
return error('Difference found in test: $file
|
||||||
====> Got :
|
====> Got :
|
||||||
|
|
|
@ -19,7 +19,7 @@ fn pipe_to_v_run() ? {
|
||||||
// eprintln('>> cmd: $cmd | res: $res')
|
// eprintln('>> cmd: $cmd | res: $res')
|
||||||
assert res.exit_code == 0
|
assert res.exit_code == 0
|
||||||
assert res.output.replace('\r', '').trim_space().split('\n') == ['4', 'hello']
|
assert res.output.replace('\r', '').trim_space().split('\n') == ['4', 'hello']
|
||||||
os.rm(tmp_v_file)
|
os.rm(tmp_v_file) or { panic(err) }
|
||||||
assert !os.exists(tmp_v_file)
|
assert !os.exists(tmp_v_file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,13 +53,11 @@ fn test_all() {
|
||||||
files := os.ls(dir) or { panic(err) }
|
files := os.ls(dir) or { panic(err) }
|
||||||
//
|
//
|
||||||
wrkdir := os.join_path(os.temp_dir(), 'vtests', 'valgrind')
|
wrkdir := os.join_path(os.temp_dir(), 'vtests', 'valgrind')
|
||||||
os.mkdir_all(wrkdir)
|
os.mkdir_all(wrkdir) or { panic(err) }
|
||||||
os.chdir(wrkdir)
|
os.chdir(wrkdir)
|
||||||
//
|
//
|
||||||
tests := vtest.filter_vtest_only(files.filter(it.ends_with('.v') && !it.ends_with('_test.v')),
|
only_ordinary_v_files := files.filter(it.ends_with('.v') && !it.ends_with('_test.v'))
|
||||||
|
tests := vtest.filter_vtest_only(only_ordinary_v_files, basepath: valgrind_test_path)
|
||||||
basepath: valgrind_test_path
|
|
||||||
)
|
|
||||||
bench.set_total_expected_steps(tests.len)
|
bench.set_total_expected_steps(tests.len)
|
||||||
for test in tests {
|
for test in tests {
|
||||||
bench.step()
|
bench.step()
|
||||||
|
|
|
@ -63,10 +63,10 @@ pub fn color_compare_strings(diff_cmd string, expected string, found string) str
|
||||||
ctime := time.sys_mono_now()
|
ctime := time.sys_mono_now()
|
||||||
e_file := os.join_path(cdir, '${ctime}.expected.txt')
|
e_file := os.join_path(cdir, '${ctime}.expected.txt')
|
||||||
f_file := os.join_path(cdir, '${ctime}.found.txt')
|
f_file := os.join_path(cdir, '${ctime}.found.txt')
|
||||||
os.write_file(e_file, expected)
|
os.write_file(e_file, expected) or { panic(err) }
|
||||||
os.write_file(f_file, found)
|
os.write_file(f_file, found) or { panic(err) }
|
||||||
res := color_compare_files(diff_cmd, e_file, f_file)
|
res := color_compare_files(diff_cmd, e_file, f_file)
|
||||||
os.rm(e_file)
|
os.rm(e_file) or { panic(err) }
|
||||||
os.rm(f_file)
|
os.rm(f_file) or { panic(err) }
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -489,7 +489,7 @@ pub fn get_vtmp_folder() string {
|
||||||
}
|
}
|
||||||
vtmp = os.join_path(os.temp_dir(), 'v')
|
vtmp = os.join_path(os.temp_dir(), 'v')
|
||||||
if !os.exists(vtmp) || !os.is_dir(vtmp) {
|
if !os.exists(vtmp) || !os.is_dir(vtmp) {
|
||||||
os.mkdir_all(vtmp)
|
os.mkdir_all(vtmp) or { panic(err) }
|
||||||
}
|
}
|
||||||
os.setenv('VTMP', vtmp, true)
|
os.setenv('VTMP', vtmp, true)
|
||||||
return vtmp
|
return vtmp
|
||||||
|
|
|
@ -40,13 +40,13 @@ pub fn new_cache_manager(opts []string) CacheManager {
|
||||||
vcache_basepath = os.join_path(os.vmodules_dir(), 'cache')
|
vcache_basepath = os.join_path(os.vmodules_dir(), 'cache')
|
||||||
}
|
}
|
||||||
if !os.is_dir(vcache_basepath) {
|
if !os.is_dir(vcache_basepath) {
|
||||||
os.mkdir_all(vcache_basepath)
|
os.mkdir_all(vcache_basepath) or { panic(err) }
|
||||||
readme_content := 'This folder contains cached build artifacts from the V build system.
|
readme_content := 'This folder contains cached build artifacts from the V build system.
|
||||||
|You can safely delete it, if it is getting too large.
|
|You can safely delete it, if it is getting too large.
|
||||||
|It will be recreated the next time you compile something with V.
|
|It will be recreated the next time you compile something with V.
|
||||||
|You can change its location with the VCACHE environment variable.
|
|You can change its location with the VCACHE environment variable.
|
||||||
'.strip_margin()
|
'.strip_margin()
|
||||||
os.write_file(os.join_path(vcache_basepath, 'README.md'), readme_content)
|
os.write_file(os.join_path(vcache_basepath, 'README.md'), readme_content) or { panic(err) }
|
||||||
}
|
}
|
||||||
original_vopts := opts.join('|')
|
original_vopts := opts.join('|')
|
||||||
return CacheManager{
|
return CacheManager{
|
||||||
|
@ -74,7 +74,7 @@ pub fn (mut cm CacheManager) key2cpath(key string) string {
|
||||||
cprefix_folder := os.join_path(cm.basepath, prefix)
|
cprefix_folder := os.join_path(cm.basepath, prefix)
|
||||||
cpath = os.join_path(cprefix_folder, khash)
|
cpath = os.join_path(cprefix_folder, khash)
|
||||||
if !os.is_dir(cprefix_folder) {
|
if !os.is_dir(cprefix_folder) {
|
||||||
os.mkdir_all(cprefix_folder)
|
os.mkdir_all(cprefix_folder) or { panic(err) }
|
||||||
os.chmod(cprefix_folder, 0o777)
|
os.chmod(cprefix_folder, 0o777)
|
||||||
}
|
}
|
||||||
cm.k2cpath[key] = cpath
|
cm.k2cpath[key] = cpath
|
||||||
|
|
|
@ -17,7 +17,7 @@ fn check_cache_entry_fpath_invariants(x string, extension string) {
|
||||||
fn testsuite_begin() {
|
fn testsuite_begin() {
|
||||||
os.setenv('VCACHE', vcache_folder, true)
|
os.setenv('VCACHE', vcache_folder, true)
|
||||||
// eprintln('testsuite_begin, vcache_folder = $vcache_folder')
|
// eprintln('testsuite_begin, vcache_folder = $vcache_folder')
|
||||||
os.rmdir_all(vcache_folder)
|
os.rmdir_all(vcache_folder) or { }
|
||||||
vcache.new_cache_manager([])
|
vcache.new_cache_manager([])
|
||||||
assert os.is_dir(vcache_folder)
|
assert os.is_dir(vcache_folder)
|
||||||
}
|
}
|
||||||
|
@ -54,33 +54,25 @@ fn test_different_options_should_produce_different_cache_entries_for_same_key_an
|
||||||
|
|
||||||
fn test_exists() {
|
fn test_exists() {
|
||||||
mut cm := vcache.new_cache_manager([])
|
mut cm := vcache.new_cache_manager([])
|
||||||
cm.exists('.o', 'abc') or {
|
cm.exists('.o', 'abc') or { assert true }
|
||||||
assert true
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
x := cm.save('.x', 'abc', '') or {
|
x := cm.save('.x', 'abc', '') or {
|
||||||
assert false
|
assert false
|
||||||
''
|
''
|
||||||
}
|
}
|
||||||
cm.exists('.o', 'abc') or {
|
cm.exists('.o', 'abc') or { assert true }
|
||||||
assert true
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
y := cm.save('.o', 'zbc', '') or {
|
y := cm.save('.o', 'zbc', '') or {
|
||||||
assert false
|
assert false
|
||||||
''
|
''
|
||||||
}
|
}
|
||||||
cm.exists('.o', 'abc') or {
|
cm.exists('.o', 'abc') or { assert true }
|
||||||
assert true
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
z := cm.save('.o', 'abc', '') or {
|
z := cm.save('.o', 'abc', '') or {
|
||||||
assert false
|
assert false
|
||||||
''
|
''
|
||||||
}
|
}
|
||||||
cm.exists('.o', 'abc') or {
|
cm.exists('.o', 'abc') or { assert false }
|
||||||
assert false
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
assert os.is_file(x)
|
assert os.is_file(x)
|
||||||
assert os.is_file(y)
|
assert os.is_file(y)
|
||||||
|
@ -104,6 +96,6 @@ fn test_readme_exists_and_is_readable() {
|
||||||
|
|
||||||
fn testsuite_end() {
|
fn testsuite_end() {
|
||||||
os.chdir(os.wd_at_startup)
|
os.chdir(os.wd_at_startup)
|
||||||
os.rmdir_all(vcache_folder)
|
os.rmdir_all(vcache_folder) or { }
|
||||||
assert !os.is_dir(vcache_folder)
|
assert !os.is_dir(vcache_folder)
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ fn (am AssetManager) combine(asset_type string, to_file bool) string {
|
||||||
os.mkdir(am.cache_dir) or { panic(err) }
|
os.mkdir(am.cache_dir) or { panic(err) }
|
||||||
}
|
}
|
||||||
mut file := os.create(out_file) or { panic(err) }
|
mut file := os.create(out_file) or { panic(err) }
|
||||||
file.write(out.bytes())
|
file.write(out.bytes()) or { panic(err) }
|
||||||
file.close()
|
file.close()
|
||||||
return out_file
|
return out_file
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import os
|
||||||
// unique cache dirs are needed per test function.
|
// unique cache dirs are needed per test function.
|
||||||
fn clean_cache_dir(dir string) {
|
fn clean_cache_dir(dir string) {
|
||||||
if os.is_dir(dir) {
|
if os.is_dir(dir) {
|
||||||
os.rmdir_all(dir)
|
os.rmdir_all(dir) or { panic(err) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,10 +21,10 @@ fn cache_dir(test_name string) string {
|
||||||
fn get_test_file_path(file string) string {
|
fn get_test_file_path(file string) string {
|
||||||
path := os.join_path(base_cache_dir(), file)
|
path := os.join_path(base_cache_dir(), file)
|
||||||
if !os.is_dir(base_cache_dir()) {
|
if !os.is_dir(base_cache_dir()) {
|
||||||
os.mkdir_all(base_cache_dir())
|
os.mkdir_all(base_cache_dir()) or { panic(err) }
|
||||||
}
|
}
|
||||||
if !os.exists(path) {
|
if !os.exists(path) {
|
||||||
os.write_file(path, get_test_file_contents(file))
|
os.write_file(path, get_test_file_contents(file)) or { panic(err) }
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ const (
|
||||||
fn testsuite_begin() {
|
fn testsuite_begin() {
|
||||||
os.chdir(vroot)
|
os.chdir(vroot)
|
||||||
if os.exists(serverexe) {
|
if os.exists(serverexe) {
|
||||||
os.rm(serverexe)
|
os.rm(serverexe) or { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ fn simple_tcp_client(config SimpleTcpClientConfig) ?string {
|
||||||
client.set_read_timeout(tcp_r_timeout)
|
client.set_read_timeout(tcp_r_timeout)
|
||||||
client.set_write_timeout(tcp_w_timeout)
|
client.set_write_timeout(tcp_w_timeout)
|
||||||
defer {
|
defer {
|
||||||
client.close()
|
client.close() or { }
|
||||||
}
|
}
|
||||||
message := 'GET $config.path HTTP/1.1
|
message := 'GET $config.path HTTP/1.1
|
||||||
Host: $config.host
|
Host: $config.host
|
||||||
|
|
|
@ -355,7 +355,8 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
|
||||||
//}
|
//}
|
||||||
// read body
|
// read body
|
||||||
mut read_body := []byte{len: len}
|
mut read_body := []byte{len: len}
|
||||||
reader.read(mut read_body) // read just the amount of content len if there is no content there is nothing more to read here
|
// read just the amount of content len if there is no content there is nothing more to read here
|
||||||
|
reader.read(mut read_body) or { println('reader.read failed with err: $err') }
|
||||||
body += read_body.bytestr()
|
body += read_body.bytestr()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
module ttf
|
module ttf
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
*
|
*
|
||||||
* Common data for the module
|
* Common data for the module
|
||||||
|
@ -15,8 +16,7 @@ import os
|
||||||
import math
|
import math
|
||||||
|
|
||||||
// text align
|
// text align
|
||||||
pub
|
pub enum Text_align {
|
||||||
enum Text_align {
|
|
||||||
left
|
left
|
||||||
center
|
center
|
||||||
right
|
right
|
||||||
|
@ -24,8 +24,7 @@ enum Text_align {
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw style
|
// draw style
|
||||||
pub
|
pub enum Style {
|
||||||
enum Style {
|
|
||||||
outline
|
outline
|
||||||
outline_aliased
|
outline_aliased
|
||||||
filled
|
filled
|
||||||
|
@ -38,8 +37,9 @@ enum Style {
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
const debug_flag = false
|
const debug_flag = false
|
||||||
|
|
||||||
fn dprintln(txt string) {
|
fn dprintln(txt string) {
|
||||||
if debug_flag {
|
if ttf.debug_flag {
|
||||||
println(txt)
|
println(txt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,8 +85,7 @@ fn (mut bmp BitMap) format_texture(){
|
||||||
}
|
}
|
||||||
|
|
||||||
// write out a .ppm file
|
// write out a .ppm file
|
||||||
pub
|
pub fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
||||||
fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
|
||||||
tmp_buf := bmp.buf
|
tmp_buf := bmp.buf
|
||||||
mut buf := malloc(bmp.buf_size)
|
mut buf := malloc(bmp.buf_size)
|
||||||
unsafe { C.memcpy(buf, tmp_buf, bmp.buf_size) }
|
unsafe { C.memcpy(buf, tmp_buf, bmp.buf_size) }
|
||||||
|
@ -95,18 +94,17 @@ fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
||||||
bmp.format_texture()
|
bmp.format_texture()
|
||||||
npixels := bmp.width * bmp.height
|
npixels := bmp.width * bmp.height
|
||||||
mut f_out := os.create(file_name) or { panic(err) }
|
mut f_out := os.create(file_name) or { panic(err) }
|
||||||
f_out.writeln('P3')
|
f_out.writeln('P3') or { panic(err) }
|
||||||
f_out.writeln('${bmp.width} ${bmp.height}')
|
f_out.writeln('$bmp.width $bmp.height') or { panic(err) }
|
||||||
f_out.writeln('255')
|
f_out.writeln('255') or { panic(err) }
|
||||||
for i in 0 .. npixels {
|
for i in 0 .. npixels {
|
||||||
pos := i * bmp.bp
|
pos := i * bmp.bp
|
||||||
unsafe {
|
unsafe {
|
||||||
c_r := bmp.buf[pos]
|
c_r := bmp.buf[pos]
|
||||||
c_g := bmp.buf[pos + 1]
|
c_g := bmp.buf[pos + 1]
|
||||||
c_b := bmp.buf[pos + 2]
|
c_b := bmp.buf[pos + 2]
|
||||||
f_out.write_str('${c_r} ${c_g} ${c_b} ')
|
f_out.write_str('$c_r $c_g $c_b ') or { panic(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
f_out.close()
|
f_out.close()
|
||||||
|
|
||||||
|
@ -114,23 +112,22 @@ fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
||||||
bmp.buf = tmp_buf
|
bmp.buf = tmp_buf
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut bmp BitMap) get_raw_bytes() []byte {
|
||||||
fn (mut bmp BitMap) get_raw_bytes() []byte {
|
|
||||||
mut f_buf := []byte{len: bmp.buf_size / 4}
|
mut f_buf := []byte{len: bmp.buf_size / 4}
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for i < bmp.buf_size {
|
for i < bmp.buf_size {
|
||||||
unsafe { f_buf[i>>2] = *(bmp.buf + i) }
|
unsafe {
|
||||||
|
f_buf[i >> 2] = *(bmp.buf + i)
|
||||||
|
}
|
||||||
i += 4
|
i += 4
|
||||||
}
|
}
|
||||||
return f_buf
|
return f_buf
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut bmp BitMap) save_raw_data(file_name string) {
|
||||||
fn (mut bmp BitMap) save_raw_data(file_name string) {
|
os.write_file_array(file_name, bmp.get_raw_bytes()) or { panic(err) }
|
||||||
os.write_file_array(file_name, bmp.get_raw_bytes())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Math functions
|
// Math functions
|
||||||
//
|
//
|
||||||
|
@ -181,8 +178,7 @@ fn rfpart(x f32) f32 {
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
/*
|
/*
|
||||||
[inline]
|
[inline]
|
||||||
pub
|
pub fn (mut dev BitMap) get_color(x int, y int) (int, int, int, int){
|
||||||
fn (mut dev BitMap) get_color(x int, y int) (int, int, int, int){
|
|
||||||
if x < 0 || x >= dev.width || y < 0 || y >= dev.height {
|
if x < 0 || x >= dev.width || y < 0 || y >= dev.height {
|
||||||
return 0,0,0,0
|
return 0,0,0,0
|
||||||
}
|
}
|
||||||
|
@ -193,8 +189,7 @@ fn (mut dev BitMap) get_color(x int, y int) (int, int, int, int){
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub
|
pub fn (mut dev BitMap) get_color_u32(x int, y int) u32{
|
||||||
fn (mut dev BitMap) get_color_u32(x int, y int) u32{
|
|
||||||
r, g, b, a := dev.get_color(x, y)
|
r, g, b, a := dev.get_color(x, y)
|
||||||
unsafe{
|
unsafe{
|
||||||
return u32(r<<24) | u32(g<<16) | u32(b<<8) | u32(a)
|
return u32(r<<24) | u32(g<<16) | u32(b<<8) | u32(a)
|
||||||
|
@ -207,14 +202,12 @@ fn (mut dev BitMap) get_color_u32(x int, y int) u32{
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
[inline]
|
[inline]
|
||||||
pub
|
pub fn color_multiply_alpha(c u32, level f32) u32 {
|
||||||
fn color_multiply_alpha(c u32, level f32) u32 {
|
|
||||||
return u32(f32(c & 0xFF) * level)
|
return u32(f32(c & 0xFF) * level)
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub
|
pub fn color_multiply(c u32, level f32) u32 {
|
||||||
fn color_multiply(c u32, level f32) u32 {
|
|
||||||
mut r := (f32((c >> 24) & 0xFF) / 255.0) * level
|
mut r := (f32((c >> 24) & 0xFF) / 255.0) * level
|
||||||
mut g := (f32((c >> 16) & 0xFF) / 255.0) * level
|
mut g := (f32((c >> 16) & 0xFF) / 255.0) * level
|
||||||
mut b := (f32((c >> 8) & 0xFF) / 255.0) * level
|
mut b := (f32((c >> 8) & 0xFF) / 255.0) * level
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
module ttf
|
module ttf
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
*
|
*
|
||||||
* BMP render module utility functions
|
* BMP render module utility functions
|
||||||
|
@ -15,40 +16,31 @@ module ttf
|
||||||
import encoding.utf8
|
import encoding.utf8
|
||||||
import math
|
import math
|
||||||
|
|
||||||
pub
|
pub struct BitMap {
|
||||||
struct BitMap {
|
|
||||||
pub mut:
|
pub mut:
|
||||||
tf &TTF_File
|
tf &TTF_File
|
||||||
|
|
||||||
buf byteptr // pointer to the memory buffer
|
buf byteptr // pointer to the memory buffer
|
||||||
buf_size int // allocated buf size in bytes
|
buf_size int // allocated buf size in bytes
|
||||||
|
|
||||||
width int = 1 // width of the buffer
|
width int = 1 // width of the buffer
|
||||||
height int = 1 // height of the buffer
|
height int = 1 // height of the buffer
|
||||||
bp int = 4 // byte per pixel of the buffer
|
bp int = 4 // byte per pixel of the buffer
|
||||||
|
|
||||||
bg_color u32 = 0xFFFFFF_00 // background RGBA format
|
bg_color u32 = 0xFFFFFF_00 // background RGBA format
|
||||||
color u32 = 0x000000_FF // RGBA format
|
color u32 = 0x000000_FF // RGBA format
|
||||||
scale f32 = 1.0 // internal usage!!
|
scale f32 = 1.0 // internal usage!!
|
||||||
scale_x f32 = 1.0 // X scale of the single glyph
|
scale_x f32 = 1.0 // X scale of the single glyph
|
||||||
scale_y f32 = 1.0 // Y scale of the single glyph
|
scale_y f32 = 1.0 // Y scale of the single glyph
|
||||||
angle f32 = 0.0 // angle of rotation of the bitmap
|
angle f32 = 0.0 // angle of rotation of the bitmap
|
||||||
|
|
||||||
// spaces
|
// spaces
|
||||||
space_cw f32 = 1.0 // width of the space glyph internal usage!!
|
space_cw f32 = 1.0 // width of the space glyph internal usage!!
|
||||||
space_mult f32 = f32(0.0) // 1.0/16.0 // space between letter, is a multiplier for a standrd space ax
|
space_mult f32 = f32(0.0) // 1.0/16.0 // space between letter, is a multiplier for a standrd space ax
|
||||||
|
|
||||||
// used only by internal text rendering!!
|
// used only by internal text rendering!!
|
||||||
tr_matrix []f32 = [f32(1), 0, 0, 0, 1, 0, 0, 0, 0] // transformation matrix
|
tr_matrix []f32 = [f32(1), 0, 0, 0, 1, 0, 0, 0, 0] // transformation matrix
|
||||||
ch_matrix []f32 = [f32(1), 0, 0, 0, 1, 0, 0, 0, 0] // character matrix
|
ch_matrix []f32 = [f32(1), 0, 0, 0, 1, 0, 0, 0, 0] // character matrix
|
||||||
|
|
||||||
style Style = .filled // default syle
|
style Style = .filled // default syle
|
||||||
align Text_align = .left // default text align
|
align Text_align = .left // default text align
|
||||||
justify bool // justify text flag, default deactivated
|
justify bool // justify text flag, default deactivated
|
||||||
justify_fill_ratio f32 = 0.5 // justify fill ratio, if the ratio of the filled row is >= of this then justify the text
|
justify_fill_ratio f32 = 0.5 // justify fill ratio, if the ratio of the filled row is >= of this then justify the text
|
||||||
|
|
||||||
filler [][]int // filler buffer for the renderer
|
filler [][]int // filler buffer for the renderer
|
||||||
|
|
||||||
// flag to force font embedded metrics
|
// flag to force font embedded metrics
|
||||||
use_font_metrics bool
|
use_font_metrics bool
|
||||||
}
|
}
|
||||||
|
@ -59,8 +51,7 @@ pub mut:
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
// clear clear the bitmap with 0 bytes
|
// clear clear the bitmap with 0 bytes
|
||||||
pub
|
pub fn (mut bmp BitMap) clear() {
|
||||||
fn (mut bmp BitMap) clear() {
|
|
||||||
mut sz := bmp.width * bmp.height * bmp.bp
|
mut sz := bmp.width * bmp.height * bmp.bp
|
||||||
unsafe {
|
unsafe {
|
||||||
C.memset(bmp.buf, 0x00, sz)
|
C.memset(bmp.buf, 0x00, sz)
|
||||||
|
@ -69,26 +60,24 @@ fn (mut bmp BitMap) clear() {
|
||||||
|
|
||||||
// transform matrix applied to the text
|
// transform matrix applied to the text
|
||||||
fn (bmp &BitMap) trf_txt(p &Point) (int, int) {
|
fn (bmp &BitMap) trf_txt(p &Point) (int, int) {
|
||||||
return int(p.x * bmp.tr_matrix[0] + p.y * bmp.tr_matrix[3] + bmp.tr_matrix[6]),
|
return int(p.x * bmp.tr_matrix[0] + p.y * bmp.tr_matrix[3] + bmp.tr_matrix[6]), int(
|
||||||
int(p.x * bmp.tr_matrix[1] + p.y * bmp.tr_matrix[4] + bmp.tr_matrix[7])
|
p.x * bmp.tr_matrix[1] + p.y * bmp.tr_matrix[4] + bmp.tr_matrix[7])
|
||||||
}
|
}
|
||||||
|
|
||||||
// transform matrix applied to the char
|
// transform matrix applied to the char
|
||||||
fn (bmp &BitMap) trf_ch(p &Point) (int, int) {
|
fn (bmp &BitMap) trf_ch(p &Point) (int, int) {
|
||||||
return int(p.x * bmp.ch_matrix[0] + p.y * bmp.ch_matrix[3] + bmp.ch_matrix[6]),
|
return int(p.x * bmp.ch_matrix[0] + p.y * bmp.ch_matrix[3] + bmp.ch_matrix[6]), int(
|
||||||
int(p.x * bmp.ch_matrix[1] + p.y * bmp.ch_matrix[4] + bmp.ch_matrix[7])
|
p.x * bmp.ch_matrix[1] + p.y * bmp.ch_matrix[4] + bmp.ch_matrix[7])
|
||||||
}
|
}
|
||||||
|
|
||||||
// set draw postion in the buffer
|
// set draw postion in the buffer
|
||||||
pub
|
pub fn (mut bmp BitMap) set_pos(x f32, y f32) {
|
||||||
fn (mut bmp BitMap) set_pos(x f32, y f32) {
|
|
||||||
bmp.tr_matrix[6] = x
|
bmp.tr_matrix[6] = x
|
||||||
bmp.tr_matrix[7] = y
|
bmp.tr_matrix[7] = y
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the rotation angle in radiants
|
// set the rotation angle in radiants
|
||||||
pub
|
pub fn (mut bmp BitMap) set_rotation(a f32) {
|
||||||
fn (mut bmp BitMap) set_rotation(a f32) {
|
|
||||||
bmp.tr_matrix[0] = f32(math.cos(a)) // 1
|
bmp.tr_matrix[0] = f32(math.cos(a)) // 1
|
||||||
bmp.tr_matrix[1] = f32(-math.sin(a)) // 0
|
bmp.tr_matrix[1] = f32(-math.sin(a)) // 0
|
||||||
bmp.tr_matrix[3] = f32(math.sin(a)) // 0
|
bmp.tr_matrix[3] = f32(math.sin(a)) // 0
|
||||||
|
@ -100,8 +89,7 @@ fn (mut bmp BitMap) set_rotation(a f32) {
|
||||||
* Filler functions
|
* Filler functions
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
pub
|
pub fn (mut bmp BitMap) init_filler() {
|
||||||
fn (mut bmp BitMap) init_filler() {
|
|
||||||
h := bmp.height - bmp.filler.len
|
h := bmp.height - bmp.filler.len
|
||||||
if h < 1 {
|
if h < 1 {
|
||||||
return
|
return
|
||||||
|
@ -112,15 +100,13 @@ fn (mut bmp BitMap) init_filler() {
|
||||||
// dprintln("Init filler: ${bmp.filler.len} rows")
|
// dprintln("Init filler: ${bmp.filler.len} rows")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut bmp BitMap) clear_filler() {
|
||||||
fn (mut bmp BitMap) clear_filler() {
|
|
||||||
for i in 0 .. bmp.height {
|
for i in 0 .. bmp.height {
|
||||||
bmp.filler[i].clear()
|
bmp.filler[i].clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut bmp BitMap) exec_filler() {
|
||||||
fn (mut bmp BitMap) exec_filler() {
|
|
||||||
for y in 0 .. bmp.height {
|
for y in 0 .. bmp.height {
|
||||||
if bmp.filler[y].len > 0 {
|
if bmp.filler[y].len > 0 {
|
||||||
bmp.filler[y].sort()
|
bmp.filler[y].sort()
|
||||||
|
@ -145,8 +131,7 @@ fn (mut bmp BitMap) exec_filler() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut bmp BitMap) fline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||||
fn (mut bmp BitMap) fline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|
||||||
mut x0 := f32(in_x0)
|
mut x0 := f32(in_x0)
|
||||||
mut x1 := f32(in_x1)
|
mut x1 := f32(in_x1)
|
||||||
mut y0 := f32(in_y0)
|
mut y0 := f32(in_y0)
|
||||||
|
@ -203,8 +188,7 @@ fn (mut bmp BitMap) fline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
[inline]
|
[inline]
|
||||||
pub
|
pub fn (mut bmp BitMap) plot(x int, y int, c u32) bool {
|
||||||
fn (mut bmp BitMap) plot(x int, y int, c u32) bool {
|
|
||||||
if x < 0 || x >= bmp.width || y < 0 || y >= bmp.height {
|
if x < 0 || x >= bmp.width || y < 0 || y >= bmp.height {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -229,8 +213,7 @@ fn (mut bmp BitMap) plot(x int, y int, c u32) bool {
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
// aline draw an aliased line on the bitmap
|
// aline draw an aliased line on the bitmap
|
||||||
pub
|
pub fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||||
fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|
||||||
// mut c1 := c
|
// mut c1 := c
|
||||||
mut x0 := f32(in_x0)
|
mut x0 := f32(in_x0)
|
||||||
mut x1 := f32(in_x1)
|
mut x1 := f32(in_x1)
|
||||||
|
@ -280,7 +263,6 @@ fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||||
|
|
||||||
x += 1.0
|
x += 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if y1 < y0 {
|
if y1 < y0 {
|
||||||
tmp = x0
|
tmp = x0
|
||||||
|
@ -325,9 +307,7 @@ fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||||
* draw functions
|
* draw functions
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
pub
|
pub fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||||
fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|
||||||
|
|
||||||
// outline with aliased borders
|
// outline with aliased borders
|
||||||
if bmp.style == .outline_aliased {
|
if bmp.style == .outline_aliased {
|
||||||
bmp.aline(in_x0, in_y0, in_x1, in_y1, c)
|
bmp.aline(in_x0, in_y0, in_x1, in_y1, c)
|
||||||
|
@ -371,8 +351,8 @@ fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||||
for yt in y1 .. y0 + 1 {
|
for yt in y1 .. y0 + 1 {
|
||||||
bmp.plot(x0, yt, c)
|
bmp.plot(x0, yt, c)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
// horizontal line
|
// horizontal line
|
||||||
|
return
|
||||||
} else if dy == 0 {
|
} else if dy == 0 {
|
||||||
if x0 < x1 {
|
if x0 < x1 {
|
||||||
for xt in x0 .. x1 + 1 {
|
for xt in x0 .. x1 + 1 {
|
||||||
|
@ -405,20 +385,16 @@ fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||||
y += sy
|
y += sy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (mut bmp BitMap) box(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||||
pub
|
|
||||||
fn (mut bmp BitMap) box(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|
||||||
bmp.line(in_x0, in_y0, in_x1, in_y0, c)
|
bmp.line(in_x0, in_y0, in_x1, in_y0, c)
|
||||||
bmp.line(in_x1, in_y0, in_x1, in_y1, c)
|
bmp.line(in_x1, in_y0, in_x1, in_y1, c)
|
||||||
bmp.line(in_x0, in_y1, in_x1, in_y1, c)
|
bmp.line(in_x0, in_y1, in_x1, in_y1, c)
|
||||||
bmp.line(in_x0, in_y0, in_x0, in_y1, c)
|
bmp.line(in_x0, in_y0, in_x0, in_y1, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in_cx int, in_cy int, c u32) {
|
||||||
fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in_cx int, in_cy int, c u32) {
|
|
||||||
/*
|
/*
|
||||||
x0 := int(in_x0 * bmp.scale)
|
x0 := int(in_x0 * bmp.scale)
|
||||||
x1 := int(in_x1 * bmp.scale)
|
x1 := int(in_x1 * bmp.scale)
|
||||||
|
@ -484,8 +460,7 @@ fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in_cx
|
||||||
* TTF Query functions
|
* TTF Query functions
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
pub
|
pub fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
|
||||||
fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
|
|
||||||
mut res := []int{}
|
mut res := []int{}
|
||||||
mut w := 0
|
mut w := 0
|
||||||
|
|
||||||
|
@ -505,7 +480,6 @@ fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// manage unicode chars like latin greek etc
|
// manage unicode chars like latin greek etc
|
||||||
c_len := ((0xe5000000 >> ((char >> 3) & 0x1e)) & 3) + 1
|
c_len := ((0xe5000000 >> ((char >> 3) & 0x1e)) & 3) + 1
|
||||||
if c_len > 1 {
|
if c_len > 1 {
|
||||||
|
@ -558,8 +532,7 @@ fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut bmp BitMap) get_bbox(in_string string) (int, int) {
|
||||||
fn (mut bmp BitMap) get_bbox(in_string string) (int, int){
|
|
||||||
mut w := 0
|
mut w := 0
|
||||||
|
|
||||||
mut space_cw, _ := bmp.tf.get_horizontal_metrics(u16(` `))
|
mut space_cw, _ := bmp.tf.get_horizontal_metrics(u16(` `))
|
||||||
|
@ -578,7 +551,6 @@ fn (mut bmp BitMap) get_bbox(in_string string) (int, int){
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// manage unicode chars like latin greek etc
|
// manage unicode chars like latin greek etc
|
||||||
c_len := ((0xe5000000 >> ((char >> 3) & 0x1e)) & 3) + 1
|
c_len := ((0xe5000000 >> ((char >> 3) & 0x1e)) & 3) + 1
|
||||||
if c_len > 1 {
|
if c_len > 1 {
|
||||||
|
@ -655,8 +627,7 @@ fn (mut bmp BitMap) draw_notdef_glyph(in_x int, in_w int) {
|
||||||
bmp.line(int(x - in_w), int(y), int(x), int(y - y_h), bmp.color)
|
bmp.line(int(x - in_w), int(y), int(x), int(y - y_h), bmp.color)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut bmp BitMap) draw_text(in_string string) (int, int) {
|
||||||
fn (mut bmp BitMap) draw_text(in_string string) (int, int){
|
|
||||||
mut w := 0
|
mut w := 0
|
||||||
|
|
||||||
mut space_cw, _ := bmp.tf.get_horizontal_metrics(u16(` `))
|
mut space_cw, _ := bmp.tf.get_horizontal_metrics(u16(` `))
|
||||||
|
@ -675,7 +646,6 @@ fn (mut bmp BitMap) draw_text(in_string string) (int, int){
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// manage unicode chars like latin greek etc
|
// manage unicode chars like latin greek etc
|
||||||
c_len := ((0xe5000000 >> ((char >> 3) & 0x1e)) & 3) + 1
|
c_len := ((0xe5000000 >> ((char >> 3) & 0x1e)) & 3) + 1
|
||||||
if c_len > 1 {
|
if c_len > 1 {
|
||||||
|
@ -732,8 +702,7 @@ fn (mut bmp BitMap) draw_text(in_string string) (int, int){
|
||||||
return w, int(abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale)
|
return w, int(abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut bmp BitMap) draw_glyph(index u16) (int, int) {
|
||||||
fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
|
|
||||||
glyph := bmp.tf.read_glyph(index)
|
glyph := bmp.tf.read_glyph(index)
|
||||||
|
|
||||||
if !glyph.valid_glyph {
|
if !glyph.valid_glyph {
|
||||||
|
@ -781,7 +750,6 @@ fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
|
||||||
} else {
|
} else {
|
||||||
s = 2
|
s = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// dprintln("s==2")
|
// dprintln("s==2")
|
||||||
mut prev := glyph.points[count - 1]
|
mut prev := glyph.points[count - 1]
|
||||||
|
@ -803,7 +771,8 @@ fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
|
||||||
|
|
||||||
// bmp.line(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, color2)
|
// bmp.line(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, color2)
|
||||||
// bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color2)
|
// bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color2)
|
||||||
bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color)
|
bmp.quadratic(x0, y0, (prev.x + point.x) / 2, (prev.y + point.y) / 2,
|
||||||
|
prev.x, prev.y, color)
|
||||||
x0 = (prev.x + point.x) / 2
|
x0 = (prev.x + point.x) / 2
|
||||||
y0 = (prev.y + point.y) / 2
|
y0 = (prev.y + point.y) / 2
|
||||||
}
|
}
|
||||||
|
@ -820,20 +789,18 @@ fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
|
||||||
// point.x + x, point.y + y);
|
// point.x + x, point.y + y);
|
||||||
// bmp.line(x0, y0, start_point.x + in_x, start_point.y + in_y, u32(0x00FF0000))
|
// bmp.line(x0, y0, start_point.x + in_x, start_point.y + in_y, u32(0x00FF0000))
|
||||||
|
|
||||||
bmp.quadratic(x0, y0, start_point.x, start_point.y ,
|
|
||||||
// start_point.x + in_x, start_point.y + in_y, u32(0xFF00FF00))
|
// start_point.x + in_x, start_point.y + in_y, u32(0xFF00FF00))
|
||||||
start_point.x, start_point.y, color)
|
bmp.quadratic(x0, y0, start_point.x, start_point.y, start_point.x,
|
||||||
|
start_point.y, color)
|
||||||
} else {
|
} else {
|
||||||
// ctx.quadraticCurveTo(prev.x + x, prev.y + y,
|
// ctx.quadraticCurveTo(prev.x + x, prev.y + y,
|
||||||
// (prev.x + point.x) / 2 + x,
|
// (prev.x + point.x) / 2 + x,
|
||||||
// (prev.y + point.y) / 2 + y);
|
// (prev.y + point.y) / 2 + y);
|
||||||
|
|
||||||
// bmp.line(x0, y0, start_point.x, start_point.y, u32(0x00FF0000)
|
// bmp.line(x0, y0, start_point.x, start_point.y, u32(0x00FF0000)
|
||||||
bmp.quadratic(x0, y0, start_point.x, start_point.y,
|
|
||||||
(point.x + start_point.x)/2,
|
|
||||||
(point.y + start_point.y)/2,
|
|
||||||
// u32(0xFF000000))
|
// u32(0xFF000000))
|
||||||
color)
|
bmp.quadratic(x0, y0, start_point.x, start_point.y, (point.x +
|
||||||
|
start_point.x) / 2, (point.y + start_point.y) / 2, color)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// last point not in a curve
|
// last point not in a curve
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
module ttf
|
module ttf
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
*
|
*
|
||||||
* BMP render module utility functions
|
* BMP render module utility functions
|
||||||
|
@ -15,11 +16,9 @@ import math
|
||||||
import gg
|
import gg
|
||||||
import sokol.sgl
|
import sokol.sgl
|
||||||
|
|
||||||
pub
|
pub struct TTF_render_Sokol {
|
||||||
struct TTF_render_Sokol {
|
|
||||||
pub mut:
|
pub mut:
|
||||||
bmp &BitMap // Base bitmap render
|
bmp &BitMap // Base bitmap render
|
||||||
|
|
||||||
// rendering fields
|
// rendering fields
|
||||||
sg_img C.sg_image // sokol image
|
sg_img C.sg_image // sokol image
|
||||||
scale_reduct f32 = 2.0 // scale of the cpu texture for filtering
|
scale_reduct f32 = 2.0 // scale of the cpu texture for filtering
|
||||||
|
@ -35,8 +34,7 @@ fn (mut tf_skl TTF_render_Sokol) format_texture(){
|
||||||
tf_skl.bmp.format_texture()
|
tf_skl.bmp.format_texture()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32) {
|
||||||
fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32){
|
|
||||||
scale_reduct := tf_skl.scale_reduct
|
scale_reduct := tf_skl.scale_reduct
|
||||||
device_dpi := tf_skl.device_dpi
|
device_dpi := tf_skl.device_dpi
|
||||||
font_size := in_font_size //* scale_reduct
|
font_size := in_font_size //* scale_reduct
|
||||||
|
@ -57,7 +55,7 @@ fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32){
|
||||||
if sz > 0 {
|
if sz > 0 {
|
||||||
free(tf_skl.bmp.buf)
|
free(tf_skl.bmp.buf)
|
||||||
}
|
}
|
||||||
dprintln("create_text Alloc: $sz bytes")
|
dprintln('create_text Alloc: $sz bytes')
|
||||||
tf_skl.bmp.buf = malloc(sz)
|
tf_skl.bmp.buf = malloc(sz)
|
||||||
tf_skl.bmp.buf_size = sz
|
tf_skl.bmp.buf_size = sz
|
||||||
}
|
}
|
||||||
|
@ -72,8 +70,7 @@ fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32){
|
||||||
tf_skl.format_texture()
|
tf_skl.format_texture()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, in_h int, in_font_size f32) {
|
||||||
fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, in_h int, in_font_size f32){
|
|
||||||
scale_reduct := tf_skl.scale_reduct
|
scale_reduct := tf_skl.scale_reduct
|
||||||
device_dpi := tf_skl.device_dpi
|
device_dpi := tf_skl.device_dpi
|
||||||
font_size := in_font_size //* scale_reduct
|
font_size := in_font_size //* scale_reduct
|
||||||
|
@ -96,7 +93,7 @@ fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, in_h
|
||||||
if sz > 0 {
|
if sz > 0 {
|
||||||
free(tf_skl.bmp.buf)
|
free(tf_skl.bmp.buf)
|
||||||
}
|
}
|
||||||
dprintln("Alloc: $sz bytes")
|
dprintln('Alloc: $sz bytes')
|
||||||
tf_skl.bmp.buf = malloc(sz)
|
tf_skl.bmp.buf = malloc(sz)
|
||||||
tf_skl.bmp.buf_size = sz
|
tf_skl.bmp.buf_size = sz
|
||||||
}
|
}
|
||||||
|
@ -108,16 +105,16 @@ fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, in_h
|
||||||
tf_skl.bmp.set_pos(0, y_base)
|
tf_skl.bmp.set_pos(0, y_base)
|
||||||
tf_skl.bmp.clear()
|
tf_skl.bmp.clear()
|
||||||
|
|
||||||
tf_skl.bmp.draw_text_block(in_txt, {x: 0, y:0, w:w, h:h})
|
tf_skl.bmp.draw_text_block(in_txt, x: 0, y: 0, w: w, h: h)
|
||||||
tf_skl.format_texture()
|
tf_skl.format_texture()
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* Sokol Render functions
|
* Sokol Render functions
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
pub
|
pub fn (mut tf_skl TTF_render_Sokol) create_texture() {
|
||||||
fn (mut tf_skl TTF_render_Sokol) create_texture(){
|
|
||||||
w := tf_skl.bmp.width
|
w := tf_skl.bmp.width
|
||||||
h := tf_skl.bmp.height
|
h := tf_skl.bmp.height
|
||||||
sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
|
sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
|
||||||
|
@ -144,14 +141,12 @@ fn (mut tf_skl TTF_render_Sokol) create_texture(){
|
||||||
tf_skl.sg_img = simg
|
tf_skl.sg_img = simg
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (tf_skl TTF_render_Sokol) destroy_texture() {
|
||||||
fn (tf_skl TTF_render_Sokol) destroy_texture(){
|
|
||||||
C.sg_destroy_image(tf_skl.sg_img)
|
C.sg_destroy_image(tf_skl.sg_img)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use only if usage: .dynamic
|
// Use only if usage: .dynamic
|
||||||
pub
|
pub fn (mut tf_skl TTF_render_Sokol) update_text_texture() {
|
||||||
fn (mut tf_skl TTF_render_Sokol) update_text_texture(){
|
|
||||||
sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
|
sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
|
||||||
mut tmp_sbc := C.sg_image_content{}
|
mut tmp_sbc := C.sg_image_content{}
|
||||||
tmp_sbc.subimage[0][0] = C.sg_subimage_content{
|
tmp_sbc.subimage[0][0] = C.sg_subimage_content{
|
||||||
|
@ -161,8 +156,7 @@ fn (mut tf_skl TTF_render_Sokol) update_text_texture(){
|
||||||
C.sg_update_image(tf_skl.sg_img, &tmp_sbc)
|
C.sg_update_image(tf_skl.sg_img, &tmp_sbc)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) {
|
||||||
fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) {
|
|
||||||
// width := tf_skl.bmp.width >> 1
|
// width := tf_skl.bmp.width >> 1
|
||||||
// height := tf_skl.bmp.height >> 1
|
// height := tf_skl.bmp.height >> 1
|
||||||
sgl.push_matrix()
|
sgl.push_matrix()
|
||||||
|
@ -182,10 +176,22 @@ fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) {
|
||||||
ca := f32(math.cos(tf_skl.bmp.angle))
|
ca := f32(math.cos(tf_skl.bmp.angle))
|
||||||
sa := f32(math.sin(tf_skl.bmp.angle))
|
sa := f32(math.sin(tf_skl.bmp.angle))
|
||||||
m := [
|
m := [
|
||||||
f32(ca),-sa,0,0,
|
f32(ca),
|
||||||
sa,ca,0,0,
|
-sa,
|
||||||
0,0,1,0,
|
0,
|
||||||
x,y,0,1
|
0,
|
||||||
|
sa,
|
||||||
|
ca,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
]
|
]
|
||||||
sgl.mult_matrix(m)
|
sgl.mult_matrix(m)
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
module ttf
|
module ttf
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
*
|
*
|
||||||
* BMP render module utility functions
|
* BMP render module utility functions
|
||||||
|
@ -11,8 +12,7 @@ module ttf
|
||||||
*
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
pub
|
pub struct Text_block {
|
||||||
struct Text_block {
|
|
||||||
x int // x postion of the left high corner
|
x int // x postion of the left high corner
|
||||||
y int // y postion of the left high corner
|
y int // y postion of the left high corner
|
||||||
w int // width of the text block
|
w int // width of the text block
|
||||||
|
@ -21,7 +21,7 @@ struct Text_block {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut dev BitMap) get_justify_space_cw(txt string, w int, block_w int, space_cw int) f32 {
|
fn (mut dev BitMap) get_justify_space_cw(txt string, w int, block_w int, space_cw int) f32 {
|
||||||
num_spaces := txt.count(" ")
|
num_spaces := txt.count(' ')
|
||||||
if num_spaces < 1 {
|
if num_spaces < 1 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,7 @@ fn (mut dev BitMap) get_justify_space_cw(txt string, w int, block_w int, space_c
|
||||||
}
|
}
|
||||||
|
|
||||||
// write out a text
|
// write out a text
|
||||||
pub
|
pub fn (mut bmp BitMap) draw_text_block(text string, block Text_block) {
|
||||||
fn (mut bmp BitMap) draw_text_block(text string, block Text_block) {
|
|
||||||
mut x := block.x
|
mut x := block.x
|
||||||
mut y := block.y
|
mut y := block.y
|
||||||
mut y_base := int((bmp.tf.y_max - bmp.tf.y_min) * bmp.scale)
|
mut y_base := int((bmp.tf.y_max - bmp.tf.y_min) * bmp.scale)
|
||||||
|
@ -73,7 +72,7 @@ fn (mut bmp BitMap) draw_text_block(text string, block Text_block) {
|
||||||
y += y_base
|
y += y_base
|
||||||
} else {
|
} else {
|
||||||
// println("to cut: ${txt}")
|
// println("to cut: ${txt}")
|
||||||
mut txt1 := txt.split(" ")
|
mut txt1 := txt.split(' ')
|
||||||
mut c := txt1.len
|
mut c := txt1.len
|
||||||
// mut done := false
|
// mut done := false
|
||||||
for c > 0 {
|
for c > 0 {
|
||||||
|
|
282
vlib/x/ttf/ttf.v
282
vlib/x/ttf/ttf.v
|
@ -1,4 +1,5 @@
|
||||||
module ttf
|
module ttf
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
*
|
*
|
||||||
* TrueTypeFont reader V implementation
|
* TrueTypeFont reader V implementation
|
||||||
|
@ -16,7 +17,6 @@ module ttf
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
import strings
|
import strings
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* CMAP structs
|
* CMAP structs
|
||||||
|
@ -43,21 +43,16 @@ mut:
|
||||||
* TTF_File structs
|
* TTF_File structs
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
pub
|
pub struct TTF_File {
|
||||||
struct TTF_File{
|
|
||||||
pub mut:
|
pub mut:
|
||||||
buf []byte
|
buf []byte
|
||||||
pos u32
|
pos u32
|
||||||
|
|
||||||
length u16
|
length u16
|
||||||
|
|
||||||
scalar_type u32
|
scalar_type u32
|
||||||
search_range u16
|
search_range u16
|
||||||
entry_selector u16
|
entry_selector u16
|
||||||
range_shift u16
|
range_shift u16
|
||||||
|
|
||||||
tables map[string]Offset_Table
|
tables map[string]Offset_Table
|
||||||
|
|
||||||
version f32
|
version f32
|
||||||
font_revision f32
|
font_revision f32
|
||||||
checksum_adjustment u32
|
checksum_adjustment u32
|
||||||
|
@ -75,14 +70,11 @@ pub mut:
|
||||||
font_direction_hint i16
|
font_direction_hint i16
|
||||||
index_to_loc_format i16
|
index_to_loc_format i16
|
||||||
glyph_data_format i16
|
glyph_data_format i16
|
||||||
|
|
||||||
font_family string
|
font_family string
|
||||||
font_sub_family string
|
font_sub_family string
|
||||||
full_name string
|
full_name string
|
||||||
postscript_name string
|
postscript_name string
|
||||||
|
|
||||||
cmaps []TrueTypeCmap
|
cmaps []TrueTypeCmap
|
||||||
|
|
||||||
ascent i16
|
ascent i16
|
||||||
descent i16
|
descent i16
|
||||||
line_gap i16
|
line_gap i16
|
||||||
|
@ -95,15 +87,12 @@ pub mut:
|
||||||
caret_offset i16
|
caret_offset i16
|
||||||
metric_data_format i16
|
metric_data_format i16
|
||||||
num_of_long_hor_metrics u16
|
num_of_long_hor_metrics u16
|
||||||
|
|
||||||
kern []Kern0Table
|
kern []Kern0Table
|
||||||
|
|
||||||
// cache
|
// cache
|
||||||
glyph_cache map[int]Glyph
|
glyph_cache map[int]Glyph
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut tf TTF_File) init() {
|
||||||
fn (mut tf TTF_File) init() {
|
|
||||||
tf.read_offset_tables()
|
tf.read_offset_tables()
|
||||||
tf.read_head_table()
|
tf.read_head_table()
|
||||||
// dprintln(tf.get_info_string())
|
// dprintln(tf.get_info_string())
|
||||||
|
@ -112,17 +101,16 @@ fn (mut tf TTF_File) init() {
|
||||||
tf.read_hhea_table()
|
tf.read_hhea_table()
|
||||||
tf.read_kern_table()
|
tf.read_kern_table()
|
||||||
tf.length = tf.glyph_count()
|
tf.length = tf.glyph_count()
|
||||||
dprintln("Number of symbols: $tf.length")
|
dprintln('Number of symbols: $tf.length')
|
||||||
dprintln("*****************************")
|
dprintln('*****************************')
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* TTF_File Glyph Structs
|
* TTF_File Glyph Structs
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
pub struct Point {
|
||||||
pub
|
|
||||||
struct Point {
|
|
||||||
pub mut:
|
pub mut:
|
||||||
x int
|
x int
|
||||||
y int
|
y int
|
||||||
|
@ -140,10 +128,9 @@ const(
|
||||||
g_type_complex = u16(2) // compound type
|
g_type_complex = u16(2) // compound type
|
||||||
)
|
)
|
||||||
|
|
||||||
pub
|
pub struct Glyph {
|
||||||
struct Glyph {
|
|
||||||
pub mut:
|
pub mut:
|
||||||
g_type u16 = g_type_simple
|
g_type u16 = ttf.g_type_simple
|
||||||
contour_ends []u16
|
contour_ends []u16
|
||||||
number_of_contours i16
|
number_of_contours i16
|
||||||
points []Point
|
points []Point
|
||||||
|
@ -155,17 +142,15 @@ pub mut:
|
||||||
components []Component
|
components []Component
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* TTF_File metrics and glyph
|
* TTF_File metrics and glyph
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
pub
|
pub fn (mut tf TTF_File) get_horizontal_metrics(glyph_index u16) (int, int) {
|
||||||
fn (mut tf TTF_File) get_horizontal_metrics(glyph_index u16) (int, int) {
|
assert 'hmtx' in tf.tables
|
||||||
assert"hmtx" in tf.tables
|
|
||||||
old_pos := tf.pos
|
old_pos := tf.pos
|
||||||
mut offset := tf.tables["hmtx"].offset
|
mut offset := tf.tables['hmtx'].offset
|
||||||
|
|
||||||
mut advance_width := 0
|
mut advance_width := 0
|
||||||
mut left_side_bearing := 0
|
mut left_side_bearing := 0
|
||||||
|
@ -179,7 +164,8 @@ fn (mut tf TTF_File) get_horizontal_metrics(glyph_index u16) (int, int) {
|
||||||
// read the last entry of the hMetrics array
|
// read the last entry of the hMetrics array
|
||||||
tf.pos = offset + (tf.num_of_long_hor_metrics - 1) * 4
|
tf.pos = offset + (tf.num_of_long_hor_metrics - 1) * 4
|
||||||
advance_width = tf.get_u16()
|
advance_width = tf.get_u16()
|
||||||
tf.pos = offset + tf.num_of_long_hor_metrics * 4 + 2 * (glyph_index - tf.num_of_long_hor_metrics)
|
tf.pos = offset + tf.num_of_long_hor_metrics * 4 +
|
||||||
|
2 * (glyph_index - tf.num_of_long_hor_metrics)
|
||||||
left_side_bearing = tf.get_fword()
|
left_side_bearing = tf.get_fword()
|
||||||
}
|
}
|
||||||
tf.pos = old_pos
|
tf.pos = old_pos
|
||||||
|
@ -188,11 +174,11 @@ fn (mut tf TTF_File) get_horizontal_metrics(glyph_index u16) (int, int) {
|
||||||
|
|
||||||
fn (mut tf TTF_File) get_glyph_offset(index u32) u32 {
|
fn (mut tf TTF_File) get_glyph_offset(index u32) u32 {
|
||||||
// check if needed tables exists
|
// check if needed tables exists
|
||||||
assert "loca" in tf.tables
|
assert 'loca' in tf.tables
|
||||||
assert "glyf" in tf.tables
|
assert 'glyf' in tf.tables
|
||||||
mut old_pos := tf.pos
|
mut old_pos := tf.pos
|
||||||
|
|
||||||
table := tf.tables["loca"]
|
table := tf.tables['loca']
|
||||||
mut offset := u32(0)
|
mut offset := u32(0)
|
||||||
mut next := u32(0)
|
mut next := u32(0)
|
||||||
if tf.index_to_loc_format == 1 {
|
if tf.index_to_loc_format == 1 {
|
||||||
|
@ -209,37 +195,36 @@ fn (mut tf TTF_File) get_glyph_offset(index u32) u32{
|
||||||
// indicates glyph has no outline( eg space)
|
// indicates glyph has no outline( eg space)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// dprintln("Offset for glyph index $index is $offset")
|
// dprintln("Offset for glyph index $index is $offset")
|
||||||
tf.pos = old_pos
|
tf.pos = old_pos
|
||||||
return offset + tf.tables['glyf'].offset
|
return offset + tf.tables['glyf'].offset
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut tf TTF_File) glyph_count() u16 {
|
fn (mut tf TTF_File) glyph_count() u16 {
|
||||||
assert "maxp" in tf.tables
|
assert 'maxp' in tf.tables
|
||||||
old_pos := tf.pos
|
old_pos := tf.pos
|
||||||
tf.pos = tf.tables["maxp"].offset + 4
|
tf.pos = tf.tables['maxp'].offset + 4
|
||||||
count := tf.get_u16()
|
count := tf.get_u16()
|
||||||
tf.pos = old_pos
|
tf.pos = old_pos
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut tf TTF_File) read_glyph_dim(index u16) (int, int, int, int) {
|
||||||
fn (mut tf TTF_File) read_glyph_dim(index u16) (int, int, int, int) {
|
|
||||||
offset := tf.get_glyph_offset(index)
|
offset := tf.get_glyph_offset(index)
|
||||||
// dprintln("offset: $offset")
|
// dprintln("offset: $offset")
|
||||||
if offset == 0 || offset >= tf.tables["glyf"].offset + tf.tables["glyf"].length {
|
if offset == 0 || offset >= tf.tables['glyf'].offset + tf.tables['glyf'].length {
|
||||||
dprintln("No glyph found!")
|
dprintln('No glyph found!')
|
||||||
return 0, 0, 0, 0
|
return 0, 0, 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
assert offset >= tf.tables["glyf"].offset
|
assert offset >= tf.tables['glyf'].offset
|
||||||
assert offset < tf.tables["glyf"].offset + tf.tables["glyf"].length
|
assert offset < tf.tables['glyf'].offset + tf.tables['glyf'].length
|
||||||
|
|
||||||
tf.pos = offset
|
tf.pos = offset
|
||||||
// dprintln("file seek read_glyph: $tf.pos")
|
// dprintln("file seek read_glyph: $tf.pos")
|
||||||
|
|
||||||
/*number_of_contours*/ _ := tf.get_i16()
|
// number_of_contours
|
||||||
|
_ := tf.get_i16()
|
||||||
x_min := tf.get_fword()
|
x_min := tf.get_fword()
|
||||||
y_min := tf.get_fword()
|
y_min := tf.get_fword()
|
||||||
x_max := tf.get_fword()
|
x_max := tf.get_fword()
|
||||||
|
@ -248,8 +233,7 @@ fn (mut tf TTF_File) read_glyph_dim(index u16) (int, int, int, int) {
|
||||||
return x_min, x_max, y_min, y_max
|
return x_min, x_max, y_min, y_max
|
||||||
}
|
}
|
||||||
|
|
||||||
pub
|
pub fn (mut tf TTF_File) read_glyph(index u16) Glyph {
|
||||||
fn (mut tf TTF_File) read_glyph(index u16) Glyph {
|
|
||||||
index_int := int(index) // index.str()
|
index_int := int(index) // index.str()
|
||||||
if index_int in tf.glyph_cache {
|
if index_int in tf.glyph_cache {
|
||||||
// dprintln("Found glyp: ${index}")
|
// dprintln("Found glyp: ${index}")
|
||||||
|
@ -259,18 +243,19 @@ fn (mut tf TTF_File) read_glyph(index u16) Glyph {
|
||||||
|
|
||||||
offset := tf.get_glyph_offset(index)
|
offset := tf.get_glyph_offset(index)
|
||||||
// dprintln("offset: $offset")
|
// dprintln("offset: $offset")
|
||||||
if offset == 0 || offset >= tf.tables["glyf"].offset + tf.tables["glyf"].length {
|
if offset == 0 || offset >= tf.tables['glyf'].offset + tf.tables['glyf'].length {
|
||||||
dprintln("No glyph found!")
|
dprintln('No glyph found!')
|
||||||
return Glyph{}
|
return Glyph{}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert offset >= tf.tables["glyf"].offset
|
assert offset >= tf.tables['glyf'].offset
|
||||||
assert offset < tf.tables["glyf"].offset + tf.tables["glyf"].length
|
assert offset < tf.tables['glyf'].offset + tf.tables['glyf'].length
|
||||||
|
|
||||||
tf.pos = offset
|
tf.pos = offset
|
||||||
// dprintln("file seek read_glyph: $tf.pos")
|
// dprintln("file seek read_glyph: $tf.pos")
|
||||||
|
|
||||||
/* ---- BUG TO SOLVE -----
|
/*
|
||||||
|
---- BUG TO SOLVE -----
|
||||||
--- Order of the data if printed in the main is shuffled!! Very Strange
|
--- Order of the data if printed in the main is shuffled!! Very Strange
|
||||||
mut tmp_glyph := Glyph{
|
mut tmp_glyph := Glyph{
|
||||||
number_of_contours : tf.get_i16()
|
number_of_contours : tf.get_i16()
|
||||||
|
@ -341,10 +326,9 @@ fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph){
|
||||||
in_glyph.points << Point{
|
in_glyph.points << Point{
|
||||||
x: 0
|
x: 0
|
||||||
y: 0
|
y: 0
|
||||||
on_curve: (flag & tfk_on_curve) > 0
|
on_curve: (flag & ttf.tfk_on_curve) > 0
|
||||||
}
|
}
|
||||||
|
if (flag & ttf.tfk_repeat) > 0 {
|
||||||
if (flag & tfk_repeat) > 0 {
|
|
||||||
mut repeat_count := tf.get_u8()
|
mut repeat_count := tf.get_u8()
|
||||||
assert repeat_count > 0
|
assert repeat_count > 0
|
||||||
i += repeat_count
|
i += repeat_count
|
||||||
|
@ -353,7 +337,7 @@ fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph){
|
||||||
in_glyph.points << Point{
|
in_glyph.points << Point{
|
||||||
x: 0
|
x: 0
|
||||||
y: 0
|
y: 0
|
||||||
on_curve: (flag & tfk_on_curve) > 0
|
on_curve: (flag & ttf.tfk_on_curve) > 0
|
||||||
}
|
}
|
||||||
repeat_count--
|
repeat_count--
|
||||||
}
|
}
|
||||||
|
@ -365,13 +349,13 @@ fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph){
|
||||||
mut value := 0
|
mut value := 0
|
||||||
for i_x in 0 .. num_points {
|
for i_x in 0 .. num_points {
|
||||||
flag_x := flags[i_x]
|
flag_x := flags[i_x]
|
||||||
if (flag_x & tfk_x_is_byte) > 0 {
|
if (flag_x & ttf.tfk_x_is_byte) > 0 {
|
||||||
if (flag_x & tfk_x_delta) > 0 {
|
if (flag_x & ttf.tfk_x_delta) > 0 {
|
||||||
value += tf.get_u8()
|
value += tf.get_u8()
|
||||||
} else {
|
} else {
|
||||||
value -= tf.get_u8()
|
value -= tf.get_u8()
|
||||||
}
|
}
|
||||||
} else if (~flag_x & tfk_x_delta) > 0 {
|
} else if (~flag_x & ttf.tfk_x_delta) > 0 {
|
||||||
value += tf.get_i16()
|
value += tf.get_i16()
|
||||||
} else {
|
} else {
|
||||||
// value is unchanged
|
// value is unchanged
|
||||||
|
@ -384,13 +368,13 @@ fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph){
|
||||||
value = 0
|
value = 0
|
||||||
for i_y in 0 .. num_points {
|
for i_y in 0 .. num_points {
|
||||||
flag_y := flags[i_y]
|
flag_y := flags[i_y]
|
||||||
if (flag_y & tfk_y_is_byte) > 0 {
|
if (flag_y & ttf.tfk_y_is_byte) > 0 {
|
||||||
if (flag_y & tfk_y_delta) > 0 {
|
if (flag_y & ttf.tfk_y_delta) > 0 {
|
||||||
value += tf.get_u8()
|
value += tf.get_u8()
|
||||||
} else {
|
} else {
|
||||||
value -= tf.get_u8()
|
value -= tf.get_u8()
|
||||||
}
|
}
|
||||||
} else if (~flag_y & tfk_y_delta) > 0 {
|
} else if (~flag_y & ttf.tfk_y_delta) > 0 {
|
||||||
value += tf.get_i16()
|
value += tf.get_i16()
|
||||||
} else {
|
} else {
|
||||||
// value is unchanged
|
// value is unchanged
|
||||||
|
@ -426,10 +410,10 @@ mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph) {
|
fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph) {
|
||||||
in_glyph.g_type = g_type_complex
|
in_glyph.g_type = ttf.g_type_complex
|
||||||
mut component := Component{}
|
mut component := Component{}
|
||||||
mut flags := tfkc_more_components
|
mut flags := ttf.tfkc_more_components
|
||||||
for (flags & tfkc_more_components) > 0 {
|
for (flags & ttf.tfkc_more_components) > 0 {
|
||||||
mut arg1 := i16(0)
|
mut arg1 := i16(0)
|
||||||
mut arg2 := i16(0)
|
mut arg2 := i16(0)
|
||||||
|
|
||||||
|
@ -437,7 +421,7 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
|
||||||
|
|
||||||
component.glyph_index = tf.get_u16()
|
component.glyph_index = tf.get_u16()
|
||||||
|
|
||||||
if (flags & tfkc_arg_1_and_2_are_words) > 0 {
|
if (flags & ttf.tfkc_arg_1_and_2_are_words) > 0 {
|
||||||
arg1 = tf.get_i16()
|
arg1 = tf.get_i16()
|
||||||
arg2 = tf.get_i16()
|
arg2 = tf.get_i16()
|
||||||
} else {
|
} else {
|
||||||
|
@ -445,7 +429,7 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
|
||||||
arg2 = tf.get_u8()
|
arg2 = tf.get_u8()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & tfkc_args_are_xy_values) > 0 {
|
if (flags & ttf.tfkc_args_are_xy_values) > 0 {
|
||||||
component.matrix[4] = arg1
|
component.matrix[4] = arg1
|
||||||
component.matrix[5] = arg2
|
component.matrix[5] = arg2
|
||||||
} else {
|
} else {
|
||||||
|
@ -453,19 +437,18 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
|
||||||
component.src_point_index = arg2
|
component.src_point_index = arg2
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & tfkc_we_have_a_scale) > 0 {
|
if (flags & ttf.tfkc_we_have_a_scale) > 0 {
|
||||||
component.matrix[0] = tf.get_2dot14()
|
component.matrix[0] = tf.get_2dot14()
|
||||||
component.matrix[3] = component.matrix[0]
|
component.matrix[3] = component.matrix[0]
|
||||||
} else if (flags & tfkc_we_have_an_x_and_y_scale) > 0 {
|
} else if (flags & ttf.tfkc_we_have_an_x_and_y_scale) > 0 {
|
||||||
component.matrix[0] = tf.get_2dot14()
|
component.matrix[0] = tf.get_2dot14()
|
||||||
component.matrix[3] = tf.get_2dot14()
|
component.matrix[3] = tf.get_2dot14()
|
||||||
} else if (flags & tfkc_we_have_a_two_by_two) > 0 {
|
} else if (flags & ttf.tfkc_we_have_a_two_by_two) > 0 {
|
||||||
component.matrix[0] = tf.get_2dot14()
|
component.matrix[0] = tf.get_2dot14()
|
||||||
component.matrix[1] = tf.get_2dot14()
|
component.matrix[1] = tf.get_2dot14()
|
||||||
component.matrix[2] = tf.get_2dot14()
|
component.matrix[2] = tf.get_2dot14()
|
||||||
component.matrix[3] = tf.get_2dot14()
|
component.matrix[3] = tf.get_2dot14()
|
||||||
}
|
}
|
||||||
|
|
||||||
// dprintln("Read component glyph index ${component.glyph_index}")
|
// dprintln("Read component glyph index ${component.glyph_index}")
|
||||||
// dprintln("Transform: ${component.matrix}")
|
// dprintln("Transform: ${component.matrix}")
|
||||||
|
|
||||||
|
@ -495,10 +478,9 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
|
||||||
|
|
||||||
in_glyph.number_of_contours = i16(in_glyph.contour_ends.len)
|
in_glyph.number_of_contours = i16(in_glyph.contour_ends.len)
|
||||||
|
|
||||||
if (flags & tfkc_we_have_instructions) > 0 {
|
if (flags & ttf.tfkc_we_have_instructions) > 0 {
|
||||||
tf.pos = tf.get_u16() + tf.pos
|
tf.pos = tf.get_u16() + tf.pos
|
||||||
}
|
}
|
||||||
|
|
||||||
// ok we have a valid glyph
|
// ok we have a valid glyph
|
||||||
in_glyph.valid_glyph = true
|
in_glyph.valid_glyph = true
|
||||||
}
|
}
|
||||||
|
@ -537,10 +519,8 @@ fn (mut tf TTF_File) get_fword() i16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut tf TTF_File) get_u32() u32 {
|
fn (mut tf TTF_File) get_u32() u32 {
|
||||||
x :=(u32(tf.buf[tf.pos]) << u32(24)) |
|
x := (u32(tf.buf[tf.pos]) << u32(24)) | (u32(tf.buf[tf.pos +
|
||||||
(u32(tf.buf[tf.pos + 1]) << u32(16)) |
|
1]) << u32(16)) | (u32(tf.buf[tf.pos + 2]) << u32(8)) | u32(tf.buf[tf.pos + 3])
|
||||||
(u32(tf.buf[tf.pos + 2]) << u32(8)) |
|
|
||||||
u32(tf.buf[tf.pos + 3])
|
|
||||||
tf.pos += 4
|
tf.pos += 4
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
@ -619,7 +599,7 @@ mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut tf TTF_File) read_offset_tables() {
|
fn (mut tf TTF_File) read_offset_tables() {
|
||||||
dprintln("*** READ TABLES OFFSET ***")
|
dprintln('*** READ TABLES OFFSET ***')
|
||||||
tf.pos = 0
|
tf.pos = 0
|
||||||
tf.scalar_type = tf.get_u32()
|
tf.scalar_type = tf.get_u32()
|
||||||
num_tables := tf.get_u16()
|
num_tables := tf.get_u16()
|
||||||
|
@ -627,11 +607,11 @@ fn (mut tf TTF_File) read_offset_tables() {
|
||||||
tf.entry_selector = tf.get_u16()
|
tf.entry_selector = tf.get_u16()
|
||||||
tf.range_shift = tf.get_u16()
|
tf.range_shift = tf.get_u16()
|
||||||
|
|
||||||
dprintln("scalar_type : [0x$tf.scalar_type.hex()]")
|
dprintln('scalar_type : [0x$tf.scalar_type.hex()]')
|
||||||
dprintln("num tables : [$num_tables]")
|
dprintln('num tables : [$num_tables]')
|
||||||
dprintln("search_range : [0x$tf.search_range.hex()]")
|
dprintln('search_range : [0x$tf.search_range.hex()]')
|
||||||
dprintln("entry_selector: [0x$tf.entry_selector.hex()]")
|
dprintln('entry_selector: [0x$tf.entry_selector.hex()]')
|
||||||
dprintln("range_shift : [0x$tf.range_shift.hex()]")
|
dprintln('range_shift : [0x$tf.range_shift.hex()]')
|
||||||
|
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for i < num_tables {
|
for i < num_tables {
|
||||||
|
@ -641,7 +621,7 @@ fn (mut tf TTF_File) read_offset_tables() {
|
||||||
offset: tf.get_u32()
|
offset: tf.get_u32()
|
||||||
length: tf.get_u32()
|
length: tf.get_u32()
|
||||||
}
|
}
|
||||||
dprintln("Table: [$tag]")
|
dprintln('Table: [$tag]')
|
||||||
// dprintln("${tf.tables[tag]}")
|
// dprintln("${tf.tables[tag]}")
|
||||||
|
|
||||||
if tag != 'head' {
|
if tag != 'head' {
|
||||||
|
@ -649,7 +629,7 @@ fn (mut tf TTF_File) read_offset_tables() {
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
dprintln("*** END READ TABLES OFFSET ***")
|
dprintln('*** END READ TABLES OFFSET ***')
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -658,9 +638,9 @@ fn (mut tf TTF_File) read_offset_tables() {
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
fn (mut tf TTF_File) read_head_table() {
|
fn (mut tf TTF_File) read_head_table() {
|
||||||
dprintln("*** READ HEAD TABLE ***")
|
dprintln('*** READ HEAD TABLE ***')
|
||||||
tf.pos = tf.tables["head"].offset
|
tf.pos = tf.tables['head'].offset
|
||||||
dprintln("Offset: $tf.pos")
|
dprintln('Offset: $tf.pos')
|
||||||
|
|
||||||
tf.version = tf.get_fixed()
|
tf.version = tf.get_fixed()
|
||||||
tf.font_revision = tf.get_fixed()
|
tf.font_revision = tf.get_fixed()
|
||||||
|
@ -688,10 +668,10 @@ fn (mut tf TTF_File) read_head_table() {
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
fn (mut tf TTF_File) read_name_table() {
|
fn (mut tf TTF_File) read_name_table() {
|
||||||
dprintln("*** READ NAME TABLE ***")
|
dprintln('*** READ NAME TABLE ***')
|
||||||
assert "name" in tf.tables
|
assert 'name' in tf.tables
|
||||||
table_offset := tf.tables["name"].offset
|
table_offset := tf.tables['name'].offset
|
||||||
tf.pos = tf.tables["name"].offset
|
tf.pos = tf.tables['name'].offset
|
||||||
|
|
||||||
format := tf.get_u16() // must be 0
|
format := tf.get_u16() // must be 0
|
||||||
assert format == 0
|
assert format == 0
|
||||||
|
@ -700,8 +680,10 @@ fn (mut tf TTF_File) read_name_table() {
|
||||||
|
|
||||||
for _ in 0 .. count {
|
for _ in 0 .. count {
|
||||||
platform_id := tf.get_u16()
|
platform_id := tf.get_u16()
|
||||||
/*platform_specific_id :=*/ tf.get_u16()
|
// platform_specific_id :=
|
||||||
/*language_id :=*/ tf.get_u16()
|
tf.get_u16()
|
||||||
|
// language_id :=
|
||||||
|
tf.get_u16()
|
||||||
name_id := tf.get_u16()
|
name_id := tf.get_u16()
|
||||||
length := tf.get_u16()
|
length := tf.get_u16()
|
||||||
offset := tf.get_u16()
|
offset := tf.get_u16()
|
||||||
|
@ -709,7 +691,7 @@ fn (mut tf TTF_File) read_name_table() {
|
||||||
old_pos := tf.pos
|
old_pos := tf.pos
|
||||||
tf.pos = table_offset + string_offset + offset
|
tf.pos = table_offset + string_offset + offset
|
||||||
|
|
||||||
mut name := ""
|
mut name := ''
|
||||||
if platform_id == 0 || platform_id == 3 {
|
if platform_id == 0 || platform_id == 3 {
|
||||||
name = tf.get_unicode_string(length)
|
name = tf.get_unicode_string(length)
|
||||||
} else {
|
} else {
|
||||||
|
@ -719,18 +701,10 @@ fn (mut tf TTF_File) read_name_table() {
|
||||||
tf.pos = old_pos
|
tf.pos = old_pos
|
||||||
|
|
||||||
match name_id {
|
match name_id {
|
||||||
1 {
|
1 { tf.font_family = name }
|
||||||
tf.font_family = name
|
2 { tf.font_sub_family = name }
|
||||||
}
|
4 { tf.full_name = name }
|
||||||
2 {
|
6 { tf.postscript_name = name }
|
||||||
tf.font_sub_family = name
|
|
||||||
}
|
|
||||||
4 {
|
|
||||||
tf.full_name = name
|
|
||||||
}
|
|
||||||
6 {
|
|
||||||
tf.postscript_name = name
|
|
||||||
}
|
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -742,9 +716,9 @@ fn (mut tf TTF_File) read_name_table() {
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
fn (mut tf TTF_File) read_cmap_table() {
|
fn (mut tf TTF_File) read_cmap_table() {
|
||||||
dprintln("*** READ CMAP TABLE ***")
|
dprintln('*** READ CMAP TABLE ***')
|
||||||
assert "cmap" in tf.tables
|
assert 'cmap' in tf.tables
|
||||||
table_offset := tf.tables["cmap"].offset
|
table_offset := tf.tables['cmap'].offset
|
||||||
tf.pos = table_offset
|
tf.pos = table_offset
|
||||||
|
|
||||||
version := tf.get_u16() // must be 0
|
version := tf.get_u16() // must be 0
|
||||||
|
@ -762,7 +736,7 @@ fn (mut tf TTF_File) read_cmap_table() {
|
||||||
platform_id := tf.get_u16()
|
platform_id := tf.get_u16()
|
||||||
platform_specific_id := tf.get_u16()
|
platform_specific_id := tf.get_u16()
|
||||||
offset := tf.get_u32()
|
offset := tf.get_u32()
|
||||||
dprintln("CMap platform_id=${platform_id} specific_id=${platform_specific_id} offset=${offset}")
|
dprintln('CMap platform_id=$platform_id specific_id=$platform_specific_id offset=$offset')
|
||||||
if platform_id == 3 && platform_specific_id <= 1 {
|
if platform_id == 3 && platform_specific_id <= 1 {
|
||||||
tf.read_cmap(table_offset + offset)
|
tf.read_cmap(table_offset + offset)
|
||||||
}
|
}
|
||||||
|
@ -776,14 +750,14 @@ fn (mut tf TTF_File) read_cmap(offset u32) {
|
||||||
length := tf.get_u16()
|
length := tf.get_u16()
|
||||||
language := tf.get_u16()
|
language := tf.get_u16()
|
||||||
|
|
||||||
dprintln(" Cmap format: $format length: $length language: $language")
|
dprintln(' Cmap format: $format length: $length language: $language')
|
||||||
if format == 0 {
|
if format == 0 {
|
||||||
dprintln(" Cmap 0 Init...")
|
dprintln(' Cmap 0 Init...')
|
||||||
mut cmap := TrueTypeCmap{}
|
mut cmap := TrueTypeCmap{}
|
||||||
cmap.init_0(mut tf)
|
cmap.init_0(mut tf)
|
||||||
tf.cmaps << cmap
|
tf.cmaps << cmap
|
||||||
} else if format == 4 {
|
} else if format == 4 {
|
||||||
dprintln(" Cmap 4 Init...")
|
dprintln(' Cmap 4 Init...')
|
||||||
mut cmap := TrueTypeCmap{}
|
mut cmap := TrueTypeCmap{}
|
||||||
cmap.init_4(mut tf)
|
cmap.init_4(mut tf)
|
||||||
tf.cmaps << cmap
|
tf.cmaps << cmap
|
||||||
|
@ -816,7 +790,7 @@ fn (mut tm TrueTypeCmap) init_0(mut tf TTF_File) {
|
||||||
tm.format = 0
|
tm.format = 0
|
||||||
for i in 0 .. 256 {
|
for i in 0 .. 256 {
|
||||||
glyph_index := tf.get_u8()
|
glyph_index := tf.get_u8()
|
||||||
dprintln(" Glyph[$i] = %glyph_index")
|
dprintln(' Glyph[$i] = %glyph_index')
|
||||||
tm.arr << glyph_index
|
tm.arr << glyph_index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -834,10 +808,12 @@ fn (mut tm TrueTypeCmap) init_4(mut tf TTF_File) {
|
||||||
|
|
||||||
// 2x segcount
|
// 2x segcount
|
||||||
seg_count := tf.get_u16() >> 1
|
seg_count := tf.get_u16() >> 1
|
||||||
/*search_range :=*/ tf.get_u16()
|
// search_range :=
|
||||||
/*entry_selector :=*/ tf.get_u16()
|
tf.get_u16()
|
||||||
/*range_shift :=*/ tf.get_u16()
|
// entry_selector :=
|
||||||
|
tf.get_u16()
|
||||||
|
// range_shift :=
|
||||||
|
tf.get_u16()
|
||||||
|
|
||||||
// Ending character code for each segment, last is 0xffff
|
// Ending character code for each segment, last is 0xffff
|
||||||
for _ in 0 .. seg_count {
|
for _ in 0 .. seg_count {
|
||||||
|
@ -885,7 +861,8 @@ fn (mut tm TrueTypeCmap) map_4(char_code int, mut tf TTF_File) int {
|
||||||
if segment.start_code <= char_code && segment.end_code >= char_code {
|
if segment.start_code <= char_code && segment.end_code >= char_code {
|
||||||
mut index := (segment.id_delta + char_code) & 0xffff
|
mut index := (segment.id_delta + char_code) & 0xffff
|
||||||
if segment.id_range_offset > 0 {
|
if segment.id_range_offset > 0 {
|
||||||
glyph_index_address := segment.id_range_offset + 2 * u32(char_code - segment.start_code)
|
glyph_index_address := segment.id_range_offset +
|
||||||
|
2 * u32(char_code - segment.start_code)
|
||||||
tf.pos = glyph_index_address
|
tf.pos = glyph_index_address
|
||||||
index = tf.get_u16()
|
index = tf.get_u16()
|
||||||
}
|
}
|
||||||
|
@ -909,12 +886,13 @@ fn (mut tm TrueTypeCmap) map_4(char_code int, mut tf TTF_File) int {
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
fn (mut tf TTF_File) read_hhea_table() {
|
fn (mut tf TTF_File) read_hhea_table() {
|
||||||
dprintln("*** READ HHEA TABLE ***")
|
dprintln('*** READ HHEA TABLE ***')
|
||||||
assert "hhea" in tf.tables
|
assert 'hhea' in tf.tables
|
||||||
table_offset := tf.tables["hhea"].offset
|
table_offset := tf.tables['hhea'].offset
|
||||||
tf.pos = table_offset
|
tf.pos = table_offset
|
||||||
|
|
||||||
/*version :=*/ tf.get_fixed() // 0x00010000
|
// version :=
|
||||||
|
tf.get_fixed() // 0x00010000
|
||||||
|
|
||||||
tf.ascent = tf.get_fword()
|
tf.ascent = tf.get_fword()
|
||||||
tf.descent = tf.get_fword()
|
tf.descent = tf.get_fword()
|
||||||
|
@ -975,7 +953,7 @@ fn (mut tf TTF_File) create_kern_table0(vertical bool, cross bool) Kern0Table {
|
||||||
search_range := tf.get_u16()
|
search_range := tf.get_u16()
|
||||||
entry_selector := tf.get_u16()
|
entry_selector := tf.get_u16()
|
||||||
range_shift := tf.get_u16()
|
range_shift := tf.get_u16()
|
||||||
dprintln("n_pairs: $n_pairs search_range: $search_range entry_selector: $entry_selector range_shift: $range_shift")
|
dprintln('n_pairs: $n_pairs search_range: $search_range entry_selector: $entry_selector range_shift: $range_shift')
|
||||||
|
|
||||||
mut kt0 := Kern0Table{
|
mut kt0 := Kern0Table{
|
||||||
swap: (vertical && !cross) || (!vertical && cross)
|
swap: (vertical && !cross) || (!vertical && cross)
|
||||||
|
@ -996,18 +974,18 @@ fn (mut tf TTF_File) create_kern_table0(vertical bool, cross bool) Kern0Table {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut tf TTF_File) read_kern_table() {
|
fn (mut tf TTF_File) read_kern_table() {
|
||||||
dprintln("*** READ KERN TABLE ***")
|
dprintln('*** READ KERN TABLE ***')
|
||||||
if !("kern" in tf.tables){
|
if !('kern' in tf.tables) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
table_offset := tf.tables["kern"].offset
|
table_offset := tf.tables['kern'].offset
|
||||||
tf.pos = table_offset
|
tf.pos = table_offset
|
||||||
|
|
||||||
version := tf.get_u16() // must be 0
|
version := tf.get_u16() // must be 0
|
||||||
assert version == 0 // must be 0
|
assert version == 0 // must be 0
|
||||||
n_tables := tf.get_u16()
|
n_tables := tf.get_u16()
|
||||||
|
|
||||||
dprintln("Kern Table version: $version Kern nTables: $n_tables")
|
dprintln('Kern Table version: $version Kern nTables: $n_tables')
|
||||||
|
|
||||||
for _ in 0 .. n_tables {
|
for _ in 0 .. n_tables {
|
||||||
st_version := tf.get_u16() // sub table version
|
st_version := tf.get_u16() // sub table version
|
||||||
|
@ -1016,13 +994,13 @@ fn (mut tf TTF_File) read_kern_table() {
|
||||||
format := coverage >> 8
|
format := coverage >> 8
|
||||||
cross := coverage & 4
|
cross := coverage & 4
|
||||||
vertical := (coverage & 0x1) == 0
|
vertical := (coverage & 0x1) == 0
|
||||||
dprintln("Kerning subtable version [$st_version] format [$format] length [$length] coverage: [${coverage.hex()}]")
|
dprintln('Kerning subtable version [$st_version] format [$format] length [$length] coverage: [$coverage.hex()]')
|
||||||
if format == 0 {
|
if format == 0 {
|
||||||
dprintln("kern format: 0")
|
dprintln('kern format: 0')
|
||||||
kern := tf.create_kern_table0(vertical, cross != 0)
|
kern := tf.create_kern_table0(vertical, cross != 0)
|
||||||
tf.kern << kern
|
tf.kern << kern
|
||||||
} else {
|
} else {
|
||||||
dprintln("Unknown format -- skip")
|
dprintln('Unknown format -- skip')
|
||||||
tf.pos = tf.pos + length
|
tf.pos = tf.pos + length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1045,29 +1023,27 @@ fn (mut tf TTF_File) next_kern(glyph_index int) (int, int){
|
||||||
return x, y
|
return x, y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
* TTF_File Utility
|
* TTF_File Utility
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
pub
|
pub fn (tf TTF_File) get_info_string() string {
|
||||||
fn (tf TTF_File) get_info_string() string{
|
txt := '----- Font Info -----
|
||||||
txt := "----- Font Info -----
|
|
||||||
font_family : $tf.font_family
|
font_family : $tf.font_family
|
||||||
font_sub_family : $tf.font_sub_family
|
font_sub_family : $tf.font_sub_family
|
||||||
full_name : $tf.full_name
|
full_name : $tf.full_name
|
||||||
postscript_name : $tf.postscript_name
|
postscript_name : $tf.postscript_name
|
||||||
version : $tf.version
|
version : $tf.version
|
||||||
font_revision : $tf.font_revision
|
font_revision : $tf.font_revision
|
||||||
magic_number : ${tf.magic_number.hex()}
|
magic_number : $tf.magic_number.hex()
|
||||||
flags : ${tf.flags.hex()}
|
flags : $tf.flags.hex()
|
||||||
created unixTS : ${tf.created}
|
created unixTS : $tf.created
|
||||||
modified unixTS : ${tf.modified}
|
modified unixTS : $tf.modified
|
||||||
box : [x_min:${tf.x_min}, y_min:${tf.y_min}, x_Max:${tf.x_max}, y_Max:${tf.y_max}]
|
box : [x_min:$tf.x_min, y_min:$tf.y_min, x_Max:$tf.x_max, y_Max:$tf.y_max]
|
||||||
mac_style : ${tf.mac_style}
|
mac_style : $tf.mac_style
|
||||||
-----------------------
|
-----------------------
|
||||||
"
|
'
|
||||||
return txt
|
return txt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1080,17 +1056,27 @@ fn tst(){
|
||||||
mut tf := TTF_File{}
|
mut tf := TTF_File{}
|
||||||
|
|
||||||
tf.buf = [
|
tf.buf = [
|
||||||
byte(0xFF), // 8 bit
|
byte(0xFF), /* 8 bit */
|
||||||
0xF1, 0xF2, // 16 bit
|
0xF1,
|
||||||
0x81, 0x23, 0x45, 0x67, // 32 bit
|
0xF2, /* 16 bit */
|
||||||
0x12, 0x34, 0x12, 0x34, // get_2dot14 16 bit
|
0x81,
|
||||||
0x12, 0x34, 0x12, 0x34 // get_fixed 32 bit int
|
0x23,
|
||||||
|
0x45,
|
||||||
|
0x67, /* 32 bit */
|
||||||
|
0x12,
|
||||||
|
0x34,
|
||||||
|
0x12,
|
||||||
|
0x34, /* get_2dot14 16 bit */
|
||||||
|
0x12,
|
||||||
|
0x34,
|
||||||
|
0x12,
|
||||||
|
0x34 /* get_fixed 32 bit int */,
|
||||||
]
|
]
|
||||||
assert tf.get_u8().hex() == "ff"
|
assert tf.get_u8().hex() == 'ff'
|
||||||
assert tf.get_u16().hex() == "f1f2"
|
assert tf.get_u16().hex() == 'f1f2'
|
||||||
assert tf.get_u32().hex() == "81234567"
|
assert tf.get_u32().hex() == '81234567'
|
||||||
|
|
||||||
dprintln("buf len: ${tf.buf.len}")
|
dprintln('buf len: $tf.buf.len')
|
||||||
// dprintln( tf.get_u8().hex() )
|
// dprintln( tf.get_u8().hex() )
|
||||||
// dprintln( tf.get_u16().hex() )
|
// dprintln( tf.get_u16().hex() )
|
||||||
// dprintln( tf.get_u32().hex() )
|
// dprintln( tf.get_u32().hex() )
|
||||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -171,21 +171,27 @@ fn (mut ws Client) send_message_event(msg &Message) {
|
||||||
ws.debug_log('sending on_message event')
|
ws.debug_log('sending on_message event')
|
||||||
for ev_handler in ws.message_callbacks {
|
for ev_handler in ws.message_callbacks {
|
||||||
if !ev_handler.is_ref {
|
if !ev_handler.is_ref {
|
||||||
ev_handler.handler(ws, msg)
|
ev_handler.handler(ws, msg) or { ws.logger.error('send_message_event error: $err') }
|
||||||
} else {
|
} else {
|
||||||
ev_handler.handler2(ws, msg, ev_handler.ref)
|
ev_handler.handler2(ws, msg, ev_handler.ref) or {
|
||||||
|
ws.logger.error('send_message_event error: $err')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send_error_event invokes the on_error callback
|
// send_error_event invokes the on_error callback
|
||||||
fn (mut ws Client) send_error_event(err string) {
|
fn (mut ws Client) send_error_event(error string) {
|
||||||
ws.debug_log('sending on_error event')
|
ws.debug_log('sending on_error event')
|
||||||
for ev_handler in ws.error_callbacks {
|
for ev_handler in ws.error_callbacks {
|
||||||
if !ev_handler.is_ref {
|
if !ev_handler.is_ref {
|
||||||
ev_handler.handler(mut ws, err)
|
ev_handler.handler(mut ws, error) or {
|
||||||
|
ws.logger.error('send_error_event error: $error, err: $err')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ev_handler.handler2(mut ws, err, ev_handler.ref)
|
ev_handler.handler2(mut ws, error, ev_handler.ref) or {
|
||||||
|
ws.logger.error('send_error_event error: $error, err: $err')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,9 +201,13 @@ fn (mut ws Client) send_close_event(code int, reason string) {
|
||||||
ws.debug_log('sending on_close event')
|
ws.debug_log('sending on_close event')
|
||||||
for ev_handler in ws.close_callbacks {
|
for ev_handler in ws.close_callbacks {
|
||||||
if !ev_handler.is_ref {
|
if !ev_handler.is_ref {
|
||||||
ev_handler.handler(mut ws, code, reason)
|
ev_handler.handler(mut ws, code, reason) or {
|
||||||
|
ws.logger.error('send_close_event error: $err')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ev_handler.handler2(mut ws, code, reason, ev_handler.ref)
|
ev_handler.handler2(mut ws, code, reason, ev_handler.ref) or {
|
||||||
|
ws.logger.error('send_close_event error: $err')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,9 +217,11 @@ fn (mut ws Client) send_open_event() {
|
||||||
ws.debug_log('sending on_open event')
|
ws.debug_log('sending on_open event')
|
||||||
for ev_handler in ws.open_callbacks {
|
for ev_handler in ws.open_callbacks {
|
||||||
if !ev_handler.is_ref {
|
if !ev_handler.is_ref {
|
||||||
ev_handler.handler(mut ws)
|
ev_handler.handler(mut ws) or { ws.logger.error('send_open_event error: $err') }
|
||||||
} else {
|
} else {
|
||||||
ev_handler.handler2(mut ws, ev_handler.ref)
|
ev_handler.handler2(mut ws, ev_handler.ref) or {
|
||||||
|
ws.logger.error('send_open_event error: $err')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ const (
|
||||||
// validate_client validates client frame rules from RFC6455
|
// validate_client validates client frame rules from RFC6455
|
||||||
pub fn (mut ws Client) validate_frame(frame &Frame) ? {
|
pub fn (mut ws Client) validate_frame(frame &Frame) ? {
|
||||||
if frame.rsv1 || frame.rsv2 || frame.rsv3 {
|
if frame.rsv1 || frame.rsv2 || frame.rsv3 {
|
||||||
ws.close(1002, 'rsv cannot be other than 0, not negotiated')
|
ws.close(1002, 'rsv cannot be other than 0, not negotiated') ?
|
||||||
return error('rsv cannot be other than 0, not negotiated')
|
return error('rsv cannot be other than 0, not negotiated')
|
||||||
}
|
}
|
||||||
if (int(frame.opcode) >= 3 && int(frame.opcode) <= 7)
|
if (int(frame.opcode) >= 3 && int(frame.opcode) <= 7)
|
||||||
|
@ -113,7 +113,7 @@ fn (mut ws Client) validate_utf_8(opcode OPCode, payload []byte) ? {
|
||||||
if opcode in [.text_frame, .close] && !utf8.validate(payload.data, payload.len) {
|
if opcode in [.text_frame, .close] && !utf8.validate(payload.data, payload.len) {
|
||||||
ws.logger.error('malformed utf8 payload, payload len: ($payload.len)')
|
ws.logger.error('malformed utf8 payload, payload len: ($payload.len)')
|
||||||
ws.send_error_event('Recieved malformed utf8.')
|
ws.send_error_event('Recieved malformed utf8.')
|
||||||
ws.close(1007, 'malformed utf8 payload')
|
ws.close(1007, 'malformed utf8 payload') ?
|
||||||
return error('malformed utf8 payload')
|
return error('malformed utf8 payload')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ pub fn (mut ws Client) listen() ? {
|
||||||
defer {
|
defer {
|
||||||
ws.logger.info('Quit client listener, server($ws.is_server)...')
|
ws.logger.info('Quit client listener, server($ws.is_server)...')
|
||||||
if ws.state == .open {
|
if ws.state == .open {
|
||||||
ws.close(1000, 'closed by client')
|
ws.close(1000, 'closed by client') or { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ws.state == .open {
|
for ws.state == .open {
|
||||||
|
@ -243,10 +243,6 @@ pub fn (mut ws Client) write_ptr(bytes byteptr, payload_len int, code OPCode) ?
|
||||||
mut header := []byte{len: header_len, init: `0`} // [`0`].repeat(header_len)
|
mut header := []byte{len: header_len, init: `0`} // [`0`].repeat(header_len)
|
||||||
header[0] = byte(int(code)) | 0x80
|
header[0] = byte(int(code)) | 0x80
|
||||||
masking_key := create_masking_key()
|
masking_key := create_masking_key()
|
||||||
defer {
|
|
||||||
unsafe {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ws.is_server {
|
if ws.is_server {
|
||||||
if payload_len <= 125 {
|
if payload_len <= 125 {
|
||||||
header[1] = byte(payload_len)
|
header[1] = byte(payload_len)
|
||||||
|
@ -315,7 +311,7 @@ pub fn (mut ws Client) write(bytes []byte, code OPCode) ? {
|
||||||
|
|
||||||
// write_str, writes a string with a websocket texttype to socket
|
// write_str, writes a string with a websocket texttype to socket
|
||||||
pub fn (mut ws Client) write_str(str string) ? {
|
pub fn (mut ws Client) write_str(str string) ? {
|
||||||
ws.write_ptr(str.str, str.len, .text_frame)
|
ws.write_ptr(str.str, str.len, .text_frame) ?
|
||||||
}
|
}
|
||||||
|
|
||||||
// close closes the websocket connection
|
// close closes the websocket connection
|
||||||
|
@ -328,7 +324,7 @@ pub fn (mut ws Client) close(code int, message string) ? {
|
||||||
return ret_err
|
return ret_err
|
||||||
}
|
}
|
||||||
defer {
|
defer {
|
||||||
ws.shutdown_socket()
|
ws.shutdown_socket() or { }
|
||||||
ws.reset_state()
|
ws.reset_state()
|
||||||
}
|
}
|
||||||
ws.set_state(.closing)
|
ws.set_state(.closing)
|
||||||
|
|
|
@ -30,7 +30,7 @@ fn start_server() ? {
|
||||||
}) ?
|
}) ?
|
||||||
s.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? {
|
s.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? {
|
||||||
match msg.opcode {
|
match msg.opcode {
|
||||||
.pong { ws.write_str('pong') }
|
.pong { ws.write_str('pong') or { panic(err) } }
|
||||||
else { ws.write(msg.payload, msg.opcode) or { panic(err) } }
|
else { ws.write(msg.payload, msg.opcode) or { panic(err) } }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue