From 591d2b6167af53ce07b060711a4074f1e19c5f3f Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 8 May 2021 21:25:47 +0530 Subject: add basic user-definable keybinds --- src/lisp/error.rs | 13 +++++++++---- src/lisp/eval.rs | 20 +++++++++++++++++++- src/lisp/std.lisp | 15 +++++++++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) (limited to 'src/lisp') diff --git a/src/lisp/error.rs b/src/lisp/error.rs index 9e9dc90..7bde872 100644 --- a/src/lisp/error.rs +++ b/src/lisp/error.rs @@ -1,7 +1,10 @@ -use crate::lisp::{ - expr::{Arity, LispExpr}, - lex::{Span, SpanDisplay}, - number::LispNumber, +use crate::{ + keybind::KeybindError, + lisp::{ + expr::{Arity, LispExpr}, + lex::{Span, SpanDisplay}, + number::LispNumber, + }, }; use std::{fmt, io}; @@ -104,6 +107,7 @@ pub enum EvalError { AssertionError { expected: LispExpr, got: LispExpr }, ScriptLoadError(io::Error), CustomInternal(&'static str), + KeybindError(KeybindError), Custom(String), } @@ -134,6 +138,7 @@ impl fmt::Display for EvalError { write!(f, "assertion error: expected `{}` got `{}`", expected, got) } Self::ScriptLoadError(s) => write!(f, "error while loading script: {}", s), + Self::KeybindError(k) => write!(f, "keybind error: {}", k), Self::CustomInternal(s) => write!(f, "{}", s), Self::Custom(s) => write!(f, "error: {}", s), } diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs index 75cb5c9..677fa23 100644 --- a/src/lisp/eval.rs +++ b/src/lisp/eval.rs @@ -1,5 +1,6 @@ use crate::{ app::AppState, + keybind::Keybind, lisp::{ error::{EvalError, LispError}, expr::{Arity, Ident, LispExpr, LispFunction}, @@ -8,7 +9,7 @@ use crate::{ type_match, }; -use std::convert::TryInto; +use std::{convert::TryInto, str::FromStr}; use log::{error, info}; @@ -44,6 +45,7 @@ where "for" => self.eval_for(&li[1..]), "quote" => Ok(apply_quote(&li[1])), "let" => self.eval_let(&li[1..]), + "bind-key" => self.eval_bind_key(&li[1..]), _ => { let mut new_ls = vec![self.eval(&func_expr)?]; new_ls.extend(li[1..].to_vec()); @@ -302,6 +304,22 @@ where } } } + + pub fn eval_bind_key(&mut self, args: &[LispExpr]) -> Result { + let arity = Arity::Exact(2); + if !arity.check(args) { + Err(arity.to_error()) + } else { + match args { + [LispExpr::StringLit(s), body] => { + let bind = Keybind::from_str(&s).map_err(EvalError::KeybindError)?; + self.app.keybinds.insert(bind, body.clone()); + Ok(LispExpr::Unit) + } + _ => Err(EvalError::BadForm.into()), + } + } + } } pub fn apply_quote(arg: &LispExpr) -> LispExpr { diff --git a/src/lisp/std.lisp b/src/lisp/std.lisp index a256125..fe09a8a 100644 --- a/src/lisp/std.lisp +++ b/src/lisp/std.lisp @@ -72,3 +72,18 @@ acc (rev-helper (cdr p) (cons (car p) acc)))) (rev-helper ls '()))) + +(define (append l1 l2) + (if (null? l1) + l2 + (cons (car l1) + (append (cdr l1) l2)))) + +(define (cross xs ys) + (if (or (null? xs) + (null? ys)) + '() + (fold '() + append + (map (lambda (x) + (map (lambda (y) (list x y)) ys)) xs)))) -- cgit v1.2.3