From b8f46716572b006e5a6175c29a2dda8c8fc0a346 Mon Sep 17 00:00:00 2001 From: ef3d0c3e Date: Wed, 24 Jul 2024 11:54:04 +0200 Subject: [PATCH] Add graph --- src/elements/graphviz.rs | 470 ++++++++++++++++++++++---------------- src/elements/mod.rs | 1 + src/elements/raw.rs | 2 +- src/elements/registrar.rs | 45 ++-- src/elements/tex.rs | 318 +++++++++++++++----------- src/lsp/parser.rs | 2 + src/main.rs | 57 ++--- src/parser/langparser.rs | 266 +++++++++++---------- src/parser/mod.rs | 4 +- src/parser/parser.rs | 160 +++++++------ src/parser/rule.rs | 105 ++++++--- src/parser/source.rs | 194 ++++++++-------- src/parser/state.rs | 94 ++++---- src/parser/util.rs | 36 ++- 14 files changed, 1000 insertions(+), 754 deletions(-) diff --git a/src/elements/graphviz.rs b/src/elements/graphviz.rs index 5be07ad..7431d25 100644 --- a/src/elements/graphviz.rs +++ b/src/elements/graphviz.rs @@ -1,266 +1,340 @@ -use std::{io::{Read, Write}, ops::Range, process::{Command, Stdio}, rc::Rc, sync::Once}; +use std::collections::HashMap; +use std::io::Read; +use std::io::Write; +use std::ops::Range; +use std::process::Command; +use std::process::Stdio; +use std::rc::Rc; +use std::str::FromStr; +use std::sync::Once; -use ariadne::{Fmt, Label, Report, ReportKind}; -use crypto::{digest::Digest, sha2::Sha512}; -use mlua::{Function, Lua}; -use regex::{Captures, Regex}; +use crate::parser::util::Property; +use crate::parser::util::PropertyMapError; +use crate::parser::util::PropertyParser; +use ariadne::Fmt; +use ariadne::Label; +use ariadne::Report; +use ariadne::ReportKind; +use crypto::digest::Digest; +use crypto::sha2::Sha512; +use graphviz_rust::cmd::Format; +use graphviz_rust::cmd::Layout; +use graphviz_rust::exec; +use graphviz_rust::exec_dot; +use graphviz_rust::parse; +use graphviz_rust::printer::PrinterContext; +use mlua::Function; +use mlua::Lua; +use regex::Captures; +use regex::Regex; -use crate::{cache::cache::{Cached, CachedError}, compiler::compiler::{Compiler, Target}, document::{document::Document, element::{ElemKind, Element}}, parser::{parser::Parser, rule::RegexRule, source::{Source, Token}, util}}; - -#[derive(Debug, PartialEq, Eq)] -enum TexKind -{ - Block, - Inline, -} - -impl From<&TexKind> for ElemKind -{ - fn from(value: &TexKind) -> Self { - match value { - TexKind::Inline => ElemKind::Inline, - _ => ElemKind::Block - } - } -} +use crate::cache::cache::Cached; +use crate::cache::cache::CachedError; +use crate::compiler::compiler::Compiler; +use crate::compiler::compiler::Target; +use crate::document::document::Document; +use crate::document::element::ElemKind; +use crate::document::element::Element; +use crate::parser::parser::Parser; +use crate::parser::rule::RegexRule; +use crate::parser::source::Source; +use crate::parser::source::Token; +use crate::parser::util; #[derive(Debug)] -struct Tex -{ - location: Token, - block: TexKind, - env: String, - tex: String, - caption: Option, +struct Graphviz { + pub location: Token, + pub dot: String, + pub layout: Layout, + pub caption: Option, } -impl Tex { - fn new(location: Token, block: TexKind, env: String, tex: String, caption: Option) -> Self { - Self { location, block, env, tex, caption } - } - - fn format_latex(fontsize: &String, preamble: &String, tex: &String) -> FormattedTex - { - FormattedTex(format!(r"\documentclass[{}pt,preview]{{standalone}} -{} -\begin{{document}} -\begin{{preview}} -{} -\end{{preview}} -\end{{document}}", - fontsize, preamble, tex)) +fn layout_from_str(value: &str) -> Result { + match value { + "dot" => Ok(Layout::Dot), + "neato" => Ok(Layout::Neato), + "fdp" => Ok(Layout::Fdp), + "sfdp" => Ok(Layout::Sfdp), + "circo" => Ok(Layout::Circo), + "twopi" => Ok(Layout::Twopi), + "osage" => Ok(Layout::Asage), // typo in graphviz_rust ? + "patchwork" => Ok(Layout::Patchwork), + _ => Err(format!("Unknown layout: {value}")), } } -struct FormattedTex(String); +impl Graphviz { + /// Renders dot to svg + fn dot_to_svg(&self) -> Result { + print!("Rendering Graphviz `{}`... ", self.dot); -impl FormattedTex -{ - /// Renders latex to svg - fn latex_to_svg(&self, exec: &String, fontsize: &String) -> Result - { - print!("Rendering LaTex `{}`... ", self.0); - let process = match Command::new(exec) - .arg("--fontsize").arg(fontsize) - .stdout(Stdio::piped()) - .stdin(Stdio::piped()) - .spawn() - { - Err(e) => return Err(format!("Could not spawn `{exec}`: {}", e)), - Ok(process) => process - }; + let svg = match exec_dot( + self.dot.clone(), + vec![self.layout.into(), Format::Svg.into()], + ) { + Ok(svg) => { + let out = String::from_utf8_lossy(svg.as_slice()); + let split_at = out.find("