From 295e097e9127621c4ef01dc6a2c47f77350f9f08 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sat, 28 Nov 2020 13:59:12 +0800 Subject: [PATCH] feat: add qjs --- Cargo.toml | 1 + src/cmd_default.rs | 21 +++++++++++- src/main.rs | 1 + src/template_quickjs.rs | 74 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 src/template_quickjs.rs diff --git a/Cargo.toml b/Cargo.toml index dd0451b..1a6dc65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,5 +17,6 @@ clap = "2.33" toml = "0.5" rust_util = "0.6" regex = "1.4" +quick-js = { git = "https://git.hatter.ink/public-collect/quickjs-rs.git" } diff --git a/src/cmd_default.rs b/src/cmd_default.rs index badfc73..d0b49dd 100644 --- a/src/cmd_default.rs +++ b/src/cmd_default.rs @@ -1,6 +1,8 @@ use clap::{App, Arg, ArgMatches}; use crate::cmd::CommandError; +use crate::template::CommitMsgCheck; use crate::template_regex::CommitMsgCheckRegex; +use crate::template_quickjs::CommitMsgCheckQuickJs; pub struct CommandImpl; @@ -15,7 +17,24 @@ impl CommandImpl { information!("Verbose count: {}", verbose_count); information!(r#"Print using command line: commit-msg usage"#); - CommitMsgCheckRegex::new_default(); + let a = CommitMsgCheckRegex::new_default(); + let b = CommitMsgCheckQuickJs::new_from_js(r##" + function check(a) { + return false; + } + + function hint() { + return "hello"; + } + "##).expect("err"); + + if !a.check("a") { + a.print_hint(); + } + if !b.check("b") { + b.print_hint(); + } + Ok(()) } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 8622adf..ac8f442 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod cmd_usage; mod cmd_install; mod template; mod template_regex; +mod template_quickjs; use clap::App; use cmd::{Command, CommandError}; diff --git a/src/template_quickjs.rs b/src/template_quickjs.rs new file mode 100644 index 0000000..cb37c5c --- /dev/null +++ b/src/template_quickjs.rs @@ -0,0 +1,74 @@ +use quick_js::{Context, JsValue}; +use quick_js::console::{Level, ConsoleBackend}; +use rust_util::XResult; +use crate::template::CommitMsgCheck; + +pub struct CommitMsgCheckQuickJs { + context: Context, +} + +impl CommitMsgCheck for CommitMsgCheckQuickJs { + fn check(&self, msg: &str) -> bool { + match self.context.eval(&format!("check('{}')", encode_str(msg))) { + Err(e) => { + failure!("Run JS function #check(msg) faield: {}", e); + false + }, + Ok(JsValue::Bool(val)) => val, + Ok(JsValue::Null) => false, + Ok(JsValue::Int(val)) => val == 1, + Ok(JsValue::Float(val)) => val == 1.0, + Ok(JsValue::String(val)) => val == "1", + others => { + warning!("Run JS function #check(msg) return value unknown: {:?}", others); + false + }, + } + } + + fn print_hint(&self) { + match self.context.eval("hint()") { + Err(e) => failure!("Run JS function #hint() faield: {}", e), + Ok(JsValue::String(val)) => println!("[USAGE] {}", val), + others => println!("[USAGE] {:?}", others), + } + } +} + +struct ConsoleBackendImpl; +impl ConsoleBackend for ConsoleBackendImpl { + fn log(&self, level: Level, values: Vec) { + println!("[{:>5}] - {:?}", format!("{:?}", level).to_uppercase(), values); + } +} + +impl CommitMsgCheckQuickJs { + pub fn new_from_js(js: &str) -> XResult { + let context = Context::builder().memory_limit(16 * 1024 * 1024) + .console(ConsoleBackendImpl{}) + .build()?; + context.eval(js)?; + Ok(Self{ + context, + }) + } +} + +fn encode_str(s: &str) -> String { + let mut ret = String::with_capacity(s.len() + 10); + for c in s.chars() { + if c == '\\' || c == '\'' { + ret.push('\\'); + ret.push(c); + } else if c == '\n' { + ret.push_str("\\n"); + } else if c == '\r' { + ret.push_str("\\r"); + } else if c == '\t' { + ret.push_str("\\t"); + } else { + ret.push(c); + } + } + ret +}