diff options
author | Kyohei Uto <im@kyoheiu.dev> | 2023-11-02 04:48:03 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-02 04:48:03 +0900 |
commit | efa494ba36521da858e9d9032574ce6152e09ec6 (patch) | |
tree | bc571c648dcaa7e71f49d5d51c7cabe1dd4b74a0 | |
parent | d12f8c66cfba3fb87c009bc86b8ffe2a29983ad6 (diff) | |
parent | 9b846bd9b03fbe4d43108666462ac78553d8e5fa (diff) |
Merge pull request #250 from kyoheiu/developv2.10.0
v2.10.0
-rw-r--r-- | CHANGELOG.md | 7 | ||||
-rw-r--r-- | Cargo.lock | 30 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | src/errors.rs | 4 | ||||
-rw-r--r-- | src/layout.rs | 75 | ||||
-rw-r--r-- | src/state.rs | 10 |
7 files changed, 85 insertions, 53 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index c08aaf2..0f07bc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ ## Unreleased +## v2.10.0 (2023-11-01) + +### Added +- `bat` integration: If `bat` installed, felix automatically adds syntax highlighting to the text preview. + - Add `has_bat` field to `State`. + - Add `FxError::InvalidPath` to handle invalid unicode in file path. + ## v2.9.0 (2023-10-22) ### Added @@ -170,9 +170,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -188,9 +188,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" +checksum = "4939f9ed1444bd8c896d37f3090012fa6e7834fe84ef8c9daa166109515732f9" [[package]] name = "crc32fast" @@ -330,7 +330,7 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "felix" -version = "2.9.0" +version = "2.10.0" dependencies = [ "bwrap", "chrono", @@ -470,9 +470,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown", @@ -602,9 +602,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "log", @@ -836,18 +836,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.189" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", @@ -856,9 +856,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.25" +version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ "indexmap", "itoa", @@ -1,6 +1,6 @@ [package] name = "felix" -version = "2.9.0" +version = "2.10.0" authors = ["Kyohei Uto <im@kyoheiu.dev>"] edition = "2021" description = "tui file manager with vim-like key mapping" @@ -25,6 +25,13 @@ For more detailed document, visit https://kyoheiu.dev/felix. ## New release +## v2.10.0 (2023-11-01) + +### Added +- `bat` integration: If `bat` installed, felix automatically adds syntax highlighting to the text preview. + - Add `has_bat` field to `State`. + - Add `FxError::InvalidPath` to handle invalid unicode in file path. + ## v2.9.0 (2023-10-22) ### Added @@ -115,13 +122,14 @@ source <(command fx --init) *If this is not set, exiting to LWD will fail and show the error message.* ### Others -In addition, you can use felix more conveniently by installing these two apps: +In addition, you can use felix more conveniently by installing these apps: - [zoxide](https://github.com/ajeetdsouza/zoxide): A smarter `cd` command, which enables you to jump to a directory that matches the keyword in felix. - [chafa](https://hpjansson.org/chafa/): Terminal graphics for the 21st century, by which you can preview images in felix. _**chafa must be v1.10.0 or later.**_ +- [bat](https://github.com/sharkdp/bat): A *cat(1)* clone. Add syntax highlighting to the text preview with bat. These apps do not need any configuration to use with felix! diff --git a/src/errors.rs b/src/errors.rs index 112f2bd..fa58e79 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -18,6 +18,7 @@ pub enum FxError { TooSmallWindowSize, Log(String), Unpack(String), + InvalidPath, Panic, #[cfg(any(target_os = "linux", target_os = "netbsd"))] Nix(String), @@ -29,7 +30,7 @@ impl std::fmt::Display for FxError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let printable = match self { FxError::Arg(s) => s.to_owned(), - FxError::TerminalSizeDetection => "Error: Cannot detect terminal size.".to_owned(), + FxError::TerminalSizeDetection => "Error: Cannot detect terminal size".to_owned(), FxError::Io(s) => s.to_owned(), FxError::Dirs(s) => s.to_owned(), FxError::GetItem => "Error: Cannot get item info".to_owned(), @@ -46,6 +47,7 @@ impl std::fmt::Display for FxError { FxError::TooSmallWindowSize => "Error: Too small window size".to_owned(), FxError::Log(s) => s.to_owned(), FxError::Unpack(s) => s.to_owned(), + FxError::InvalidPath => "Error: Path may contain invalid unicode".to_owned(), FxError::Panic => "Error: felix panicked".to_owned(), #[cfg(any(target_os = "linux", target_os = "netbsd"))] FxError::Nix(s) => s.to_owned(), diff --git a/src/layout.rs b/src/layout.rs index 25c2921..56e92b5 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -32,6 +32,7 @@ pub struct Layout { pub preview_start: (u16, u16), pub preview_space: (u16, u16), pub has_chafa: bool, + pub has_bat: bool, pub is_kitty: bool, } @@ -145,7 +146,7 @@ impl Layout { } Some(PreviewType::Image) => { if self.has_chafa { - if let Err(e) = self.preview_image(item, y) { + if let Err(e) = self.preview_image(item) { print_warning(e, y); } } else { @@ -160,7 +161,9 @@ impl Layout { } } Some(PreviewType::Text) => { - self.preview_text(item); + if let Err(e) = self.preview_text(item) { + print_warning(e, y); + } } Some(PreviewType::Binary) => { print!("(Binary file)"); @@ -184,14 +187,35 @@ impl Layout { print!("{}", file_name); } - fn preview_text(&self, item: &ItemInfo) { + fn preview_text(&self, item: &ItemInfo) -> Result<(), FxError> { if let Some(content) = &item.content { - self.print_txt_in_preview_area( - item, - &format_txt(content, self.preview_space.0, false), - false, - ); + if !self.has_bat { + self.print_txt_in_preview_area( + item, + &format_txt(content, self.preview_space.0, false), + ); + } else { + let path = item.file_path.to_str().ok_or(FxError::InvalidPath)?; + let output = std::process::Command::new("bat") + .args([ + path, + "-fpP", + "--wrap", + "character", + "--terminal-width", + &format!("{}", self.preview_space.0), + ]) + .output()? + .stdout; + let content = String::from_utf8(output)?; + let content = content + .split('\n') + .map(|x| x.to_owned()) + .collect::<Vec<String>>(); + self.print_txt_in_preview_area(item, &content); + } } + Ok(()) } fn preview_directory(&self, item: &ItemInfo) { @@ -203,17 +227,11 @@ impl Layout { self.print_txt_in_preview_area( item, &format_txt(&contents, self.preview_space.0, false), - false, ); } } - fn print_txt_in_preview_area( - &self, - item: &ItemInfo, - content: &[String], - syntex_highlight: bool, - ) { + fn print_txt_in_preview_area(&self, item: &ItemInfo, content: &[String]) { match self.split { Split::Vertical => { for (i, line) in content.iter().enumerate() { @@ -223,12 +241,8 @@ impl Layout { let sum = (i - item.preview_scroll) as u16; let row = self.preview_start.1 + sum; move_to(self.preview_start.0, row); - if syntex_highlight { - print!("{}", line); - } else { - set_color(&TermColor::ForeGround(&Colorname::LightBlack)); - print!("{}", line); - } + set_color(&TermColor::ForeGround(&Colorname::LightBlack)); + print!("{}", line); if sum == self.preview_space.1 - 1 { break; } @@ -242,12 +256,8 @@ impl Layout { let sum = (i - item.preview_scroll) as u16; let row = self.preview_start.1 + sum; move_to(1, row); - if syntex_highlight { - print!("{}", line); - } else { - set_color(&TermColor::ForeGround(&Colorname::LightBlack)); - print!("{}", line); - } + set_color(&TermColor::ForeGround(&Colorname::LightBlack)); + print!("{}", line); if row == self.terminal_row + self.preview_space.1 { break; } @@ -258,7 +268,7 @@ impl Layout { } /// Print text preview on the right half of the terminal (Experimental). - fn preview_image(&self, item: &ItemInfo, y: u16) -> Result<(), FxError> { + fn preview_image(&self, item: &ItemInfo) -> Result<(), FxError> { let wxh = match self.split { Split::Vertical => { format!("--size={}x{}", self.preview_space.0, self.preview_space.1) @@ -272,14 +282,9 @@ impl Layout { } }; - let file_path = item.file_path.to_str(); - if file_path.is_none() { - print_warning("Cannot read the file path correctly.", y); - return Ok(()); - } - + let file_path = item.file_path.to_str().ok_or(FxError::InvalidPath)?; let output = std::process::Command::new("chafa") - .args(["--animate=false", &wxh, file_path.unwrap()]) + .args(["--animate=false", &wxh, file_path]) .output()? .stdout; let output = String::from_utf8(output)?; diff --git a/src/state.rs b/src/state.rs index e7c757b..bbfd149 100644 --- a/src/state.rs +++ b/src/state.rs @@ -262,6 +262,7 @@ impl State { let split = session.split.unwrap_or(Split::Vertical); + let has_bat = check_bat(); let has_chafa = check_chafa(); let has_zoxide = check_zoxide(); let is_kitty = check_kitty_support(); @@ -316,6 +317,7 @@ impl State { Split::Vertical => (0, 0), Split::Horizontal => (0, 0), }, + has_bat, has_chafa, is_kitty, }, @@ -1941,6 +1943,14 @@ fn read_item(entry: fs::DirEntry) -> ItemInfo { // Ok(result) // } +/// Check if bat is installed. +fn check_bat() -> bool { + std::process::Command::new("bat") + .arg("--help") + .output() + .is_ok() +} + /// Check if chafa is installed. fn check_chafa() -> bool { std::process::Command::new("chafa") |