Fixed fzf search added pwd shell option

Now I can finally use it to replace nnn
pull/3/head
Arijit Basu 3 years ago
parent 980fb8728a
commit 044b7860a1
No known key found for this signature in database
GPG Key ID: 7D7BF809E7378863

2
Cargo.lock generated

@ -1133,7 +1133,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "xplr"
version = "0.1.5"
version = "0.1.7"
dependencies = [
"criterion",
"crossterm",

@ -1,6 +1,6 @@
[package]
name = "xplr"
version = "0.1.5"
version = "0.1.7" # Update app.rs
authors = ["Arijit Basu <sayanarijit@gmail.com>"]
edition = "2018"
description = "An experimental, minimal, configurable TUI file explorer, stealing ideas from nnn and fzf."

@ -14,6 +14,7 @@ use std::io::BufReader;
use std::path::Path;
use std::path::PathBuf;
pub const VERSION: &str = "v0.1.7"; // Update Cargo.toml
pub const UNSUPPORTED_STR: &str = "???";
pub const TOTAL_ROWS: usize = 50;
@ -39,8 +40,9 @@ fn expand_tilde<P: AsRef<Path>>(path_user_input: P) -> Option<PathBuf> {
})
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DirectoryBuffer {
pub pwd: PathBuf,
pub focus: Option<usize>,
pub items: Vec<(PathBuf, DirectoryItemMetadata)>,
pub total: usize,
@ -214,6 +216,7 @@ impl DirectoryBuffer {
});
Ok(Self {
pwd: path.into(),
total,
items: visible,
focus,
@ -255,10 +258,10 @@ pub struct DirectoryItemMetadata {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct App {
pub version: String,
pub config: Config,
pub pwd: PathBuf,
pub directory_buffer: DirectoryBuffer,
pub saved_buffers: HashMap<PathBuf, DirectoryBuffer>,
pub saved_buffers: HashMap<PathBuf, Option<usize>>,
pub selected_paths: HashSet<PathBuf>,
pub mode: Mode,
pub show_hidden: bool,
@ -270,21 +273,24 @@ impl App {
pub fn new(
config: &Config,
pwd: &PathBuf,
saved_buffers: &HashMap<PathBuf, DirectoryBuffer>,
saved_buffers: &HashMap<PathBuf, Option<usize>>,
selected_paths: &HashSet<PathBuf>,
mode: Mode,
show_hidden: bool,
focus: Option<usize>,
) -> Result<Self, Error> {
let directory_buffer =
DirectoryBuffer::load(config, focus.or(Some(0)), pwd, show_hidden, selected_paths)?;
DirectoryBuffer::load(config, focus.or(Some(0)), &pwd, show_hidden, selected_paths)?;
let mut saved_buffers = saved_buffers.clone();
saved_buffers.insert(pwd.into(), directory_buffer.to_owned());
saved_buffers.insert(
directory_buffer.pwd.clone().into(),
directory_buffer.focus.clone(),
);
Ok(Self {
version: VERSION.into(),
config: config.to_owned(),
pwd: pwd.to_owned(),
directory_buffer,
saved_buffers,
selected_paths: selected_paths.to_owned(),
@ -309,7 +315,7 @@ impl App {
pub fn toggle_hidden(self) -> Result<Self, Error> {
Self::new(
&self.config,
&self.pwd,
&self.directory_buffer.pwd,
&self.saved_buffers,
&self.selected_paths,
self.mode,
@ -327,7 +333,7 @@ impl App {
Self::new(
&self.config,
&self.pwd,
&self.directory_buffer.pwd,
&self.saved_buffers,
&self.selected_paths,
self.mode,
@ -345,7 +351,7 @@ impl App {
Self::new(
&self.config,
&self.pwd,
&self.directory_buffer.pwd,
&self.saved_buffers,
&self.selected_paths,
self.mode,
@ -373,7 +379,7 @@ impl App {
Self::new(
&self.config,
&self.pwd,
&self.directory_buffer.pwd,
&self.saved_buffers,
&self.selected_paths,
self.mode,
@ -395,7 +401,7 @@ impl App {
Self::new(
&self.config,
&self.pwd,
&self.directory_buffer.pwd,
&self.saved_buffers,
&self.selected_paths,
self.mode,
@ -437,7 +443,7 @@ impl App {
pub fn focus_by_index(self, idx: &usize) -> Result<Self, Error> {
Self::new(
&self.config,
&self.pwd,
&self.directory_buffer.pwd,
&self.saved_buffers,
&self.selected_paths,
self.mode.clone(),
@ -449,7 +455,7 @@ impl App {
pub fn focus_by_buffer_relative_index(self, idx: &usize) -> Result<Self, Error> {
Self::new(
&self.config,
&self.pwd,
&self.directory_buffer.pwd,
&self.saved_buffers,
&self.selected_paths,
self.mode.clone(),
@ -461,7 +467,7 @@ impl App {
pub fn focus_by_focus_relative_index(self, idx: &isize) -> Result<Self, Error> {
Self::new(
&self.config,
&self.pwd,
&self.directory_buffer.pwd,
&self.saved_buffers,
&self.selected_paths,
self.mode.clone(),
@ -477,10 +483,16 @@ impl App {
.directory_buffer
.focused_item()
.map(|(p, _)| p)
.map(|p| if p.is_dir() { p } else { self.pwd.clone() })
.unwrap_or_else(|| self.pwd.clone());
.map(|p| {
if p.is_dir() {
p
} else {
self.directory_buffer.pwd.clone()
}
})
.unwrap_or_else(|| self.directory_buffer.pwd.clone());
let focus = self.saved_buffers.get(&pwd).and_then(|b| b.focus);
let focus = self.saved_buffers.get(&pwd).unwrap_or(&None);
Self::new(
&self.config,
@ -489,13 +501,13 @@ impl App {
&self.selected_paths,
self.mode,
self.show_hidden,
focus,
focus.clone(),
)
}
pub fn back(self) -> Result<Self, Error> {
let app = self.clone();
self.focus_path(&app.pwd)
self.focus_path(&app.directory_buffer.pwd)
}
pub fn select(self) -> Result<Self, Error> {
@ -559,7 +571,7 @@ impl App {
pub fn print_pwd(self) -> Result<Self, Error> {
let mut app = self;
app.result = app.pwd.to_str().map(|s| s.to_string());
app.result = app.directory_buffer.pwd.to_str().map(|s| s.to_string());
Ok(app)
}
@ -747,16 +759,29 @@ pub fn create() -> Result<App, Error> {
let config_file = config_dir.join("config.yml");
let config: Config = if config_file.exists() {
serde_yaml::from_reader(BufReader::new(&File::open(config_file)?))?
serde_yaml::from_reader(BufReader::new(&File::open(&config_file)?))?
} else {
Config::default()
};
let pwd = PathBuf::from("./")
if !config.version.eq(VERSION) {
return Err(Error::IncompatibleVersion(
format!("Config file {} is outdated", config_file.to_string_lossy()),
));
}
let root = Path::new("/");
let pwd = PathBuf::from(std::env::args().skip(1).next().unwrap_or("./".into()))
.canonicalize()
.unwrap_or(PathBuf::from("/"));
.unwrap_or(root.into());
let (pwd, file_to_focus) = if pwd.is_file() {
(pwd.parent().unwrap_or(root).into(), Some(pwd))
} else {
(pwd, None)
};
App::new(
let app = App::new(
&config,
&pwd,
&Default::default(),
@ -764,5 +789,11 @@ pub fn create() -> Result<App, Error> {
Mode::Explore,
config.general.show_hidden,
None,
)
)?;
if let Some(file) = file_to_focus {
app.focus_path(&file)
} else {
Ok(app)
}
}

@ -1,3 +1,4 @@
use crate::app::VERSION;
use crate::input::Key;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@ -32,6 +33,8 @@ impl Default for Format {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CommandConfig {
pub command: String,
#[serde(default)]
pub args: Vec<String>,
}
@ -187,7 +190,6 @@ impl Default for KeyBindings {
help: print debug info
actions:
- PrintAppState
- Quit
up:
help: up
actions:
@ -200,10 +202,6 @@ impl Default for KeyBindings {
help: bottom
actions:
- FocusLast
forward-slash:
help: go root
actions:
- ChangeDirectory: /
tilde:
help: go home
actions:
@ -227,14 +225,14 @@ impl Default for KeyBindings {
command: bash
args:
- "-c"
- "xdg-open {{shell_escape absolutePath}} &> /dev/null"
- FILE="{{shellescape relativePath}}" && xdg-open "${FILE:?}" &> /dev/null
e:
help: edit
actions:
- Call:
command: vim
args:
- "{{absolutePath}}"
- "{{shellescape relativePath}}"
forward-slash:
help: search
actions:
@ -242,17 +240,14 @@ impl Default for KeyBindings {
command: bash
args:
- "-c"
- "cd $(dirname {{shell_escape absolutePath}}) && fzf"
- FILE="$(ls -a | fzf)" && xplr "${FILE:?}" || xplr "${PWD:?}"
- Quit
c:
help: copy to
s:
help: shell
actions:
- Call:
command: bash
args:
- "-c"
- "cp {{shell_escape absolutePath}} $(xplr)/"
escape:
help: quit
@ -268,7 +263,6 @@ impl Default for KeyBindings {
help: done
actions:
- PrintFocused
- Quit
space:
help: select
actions:
@ -505,8 +499,10 @@ impl Default for GeneralConfig {
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub version: String,
#[serde(default)]
pub general: GeneralConfig,
@ -516,3 +512,14 @@ pub struct Config {
#[serde(default)]
pub key_bindings: KeyBindings,
}
impl Default for Config {
fn default() -> Self {
Self {
version: VERSION.into(),
general: Default::default(),
filetypes: Default::default(),
key_bindings: Default::default(),
}
}
}

@ -4,6 +4,7 @@ use serde_yaml;
#[derive(Debug)]
pub enum Error {
IncompatibleVersion(String),
Terminated,
// Real errors

@ -12,13 +12,13 @@ use xplr::error::Error;
use xplr::input::Key;
use xplr::ui;
handlebars_helper!(shell_escape: |v: str| format!("{}", shellwords::escape(v)));
handlebars_helper!(shellescape: |v: str| format!("{}", shellwords::escape(v)));
fn main() -> Result<(), Error> {
let mut app = app::create()?;
let mut hb = Handlebars::new();
hb.register_helper("shell_escape", Box::new(shell_escape));
hb.register_helper("shellescape", Box::new(shellescape));
hb.register_template_string(
app::TEMPLATE_TABLE_ROW,
&app.config
@ -73,6 +73,7 @@ fn main() -> Result<(), Error> {
std::mem::drop(terminal);
if let Some((_, meta)) = a.directory_buffer.focused_item() {
let _ = std::process::Command::new(cmd.command.clone())
.current_dir(&a.directory_buffer.pwd)
.args(
cmd.args
.iter()

@ -72,11 +72,10 @@ pub fn draw<B: Backend>(
.style(app.config.general.table.style)
.highlight_style(app.config.general.focused_ui.style)
.column_spacing(app.config.general.table.col_spacing)
.block(
Block::default()
.borders(Borders::ALL)
.title(format!(" {} ", app.pwd.to_str().unwrap_or("???"))),
);
.block(Block::default().borders(Borders::ALL).title(format!(
" {} ",
app.directory_buffer.pwd.to_str().unwrap_or("???")
)));
let table = app
.config

Loading…
Cancel
Save