diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e4f08de..9bd40d5 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2258,6 +2258,7 @@ dependencies = [ "tempfile", "tokio", "tokio-tungstenite", + "toml 0.8.8", "uuid", "which", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index fa08285..1d3192d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -40,6 +40,7 @@ tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", rusqlite = { version = "0.30.0", features = ["bundled"] } gethostname = "0.4.3" which = "5.0.0" +toml = "0.8.8" [features] # this feature is used for production builds or when `devPath` points to the filesystem diff --git a/src-tauri/src/ipc/rt/compiler.rs b/src-tauri/src/ipc/rt/compiler.rs index ccbd03e..27f23ab 100644 --- a/src-tauri/src/ipc/rt/compiler.rs +++ b/src-tauri/src/ipc/rt/compiler.rs @@ -7,7 +7,7 @@ use tokio::sync::RwLock; use crate::{ipc::LanguageMode, util::keylock::KeyLock}; -use super::gnu_gcc::GNUGccCompiler; +use super::{gnu_gcc::GNUGccCompiler, interpreter::Interpreter}; #[derive(Debug, Serialize, Deserialize)] pub struct CompileLint { @@ -84,7 +84,7 @@ pub async fn compile_source( let compiler_handle: Box = match mode { LanguageMode::CXX => Box::new(GNUGccCompiler), - LanguageMode::PY => unimplemented!(), + LanguageMode::PY => Box::new(Interpreter::with_ext(String::from("py"))), }; let result = compiler_handle diff --git a/src-tauri/src/ipc/rt/interpreter.rs b/src-tauri/src/ipc/rt/interpreter.rs new file mode 100644 index 0000000..d5cae03 --- /dev/null +++ b/src-tauri/src/ipc/rt/interpreter.rs @@ -0,0 +1,77 @@ +use std::{ + path::{Path, PathBuf}, + process::Stdio, +}; + +use crate::{ipc::rt::compiler::CompileLint, util::console}; + +use super::compiler::{CompileResult, Compiler, CompilerOptions}; +use anyhow::{Ok, Result}; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use tokio::{fs, process::Command}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct InterpreterStore { + pub interpreter: String, + pub script: String, + pub args: Vec, +} + +// It just record its compiler into a config file, not compile it +// it always success +pub struct Interpreter { + ext: String, +} +impl Interpreter { + pub fn with_ext(ext: String) -> Self { + Self { ext } + } +} + +#[async_trait] +impl Compiler for Interpreter { + async fn compile( + &self, + source: String, + compiler_options: CompilerOptions, + working_path: PathBuf, + ) -> Result { + let source_file = working_path.join(format!("source.{}", self.ext)); + let config_file = working_path.join(format!("source.{}.toml", self.ext)); + let compiler = if let Some(compiler) = compiler_options.path { + compiler + } else { + return Ok(CompileResult::Error { + data: vec![CompileLint { + position: Some((0, 0)), + ty: Some(String::from("Error")), + description: String::from("An compiler or interpreter must be specificed"), + }], + }); + }; + let compiler_args = compiler_options.args.unwrap_or(vec![]); + let config_content = toml::to_string(&InterpreterStore { + interpreter: compiler, + script: source_file.to_str().unwrap().to_owned(), + args: compiler_args, + }) + .unwrap(); + fs::write(&source_file, source).await?; + fs::write(&config_file, config_content).await?; + Ok(CompileResult::Success { + data: config_file.to_str().unwrap().to_owned(), + }) + } +} + +pub async fn build_command_from_config>( + config_file: P, +) -> Result { + let config = tokio::fs::read_to_string(config_file).await?; + let config = toml::from_str::(&config)?; + let mut cmd = std::process::Command::new(&config.interpreter); + cmd.args(&config.args); + cmd.arg(config.script); + Ok(cmd) +} diff --git a/src-tauri/src/ipc/rt/mod.rs b/src-tauri/src/ipc/rt/mod.rs index 02b4b1a..1916422 100644 --- a/src-tauri/src/ipc/rt/mod.rs +++ b/src-tauri/src/ipc/rt/mod.rs @@ -1,4 +1,5 @@ pub mod compiler; +pub mod interpreter; pub mod runner; pub mod checker; diff --git a/src-tauri/src/ipc/rt/runner.rs b/src-tauri/src/ipc/rt/runner.rs index dc2682b..594ea11 100644 --- a/src-tauri/src/ipc/rt/runner.rs +++ b/src-tauri/src/ipc/rt/runner.rs @@ -8,6 +8,7 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use tokio::process::{Child, Command}; use tokio::sync::Mutex; +use crate::ipc::rt::interpreter::build_command_from_config; use crate::{ ipc::LanguageMode, util::{ @@ -154,7 +155,9 @@ pub async fn run_redirect( let working_dir = PathBuf::from(&exec_target).parent().unwrap().to_path_buf(); let mut cmd = match mode { LanguageMode::CXX => std::process::Command::new(exec_target), - _ => unimplemented!(), + LanguageMode::PY => build_command_from_config(PathBuf::from(exec_target)) + .await + .map_err(|e| e.to_string())?, }; cmd.current_dir(working_dir);