From 41713f9aff6e5eabd11fc5b91a2ba0ad6ebd9903 Mon Sep 17 00:00:00 2001 From: Arijit Basu Date: Mon, 1 Mar 2021 21:32:30 +0530 Subject: [PATCH] Basically working now. --- README.md | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- config.yml | 38 +++++++++++++++++++++++++++++++------- src/main.rs | 35 +++++++++++++++++++++++++---------- 3 files changed, 102 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 20963e2..f46fed1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,47 @@ -A Hackable TUI File Explorer -============================ +An experimental, minimal, configurable TUI file explorer, stealing ideas from `nnn` and `fzf`. -Don't run it without copying the `config.yml` inside `~/.config/xplr`. +![Screenshot](https://user-images.githubusercontent.com/11632726/109526906-1b555080-7ad9-11eb-9fd7-03e092220618.gif) + + +Example usage: +-------------- + +```bash +# Edit file +vim $(xplr) + +# Copy file(s) +cp $(xplr) $(xplr) + +# Search and move file +mv $(fzf) $(xplr) +``` + + +Let's brainstorm +---------------- + +You can also experiment and help by suggesting ideas/opinions. + +1. Install + +```bash +cargo install xplr +``` + +2. Create config directory `~/.config/xplr/` and place the [`config.yml`](https://github.com/sayanarijit/xplr/blob/main/config.yml) file inside it. + +3. Check the key bindings in the config file. + +4. Run `xplr`. + + +TODO research +------------- + +- [ ] Research FIFO/socket options for better integration with other tools. +- [ ] Research saner configuration formats. +- [ ] Research saner key binding options. +- [ ] Research how to go beyond filesystem and explore any tree-like structure. +- [ ] CLI options and help menu. +- [ ] Go beyond research and implement things. diff --git a/config.yml b/config.yml index cc33b9f..626bad4 100644 --- a/config.yml +++ b/config.yml @@ -49,7 +49,7 @@ general: style: fg: LightGreen add_modifier: - bits: 0 + bits: 1 sub_modifier: bits: 0 @@ -98,6 +98,10 @@ key_bindings: help: quit actions: - Quit + question-mark: + help: print debug info + actions: + - PrintAppStateAndQuit left: help: back actions: @@ -113,16 +117,16 @@ key_bindings: up: help: up actions: - - FocusPreviousItem + - FocusPrevious down: help: down actions: - - FocusNextItem + - FocusNext shift-g: help: bottom actions: - - FocusLastItem + - FocusLast tilda: help: go home @@ -139,18 +143,22 @@ key_bindings: help: select actions: - Select - - FocusNextItem + - FocusNext g: help: go to actions: - EnterSubmode: GoTo + return: + help: done + actions: + - PrintFocusedAndQuit explore_submodes: GoTo: g: help: top actions: - - FocusFirstItem + - FocusFirst - ExitSubmode select_mode: @@ -158,4 +166,20 @@ key_bindings: help: toggle selection actions: - ToggleSelection - - FocusNextItem + - FocusNext + g: + help: go to + actions: + - EnterSubmode: GoTo + return: + help: done + actions: + - PrintSelectedAndQuit + + select_submodes: + GoTo: + g: + help: top + actions: + - FocusFirst + - ExitSubmode diff --git a/src/main.rs b/src/main.rs index 2980323..f753a7c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ +use crossterm::terminal as term; use handlebars::Handlebars; use std::io; -use termion::{input::MouseTerminal, input::TermRead, raw::IntoRawMode, screen::AlternateScreen}; +use termion::get_tty; +use termion::{input::TermRead, screen::AlternateScreen}; use tui::backend::CrosstermBackend; use tui::widgets::{ListState, TableState}; use tui::Terminal; @@ -27,8 +29,8 @@ fn main() -> Result<(), Error> { .join("\t"), )?; - let stdout = io::stdout().into_raw_mode()?; - let stdout = MouseTerminal::from(stdout); + let stdout = get_tty()?; + // let stdout = MouseTerminal::from(stdout); let stdout = AlternateScreen::from(stdout); let stdin = io::stdin(); let backend = CrosstermBackend::new(stdout); @@ -41,21 +43,34 @@ fn main() -> Result<(), Error> { let mut table_state = TableState::default(); let mut list_state = ListState::default(); + term::enable_raw_mode().unwrap(); terminal.draw(|f| ui::draw(&app, &hb, f, &mut table_state, &mut list_state))?; + let mut result = Ok(()); 'outer: for key in keys { if let Some(actions) = app.actions_from_key(key) { for action in actions.iter() { - app = app.handle(action)?; - terminal.draw(|f| ui::draw(&app, &hb, f, &mut table_state, &mut list_state))?; - if app.result.is_some() { - break 'outer; + app = match app.handle(action) { + Ok(a) => { + terminal + .draw(|f| ui::draw(&a, &hb, f, &mut table_state, &mut list_state))?; + if a.result.is_some() { + term::disable_raw_mode().unwrap(); + std::mem::drop(terminal); + println!("{}", &a.result.unwrap_or("".into())); + break 'outer; + }; + a + } + Err(e) => { + term::disable_raw_mode().unwrap(); + result = Err(e); + break 'outer; + } } } }; } - std::mem::drop(terminal); - println!("{}", app.result.unwrap_or("".into())); - Ok(()) + result }