summaryrefslogtreecommitdiffstats
path: root/src/verb
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2021-06-10 22:35:31 +0200
committerCanop <cano.petrole@gmail.com>2021-06-10 22:35:31 +0200
commit8b7bbf146c96de074c242abfdad40d21833d8a5a (patch)
treeb3d93918cbb9b21eea3f59a45072fd9b796e0714 /src/verb
parent6ea38c86908ca169f871ed6f5971e9fa44b84e7a (diff)
`working_dir` verb attribute
It makes it possible to set the working dir of a new executable to something different than the current directory. For example working_dir: "{directory}/.git" Fix #396
Diffstat (limited to 'src/verb')
-rw-r--r--src/verb/exec_pattern.rs1
-rw-r--r--src/verb/execution_builder.rs12
-rw-r--r--src/verb/external_execution.rs51
3 files changed, 41 insertions, 23 deletions
diff --git a/src/verb/exec_pattern.rs b/src/verb/exec_pattern.rs
index d320958..addf0b1 100644
--- a/src/verb/exec_pattern.rs
+++ b/src/verb/exec_pattern.rs
@@ -9,6 +9,7 @@ use {
},
};
+/// A pattern which can be expanded into an executable
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum ExecPattern {
diff --git a/src/verb/execution_builder.rs b/src/verb/execution_builder.rs
index e8e5b8a..4b2f61b 100644
--- a/src/verb/execution_builder.rs
+++ b/src/verb/execution_builder.rs
@@ -213,6 +213,18 @@ impl<'b> ExecutionStringBuilder<'b> {
}
}
+ /// build a path
+ pub fn path(
+ &self,
+ pattern: &str,
+ ) -> PathBuf {
+ PathBuf::from(
+ GROUP.replace_all(
+ pattern,
+ |ec: &Captures<'_>| self.get_capture_replacement(ec),
+ ).to_string()
+ )
+ }
/// build a shell compatible command, with escapings
pub fn shell_exec_string(
&self,
diff --git a/src/verb/external_execution.rs b/src/verb/external_execution.rs
index d20b197..af4a245 100644
--- a/src/verb/external_execution.rs
+++ b/src/verb/external_execution.rs
@@ -5,15 +5,14 @@ use {
display::W,
errors::ProgramError,
launchable::Launchable,
- path,
},
std::{
fs::OpenOptions,
io::Write,
+ path::PathBuf,
},
};
-
/// Definition of how the user input should be interpreted
/// to be executed in an external command.
#[derive(Debug, Clone)]
@@ -34,9 +33,9 @@ pub struct ExternalExecution {
/// how the external process must be launched
pub exec_mode: ExternalExecutionMode,
- /// whether the working dir of the external process must be set
- /// to the current directory
- pub set_working_dir: bool,
+ /// the working directory of the new process, or none if we don't
+ /// want to set it
+ pub working_dir: Option<String>,
}
impl ExternalExecution {
@@ -47,14 +46,12 @@ impl ExternalExecution {
Self {
exec_pattern,
exec_mode,
- set_working_dir: false,
+ working_dir: None,
}
}
- pub fn with_set_working_dir(mut self, b: Option<bool>) -> Self {
- if let Some(b) = b {
- self.set_working_dir = b;
- }
+ pub fn with_working_dir(mut self, b: Option<String>) -> Self {
+ self.working_dir = b;
self
}
@@ -84,6 +81,23 @@ impl ExternalExecution {
}
}
+ fn working_dir_path(
+ &self,
+ builder: &ExecutionStringBuilder<'_>,
+ ) -> Option<PathBuf> {
+ self.working_dir
+ .as_ref()
+ .map(|pattern| builder.path(pattern))
+ .filter(|pb| {
+ if pb.exists() {
+ true
+ } else {
+ warn!("workding dir doesn't exist: {:?}", pb);
+ false
+ }
+ })
+ }
+
/// build the cmd result as an executable which will be called
/// from the parent shell (meaning broot must quit)
fn cmd_result_exec_from_parent_shell(
@@ -134,10 +148,7 @@ impl ExternalExecution {
}
let launchable = Launchable::program(
builder.exec_token(&self.exec_pattern),
- builder.sel_info
- .one_sel()
- .filter(|_| self.set_working_dir)
- .map(|sel| path::closest_dir(sel.path)),
+ self.working_dir_path(&builder),
con,
)?;
Ok(CmdResult::from(launchable))
@@ -151,15 +162,13 @@ impl ExternalExecution {
builder: ExecutionStringBuilder<'_>,
con: &AppContext,
) -> Result<CmdResult, ProgramError> {
+ let working_dir_path = self.working_dir_path(&builder);
match &builder.sel_info {
SelInfo::None | SelInfo::One(_) => {
// zero or one selection -> only one execution
let launchable = Launchable::program(
builder.exec_token(&self.exec_pattern),
- builder.sel_info
- .one_sel()
- .filter(|_| self.set_working_dir)
- .map(|sel| path::closest_dir(sel.path)),
+ working_dir_path,
con,
)?;
info!("Executing not leaving, launchable {:?}", launchable);
@@ -180,11 +189,7 @@ impl ExternalExecution {
for sel in sels {
let launchable = Launchable::program(
builder.sel_exec_token(&self.exec_pattern, Some(sel)),
- if self.set_working_dir {
- Some(path::closest_dir(sel.path))
- } else {
- None
- },
+ working_dir_path.clone(),
con,
)?;
if let Err(e) = launchable.execute(Some(w)) {