summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqkzk <qu3nt1n@gmail.com>2022-10-04 22:24:00 +0200
committerqkzk <qu3nt1n@gmail.com>2022-10-04 22:24:00 +0200
commitc4130dd55c5fd781b4fbe0054afa298d1c417e1f (patch)
tree659fa28b0a53de1d1dd3de1b6f7663d18fab4d2f
parent8bf51e2f9efdc5cd417d942d4e50fa8046f602dc (diff)
preview a file with Ppreview
-rw-r--r--config.yaml1
-rw-r--r--readme.md1
-rw-r--r--src/actioner.rs5
-rw-r--r--src/config.rs9
-rw-r--r--src/display.rs33
-rw-r--r--src/event_char.rs2
-rw-r--r--src/fileinfo.rs10
-rw-r--r--src/help.rs2
-rw-r--r--src/mode.rs3
-rw-r--r--src/status.rs64
10 files changed, 109 insertions, 21 deletions
diff --git a/config.yaml b/config.yaml
index bc9c61e..a39d053 100644
--- a/config.yaml
+++ b/config.yaml
@@ -40,3 +40,4 @@ keybindings:
nvim: i
sort_by: O
symlink: S
+ preview: P
diff --git a/readme.md b/readme.md
index e1ba5cd..3bdb23c 100644
--- a/readme.md
+++ b/readme.md
@@ -78,6 +78,7 @@
- https://github.com/KillTheMule/nvim-rs/blob/master/examples/basic.rs
- https://neovim.io/doc/user/api.html
- [ ] display / event separation. use async and message passing between coroutines
+- [ ] less or cat/bat a file content, window with preview
## BUGS
diff --git a/src/actioner.rs b/src/actioner.rs
index 490c07f..fd09ca4 100644
--- a/src/actioner.rs
+++ b/src/actioner.rs
@@ -43,6 +43,7 @@ impl Actioner {
(keybindings.nvim, EventChar::NvimFilepicker),
(keybindings.sort_by, EventChar::Sort),
(keybindings.symlink, EventChar::Symlink),
+ (keybindings.preview, EventChar::Preview),
]);
Self { binds }
}
@@ -207,7 +208,7 @@ impl Actioner {
Mode::Goto => status.exec_goto(),
Mode::RegexMatch => status.exec_regex(),
Mode::Jump => status.exec_jump(),
- Mode::Normal | Mode::NeedConfirmation | Mode::Help | Mode::Sort => (),
+ Mode::Normal | Mode::NeedConfirmation | Mode::Help | Mode::Sort | Mode::Preview => (),
}
status.input.reset();
@@ -248,7 +249,7 @@ impl Actioner {
Some(event_char) => event_char.match_char(status),
None => (),
},
- Mode::Help => status.event_normal(),
+ Mode::Help | Mode::Preview => status.event_normal(),
Mode::Jump => (),
Mode::NeedConfirmation => {
if c == 'y' {
diff --git a/src/config.rs b/src/config.rs
index 9bc9ff8..e0fa5bb 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -50,6 +50,7 @@ use tuikit::attr::Color;
/// jump: j
/// nvim: i
/// sort_by: O
+/// preview: S
#[derive(Debug, Clone)]
pub struct Config {
/// Color of every kind of file
@@ -200,6 +201,8 @@ pub struct Keybindings {
pub sort_by: char,
/// Creates asymlink
pub symlink: char,
+ /// Preview with bat
+ pub preview: char,
}
impl Keybindings {
@@ -275,9 +278,12 @@ impl Keybindings {
if let Some(sort_by) = yaml["sort_by"].as_str().map(|s| s.to_string()) {
self.sort_by = sort_by.chars().next().unwrap_or('O');
}
- if let Some(symlink) = yaml["symblink"].as_str().map(|s| s.to_string()) {
+ if let Some(symlink) = yaml["symlink"].as_str().map(|s| s.to_string()) {
self.symlink = symlink.chars().next().unwrap_or('S');
}
+ if let Some(preview) = yaml["preview"].as_str().map(|s| s.to_string()) {
+ self.preview = preview.chars().next().unwrap_or('P');
+ }
}
/// Returns a new `Keybindings` instance with hardcoded values.
@@ -307,6 +313,7 @@ impl Keybindings {
nvim: 'i',
sort_by: 'O',
symlink: 'S',
+ preview: 'P',
}
}
}
diff --git a/src/display.rs b/src/display.rs
index e38adff..38167d0 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -1,5 +1,7 @@
use std::cmp::min;
+use std::io::BufRead;
+use bat::PrettyPrinter;
use tuikit::attr::*;
use tuikit::term::Term;
@@ -46,6 +48,7 @@ impl Display {
self.help(status);
self.jump_list(status);
self.completion(status);
+ self.preview(status);
}
/// Reads and returns the `tuikit::term::Term` height.
@@ -71,6 +74,10 @@ impl Display {
Mode::NeedConfirmation => {
format!("Confirm {} (y/n) : ", status.last_edition)
}
+ Mode::Preview => match status.path_content.selected_file() {
+ Some(fileinfo) => format!("{:?} {}", status.mode.clone(), fileinfo.filename),
+ None => "".to_owned(),
+ },
_ => {
format!("{:?} {}", status.mode.clone(), status.input.string.clone())
}
@@ -151,7 +158,7 @@ impl Display {
/// Display the possible completion items. The currently selected one is
/// reversed.
- pub fn completion(&mut self, status: &Status) {
+ fn completion(&mut self, status: &Status) {
match status.mode {
Mode::Goto | Mode::Exec | Mode::Search => {
let _ = self.term.clear();
@@ -170,4 +177,28 @@ impl Display {
_ => (),
}
}
+
+ /// Display a preview of a file with bat
+ fn preview(&mut self, status: &Status) {
+ if let Mode::Preview = status.mode {
+ match status.path_content.selected_file() {
+ Some(file) => {
+ let _ = self.term.clear();
+ self.first_line(status);
+ let attr = Attr::default();
+ let reader =
+ std::io::BufReader::new(std::fs::File::open(file.path.clone()).unwrap());
+ for (row, line) in reader.lines().enumerate() {
+ let _ = self.term.print_with_attr(
+ row + 1,
+ 3,
+ &line.unwrap_or("".to_owned()),
+ attr,
+ );
+ }
+ }
+ None => (),
+ }
+ }
+ }
}
diff --git a/src/event_char.rs b/src/event_char.rs
index 7f48d5c..9b3e4fc 100644
--- a/src/event_char.rs
+++ b/src/event_char.rs
@@ -25,6 +25,7 @@ pub enum EventChar {
NvimFilepicker,
Sort,
Symlink,
+ Preview,
}
impl EventChar {
@@ -54,6 +55,7 @@ impl EventChar {
EventChar::NvimFilepicker => status.event_nvim_filepicker(),
EventChar::Sort => status.event_sort(),
EventChar::Symlink => status.event_symlink(),
+ EventChar::Preview => status.event_preview(),
}
}
}
diff --git a/src/fileinfo.rs b/src/fileinfo.rs
index a56ffc6..ee91f03 100644
--- a/src/fileinfo.rs
+++ b/src/fileinfo.rs
@@ -306,6 +306,16 @@ impl PathContent {
self.files[0].select();
}
}
+
+ /// Return the Optional FileInfo
+ /// Since the FileInfo is borrowed it won't be mutable.
+ pub fn selected_file(&self) -> Option<&FileInfo> {
+ if self.files.is_empty() {
+ None
+ } else {
+ Some(&self.files[self.selected])
+ }
+ }
}
/// Associates a filetype to `tuikit::prelude::Attr` : fg color, bg color and
diff --git a/src/help.rs b/src/help.rs
index c03b086..1424201 100644
--- a/src/help.rs
+++ b/src/help.rs
@@ -19,6 +19,8 @@ PgDown: 10 lines down
a: toggle hidden
s: shell in current directory
o: xdg-open this file
+i: open in current nvim session
+P: preview this file
- Action on flagged files -
space: toggle flag on a file
diff --git a/src/mode.rs b/src/mode.rs
index 07ca789..be13bcf 100644
--- a/src/mode.rs
+++ b/src/mode.rs
@@ -31,6 +31,8 @@ pub enum Mode {
NeedConfirmation,
/// Change the type of sort
Sort,
+ /// Preview a content with bat
+ Preview,
}
impl fmt::Debug for Mode {
@@ -49,6 +51,7 @@ impl fmt::Debug for Mode {
Mode::Jump => write!(f, "Jump : "),
Mode::NeedConfirmation => write!(f, "Y/N :"),
Mode::Sort => write!(f, "(N)ame (D)ate (S)ize (E)xt (R)ev :"),
+ Mode::Preview => write!(f, "Preview : "),
}
}
}
diff --git a/src/status.rs b/src/status.rs
index c46409b..31c577a 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -188,11 +188,12 @@ impl Status {
}
pub fn event_go_to_child(&mut self) {
- if let FileKind::Directory = self.path_content.files[self.path_content.selected].file_kind {
+ if self.path_content.files.is_empty() {
+ return;
+ }
+ if let FileKind::Directory = self.path_content.selected_file().unwrap().file_kind {
self.path_content = PathContent::new(
- self.path_content.files[self.path_content.selected]
- .path
- .clone(),
+ self.path_content.selected_file().unwrap().path.clone(),
self.show_hidden,
);
self.window.reset(self.path_content.files.len());
@@ -240,6 +241,12 @@ impl Status {
self.mode = Mode::Exec
}
+ pub fn event_preview(&mut self) {
+ if !self.path_content.files.is_empty() {
+ self.mode = Mode::Preview
+ }
+ }
+
pub fn event_clear_flags(&mut self) {
self.flagged.clear()
}
@@ -302,7 +309,10 @@ impl Status {
}
pub fn event_toggle_flag(&mut self) {
- self.toggle_flag_on_path(self.path_content.files[self.file_index].path.clone());
+ if self.path_content.files.is_empty() {
+ return;
+ }
+ self.toggle_flag_on_path(self.path_content.selected_file().unwrap().path.clone());
if self.file_index < self.path_content.files.len() - WINDOW_MARGIN_TOP {
self.file_index += 1
}
@@ -336,9 +346,15 @@ impl Status {
}
pub fn event_open_file(&mut self) {
+ if self.path_content.files.is_empty() {
+ return;
+ }
execute_in_child(
&self.opener,
- &vec![self.path_content.files[self.path_content.selected]
+ &vec![self
+ .path_content
+ .selected_file()
+ .unwrap()
.path
.to_str()
.unwrap()],
@@ -350,13 +366,13 @@ impl Status {
}
pub fn event_chmod(&mut self) {
+ if self.path_content.files.is_empty() {
+ return;
+ }
self.mode = Mode::Chmod;
if self.flagged.is_empty() {
- self.flagged.insert(
- self.path_content.files[self.path_content.selected]
- .path
- .clone(),
- );
+ self.flagged
+ .insert(self.path_content.selected_file().unwrap().path.clone());
}
}
@@ -380,10 +396,13 @@ impl Status {
}
pub fn event_right_click(&mut self, row: u16) {
+ if self.path_content.files.is_empty() || row as usize > self.path_content.files.len() {
+ return;
+ }
self.file_index = (row - 1).into();
self.path_content.select_index(self.file_index);
self.window.scroll_to(self.file_index);
- if let FileKind::Directory = self.path_content.files[self.file_index].file_kind {
+ if let FileKind::Directory = self.path_content.selected_file().unwrap().file_kind {
self.event_go_to_child()
} else {
self.event_open_file()
@@ -410,6 +429,9 @@ impl Status {
}
pub fn event_nvim_filepicker(&mut self) {
+ if self.path_content.files.is_empty() {
+ return;
+ }
// "nvim-send --remote-send '<esc>:e readme.md<cr>' --servername 127.0.0.1:8888"
let server = std::env::var("NVIM_LISTEN_ADDRESS").unwrap_or_else(|_| "".to_owned());
if server.is_empty() {
@@ -421,7 +443,9 @@ impl Status {
"--remote-send",
&format!(
"<esc>:e {}<cr><esc>:close<cr>",
- self.path_content.files[self.file_index]
+ self.path_content
+ .selected_file()
+ .unwrap()
.path
.clone()
.to_str()
@@ -473,10 +497,11 @@ impl Status {
}
pub fn exec_rename(&mut self) {
+ if self.path_content.files.is_empty() {
+ return;
+ }
fs::rename(
- self.path_content.files[self.path_content.selected]
- .clone()
- .path,
+ self.path_content.selected_file().unwrap().clone().path,
self.path_content
.path
.to_path_buf()
@@ -525,11 +550,16 @@ impl Status {
}
pub fn exec_exec(&mut self) {
+ if self.path_content.files.is_empty() {
+ return;
+ }
let exec_command = self.input.string.clone();
let mut args: Vec<&str> = exec_command.split(' ').collect();
let command = args.remove(0);
args.push(
- self.path_content.files[self.path_content.selected]
+ self.path_content
+ .selected_file()
+ .unwrap()
.path
.to_str()
.unwrap(),