summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/joshuto.toml1
-rw-r--r--src/commands/change_directory.rs4
-rw-r--r--src/commands/open_file.rs102
-rw-r--r--src/config/config.rs5
-rw-r--r--src/config/keymap.rs16
-rw-r--r--src/config/mimetype.rs18
-rw-r--r--src/history.rs3
-rw-r--r--src/preview.rs21
8 files changed, 103 insertions, 67 deletions
diff --git a/config/joshuto.toml b/config/joshuto.toml
index af5be15..de8c952 100644
--- a/config/joshuto.toml
+++ b/config/joshuto.toml
@@ -6,6 +6,7 @@ column_ratio = [1, 4, 4]
scroll_offset = 6
show_preview = true
+xdg_open = false
max_preview_size = 2097152 # 2MB
# lexical, mtime, natural
diff --git a/src/commands/change_directory.rs b/src/commands/change_directory.rs
index 3ec1946..d62964e 100644
--- a/src/commands/change_directory.rs
+++ b/src/commands/change_directory.rs
@@ -33,7 +33,9 @@ impl ChangeDirectory {
std::mem::swap(&mut curr_tab.curr_list, &mut curr_list);
- curr_tab.history.insert(curr_list.file_path().clone(), curr_list);
+ curr_tab
+ .history
+ .insert(curr_list.file_path().clone(), curr_list);
curr_tab.curr_path = path.clone();
curr_tab
diff --git a/src/commands/open_file.rs b/src/commands/open_file.rs
index c5c1c90..419cefe 100644
--- a/src/commands/open_file.rs
+++ b/src/commands/open_file.rs
@@ -1,9 +1,9 @@
use std::path::{Path, PathBuf};
use crate::commands::{JoshutoCommand, JoshutoRunnable};
-use crate::config::mimetype;
+use crate::config::mimetype::JoshutoMimetypeEntry;
use crate::context::JoshutoContext;
-use crate::error::JoshutoResult;
+use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult};
use crate::history::DirectoryHistory;
use crate::textfield::JoshutoTextField;
use crate::ui;
@@ -24,8 +24,8 @@ impl OpenFile {
"open_file"
}
- pub fn get_options<'a>(path: &Path) -> Vec<&'a mimetype::JoshutoMimetypeEntry> {
- let mut mimetype_options: Vec<&mimetype::JoshutoMimetypeEntry> = Vec::new();
+ pub fn get_options<'a>(path: &Path) -> Vec<&'a JoshutoMimetypeEntry> {
+ let mut mimetype_options: Vec<&JoshutoMimetypeEntry> = Vec::new();
/* extensions have priority */
if let Some(file_ext) = path.extension() {
@@ -67,7 +67,18 @@ impl OpenFile {
let err = std::io::Error::new(std::io::ErrorKind::NotFound, "No files selected");
return Err(err);
}
- Self::open_file(&paths);
+ let mimetype_options = Self::get_options(&paths[0]);
+ if !mimetype_options.is_empty() {
+ mimetype_options[0].execute_with(&paths);
+ } else if context.config_t.xdg_open {
+ ncurses::savetty();
+ ncurses::endwin();
+ open::that(paths[0]).unwrap();
+ ncurses::resetty();
+ ncurses::refresh();
+ } else {
+ OpenFileWith::open_with(&paths);
+ }
let curr_tab = &mut context.tabs[context.curr_tab_index];
if curr_tab.curr_list.need_update() {
curr_tab
@@ -99,21 +110,6 @@ impl OpenFile {
curr_tab.curr_path = path.to_path_buf().clone();
Ok(())
}
-
- fn open_file(paths: &[&PathBuf]) {
- let mimetype_options = Self::get_options(&paths[0]);
-
- ncurses::savetty();
- ncurses::endwin();
- if mimetype_options.is_empty() {
- open::that(&paths[0]).unwrap();
- } else {
- mimetype_options[0].execute_with(paths);
- }
- ncurses::resetty();
- ncurses::refresh();
- ncurses::doupdate();
- }
}
impl JoshutoCommand for OpenFile {}
@@ -142,11 +138,10 @@ impl OpenFileWith {
"open_file_with"
}
- pub fn open_with(paths: &[&PathBuf]) {
+ pub fn open_with(paths: &[&PathBuf]) -> JoshutoResult<()> {
const PROMPT: &str = ":open_with ";
- let mimetype_options: Vec<&mimetype::JoshutoMimetypeEntry> =
- OpenFile::get_options(&paths[0]);
+ let mimetype_options: Vec<&JoshutoMimetypeEntry> = OpenFile::get_options(&paths[0]);
let user_input: Option<String>;
{
let (term_rows, term_cols) = ui::getmaxyx();
@@ -174,30 +169,42 @@ impl OpenFileWith {
}
ncurses::doupdate();
- if let Some(user_input) = user_input {
- if user_input.is_empty() {
- return;
- }
- match user_input.parse::<usize>() {
- Ok(s) => {
- if s < mimetype_options.len() {
- ncurses::savetty();
- ncurses::endwin();
- mimetype_options[s].execute_with(paths);
- ncurses::resetty();
- ncurses::refresh();
+ match user_input.as_ref() {
+ None => Ok(()),
+ Some(user_input) if user_input.is_empty() => Ok(()),
+ Some(user_input) => match user_input.parse::<usize>() {
+ Ok(n) => {
+ if n < mimetype_options.len() {
+ mimetype_options[n].execute_with(paths);
+ Ok(())
+ } else {
+ Err(JoshutoError::new(
+ JoshutoErrorKind::IOInvalidData,
+ "option does not exist".to_owned(),
+ ))
}
}
Err(_) => {
- let args: Vec<String> =
- user_input.split_whitespace().map(String::from).collect();
- ncurses::savetty();
- ncurses::endwin();
- unix::open_with_args(paths, &args);
- ncurses::resetty();
- ncurses::refresh();
+ let mut args_iter = user_input.split_whitespace();
+ match args_iter.next() {
+ Some(s) => {
+ let command = String::from(s);
+ let args = args_iter.map(String::from).collect();
+ let entry = JoshutoMimetypeEntry {
+ id: 0,
+ command,
+ args,
+ fork: true,
+ silent: false,
+ confirm_exit: true,
+ };
+ entry.execute_with(paths);
+ }
+ None => {}
+ }
+ Ok(())
}
- }
+ },
}
}
}
@@ -213,6 +220,15 @@ impl std::fmt::Display for OpenFileWith {
impl JoshutoRunnable for OpenFileWith {
fn execute(&self, context: &mut JoshutoContext, _: &JoshutoView) -> JoshutoResult<()> {
let curr_list = &context.tabs[context.curr_tab_index].curr_list;
+ match curr_list.index {
+ None => {
+ return Err(JoshutoError::new(
+ JoshutoErrorKind::IONotFound,
+ String::from("No files selected"),
+ ))
+ }
+ Some(_) => {}
+ }
let paths = curr_list.get_selected_paths();
Self::open_with(&paths);
Ok(())
diff --git a/src/config/config.rs b/src/config/config.rs
index f093d79..f4f962e 100644
--- a/src/config/config.rs
+++ b/src/config/config.rs
@@ -61,6 +61,8 @@ pub struct JoshutoRawConfig {
tilde_in_titlebar: bool,
#[serde(default = "default_true")]
show_preview: bool,
+ #[serde(default)]
+ xdg_open: bool,
#[serde(default = "default_max_preview_size")]
max_preview_size: u64,
column_ratio: Option<[usize; 3]>,
@@ -89,6 +91,7 @@ impl Flattenable<JoshutoConfig> for JoshutoRawConfig {
scroll_offset: self.scroll_offset,
tilde_in_titlebar: self.tilde_in_titlebar,
show_preview: self.show_preview,
+ xdg_open: self.xdg_open,
max_preview_size: self.max_preview_size,
column_ratio,
sort_option,
@@ -101,6 +104,7 @@ pub struct JoshutoConfig {
pub scroll_offset: usize,
pub tilde_in_titlebar: bool,
pub show_preview: bool,
+ pub xdg_open: bool,
pub max_preview_size: u64,
pub sort_option: sort::SortOption,
pub column_ratio: (usize, usize, usize),
@@ -121,6 +125,7 @@ impl std::default::Default for JoshutoConfig {
scroll_offset: default_scroll_offset(),
tilde_in_titlebar: default_true(),
show_preview: default_true(),
+ xdg_open: false,
max_preview_size: default_max_preview_size(),
sort_option,
column_ratio: default_column_ratio(),
diff --git a/src/config/keymap.rs b/src/config/keymap.rs
index 6916d49..8735a00 100644
--- a/src/config/keymap.rs
+++ b/src/config/keymap.rs
@@ -55,6 +55,14 @@ const fn default_tab() -> i32 {
}
#[derive(Debug, Deserialize)]
+struct JoshutoMapCommand {
+ pub command: String,
+ #[serde(default)]
+ pub args: Vec<String>,
+ pub keys: Vec<i32>,
+}
+
+#[derive(Debug, Deserialize)]
struct JoshutoRawKeymapping {
#[serde(default)]
keymaps: JoshutoKeyMapping,
@@ -126,14 +134,6 @@ impl ConfigStructure for JoshutoKeyMapping {
}
#[derive(Debug, Deserialize)]
-struct JoshutoMapCommand {
- pub command: String,
- #[serde(default)]
- pub args: Vec<String>,
- pub keys: Vec<i32>,
-}
-
-#[derive(Debug, Deserialize)]
struct JoshutoRawCommandMapping {
#[serde(skip)]
keymaps: JoshutoKeyMapping,
diff --git a/src/config/mimetype.rs b/src/config/mimetype.rs
index 2b20e3d..891a201 100644
--- a/src/config/mimetype.rs
+++ b/src/config/mimetype.rs
@@ -14,16 +14,16 @@ const fn default_false() -> bool {
#[derive(Debug, Deserialize)]
pub struct JoshutoMimetypeEntry {
- id: usize,
- command: String,
+ pub id: usize,
+ pub command: String,
#[serde(default)]
- args: Vec<String>,
+ pub args: Vec<String>,
#[serde(default = "default_false")]
- fork: bool,
+ pub fork: bool,
#[serde(default = "default_false")]
- silent: bool,
+ pub silent: bool,
#[serde(default = "default_false")]
- confirm_exit: bool,
+ pub confirm_exit: bool,
}
impl JoshutoMimetypeEntry {
@@ -66,15 +66,19 @@ impl JoshutoMimetypeEntry {
match command.spawn() {
Ok(mut handle) => {
if !self.get_fork() {
+ ncurses::savetty();
+ ncurses::endwin();
match handle.wait() {
Ok(_) => {
if self.get_confirm_exit() {
- println!(" --- Press any key to continue --- ");
+ println!(" --- Press ENTER to continue --- ");
std::io::stdin().bytes().next();
}
}
Err(e) => eprintln!("{}", e),
}
+ ncurses::resetty();
+ ncurses::refresh();
}
}
Err(e) => eprintln!("{}", e),
diff --git a/src/history.rs b/src/history.rs
index 7333af7..e843d29 100644
--- a/src/history.rs
+++ b/src/history.rs
@@ -43,7 +43,8 @@ impl DirectoryHistory for JoshutoHistory {
}
}
Entry::Vacant(entry) => {
- let mut dirlist = JoshutoDirList::new(curr.to_path_buf().clone(), sort_option)?;
+ let mut dirlist =
+ JoshutoDirList::new(curr.to_path_buf().clone(), sort_option)?;
if let Some(i) = get_index_of_value(&dirlist.contents, &ancestor) {
dirlist.index = Some(i);
}
diff --git a/src/preview.rs b/src/preview.rs
index 282ae43..0f97a22 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -47,15 +47,21 @@ fn preview_directory(
path: &path::Path,
win: &JoshutoPanel,
config_t: &JoshutoConfig,
-) {
+) -> std::io::Result<()> {
match history.entry(path.to_path_buf().clone()) {
Entry::Occupied(mut entry) => {
- ui::display_contents(
- win,
- entry.get_mut(),
- config_t,
- &ui::SECONDARY_DISPLAY_OPTION,
- );
+ let mut dirlist = entry.get_mut();
+ if dirlist.need_update() {
+ dirlist.reload_contents(&config_t.sort_option)?
+ } else {
+ let metadata = std::fs::symlink_metadata(dirlist.file_path())?;
+
+ let modified = metadata.modified()?;
+ if modified > dirlist.metadata.modified {
+ dirlist.reload_contents(&config_t.sort_option)?
+ }
+ }
+ ui::display_contents(win, dirlist, config_t, &ui::SECONDARY_DISPLAY_OPTION);
}
Entry::Vacant(entry) => {
if let Ok(s) = JoshutoDirList::new(path.to_path_buf().clone(), &config_t.sort_option) {
@@ -69,6 +75,7 @@ fn preview_directory(
}
}
win.queue_for_refresh();
+ Ok(())
}
fn preview_file(entry: &JoshutoDirEntry, win: &JoshutoPanel) {