Compare commits
7 Commits
196c392f59
...
27d8a2fd0c
Author | SHA1 | Date |
---|---|---|
Benedikt Peetz | 27d8a2fd0c | |
Benedikt Peetz | c66358261c | |
Benedikt Peetz | c3ba5ad5a5 | |
Benedikt Peetz | 3702788285 | |
Benedikt Peetz | d6cc3422e4 | |
Benedikt Peetz | 43d991871f | |
Benedikt Peetz | 091d77089b |
|
@ -1270,9 +1270,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.0.2"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
|
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.14.2",
|
"hashbrown 0.14.2",
|
||||||
|
@ -2678,7 +2678,7 @@ version = "0.19.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.0.2",
|
"indexmap 2.1.0",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
@ -2729,7 +2729,7 @@ dependencies = [
|
||||||
"cli-log",
|
"cli-log",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"directories",
|
"directories",
|
||||||
"indexmap 2.0.2",
|
"indexmap 2.1.0",
|
||||||
"language_macros",
|
"language_macros",
|
||||||
"matrix-sdk",
|
"matrix-sdk",
|
||||||
"mlua",
|
"mlua",
|
||||||
|
|
|
@ -28,7 +28,7 @@ tui-textarea = { version = "0.2", features = ["crossterm"], optional = true }
|
||||||
crossterm = { version = "0.25", optional = true }
|
crossterm = { version = "0.25", optional = true }
|
||||||
tokio-util = { version = "0.7", optional = true }
|
tokio-util = { version = "0.7", optional = true }
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1.0", optional = true }
|
||||||
indexmap = { version = "2.0.2", optional = true }
|
indexmap = { version = "2.1.0", optional = true }
|
||||||
directories = "5.0.1"
|
directories = "5.0.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -89,11 +89,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1698726852,
|
"lastModified": 1698804896,
|
||||||
"narHash": "sha256-V1S4TTzg++GzPc96i/yy4jib+7/xU0LXHcggm9MllMM=",
|
"narHash": "sha256-vSms7A9bWHC00343qyXuNVm65LZDagDkukpkpwC2VxY=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "ec19bd20af08f3b004089cc12ab54c823ed899b7",
|
"rev": "c5f8326c668b78275eccce90839861a3c8e1d3b2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
overlays = [(import rust-overlay)];
|
overlays = [(import rust-overlay)];
|
||||||
};
|
};
|
||||||
|
|
||||||
nightly = true;
|
nightly = false;
|
||||||
rust =
|
rust =
|
||||||
if nightly
|
if nightly
|
||||||
then
|
then
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
# build
|
||||||
|
/target
|
||||||
|
/result
|
||||||
|
|
||||||
|
# It is a library
|
||||||
|
Cargo.lock
|
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "trinitry"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
pest = "2.7.5"
|
||||||
|
pest_derive = {version = "2.7.5", features = ["grammar-extras"]}
|
||||||
|
|
||||||
|
# The header imports katex, a js latex parser, into the doc comments
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
rustdoc-args = [ "--html-in-header", "./docs-header.html" ]
|
|
@ -0,0 +1,45 @@
|
||||||
|
<!doctype html>
|
||||||
|
<!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css"
|
||||||
|
integrity="sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- The loading of KaTeX is deferred to speed up page rendering -->
|
||||||
|
<script
|
||||||
|
defer
|
||||||
|
src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"
|
||||||
|
integrity="sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
|
||||||
|
<!-- To automatically render math in text elements, include the auto-render extension: -->
|
||||||
|
<script
|
||||||
|
defer
|
||||||
|
src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"
|
||||||
|
integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
renderMathInElement(document.body, {
|
||||||
|
delimiters: [
|
||||||
|
{ left: "$$", right: "$$", display: true },
|
||||||
|
{ left: "\\(", right: "\\)", display: false },
|
||||||
|
{ left: "$", right: "$", display: false },
|
||||||
|
{ left: "\\[", right: "\\]", display: true },
|
||||||
|
]
|
||||||
|
// FIXME(@soispha): This removes the quotes completely <2023-10-31>
|
||||||
|
// macros: {
|
||||||
|
// "”": "\\noexpand ”",
|
||||||
|
// "“": "\\noexpand “",
|
||||||
|
// },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
</html>
|
|
@ -0,0 +1,192 @@
|
||||||
|
//! This crate is a parser for the 'Trinitry' (not 'Trinity') language, used to map all sort of
|
||||||
|
//! Functions to a memorable command.
|
||||||
|
//!
|
||||||
|
//! This parser is more of a validator, as Trinitry does not support any language features besides
|
||||||
|
//! the aforementioned commands and arguments. That includes some simple constructs like: '||' (OR)
|
||||||
|
//! or '&&' (AND). If you need these features, simple write them in the language, you've written your
|
||||||
|
//! Function in.
|
||||||
|
//!
|
||||||
|
//! # General specification
|
||||||
|
//! ## Command
|
||||||
|
//! Basically every command can be a series of alphanumeric ASCII values.
|
||||||
|
//!
|
||||||
|
//! Correctly spoken, the Language, containing all valid command names, is just the Kleene closure
|
||||||
|
//! over an Alphabet $\Sigma$, which contains all alphanumeric characters:
|
||||||
|
//! $$ \Sigma_{cmd} = \\{x | 0 \leqslant x \leqslant 9\\} \cup \\{x | "a" \leqslant x \leqslant "z"\\} \cup \\{x | "A" \leqslant x \leqslant "Z"\\} \cup \\{"\\_", "\text{-}", "."\\} $$
|
||||||
|
//!
|
||||||
|
//! ## Argument
|
||||||
|
//! Arguments are similar to the command, although they can also contain spaces and quotes,
|
||||||
|
//! if it's quoted and additional characters (here notated as "$\\dots{}$"):
|
||||||
|
//! $$ \Sigma_{args-quoted} = \Sigma_{cmd} \cup \\{"\\text{"}", "\\ ", \\dots{}\\} $$
|
||||||
|
//! $$ \Sigma_{args-single-quoted} = \Sigma_{cmd} \cup \\{"'", "\\ ", \\dots{}\\} $$
|
||||||
|
//! $$ \Sigma_{args} = \Sigma_{cmd} \cup \\{\\dots{}\\} $$
|
||||||
|
//! Look at the [trinitry.pest](../../../src/trinitry.pest) file for a full list of the additional
|
||||||
|
//! allowed characters.
|
||||||
|
//!
|
||||||
|
//! # Examples
|
||||||
|
//! ## Command
|
||||||
|
//! A valid command would be something like that:
|
||||||
|
//! ```text
|
||||||
|
//! quit
|
||||||
|
//! ```
|
||||||
|
//! something like that would not be valid however, as Trinitry does not support these 'complex'
|
||||||
|
//! language features:
|
||||||
|
//! ```text
|
||||||
|
//! write && quit
|
||||||
|
//! ```
|
||||||
|
//! ## Arguments
|
||||||
|
//! A valid argumented command would be:
|
||||||
|
//! ```text
|
||||||
|
//! lua "function() print('Hi!') end"
|
||||||
|
//! ```
|
||||||
|
//! Whilst this would not be valid (that is, it would very likely not be what you want):
|
||||||
|
//! ```text
|
||||||
|
//! lua "function() print("Hi!") end"
|
||||||
|
//! ```
|
||||||
|
//! as the double quotes in the print statement actually unquote the argument, leaving you with
|
||||||
|
//! three arguments:
|
||||||
|
//! 1. `function() print(`
|
||||||
|
//! 1. `Hi!`
|
||||||
|
//! 1. `) end`
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use pest::{error::Error, Parser};
|
||||||
|
use pest_derive::Parser;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[grammar = "trinitry.pest"]
|
||||||
|
pub struct Trinitry {
|
||||||
|
command: String,
|
||||||
|
arguments: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trinitry {
|
||||||
|
pub fn new(input: &str) -> Result<Self, Error<Rule>> {
|
||||||
|
let parsed = Self::parse(Rule::trinitry, input)?;
|
||||||
|
|
||||||
|
let command = {
|
||||||
|
let command: Vec<_> = parsed.clone().find_tagged("command").collect();
|
||||||
|
|
||||||
|
// Ensure that we have only one command
|
||||||
|
// This should be ensured by the grammar, thus the 'debug_assert'
|
||||||
|
debug_assert_eq!(command.len(), 1);
|
||||||
|
|
||||||
|
// PERFORMANCE(@soispha): Replace this with `mem::take` (when pairs implements Default)
|
||||||
|
// <2023-11-01>
|
||||||
|
command
|
||||||
|
.first()
|
||||||
|
.expect("This should contain exactly one element")
|
||||||
|
.to_owned()
|
||||||
|
};
|
||||||
|
let arguments: Vec<_> = parsed.clone().find_tagged("argument").collect();
|
||||||
|
|
||||||
|
Ok(Trinitry {
|
||||||
|
command: command.as_str().to_owned(),
|
||||||
|
arguments: arguments
|
||||||
|
.iter()
|
||||||
|
.map(|arg| {
|
||||||
|
let mut arg = arg.as_str().trim();
|
||||||
|
arg = if let Some(new_arg) = arg.strip_prefix("\"") {
|
||||||
|
new_arg
|
||||||
|
} else {
|
||||||
|
arg
|
||||||
|
};
|
||||||
|
arg = if let Some(new_arg) = arg.strip_suffix("\"") {
|
||||||
|
new_arg
|
||||||
|
} else {
|
||||||
|
arg
|
||||||
|
};
|
||||||
|
|
||||||
|
arg = if let Some(new_arg) = arg.strip_prefix("'") {
|
||||||
|
new_arg
|
||||||
|
} else {
|
||||||
|
arg
|
||||||
|
};
|
||||||
|
arg = if let Some(new_arg) = arg.strip_suffix("'") {
|
||||||
|
new_arg
|
||||||
|
} else {
|
||||||
|
arg
|
||||||
|
};
|
||||||
|
arg.to_owned()
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Trinitry {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
if self.arguments.is_empty() {
|
||||||
|
f.write_str(&self.command)
|
||||||
|
} else {
|
||||||
|
f.write_fmt(format_args!(
|
||||||
|
"{} {}",
|
||||||
|
&self.command,
|
||||||
|
&self.arguments.join(" ")
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod tests;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::Trinitry;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_cmd() {
|
||||||
|
let string = "quit";
|
||||||
|
let p = Trinitry::new(string).unwrap_or_else(|e| {
|
||||||
|
panic!("{}", e);
|
||||||
|
});
|
||||||
|
assert_eq!(&p.command, "quit");
|
||||||
|
assert!(&p.arguments.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_arg_clean() {
|
||||||
|
let string = r##"lua print("Hi")"##;
|
||||||
|
let p = Trinitry::new(string).unwrap_or_else(|e| {
|
||||||
|
panic!("{}", e);
|
||||||
|
});
|
||||||
|
assert_eq!(&p.command, "lua");
|
||||||
|
assert_eq!(&p.arguments[0], r#"print("Hi")"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_arg_quote() {
|
||||||
|
let string = r##"write "some 'file' name""##;
|
||||||
|
let p = Trinitry::new(string).unwrap_or_else(|e| {
|
||||||
|
panic!("{}", e);
|
||||||
|
});
|
||||||
|
assert_eq!(&p.command, "write");
|
||||||
|
assert_eq!(&p.arguments[0], "some 'file' name");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_arg_single_quote() {
|
||||||
|
let string = r##"write 'some "file" name'"##;
|
||||||
|
let p = Trinitry::new(string).unwrap_or_else(|e| {
|
||||||
|
panic!("{}", e);
|
||||||
|
});
|
||||||
|
assert_eq!(&p.command, "write");
|
||||||
|
assert_eq!(&p.arguments[0], "some \"file\" name");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_arg_multi() {
|
||||||
|
let string = r##"write 'some "file" name' "other name" last"##;
|
||||||
|
let p = Trinitry::new(string).unwrap_or_else(|e| {
|
||||||
|
panic!("{}", e);
|
||||||
|
});
|
||||||
|
|
||||||
|
let expected_args = vec!["some \"file\" name", "other name", "last"]
|
||||||
|
.iter()
|
||||||
|
.map(|str| (*str).to_owned())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
|
assert_eq!(&p.command, "write");
|
||||||
|
assert_eq!(&p.arguments, &expected_args);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,25 @@
|
||||||
|
chars = { ASCII_ALPHANUMERIC | "_" | "-" | "." }
|
||||||
|
|
||||||
|
// TODO(@soispha): Are these all the valid characters? <2023-11-01>
|
||||||
|
argument_chars = { chars | "(" | ")" | "{" | "}" | "<" | ">" | "?" | "!" | "+" | "^" | "@"
|
||||||
|
| "&" | "*" | "~" | "|" | "=" | "," | "\\" | "/" }
|
||||||
|
whitespace = _{ " " } // lower case to avoid special treatment of 'WHITESPACE'
|
||||||
|
|
||||||
|
quote = _{ "\"" }
|
||||||
|
q = _{ quote }
|
||||||
|
|
||||||
|
single_quote = _{ "'" }
|
||||||
|
sq = _{ single_quote }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
command = { chars+ }
|
||||||
|
|
||||||
|
arg_quoted = { q ~ (!q ~ (argument_chars | " " | "'" ))+ ~ q }
|
||||||
|
arg_single_quoted = { sq ~ (!sq ~ (argument_chars | " " | "\"" ))+ ~ sq }
|
||||||
|
arg = { (argument_chars | "\"" | "'")+ }
|
||||||
|
|
||||||
|
argument = { whitespace+ ~ (arg_quoted | arg_single_quoted | arg )}
|
||||||
|
|
||||||
|
|
||||||
|
trinitry = { SOI ~ #command = command ~ (#argument = argument)* ~ EOI }
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Library {{{
|
||||||
|
mktmp() {
|
||||||
|
ensure_tmp_dir
|
||||||
|
mktemp -p "$LIB_TEMP_DIR_FOR_SCRIPT"
|
||||||
|
}
|
||||||
|
ensure_tmp_dir() {
|
||||||
|
if ! [ -d "$LIB_TEMP_DIR_FOR_SCRIPT" ]; then
|
||||||
|
LIB_TEMP_DIR_FOR_SCRIPT="$(mktemp -d)"
|
||||||
|
export LIB_TEMP_DIR_FOR_SCRIPT
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
remove_tmp_dir() {
|
||||||
|
# The test is here because some scripts still delete this on their own
|
||||||
|
if [ -d "$LIB_TEMP_DIR_FOR_SCRIPT" ]; then
|
||||||
|
rm -r "$LIB_TEMP_DIR_FOR_SCRIPT"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
trap remove_tmp_dir EXIT
|
||||||
|
ensure_tmp_dir # ensure that the variable has been set, even in subshells
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
tmp="$(mktmp)"
|
||||||
|
|
||||||
|
curl https://raw.githubusercontent.com/minimaxir/big-list-of-naughty-strings/master/blns.txt |
|
||||||
|
awk '!/^#/' |
|
||||||
|
awk '!/^[\s\t]*$/' |
|
||||||
|
awk -v s="'" '!/.*s.*/' |
|
||||||
|
|
||||||
|
# This entry contains duplicated spaces, just ignore it
|
||||||
|
awk '!/Power/' |
|
||||||
|
iconv -c -f utf-8 -t ascii \
|
||||||
|
>"$tmp"
|
||||||
|
|
||||||
|
counter=0
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
// DO NOT EDIT
|
||||||
|
// This file is automatically generated by the 'update.sh' file, with data from:
|
||||||
|
// https://raw.githubusercontent.com/minimaxir/big-list-of-naughty-strings/master/blns.txt
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::Trinitry;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
while read -r name; do
|
||||||
|
tmp2="$(mktmp)"
|
||||||
|
printf "%s" "$name" >"$tmp2"
|
||||||
|
if rg '^[A-Za-z0-9_.-]+$' "$tmp2" -q; then
|
||||||
|
cat <<EOF
|
||||||
|
#[test]
|
||||||
|
fn parse_$counter() {
|
||||||
|
let p = Trinitry::new(r##"$name"##).unwrap_or_else(|e| {
|
||||||
|
panic!("{}", e);
|
||||||
|
});
|
||||||
|
assert_eq!(r##"$name"##, &p.to_string());
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
elif rg '^[A-Za-z0-9_.-]+ [A-Za-z0-9_.(){}<>?!+^@&*~|=,/\\ -]*$' "$tmp2" -q; then
|
||||||
|
cat <<EOF
|
||||||
|
#[test]
|
||||||
|
fn parse_$counter() {
|
||||||
|
let p = Trinitry::new(r##"$name"##).unwrap_or_else(|e| {
|
||||||
|
panic!("{}", e);
|
||||||
|
});
|
||||||
|
assert_eq!(r##"$name"##, &p.to_string());
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat <<EOF
|
||||||
|
#[test]
|
||||||
|
fn parse_$counter() {
|
||||||
|
let p = Trinitry::new(r##"$name"##);
|
||||||
|
assert!(p.is_err());
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
counter=$((counter + 1))
|
||||||
|
done <"$tmp"
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# vim: ft=sh
|
19
update.sh
19
update.sh
|
@ -1,13 +1,24 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
|
||||||
cargo update && cargo upgrade
|
cargo update && cargo upgrade
|
||||||
|
|
||||||
cd ./language_macros || (echo "No language_macros directory" && exit 1)
|
cd ./language_macros || (echo "No language_macros directory" && exit 1)
|
||||||
|
|
||||||
cargo update && cargo upgrade
|
cargo update && cargo upgrade
|
||||||
|
|
||||||
cd ..
|
cd ..
|
||||||
git add Cargo.lock Cargo.toml flake.lock ./language_macros/Cargo.toml
|
|
||||||
|
cd ./trinitry || (echo "No trinitry directory" && exit 1)
|
||||||
|
cargo update && cargo upgrade
|
||||||
|
./update.sh > ./src/tests.rs
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
git add \
|
||||||
|
Cargo.lock Cargo.toml \
|
||||||
|
flake.lock \
|
||||||
|
./language_macros/Cargo.toml \
|
||||||
|
./trinitry/Cargo.toml \
|
||||||
|
./trinitry/src/tests.rs
|
||||||
|
|
||||||
# vim: ft=sh
|
# vim: ft=sh
|
||||||
|
|
Reference in New Issue