aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main.rs4
-rw-r--r--src/parse/mod.rs65
-rw-r--r--src/run/mod.rs10
3 files changed, 60 insertions, 19 deletions
diff --git a/src/main.rs b/src/main.rs
index 9e9d640..2afdbcb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -38,7 +38,7 @@ use crate::completion::PathCache;
use crate::ctrlc::CtrlC;
use crate::cursor::{Direction, move_cursor};
use crate::history::HistoryEntry;
-use crate::parse::{Ast, PreExpansion};
+use crate::parse::{Ast, Block, PreExpansion};
use crate::run::Executor;
macro_rules! print {
@@ -83,7 +83,7 @@ pub struct Session {
prev_path: BString,
builtins: HashMap<BString, &'static dyn run::Builtin>,
vars: HashMap<BString, BString>,
- funs: HashMap<BString, Ast<PreExpansion>>,
+ funs: HashMap<BString, Block>,
socket_running: Option<export_fun::SocketRunning>,
path_cache: PathCache,
ctrlc: CtrlC,
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index a15ad84..93d2de8 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -33,19 +33,19 @@ pub trait Expander {
}
#[derive(Debug, Clone, PartialEq)]
+pub struct Block {
+ pub commands: Vec<Ast<PreExpansion>>,
+}
+
+#[derive(Debug, Clone, PartialEq)]
pub enum Ast<T: Stage> {
FunDecl(FunDecl<T>),
VarAssign(VarAssign<T>),
Pipes(Pipes<T>),
}
-pub fn decl(name: ExpString, body: Ast<PreExpansion>) -> Ast<PreExpansion> {
- Ast::FunDecl(FunDecl {
- name,
- body: FunBody {
- body: Box::new(body),
- },
- })
+pub fn decl(name: ExpString, body: Block) -> Ast<PreExpansion> {
+ Ast::FunDecl(FunDecl { name, body })
}
pub fn assign(var: ExpString, val: ExpString) -> Ast<PreExpansion> {
@@ -106,6 +106,27 @@ pub fn cmd<const N: usize>(x: [ExpString; N]) -> Command<PreExpansion> {
}
}
+pub fn block<const N: usize>(x: [Ast<PreExpansion>; N]) -> Block {
+ Block {
+ commands: x.to_vec(),
+ }
+}
+
+impl CmdDisplay for Block {
+ fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> {
+ write!(w, "block([")?;
+ let mut prev = false;
+ for cmd in self.commands.iter() {
+ if prev {
+ write!(w, ",")?;
+ }
+ prev = true;
+ cmd.cdisplay(w)?;
+ }
+ write!(w, "])")
+ }
+}
+
impl CmdDisplay for Ast<PreExpansion> {
fn cdisplay(&self, w: &mut dyn std::io::Write) -> std::io::Result<()> {
match self {
@@ -113,7 +134,7 @@ impl CmdDisplay for Ast<PreExpansion> {
write!(w, "decl(")?;
fun_decl.name.cdisplay(w)?;
write!(w, ", ")?;
- fun_decl.body.body.cdisplay(w)?;
+ fun_decl.body.cdisplay(w)?;
write!(w, ")")?;
}
Ast::VarAssign(var_assign) => {
@@ -256,7 +277,13 @@ impl Parse for FunBody {
#[derive(Debug, Clone, PartialEq)]
pub struct FunDecl<S: Stage> {
pub name: S::Str,
- pub body: FunBody,
+ pub body: Block,
+}
+
+impl Parse for Block {
+ fn parse(b: &mut Cursor<'_>) -> Result<Self> {
+ todo!()
+ }
}
impl Parse for FunDecl<PreExpansion> {
@@ -267,7 +294,7 @@ impl Parse for FunDecl<PreExpansion> {
b.advance(4);
b.spaces();
let name = ExpString::parse(b)?;
- let body = FunBody::parse(b)?;
+ let body = Block::parse(b)?;
Ok(Self { name, body })
}
}
@@ -648,7 +675,11 @@ impl Parse for ExpString {
continue;
}
- if delim == b' ' && x == b'~' && p.is_empty() && (!b.has() || b" /".contains(&b.peek())) {
+ if delim == b' '
+ && x == b'~'
+ && p.is_empty()
+ && (!b.has() || b" /".contains(&b.peek()))
+ {
p.push(StringPart::Var(Var {
name: VarName {
name: b"HOME".to_vec(),
@@ -752,10 +783,20 @@ impl CompletionContext {
}
}
+impl Block {
+ fn completion<E: Expander>(&self, e: &mut E) -> CompletionContext {
+ if let Some(cmd) = self.commands.last() {
+ cmd.completion(e)
+ } else {
+ CompletionContext::none()
+ }
+ }
+}
+
impl Ast<PreExpansion> {
fn completion<E: Expander>(&self, e: &mut E) -> CompletionContext {
match self {
- Ast::FunDecl(fd) => fd.body.body.completion(e),
+ Ast::FunDecl(fd) => fd.body.completion(e),
Ast::VarAssign(va) => va.val.completion(e, CompletionKind::Argument),
Ast::Pipes(p) => p.completion(e),
}
diff --git a/src/run/mod.rs b/src/run/mod.rs
index 09051c5..751f557 100644
--- a/src/run/mod.rs
+++ b/src/run/mod.rs
@@ -210,13 +210,13 @@ impl Executor {
});
SpawnedCmd::Builtin(handle)
}
- CommandKind::Fun(ast) => {
+ CommandKind::Fun(body) => {
let mut this = self.clone();
this.args = Some(args);
let handle = wait::spawn(move || {
- let ast = ast.expand(&mut this)?;
- let cmd = this.execute(ast, stdin, stdout);
+ let body = body.expand(&mut this)?;
+ let cmd = this.execute(body, stdin, stdout);
this.exec_loop(cmd, &mut [])
});
@@ -290,7 +290,7 @@ impl Executor {
.lock()
.unwrap()
.funs
- .insert(fd.name.clone(), *fd.body.body);
+ .insert(fd.name.clone(), fd.body);
crate::export_fun::create_function_hook(self.se.clone(), &fd.name);
// TODO: very ugly to ad-hoc keep export stuff & session data in sync here
SpawnedCmd::Joined(Ok(()))
@@ -495,7 +495,7 @@ pub fn builtin_map() -> HashMap<BString, &'static dyn Builtin> {
#[derive(Clone)]
pub enum CommandKind {
Builtin(&'static dyn Builtin),
- Fun(Ast<PreExpansion>),
+ Fun(Block),
Path(PathBuf),
}