From 0d2a13739a2ddb1da3592c7b1e6a7381af0020ee Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Thu, 17 Aug 2023 03:25:12 -0400 Subject: [PATCH] Import the emacs wrapper from organic. --- src/main.rs | 3 +++ src/parse.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/parse.rs diff --git a/src/main.rs b/src/main.rs index b3cafd2..b20b551 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,10 @@ +#![feature(exit_status_error)] use axum::{http::StatusCode, routing::post, Json, Router}; use serde::Serialize; use tower_http::services::{ServeDir, ServeFile}; +mod parse; + #[tokio::main] async fn main() { let serve_dir = ServeDir::new("static").not_found_service(ServeFile::new("static/index.html")); diff --git a/src/parse.rs b/src/parse.rs new file mode 100644 index 0000000..bce786e --- /dev/null +++ b/src/parse.rs @@ -0,0 +1,51 @@ +use std::process::Command; + +pub fn emacs_parse_org_document(file_contents: C) -> Result> +where + C: AsRef, +{ + let escaped_file_contents = escape_elisp_string(file_contents); + let elisp_script = format!( + r#"(progn + (erase-buffer) + (insert "{escaped_file_contents}") + (org-mode) + (message "%s" (pp-to-string (org-element-parse-buffer))) +)"#, + escaped_file_contents = escaped_file_contents + ); + let mut cmd = Command::new("emacs"); + let proc = cmd + .arg("-q") + .arg("--no-site-file") + .arg("--no-splash") + .arg("--batch") + .arg("--eval") + .arg(elisp_script); + let out = proc.output()?; + out.status.exit_ok()?; + let org_sexp = out.stderr; + Ok(String::from_utf8(org_sexp)?) +} + +fn escape_elisp_string(file_contents: C) -> String +where + C: AsRef, +{ + 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 +}