Fixed some bugs, added stlib to mtgott, displaying my age at index page
This commit is contained in:
parent
3d5af95212
commit
4656288cf1
305
Cargo.lock
generated
305
Cargo.lock
generated
@ -17,6 +17,27 @@ version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.3"
|
||||
@ -86,18 +107,59 @@ dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@ -152,6 +214,12 @@ version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.3.1"
|
||||
@ -233,12 +301,56 @@ dependencies = [
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.171"
|
||||
@ -293,6 +405,15 @@ dependencies = [
|
||||
name = "mtgott"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
@ -404,6 +525,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
@ -416,6 +546,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.0"
|
||||
@ -475,6 +611,47 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "900f6c86a685850b1bc9f6223b20125115ee3f31e01207d81655bbcc0aea9231"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10558ed0bd2a1562e630926a2d1f0b98c827da99fabd3fe20920a59642504485"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_write",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_write"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28391a4201ba7eb1984cfeb6862c0b3ea2cfe23332298967c749dddc0d6cd976"
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.5.2"
|
||||
@ -535,6 +712,123 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
@ -608,11 +902,22 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yyyi_ru"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"chrono",
|
||||
"mtgott",
|
||||
"tokio",
|
||||
"toml",
|
||||
]
|
||||
|
||||
@ -7,3 +7,5 @@ edition = "2024"
|
||||
axum = "0.8.3"
|
||||
tokio = { version = "1.44.1", features = ["rt-multi-thread"] }
|
||||
mtgott = { path = "./mtgott" }
|
||||
toml="0.8.21"
|
||||
chrono = "0.4.40"
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
I am Andreev Gregory ({{age}} y.o.),
|
||||
living in Moscow, learning programming, big fond of making patches to dwm, sometimes write some unhinged ravings.
|
||||
Most interesting stuff about me gets published <a href="/blog">here</a>.
|
||||
@ -1,3 +0,0 @@
|
||||
Я Андреев Григорий ({{age}}),
|
||||
живу в Москве, учусь прогать, люблю курить dwm и иногда пишу разного рода дичь.
|
||||
Самым интересным в своей жизни делюсь <a href="/blog">вот здесь</a>.
|
||||
@ -1,12 +1,14 @@
|
||||
{@ main lang title body @}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="{{lang}}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<title>Блог Гриши</title>
|
||||
<title>{{title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{#body#}
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
{@}
|
||||
6
assets/HypertextPages/blog.mtgott.html
Normal file
6
assets/HypertextPages/blog.mtgott.html
Normal file
@ -0,0 +1,6 @@
|
||||
{@ body $ @}
|
||||
{%let pres = missing-text[$lang].blog %}
|
||||
BLOG BODY
|
||||
{%}
|
||||
{@}
|
||||
{$ main = d: base.main d.lang missing-text[d.lang].blog.title (this.body d) $}
|
||||
@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="/assets/css/common.css">
|
||||
<title>{{pres.index.title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-container">
|
||||
<div>
|
||||
<h2 class="">{{pres.index.about_me_header}}</h2>
|
||||
<p class="description-text">{% if aboutme_template is string %} STRING {{lang_macro::incl('aboutme/')}} {% else %} NOT STRING{%endif%}</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
11
assets/HypertextPages/index.mtgott.html
Normal file
11
assets/HypertextPages/index.mtgott.html
Normal file
@ -0,0 +1,11 @@
|
||||
{@ body $ @}
|
||||
{%let pres = missing-text[$lang].index %}
|
||||
<div class="main-container">
|
||||
<div>
|
||||
<h2 class="">{{ pres.about-me-header }}</h2>
|
||||
<p class="description-text">{#pres.aboutme $#}</p>
|
||||
</div>
|
||||
</div>
|
||||
{%}
|
||||
{@}
|
||||
{$ main = d: base.main d.lang missing-text[d.lang].index.title (this.body d) $}
|
||||
12
assets/HypertextPages/missing-text/en-US.mtgott.html
Normal file
12
assets/HypertextPages/missing-text/en-US.mtgott.html
Normal file
@ -0,0 +1,12 @@
|
||||
{$ index $}
|
||||
{@ title @} Gregory title page {@}
|
||||
{@ about-me-header @} About me {@}
|
||||
{@ aboutme $ @}
|
||||
I am Andreev Gregory ({{$age}} y.o.),
|
||||
living in Moscow, learning programming, big fond of making patches to dwm, sometimes write some unhinged ravings.
|
||||
Most interesting stuff about me gets published <a href="/blog">here</a>.
|
||||
{@}
|
||||
{$}
|
||||
{$ blog $}
|
||||
{@ title @} Gregory blog {@}
|
||||
{$}
|
||||
12
assets/HypertextPages/missing-text/ru-RU.mtgott.html
Normal file
12
assets/HypertextPages/missing-text/ru-RU.mtgott.html
Normal file
@ -0,0 +1,12 @@
|
||||
{$index$}
|
||||
{@ title @} Гришина заглавная страничка {@}
|
||||
{@ about-me-header @} Обо мне {@}
|
||||
{@ aboutme $ @}
|
||||
Я Андреев Григорий ({{$age}} {%let d = o/o $age 10%}{%if == d 1%}год{%else if && (<= 2 d) (<= d 4) %}года{%else%}лет{%}{%}),
|
||||
живу в Москве, учусь прогать, люблю курить dwm и иногда пишу разного рода дичь.
|
||||
Самым интересным в своей жизни делюсь <a href="/blog">вот здесь</a>.
|
||||
{@}
|
||||
{$}
|
||||
{$blog$}
|
||||
{@ title @} Гришин блог {@}
|
||||
{$}
|
||||
@ -10,7 +10,7 @@ use crate::mtgott::runtime::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
fn usage() -> ! {
|
||||
eprintln!("Usage: program <path> [-D name value]...");
|
||||
eprintln!("Usage: mtgott_cli <template dir> <path> [-D name value]...");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ pub fn is_digit(ch: char) -> bool {
|
||||
|
||||
pub fn is_normal_word_constituent(ch: char) -> bool {
|
||||
('0'..='9').contains(&ch) || ('a'..='z').contains(&ch) || ('A'..='Z').contains(&ch)
|
||||
|| "-_+/|&~!^*".contains(ch)
|
||||
|| "<>=-_+/|&~!^*".contains(ch)
|
||||
}
|
||||
|
||||
pub fn is_normal_word(s: &str) -> bool {
|
||||
|
||||
@ -8,6 +8,7 @@ use super::parser::{parse_one_file_simplified, parse_one_file_packed};
|
||||
use super::lambda_compilation::{plemege_to_value};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use super::stdlib::add_entire_stdlib_to_root;
|
||||
|
||||
pub fn search_dir_rec_helper(
|
||||
res: &mut Vec<Vec<String>>,
|
||||
@ -121,6 +122,8 @@ pub fn get_all_templates_from_dir_text(dir: MtgottDirContent, plain_ext: &str) -
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
// fn operator_
|
||||
|
||||
pub fn get_all_templates_plus_builtins_from_dir_text(
|
||||
dir: MtgottDirContent, plain_ext: &str,
|
||||
sanitize: fn(&str) -> String,
|
||||
@ -137,12 +140,9 @@ pub fn get_all_templates_plus_builtins_from_dir_text(
|
||||
} else {
|
||||
Ok(Value::Str(Rc::new(sanitize(&format!("{:?}", arg)))))
|
||||
}
|
||||
})))?;
|
||||
add_path_with_slashes_to_root(&mut res.root, "cmd_tag_start", SharedValue::Str("{%".into()))?;
|
||||
add_path_with_slashes_to_root(&mut res.root, "write_tag_start", SharedValue::Str("{{".into()))?;
|
||||
add_path_with_slashes_to_root(&mut res.root, "roughinsert_tag_start", SharedValue::Str("{#".into()))?;
|
||||
add_path_with_slashes_to_root(&mut res.root, "magic_block_ending_tag", SharedValue::Str("{%}".into()))?;
|
||||
add_path_with_slashes_to_root(&mut res.root, "element_ending_tag", SharedValue::Str("{@}".into()))?;
|
||||
}))
|
||||
)?;
|
||||
add_entire_stdlib_to_root(&mut res.root)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
|
||||
@ -38,8 +38,8 @@ impl<'m> RuntimeEnv<'m> {
|
||||
) -> Result<Option<&'i Element>, String> {
|
||||
let n = if_sub_el.conditions.len();
|
||||
for i in 0..n {
|
||||
let expr_res = self.execute_expression(&if_sub_el.conditions[i], local, recc - 1)?;
|
||||
if expr_res.to_bool()? {
|
||||
let r = self.execute_expression(&if_sub_el.conditions[i], local, recc - 1)?;
|
||||
if self.value_to_bool(&r)? {
|
||||
return Ok(Some(&if_sub_el.branches[i]));
|
||||
}
|
||||
}
|
||||
@ -96,13 +96,13 @@ impl<'m> RuntimeEnv<'m> {
|
||||
}).collect::<Result<Vec<String>, String>>()?,
|
||||
Value::Arr(arr) => arr.as_ref().iter().enumerate()
|
||||
.map(|(ind ,value)| -> Result<String, String> {
|
||||
local[k] = Value::Int(ind as u64);
|
||||
local[k] = Value::Int(ind as i64);
|
||||
local[k + 1] = value.clone();
|
||||
self.execute_element_block(core, local, recc - 1)
|
||||
}).collect::<Result<Vec<String>, String>>()?,
|
||||
Value::Ref(SharedValue::Arr(arr)) => arr.iter().enumerate()
|
||||
.map(|(ind, sh_val)| -> Result<String, String> {
|
||||
local[k] = Value::Int(ind as u64);
|
||||
local[k] = Value::Int(ind as i64);
|
||||
local[k + 1] = Value::Ref(sh_val);
|
||||
self.execute_element_block(core, local, recc - 1)
|
||||
}).collect::<Result<Vec<String>, String>>()?,
|
||||
@ -191,7 +191,7 @@ pub fn plemege_to_value(
|
||||
}
|
||||
}
|
||||
Plemege::Expression(expr) => match expr {
|
||||
Expression::Int(n) => Ok(SharedValue::Int(n)),
|
||||
Expression::Int(n) => Ok(SharedValue::Int(n as i64)),
|
||||
Expression::Str(s) => Ok(SharedValue::Str(s)),
|
||||
// todo: optimize arrays
|
||||
Expression::Lambda(NewLambdaExpression{local_var_array, expr_id}) => {
|
||||
|
||||
@ -2,4 +2,5 @@ pub mod charclasses;
|
||||
pub mod parser;
|
||||
pub mod dirsearch;
|
||||
pub mod runtime;
|
||||
pub mod lambda_compilation;
|
||||
pub mod lambda_compilation;
|
||||
pub mod stdlib;
|
||||
@ -472,13 +472,13 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
self.p += 2;
|
||||
tp1 = self.p;
|
||||
} else if self.is_ahead("{[") {
|
||||
} else if self.is_ahead("{#") {
|
||||
fin_static(self, tp1, &mut res);
|
||||
self.p += 2;
|
||||
let expr: Expression = self.parse_expression(
|
||||
arg_names, &mut (0..arg_names.len()).collect(), recc)?;
|
||||
res.push(SubElement::InsertExpr(expr));
|
||||
if !self.is_ahead("]}") {
|
||||
if !self.is_ahead("#}") {
|
||||
return Err(FileParsingError::new(expected_write_tag_end_after_expression, self.p - 2, self.p));
|
||||
}
|
||||
self.p += 2;
|
||||
@ -869,8 +869,10 @@ impl<'a> Parser<'a> {
|
||||
used_local_consts: &mut Vec<usize>, recc: u32
|
||||
) -> Result<Expression, FileParsingError> {
|
||||
self.check_recursion_limit(recc)?;
|
||||
let mut e1: Expression = self.parse_expression_l2(arg_names, used_local_consts, recc - 1)?
|
||||
.ok_or(self.new_unexpected_char_error(expected_round_brackets_open_or_dollar_or_word_or_int_or_string_or_square_bracket_open))?;
|
||||
let mut e1o: Option<Expression> = self.parse_expression_l2(arg_names, used_local_consts, recc - 1)?;
|
||||
let Some(mut e1) = e1o else { return Err(
|
||||
self.new_unexpected_char_error(expected_round_brackets_open_or_dollar_or_word_or_int_or_string_or_square_bracket_open)
|
||||
)};
|
||||
loop {
|
||||
let arg_expr: Option<Expression> = self.parse_expression_l2(arg_names, used_local_consts,recc - 1)?;
|
||||
if matches!(arg_expr, None) { break }
|
||||
|
||||
@ -16,7 +16,7 @@ impl<'a> Drop for DebugStateGuard<'a> {
|
||||
}
|
||||
|
||||
pub enum SharedValue {
|
||||
Int(u64),
|
||||
Int(i64),
|
||||
Str(String),
|
||||
Arr(Vec<SharedValue>),
|
||||
Dict(HashMap<String, SharedValue>),
|
||||
@ -58,7 +58,7 @@ impl<'m> RuntimeEnv<'m> {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Value<'m> {
|
||||
Int(u64),
|
||||
Int(i64),
|
||||
Str(Rc<String>),
|
||||
Arr(Rc<Vec<Value<'m>>>),
|
||||
Dict(Rc<HashMap<String, Value<'m>>>),
|
||||
@ -112,7 +112,7 @@ impl SharedValue {
|
||||
}
|
||||
|
||||
impl<'m> Value<'m> {
|
||||
pub fn if_int_get(&self) -> Option<u64> {
|
||||
pub fn if_int_get(&self) -> Option<i64> {
|
||||
match self {
|
||||
Value::Int(n) => Some(*n),
|
||||
Value::Ref(SharedValue::Int(n)) => Some(*n),
|
||||
@ -195,20 +195,6 @@ impl<'m> Value<'m> {
|
||||
Value::Ref(r) => format!("Reference to {}", r.type_name())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bool(&self) -> Result<bool, String> {
|
||||
if let Some(n) = self.if_int_get() {
|
||||
Ok(n != 0)
|
||||
} else if let Some(s) = self.if_str_get_ref() {
|
||||
Ok(!s.is_empty())
|
||||
} else if self.is_arr() {
|
||||
Ok(self.arr_len() > 0)
|
||||
} else if self.is_dict() {
|
||||
Ok(self.dict_is_empty())
|
||||
} else {
|
||||
Err("Can't convert Function to bool".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'm> Value<'m> {
|
||||
@ -251,7 +237,7 @@ impl<'m> RuntimeEnv<'m> {
|
||||
match expr {
|
||||
Expression::Root => Ok(Value::Ref(&self.mtgott.root)),
|
||||
Expression::Local(i) => Ok(local[*i].clone()),
|
||||
Expression::Int(n) => Ok(Value::Int(*n)),
|
||||
Expression::Int(n) => Ok(Value::Int(*n as i64)),
|
||||
/* Yes, I could have avoided cloning. But who cares anyway, consider using
|
||||
* Element syntax for long text */
|
||||
Expression::Str(s) => Ok(Value::Str(Rc::new(s.clone()))),
|
||||
@ -318,6 +304,43 @@ impl<'m> RuntimeEnv<'m> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn value_to_bool(&self, x: &Value<'m>) -> Result<bool, String> {
|
||||
if let Some(n) = x.if_int_get() {
|
||||
Ok(n != 0)
|
||||
} else if let Some(s) = x.if_str_get_ref() {
|
||||
Ok(!s.is_empty())
|
||||
} else if x.is_arr() {
|
||||
Ok(x.arr_len() > 0)
|
||||
} else if x.is_dict() {
|
||||
Ok(!x.dict_is_empty())
|
||||
} else {
|
||||
Err(self.make_error("Can't convert Function to bool".into()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn value_eq_value(&self, a: &Value<'m>, b: &Value<'m>, recc: u32) -> Result<bool, String> {
|
||||
self.check_recc(recc)?;
|
||||
if let (Some(na), Some(nb)) = (a.if_int_get(), b.if_int_get()) {
|
||||
Ok(na == nb)
|
||||
} else if let (Some(sa), Some(sb)) = (a.if_str_get_ref(), b.if_str_get_ref()) {
|
||||
Ok(sa == sb)
|
||||
} else if a.is_arr() && b.is_arr() {
|
||||
let n = a.arr_len();
|
||||
if b.arr_len() != n { return Ok(false); }
|
||||
for i in 0..n {
|
||||
if !self.value_eq_value(&a.access_arr(i).unwrap(), &b.access_arr(i).unwrap(), recc - 1)?{
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
Ok(true)
|
||||
} else if a.is_dict() || b.is_dict() || a.if_fn_get().is_some() || b.if_fn_get().is_some() {
|
||||
Err(self.make_error("Can't compare dictionaries and functions"))
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have to add two paths and one is a prefix of another, like here:
|
||||
|
||||
185
mtgott/src/stdlib.rs
Normal file
185
mtgott/src/stdlib.rs
Normal file
@ -0,0 +1,185 @@
|
||||
/* I pray for rustc correctly understanding this filename */
|
||||
|
||||
use std::error::Error;
|
||||
use std::rc::Rc;
|
||||
use runtime::*;
|
||||
|
||||
fn add_basic_bin_operator_to_root(
|
||||
root: &mut SharedValue, path: &str,
|
||||
op: for<'a> fn(&RuntimeEnv<'a>, Value<'a>, Value<'a>, u32) -> Result<Value<'a>, String>
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
add_path_with_dots_to_root(root, path, SharedValue::Fn(Box::new(
|
||||
move |re: &RuntimeEnv, a: Value, _: u32| -> Result<Value, String> {
|
||||
Ok(Value::Fn(Rc::new(move |re: &RuntimeEnv, b: Value, recc: u32| -> Result<Value, String> {
|
||||
re.check_recc(recc)?;
|
||||
op(re, a.clone(), b, recc)
|
||||
})))
|
||||
}
|
||||
)))
|
||||
}
|
||||
|
||||
fn operator_plus<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
if let (Some(na), Some(nb)) = (a.if_int_get(), b.if_int_get()) {
|
||||
Ok(Value::Int(na + nb))
|
||||
} else if let (Some(sa), Some(sb)) = (a.if_str_get_ref(), b.if_str_get_ref()) {
|
||||
Ok(Value::Str(Rc::new(String::from(sa) + sb)))
|
||||
} else {
|
||||
Err(re.make_error(&format!("Incorrect operation {} + {}", a.type_name(), b.type_name())))
|
||||
}
|
||||
}
|
||||
|
||||
fn operator_minus<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
if let (Some(na), Some(nb)) = (a.if_int_get(), b.if_int_get()) {
|
||||
Ok(Value::Int(na - nb))
|
||||
} else {
|
||||
Err(re.make_error(&format!("Incorrect operation {} - {}", a.type_name(), b.type_name())))
|
||||
}
|
||||
}
|
||||
|
||||
fn operator_product<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
if let (Some(na), Some(nb)) = (a.if_int_get(), b.if_int_get()) {
|
||||
Ok(Value::Int(na + nb))
|
||||
} else if let (Some(s), Some(n)) = (a.if_str_get_ref(), b.if_int_get()) {
|
||||
Ok(Value::Str(Rc::new(s.repeat(n as usize))))
|
||||
} else if let (Some(n), Some(s)) = (a.if_int_get(), b.if_str_get_ref()) {
|
||||
Ok(Value::Str(Rc::new(s.repeat(n as usize))))
|
||||
} else {
|
||||
Err(re.make_error(&format!("Incorrect operation {} * {}", a.type_name(), b.type_name())))
|
||||
}
|
||||
}
|
||||
|
||||
fn operator_division<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
if let (Some(na), Some(nb)) = (a.if_int_get(), b.if_int_get()) {
|
||||
if nb == 0 {
|
||||
Err(re.make_error("Divided by zero".into()))
|
||||
} else {
|
||||
Ok(Value::Int(na.div_euclid(nb)))
|
||||
}
|
||||
} else {
|
||||
Err(re.make_error(&format!("Incorrect operation {} / {}", a.type_name(), b.type_name())))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn operator_remainder<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
if let (Some(na), Some(nb)) = (a.if_int_get(), b.if_int_get()) {
|
||||
if nb == 0 {
|
||||
Err(re.make_error("Divided by zero".into()))
|
||||
} else {
|
||||
Ok(Value::Int(na.rem_euclid(nb)))
|
||||
}
|
||||
} else {
|
||||
Err(re.make_error(&format!("Incorrect operation {} % {}", a.type_name(), b.type_name())))
|
||||
}
|
||||
}
|
||||
|
||||
fn operator_and<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
Ok(Value::Int((re.value_to_bool(&a)? && re.value_to_bool(&b)?) as i64))
|
||||
}
|
||||
|
||||
fn operator_or<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
Ok(Value::Int((re.value_to_bool(&a)? || re.value_to_bool(&b)?) as i64))
|
||||
}
|
||||
|
||||
fn operator_xor<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
Ok(Value::Int((re.value_to_bool(&a)? ^ re.value_to_bool(&b)?) as i64))
|
||||
}
|
||||
|
||||
fn operator_equal<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, recc: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
Ok(Value::Int(re.value_eq_value(&a, &b, recc)? as i64))
|
||||
}
|
||||
|
||||
fn operator_not_equal<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, recc: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
Ok(Value::Int(!re.value_eq_value(&a, &b, recc)? as i64))
|
||||
}
|
||||
|
||||
fn value_less(a: &Value, b: &Value) -> Result<bool, ()> {
|
||||
if let (Some(na), Some(nb)) = (a.if_int_get(), b.if_int_get()) {
|
||||
Ok(na < nb)
|
||||
} else if let (Some(sa), Some(sb)) = (a.if_str_get_ref(), b.if_str_get_ref()) {
|
||||
Ok(sa < sb)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
fn operator_less<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
match value_less(&a, &b) {
|
||||
Ok(ans) => Ok(Value::Int(ans as i64)),
|
||||
Err(_) => Err(re.make_error(&format!("Incorrect operation {} < {}", a.type_name(), b.type_name())))
|
||||
}
|
||||
}
|
||||
|
||||
fn operator_less_or_equal<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
match value_less(&b, &a) {
|
||||
Ok(ans) => Ok(Value::Int(!ans as i64)),
|
||||
Err(_) => Err(re.make_error(&format!("Incorrect operation {} <= {}", a.type_name(), b.type_name())))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn operator_greater<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
match value_less(&b, &a) {
|
||||
Ok(ans) => Ok(Value::Int(ans as i64)),
|
||||
Err(_) => Err(re.make_error(&format!("Incorrect operation {} > {}", a.type_name(), b.type_name())))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn operator_greater_or_equal<'a>(
|
||||
re: &RuntimeEnv<'a>, a: Value<'a>, b: Value<'a>, _: u32
|
||||
) -> Result<Value<'a>, String> {
|
||||
match value_less(&a, &b) {
|
||||
Ok(ans) => Ok(Value::Int(!ans as i64)),
|
||||
Err(_) => Err(re.make_error(&format!("Incorrect operation {} >= {}", a.type_name(), b.type_name())))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_entire_stdlib_to_root(root: &mut SharedValue) -> Result<(), Box<dyn Error>> {
|
||||
add_path_with_slashes_to_root(root, "magic_tag_start", SharedValue::Str("{%".into()))?;
|
||||
add_path_with_slashes_to_root(root, "write_tag_start", SharedValue::Str("{{".into()))?;
|
||||
add_path_with_slashes_to_root(root, "roughinsert_tag_start", SharedValue::Str("{#".into()))?;
|
||||
add_path_with_slashes_to_root(root, "magic_block_ending_tag", SharedValue::Str("{%}".into()))?;
|
||||
add_path_with_slashes_to_root(root, "element_ending_tag", SharedValue::Str("{@}".into()))?;
|
||||
add_basic_bin_operator_to_root(root, "+", operator_plus)?;
|
||||
add_basic_bin_operator_to_root(root, "-", operator_minus)?;
|
||||
add_basic_bin_operator_to_root(root, "*", operator_product)?;
|
||||
add_basic_bin_operator_to_root(root, "/", operator_division)?;
|
||||
add_basic_bin_operator_to_root(root, "o/o", operator_remainder)?;
|
||||
add_basic_bin_operator_to_root(root, "&&", operator_and)?;
|
||||
add_basic_bin_operator_to_root(root, "||", operator_or)?;
|
||||
add_basic_bin_operator_to_root(root, "^^", operator_xor)?;
|
||||
add_basic_bin_operator_to_root(root, "==", operator_equal)?;
|
||||
add_basic_bin_operator_to_root(root, "!=", operator_not_equal)?;
|
||||
add_basic_bin_operator_to_root(root, "<", operator_less)?;
|
||||
add_basic_bin_operator_to_root(root, "<=", operator_less_or_equal)?;
|
||||
add_basic_bin_operator_to_root(root, ">", operator_greater)?;
|
||||
add_basic_bin_operator_to_root(root, ">=", operator_greater_or_equal)?;
|
||||
Ok(())
|
||||
}
|
||||
@ -84,7 +84,7 @@ fn t007(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "file".into(), text: "{$ pack $}{$c=45$}{$} {@ el @}---{{this.pack.c}}---{@} ".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{[file.el]}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: "{#file.el#}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "---45---");
|
||||
@ -95,7 +95,7 @@ fn t008(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "file".into(), text: "{@ el a@}---{{a}}---{@} ".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{[file.el \"45\"]}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: "{#file.el \"45\"#}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "---45---");
|
||||
@ -106,7 +106,7 @@ fn t009(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "file".into(), text: "{@ el a b c d e f g @}---{{a}}---{{c}}---{{e}}---{{g}}---{@} ".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{[file.el 1 2 3 4 5 6 7]}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: "{#file.el 1 2 3 4 5 6 7#}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "---1---3---5---7---");
|
||||
@ -118,7 +118,7 @@ fn t010(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "file".into(), text: "{@el a b @} {{a}}{{b}} {@} ".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{[file.el 1 2]}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: "{#file.el 1 2#}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(Value::Int(0), "index", 50).unwrap(), "12");
|
||||
@ -127,9 +127,9 @@ fn t010(){
|
||||
#[test]
|
||||
fn t011(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "file".into(), text: "{@el a @} {{a[1]}} {@} ".into()}
|
||||
FileWithPath{v_path: "file".into(), text: "{@el a @} {{a[1#}} {@} ".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{[file.el $]}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: "{#file.el $#}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
@ -142,9 +142,9 @@ fn t011(){
|
||||
#[test]
|
||||
fn t012(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "file".into(), text: "{@el a @} {{a[1]}} {@} ".into()}
|
||||
FileWithPath{v_path: "file".into(), text: "{@el a @} {{a[1#}} {@} ".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{[file[\"el\"] $]}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: "{#file[\"el\"] $#}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
@ -170,7 +170,7 @@ fn t013(){
|
||||
fn t014(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: " {{ $[0 ]}} {{$ [1]}} {{$[ 2]}} ".into()}
|
||||
FileWithPath{v_path: "index".into(), text: " {{ $[0 #}} {{$ [1#}} {{$[ 2#}} ".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
@ -182,9 +182,9 @@ fn t014(){
|
||||
#[test]
|
||||
fn t015(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "help".into(), text: " {@www $ a b@} {{$[a]}} {{$[b]}} {@}".into()}
|
||||
FileWithPath{v_path: "help".into(), text: " {@www $ a b@} {{$[a#}} {{$[b#}} {@}".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: " {[help.www $ 2 1 ]}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: " {#help.www $ 2 1 #}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
@ -242,7 +242,7 @@ fn t019(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "__".into(), text: "{$arr = [0, 10, 20, 30]$}".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: " {{ (x:y:z:w:w x z) 2 \"Lol\" __ x:z:z.arr[x]}}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: " {{ (x:y:z:w:w x z) 2 \"Lol\" __ x:z:z.arr[x#}}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
@ -256,7 +256,7 @@ fn t020(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "__".into(), text: "{$arr = [0, 10, 20, 30]$}".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: " {{ (x:y:z:w:w x z) __ \"Lol\" 2 x:z:x.arr[z]}}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: " {{ (x:y:z:w:w x z) __ \"Lol\" 2 x:z:x.arr[z#}}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
@ -268,7 +268,7 @@ fn t020(){
|
||||
#[test]
|
||||
fn t021(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "__".into(), text: "{$arr = [\" zero\", 10, 20,]$} {$dict$} {$lol = \"HELLO\"$} {@ cat a b @}{[a]}{[b]}{@} {$}".into()}
|
||||
FileWithPath{v_path: "__".into(), text: "{$arr = [\" zero\", 10, 20,]$} {$dict$} {$lol = \"HELLO\"$} {@ cat a b @}{#a#}{#b#}{@} {$}".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: " {{ __.dict.cat ((a:b:c:c[b][a]) \"lol\" \"dict\" __) __.arr[0] }}".into()}
|
||||
], plain: vec![]};
|
||||
@ -281,7 +281,7 @@ fn t021(){
|
||||
#[test]
|
||||
fn t022(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "__".into(), text: "{$arr = [\" zero\", 10, 20,]$} {$dict$} {$lol = \"HELLO\"$} {@ cat a b @}{[a]}{[b]}{@} {$}".into()}
|
||||
FileWithPath{v_path: "__".into(), text: "{$arr = [\" zero\", 10, 20,]$} {$dict$} {$lol = \"HELLO\"$} {@ cat a b @}{#a#}{#b#}{@} {$}".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: " {{ __.dict.cat ((a:b:c:c[a][b]) \"dict\" \"lol\" __) __.arr[0] }}".into()}
|
||||
], plain: vec![]};
|
||||
@ -301,7 +301,7 @@ fn t023(){
|
||||
B
|
||||
{@} ".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: " {[ aaa.el ([1, 2, 3]) ]}".into()}
|
||||
FileWithPath{v_path: "index".into(), text: " {# aaa.el ([1, 2, 3]) #}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
@ -414,9 +414,7 @@ fn t029(){
|
||||
|
||||
#[test]
|
||||
fn t030(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "A".into(), text: "".into()}
|
||||
], imtgott: vec![
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{% for k, v: $ %} {{k }}->{{ v}} {% lf %} ".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
@ -429,9 +427,7 @@ fn t030(){
|
||||
|
||||
#[test]
|
||||
fn t031(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "A".into(), text: "".into()}
|
||||
], imtgott: vec![
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{% for k, v: $ %} {{k }}:{{ v}} {% gap %} ".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
@ -444,9 +440,7 @@ fn t031(){
|
||||
|
||||
#[test]
|
||||
fn t032(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "A".into(), text: "".into()}
|
||||
], imtgott: vec![
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{%for v: $ %} ->{{v}} {%gap%} ".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
@ -455,4 +449,132 @@ fn t032(){
|
||||
"index", 50
|
||||
).unwrap();
|
||||
assert!(["->1 ->2".to_string(), "->2 ->1".to_string()].contains(&a));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t033(){
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{% if 1%}Yes{%}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
Value::Int(0), "index", 50
|
||||
).unwrap(), "Yes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t034(){
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{% if 0%}Yes{%}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
Value::Int(0), "index", 50
|
||||
).unwrap(), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t035(){
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{%if 0%}Yes{%endif%}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
Value::Int(0), "index", 50
|
||||
).unwrap(), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t036(){
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{%if 0%}Yes{%else%}No{%}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
Value::Int(0), "index", 50
|
||||
).unwrap(), "No");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn t037(){
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{%if \"0\"%}Yes{%else%}No{%endif%}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
Value::Int(0), "index", 50
|
||||
).unwrap(), "Yes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t038(){
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{%if \"0\"%}Yes{%else%}No{%endif%}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
Value::Int(0), "index", 50
|
||||
).unwrap(), "Yes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t039(){
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{%if \"\"%}Yes{%else if 1%}Or Maybe{%else%}No{%endif%}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
Value::Int(0), "index", 50
|
||||
).unwrap(), "Or Maybe");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t040(){
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{%if \"\"%}Yes{%else if 0%}Or Maybe{%}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
Value::Int(0), "index", 50
|
||||
).unwrap(), "");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn t041(){
|
||||
let i = MtgottDirContent{mtgott: vec![
|
||||
FileWithPath{v_path: "dictionaries".into(), text: "{$ empty $}{$} {$second$}{$el = 3$} {$}".into()}
|
||||
], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "{%if dictionaries.empty%}Yes {%else if dictionaries.second %}Or Maybe {%}".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
Value::Int(0), "index", 50
|
||||
).unwrap(), "Or Maybe");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn t042(){
|
||||
let i = MtgottDirContent{mtgott: vec![], imtgott: vec![
|
||||
FileWithPath{v_path: "index".into(), text: "
|
||||
START
|
||||
{%for x: $%}
|
||||
{%if x.a%} A {% else if x.b%}B {%else if x.c%}C {%else%} D{%}
|
||||
|
||||
{%lf%}
|
||||
END
|
||||
".into()}
|
||||
], plain: vec![]};
|
||||
let r = get_root_html_from_dir_text_html(i).unwrap();
|
||||
assert_gave!(r.render(
|
||||
valarr![
|
||||
valdict!["a" => Value::Int(1), "b" => Value::Int(1), "c" => Value::Int(1),],
|
||||
valdict!["a" => Value::Int(0), "b" => Value::Int(1), "c" => Value::Int(1),],
|
||||
valdict!["a" => Value::Int(0), "b" => Value::Int(0), "c" => Value::Int(1),],
|
||||
valdict!["a" => Value::Int(0), "b" => Value::Int(0), "c" => Value::Int(0),],
|
||||
],
|
||||
"index", 50
|
||||
).unwrap(), "START\n A\n B\n C\n D\nEND");
|
||||
}
|
||||
73
src/lib.rs
73
src/lib.rs
@ -9,6 +9,48 @@ use axum::http;
|
||||
use mtgott::dirsearch::{search_dir, get_root_html};
|
||||
use mtgott::runtime::{MTGOTT, Value};
|
||||
use std::error::Error;
|
||||
use axum::http::header::ACCEPT_LANGUAGE;
|
||||
use std::rc::Rc;
|
||||
use chrono::{Datelike, TimeZone, Utc};
|
||||
|
||||
macro_rules! valarr {
|
||||
($($el:expr),* $(,)?) => {
|
||||
mtgott::runtime::Value::Arr(std::rc::Rc::new(
|
||||
vec![$($el),*]
|
||||
))
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! valdict {
|
||||
($($el:literal => $val:expr),* $(,)?) => {{
|
||||
let mut hashmap: std::collections::HashMap<String, mtgott::runtime::Value> = std::collections::HashMap::new();
|
||||
$(hashmap.insert($el.to_string(), $val);)*
|
||||
mtgott::runtime::Value::Dict(std::rc::Rc::new(hashmap))
|
||||
}}
|
||||
}
|
||||
|
||||
fn years_between<T: chrono::Datelike>(start: T, end: T) -> i32 {
|
||||
let mut years = end.year() - start.year();
|
||||
if (end.month(), end.day()) < (start.month(), start.day()) {
|
||||
years -= 1;
|
||||
}
|
||||
years
|
||||
}
|
||||
|
||||
struct YyyiConfig {
|
||||
birthday: chrono::DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl YyyiConfig {
|
||||
fn for_me() -> YyyiConfig { Self {
|
||||
birthday: Utc.with_ymd_and_hms(2005, 06, 21, 0, 0, 0).single().unwrap(),
|
||||
} }
|
||||
}
|
||||
|
||||
struct LanguageConfig {
|
||||
available: Vec<String>,
|
||||
default: String,
|
||||
}
|
||||
|
||||
struct StaticAsset {
|
||||
content_type: HeaderValue,
|
||||
@ -18,6 +60,8 @@ struct StaticAsset {
|
||||
struct AssetsCache {
|
||||
static_assets: HashMap<String, StaticAsset>,
|
||||
pages: MTGOTT,
|
||||
l_conf: LanguageConfig,
|
||||
misc_cfg: YyyiConfig,
|
||||
}
|
||||
|
||||
struct ExtensionContentTypeCorr{
|
||||
@ -56,7 +100,12 @@ impl AssetsCache {
|
||||
fn load_assets(assets_dir: &str) -> Result<AssetsCache, Box<dyn Error>> {
|
||||
Ok(AssetsCache {
|
||||
static_assets: load_needed_static_assets(assets_dir)?,
|
||||
pages: get_root_html(&format!("{assets_dir}/HypertextPages"))?
|
||||
pages: get_root_html(&format!("{assets_dir}/HypertextPages"))?,
|
||||
l_conf: LanguageConfig{
|
||||
available: vec!["ru-RU".into(), "en-US".into()],
|
||||
default: "ru-RU".into(),
|
||||
},
|
||||
misc_cfg: YyyiConfig::for_me(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -76,21 +125,23 @@ async fn static_assets(
|
||||
|
||||
async fn page_index(
|
||||
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
|
||||
// axum::extract::Extension(t): axum::extract::Extension<tera::Tera>
|
||||
) -> axum::response::Html<String> {
|
||||
let gr = Value::Int(0);
|
||||
axum::response::Html(assets.pages.render(gr, "index", 500).unwrap())
|
||||
let now = chrono::Utc::now();
|
||||
let age = years_between(assets.misc_cfg.birthday, now);
|
||||
let gr = valdict![
|
||||
"age" => Value::Int(age as i64),
|
||||
"lang" => Value::Str(Rc::new(assets.l_conf.default.clone()))
|
||||
];
|
||||
axum::response::Html(assets.pages.render(gr, "index.main", 500).unwrap())
|
||||
}
|
||||
|
||||
async fn page_blog(
|
||||
axum::extract::State(assets): axum::extract::State<Arc<AssetsCache>>,
|
||||
// axum::extract::Extension(t): axum::extract::Extension<tera::Tera>
|
||||
) -> impl axum::response::IntoResponse {
|
||||
// let mut context = tera::Context::new();
|
||||
// context.insert("lang", &assets.missing_text[0].0);
|
||||
// context.insert("pres", &assets.missing_text[0].1);
|
||||
// axum::response::Html(assets.templates.render("blog.html", &context).expect("Tera failure"))
|
||||
axum::response::Html(String::new())
|
||||
let gr = valdict![
|
||||
"lang" => Value::Str(Rc::new(assets.l_conf.default.clone()))
|
||||
];
|
||||
axum::response::Html(assets.pages.render(gr, "blog.main", 500).unwrap())
|
||||
}
|
||||
|
||||
async fn fallback_page() -> axum::http::StatusCode {
|
||||
@ -108,8 +159,8 @@ pub async fn run_yyyi_ru() {
|
||||
let app = axum::Router::new()
|
||||
.without_v07_checks()
|
||||
.route("/", axum::routing::MethodRouter::new().get(page_index))
|
||||
.route("/assets/{*path}", axum::routing::get(static_assets))
|
||||
.route("/blog", axum::routing::get(page_blog))
|
||||
.route("/assets/{*path}", axum::routing::get(static_assets))
|
||||
.fallback(fallback_page).with_state(assets);
|
||||
// .layer(axum::Extension(templates));
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user