Improve history navigation

Make path history behave like jump list and allow jumping back and
forth in the same directory.
pull/168/head
Arijit Basu 3 years ago committed by Arijit Basu
parent 5c179a9b70
commit 5b2aee3479

@ -1,6 +1,7 @@
use crate::config::Config;
use crate::config::Mode;
use crate::default_config::DEFAULT_LUA_SCRIPT;
use crate::explorer;
use crate::input::Key;
use crate::lua;
use crate::ui::Layout;
@ -1328,7 +1329,6 @@ impl Command {
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum MsgOut {
ExplorePwd,
ExplorePwdAsync,
ExploreParentsAsync,
Refresh,
@ -1588,7 +1588,9 @@ impl App {
history: Default::default(),
last_modes: Default::default(),
}
.change_directory(&pwd)?;
.change_directory(&pwd, false)?
.explore_pwd()? // Populates the history
.focus_first(true)?;
if let Some(notif) = config.upgrade_notification()? {
let notif = format!(
@ -1658,7 +1660,7 @@ impl App {
ExternalMsg::ExplorePwdAsync => self.explore_pwd_async(),
ExternalMsg::Refresh => self.refresh(),
ExternalMsg::ClearScreen => self.clear_screen(),
ExternalMsg::FocusFirst => self.focus_first(),
ExternalMsg::FocusFirst => self.focus_first(true),
ExternalMsg::FocusLast => self.focus_last(),
ExternalMsg::FocusPrevious => self.focus_previous(),
ExternalMsg::FocusPreviousByRelativeIndex(i) => {
@ -1673,12 +1675,12 @@ impl App {
ExternalMsg::FocusNextByRelativeIndexFromInput => {
self.focus_next_by_relative_index_from_input()
}
ExternalMsg::FocusPath(p) => self.focus_path(&p),
ExternalMsg::FocusPath(p) => self.focus_path(&p, true),
ExternalMsg::FocusPathFromInput => self.focus_path_from_input(),
ExternalMsg::FocusByIndex(i) => self.focus_by_index(i),
ExternalMsg::FocusByIndexFromInput => self.focus_by_index_from_input(),
ExternalMsg::FocusByFileName(n) => self.focus_by_file_name(&n),
ExternalMsg::ChangeDirectory(dir) => self.change_directory(&dir),
ExternalMsg::FocusByFileName(n) => self.focus_by_file_name(&n, true),
ExternalMsg::ChangeDirectory(dir) => self.change_directory(&dir, true),
ExternalMsg::Enter => self.enter(),
ExternalMsg::Back => self.back(),
ExternalMsg::LastVisitedPath => self.last_visited_path(),
@ -1783,9 +1785,13 @@ impl App {
Ok(self)
}
fn explore_pwd(mut self) -> Result<Self> {
self.msg_out.push_back(MsgOut::ExplorePwd);
Ok(self)
fn explore_pwd(self) -> Result<Self> {
let dir = explorer::explore_sync(
self.explorer_config().clone(),
self.pwd().clone(),
self.focused_node().map(|n| n.absolute_path().clone()),
)?;
self.add_directory(dir.parent().clone(), dir)
}
fn explore_pwd_async(mut self) -> Result<Self> {
@ -1808,36 +1814,54 @@ impl App {
Ok(self)
}
fn focus_first(mut self) -> Result<Self> {
fn focus_first(mut self, save_history: bool) -> Result<Self> {
if let Some(dir) = self.directory_buffer_mut() {
dir.focus = 0;
self.msg_out.push_back(MsgOut::Refresh);
};
Ok(self)
if save_history {
if let Some(n) = self.clone().focused_node() {
self.history = self.history.push(n.absolute_path().clone())
}
}
self.refresh()
} else {
Ok(self)
}
}
fn focus_last(mut self) -> Result<Self> {
let history = self.history.clone();
if let Some(dir) = self.directory_buffer_mut() {
dir.focus = dir.total.max(1) - 1;
self.msg_out.push_back(MsgOut::Refresh);
};
Ok(self)
if let Some(n) = self.focused_node() {
self.history = history.push(n.absolute_path().clone());
}
self.refresh()
} else {
Ok(self)
}
}
fn focus_previous(mut self) -> Result<Self> {
if let Some(dir) = self.directory_buffer_mut() {
dir.focus = dir.focus.max(1) - 1;
self.msg_out.push_back(MsgOut::Refresh);
};
Ok(self)
self.refresh()
} else {
Ok(self)
}
}
fn focus_previous_by_relative_index(mut self, index: usize) -> Result<Self> {
let history = self.history.clone();
if let Some(dir) = self.directory_buffer_mut() {
dir.focus = dir.focus.max(index) - index;
self.msg_out.push_back(MsgOut::Refresh);
};
Ok(self)
if let Some(n) = self.focused_node() {
self.history = history.push(n.absolute_path().clone());
}
self.refresh()
} else {
Ok(self)
}
}
fn focus_previous_by_relative_index_from_input(self) -> Result<Self> {
@ -1851,17 +1875,23 @@ impl App {
fn focus_next(mut self) -> Result<Self> {
if let Some(dir) = self.directory_buffer_mut() {
dir.focus = (dir.focus + 1).min(dir.total.max(1) - 1);
self.msg_out.push_back(MsgOut::Refresh);
};
Ok(self)
self.refresh()
} else {
Ok(self)
}
}
fn focus_next_by_relative_index(mut self, index: usize) -> Result<Self> {
let history = self.history.clone();
if let Some(dir) = self.directory_buffer_mut() {
dir.focus = (dir.focus + index).min(dir.total.max(1) - 1);
self.msg_out.push_back(MsgOut::Refresh);
};
Ok(self)
if let Some(n) = self.focused_node() {
self.history = history.push(n.absolute_path().clone());
}
self.refresh()
} else {
Ok(self)
}
}
fn focus_next_by_relative_index_from_input(self) -> Result<Self> {
@ -1877,17 +1907,19 @@ impl App {
.focused_node()
.and_then(|n| n.symlink.to_owned().map(|s| s.absolute_path))
{
self.focus_path(&pth)
self.focus_path(&pth, true)
} else {
Ok(self)
}
}
fn change_directory(mut self, dir: &str) -> Result<Self> {
fn change_directory(mut self, dir: &str, save_history: bool) -> Result<Self> {
match env::set_current_dir(dir) {
Ok(()) => {
self.pwd = dir.to_owned();
self.history = self.history.push(self.pwd.clone());
if save_history {
self.history = self.history.push(format!("{}/", self.pwd));
}
self.explore_pwd_async()
}
Err(e) => self.log_error(e.to_string()),
@ -1897,7 +1929,7 @@ impl App {
fn enter(self) -> Result<Self> {
self.focused_node()
.map(|n| n.absolute_path.clone())
.map(|p| self.clone().change_directory(&p))
.map(|p| self.clone().change_directory(&p, true))
.unwrap_or(Ok(self))
}
@ -1906,31 +1938,41 @@ impl App {
.parent()
.map(|p| {
self.clone()
.change_directory(&p.to_string_lossy().to_string())
.change_directory(&p.to_string_lossy().to_string(), true)
})
.unwrap_or(Ok(self))
}
fn last_visited_path(mut self) -> Result<Self> {
self.history = self.history.visit_last();
self.pwd = self
.history
.peek()
.map(|p| p.to_owned())
.unwrap_or(self.pwd);
env::set_current_dir(&self.pwd)?;
self.explore_pwd_async()
if let Some(target) = self.history.peek() {
if target.ends_with('/') {
target
.strip_suffix('/')
.map(|s| self.clone().change_directory(s, false))
.unwrap_or(Ok(self))
} else {
self.clone().focus_path(target, false)
}
} else {
Ok(self)
}
}
fn next_visited_path(mut self) -> Result<Self> {
self.history = self.history.visit_next();
self.pwd = self
.history
.peek()
.map(|p| p.to_owned())
.unwrap_or(self.pwd);
env::set_current_dir(&self.pwd)?;
self.explore_pwd_async()
if let Some(target) = self.history.peek() {
if target.ends_with('/') {
target
.strip_suffix('/')
.map(|s| self.clone().change_directory(s, false))
.unwrap_or(Ok(self))
} else {
self.clone().focus_path(target, false)?.refresh()
}
} else {
Ok(self)
}
}
fn buffer_input(mut self, input: &str) -> Result<Self> {
@ -1995,8 +2037,12 @@ impl App {
}
fn focus_by_index(mut self, index: usize) -> Result<Self> {
let history = self.history.clone();
if let Some(dir) = self.directory_buffer_mut() {
dir.focus = index.min(dir.total.max(1) - 1);
if let Some(n) = self.focused_node() {
self.history = history.push(n.absolute_path().clone());
}
self.refresh()
} else {
Ok(self)
@ -2011,7 +2057,8 @@ impl App {
}
}
fn focus_by_file_name(mut self, name: &str) -> Result<Self> {
fn focus_by_file_name(mut self, name: &str, save_history: bool) -> Result<Self> {
let history = self.history.clone();
if let Some(dir_buf) = self.directory_buffer_mut() {
if let Some(focus) = dir_buf
.clone()
@ -2022,6 +2069,11 @@ impl App {
.map(|(i, _)| i)
{
dir_buf.focus = focus;
if save_history {
if let Some(n) = dir_buf.focused_node() {
self.history = history.push(n.absolute_path().clone());
}
}
self.refresh()
} else {
self.log_error(format!("{} not found in $PWD", name))
@ -2031,12 +2083,12 @@ impl App {
}
}
fn focus_path(self, path: &str) -> Result<Self> {
fn focus_path(self, path: &str, save_history: bool) -> Result<Self> {
let pathbuf = PathBuf::from(path);
if let Some(parent) = pathbuf.parent() {
if let Some(filename) = pathbuf.file_name() {
self.change_directory(&parent.to_string_lossy().to_string())?
.focus_by_file_name(&filename.to_string_lossy().to_string())
self.change_directory(&parent.to_string_lossy().to_string(), false)?
.focus_by_file_name(&filename.to_string_lossy().to_string(), save_history)
} else {
self.log_error(format!("{} not found", path))
}
@ -2047,7 +2099,7 @@ impl App {
fn focus_path_from_input(self) -> Result<Self> {
if let Some(p) = self.input_buffer() {
self.focus_path(&p)
self.focus_path(&p, true)
} else {
Ok(self)
}

@ -133,23 +133,6 @@ pub fn run(
terminal.clear()?;
}
app::MsgOut::ExplorePwd => {
match explorer::explore_sync(
app.explorer_config().clone(),
app.pwd().clone(),
app.focused_node().map(|n| n.relative_path().clone()),
) {
Ok(buf) => {
let pwd = buf.parent().clone();
app = app.add_directory(pwd.clone(), buf)?;
}
Err(e) => {
app = app.log_error(e.to_string())?;
}
};
tx_pwd_watcher.send(app.pwd().clone())?;
}
app::MsgOut::ExplorePwdAsync => {
explorer::explore_async(
app.explorer_config().clone(),

Loading…
Cancel
Save