feat: ability to categorize
This commit is contained in:
26
index.html
26
index.html
@@ -45,13 +45,21 @@ span {
|
|||||||
<h2><!-- t: safe sitename --></h2>
|
<h2><!-- t: safe sitename --></h2>
|
||||||
<!-- t: end -->
|
<!-- t: end -->
|
||||||
|
|
||||||
|
<!-- t: set ignore
|
||||||
|
-->
|
||||||
|
|
||||||
<!-- t: if running -->
|
<!-- t: if running -->
|
||||||
|
<!-- t: set heading true -->
|
||||||
|
<!-- t: for running -->
|
||||||
|
<!-- t: ifline id ignore -->
|
||||||
|
<!-- t: else -->
|
||||||
|
<!-- t: if heading -->
|
||||||
|
<!-- t: set heading -->
|
||||||
|
|
||||||
<h3>things running on the server</h3>
|
<h3>things running on the server</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<!-- t: for running -->
|
<!-- t: end -->
|
||||||
<li>
|
<li>
|
||||||
<!-- t: if info -->
|
<!-- t: if info -->
|
||||||
<a href="/info/<!-- t: raw info -->">
|
<a href="/info/<!-- t: raw info -->">
|
||||||
@@ -82,8 +90,7 @@ span {
|
|||||||
<!-- t: set linebreak -->
|
<!-- t: set linebreak -->
|
||||||
<!-- t: for line additional -->
|
<!-- t: for line additional -->
|
||||||
<!-- t: raw linebreak -->
|
<!-- t: raw linebreak -->
|
||||||
<!-- t: set linebreak <br>
|
<!-- t: set linebreak <br> -->
|
||||||
-->
|
|
||||||
<!-- t: safe line -->
|
<!-- t: safe line -->
|
||||||
<!-- t: end -->
|
<!-- t: end -->
|
||||||
</div>
|
</div>
|
||||||
@@ -95,17 +102,24 @@ span {
|
|||||||
<!-- t: end -->
|
<!-- t: end -->
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<!-- t: end -->
|
||||||
<!-- t: end -->
|
<!-- t: end -->
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- t: end -->
|
<!-- t: end -->
|
||||||
|
|
||||||
<!-- t: if static -->
|
<!-- t: if static -->
|
||||||
|
<!-- t: set heading true -->
|
||||||
|
<!-- t: for static -->
|
||||||
|
<!-- t: ifline id ignore -->
|
||||||
|
<!-- t: else -->
|
||||||
|
<!-- t: if heading -->
|
||||||
|
<!-- t: set heading -->
|
||||||
|
|
||||||
<h3>everything else</h3>
|
<h3>everything else</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<!-- t: for static -->
|
<!-- t: end -->
|
||||||
<li>
|
<li>
|
||||||
<!-- t: if info -->
|
<!-- t: if info -->
|
||||||
<a href="/info/<!-- t: raw info -->">
|
<a href="/info/<!-- t: raw info -->">
|
||||||
@@ -136,8 +150,7 @@ span {
|
|||||||
<!-- t: set linebreak -->
|
<!-- t: set linebreak -->
|
||||||
<!-- t: for line additional -->
|
<!-- t: for line additional -->
|
||||||
<!-- t: raw linebreak -->
|
<!-- t: raw linebreak -->
|
||||||
<!-- t: set linebreak <br>
|
<!-- t: set linebreak <br> -->
|
||||||
-->
|
|
||||||
<!-- t: safe line -->
|
<!-- t: safe line -->
|
||||||
<!-- t: end -->
|
<!-- t: end -->
|
||||||
</div>
|
</div>
|
||||||
@@ -149,6 +162,7 @@ span {
|
|||||||
<!-- t: end -->
|
<!-- t: end -->
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<!-- t: end -->
|
||||||
<!-- t: end -->
|
<!-- t: end -->
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ impl Data {
|
|||||||
status_updated: Mutex::new((Instant::now(), false)),
|
status_updated: Mutex::new((Instant::now(), false)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn status_sync(&self, dbg: bool) -> MutexGuard<Status> {
|
pub fn status_sync(&'_ self, dbg: bool) -> MutexGuard<'_, Status> {
|
||||||
let mut updated = self.status_updated.blocking_lock();
|
let mut updated = self.status_updated.blocking_lock();
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
if (now - updated.0).as_secs_f32() > 3.0 || (dbg && !updated.1) {
|
if (now - updated.0).as_secs_f32() > 3.0 || (dbg && !updated.1) {
|
||||||
@@ -47,7 +47,7 @@ impl Data {
|
|||||||
self.status.blocking_lock()
|
self.status.blocking_lock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn status_async(&self, dbg: bool) -> MutexGuard<Status> {
|
pub async fn status_async(&'_ self, dbg: bool) -> MutexGuard<'_, Status> {
|
||||||
let mut updated = self.status_updated.lock().await;
|
let mut updated = self.status_updated.lock().await;
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
if (now - updated.0).as_secs_f32() > 3.0 || (dbg && !updated.1) {
|
if (now - updated.0).as_secs_f32() > 3.0 || (dbg && !updated.1) {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ async fn index_dbg(data: &State<Data>) -> RawHtml<String> {
|
|||||||
|
|
||||||
async fn index_gen(data: &State<Data>, dbg: bool) -> RawHtml<String> {
|
async fn index_gen(data: &State<Data>, dbg: bool) -> RawHtml<String> {
|
||||||
let status = data.status_async(dbg).await;
|
let status = data.status_async(dbg).await;
|
||||||
return RawHtml(data.index.gen(&status, dbg, data.globals.clone()));
|
RawHtml(data.index.gen(&status, dbg, data.globals.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/int")]
|
#[get("/int")]
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ use std::{collections::BTreeMap, os::unix::fs::PermissionsExt, path::Path, time:
|
|||||||
|
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
|
|
||||||
const SLASHINFO: &'static str = "/srv/tomatenmhark-slashinfo/";
|
const SLASHINFO: &str = "/srv/tomatenmhark-slashinfo/";
|
||||||
const REDIRECT: &'static str = "/srv/tomatenmhark-redirect/";
|
const REDIRECT: &str = "/srv/tomatenmhark-redirect/";
|
||||||
|
|
||||||
pub struct Status(
|
pub struct Status(
|
||||||
pub BTreeMap<String, (bool, bool, String, Option<String>, Option<Duration>)>,
|
pub BTreeMap<String, (bool, bool, String, Option<String>, Option<Duration>)>,
|
||||||
@@ -40,16 +40,15 @@ impl Status {
|
|||||||
);
|
);
|
||||||
let mut rest = BTreeMap::new();
|
let mut rest = BTreeMap::new();
|
||||||
if let Ok(rd) = std::fs::read_dir(SLASHINFO) {
|
if let Ok(rd) = std::fs::read_dir(SLASHINFO) {
|
||||||
for f in rd {
|
for f in rd.filter_map(Result::ok) {
|
||||||
if let Ok(f) = f {
|
|
||||||
if let Some(id) = f.file_name().to_str() {
|
if let Some(id) = f.file_name().to_str() {
|
||||||
if !map.contains_key(id) {
|
if !map.contains_key(id) {
|
||||||
let mut p = f.path();
|
let mut p = f.path();
|
||||||
p.push("desc");
|
p.push("desc");
|
||||||
if let Ok(desc) = std::fs::read_to_string(&p) {
|
if let Ok(desc) = std::fs::read_to_string(&p) {
|
||||||
let info = Path::new(SLASHINFO).join(id).join("index.html");
|
let info = Path::new(SLASHINFO).join(id).join("index.html");
|
||||||
let info = info.starts_with(SLASHINFO)
|
let info =
|
||||||
&& info.try_exists().ok() == Some(true);
|
info.starts_with(SLASHINFO) && info.try_exists().ok() == Some(true);
|
||||||
let redirect = Path::new(REDIRECT).join(id);
|
let redirect = Path::new(REDIRECT).join(id);
|
||||||
let redirect = redirect.starts_with(REDIRECT)
|
let redirect = redirect.starts_with(REDIRECT)
|
||||||
&& redirect.try_exists().ok() == Some(true);
|
&& redirect.try_exists().ok() == Some(true);
|
||||||
@@ -65,11 +64,7 @@ impl Status {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
rest.insert(
|
rest.insert(id.to_owned(), (info, redirect, desc.to_owned(), None));
|
||||||
id.to_owned(),
|
|
||||||
(info, redirect, desc.to_owned(), None),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,20 +138,21 @@ impl Status {
|
|||||||
|
|
||||||
fn query_status_sync(mut func: impl FnMut(&str, bool, bool, &str, Option<Duration>), dbg: bool) {
|
fn query_status_sync(mut func: impl FnMut(&str, bool, bool, &str, Option<Duration>), dbg: bool) {
|
||||||
if let Ok(rd) = std::fs::read_dir("/tmp/") {
|
if let Ok(rd) = std::fs::read_dir("/tmp/") {
|
||||||
for f in rd {
|
for f in rd.filter_map(Result::ok) {
|
||||||
if let Ok(f) = f {
|
|
||||||
if let Some(name) = f.file_name().to_str() {
|
if let Some(name) = f.file_name().to_str() {
|
||||||
if name.starts_with("tomatenmhark-status-") {
|
if let Some(id) = name
|
||||||
let id = name["tomatenmhark-status-".len()..].trim();
|
.strip_prefix("tomatenmhark-status-")
|
||||||
if !id.is_empty() {
|
.map(|v| v.trim())
|
||||||
|
.filter(|v| !v.is_empty())
|
||||||
|
{
|
||||||
if let Ok(status) = std::fs::read_to_string(f.path())
|
if let Ok(status) = std::fs::read_to_string(f.path())
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|v| v.trim_end())
|
.map(|v| v.trim_end())
|
||||||
{
|
{
|
||||||
if !status.is_empty() {
|
if !status.is_empty() {
|
||||||
let info = Path::new(SLASHINFO).join(id).join("index.html");
|
let info = Path::new(SLASHINFO).join(id).join("index.html");
|
||||||
let info = info.starts_with(SLASHINFO)
|
let info =
|
||||||
&& info.try_exists().ok() == Some(true);
|
info.starts_with(SLASHINFO) && info.try_exists().ok() == Some(true);
|
||||||
let redirect = Path::new(REDIRECT).join(id);
|
let redirect = Path::new(REDIRECT).join(id);
|
||||||
let redirect = redirect.starts_with(REDIRECT)
|
let redirect = redirect.starts_with(REDIRECT)
|
||||||
&& redirect.try_exists().ok() == Some(true);
|
&& redirect.try_exists().ok() == Some(true);
|
||||||
@@ -167,11 +163,8 @@ fn query_status_sync(mut func: impl FnMut(&str, bool, bool, &str, Option<Duratio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Ok(rd) = std::fs::read_dir("/srv/tomatenmhark-dystatus/") {
|
if let Ok(rd) = std::fs::read_dir("/srv/tomatenmhark-dystatus/") {
|
||||||
for f in rd {
|
for f in rd.filter_map(Result::ok) {
|
||||||
if let Ok(f) = f {
|
|
||||||
if let Some(name) = f.file_name().to_str() {
|
if let Some(name) = f.file_name().to_str() {
|
||||||
if f.metadata()
|
if f.metadata()
|
||||||
.is_ok_and(|meta| meta.is_file() && meta.permissions().mode() & 1 == 1)
|
.is_ok_and(|meta| meta.is_file() && meta.permissions().mode() & 1 == 1)
|
||||||
@@ -198,7 +191,6 @@ fn query_status_sync(mut func: impl FnMut(&str, bool, bool, &str, Option<Duratio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async fn query_status_async(
|
async fn query_status_async(
|
||||||
mut func: impl FnMut(&str, bool, bool, &str, Option<Duration>),
|
mut func: impl FnMut(&str, bool, bool, &str, Option<Duration>),
|
||||||
@@ -207,9 +199,11 @@ async fn query_status_async(
|
|||||||
if let Ok(mut rd) = tokio::fs::read_dir("/tmp/").await {
|
if let Ok(mut rd) = tokio::fs::read_dir("/tmp/").await {
|
||||||
while let Ok(Some(f)) = rd.next_entry().await {
|
while let Ok(Some(f)) = rd.next_entry().await {
|
||||||
if let Some(name) = f.file_name().to_str() {
|
if let Some(name) = f.file_name().to_str() {
|
||||||
if name.starts_with("tomatenmhark-status-") {
|
if let Some(id) = name
|
||||||
let id = name["tomatenmhark-status-".len()..].trim();
|
.strip_prefix("tomatenmhark-status-")
|
||||||
if !id.is_empty() {
|
.map(|v| v.trim())
|
||||||
|
.filter(|v| !v.is_empty())
|
||||||
|
{
|
||||||
if let Ok(status) = tokio::fs::read_to_string(f.path())
|
if let Ok(status) = tokio::fs::read_to_string(f.path())
|
||||||
.await
|
.await
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -229,7 +223,6 @@ async fn query_status_async(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let Ok(mut rd) = tokio::fs::read_dir("/srv/tomatenmhark-dystatus/").await {
|
if let Ok(mut rd) = tokio::fs::read_dir("/srv/tomatenmhark-dystatus/").await {
|
||||||
while let Ok(Some(f)) = rd.next_entry().await {
|
while let Ok(Some(f)) = rd.next_entry().await {
|
||||||
if let Some(name) = f.file_name().to_str() {
|
if let Some(name) = f.file_name().to_str() {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ pub enum TemplateType {
|
|||||||
Set(usize, String),
|
Set(usize, String),
|
||||||
Concat(usize, usize),
|
Concat(usize, usize),
|
||||||
If(usize, Templates, Option<Templates>),
|
If(usize, Templates, Option<Templates>),
|
||||||
|
IfEq(usize, usize, Templates, Option<Templates>),
|
||||||
|
IfLine(usize, usize, Templates, Option<Templates>),
|
||||||
For(Vec<TemplateLoop>, Templates),
|
For(Vec<TemplateLoop>, Templates),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,8 +96,8 @@ pub struct TemplateInfo {
|
|||||||
last_end_was_else: Option<bool>,
|
last_end_was_else: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const COMMENT_START: &'static str = "<!-- t: ";
|
const COMMENT_START: &str = "<!-- t: ";
|
||||||
const COMMENT_END: &'static str = "-->";
|
const COMMENT_END: &str = " -->";
|
||||||
impl Template {
|
impl Template {
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
mut src: &str,
|
mut src: &str,
|
||||||
@@ -137,13 +139,14 @@ impl Templates {
|
|||||||
|
|
||||||
if let Some(comment_end) = src.find(COMMENT_END) {
|
if let Some(comment_end) = src.find(COMMENT_END) {
|
||||||
// extract comment content
|
// extract comment content
|
||||||
let comment_og = src[..comment_end].trim();
|
let comment_og = src[..comment_end].trim_start();
|
||||||
*src = &src[comment_end + COMMENT_END.len()..].trim_start_matches('\r');
|
*src = src[comment_end + COMMENT_END.len()..].trim_start_matches('\r');
|
||||||
*src = src.strip_prefix('\n').unwrap_or(src);
|
*src = src.strip_prefix('\n').unwrap_or(src);
|
||||||
// do template things
|
// do template things
|
||||||
let comment = comment_og.to_lowercase();
|
let comment = comment_og.to_lowercase();
|
||||||
let mut comment = comment.split(char::is_whitespace);
|
let mut comment = comment.split(char::is_whitespace);
|
||||||
match comment.next().unwrap_or("") {
|
let comment_match = comment.next().unwrap_or("");
|
||||||
|
match comment_match {
|
||||||
"//" | "#" => {}
|
"//" | "#" => {}
|
||||||
"end" => {
|
"end" => {
|
||||||
break 'parsing;
|
break 'parsing;
|
||||||
@@ -170,7 +173,8 @@ impl Templates {
|
|||||||
let var_name = comment
|
let var_name = comment
|
||||||
.next()
|
.next()
|
||||||
.ok_or(TemplateParseError::MissingVariable("set"))?;
|
.ok_or(TemplateParseError::MissingVariable("set"))?;
|
||||||
let value = comment_og[3..].trim_start()[var_name.len()..].trim_start();
|
let value = &comment_og[3..].trim_start()[var_name.len()..];
|
||||||
|
let value = value.strip_prefix(char::is_whitespace).unwrap_or(value);
|
||||||
out.push(TemplateType::Set(info.var(var_name), value.to_owned()));
|
out.push(TemplateType::Set(info.var(var_name), value.to_owned()));
|
||||||
}
|
}
|
||||||
"concat" => {
|
"concat" => {
|
||||||
@@ -187,22 +191,55 @@ impl Templates {
|
|||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
"if" => {
|
"if" | "ifeq" | "ifline" => {
|
||||||
let prev_lewe = info.last_end_was_else;
|
let prev_lewe = info.last_end_was_else;
|
||||||
info.last_end_was_else = Some(false);
|
info.last_end_was_else = Some(false);
|
||||||
out.push(TemplateType::If(
|
let (t_if, t_else) = (
|
||||||
info.var(
|
|
||||||
comment
|
|
||||||
.next()
|
|
||||||
.ok_or(TemplateParseError::MissingVariable("if"))?,
|
|
||||||
),
|
|
||||||
Templates::parse(src, info)?,
|
Templates::parse(src, info)?,
|
||||||
if info.last_end_was_else.is_some_and(|v| v) {
|
if info.last_end_was_else.is_some_and(|v| v) {
|
||||||
Some(Templates::parse(src, info)?)
|
Some(Templates::parse(src, info)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
));
|
);
|
||||||
|
out.push(match comment_match {
|
||||||
|
"if" => TemplateType::If(
|
||||||
|
info.var(
|
||||||
|
comment
|
||||||
|
.next()
|
||||||
|
.ok_or(TemplateParseError::MissingVariable("if"))?,
|
||||||
|
),
|
||||||
|
t_if,
|
||||||
|
t_else,
|
||||||
|
),
|
||||||
|
"ifeq" => TemplateType::IfEq(
|
||||||
|
info.var(
|
||||||
|
comment
|
||||||
|
.next()
|
||||||
|
.ok_or(TemplateParseError::MissingVariable("ifeq"))?,
|
||||||
|
),
|
||||||
|
info.var(
|
||||||
|
comment
|
||||||
|
.next()
|
||||||
|
.ok_or(TemplateParseError::MissingVariable("ifeq"))?,
|
||||||
|
),
|
||||||
|
t_if,
|
||||||
|
t_else,
|
||||||
|
),
|
||||||
|
"ifline" => {
|
||||||
|
TemplateType::IfLine(
|
||||||
|
info.var(comment.next().ok_or(
|
||||||
|
TemplateParseError::MissingVariable("ifline"),
|
||||||
|
)?),
|
||||||
|
info.var(comment.next().ok_or(
|
||||||
|
TemplateParseError::MissingVariable("ifline"),
|
||||||
|
)?),
|
||||||
|
t_if,
|
||||||
|
t_else,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
});
|
||||||
info.last_end_was_else = prev_lewe;
|
info.last_end_was_else = prev_lewe;
|
||||||
}
|
}
|
||||||
"for" => {
|
"for" => {
|
||||||
@@ -256,7 +293,7 @@ pub enum TemplateParseError {
|
|||||||
impl Display for TemplateParseError {
|
impl Display for TemplateParseError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::UnclosedComment => write!(f, "There is an unclosed comment. Make sure all `<!-- t: ` comments are closed by a `-->`"),
|
Self::UnclosedComment => write!(f, "There is an unclosed comment. Make sure all `<!-- t: ` comments are closed by a ` -->`"),
|
||||||
Self::InvalidTemplateKeyword(kw) => write!(f, "Invalid keyword `{kw}` after `<!-- t: `"),
|
Self::InvalidTemplateKeyword(kw) => write!(f, "Invalid keyword `{kw}` after `<!-- t: `"),
|
||||||
Self::UnknownForSource(s) => write!(f, "For loop can only be used with one or more of `running`, `static`, or `line varname`, not `{s}`"),
|
Self::UnknownForSource(s) => write!(f, "For loop can only be used with one or more of `running`, `static`, or `line varname`, not `{s}`"),
|
||||||
Self::DidNotReachEOF(s) => write!(f, "Stopped parsing before the end of the file. Remaining, unparsed text: {s}"),
|
Self::DidNotReachEOF(s) => write!(f, "Stopped parsing before the end of the file. Remaining, unparsed text: {s}"),
|
||||||
@@ -296,16 +333,16 @@ impl TemplateType {
|
|||||||
Self::Concat(v, a) => {
|
Self::Concat(v, a) => {
|
||||||
if *v == *a {
|
if *v == *a {
|
||||||
let a = &mut vars[*v];
|
let a = &mut vars[*v];
|
||||||
a.reserve(a.len());
|
let len = a.len();
|
||||||
|
a.reserve(len);
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while let Some(ch) = a[i..].chars().next() {
|
while let Some(ch) = a[i..len].chars().next() {
|
||||||
i += ch.len_utf8();
|
i += ch.len_utf8();
|
||||||
a.push(ch);
|
a.push(ch);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let a_temp = std::mem::replace(&mut vars[*a], String::new());
|
let [a, v] = vars.get_disjoint_mut([*a, *v]).unwrap();
|
||||||
vars[*v].push_str(&a_temp);
|
v.push_str(a);
|
||||||
vars[*a] = a_temp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::If(v, template, else_template) => {
|
Self::If(v, template, else_template) => {
|
||||||
@@ -315,6 +352,20 @@ impl TemplateType {
|
|||||||
else_template.gen(status, debug, vars, out);
|
else_template.gen(status, debug, vars, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Self::IfEq(x, y, template, else_template) => {
|
||||||
|
if vars[*x] == vars[*y] {
|
||||||
|
template.gen(status, debug, vars, out);
|
||||||
|
} else if let Some(else_template) = else_template {
|
||||||
|
else_template.gen(status, debug, vars, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::IfLine(x, y, template, else_template) => {
|
||||||
|
if vars[*y].lines().any(|line| line == vars[*x]) {
|
||||||
|
template.gen(status, debug, vars, out);
|
||||||
|
} else if let Some(else_template) = else_template {
|
||||||
|
else_template.gen(status, debug, vars, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::For(src, template) => {
|
Self::For(src, template) => {
|
||||||
for src in src {
|
for src in src {
|
||||||
match src {
|
match src {
|
||||||
|
|||||||
Reference in New Issue
Block a user