autocd will now prioritize running a command if a directory name is entered that matches the name of a command
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
use std::{collections::{HashSet, VecDeque}, os::unix::fs::PermissionsExt};
|
||||
|
||||
use crate::{
|
||||
builtin::{
|
||||
@@ -9,7 +9,7 @@ use crate::{
|
||||
libsh::error::{ShErr, ShErrKind, ShResult, ShResultExt},
|
||||
prelude::*,
|
||||
procio::{IoMode, IoStack},
|
||||
state::{self, ShFunc, VarFlags, read_logic, write_jobs, write_logic, write_vars},
|
||||
state::{self, ShFunc, VarFlags, read_logic, read_shopts, write_jobs, write_logic, write_vars},
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -22,6 +22,38 @@ thread_local! {
|
||||
static RECURSE_DEPTH: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
|
||||
}
|
||||
|
||||
pub fn is_in_path(name: &str) -> bool {
|
||||
if name.starts_with("./") || name.starts_with("../") || name.starts_with('/') {
|
||||
let path = Path::new(name);
|
||||
if path.exists() && path.is_file() && !path.is_dir() {
|
||||
let meta = match path.metadata() {
|
||||
Ok(m) => m,
|
||||
Err(_) => return false,
|
||||
};
|
||||
if meta.permissions().mode() & 0o111 != 0 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
} else {
|
||||
let Ok(path) = env::var("PATH") else { return false };
|
||||
let paths = path.split(':');
|
||||
for path in paths {
|
||||
let full_path = Path::new(path).join(name);
|
||||
if full_path.exists() && full_path.is_file() && !full_path.is_dir() {
|
||||
let meta = match full_path.metadata() {
|
||||
Ok(m) => m,
|
||||
Err(_) => continue,
|
||||
};
|
||||
if meta.permissions().mode() & 0o111 != 0 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ScopeGuard;
|
||||
|
||||
impl ScopeGuard {
|
||||
@@ -190,8 +222,9 @@ impl Dispatcher {
|
||||
self.exec_builtin(node)
|
||||
} else if is_subsh(node.get_command().cloned()) {
|
||||
self.exec_subsh(node)
|
||||
} else if crate::state::read_shopts(|s| s.core.autocd) && Path::new(cmd.span.as_str()).is_dir()
|
||||
{
|
||||
} else if read_shopts(|s| s.core.autocd)
|
||||
&& Path::new(cmd.span.as_str()).is_dir()
|
||||
&& !is_in_path(cmd.span.as_str()) {
|
||||
let dir = cmd.span.as_str().to_string();
|
||||
let stack = IoStack {
|
||||
stack: self.io_stack.clone(),
|
||||
@@ -293,7 +326,7 @@ impl Dispatcher {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let max_depth = crate::state::read_shopts(|s| s.core.max_recurse_depth);
|
||||
let max_depth = read_shopts(|s| s.core.max_recurse_depth);
|
||||
let depth = RECURSE_DEPTH.with(|d| {
|
||||
let cur = d.get();
|
||||
d.set(cur + 1);
|
||||
|
||||
Reference in New Issue
Block a user