104 Commits

Author SHA1 Message Date
Tom Alexander
068864ea87 Publish version 0.1.14.
All checks were successful
clippy Build clippy has succeeded
rustfmt Build rustfmt has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2024-01-03 23:59:51 -05:00
Tom Alexander
03a3ddbd63 Merge branch 'wasm'
All checks were successful
clippy Build clippy has succeeded
rustfmt Build rustfmt has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2024-01-03 23:56:35 -05:00
Tom Alexander
122adee23b Hide the wasm module.
All checks were successful
clippy Build clippy has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2024-01-03 23:38:04 -05:00
Tom Alexander
556afecbb8 Hide the util module. 2024-01-03 23:04:47 -05:00
Tom Alexander
e4407cbdd1 Hide the event_count module.
All checks were successful
clippy Build clippy has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
By placing the code for the parse executable inside a module inside the organic library, we only need to expose the entrypoint publicly rather than all functions it calls. This hides the event_count module, but I will be expanding the practice to the rest of the code base shortly. This is important for not inadvertently promising stability w.r.t. semver for essentially internal functions for development tools.

It was the parse binary, not compare.
2024-01-03 21:17:44 -05:00
Tom Alexander
f57d60dab0 Add a doc target to the Makefile. 2024-01-03 19:55:22 -05:00
Tom Alexander
0aa3939a75 Format. 2024-01-01 18:34:10 -05:00
Tom Alexander
52cb81e75e Cleanup.
All checks were successful
clippy Build clippy has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2023-12-31 12:02:02 -05:00
Tom Alexander
945121202d Remove wasm_test's dependency on compare module.
All checks were successful
clippy Build clippy has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2023-12-31 11:11:25 -05:00
Tom Alexander
f4e0dddd9d Fix clippy.
All checks were successful
clippy Build clippy has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2023-12-30 23:14:40 -05:00
Tom Alexander
6b62176fd0 Run cargo fix.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2023-12-30 22:22:32 -05:00
Tom Alexander
44483b4d54 Break util up into modules. 2023-12-30 22:19:16 -05:00
Tom Alexander
48d3de77fe Move elisp fact to util. 2023-12-30 21:37:25 -05:00
Tom Alexander
680b176501 Fix src block value.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has succeeded
2023-12-30 21:30:08 -05:00
Tom Alexander
dc0338e978 Handle nil in object tree. 2023-12-30 21:28:25 -05:00
Tom Alexander
ff3e0a50af Implement dynamic block.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has failed
2023-12-30 20:56:35 -05:00
Tom Alexander
03c8c07fe0 Implement quote block. 2023-12-30 20:53:20 -05:00
Tom Alexander
3a6fc5b669 Support noop on all token types. 2023-12-30 20:50:28 -05:00
Tom Alexander
d258cdb839 Support null vs noop comparison. 2023-12-30 20:47:17 -05:00
Tom Alexander
aa5629354e Implement special block. 2023-12-30 20:43:01 -05:00
Tom Alexander
efc4a04829 Implement center block. 2023-12-30 20:38:08 -05:00
Tom Alexander
dd611ea64a Fix plain list item. 2023-12-30 20:35:27 -05:00
Tom Alexander
4bd5f3bec7 Implement node property. 2023-12-30 19:01:07 -05:00
Tom Alexander
c2b3509b6a Implement property drawer. 2023-12-30 18:59:52 -05:00
Tom Alexander
7f3f5fb889 Implement table cell.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has failed
2023-12-30 18:52:52 -05:00
Tom Alexander
e0fbf17226 Implement table row. 2023-12-30 18:52:51 -05:00
Tom Alexander
4e18cbafba Implement table. 2023-12-30 18:52:51 -05:00
Tom Alexander
46c36d7f3e Implement babel call. 2023-12-30 18:15:58 -05:00
Tom Alexander
c46a935cfc Implement clock.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has failed
2023-12-30 18:12:09 -05:00
Tom Alexander
f50415cb32 Implement drawer. 2023-12-30 18:05:46 -05:00
Tom Alexander
4f1a151e97 Implement diary sexp. 2023-12-30 18:03:57 -05:00
Tom Alexander
c8e3fdba51 Implement horizontal rule. 2023-12-30 18:02:38 -05:00
Tom Alexander
4b3fc20c62 Fix order of reading optional pair values from elisp. 2023-12-30 18:00:26 -05:00
Tom Alexander
3131f8ac64 Implement example block and export block. 2023-12-30 17:55:56 -05:00
Tom Alexander
60a4835590 Implement comment block. 2023-12-30 17:44:32 -05:00
Tom Alexander
172d72aa46 Implement src block.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has failed
2023-12-30 17:40:15 -05:00
Tom Alexander
b4fcc6500b Implement verse block. 2023-12-30 16:47:24 -05:00
Tom Alexander
ddb6f31562 Implement angle link. 2023-12-30 16:41:55 -05:00
Tom Alexander
dc080b30fc Implement citation reference. 2023-12-30 16:35:01 -05:00
Tom Alexander
9901e17437 Implement citation. 2023-12-30 16:33:02 -05:00
Tom Alexander
ea000894f0 Implement entity. 2023-12-30 16:24:51 -05:00
Tom Alexander
e7742b529a Implement export snippet.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has failed
2023-12-30 16:18:08 -05:00
Tom Alexander
8eba0c4923 Implement footnote definition. 2023-12-30 16:13:54 -05:00
Tom Alexander
e0c0070a13 Implement footnote reference. 2023-12-30 16:05:41 -05:00
Tom Alexander
65ce116998 Implement inline babel call. 2023-12-30 15:52:48 -05:00
Tom Alexander
e348e7d4e3 Implement inline source block. 2023-12-30 13:13:35 -05:00
Tom Alexander
492090470c Implement latex environment. 2023-12-30 13:07:16 -05:00
Tom Alexander
3ec900c8df Implement latex fragment.
Some checks failed
clippy Build clippy has failed
rust-build Build rust-build has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-test Build rust-test has failed
2023-12-30 13:00:07 -05:00
Tom Alexander
d0a008ed22 Implement org macro. 2023-12-30 13:00:07 -05:00
Tom Alexander
f2292f1c07 Implement target. 2023-12-30 12:22:23 -05:00
Tom Alexander
44392cfcca Implement radio target. 2023-12-30 12:17:04 -05:00
Tom Alexander
110630d230 Implement radio link and regular link. 2023-12-30 12:14:03 -05:00
Tom Alexander
ebe12d96c1 Implement subscript and superscript.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has failed
2023-12-29 23:46:47 -05:00
Tom Alexander
24c8ac8e21 Implement all the text markup.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has failed
2023-12-29 23:41:15 -05:00
Tom Alexander
259ad6e242 Implement line break. 2023-12-29 23:27:37 -05:00
Tom Alexander
dd1f7c7777 Support a no-op for headline pre-blank.
Some checks failed
clippy Build clippy has failed
rust-build Build rust-build has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-test Build rust-test has failed
2023-12-29 23:21:30 -05:00
Tom Alexander
c1b471208d Implement plain list item.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has failed
2023-12-29 23:06:45 -05:00
Tom Alexander
606bab9e6d Fix handling of optval. 2023-12-29 22:58:32 -05:00
Tom Alexander
0edf5620a2 Implement plain list. 2023-12-29 22:04:34 -05:00
Tom Alexander
cdf87641c5 Implement comment. 2023-12-29 21:59:45 -05:00
Tom Alexander
eb2995dd3b Support list with empty string as only element for empty list. 2023-12-29 21:56:31 -05:00
Tom Alexander
cd6a64c015 Implement keyword. 2023-12-29 21:36:52 -05:00
Tom Alexander
a4a83d047d Fix node name getting chopped off.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has failed
rust-test Build rust-test has failed
2023-12-29 21:33:17 -05:00
Tom Alexander
a4414369ce Remove unnecessary additional properties in the already-implemented types. 2023-12-29 21:04:31 -05:00
Tom Alexander
83e4b72307 Implement timestamp. 2023-12-29 20:55:01 -05:00
Tom Alexander
34b3e4fa7b Implement statistics cookie. 2023-12-29 20:26:12 -05:00
Tom Alexander
c0e879dc1e Implement headline. 2023-12-29 20:26:11 -05:00
Tom Alexander
fa31b001f4 Implement fixed width area. 2023-12-29 19:21:35 -05:00
Tom Alexander
0897061ff6 Add wasm tests to the CI. 2023-12-29 19:07:07 -05:00
Tom Alexander
28a3e1bc7b Implement bold. 2023-12-29 18:56:29 -05:00
Tom Alexander
3fd3d20722 Merge branch 'test_wasm_json' into wasm
Some checks failed
clippy Build clippy has failed
rust-build Build rust-build has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-test Build rust-test has succeeded
2023-12-29 18:54:58 -05:00
Tom Alexander
90735586b5 Add special case for object trees. 2023-12-29 18:54:41 -05:00
Tom Alexander
78befc7665 Remove old code. 2023-12-29 17:31:14 -05:00
Tom Alexander
ef549d3b19 Compare quoted strings. 2023-12-29 17:29:13 -05:00
Tom Alexander
777c756a7f Compare plain text AST nodes. 2023-12-29 17:24:38 -05:00
Tom Alexander
037caf369c Standardize parameter order. 2023-12-29 16:56:02 -05:00
Tom Alexander
54085b5833 Implement compare optional pair. 2023-12-29 16:51:52 -05:00
Tom Alexander
2bfa8e59e7 Add code to compare children. 2023-12-29 16:06:07 -05:00
Tom Alexander
5d31db39a4 Remove some underscores from wasm schema to match elisp. 2023-12-29 15:41:41 -05:00
Tom Alexander
adcd0de7e4 Compare standard properties. 2023-12-29 15:38:18 -05:00
Tom Alexander
c2f9789a64 Placeholder for comparing quoted strings. 2023-12-29 15:09:54 -05:00
Tom Alexander
579cbb5d11 Switch everything over to the new to_wasm macro. 2023-12-29 15:03:36 -05:00
Tom Alexander
cad2be43bf Implement a new to_wasm macro that uses the WasmAstNodeWrapper. 2023-12-29 14:06:10 -05:00
Tom Alexander
a0a4f0eb90 Remove lifetimes from wasm ast nodes. 2023-12-29 12:49:43 -05:00
Tom Alexander
9f4f8e79ce Implement a wrapper type for AST nodes.
This is to make it impossible to have a collision for attribute names that are real attributes vs attributes I've added for structure (like children and ast_node).
2023-12-29 11:58:46 -05:00
Tom Alexander
77e0dbb42e Start working on a version of compare based on json values.
This will be a better test because it will be testing that what we export to json is equivalent to the elisp AST generated from emacs. Because of these tests, we could also confidently use the wasm structure to elisp.
2023-12-29 11:37:30 -05:00
Tom Alexander
eff5cdbf40 Flatten some structures.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2023-12-29 10:04:59 -05:00
Tom Alexander
eef3571299 Add compare logic for optional pair.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2023-12-27 21:23:06 -05:00
Tom Alexander
f227d8405e Implement compare for list of quoted strings.
Some checks failed
clippy Build clippy has failed
rust-build Build rust-build has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-test Build rust-test has succeeded
2023-12-27 21:00:12 -05:00
Tom Alexander
9520e5814b Add conversion for affiliated keywords to wasm additional properties. 2023-12-27 20:36:35 -05:00
Tom Alexander
28ad4fd046 Add conversion to WasmAstNode for wasm Objects. 2023-12-27 19:53:07 -05:00
Tom Alexander
7626a69fa1 Add default implementations for WasmElispCompare. 2023-12-27 19:42:45 -05:00
Tom Alexander
121c0ce516 Move the logic functions into their own module. 2023-12-27 19:22:43 -05:00
Tom Alexander
5a64db98fe Move wasm diff structs to their own module. 2023-12-27 19:15:39 -05:00
Tom Alexander
abfae9c6c0 Compare section.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-12-27 19:10:43 -05:00
Tom Alexander
5272e2f1b4 Start adding paragraph. 2023-12-27 18:47:59 -05:00
Tom Alexander
90d4b11922 Switch to a formatted print of the wasm compare status.
Some checks failed
clippy Build clippy has failed
rust-build Build rust-build has succeeded
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-test Build rust-test has succeeded
2023-12-27 18:39:10 -05:00
Tom Alexander
d552ef6569 Compare the additional properties. 2023-12-27 18:20:23 -05:00
Tom Alexander
f050e9b6a8 Taking into account additional property names but not comparing their values. 2023-12-27 18:01:56 -05:00
Tom Alexander
a5e108bc37 Compare the standard properties.
Some checks failed
clippy Build clippy has failed
rust-foreign-document-test Build rust-foreign-document-test has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2023-12-27 17:07:42 -05:00
Tom Alexander
58290515b5 Enable child checking. 2023-12-27 16:47:02 -05:00
Tom Alexander
423f65046e Record the property comparisons. 2023-12-27 16:40:55 -05:00
Tom Alexander
badeaf8246 Add compare for document category. 2023-12-27 16:34:04 -05:00
Tom Alexander
d38100581c Add a script to run the wasm test inside docker. 2023-12-27 16:32:06 -05:00
99 changed files with 3906 additions and 1751 deletions

View File

@@ -115,7 +115,7 @@ spec:
[
--no-default-features,
--features,
compare,
"compare,wasm_test",
--no-fail-fast,
--lib,
--test,

View File

@@ -127,7 +127,7 @@ spec:
- name: command
value: ["cargo", "fix"]
- name: args
value: ["--allow-dirty"]
value: ["--all-targets", "--all-features", "--allow-dirty"]
- name: docker-image
value: "$(params.image-name):$(tasks.fetch-repository.results.commit)"
- name: commit-changes

View File

@@ -2,7 +2,7 @@
[package]
name = "organic"
version = "0.1.13"
version = "0.1.14"
authors = ["Tom Alexander <tom@fizz.buzz>"]
description = "An org-mode parser."
edition = "2021"
@@ -45,6 +45,7 @@ path = "src/lib.rs"
required-features = ["wasm"]
[[bin]]
# This bin exists for development purposes only. The real target of this crate is the library.
name = "wasm_test"
path = "src/bin_wasm_test.rs"
required-features = ["wasm_test"]

View File

@@ -34,10 +34,6 @@ wasm:
> cargo build --target=wasm32-unknown-unknown --profile wasm --bin wasm --features wasm
> wasm-bindgen --target web --out-dir target/wasm32-unknown-unknown/js target/wasm32-unknown-unknown/wasm/wasm.wasm
.PHONY: run_wasm
run_wasm:
> cat /tmp/test.org | cargo run --profile wasm --bin wasm_test --features wasm_test
.PHONY: clean
clean:
> cargo clean
@@ -58,11 +54,20 @@ clippy:
test:
> cargo test --no-default-features --features compare --no-fail-fast --lib --test test_loader -- --test-threads $(TESTJOBS)
.PHONY: doc
doc:
> cargo doc --no-deps --open --lib --release --all-features
.PHONY: dockertest
dockertest:
> $(MAKE) -C docker/organic_test
> docker run --init --rm -i -t --read-only -v "$$(readlink -f ./):/source:ro" --mount type=tmpfs,destination=/tmp --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target -w /source organic-test --no-default-features --features compare --no-fail-fast --lib --test test_loader -- --test-threads $(TESTJOBS)
.PHONY: dockerwasmtest
dockerwasmtest:
> $(MAKE) -C docker/organic_test
> docker run --init --rm -i -t --read-only -v "$$(readlink -f ./):/source:ro" --mount type=tmpfs,destination=/tmp --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target -w /source organic-test --no-default-features --features compare,wasm_test --no-fail-fast --lib --test test_loader autogen_wasm_ -- --test-threads $(TESTJOBS)
.PHONY: buildtest
buildtest:
> cargo build --no-default-features
@@ -71,6 +76,8 @@ buildtest:
> cargo build --no-default-features --features compare,tracing
> cargo build --no-default-features --features compare,foreign_document_test
> cargo build --no-default-features --features compare,tracing,foreign_document_test
> cargo build --target wasm32-unknown-unknown --profile wasm --bin wasm --no-default-features --features wasm
> cargo build --bin wasm_test --no-default-features --features wasm_test
.PHONY: foreign_document_test
foreign_document_test:

View File

@@ -30,7 +30,7 @@ endif
# NOTE: This target will write to folders underneath the git-root
.PHONY: run
run: build
docker run --rm --init --read-only --mount type=tmpfs,destination=/tmp -v "$$(readlink -f ../../):/source:ro" --workdir=/source --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target $(IMAGE_NAME)
docker run --rm --init -t --read-only --mount type=tmpfs,destination=/tmp -v "$$(readlink -f ../../):/source:ro" --workdir=/source --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target $(IMAGE_NAME)
.PHONY: shell
shell: build

View File

@@ -0,0 +1,111 @@
#!/usr/bin/env bash
#
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
: ${SHELL:="NO"} # or YES to launch a shell instead of running the test
: ${TRACE:="NO"} # or YES to send traces to jaeger
: ${BACKTRACE:="NO"} # or YES to print a rust backtrace when panicking
: ${NO_COLOR:=""} # Set to anything to disable color output
: ${PROFILE:="debug"}
REALPATH=$(command -v uu-realpath || command -v realpath)
MAKE=$(command -v gmake || command -v make)
############## Setup #########################
function die {
local status_code="$1"
shift
(>&2 echo "${@}")
exit "$status_code"
}
function log {
(>&2 echo "${@}")
}
############## Program #########################
function main {
build_container
launch_container "${@}"
}
function build_container {
$MAKE -C "$DIR/../docker/organic_test"
}
function launch_container {
local additional_flags=()
local features=(wasm_test)
if [ "$NO_COLOR" != "" ]; then
additional_flags+=(--env "NO_COLOR=$NO_COLOR")
fi
if [ "$TRACE" = "YES" ]; then
# We use the host network so it can talk to jaeger hosted at 127.0.0.1
additional_flags+=(--network=host --env RUST_LOG=debug)
features+=(tracing)
fi
if [ "$SHELL" != "YES" ]; then
additional_flags+=(--read-only)
else
additional_flags+=(-t)
fi
if [ "$BACKTRACE" = "YES" ]; then
additional_flags+=(--env RUST_BACKTRACE=full)
fi
if [ "$SHELL" = "YES" ]; then
exec docker run "${additional_flags[@]}" --init --rm -i --mount type=tmpfs,destination=/tmp -v "/:/input:ro" -v "$($REALPATH "$DIR/../"):/source:ro" --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target -w /source --entrypoint "" organic-test /bin/sh
fi
local features_joined
features_joined=$(IFS=","; echo "${features[*]}")
local build_flags=()
if [ "$PROFILE" = "dev" ] || [ "$PROFILE" = "debug" ]; then
PROFILE="debug"
else
build_flags+=(--profile "$PROFILE")
fi
if [ $# -gt 0 ]; then
# If we passed in args, we need to forward them along
for path in "${@}"; do
local full_path
full_path=$($REALPATH "$path")
init_script=$(cat <<EOF
set -euo pipefail
IFS=\$'\n\t'
cargo build --bin wasm_test --no-default-features --features "$features_joined" ${build_flags[@]}
exec /target/${PROFILE}/wasm_test "/input${full_path}"
EOF
)
docker run "${additional_flags[@]}" --init --rm -i --mount type=tmpfs,destination=/tmp -v "/:/input:ro" -v "$($REALPATH "$DIR/../"):/source:ro" --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target -w /source --entrypoint "" organic-test sh -c "$init_script"
done
else
local current_directory init_script
current_directory=$(pwd)
init_script=$(cat <<EOF
set -euo pipefail
IFS=\$'\n\t'
cargo build --bin wasm_test --no-default-features --features "$features_joined" ${build_flags[@]}
cd /input${current_directory}
exec /target/${PROFILE}/wasm_test
EOF
)
docker run "${additional_flags[@]}" --init --rm -i --mount type=tmpfs,destination=/tmp -v "/:/input:ro" -v "$($REALPATH "$DIR/../"):/source:ro" --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target -w /source --entrypoint "" organic-test sh -c "$init_script"
fi
}
main "${@}"

View File

@@ -1,28 +1,8 @@
use organic::parser::parse_with_settings;
use organic::settings::GlobalSettings;
use organic::wasm::ParseResult;
use organic::wasm::ToWasm;
use organic::wasm::ToWasmContext;
use wasm_bindgen::prelude::wasm_bindgen;
#[wasm_bindgen]
pub fn parse_org(org_contents: &str) -> wasm_bindgen::JsValue {
let rust_parsed = match parse_with_settings(org_contents, &GlobalSettings::default()) {
Ok(document) => document,
Err(err) => {
return serde_wasm_bindgen::to_value(&ParseResult::Error(format!("{:?}", err)))
.unwrap();
}
};
let to_wasm_context = ToWasmContext::new(org_contents);
let wasm_document = match rust_parsed.to_wasm(to_wasm_context) {
Ok(document) => document,
Err(err) => {
return serde_wasm_bindgen::to_value(&ParseResult::Error(format!("{:?}", err)))
.unwrap();
}
};
serde_wasm_bindgen::to_value(&ParseResult::Success(wasm_document)).unwrap()
organic::wasm_cli::parse_org(org_contents)
}
fn main() -> Result<(), Box<dyn std::error::Error>> {

View File

@@ -3,6 +3,7 @@
use std::io::Read;
use organic::wasm_test::wasm_run_anonymous_compare;
use organic::wasm_test::wasm_run_compare_on_file;
#[cfg(feature = "tracing")]
use crate::init_tracing::init_telemetry;
@@ -42,14 +43,13 @@ async fn main_body() -> Result<(), Box<dyn std::error::Error>> {
}
Ok(())
} else {
todo!()
// for arg in args {
// if run_compare_on_file(arg).await? {
// } else {
// Err("Diff results do not match.")?;
// }
// }
// Ok(())
for arg in args {
if wasm_run_compare_on_file(arg).await? {
} else {
Err("Diff results do not match.")?;
}
}
Ok(())
}
}

View File

@@ -1,17 +1,16 @@
use std::path::Path;
use crate::compare::diff::compare_document;
use crate::compare::diff::DiffResult;
use crate::compare::sexp::sexp;
use crate::context::GlobalSettings;
use crate::context::LocalFileAccessInterface;
use crate::parser::parse_file_with_settings;
use crate::parser::parse_with_settings;
use crate::util::emacs_parse_anonymous_org_document;
use crate::util::emacs_parse_file_org_document;
use crate::util::foreground_color;
use crate::util::print_versions;
use crate::util::reset_color;
use crate::util::cli::emacs_parse_anonymous_org_document;
use crate::util::cli::emacs_parse_file_org_document;
use crate::util::cli::print_versions;
use crate::util::elisp::sexp;
use crate::util::terminal::foreground_color;
use crate::util::terminal::reset_color;
pub async fn run_anonymous_compare<P: AsRef<str>>(
org_contents: P,

View File

@@ -9,8 +9,6 @@ use super::diff::artificial_owned_diff_scope;
use super::diff::compare_ast_node;
use super::diff::DiffEntry;
use super::diff::DiffStatus;
use super::sexp::unquote;
use super::sexp::Token;
use super::util::get_property;
use super::util::get_property_numeric;
use super::util::get_property_quoted_string;
@@ -20,6 +18,8 @@ use crate::types::CharOffsetInLine;
use crate::types::LineNumber;
use crate::types::RetainLabels;
use crate::types::SwitchNumberLines;
use crate::util::elisp::unquote;
use crate::util::elisp::Token;
#[derive(Debug)]
pub(crate) enum EmacsField<'s> {

View File

@@ -16,10 +16,6 @@ use super::compare_field::compare_property_retain_labels;
use super::compare_field::compare_property_set_of_quoted_string;
use super::compare_field::compare_property_single_ast_node;
use super::compare_field::compare_property_unquoted_atom;
use super::elisp_fact::ElispFact;
use super::elisp_fact::GetElispFact;
use super::sexp::unquote;
use super::sexp::Token;
use super::util::affiliated_keywords_names;
use super::util::assert_no_children;
use super::util::compare_additional_properties;
@@ -109,8 +105,12 @@ use crate::types::Verbatim;
use crate::types::VerseBlock;
use crate::types::WarningDelayType;
use crate::types::Year;
use crate::util::foreground_color;
use crate::util::reset_color;
use crate::util::elisp::unquote;
use crate::util::elisp::Token;
use crate::util::elisp_fact::ElispFact;
use crate::util::elisp_fact::GetElispFact;
use crate::util::terminal::foreground_color;
use crate::util::terminal::reset_color;
#[derive(Debug)]
pub enum DiffEntry<'b, 's> {

View File

@@ -2,9 +2,7 @@
mod compare;
mod compare_field;
mod diff;
mod elisp_fact;
mod macros;
mod sexp;
mod util;
pub use compare::run_anonymous_compare;
pub use compare::run_anonymous_compare_with_settings;
@@ -12,8 +10,3 @@ pub use compare::run_compare_on_file;
pub use compare::run_compare_on_file_with_settings;
pub use compare::silent_anonymous_compare;
pub use compare::silent_compare_on_file;
pub(crate) use compare_field::EmacsField;
pub(crate) use elisp_fact::ElispFact;
pub use sexp::sexp;
pub use sexp::Token;
pub(crate) use util::get_property_quoted_string;

View File

@@ -8,14 +8,15 @@ use super::compare_field::compare_property_quoted_string;
use super::compare_field::ComparePropertiesResult;
use super::diff::DiffEntry;
use super::diff::DiffStatus;
use super::elisp_fact::GetElispFact;
use super::sexp::Token;
use crate::compare::diff::compare_ast_node;
use crate::compare::sexp::unquote;
use crate::types::AffiliatedKeywordValue;
use crate::types::AstNode;
use crate::types::GetAffiliatedKeywords;
use crate::types::StandardProperties;
use crate::util::elisp::get_emacs_standard_properties;
use crate::util::elisp::unquote;
use crate::util::elisp::Token;
use crate::util::elisp_fact::GetElispFact;
/// Check if the child string slice is a slice of the parent string slice.
fn is_slice_of(parent: &str, child: &str) -> bool {
@@ -145,80 +146,6 @@ fn assert_post_blank<'b, 's, S: StandardProperties<'s> + ?Sized>(
Ok(())
}
struct EmacsStandardProperties {
begin: Option<usize>,
#[allow(dead_code)]
post_affiliated: Option<usize>,
#[allow(dead_code)]
contents_begin: Option<usize>,
#[allow(dead_code)]
contents_end: Option<usize>,
end: Option<usize>,
#[allow(dead_code)]
post_blank: Option<usize>,
}
fn get_emacs_standard_properties(
emacs: &Token<'_>,
) -> Result<EmacsStandardProperties, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let attributes_child = children.get(1).ok_or("Should have an attributes child.")?;
let attributes_map = attributes_child.as_map()?;
let standard_properties = attributes_map.get(":standard-properties");
Ok(if standard_properties.is_some() {
let mut std_props = standard_properties
.expect("if statement proves its Some")
.as_vector()?
.iter();
let begin = maybe_token_to_usize(std_props.next())?;
let post_affiliated = maybe_token_to_usize(std_props.next())?;
let contents_begin = maybe_token_to_usize(std_props.next())?;
let contents_end = maybe_token_to_usize(std_props.next())?;
let end = maybe_token_to_usize(std_props.next())?;
let post_blank = maybe_token_to_usize(std_props.next())?;
EmacsStandardProperties {
begin,
post_affiliated,
contents_begin,
contents_end,
end,
post_blank,
}
} else {
let begin = maybe_token_to_usize(attributes_map.get(":begin").copied())?;
let end = maybe_token_to_usize(attributes_map.get(":end").copied())?;
let contents_begin = maybe_token_to_usize(attributes_map.get(":contents-begin").copied())?;
let contents_end = maybe_token_to_usize(attributes_map.get(":contents-end").copied())?;
let post_blank = maybe_token_to_usize(attributes_map.get(":post-blank").copied())?;
let post_affiliated =
maybe_token_to_usize(attributes_map.get(":post-affiliated").copied())?;
EmacsStandardProperties {
begin,
post_affiliated,
contents_begin,
contents_end,
end,
post_blank,
}
})
}
fn maybe_token_to_usize(
token: Option<&Token<'_>>,
) -> Result<Option<usize>, Box<dyn std::error::Error>> {
Ok(token
.map(|token| token.as_atom())
.map_or(Ok(None), |r| r.map(Some))?
.and_then(|val| {
if val == "nil" {
None
} else {
Some(val.parse::<usize>())
}
})
.map_or(Ok(None), |r| r.map(Some))?)
}
/// Get a named property from the emacs token.
///
/// Returns Ok(None) if value is nil or absent.

View File

@@ -24,7 +24,7 @@ pub(crate) fn record_event(event_type: EventType, input: OrgSource<'_>) {
*db.entry(key).or_insert(0) += 1;
}
pub fn report(original_document: &str) {
pub(crate) fn report(original_document: &str) {
let mut db = GLOBAL_DATA.lock().unwrap();
let db = db.get_or_insert_with(HashMap::new);
let mut results: Vec<_> = db.iter().collect();

View File

@@ -2,5 +2,5 @@ mod database;
mod event_type;
pub(crate) use database::record_event;
pub use database::report;
pub(crate) use database::report;
pub(crate) use event_type::EventType;

View File

@@ -3,25 +3,29 @@
#![feature(path_file_prefix)]
#![feature(is_sorted)]
#![feature(test)]
#![feature(iter_intersperse)]
#![feature(exact_size_is_empty)]
// TODO: #![warn(missing_docs)]
#![allow(clippy::bool_assert_comparison)] // Sometimes you want the long form because its easier to see at a glance.
extern crate test;
// TODO: I only include compare to use some shared stuff like sexp and DiffResult. Ideally, this would be moved to a shared module.
#[cfg(any(feature = "compare", feature = "wasm_test"))]
#[cfg(feature = "compare")]
pub mod compare;
#[cfg(any(feature = "compare", feature = "wasm_test"))]
pub mod util;
pub mod parse_cli;
#[cfg(any(feature = "compare", feature = "wasm", feature = "wasm_test"))]
mod util;
#[cfg(any(feature = "wasm", feature = "wasm_test"))]
pub mod wasm;
mod wasm;
#[cfg(any(feature = "wasm", feature = "wasm_test"))]
pub mod wasm_cli;
#[cfg(feature = "wasm_test")]
pub mod wasm_test;
mod context;
mod error;
#[cfg(feature = "event_count")]
pub mod event_count;
mod event_count;
mod iter;
pub mod parser;
pub mod types;

View File

@@ -1,12 +1,4 @@
#![feature(round_char_boundary)]
#![feature(exact_size_is_empty)]
use std::io::Read;
use std::path::Path;
use ::organic::parser::parse;
use organic::parser::parse_with_settings;
use organic::settings::GlobalSettings;
use organic::settings::LocalFileAccessInterface;
use organic::parse_cli::main_body;
#[cfg(feature = "tracing")]
use crate::init_tracing::init_telemetry;
@@ -30,55 +22,3 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
main_body_result
})
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn main_body() -> Result<(), Box<dyn std::error::Error>> {
let args = std::env::args().skip(1);
if args.is_empty() {
let org_contents = read_stdin_to_string()?;
run_anonymous_parse(org_contents)
} else {
for arg in args {
run_parse_on_file(arg)?
}
Ok(())
}
}
fn read_stdin_to_string() -> Result<String, Box<dyn std::error::Error>> {
let mut stdin_contents = String::new();
std::io::stdin()
.lock()
.read_to_string(&mut stdin_contents)?;
Ok(stdin_contents)
}
fn run_anonymous_parse<P: AsRef<str>>(org_contents: P) -> Result<(), Box<dyn std::error::Error>> {
let org_contents = org_contents.as_ref();
let rust_parsed = parse(org_contents)?;
println!("{:#?}", rust_parsed);
#[cfg(feature = "event_count")]
organic::event_count::report(org_contents);
Ok(())
}
fn run_parse_on_file<P: AsRef<Path>>(org_path: P) -> Result<(), Box<dyn std::error::Error>> {
let org_path = org_path.as_ref();
let parent_directory = org_path
.parent()
.ok_or("Should be contained inside a directory.")?;
let org_contents = std::fs::read_to_string(org_path)?;
let org_contents = org_contents.as_str();
let file_access_interface = LocalFileAccessInterface {
working_directory: Some(parent_directory.to_path_buf()),
};
let global_settings = GlobalSettings {
file_access: &file_access_interface,
..Default::default()
};
let rust_parsed = parse_with_settings(org_contents, &global_settings)?;
println!("{:#?}", rust_parsed);
#[cfg(feature = "event_count")]
organic::event_count::report(org_contents);
Ok(())
}

59
src/parse_cli/mod.rs Normal file
View File

@@ -0,0 +1,59 @@
use std::io::Read;
use std::path::Path;
use crate::parser::parse;
use crate::parser::parse_with_settings;
use crate::settings::GlobalSettings;
use crate::settings::LocalFileAccessInterface;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn main_body() -> Result<(), Box<dyn std::error::Error>> {
let args = std::env::args().skip(1);
if args.is_empty() {
let org_contents = read_stdin_to_string()?;
run_anonymous_parse(org_contents)
} else {
for arg in args {
run_parse_on_file(arg)?
}
Ok(())
}
}
fn read_stdin_to_string() -> Result<String, Box<dyn std::error::Error>> {
let mut stdin_contents = String::new();
std::io::stdin()
.lock()
.read_to_string(&mut stdin_contents)?;
Ok(stdin_contents)
}
fn run_anonymous_parse<P: AsRef<str>>(org_contents: P) -> Result<(), Box<dyn std::error::Error>> {
let org_contents = org_contents.as_ref();
let rust_parsed = parse(org_contents)?;
println!("{:#?}", rust_parsed);
#[cfg(feature = "event_count")]
crate::event_count::report(org_contents);
Ok(())
}
fn run_parse_on_file<P: AsRef<Path>>(org_path: P) -> Result<(), Box<dyn std::error::Error>> {
let org_path = org_path.as_ref();
let parent_directory = org_path
.parent()
.ok_or("Should be contained inside a directory.")?;
let org_contents = std::fs::read_to_string(org_path)?;
let org_contents = org_contents.as_str();
let file_access_interface = LocalFileAccessInterface {
working_directory: Some(parent_directory.to_path_buf()),
};
let global_settings = GlobalSettings {
file_access: &file_access_interface,
..Default::default()
};
let rust_parsed = parse_with_settings(org_contents, &global_settings)?;
println!("{:#?}", rust_parsed);
#[cfg(feature = "event_count")]
crate::event_count::report(org_contents);
Ok(())
}

View File

@@ -332,19 +332,19 @@ pub type HourInner = u8;
pub type MinuteInner = u8;
#[derive(Debug, Clone)]
pub struct Year(YearInner);
pub struct Year(pub YearInner);
#[derive(Debug, Clone)]
pub struct Month(MonthInner);
pub struct Month(pub MonthInner);
#[derive(Debug, Clone)]
pub struct DayOfMonth(DayOfMonthInner);
pub struct DayOfMonth(pub DayOfMonthInner);
#[derive(Debug, Clone)]
pub struct Hour(HourInner);
pub struct Hour(pub HourInner);
#[derive(Debug, Clone)]
pub struct Minute(MinuteInner);
pub struct Minute(pub MinuteInner);
impl Year {
// TODO: Make a real error type instead of a boxed any error.

191
src/util/cli.rs Normal file
View File

@@ -0,0 +1,191 @@
use std::path::Path;
use tokio::process::Command;
use crate::settings::GlobalSettings;
use crate::settings::HeadlineLevelFilter;
pub async fn print_versions() -> Result<(), Box<dyn std::error::Error>> {
eprintln!("Using emacs version: {}", get_emacs_version().await?.trim());
eprintln!(
"Using org-mode version: {}",
get_org_mode_version().await?.trim()
);
Ok(())
}
pub(crate) async fn get_emacs_version() -> Result<String, Box<dyn std::error::Error>> {
let elisp_script = r#"(progn
(message "%s" (version))
)"#;
let mut cmd = Command::new("emacs");
let cmd = cmd
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = cmd.output().await?;
out.status.exit_ok()?;
Ok(String::from_utf8(out.stderr)?)
}
pub(crate) async fn get_org_mode_version() -> Result<String, Box<dyn std::error::Error>> {
let elisp_script = r#"(progn
(org-mode)
(message "%s" (org-version nil t nil))
)"#;
let mut cmd = Command::new("emacs");
let cmd = cmd
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = cmd.output().await?;
out.status.exit_ok()?;
Ok(String::from_utf8(out.stderr)?)
}
pub(crate) async fn emacs_parse_anonymous_org_document<'g, 's, C>(
file_contents: C,
global_settings: &GlobalSettings<'g, 's>,
) -> Result<String, Box<dyn std::error::Error>>
where
C: AsRef<str>,
{
let escaped_file_contents = escape_elisp_string(file_contents);
let elisp_script = format!(
r#"(progn
(erase-buffer)
(require 'org)
(defun org-table-align () t)
(insert "{escaped_file_contents}")
{global_settings}
(org-mode)
(message "%s" (pp-to-string (org-element-parse-buffer)))
)"#,
escaped_file_contents = escaped_file_contents,
global_settings = global_settings_elisp(global_settings)
);
let mut cmd = Command::new("emacs");
let cmd = cmd
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = cmd.output().await?;
let status = out.status.exit_ok();
if status.is_err() {
eprintln!(
"Emacs errored out: {}\n{}",
String::from_utf8(out.stdout)?,
String::from_utf8(out.stderr)?
);
status?;
unreachable!();
}
let org_sexp = out.stderr;
Ok(String::from_utf8(org_sexp)?)
}
pub(crate) async fn emacs_parse_file_org_document<'g, 's, P>(
file_path: P,
global_settings: &GlobalSettings<'g, 's>,
) -> Result<String, Box<dyn std::error::Error>>
where
P: AsRef<Path>,
{
let file_path = file_path.as_ref().canonicalize()?;
let containing_directory = file_path.parent().ok_or(format!(
"Failed to get containing directory for path {}",
file_path.display()
))?;
let elisp_script = format!(
r#"(progn
(require 'org)
(defun org-table-align () t)
(setq vc-handled-backends nil)
{global_settings}
(find-file-read-only "{file_path}")
(org-mode)
(message "%s" (pp-to-string (org-element-parse-buffer)))
)"#,
global_settings = global_settings_elisp(global_settings),
file_path = file_path
.as_os_str()
.to_str()
.expect("File name should be valid utf-8.")
);
let mut cmd = Command::new("emacs");
let cmd = cmd
.current_dir(containing_directory)
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = cmd.output().await?;
let status = out.status.exit_ok();
if status.is_err() {
eprintln!(
"Emacs errored out: {}\n{}",
String::from_utf8(out.stdout)?,
String::from_utf8(out.stderr)?
);
status?;
unreachable!();
}
let org_sexp = out.stderr;
Ok(String::from_utf8(org_sexp)?)
}
fn escape_elisp_string<C>(file_contents: C) -> String
where
C: AsRef<str>,
{
let source = file_contents.as_ref();
let source_len = source.len();
// We allocate a string 10% larger than the source to account for escape characters. Without this, we would have more allocations during processing.
let mut output = String::with_capacity(source_len + (source_len / 10));
for c in source.chars() {
match c {
'"' | '\\' => {
output.push('\\');
output.push(c);
}
_ => {
output.push(c);
}
}
}
output
}
/// Generate elisp to configure org-mode parsing settings
///
/// Currently only org-list-allow-alphabetical is supported.
fn global_settings_elisp(global_settings: &GlobalSettings) -> String {
// This string concatenation is wildly inefficient but its only called in tests 🤷.
let mut ret = "".to_owned();
if global_settings.list_allow_alphabetical {
ret += "(setq org-list-allow-alphabetical t)\n"
}
if global_settings.tab_width != crate::settings::DEFAULT_TAB_WIDTH {
ret += format!("(setq-default tab-width {})", global_settings.tab_width).as_str();
}
if global_settings.odd_levels_only != HeadlineLevelFilter::default() {
ret += match global_settings.odd_levels_only {
HeadlineLevelFilter::Odd => "(setq org-odd-levels-only t)\n",
HeadlineLevelFilter::OddEven => "(setq org-odd-levels-only nil)\n",
};
}
ret
}

14
src/util/elisp/mod.rs Normal file
View File

@@ -0,0 +1,14 @@
mod sexp;
mod util;
pub use sexp::sexp;
pub(crate) use sexp::unquote;
#[cfg(feature = "wasm_test")]
pub(crate) use sexp::TextWithProperties;
pub use sexp::Token;
#[cfg(feature = "compare")]
pub(crate) use util::get_emacs_standard_properties;
#[cfg(feature = "wasm_test")]
pub(crate) use util::maybe_token_to_usize;
#[cfg(feature = "wasm_test")]
pub(crate) use util::EmacsStandardProperties;

View File

@@ -61,6 +61,7 @@ impl<'s> Token<'s> {
}?)
}
#[cfg(feature = "compare")]
pub(crate) fn as_text<'p>(
&'p self,
) -> Result<&'p TextWithProperties<'s>, Box<dyn std::error::Error>> {

76
src/util/elisp/util.rs Normal file
View File

@@ -0,0 +1,76 @@
use super::Token;
pub(crate) fn maybe_token_to_usize(
token: Option<&Token<'_>>,
) -> Result<Option<usize>, Box<dyn std::error::Error>> {
Ok(token
.map(|token| token.as_atom())
.map_or(Ok(None), |r| r.map(Some))?
.and_then(|val| {
if val == "nil" {
None
} else {
Some(val.parse::<usize>())
}
})
.map_or(Ok(None), |r| r.map(Some))?)
}
pub(crate) struct EmacsStandardProperties {
pub(crate) begin: Option<usize>,
#[allow(dead_code)]
pub(crate) post_affiliated: Option<usize>,
#[allow(dead_code)]
pub(crate) contents_begin: Option<usize>,
#[allow(dead_code)]
pub(crate) contents_end: Option<usize>,
pub(crate) end: Option<usize>,
#[allow(dead_code)]
pub(crate) post_blank: Option<usize>,
}
#[cfg(feature = "compare")]
pub(crate) fn get_emacs_standard_properties(
emacs: &Token<'_>,
) -> Result<EmacsStandardProperties, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let attributes_child = children.get(1).ok_or("Should have an attributes child.")?;
let attributes_map = attributes_child.as_map()?;
let standard_properties = attributes_map.get(":standard-properties");
Ok(if standard_properties.is_some() {
let mut std_props = standard_properties
.expect("if statement proves its Some")
.as_vector()?
.iter();
let begin = maybe_token_to_usize(std_props.next())?;
let post_affiliated = maybe_token_to_usize(std_props.next())?;
let contents_begin = maybe_token_to_usize(std_props.next())?;
let contents_end = maybe_token_to_usize(std_props.next())?;
let end = maybe_token_to_usize(std_props.next())?;
let post_blank = maybe_token_to_usize(std_props.next())?;
EmacsStandardProperties {
begin,
post_affiliated,
contents_begin,
contents_end,
end,
post_blank,
}
} else {
let begin = maybe_token_to_usize(attributes_map.get(":begin").copied())?;
let end = maybe_token_to_usize(attributes_map.get(":end").copied())?;
let contents_begin = maybe_token_to_usize(attributes_map.get(":contents-begin").copied())?;
let contents_end = maybe_token_to_usize(attributes_map.get(":contents-end").copied())?;
let post_blank = maybe_token_to_usize(attributes_map.get(":post-blank").copied())?;
let post_affiliated =
maybe_token_to_usize(attributes_map.get(":post-affiliated").copied())?;
EmacsStandardProperties {
begin,
post_affiliated,
contents_begin,
contents_end,
end,
post_blank,
}
})
}

View File

@@ -1,233 +1,8 @@
use std::borrow::Cow;
use std::path::Path;
use tokio::process::Command;
use crate::settings::GlobalSettings;
use crate::settings::HeadlineLevelFilter;
pub async fn print_versions() -> Result<(), Box<dyn std::error::Error>> {
eprintln!("Using emacs version: {}", get_emacs_version().await?.trim());
eprintln!(
"Using org-mode version: {}",
get_org_mode_version().await?.trim()
);
Ok(())
}
pub(crate) async fn get_emacs_version() -> Result<String, Box<dyn std::error::Error>> {
let elisp_script = r#"(progn
(message "%s" (version))
)"#;
let mut cmd = Command::new("emacs");
let cmd = cmd
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = cmd.output().await?;
out.status.exit_ok()?;
Ok(String::from_utf8(out.stderr)?)
}
pub(crate) async fn get_org_mode_version() -> Result<String, Box<dyn std::error::Error>> {
let elisp_script = r#"(progn
(org-mode)
(message "%s" (org-version nil t nil))
)"#;
let mut cmd = Command::new("emacs");
let cmd = cmd
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = cmd.output().await?;
out.status.exit_ok()?;
Ok(String::from_utf8(out.stderr)?)
}
pub(crate) async fn emacs_parse_anonymous_org_document<'g, 's, C>(
file_contents: C,
global_settings: &GlobalSettings<'g, 's>,
) -> Result<String, Box<dyn std::error::Error>>
where
C: AsRef<str>,
{
let escaped_file_contents = escape_elisp_string(file_contents);
let elisp_script = format!(
r#"(progn
(erase-buffer)
(require 'org)
(defun org-table-align () t)
(insert "{escaped_file_contents}")
{global_settings}
(org-mode)
(message "%s" (pp-to-string (org-element-parse-buffer)))
)"#,
escaped_file_contents = escaped_file_contents,
global_settings = global_settings_elisp(global_settings)
);
let mut cmd = Command::new("emacs");
let cmd = cmd
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = cmd.output().await?;
let status = out.status.exit_ok();
if status.is_err() {
eprintln!(
"Emacs errored out: {}\n{}",
String::from_utf8(out.stdout)?,
String::from_utf8(out.stderr)?
);
status?;
unreachable!();
}
let org_sexp = out.stderr;
Ok(String::from_utf8(org_sexp)?)
}
pub(crate) async fn emacs_parse_file_org_document<'g, 's, P>(
file_path: P,
global_settings: &GlobalSettings<'g, 's>,
) -> Result<String, Box<dyn std::error::Error>>
where
P: AsRef<Path>,
{
let file_path = file_path.as_ref().canonicalize()?;
let containing_directory = file_path.parent().ok_or(format!(
"Failed to get containing directory for path {}",
file_path.display()
))?;
let elisp_script = format!(
r#"(progn
(require 'org)
(defun org-table-align () t)
(setq vc-handled-backends nil)
{global_settings}
(find-file-read-only "{file_path}")
(org-mode)
(message "%s" (pp-to-string (org-element-parse-buffer)))
)"#,
global_settings = global_settings_elisp(global_settings),
file_path = file_path
.as_os_str()
.to_str()
.expect("File name should be valid utf-8.")
);
let mut cmd = Command::new("emacs");
let cmd = cmd
.current_dir(containing_directory)
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = cmd.output().await?;
let status = out.status.exit_ok();
if status.is_err() {
eprintln!(
"Emacs errored out: {}\n{}",
String::from_utf8(out.stdout)?,
String::from_utf8(out.stderr)?
);
status?;
unreachable!();
}
let org_sexp = out.stderr;
Ok(String::from_utf8(org_sexp)?)
}
fn escape_elisp_string<C>(file_contents: C) -> String
where
C: AsRef<str>,
{
let source = file_contents.as_ref();
let source_len = source.len();
// We allocate a string 10% larger than the source to account for escape characters. Without this, we would have more allocations during processing.
let mut output = String::with_capacity(source_len + (source_len / 10));
for c in source.chars() {
match c {
'"' | '\\' => {
output.push('\\');
output.push(c);
}
_ => {
output.push(c);
}
}
}
output
}
/// Generate elisp to configure org-mode parsing settings
///
/// Currently only org-list-allow-alphabetical is supported.
fn global_settings_elisp(global_settings: &GlobalSettings) -> String {
// This string concatenation is wildly inefficient but its only called in tests 🤷.
let mut ret = "".to_owned();
if global_settings.list_allow_alphabetical {
ret += "(setq org-list-allow-alphabetical t)\n"
}
if global_settings.tab_width != crate::settings::DEFAULT_TAB_WIDTH {
ret += format!("(setq-default tab-width {})", global_settings.tab_width).as_str();
}
if global_settings.odd_levels_only != HeadlineLevelFilter::default() {
ret += match global_settings.odd_levels_only {
HeadlineLevelFilter::Odd => "(setq org-odd-levels-only t)\n",
HeadlineLevelFilter::OddEven => "(setq org-odd-levels-only nil)\n",
};
}
ret
}
fn should_use_color() -> bool {
!std::env::var("NO_COLOR").is_ok_and(|val| !val.is_empty())
}
pub(crate) fn foreground_color(red: u8, green: u8, blue: u8) -> Cow<'static, str> {
if should_use_color() {
format!(
"\x1b[38;2;{red};{green};{blue}m",
red = red,
green = green,
blue = blue
)
.into()
} else {
Cow::from("")
}
}
#[allow(dead_code)]
pub(crate) fn background_color(red: u8, green: u8, blue: u8) -> Cow<'static, str> {
if should_use_color() {
format!(
"\x1b[48;2;{red};{green};{blue}m",
red = red,
green = green,
blue = blue
)
.into()
} else {
Cow::from("")
}
}
pub(crate) fn reset_color() -> &'static str {
if should_use_color() {
"\x1b[0m"
} else {
""
}
}
#[cfg(any(feature = "compare", feature = "wasm_test"))]
pub mod cli;
#[cfg(any(feature = "compare", feature = "wasm_test"))]
pub mod elisp;
#[cfg(any(feature = "compare", feature = "wasm", feature = "wasm_test"))]
pub mod elisp_fact;
#[cfg(any(feature = "compare", feature = "wasm_test"))]
pub mod terminal;

42
src/util/terminal.rs Normal file
View File

@@ -0,0 +1,42 @@
use std::borrow::Cow;
fn should_use_color() -> bool {
!std::env::var("NO_COLOR").is_ok_and(|val| !val.is_empty())
}
pub(crate) fn foreground_color(red: u8, green: u8, blue: u8) -> Cow<'static, str> {
if should_use_color() {
format!(
"\x1b[38;2;{red};{green};{blue}m",
red = red,
green = green,
blue = blue
)
.into()
} else {
Cow::from("")
}
}
#[allow(dead_code)]
pub(crate) fn background_color(red: u8, green: u8, blue: u8) -> Cow<'static, str> {
if should_use_color() {
format!(
"\x1b[48;2;{red};{green};{blue}m",
red = red,
green = green,
blue = blue
)
.into()
} else {
Cow::from("")
}
}
pub(crate) fn reset_color() -> &'static str {
if should_use_color() {
"\x1b[0m"
} else {
""
}
}

View File

@@ -0,0 +1,95 @@
use std::collections::HashMap;
use serde::Deserialize;
use serde::Serialize;
use super::macros::to_wasm;
use super::to_wasm::ToWasm;
use super::WasmAstNode;
use crate::types::AffiliatedKeywordValue;
use crate::types::AffiliatedKeywords;
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum AdditionalPropertyValue {
SingleString(String),
ListOfStrings(Vec<String>),
OptionalPair {
optval: Option<String>,
val: String,
},
ObjectTree {
#[serde(rename = "object-tree")]
object_tree: Vec<(Option<Vec<WasmAstNode>>, Vec<WasmAstNode>)>,
},
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct AdditionalProperties {
#[serde(flatten)]
pub(crate) properties: HashMap<String, AdditionalPropertyValue>,
}
to_wasm!(
AdditionalProperties,
AffiliatedKeywords<'s>,
original,
wasm_context,
{
let mut additional_properties = AdditionalProperties::default();
for (name, val) in original.keywords.iter() {
let converted_val = match val {
AffiliatedKeywordValue::SingleString(val) => {
AdditionalPropertyValue::SingleString((*val).to_owned())
}
AffiliatedKeywordValue::ListOfStrings(val) => {
AdditionalPropertyValue::ListOfStrings(
val.iter().map(|s| (*s).to_owned()).collect(),
)
}
AffiliatedKeywordValue::OptionalPair { optval, val } => {
AdditionalPropertyValue::OptionalPair {
optval: optval.map(|s| (*s).to_owned()),
val: (*val).to_owned(),
}
}
AffiliatedKeywordValue::ObjectTree(val) => {
let mut ret = Vec::with_capacity(val.len());
for (optval, value) in val {
let converted_optval = if let Some(optval) = optval {
Some(
optval
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?,
)
} else {
None
};
let converted_value = value
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
ret.push((converted_optval, converted_value));
}
AdditionalPropertyValue::ObjectTree { object_tree: ret }
}
};
additional_properties
.properties
.insert(name.clone(), converted_val);
}
Ok(additional_properties)
}
);

View File

@@ -1,30 +1,54 @@
use std::borrow::Cow;
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::AngleLink;
use crate::types::LinkType;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmAngleLink<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "format")]
#[serde(rename = "angle")]
pub struct WasmAngleLink {
#[serde(rename = "type")]
pub(crate) link_type: String,
pub(crate) path: String,
#[serde(rename = "raw-link")]
pub(crate) raw_link: String,
pub(crate) application: Option<String>,
#[serde(rename = "search-option")]
pub(crate) search_option: Option<String>,
}
to_wasm!(
WasmAngleLink<'s, 'p>,
WasmAngleLink,
AngleLink<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::AngleLink(original) },
{ "link".into() },
{
Ok(WasmAngleLink {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmAngleLink {
link_type: match &original.link_type {
LinkType::File => "file".to_owned(),
LinkType::Protocol(protocol) => protocol.clone().into_owned(),
LinkType::Id => "id".to_owned(),
LinkType::CustomId => "custom-id".to_owned(),
LinkType::CodeRef => "coderef".to_owned(),
LinkType::Fuzzy => "fuzzy".to_owned(),
},
path: original.get_path().into_owned(),
raw_link: original.raw_link.to_owned(),
application: original.application.map(|c| c.to_owned()),
search_option: original.get_search_option().map(Cow::into_owned),
},
))
}
);

View File

@@ -1,3 +1,4 @@
use serde::Deserialize;
use serde::Serialize;
use super::angle_link::WasmAngleLink;
@@ -58,71 +59,84 @@ use super::timestamp::WasmTimestamp;
use super::underline::WasmUnderline;
use super::verbatim::WasmVerbatim;
use super::verse_block::WasmVerseBlock;
use super::WasmStandardProperties;
#[derive(Debug, Serialize)]
#[serde(untagged)]
pub enum WasmAstNode<'s, 'p> {
// Document Nodes
Document(WasmDocument<'s, 'p>),
Headline(WasmHeadline<'s, 'p>),
Section(WasmSection<'s, 'p>),
// Elements
Paragraph(WasmParagraph<'s, 'p>),
PlainList(WasmPlainList<'s, 'p>),
PlainListItem(WasmPlainListItem<'s, 'p>),
CenterBlock(WasmCenterBlock<'s, 'p>),
QuoteBlock(WasmQuoteBlock<'s, 'p>),
SpecialBlock(WasmSpecialBlock<'s, 'p>),
DynamicBlock(WasmDynamicBlock<'s, 'p>),
FootnoteDefinition(WasmFootnoteDefinition<'s, 'p>),
Comment(WasmComment<'s, 'p>),
Drawer(WasmDrawer<'s, 'p>),
PropertyDrawer(WasmPropertyDrawer<'s, 'p>),
NodeProperty(WasmNodeProperty<'s, 'p>),
Table(WasmTable<'s, 'p>),
TableRow(WasmTableRow<'s, 'p>),
VerseBlock(WasmVerseBlock<'s, 'p>),
CommentBlock(WasmCommentBlock<'s, 'p>),
ExampleBlock(WasmExampleBlock<'s, 'p>),
ExportBlock(WasmExportBlock<'s, 'p>),
SrcBlock(WasmSrcBlock<'s, 'p>),
Clock(WasmClock<'s, 'p>),
DiarySexp(WasmDiarySexp<'s, 'p>),
Planning(WasmPlanning<'s, 'p>),
FixedWidthArea(WasmFixedWidthArea<'s, 'p>),
HorizontalRule(WasmHorizontalRule<'s, 'p>),
Keyword(WasmKeyword<'s, 'p>),
BabelCall(WasmBabelCall<'s, 'p>),
LatexEnvironment(WasmLatexEnvironment<'s, 'p>),
// Objects
Bold(WasmBold<'s, 'p>),
Italic(WasmItalic<'s, 'p>),
Underline(WasmUnderline<'s, 'p>),
StrikeThrough(WasmStrikeThrough<'s, 'p>),
Code(WasmCode<'s, 'p>),
Verbatim(WasmVerbatim<'s, 'p>),
PlainText(WasmPlainText<'s, 'p>),
RegularLink(WasmRegularLink<'s, 'p>),
RadioLink(WasmRadioLink<'s, 'p>),
RadioTarget(WasmRadioTarget<'s, 'p>),
PlainLink(WasmPlainLink<'s, 'p>),
AngleLink(WasmAngleLink<'s, 'p>),
OrgMacro(WasmOrgMacro<'s, 'p>),
Entity(WasmEntity<'s, 'p>),
LatexFragment(WasmLatexFragment<'s, 'p>),
ExportSnippet(WasmExportSnippet<'s, 'p>),
FootnoteReference(WasmFootnoteReference<'s, 'p>),
Citation(WasmCitation<'s, 'p>),
CitationReference(WasmCitationReference<'s, 'p>),
InlineBabelCall(WasmInlineBabelCall<'s, 'p>),
InlineSourceBlock(WasmInlineSourceBlock<'s, 'p>),
LineBreak(WasmLineBreak<'s, 'p>),
Target(WasmTarget<'s, 'p>),
StatisticsCookie(WasmStatisticsCookie<'s, 'p>),
Subscript(WasmSubscript<'s, 'p>),
Superscript(WasmSuperscript<'s, 'p>),
TableCell(WasmTableCell<'s, 'p>),
Timestamp(WasmTimestamp<'s, 'p>),
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmAstNodeWrapper<I> {
#[serde(rename = "ast-node")]
pub(crate) ast_node: String,
#[serde(rename = "standard-properties")]
pub(crate) standard_properties: WasmStandardProperties,
#[serde(rename = "children")]
pub(crate) children: Vec<WasmAstNode>,
#[serde(rename = "properties")]
pub(crate) properties: I,
}
impl<'s, 'p> WasmAstNode<'s, 'p> {}
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum WasmAstNode {
// Document Nodes
Document(WasmAstNodeWrapper<WasmDocument>),
Headline(WasmAstNodeWrapper<WasmHeadline>),
Section(WasmAstNodeWrapper<WasmSection>),
// Elements
Paragraph(WasmAstNodeWrapper<WasmParagraph>),
PlainList(WasmAstNodeWrapper<WasmPlainList>),
PlainListItem(WasmAstNodeWrapper<WasmPlainListItem>),
CenterBlock(WasmAstNodeWrapper<WasmCenterBlock>),
QuoteBlock(WasmAstNodeWrapper<WasmQuoteBlock>),
SpecialBlock(WasmAstNodeWrapper<WasmSpecialBlock>),
DynamicBlock(WasmAstNodeWrapper<WasmDynamicBlock>),
FootnoteDefinition(WasmAstNodeWrapper<WasmFootnoteDefinition>),
Comment(WasmAstNodeWrapper<WasmComment>),
Drawer(WasmAstNodeWrapper<WasmDrawer>),
PropertyDrawer(WasmAstNodeWrapper<WasmPropertyDrawer>),
NodeProperty(WasmAstNodeWrapper<WasmNodeProperty>),
Table(WasmAstNodeWrapper<WasmTable>),
TableRow(WasmAstNodeWrapper<WasmTableRow>),
VerseBlock(WasmAstNodeWrapper<WasmVerseBlock>),
CommentBlock(WasmAstNodeWrapper<WasmCommentBlock>),
ExampleBlock(WasmAstNodeWrapper<WasmExampleBlock>),
ExportBlock(WasmAstNodeWrapper<WasmExportBlock>),
SrcBlock(WasmAstNodeWrapper<WasmSrcBlock>),
Clock(WasmAstNodeWrapper<WasmClock>),
DiarySexp(WasmAstNodeWrapper<WasmDiarySexp>),
Planning(WasmAstNodeWrapper<WasmPlanning>),
FixedWidthArea(WasmAstNodeWrapper<WasmFixedWidthArea>),
HorizontalRule(WasmAstNodeWrapper<WasmHorizontalRule>),
Keyword(WasmAstNodeWrapper<WasmKeyword>),
BabelCall(WasmAstNodeWrapper<WasmBabelCall>),
LatexEnvironment(WasmAstNodeWrapper<WasmLatexEnvironment>),
// Objects
Bold(WasmAstNodeWrapper<WasmBold>),
Italic(WasmAstNodeWrapper<WasmItalic>),
Underline(WasmAstNodeWrapper<WasmUnderline>),
StrikeThrough(WasmAstNodeWrapper<WasmStrikeThrough>),
Code(WasmAstNodeWrapper<WasmCode>),
Verbatim(WasmAstNodeWrapper<WasmVerbatim>),
PlainText(WasmAstNodeWrapper<WasmPlainText>),
RegularLink(WasmAstNodeWrapper<WasmRegularLink>),
RadioLink(WasmAstNodeWrapper<WasmRadioLink>),
RadioTarget(WasmAstNodeWrapper<WasmRadioTarget>),
PlainLink(WasmAstNodeWrapper<WasmPlainLink>),
AngleLink(WasmAstNodeWrapper<WasmAngleLink>),
OrgMacro(WasmAstNodeWrapper<WasmOrgMacro>),
Entity(WasmAstNodeWrapper<WasmEntity>),
LatexFragment(WasmAstNodeWrapper<WasmLatexFragment>),
ExportSnippet(WasmAstNodeWrapper<WasmExportSnippet>),
FootnoteReference(WasmAstNodeWrapper<WasmFootnoteReference>),
Citation(WasmAstNodeWrapper<WasmCitation>),
CitationReference(WasmAstNodeWrapper<WasmCitationReference>),
InlineBabelCall(WasmAstNodeWrapper<WasmInlineBabelCall>),
InlineSourceBlock(WasmAstNodeWrapper<WasmInlineSourceBlock>),
LineBreak(WasmAstNodeWrapper<WasmLineBreak>),
Target(WasmAstNodeWrapper<WasmTarget>),
StatisticsCookie(WasmAstNodeWrapper<WasmStatisticsCookie>),
Subscript(WasmAstNodeWrapper<WasmSubscript>),
Superscript(WasmAstNodeWrapper<WasmSuperscript>),
TableCell(WasmAstNodeWrapper<WasmTableCell>),
Timestamp(WasmAstNodeWrapper<WasmTimestamp>),
}
impl WasmAstNode {}

View File

@@ -1,30 +1,50 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::BabelCall;
use crate::types::GetAffiliatedKeywords;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmBabelCall<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmBabelCall {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) call: Option<String>,
#[serde(rename = "inside-header")]
pub(crate) inside_header: Option<String>,
pub(crate) arguments: Option<String>,
#[serde(rename = "end-header")]
pub(crate) end_header: Option<String>,
pub(crate) value: String,
}
to_wasm!(
WasmBabelCall<'s, 'p>,
WasmBabelCall,
BabelCall<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::BabelCall(original) },
{ "babel-call".into() },
{
Ok(WasmBabelCall {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
Ok((
Vec::new(),
WasmBabelCall {
additional_properties,
call: original.call.map(|s| s.to_owned()),
inside_header: original.inside_header.map(|s| s.to_owned()),
arguments: original.arguments.map(|s| s.to_owned()),
end_header: original.end_header.map(|s| s.to_owned()),
value: original.value.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,34 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Bold;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmBold<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmBold {}
to_wasm!(
WasmBold<'s, 'p>,
WasmBold,
Bold<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Bold(original) },
{ "bold".into() },
{
Ok(WasmBold {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((children, WasmBold {}))
}
);

View File

@@ -1,30 +1,48 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::CenterBlock;
use crate::types::GetAffiliatedKeywords;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmCenterBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmCenterBlock {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
}
to_wasm!(
WasmCenterBlock<'s, 'p>,
WasmCenterBlock,
CenterBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::CenterBlock(original) },
{ "center-block".into() },
{
Ok(WasmCenterBlock {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmCenterBlock {
additional_properties,
},
))
}
);

View File

@@ -1,30 +1,71 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Citation;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmCitation<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmCitation {
pub(crate) style: Option<String>,
pub(crate) prefix: Option<Vec<WasmAstNode>>,
pub(crate) suffix: Option<Vec<WasmAstNode>>,
}
to_wasm!(
WasmCitation<'s, 'p>,
WasmCitation,
Citation<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Citation(original) },
{ "citation".into() },
{
Ok(WasmCitation {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
let prefix = original
.prefix
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
let suffix = original
.suffix
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmCitation {
style: original.style.map(|s| s.to_owned()),
prefix: if prefix.is_empty() {
None
} else {
Some(prefix)
},
suffix: if suffix.is_empty() {
None
} else {
Some(suffix)
},
},
))
}
);

View File

@@ -1,30 +1,62 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::CitationReference;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmCitationReference<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmCitationReference {
pub(crate) key: String,
pub(crate) prefix: Option<Vec<WasmAstNode>>,
pub(crate) suffix: Option<Vec<WasmAstNode>>,
}
to_wasm!(
WasmCitationReference<'s, 'p>,
WasmCitationReference,
CitationReference<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::CitationReference(original) },
{ "citation-reference".into() },
{
Ok(WasmCitationReference {
standard_properties,
children: Vec::new(),
})
let prefix = original
.prefix
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
let suffix = original
.suffix
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
Vec::new(),
WasmCitationReference {
key: original.key.to_owned(),
prefix: if prefix.is_empty() {
None
} else {
Some(prefix)
},
suffix: if suffix.is_empty() {
None
} else {
Some(suffix)
},
},
))
}
);

View File

@@ -1,30 +1,43 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Clock;
use crate::types::ClockStatus;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmClock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmClock {
#[serde(rename = "value")]
pub(crate) timestamp: Box<WasmAstNode>,
pub(crate) duration: Option<String>,
pub(crate) status: String,
}
to_wasm!(
WasmClock<'s, 'p>,
WasmClock,
Clock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Clock(original) },
{ "clock".into() },
{
Ok(WasmClock {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmClock {
timestamp: Box::new(Into::<WasmAstNode>::into(
original.timestamp.to_wasm(wasm_context.clone())?,
)),
duration: original.duration.map(|s| s.to_owned()),
status: match original.status {
ClockStatus::Running => "running",
ClockStatus::Closed => "closed",
}
.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,31 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Code;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmCode<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmCode {
pub(crate) value: String,
}
to_wasm!(
WasmCode<'s, 'p>,
WasmCode,
Code<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Code(original) },
{ "code".into() },
{
Ok(WasmCode {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmCode {
value: original.contents.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,31 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Comment;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmComment<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmComment {
pub(crate) value: String,
}
to_wasm!(
WasmComment<'s, 'p>,
WasmComment,
Comment<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Comment(original) },
{ "comment".into() },
{
Ok(WasmComment {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmComment {
value: original.get_value(),
},
))
}
);

View File

@@ -1,30 +1,40 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::CommentBlock;
use crate::types::GetAffiliatedKeywords;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmCommentBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmCommentBlock {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) value: String,
}
to_wasm!(
WasmCommentBlock<'s, 'p>,
WasmCommentBlock,
CommentBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::CommentBlock(original) },
{ "comment-block".into() },
{
Ok(WasmCommentBlock {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
Ok((
Vec::new(),
WasmCommentBlock {
additional_properties,
value: original.contents.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,40 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::DiarySexp;
use crate::types::GetAffiliatedKeywords;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmDiarySexp<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmDiarySexp {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) value: String,
}
to_wasm!(
WasmDiarySexp<'s, 'p>,
WasmDiarySexp,
DiarySexp<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::DiarySexp(original) },
{ "diary-sexp".into() },
{
Ok(WasmDiarySexp {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
Ok((
Vec::new(),
WasmDiarySexp {
additional_properties,
value: original.value.to_owned(),
},
))
}
);

View File

@@ -1,46 +1,46 @@
use std::path::PathBuf;
use serde::Deserialize;
use serde::Serialize;
use super::additional_property::AdditionalProperties;
use super::additional_property::AdditionalPropertyValue;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
#[cfg(feature = "wasm_test")]
use crate::compare::ElispFact;
use crate::types::Document;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmDocument<'s, 'p> {
standard_properties: WasmStandardProperties,
additional_properties: Vec<(String, &'s str)>,
pub(crate) children: Vec<WasmAstNode<'s, 'p>>,
category: Option<&'p str>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmDocument {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
#[serde(rename = "CATEGORY")]
pub(crate) category: Option<String>,
pub(crate) path: Option<PathBuf>,
}
to_wasm!(
WasmDocument<'s, 'p>,
WasmDocument,
Document<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Document(original) },
{ "org-data".into() },
{
let category = original.category.as_ref().map(String::as_str);
let category = original.category.as_deref();
let path = original.path.clone();
let additional_properties: Vec<(String, &str)> = original
.get_additional_properties()
.map(|node_property| {
(
format!(":{}", node_property.property_name.to_uppercase()),
node_property.value.unwrap_or(""),
)
})
.collect();
let mut additional_properties = AdditionalProperties::default();
for (name, val) in original.get_additional_properties().map(|node_property| {
(
node_property.property_name.to_uppercase(),
AdditionalPropertyValue::SingleString(node_property.value.unwrap_or("").to_owned()),
)
}) {
additional_properties.properties.insert(name, val);
}
let children = original
.zeroth_section
@@ -48,34 +48,22 @@ to_wasm!(
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode<'_, '_>>::into)
.map(Into::<WasmAstNode>::into)
})
.chain(original.children.iter().map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode<'_, '_>>::into)
.map(Into::<WasmAstNode>::into)
}))
.collect::<Result<Vec<_>, _>>()?;
Ok(WasmDocument {
standard_properties,
additional_properties,
Ok((
children,
category,
path,
})
WasmDocument {
additional_properties,
category: category.map(str::to_owned),
path,
},
))
}
);
impl<'s, 'p> Into<WasmAstNode<'s, 'p>> for WasmDocument<'s, 'p> {
fn into(self) -> WasmAstNode<'s, 'p> {
WasmAstNode::Document(self)
}
}
#[cfg(feature = "wasm_test")]
impl<'s, 'p> ElispFact<'s> for WasmDocument<'s, 'p> {
fn get_elisp_name<'b>(&'b self) -> std::borrow::Cow<'s, str> {
"org-data".into()
}
}

View File

@@ -1,30 +1,51 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::Drawer;
use crate::types::GetAffiliatedKeywords;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmDrawer<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmDrawer {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
#[serde(rename = "drawer-name")]
pub(crate) drawer_name: String,
}
to_wasm!(
WasmDrawer<'s, 'p>,
WasmDrawer,
Drawer<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Drawer(original) },
{ "drawer".into() },
{
Ok(WasmDrawer {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmDrawer {
additional_properties,
drawer_name: original.drawer_name.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,53 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::DynamicBlock;
use crate::types::GetAffiliatedKeywords;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmDynamicBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmDynamicBlock {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
#[serde(rename = "block-name")]
pub(crate) block_name: String,
pub(crate) arguments: Option<String>,
}
to_wasm!(
WasmDynamicBlock<'s, 'p>,
WasmDynamicBlock,
DynamicBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::DynamicBlock(original) },
{ "dynamic-block".into() },
{
Ok(WasmDynamicBlock {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmDynamicBlock {
additional_properties,
block_name: original.block_name.to_owned(),
arguments: original.parameters.map(|s| s.to_owned()),
},
))
}
);

View File

@@ -1,30 +1,49 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::headline::Noop;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Entity;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmEntity<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmEntity {
pub(crate) name: String,
pub(crate) latex: String,
#[serde(rename = "latex-math-p")]
pub(crate) latex_math_mode: bool,
pub(crate) html: String,
pub(crate) ascii: String,
pub(crate) latin1: Noop,
#[serde(rename = "utf-8")]
pub(crate) utf8: String,
#[serde(rename = "use-brackets-p")]
pub(crate) use_brackets: bool,
}
to_wasm!(
WasmEntity<'s, 'p>,
WasmEntity,
Entity<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Entity(original) },
{ "entity".into() },
{
Ok(WasmEntity {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmEntity {
name: original.name.to_owned(),
latex: original.latex.to_owned(),
latex_math_mode: original.latex_math_mode,
html: original.html.to_owned(),
ascii: original.ascii.to_owned(),
latin1: Noop {},
utf8: original.utf8.to_owned(),
use_brackets: original.use_brackets,
},
))
}
);

View File

@@ -1,30 +1,75 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::src_block::WasmNumberLines;
use super::src_block::WasmNumberLinesWrapper;
use super::src_block::WasmRetainLabels;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::CharOffsetInLine;
use crate::types::ExampleBlock;
use crate::types::GetAffiliatedKeywords;
use crate::types::RetainLabels;
use crate::types::SwitchNumberLines;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmExampleBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmExampleBlock {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) value: String,
pub(crate) switches: Option<String>,
#[serde(rename = "number-lines")]
pub(crate) number_lines: Option<WasmNumberLinesWrapper>,
#[serde(rename = "preserve-indent")]
pub(crate) preserve_indent: Option<CharOffsetInLine>,
#[serde(rename = "retain-labels")]
pub(crate) retain_labels: WasmRetainLabels,
#[serde(rename = "use-labels")]
pub(crate) use_labels: bool,
#[serde(rename = "label-fmt")]
pub(crate) label_format: Option<String>,
}
to_wasm!(
WasmExampleBlock<'s, 'p>,
WasmExampleBlock,
ExampleBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::ExampleBlock(original) },
{ "example-block".into() },
{
Ok(WasmExampleBlock {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
Ok((
Vec::new(),
WasmExampleBlock {
additional_properties,
value: original.get_value().into_owned(),
switches: original.switches.map(|s| s.to_owned()),
number_lines: match original.number_lines {
None => None,
Some(SwitchNumberLines::New(n)) => Some(WasmNumberLinesWrapper {
inner: WasmNumberLines::New(n),
}),
Some(SwitchNumberLines::Continued(n)) => Some(WasmNumberLinesWrapper {
inner: WasmNumberLines::Continued(n),
}),
},
preserve_indent: original.preserve_indent,
retain_labels: match original.retain_labels {
RetainLabels::No => WasmRetainLabels::YesNo(false),
RetainLabels::Yes => WasmRetainLabels::YesNo(true),
RetainLabels::Keep(n) => WasmRetainLabels::Keep(n),
},
use_labels: original.use_labels,
label_format: original.label_format.map(|s| s.to_owned()),
},
))
}
);

View File

@@ -1,30 +1,43 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::ExportBlock;
use crate::types::GetAffiliatedKeywords;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmExportBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmExportBlock {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
#[serde(rename = "type")]
pub(crate) export_type: Option<String>,
pub(crate) value: String,
}
to_wasm!(
WasmExportBlock<'s, 'p>,
WasmExportBlock,
ExportBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::ExportBlock(original) },
{ "export-block".into() },
{
Ok(WasmExportBlock {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
Ok((
Vec::new(),
WasmExportBlock {
additional_properties,
export_type: original.get_export_type(),
value: original.get_value().into_owned(),
},
))
}
);

View File

@@ -1,30 +1,34 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::ExportSnippet;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmExportSnippet<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmExportSnippet {
#[serde(rename = "back-end")]
pub(crate) backend: String,
pub(crate) value: Option<String>,
}
to_wasm!(
WasmExportSnippet<'s, 'p>,
WasmExportSnippet,
ExportSnippet<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::ExportSnippet(original) },
{ "export-snippet".into() },
{
Ok(WasmExportSnippet {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmExportSnippet {
backend: original.backend.to_owned(),
value: original.contents.map(|s| s.to_owned()),
},
))
}
);

View File

@@ -1,30 +1,42 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::FixedWidthArea;
use crate::types::GetAffiliatedKeywords;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmFixedWidthArea<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmFixedWidthArea {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) value: String,
}
to_wasm!(
WasmFixedWidthArea<'s, 'p>,
WasmFixedWidthArea,
FixedWidthArea<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::FixedWidthArea(original) },
{ "fixed-width".into() },
{
Ok(WasmFixedWidthArea {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let value = original.get_value();
Ok((
Vec::new(),
WasmFixedWidthArea {
additional_properties,
value,
},
))
}
);

View File

@@ -1,30 +1,54 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::headline::Noop;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::FootnoteDefinition;
use crate::types::GetAffiliatedKeywords;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmFootnoteDefinition<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmFootnoteDefinition {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) label: String,
#[serde(rename = "pre-blank")]
pub(crate) pre_blank: Noop,
}
to_wasm!(
WasmFootnoteDefinition<'s, 'p>,
WasmFootnoteDefinition,
FootnoteDefinition<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::FootnoteDefinition(original) },
{ "footnote-definition".into() },
{
Ok(WasmFootnoteDefinition {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmFootnoteDefinition {
additional_properties,
label: original.label.to_owned(),
pre_blank: Noop {},
},
))
}
);

View File

@@ -1,30 +1,49 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::FootnoteReference;
use crate::types::FootnoteReferenceType;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmFootnoteReference<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmFootnoteReference {
pub(crate) label: Option<String>,
#[serde(rename = "type")]
pub(crate) footnote_reference_type: String,
}
to_wasm!(
WasmFootnoteReference<'s, 'p>,
WasmFootnoteReference,
FootnoteReference<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::FootnoteReference(original) },
{ "footnote-reference".into() },
{
Ok(WasmFootnoteReference {
standard_properties,
children: Vec::new(),
})
let children = original
.definition
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmFootnoteReference {
label: original.label.map(|s| s.to_owned()),
footnote_reference_type: match original.get_type() {
FootnoteReferenceType::Standard => "standard",
FootnoteReferenceType::Inline => "inline",
}
.to_owned(),
},
))
}
);

View File

@@ -1,36 +1,140 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use super::AdditionalPropertyValue;
use crate::types::Heading;
use crate::types::HeadlineLevel;
use crate::types::PriorityCookie;
use crate::types::TodoKeywordType;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "headline")]
pub struct WasmHeadline<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmHeadline {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) level: HeadlineLevel,
pub(crate) tags: Vec<String>,
#[serde(rename = "todo-keyword")]
pub(crate) todo_keyword: Option<String>,
#[serde(rename = "todo-type")]
pub(crate) todo_type: Option<String>,
pub(crate) title: Vec<WasmAstNode>,
pub(crate) priority: Option<PriorityCookie>,
#[serde(rename = "archivedp")]
pub(crate) is_archived: bool,
#[serde(rename = "commentedp")]
pub(crate) is_comment: bool,
#[serde(rename = "raw-value")]
pub(crate) raw_value: String,
#[serde(rename = "footnote-section-p")]
pub(crate) is_footnote_section: bool,
pub(crate) scheduled: Option<Box<WasmAstNode>>,
pub(crate) deadline: Option<Box<WasmAstNode>>,
pub(crate) closed: Option<Box<WasmAstNode>>,
#[serde(rename = "pre-blank")]
pub(crate) pre_blank: Noop,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "noop")]
pub struct Noop {}
to_wasm!(
WasmHeadline<'s, 'p>,
WasmHeadline,
Heading<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Headline(original) },
{ "headline".into() },
{
Ok(WasmHeadline {
standard_properties,
children: Vec::new(),
})
let mut additional_properties = AdditionalProperties::default();
for (name, val) in original.get_additional_properties().map(|node_property| {
(
node_property.property_name.to_uppercase(),
AdditionalPropertyValue::SingleString(node_property.value.unwrap_or("").to_owned()),
)
}) {
additional_properties.properties.insert(name, val);
}
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmHeadline {
additional_properties,
level: original.level,
tags: original.tags.iter().map(|tag| (*tag).to_owned()).collect(),
todo_keyword: original
.todo_keyword
.as_ref()
.map(|(_, keyword)| (*keyword).to_owned()),
todo_type: original
.todo_keyword
.as_ref()
.map(|(keyword, _)| match keyword {
TodoKeywordType::Done => "done".to_owned(),
TodoKeywordType::Todo => "todo".to_owned(),
}),
title: original
.title
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?,
priority: original.priority_cookie,
is_archived: original.is_archived,
is_comment: original.is_comment,
raw_value: original.get_raw_value(),
is_footnote_section: original.is_footnote_section,
scheduled: original
.scheduled
.as_ref()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.map_or(Ok(None), |r| r.map(Some))?
.map(Box::new),
deadline: original
.deadline
.as_ref()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.map_or(Ok(None), |r| r.map(Some))?
.map(Box::new),
closed: original
.closed
.as_ref()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.map_or(Ok(None), |r| r.map(Some))?
.map(Box::new),
pre_blank: Noop {},
},
))
}
);
impl<'s, 'p> Into<WasmAstNode<'s, 'p>> for WasmHeadline<'s, 'p> {
fn into(self) -> WasmAstNode<'s, 'p> {
WasmAstNode::Headline(self)
}
}

View File

@@ -1,30 +1,38 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::GetAffiliatedKeywords;
use crate::types::HorizontalRule;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmHorizontalRule<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmHorizontalRule {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
}
to_wasm!(
WasmHorizontalRule<'s, 'p>,
WasmHorizontalRule,
HorizontalRule<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::HorizontalRule(original) },
{ "horizontal-rule".into() },
{
Ok(WasmHorizontalRule {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
Ok((
Vec::new(),
WasmHorizontalRule {
additional_properties,
},
))
}
);

View File

@@ -1,30 +1,41 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::InlineBabelCall;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmInlineBabelCall<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmInlineBabelCall {
pub(crate) call: String,
#[serde(rename = "inside-header")]
pub(crate) inside_header: Option<String>,
pub(crate) arguments: Option<String>,
#[serde(rename = "end-header")]
pub(crate) end_header: Option<String>,
pub(crate) value: String,
}
to_wasm!(
WasmInlineBabelCall<'s, 'p>,
WasmInlineBabelCall,
InlineBabelCall<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::InlineBabelCall(original) },
{ "inline-babel-call".into() },
{
Ok(WasmInlineBabelCall {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmInlineBabelCall {
call: original.call.to_owned(),
inside_header: original.inside_header.map(|s| s.to_owned()),
arguments: original.arguments.map(|s| s.to_owned()),
end_header: original.end_header.map(|s| s.to_owned()),
value: original.value.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,35 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::InlineSourceBlock;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmInlineSourceBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmInlineSourceBlock {
pub(crate) language: String,
pub(crate) value: String,
pub(crate) parameters: Option<String>,
}
to_wasm!(
WasmInlineSourceBlock<'s, 'p>,
WasmInlineSourceBlock,
InlineSourceBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::InlineSourceBlock(original) },
{ "inline-src-block".into() },
{
Ok(WasmInlineSourceBlock {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmInlineSourceBlock {
language: original.language.to_owned(),
value: original.value.to_owned(),
parameters: original.parameters.map(str::to_owned),
},
))
}
);

View File

@@ -1,30 +1,34 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Italic;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmItalic<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmItalic {}
to_wasm!(
WasmItalic<'s, 'p>,
WasmItalic,
Italic<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Italic(original) },
{ "italic".into() },
{
Ok(WasmItalic {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((children, WasmItalic {}))
}
);

View File

@@ -1,30 +1,42 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::GetAffiliatedKeywords;
use crate::types::Keyword;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmKeyword<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmKeyword {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) key: String,
pub(crate) value: String,
}
to_wasm!(
WasmKeyword<'s, 'p>,
WasmKeyword,
Keyword<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Keyword(original) },
{ "keyword".into() },
{
Ok(WasmKeyword {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
Ok((
Vec::new(),
WasmKeyword {
additional_properties,
key: original.key.to_uppercase(),
value: original.value.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,40 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::GetAffiliatedKeywords;
use crate::types::LatexEnvironment;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmLatexEnvironment<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmLatexEnvironment {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) value: String,
}
to_wasm!(
WasmLatexEnvironment<'s, 'p>,
WasmLatexEnvironment,
LatexEnvironment<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::LatexEnvironment(original) },
{ "latex-environment".into() },
{
Ok(WasmLatexEnvironment {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
Ok((
Vec::new(),
WasmLatexEnvironment {
additional_properties,
value: original.value.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,31 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::LatexFragment;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmLatexFragment<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmLatexFragment {
pub(crate) value: String,
}
to_wasm!(
WasmLatexFragment<'s, 'p>,
WasmLatexFragment,
LatexFragment<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::LatexFragment(original) },
{ "latex-fragment".into() },
{
Ok(WasmLatexFragment {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmLatexFragment {
value: original.value.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,22 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::LineBreak;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmLineBreak<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmLineBreak {}
to_wasm!(
WasmLineBreak<'s, 'p>,
WasmLineBreak,
LineBreak<'s>,
original,
wasm_context,
standard_properties,
{
Ok(WasmLineBreak {
standard_properties,
children: Vec::new(),
})
}
{ WasmAstNode::LineBreak(original) },
{ "line-break".into() },
{ Ok((Vec::new(), WasmLineBreak {},)) }
);

View File

@@ -2,21 +2,57 @@
///
/// This exists to make changing the type signature easier.
macro_rules! to_wasm {
($ostruct:ty, $istruct:ty, $original:ident, $wasm_context:ident, $standard_properties:ident, $fnbody:tt) => {
impl<'s, 'p> ToWasm<'p> for $istruct {
($ostruct:ty, $istruct:ty, $original:ident, $wasm_context:ident, $fnbody:tt) => {
impl<'s> ToWasm for $istruct {
type Output = $ostruct;
fn to_wasm(
&'p self,
&self,
$wasm_context: crate::wasm::to_wasm::ToWasmContext<'_>,
) -> Result<Self::Output, crate::error::CustomError> {
let $original = self;
let $standard_properties =
self.to_wasm_standard_properties($wasm_context.clone())?;
$fnbody
}
}
};
($ostruct:ty, $istruct:ty, $original:ident, $wasm_context:ident, $toastnodebody:tt, $elispnamebody:tt, $fnbody:tt) => {
impl<'s> ToWasm for $istruct {
type Output = crate::wasm::ast_node::WasmAstNodeWrapper<$ostruct>;
fn to_wasm(
&self,
$wasm_context: crate::wasm::to_wasm::ToWasmContext<'_>,
) -> Result<Self::Output, crate::error::CustomError> {
#[allow(unused_variables)]
let $original = self;
let standard_properties =
self.to_wasm_standard_properties($wasm_context.clone())?;
$fnbody.map(
|(children, inner)| crate::wasm::ast_node::WasmAstNodeWrapper {
ast_node: inner.get_elisp_name().into_owned(),
standard_properties,
children,
properties: inner,
},
)
}
}
impl From<crate::wasm::ast_node::WasmAstNodeWrapper<$ostruct>> for WasmAstNode {
fn from($original: crate::wasm::ast_node::WasmAstNodeWrapper<$ostruct>) -> Self {
let ret = $toastnodebody;
ret
}
}
impl<'s> crate::util::elisp_fact::ElispFact<'s> for $ostruct {
fn get_elisp_name<'b>(&'b self) -> std::borrow::Cow<'s, str> {
let ret = $elispnamebody;
ret
}
}
};
}
pub(crate) use to_wasm;

View File

@@ -1,3 +1,4 @@
mod additional_property;
mod angle_link;
mod ast_node;
mod babel_call;
@@ -62,8 +63,14 @@ mod underline;
mod verbatim;
mod verse_block;
pub use additional_property::AdditionalProperties;
pub use additional_property::AdditionalPropertyValue;
pub use ast_node::WasmAstNode;
#[cfg(feature = "wasm_test")]
pub use ast_node::WasmAstNodeWrapper;
#[cfg(feature = "wasm_test")]
pub use document::WasmDocument;
pub use parse_result::ParseResult;
pub(crate) use standard_properties::WasmStandardProperties;
pub use to_wasm::ToWasm;
pub use to_wasm::ToWasmContext;

View File

@@ -1,30 +1,33 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::NodeProperty;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmNodeProperty<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmNodeProperty {
pub(crate) key: String,
pub(crate) value: Option<String>,
}
to_wasm!(
WasmNodeProperty<'s, 'p>,
WasmNodeProperty,
NodeProperty<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::NodeProperty(original) },
{ "node-property".into() },
{
Ok(WasmNodeProperty {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmNodeProperty {
key: original.property_name.to_owned(),
value: original.value.map(|s| s.to_owned()),
},
))
}
);

View File

@@ -1,30 +1,35 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::OrgMacro;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmOrgMacro<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmOrgMacro {
pub(crate) key: String,
pub(crate) value: String,
pub(crate) args: Vec<String>,
}
to_wasm!(
WasmOrgMacro<'s, 'p>,
WasmOrgMacro,
OrgMacro<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::OrgMacro(original) },
{ "macro".into() },
{
Ok(WasmOrgMacro {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmOrgMacro {
key: original.key.to_lowercase(),
value: original.value.to_owned(),
args: original.get_args().map(|s| s.into_owned()).collect(),
},
))
}
);

View File

@@ -1,30 +1,48 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::GetAffiliatedKeywords;
use crate::types::Paragraph;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmParagraph<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmParagraph {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
}
to_wasm!(
WasmParagraph<'s, 'p>,
WasmParagraph,
Paragraph<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Paragraph(original) },
{ "paragraph".into() },
{
Ok(WasmParagraph {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmParagraph {
additional_properties,
},
))
}
);

View File

@@ -1,12 +1,14 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNodeWrapper;
use super::document::WasmDocument;
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "status", content = "content")]
pub enum ParseResult<'s, 'p> {
pub enum ParseResult {
#[serde(rename = "success")]
Success(WasmDocument<'s, 'p>),
Success(WasmAstNodeWrapper<WasmDocument>),
#[serde(rename = "error")]
Error(String),

View File

@@ -1,30 +1,52 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::LinkType;
use crate::types::PlainLink;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmPlainLink<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "format")]
#[serde(rename = "plain")]
pub struct WasmPlainLink {
#[serde(rename = "type")]
pub(crate) link_type: String,
pub(crate) path: String,
#[serde(rename = "raw-link")]
pub(crate) raw_link: String,
pub(crate) application: Option<String>,
#[serde(rename = "search-option")]
pub(crate) search_option: Option<String>,
}
to_wasm!(
WasmPlainLink<'s, 'p>,
WasmPlainLink,
PlainLink<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::PlainLink(original) },
{ "link".into() },
{
Ok(WasmPlainLink {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmPlainLink {
link_type: match &original.link_type {
LinkType::File => "file".to_owned(),
LinkType::Protocol(protocol) => protocol.clone().into_owned(),
LinkType::Id => "id".to_owned(),
LinkType::CustomId => "custom-id".to_owned(),
LinkType::CodeRef => "coderef".to_owned(),
LinkType::Fuzzy => "fuzzy".to_owned(),
},
path: original.path.to_owned(),
raw_link: original.raw_link.to_owned(),
application: original.application.map(str::to_owned),
search_option: original.search_option.map(str::to_owned),
},
))
}
);

View File

@@ -1,30 +1,57 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::GetAffiliatedKeywords;
use crate::types::PlainList;
use crate::types::PlainListType;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmPlainList<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmPlainList {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
#[serde(rename = "type")]
pub(crate) list_type: String,
}
to_wasm!(
WasmPlainList<'s, 'p>,
WasmPlainList,
PlainList<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::PlainList(original) },
{ "plain-list".into() },
{
Ok(WasmPlainList {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmPlainList {
additional_properties,
list_type: match original.list_type {
PlainListType::Unordered => "unordered",
PlainListType::Ordered => "ordered",
PlainListType::Descriptive => "descriptive",
}
.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,68 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::CheckboxType;
use crate::types::PlainListItem;
use crate::types::PlainListItemCounter;
use crate::types::PlainListItemPreBlank;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmPlainListItem<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmPlainListItem {
pub(crate) tag: Vec<WasmAstNode>,
pub(crate) bullet: String,
pub(crate) counter: Option<PlainListItemCounter>,
pub(crate) checkbox: Option<String>,
#[serde(rename = "pre-blank")]
pub(crate) pre_blank: PlainListItemPreBlank,
}
to_wasm!(
WasmPlainListItem<'s, 'p>,
WasmPlainListItem,
PlainListItem<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::PlainListItem(original) },
{ "item".into() },
{
Ok(WasmPlainListItem {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmPlainListItem {
tag: original
.tag
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?,
bullet: original.bullet.to_owned(),
counter: original.counter,
checkbox: original.checkbox.as_ref().map(|(checkbox_type, _)| {
match checkbox_type {
CheckboxType::On => "on",
CheckboxType::Trans => "trans",
CheckboxType::Off => "off",
}
.to_owned()
}),
pre_blank: original.pre_blank,
},
))
}
);

View File

@@ -1,30 +1,22 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::PlainText;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmPlainText<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmPlainText {}
to_wasm!(
WasmPlainText<'s, 'p>,
WasmPlainText,
PlainText<'s>,
original,
wasm_context,
standard_properties,
{
Ok(WasmPlainText {
standard_properties,
children: Vec::new(),
})
}
{ WasmAstNode::PlainText(original) },
{ "plain-text".into() },
{ Ok((Vec::new(), WasmPlainText {},)) }
);

View File

@@ -1,30 +1,62 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Planning;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmPlanning<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmPlanning {
pub(crate) scheduled: Option<Box<WasmAstNode>>,
pub(crate) deadline: Option<Box<WasmAstNode>>,
pub(crate) closed: Option<Box<WasmAstNode>>,
}
to_wasm!(
WasmPlanning<'s, 'p>,
WasmPlanning,
Planning<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Planning(original) },
{ "planning".into() },
{
Ok(WasmPlanning {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmPlanning {
scheduled: original
.scheduled
.as_ref()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.map_or(Ok(None), |r| r.map(Some))?
.map(Box::new),
deadline: original
.deadline
.as_ref()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.map_or(Ok(None), |r| r.map(Some))?
.map(Box::new),
closed: original
.closed
.as_ref()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.map_or(Ok(None), |r| r.map(Some))?
.map(Box::new),
},
))
}
);

View File

@@ -1,30 +1,34 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::PropertyDrawer;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmPropertyDrawer<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmPropertyDrawer {}
to_wasm!(
WasmPropertyDrawer<'s, 'p>,
WasmPropertyDrawer,
PropertyDrawer<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::PropertyDrawer(original) },
{ "property-drawer".into() },
{
Ok(WasmPropertyDrawer {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((children, WasmPropertyDrawer {}))
}
);

View File

@@ -1,30 +1,48 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::GetAffiliatedKeywords;
use crate::types::QuoteBlock;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmQuoteBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmQuoteBlock {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
}
to_wasm!(
WasmQuoteBlock<'s, 'p>,
WasmQuoteBlock,
QuoteBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::QuoteBlock(original) },
{ "quote-block".into() },
{
Ok(WasmQuoteBlock {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmQuoteBlock {
additional_properties,
},
))
}
);

View File

@@ -1,30 +1,54 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::RadioLink;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmRadioLink<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "format")]
#[serde(rename = "plain")]
pub struct WasmRadioLink {
#[serde(rename = "type")]
pub(crate) link_type: String,
pub(crate) path: String,
#[serde(rename = "raw-link")]
pub(crate) raw_link: String,
pub(crate) application: Option<String>, // Always None
#[serde(rename = "search-option")]
pub(crate) search_option: Option<String>, // Always None
}
to_wasm!(
WasmRadioLink<'s, 'p>,
WasmRadioLink,
RadioLink<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::RadioLink(original) },
{ "link".into() },
{
Ok(WasmRadioLink {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmRadioLink {
link_type: "radio".to_owned(),
path: original.path.to_owned(),
raw_link: original.get_raw_link().to_owned(),
application: None,
search_option: None,
},
))
}
);

View File

@@ -1,30 +1,41 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::RadioTarget;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmRadioTarget<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmRadioTarget {
pub(crate) value: String,
}
to_wasm!(
WasmRadioTarget<'s, 'p>,
WasmRadioTarget,
RadioTarget<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::RadioTarget(original) },
{ "radio-target".into() },
{
Ok(WasmRadioTarget {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmRadioTarget {
value: original.value.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,67 @@
use std::borrow::Cow;
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::LinkType;
use crate::types::RegularLink;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmRegularLink<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "format")]
#[serde(rename = "bracket")]
pub struct WasmRegularLink {
#[serde(rename = "type")]
pub(crate) link_type: String,
pub(crate) path: String,
#[serde(rename = "raw-link")]
pub(crate) raw_link: String,
pub(crate) application: Option<String>,
#[serde(rename = "search-option")]
pub(crate) search_option: Option<String>,
}
to_wasm!(
WasmRegularLink<'s, 'p>,
WasmRegularLink,
RegularLink<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::RegularLink(original) },
{ "link".into() },
{
Ok(WasmRegularLink {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmRegularLink {
link_type: match &original.link_type {
LinkType::File => "file".to_owned(),
LinkType::Protocol(protocol) => protocol.clone().into_owned(),
LinkType::Id => "id".to_owned(),
LinkType::CustomId => "custom-id".to_owned(),
LinkType::CodeRef => "coderef".to_owned(),
LinkType::Fuzzy => "fuzzy".to_owned(),
},
path: original.get_path().into_owned(),
raw_link: original.get_raw_link().into_owned(),
application: original
.application
.as_ref()
.map(|c| c.clone().into_owned()),
search_option: original.get_search_option().map(Cow::into_owned),
},
))
}
);

View File

@@ -1,36 +1,34 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Section;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "section")]
pub struct WasmSection<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmSection {}
to_wasm!(
WasmSection<'s, 'p>,
WasmSection,
Section<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Section(original) },
{ "section".into() },
{
Ok(WasmSection {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((children, WasmSection {}))
}
);
impl<'s, 'p> Into<WasmAstNode<'s, 'p>> for WasmSection<'s, 'p> {
fn into(self) -> WasmAstNode<'s, 'p> {
WasmAstNode::Section(self)
}
}

View File

@@ -1,30 +1,56 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::headline::Noop;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::GetAffiliatedKeywords;
use crate::types::SpecialBlock;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmSpecialBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmSpecialBlock {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
#[serde(rename = "type")]
pub(crate) block_type: String,
pub(crate) parameters: Option<String>,
pub(crate) results: Noop,
}
to_wasm!(
WasmSpecialBlock<'s, 'p>,
WasmSpecialBlock,
SpecialBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::SpecialBlock(original) },
{ "special-block".into() },
{
Ok(WasmSpecialBlock {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmSpecialBlock {
additional_properties,
block_type: original.block_type.to_owned(),
parameters: original.parameters.map(|s| s.to_owned()),
results: Noop {},
},
))
}
);

View File

@@ -1,30 +1,100 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::CharOffsetInLine;
use crate::types::GetAffiliatedKeywords;
use crate::types::LineNumber;
use crate::types::RetainLabels;
use crate::types::SrcBlock;
use crate::types::SwitchNumberLines;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmSrcBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmSrcBlock {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
pub(crate) language: Option<String>,
pub(crate) value: String,
pub(crate) switches: Option<String>,
pub(crate) parameters: Option<String>,
#[serde(rename = "number-lines")]
pub(crate) number_lines: Option<WasmNumberLinesWrapper>,
#[serde(rename = "preserve-indent")]
pub(crate) preserve_indent: Option<CharOffsetInLine>,
#[serde(rename = "retain-labels")]
pub(crate) retain_labels: WasmRetainLabels,
#[serde(rename = "use-labels")]
pub(crate) use_labels: bool,
#[serde(rename = "label-fmt")]
pub(crate) label_format: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub(crate) enum WasmRetainLabels {
YesNo(bool),
Keep(CharOffsetInLine),
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) enum WasmNumberLines {
#[serde(rename = "new")]
New(LineNumber),
#[serde(rename = "continued")]
Continued(LineNumber),
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename = "number-lines")]
#[serde(tag = "number-lines")]
pub(crate) struct WasmNumberLinesWrapper {
#[serde(flatten)]
pub(crate) inner: WasmNumberLines,
}
to_wasm!(
WasmSrcBlock<'s, 'p>,
WasmSrcBlock,
SrcBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::SrcBlock(original) },
{ "src-block".into() },
{
Ok(WasmSrcBlock {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
Ok((
Vec::new(),
WasmSrcBlock {
additional_properties,
language: original.language.map(|s| s.to_owned()),
value: original.get_value().into_owned(),
switches: original.switches.map(|s| s.to_owned()),
parameters: original.parameters.map(|s| s.to_owned()),
number_lines: match original.number_lines {
None => None,
Some(SwitchNumberLines::New(n)) => Some(WasmNumberLinesWrapper {
inner: WasmNumberLines::New(n),
}),
Some(SwitchNumberLines::Continued(n)) => Some(WasmNumberLinesWrapper {
inner: WasmNumberLines::Continued(n),
}),
},
preserve_indent: original.preserve_indent,
retain_labels: match original.retain_labels {
RetainLabels::No => WasmRetainLabels::YesNo(false),
RetainLabels::Yes => WasmRetainLabels::YesNo(true),
RetainLabels::Keep(n) => WasmRetainLabels::Keep(n),
},
use_labels: original.use_labels,
label_format: original.label_format.map(|s| s.to_owned()),
},
))
}
);

View File

@@ -1,3 +1,4 @@
use serde::Deserialize;
use serde::Serialize;
use super::to_wasm::ToWasmContext;
@@ -5,13 +6,16 @@ use super::to_wasm::ToWasmStandardProperties;
use crate::types::PostBlank;
use crate::types::StandardProperties;
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct WasmStandardProperties {
begin: usize,
end: usize,
contents_begin: Option<usize>,
contents_end: Option<usize>,
post_blank: PostBlank,
pub(crate) begin: usize,
pub(crate) end: usize,
#[serde(rename = "contents-begin")]
pub(crate) contents_begin: Option<usize>,
#[serde(rename = "contents-end")]
pub(crate) contents_end: Option<usize>,
#[serde(rename = "post-blank")]
pub(crate) post_blank: PostBlank,
}
impl<'s, SP: StandardProperties<'s>> ToWasmStandardProperties for SP {

View File

@@ -1,30 +1,31 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::StatisticsCookie;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmStatisticsCookie<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmStatisticsCookie {
pub(crate) value: String,
}
to_wasm!(
WasmStatisticsCookie<'s, 'p>,
WasmStatisticsCookie,
StatisticsCookie<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::StatisticsCookie(original) },
{ "statistics-cookie".into() },
{
Ok(WasmStatisticsCookie {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmStatisticsCookie {
value: original.value.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,34 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::StrikeThrough;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmStrikeThrough<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmStrikeThrough {}
to_wasm!(
WasmStrikeThrough<'s, 'p>,
WasmStrikeThrough,
StrikeThrough<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::StrikeThrough(original) },
{ "strike-through".into() },
{
Ok(WasmStrikeThrough {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((children, WasmStrikeThrough {}))
}
);

View File

@@ -1,30 +1,42 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Subscript;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmSubscript<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmSubscript {
#[serde(rename = "use-brackets-p")]
pub(crate) use_brackets: bool,
}
to_wasm!(
WasmSubscript<'s, 'p>,
WasmSubscript,
Subscript<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Subscript(original) },
{ "subscript".into() },
{
Ok(WasmSubscript {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmSubscript {
use_brackets: original.use_brackets,
},
))
}
);

View File

@@ -1,30 +1,42 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Superscript;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmSuperscript<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmSuperscript {
#[serde(rename = "use-brackets-p")]
pub(crate) use_brackets: bool,
}
to_wasm!(
WasmSuperscript<'s, 'p>,
WasmSuperscript,
Superscript<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Superscript(original) },
{ "superscript".into() },
{
Ok(WasmSuperscript {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmSuperscript {
use_brackets: original.use_brackets,
},
))
}
);

View File

@@ -1,30 +1,75 @@
use std::collections::BTreeSet;
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::GetAffiliatedKeywords;
use crate::types::Table;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmTable<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmTable {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
#[serde(rename = "tblfm")]
pub(crate) formulas: Option<WasmStringSet>,
#[serde(rename = "type")]
pub(crate) table_type: String,
pub(crate) value: Option<String>, // Always None
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "string-set")]
#[serde(rename = "string-set")]
pub(crate) struct WasmStringSet {
value: BTreeSet<String>,
}
to_wasm!(
WasmTable<'s, 'p>,
WasmTable,
Table<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Table(original) },
{ "table".into() },
{
Ok(WasmTable {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmTable {
additional_properties,
formulas: if original.formulas.is_empty() {
None
} else {
Some(WasmStringSet {
value: original
.formulas
.iter()
.map(|kw| kw.value.to_owned())
.collect(),
})
},
table_type: "org".to_owned(),
value: None,
},
))
}
);

View File

@@ -1,30 +1,34 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::TableCell;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmTableCell<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmTableCell {}
to_wasm!(
WasmTableCell<'s, 'p>,
WasmTableCell,
TableCell<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::TableCell(original) },
{ "table-cell".into() },
{
Ok(WasmTableCell {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((children, WasmTableCell {}))
}
);

View File

@@ -1,30 +1,47 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::TableRow;
use crate::types::TableRowType;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmTableRow<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmTableRow {
#[serde(rename = "type")]
pub(crate) row_type: String,
}
to_wasm!(
WasmTableRow<'s, 'p>,
WasmTableRow,
TableRow<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::TableRow(original) },
{ "table-row".into() },
{
Ok(WasmTableRow {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmTableRow {
row_type: match original.get_type() {
TableRowType::Standard => "standard",
TableRowType::Rule => "rule",
}
.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,31 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Target;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmTarget<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmTarget {
pub(crate) value: String,
}
to_wasm!(
WasmTarget<'s, 'p>,
WasmTarget,
Target<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Target(original) },
{ "target".into() },
{
Ok(WasmTarget {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmTarget {
value: original.value.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,146 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::DayOfMonthInner;
use crate::types::HourInner;
use crate::types::MinuteInner;
use crate::types::MonthInner;
use crate::types::RepeaterType;
use crate::types::RepeaterWarningDelayValueType;
use crate::types::TimeUnit;
use crate::types::Timestamp;
use crate::types::TimestampRangeType;
use crate::types::TimestampType;
use crate::types::WarningDelayType;
use crate::types::YearInner;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmTimestamp<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmTimestamp {
#[serde(rename = "type")]
pub(crate) timestamp_type: String,
#[serde(rename = "range-type")]
pub(crate) range_type: Option<String>,
#[serde(rename = "raw-value")]
pub(crate) raw_value: String,
#[serde(rename = "year-start")]
pub(crate) year_start: Option<YearInner>,
#[serde(rename = "month-start")]
pub(crate) month_start: Option<MonthInner>,
#[serde(rename = "day-start")]
pub(crate) day_of_month_start: Option<DayOfMonthInner>,
#[serde(rename = "hour-start")]
pub(crate) hour_start: Option<HourInner>,
#[serde(rename = "minute-start")]
pub(crate) minute_start: Option<MinuteInner>,
#[serde(rename = "year-end")]
pub(crate) year_end: Option<YearInner>,
#[serde(rename = "month-end")]
pub(crate) month_end: Option<MonthInner>,
#[serde(rename = "day-end")]
pub(crate) day_of_month_end: Option<DayOfMonthInner>,
#[serde(rename = "hour-end")]
pub(crate) hour_end: Option<HourInner>,
#[serde(rename = "minute-end")]
pub(crate) minute_end: Option<MinuteInner>,
#[serde(rename = "repeater-type")]
pub(crate) repeater_type: Option<String>,
#[serde(rename = "repeater-unit")]
pub(crate) repeater_unit: Option<String>,
#[serde(rename = "repeater-value")]
pub(crate) repeater_value: Option<RepeaterWarningDelayValueType>,
#[serde(rename = "warning-type")]
pub(crate) warning_type: Option<String>,
#[serde(rename = "warning-unit")]
pub(crate) warning_unit: Option<String>,
#[serde(rename = "warning-value")]
pub(crate) warning_value: Option<RepeaterWarningDelayValueType>,
}
to_wasm!(
WasmTimestamp<'s, 'p>,
WasmTimestamp,
Timestamp<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Timestamp(original) },
{ "timestamp".into() },
{
Ok(WasmTimestamp {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmTimestamp {
timestamp_type: match original.timestamp_type {
TimestampType::Diary => "diary",
TimestampType::Active => "active",
TimestampType::Inactive => "inactive",
TimestampType::ActiveRange => "active-range",
TimestampType::InactiveRange => "inactive-range",
}
.to_owned(),
range_type: match original.range_type {
TimestampRangeType::DateRange => Some("daterange".to_owned()),
TimestampRangeType::TimeRange => Some("timerange".to_owned()),
TimestampRangeType::None => None,
},
raw_value: original.get_raw_value().to_owned(),
year_start: original.start.as_ref().map(|date| date.get_year().0),
month_start: original.start.as_ref().map(|date| date.get_month().0),
day_of_month_start: original
.start
.as_ref()
.map(|date| date.get_day_of_month().0),
hour_start: original.start_time.as_ref().map(|time| time.get_hour().0),
minute_start: original.start_time.as_ref().map(|time| time.get_minute().0),
year_end: original.end.as_ref().map(|date| date.get_year().0),
month_end: original.end.as_ref().map(|date| date.get_month().0),
day_of_month_end: original.end.as_ref().map(|date| date.get_day_of_month().0),
hour_end: original.end_time.as_ref().map(|time| time.get_hour().0),
minute_end: original.end_time.as_ref().map(|time| time.get_minute().0),
repeater_type: original
.repeater
.as_ref()
.map(|repeater| match repeater.repeater_type {
RepeaterType::Cumulative => "cumulate",
RepeaterType::CatchUp => "catch-up",
RepeaterType::Restart => "restart",
})
.map(|text| text.to_owned()),
repeater_unit: original
.repeater
.as_ref()
.map(|repeater| match repeater.unit {
TimeUnit::Hour => "hour",
TimeUnit::Day => "day",
TimeUnit::Week => "week",
TimeUnit::Month => "month",
TimeUnit::Year => "year",
})
.map(|text| text.to_owned()),
repeater_value: original.repeater.as_ref().map(|repeater| repeater.value),
warning_type: original
.warning_delay
.as_ref()
.map(|warning| match warning.warning_delay_type {
WarningDelayType::All => "all",
WarningDelayType::First => "first",
})
.map(|text| text.to_owned()),
warning_unit: original
.warning_delay
.as_ref()
.map(|warning| match warning.unit {
TimeUnit::Hour => "hour",
TimeUnit::Day => "day",
TimeUnit::Week => "week",
TimeUnit::Month => "month",
TimeUnit::Year => "year",
})
.map(|text| text.to_owned()),
warning_value: original.warning_delay.as_ref().map(|warning| warning.value),
},
))
}
);

View File

@@ -1,9 +1,14 @@
use super::macros::to_wasm;
use super::WasmAstNode;
use crate::error::CustomError;
use crate::types::DocumentElement;
use crate::types::Element;
use crate::types::Object;
pub trait ToWasm<'p> {
pub trait ToWasm {
type Output;
fn to_wasm(&'p self, full_document: ToWasmContext<'_>) -> Result<Self::Output, CustomError>;
fn to_wasm(&self, full_document: ToWasmContext<'_>) -> Result<Self::Output, CustomError>;
}
pub(crate) trait ToWasmStandardProperties {
@@ -25,3 +30,95 @@ impl<'s> ToWasmContext<'s> {
ToWasmContext { full_document }
}
}
to_wasm!(WasmAstNode, DocumentElement<'s>, original, wasm_context, {
match original {
DocumentElement::Heading(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
DocumentElement::Section(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
}
});
to_wasm!(WasmAstNode, Element<'s>, original, wasm_context, {
match original {
Element::Paragraph(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::PlainList(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::CenterBlock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::QuoteBlock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::SpecialBlock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::DynamicBlock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::FootnoteDefinition(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
Element::Comment(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::Drawer(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::PropertyDrawer(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
Element::Table(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::VerseBlock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::CommentBlock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::ExampleBlock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::ExportBlock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::SrcBlock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::Clock(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::DiarySexp(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::Planning(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::FixedWidthArea(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
Element::HorizontalRule(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
Element::Keyword(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::BabelCall(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Element::LatexEnvironment(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
}
});
to_wasm!(WasmAstNode, Object<'s>, original, wasm_context, {
match original {
Object::Bold(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::Italic(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::Underline(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::StrikeThrough(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::Code(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::Verbatim(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::PlainText(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::RegularLink(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::RadioLink(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::RadioTarget(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::PlainLink(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::AngleLink(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::OrgMacro(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::Entity(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::LatexFragment(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::ExportSnippet(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::FootnoteReference(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
Object::Citation(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::CitationReference(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
Object::InlineBabelCall(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
Object::InlineSourceBlock(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
Object::LineBreak(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::Target(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::StatisticsCookie(inner) => {
inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into)
}
Object::Subscript(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::Superscript(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
Object::Timestamp(inner) => inner.to_wasm(wasm_context).map(Into::<WasmAstNode>::into),
}
});

View File

@@ -1,30 +1,34 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Underline;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmUnderline<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmUnderline {}
to_wasm!(
WasmUnderline<'s, 'p>,
WasmUnderline,
Underline<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Underline(original) },
{ "underline".into() },
{
Ok(WasmUnderline {
standard_properties,
children: Vec::new(),
})
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((children, WasmUnderline {}))
}
);

View File

@@ -1,30 +1,31 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use crate::types::Verbatim;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmVerbatim<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmVerbatim {
pub(crate) value: String,
}
to_wasm!(
WasmVerbatim<'s, 'p>,
WasmVerbatim,
Verbatim<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::Verbatim(original) },
{ "verbatim".into() },
{
Ok(WasmVerbatim {
standard_properties,
children: Vec::new(),
})
Ok((
Vec::new(),
WasmVerbatim {
value: original.contents.to_owned(),
},
))
}
);

View File

@@ -1,30 +1,48 @@
use serde::Deserialize;
use serde::Serialize;
use super::ast_node::WasmAstNode;
use super::macros::to_wasm;
use super::standard_properties::WasmStandardProperties;
use super::to_wasm::ToWasm;
use super::AdditionalProperties;
use crate::types::GetAffiliatedKeywords;
use crate::types::VerseBlock;
use crate::util::elisp_fact::ElispFact;
use crate::wasm::to_wasm::ToWasmStandardProperties;
use crate::wasm::WasmAstNode;
#[derive(Debug, Serialize)]
#[serde(tag = "ast_node")]
#[serde(rename = "org-data")]
pub struct WasmVerseBlock<'s, 'p> {
standard_properties: WasmStandardProperties,
children: Vec<WasmAstNode<'s, 'p>>,
#[derive(Debug, Serialize, Deserialize)]
pub struct WasmVerseBlock {
#[serde(flatten)]
pub(crate) additional_properties: AdditionalProperties,
}
to_wasm!(
WasmVerseBlock<'s, 'p>,
WasmVerseBlock,
VerseBlock<'s>,
original,
wasm_context,
standard_properties,
{ WasmAstNode::VerseBlock(original) },
{ "verse-block".into() },
{
Ok(WasmVerseBlock {
standard_properties,
children: Vec::new(),
})
let additional_properties = original
.get_affiliated_keywords()
.to_wasm(wasm_context.clone())?;
let children = original
.children
.iter()
.map(|child| {
child
.to_wasm(wasm_context.clone())
.map(Into::<WasmAstNode>::into)
})
.collect::<Result<Vec<_>, _>>()?;
Ok((
children,
WasmVerseBlock {
additional_properties,
},
))
}
);

24
src/wasm_cli/mod.rs Normal file
View File

@@ -0,0 +1,24 @@
use crate::parser::parse_with_settings;
use crate::settings::GlobalSettings;
use crate::wasm::ParseResult;
use crate::wasm::ToWasm;
use crate::wasm::ToWasmContext;
pub fn parse_org(org_contents: &str) -> wasm_bindgen::JsValue {
let rust_parsed = match parse_with_settings(org_contents, &GlobalSettings::default()) {
Ok(document) => document,
Err(err) => {
return serde_wasm_bindgen::to_value(&ParseResult::Error(format!("{:?}", err)))
.unwrap();
}
};
let to_wasm_context = ToWasmContext::new(org_contents);
let wasm_document = match rust_parsed.to_wasm(to_wasm_context) {
Ok(document) => document,
Err(err) => {
return serde_wasm_bindgen::to_value(&ParseResult::Error(format!("{:?}", err)))
.unwrap();
}
};
serde_wasm_bindgen::to_value(&ParseResult::Success(wasm_document)).unwrap()
}

File diff suppressed because it is too large Load Diff

109
src/wasm_test/diff.rs Normal file
View File

@@ -0,0 +1,109 @@
use std::borrow::Cow;
use crate::util::terminal::foreground_color;
use crate::util::terminal::reset_color;
#[derive(Debug)]
pub struct WasmDiffResult<'s> {
pub(crate) status: Vec<WasmDiffStatus>,
pub(crate) name: Cow<'s, str>,
pub(crate) children: Vec<WasmDiffResult<'s>>,
}
#[derive(Debug)]
pub(crate) enum WasmDiffStatus {
#[allow(dead_code)]
Good,
Bad(Cow<'static, str>),
}
impl<'s> WasmDiffResult<'s> {
pub(crate) fn extend(
&mut self,
other: WasmDiffResult<'s>,
) -> Result<&mut WasmDiffResult<'s>, Box<dyn std::error::Error>> {
if self.name.is_empty() {
self.name = other.name;
}
self.status.extend(other.status);
self.children.extend(other.children);
Ok(self)
}
pub fn is_bad(&self) -> bool {
self.is_self_bad() || self.has_bad_children()
}
pub fn is_self_bad(&self) -> bool {
self.status
.iter()
.any(|status| matches!(status, WasmDiffStatus::Bad(_)))
}
pub fn has_bad_children(&self) -> bool {
self.children.iter().any(WasmDiffResult::is_bad)
}
pub fn print(&self, original_document: &str) -> Result<(), Box<dyn std::error::Error>> {
self.print_indented(0, original_document)
}
fn print_indented(
&self,
indentation: usize,
_original_document: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let status_text = {
if self.is_self_bad() {
format!(
"{color}BAD{reset}",
color = foreground_color(255, 0, 0),
reset = reset_color(),
)
} else if self.has_bad_children() {
format!(
"{color}BADCHILD{reset}",
color = foreground_color(255, 255, 0),
reset = reset_color(),
)
} else {
format!(
"{color}GOOD{reset}",
color = foreground_color(0, 255, 0),
reset = reset_color(),
)
}
};
let message = self
.status
.iter()
.filter_map(|status| match status {
WasmDiffStatus::Good => None,
WasmDiffStatus::Bad(message) => Some(message),
})
.next();
println!(
"{indentation}{status_text} {name} {message}",
indentation = " ".repeat(indentation),
status_text = status_text,
name = self.name,
message = message.unwrap_or(&Cow::Borrowed(""))
);
for child in self.children.iter() {
child.print_indented(indentation + 1, _original_document)?;
}
Ok(())
}
}
impl<'s> Default for WasmDiffResult<'s> {
fn default() -> Self {
WasmDiffResult {
status: Vec::new(),
name: "".into(),
children: Vec::new(),
}
}
}

View File

@@ -1,10 +0,0 @@
use super::compare::WasmDiffResult;
use crate::compare::Token;
pub trait WasmElispCompare<'s, 'p> {
fn compare_ast_node<'b>(
&self,
source: &'s str,
emacs: &'b Token<'s>,
) -> Result<WasmDiffResult<'s>, Box<dyn std::error::Error>>;
}

View File

@@ -1,101 +0,0 @@
macro_rules! wasm_compare {
($source:expr, $emacs:expr, $wasm:expr, $(($emacs_field:expr, $wasm_value_getter:expr, $compare_fn: expr)),*) => {{
let mut result = WasmDiffResult::default();
let emacs_list = $emacs.as_list()?;
let mut emacs_list_iter = emacs_list.iter();
let emacs_name = emacs_list_iter
.next()
.ok_or("Should have an attributes child.")?
.as_atom()?;
let emacs_attributes_map = emacs_list_iter
.next()
.ok_or("Should have an attributes child.")?
.as_map()?;
let mut emacs_keys: std::collections::BTreeSet<&str> =
emacs_attributes_map.keys().map(|s| *s).collect();
{
// Compare name.
let wasm_name = $wasm.get_elisp_name();
if emacs_name != wasm_name {
result.status.push(WasmDiffStatus::Bad(
format!(
"AST node name mismatch. Emacs=({emacs}) Wasm=({wasm}).",
emacs = emacs_name,
wasm = wasm_name,
)
.into(),
));
}
}
{
// Compare children.
result.extend(wasm_compare_list(
$source,
emacs_list_iter,
$wasm.children.iter(),
)?)?;
}
{
// Check for properties that are missing from the elisp node.
$(
match $emacs_field {
EmacsField::Required(name) if emacs_keys.contains(name) => {
emacs_keys.remove(name);
}
EmacsField::Optional(name) if emacs_keys.contains(name) => {
emacs_keys.remove(name);
}
EmacsField::Required(name) => {
result.status.push(WasmDiffStatus::Bad(
format!(
"Emacs node lacked required field ({name}).",
name = name,
)
.into(),
));
}
EmacsField::Optional(_name) => {}
}
)*
}
{
// Check for elisp properties that were not compared.
if !emacs_keys.is_empty() {
let unexpected_keys: Vec<&str> = emacs_keys.into_iter().collect();
let unexpected_keys = unexpected_keys.join(", ");
result.status.push(WasmDiffStatus::Bad(
format!(
"Emacs node had extra field(s): ({field_names}).",
field_names = unexpected_keys,
)
.into(),
));
}
}
{
// Compare properties.
$(
let emacs_name = match $emacs_field {
EmacsField::Required(name) => {
name
},
EmacsField::Optional(name) => {
name
},
};
let result = $compare_fn($source, $emacs, $wasm, emacs_name, $wasm_value_getter)?;
// TODO: record this result.
)*
}
result
}};
}
pub(crate) use wasm_compare;

View File

@@ -1,7 +1,8 @@
mod compare;
mod elisp_compare;
mod macros;
mod diff;
mod runner;
pub use runner::wasm_run_anonymous_compare;
pub use runner::wasm_run_anonymous_compare_with_settings;
pub use runner::wasm_run_compare_on_file;
pub use runner::wasm_run_compare_on_file_with_settings;

View File

@@ -1,11 +1,16 @@
use std::path::Path;
use super::compare::wasm_compare_document;
use crate::compare::sexp;
use crate::context::GlobalSettings;
use crate::parser::parse_file_with_settings;
use crate::parser::parse_with_settings;
use crate::util::emacs_parse_anonymous_org_document;
use crate::util::foreground_color;
use crate::util::print_versions;
use crate::util::reset_color;
use crate::settings::LocalFileAccessInterface;
use crate::util::cli::emacs_parse_anonymous_org_document;
use crate::util::cli::emacs_parse_file_org_document;
use crate::util::cli::print_versions;
use crate::util::elisp::sexp;
use crate::util::terminal::foreground_color;
use crate::util::terminal::reset_color;
use crate::wasm::ToWasm;
use crate::wasm::ToWasmContext;
@@ -42,7 +47,72 @@ pub async fn wasm_run_anonymous_compare_with_settings<'g, 's, P: AsRef<str>>(
}
// We do the diffing after printing out both parsed forms in case the diffing panics
let diff_result = wasm_compare_document(org_contents, &parsed_sexp, wasm_parsed)?;
let diff_result = wasm_compare_document(org_contents, &parsed_sexp, &wasm_parsed)?;
if !silent {
diff_result.print(org_contents)?;
}
if diff_result.is_bad() {
return Ok(false);
} else if !silent {
println!(
"{color}Entire document passes.{reset}",
color = foreground_color(0, 255, 0),
reset = reset_color(),
);
}
Ok(true)
}
//wasm_run_compare_on_file
pub async fn wasm_run_compare_on_file<P: AsRef<Path>>(
org_path: P,
) -> Result<bool, Box<dyn std::error::Error>> {
wasm_run_compare_on_file_with_settings(org_path, &GlobalSettings::default(), false).await
}
pub async fn wasm_run_compare_on_file_with_settings<'g, 's, P: AsRef<Path>>(
org_path: P,
global_settings: &GlobalSettings<'g, 's>,
silent: bool,
) -> Result<bool, Box<dyn std::error::Error>> {
let org_path = org_path.as_ref();
if !silent {
print_versions().await?;
}
let parent_directory = org_path
.parent()
.ok_or("Should be contained inside a directory.")?;
let org_contents = std::fs::read_to_string(org_path)?;
// TODO: This is a work-around to pretend that dos line endings do not exist. It would be better to handle the difference in line endings.
let org_contents = org_contents.replace("\r\n", "\n");
let org_contents = org_contents.as_str();
let file_access_interface = LocalFileAccessInterface {
working_directory: Some(parent_directory.to_path_buf()),
};
let global_settings = {
let mut global_settings = global_settings.clone();
global_settings.file_access = &file_access_interface;
global_settings
};
let rust_parsed = parse_file_with_settings(org_contents, &global_settings, Some(org_path))?;
let to_wasm_context = ToWasmContext::new(org_contents);
let wasm_parsed = rust_parsed
.to_wasm(to_wasm_context)
.map_err(|_e| "Failed to convert to wasm.")?;
let org_sexp = emacs_parse_file_org_document(org_path, &global_settings).await?;
let (_remaining, parsed_sexp) = sexp(org_sexp.as_str()).map_err(|e| e.to_string())?;
if !silent {
println!("{}\n\n\n", org_contents);
println!("{}", org_sexp);
println!("{:#?}", rust_parsed);
println!("{}", serde_json::to_string(&wasm_parsed)?);
}
// We do the diffing after printing out both parsed forms in case the diffing panics
let diff_result = wasm_compare_document(org_contents, &parsed_sexp, &wasm_parsed)?;
if !silent {
diff_result.print(org_contents)?;
}

View File

@@ -60,3 +60,13 @@ async fn autogen_odd_{name}() -> Result<(), Box<dyn std::error::Error>> {{
assert!(organic::compare::run_anonymous_compare_with_settings(org_contents.as_str(), &global_settings, false).await?);
Ok(())
}}
#[cfg(feature = "wasm_test")]
{expect_fail}
#[tokio::test]
async fn autogen_wasm_{name}() -> Result<(), Box<dyn std::error::Error>> {{
let org_path = "{path}";
let org_contents = std::fs::read_to_string(org_path).expect("Read org file.");
assert!(organic::wasm_test::wasm_run_anonymous_compare(org_contents.as_str()).await?);
Ok(())
}}