diff --git a/meli/src/command/actions.rs b/meli/src/command/actions.rs index 387ac008..4bb7ed9c 100644 --- a/meli/src/command/actions.rs +++ b/meli/src/command/actions.rs @@ -121,6 +121,8 @@ pub enum Action { View(ViewAction), SetEnv(String, String), PrintEnv(String), + CurrentDirectory, + ChangeCurrentDirectory(PathBuf), Compose(ComposeAction), Mailbox(AccountName, MailboxOperation), AccountAction(AccountName, AccountAction), diff --git a/meli/src/command/parser.rs b/meli/src/command/parser.rs index 7d413572..40d9dd7f 100644 --- a/meli/src/command/parser.rs +++ b/meli/src/command/parser.rs @@ -136,7 +136,7 @@ pub fn parse_command(input: &[u8]) -> Result { close, mailinglist, setenv, - printenv, + alt((printenv, currentdir, change_currentdir)), view, create_mailbox, sub_mailbox, @@ -401,6 +401,25 @@ pub fn printenv(input: &[u8]) -> IResult<&[u8], Result> { let (input, _) = eof(input)?; Ok((input, Ok(PrintEnv(key.to_string())))) } +pub fn currentdir(input: &[u8]) -> IResult<&[u8], Result> { + let mut check = arg_init! { min_arg:0, max_arg: 0, currentdir}; + let (input, _) = tag("cwd")(input.ltrim())?; + arg_chk!(start check, input); + arg_chk!(finish check, input); + let (input, _) = eof(input)?; + Ok((input, Ok(CurrentDirectory))) +} +pub fn change_currentdir(input: &[u8]) -> IResult<&[u8], Result> { + let mut check = arg_init! { min_arg:1, max_arg: 1, change_currentdir}; + let (input, _) = tag("cd")(input.ltrim())?; + arg_chk!(start check, input); + let (input, _) = is_a(" ")(input)?; + arg_chk!(inc check, input); + let (input, d) = map_res(not_line_ending, std::str::from_utf8)(input.trim())?; + arg_chk!(finish check, input); + let (input, _) = eof(input)?; + Ok((input, Ok(ChangeCurrentDirectory(d.into())))) +} pub fn mailto(input: &[u8]) -> IResult<&[u8], Result> { let mut check = arg_init! { min_arg:1, max_arg: 1, mailto}; use melib::email::parser::generic::mailto as parser; diff --git a/meli/src/state.rs b/meli/src/state.rs index 87b7b3da..2030e808 100644 --- a/meli/src/state.rs +++ b/meli/src/state.rs @@ -34,7 +34,14 @@ //! for user input, observe folders for file changes etc. The relevant struct is //! [`ThreadEvent`]. -use std::{collections::BTreeSet, env, os::unix::io::RawFd, sync::Arc, thread}; +use std::{ + collections::BTreeSet, + env, + os::unix::io::RawFd, + path::{Path, PathBuf}, + sync::Arc, + thread, +}; use crossbeam::channel::{unbounded, Receiver, Sender}; use indexmap::{IndexMap, IndexSet}; @@ -133,6 +140,7 @@ pub struct Context { pub main_loop_handler: MainLoopHandler, receiver: Receiver, input_thread: InputHandler, + current_dir: PathBuf, pub children: Vec, pub temp_files: Vec, @@ -241,6 +249,7 @@ impl Context { realized: IndexMap::default(), unrealized: IndexSet::default(), temp_files: Vec::new(), + current_dir: std::env::current_dir().unwrap(), children: vec![], input_thread: InputHandler { @@ -257,6 +266,10 @@ impl Context { receiver, } } + + pub fn current_dir(&self) -> &Path { + &self.current_dir + } } /// A State object to manage and own components and components of the UI. @@ -434,6 +447,7 @@ impl State { realized: IndexMap::default(), unrealized: IndexSet::default(), temp_files: Vec::new(), + current_dir: std::env::current_dir()?, children: vec![], input_thread: InputHandler { @@ -863,6 +877,21 @@ impl State { env::var(key.as_str()).unwrap_or_else(|e| e.to_string()), ))); } + ChangeCurrentDirectory(dir) => { + self.context.current_dir = dir; + self.context + .replies + .push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage( + self.context.current_dir.display().to_string(), + ))); + } + CurrentDirectory => { + self.context + .replies + .push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage( + self.context.current_dir.display().to_string(), + ))); + } Mailbox(account_name, op) => { if let Some(account) = self .context