expand ~ on windows

main
Jordan Orelli 9 months ago
parent 8ed0868e56
commit fd730452ca

@ -7,7 +7,7 @@ use std::{env, fs, io::Write};
pub struct Ls; pub struct Ls;
impl Call for Ls { impl Call for Ls {
fn call(&self, ctx: &mut Context, args: &[Value]) -> Result<Value, ExecError> { fn call(&self, ctx: &mut Context, _args: &[Value]) -> Result<Value, ExecError> {
let cwd = env::current_dir()?; let cwd = env::current_dir()?;
let dir = fs::read_dir(&cwd)?; let dir = fs::read_dir(&cwd)?;
for child in dir { for child in dir {

@ -1,5 +1,6 @@
use crate::{ use crate::{
lex::Token, lex::Token,
syntax::ExpandError,
topo::{Glyph, Position}, topo::{Glyph, Position},
}; };
use std::io; use std::io;
@ -91,6 +92,9 @@ pub enum ParseError {
#[error("dangling")] #[error("dangling")]
DanglingElements, DanglingElements,
#[error("shell expansion error")]
ExpansionError(#[from] ExpandError),
#[error("you wouldn't parse a semicolon")] #[error("you wouldn't parse a semicolon")]
WhyParseSemicolon, WhyParseSemicolon,
} }

@ -5,7 +5,7 @@ use crate::{
parse, parse,
run::{Call, Context, Eval, Value}, run::{Call, Context, Eval, Value},
}; };
use std::{collections::HashSet, process}; use std::{collections::HashSet, env, ffi::OsString, process};
/// The differnt types of nodes that may appear in our AST /// The differnt types of nodes that may appear in our AST
#[derive(Debug)] #[derive(Debug)]
@ -170,7 +170,9 @@ impl TreeBuilder {
Element::Command(cmd) Element::Command(cmd)
} }
parse::Value::Terminal(Token::Word(word)) => { parse::Value::Terminal(Token::Word(word)) => {
Element::Literal(Value::Text(word.to_string())) let text = word.to_string();
let text = expand(&text)?;
Element::Literal(Value::Text(text))
} }
parse::Value::Terminal(Token::Glob(_)) => { parse::Value::Terminal(Token::Glob(_)) => {
todo!() todo!()
@ -192,7 +194,49 @@ pub fn parse(source: &str) -> Result<Element, ParseError> {
let parser = parse::Parser::new(tokens); let parser = parse::Parser::new(tokens);
let mut parse_tree = parser.parse()?; let mut parse_tree = parser.parse()?;
let mut builder = TreeBuilder::new(); let mut builder = TreeBuilder::new();
builder.parse(&mut parse_tree) let root = builder.parse(&mut parse_tree)?;
Ok(root)
}
#[cfg(target_os = "windows")]
fn home_dir() -> Result<OsString, ExpandError> {
env::var_os("HOMEPATH").ok_or(ExpandError::EmptyEnvironmentVar(String::from("HOMEPATH")))
}
#[derive(thiserror::Error, Debug)]
pub enum ExpandError {
#[error("environment var is not set: {0}")]
EmptyEnvironmentVar(String),
#[error("home dir is not utf-8")]
NotUnicode,
}
fn expand(text: &str) -> Result<String, ExpandError> {
let chars = text.chars();
let mut escape = false;
let mut s = String::new();
for c in chars {
if !escape && c == '\\' {
escape = true;
continue;
}
if escape {
s.push(c);
escape = false;
continue;
}
if c == '~' {
let p = home_dir()?;
s.push_str(p.to_str().ok_or(ExpandError::NotUnicode)?);
continue;
}
s.push(c);
}
Ok(s)
} }
#[cfg(test)] #[cfg(test)]

Loading…
Cancel
Save