mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: support of navigating to file for cd event
This commit is contained in:
parent
4a5154c03e
commit
9f5707ad74
11 changed files with 90 additions and 48 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
|
@ -1414,7 +1414,7 @@ checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata 0.3.2",
|
"regex-automata 0.3.3",
|
||||||
"regex-syntax 0.7.4",
|
"regex-syntax 0.7.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1429,9 +1429,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf"
|
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -1990,9 +1990,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "trash"
|
name = "trash"
|
||||||
version = "3.0.5"
|
version = "3.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "85931d0ad541fa457c3f94c7cc5f14920f17a385832a7ef7621762c23cbf9729"
|
checksum = "af3663fb8f476d674b9c61d1d2796acec725bef6bec4b41402a904252a25971e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
|
||||||
9
src/core/external/fzf.rs
vendored
9
src/core/external/fzf.rs
vendored
|
|
@ -3,17 +3,20 @@ use std::{path::PathBuf, process::Stdio};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use tokio::{process::Command, sync::oneshot::{self, Receiver}};
|
use tokio::{process::Command, sync::oneshot::{self, Receiver}};
|
||||||
|
|
||||||
pub struct FzfOpt {}
|
pub struct FzfOpt {
|
||||||
|
pub cwd: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fzf(opt: FzfOpt) -> Result<Receiver<Result<PathBuf>>> {
|
pub fn fzf(opt: FzfOpt) -> Result<Receiver<Result<PathBuf>>> {
|
||||||
let child = Command::new("fzf").kill_on_drop(true).stdout(Stdio::piped()).spawn()?;
|
let child =
|
||||||
|
Command::new("fzf").current_dir(&opt.cwd).kill_on_drop(true).stdout(Stdio::piped()).spawn()?;
|
||||||
|
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Ok(output) = child.wait_with_output().await {
|
if let Ok(output) = child.wait_with_output().await {
|
||||||
let selected = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
let selected = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||||
if !selected.is_empty() {
|
if !selected.is_empty() {
|
||||||
tx.send(Ok(selected.into())).ok();
|
tx.send(Ok(opt.cwd.join(selected))).ok();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@ impl File {
|
||||||
let is_hidden = path.file_name().map(|s| s.to_string_lossy().starts_with('.')).unwrap_or(false);
|
let is_hidden = path.file_name().map(|s| s.to_string_lossy().starts_with('.')).unwrap_or(false);
|
||||||
File { path: path.to_path_buf(), meta, length, is_link, is_hidden, is_selected: false }
|
File { path: path.to_path_buf(), meta, length, is_link, is_hidden, is_selected: false }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl File {
|
||||||
|
#[inline]
|
||||||
|
pub fn path(&self) -> PathBuf { self.path.clone() }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_path(mut self, path: &Path) -> Self {
|
pub fn set_path(mut self, path: &Path) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,11 @@ impl Files {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn duplicate(&self, idx: usize) -> Option<File> {
|
||||||
|
self.items.get_index(idx).map(|(_, file)| file.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_read(&mut self, mut items: IndexMap<PathBuf, File>) -> bool {
|
pub fn update_read(&mut self, mut items: IndexMap<PathBuf, File>) -> bool {
|
||||||
if !self.show_hidden {
|
if !self.show_hidden {
|
||||||
items.retain(|_, item| !item.is_hidden);
|
items.retain(|_, item| !item.is_hidden);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ pub struct Folder {
|
||||||
offset: usize,
|
offset: usize,
|
||||||
cursor: usize,
|
cursor: usize,
|
||||||
|
|
||||||
|
pub hovered: Option<File>,
|
||||||
pub in_search: bool,
|
pub in_search: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,8 +35,14 @@ impl Folder {
|
||||||
}
|
}
|
||||||
|
|
||||||
let len = self.files.len();
|
let len = self.files.len();
|
||||||
self.cursor = self.cursor.min(len.saturating_sub(1));
|
|
||||||
self.offset = self.offset.min(len);
|
self.offset = self.offset.min(len);
|
||||||
|
self.cursor = self.cursor.min(len.saturating_sub(1));
|
||||||
|
|
||||||
|
if let Some(h) = self.hovered.as_ref().map(|h| h.path()) {
|
||||||
|
self.hover(&h);
|
||||||
|
}
|
||||||
|
self.hovered = self.files.duplicate(self.cursor);
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,6 +57,7 @@ impl Folder {
|
||||||
|
|
||||||
let old = self.cursor;
|
let old = self.cursor;
|
||||||
self.cursor = (self.cursor + step).min(len - 1);
|
self.cursor = (self.cursor + step).min(len - 1);
|
||||||
|
self.hovered = self.files.duplicate(self.cursor);
|
||||||
|
|
||||||
let limit = Self::limit();
|
let limit = Self::limit();
|
||||||
if self.cursor >= (self.offset + limit).min(len).saturating_sub(5) {
|
if self.cursor >= (self.offset + limit).min(len).saturating_sub(5) {
|
||||||
|
|
@ -62,6 +70,7 @@ impl Folder {
|
||||||
pub fn prev(&mut self, step: usize) -> bool {
|
pub fn prev(&mut self, step: usize) -> bool {
|
||||||
let old = self.cursor;
|
let old = self.cursor;
|
||||||
self.cursor = self.cursor.saturating_sub(step);
|
self.cursor = self.cursor.saturating_sub(step);
|
||||||
|
self.hovered = self.files.duplicate(self.cursor);
|
||||||
|
|
||||||
if self.cursor < self.offset + 5 {
|
if self.cursor < self.offset + 5 {
|
||||||
self.offset = self.offset.saturating_sub(old - self.cursor);
|
self.offset = self.offset.saturating_sub(old - self.cursor);
|
||||||
|
|
@ -130,25 +139,27 @@ impl Folder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hover(&mut self, path: &Path) -> bool {
|
pub fn hover(&mut self, path: &Path) -> bool {
|
||||||
if self.hovered().map(|h| h.path.as_path()) == Some(path) {
|
if matches!(self.hovered, Some(ref h) if h.path == path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let new = self.position(path).unwrap_or(self.cursor);
|
let new = self.position(path).unwrap_or(self.cursor);
|
||||||
if new > self.cursor { self.next(new - self.cursor) } else { self.prev(self.cursor - new) }
|
if new > self.cursor { self.next(new - self.cursor) } else { self.prev(self.cursor - new) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn hover_force(&mut self, file: File) -> bool {
|
||||||
|
if !self.hover(&file.path) && self.files.is_empty() {
|
||||||
|
self.hovered = Some(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Folder {
|
impl Folder {
|
||||||
#[inline]
|
|
||||||
pub fn hovered(&self) -> Option<&File> { self.files.get_index(self.cursor).map(|(_, item)| item) }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cursor(&self) -> usize { self.cursor }
|
pub fn cursor(&self) -> usize { self.cursor }
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn rel_cursor(&self) -> usize { self.cursor - self.offset }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn position(&self, path: &Path) -> Option<usize> {
|
pub fn position(&self, path: &Path) -> Option<usize> {
|
||||||
self.files.iter().position(|(p, _)| p == path)
|
self.files.iter().position(|(p, _)| p == path)
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@ impl Manager {
|
||||||
if let Some(ref p) = tab.parent {
|
if let Some(ref p) = tab.parent {
|
||||||
to_watch.insert(p.cwd.clone());
|
to_watch.insert(p.cwd.clone());
|
||||||
}
|
}
|
||||||
if let Some(ref h) = tab.current.hovered() {
|
if let Some(ref h) = tab.current.hovered {
|
||||||
if h.meta.is_dir() {
|
if h.meta.is_dir() {
|
||||||
to_watch.insert(h.path.clone());
|
to_watch.insert(h.path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ impl Manager {
|
||||||
self.active_mut().preview.go(&hovered.path, &mime);
|
self.active_mut().preview.go(&hovered.path, &mime);
|
||||||
} else {
|
} else {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Ok(mime) = Precache::mimetype(&vec![hovered.path.clone()]).await {
|
if let Ok(mime) = Precache::mimetype(&vec![hovered.path()]).await {
|
||||||
if let Some(Some(mime)) = mime.first() {
|
if let Some(Some(mime)) = mime.first() {
|
||||||
emit!(Mimetype(hovered.path, mime.clone()));
|
emit!(Mimetype(hovered.path, mime.clone()));
|
||||||
}
|
}
|
||||||
|
|
@ -148,11 +148,7 @@ impl Manager {
|
||||||
fn bulk_rename(&self) -> bool { false }
|
fn bulk_rename(&self) -> bool { false }
|
||||||
|
|
||||||
pub fn selected(&self) -> Vec<PathBuf> {
|
pub fn selected(&self) -> Vec<PathBuf> {
|
||||||
self
|
self.current().selected().or_else(|| self.hovered().map(|h| vec![h.path()])).unwrap_or_default()
|
||||||
.current()
|
|
||||||
.selected()
|
|
||||||
.or_else(|| self.hovered().map(|h| vec![h.path.clone()]))
|
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn mimetype(&mut self, files: &Vec<PathBuf>) -> Vec<Option<String>> {
|
pub async fn mimetype(&mut self, files: &Vec<PathBuf>) -> Vec<Option<String>> {
|
||||||
|
|
@ -171,7 +167,7 @@ impl Manager {
|
||||||
pub fn update_read(&mut self, op: FilesOp) -> bool {
|
pub fn update_read(&mut self, op: FilesOp) -> bool {
|
||||||
let path = op.path();
|
let path = op.path();
|
||||||
let cwd = self.current().cwd.clone();
|
let cwd = self.current().cwd.clone();
|
||||||
let hovered = self.hovered().map(|h| h.path.clone());
|
let hovered = self.hovered().map(|h| h.path());
|
||||||
|
|
||||||
let mut b = if cwd == path && !self.current().in_search {
|
let mut b = if cwd == path && !self.current().in_search {
|
||||||
self.current_mut().update(op)
|
self.current_mut().update(op)
|
||||||
|
|
@ -191,7 +187,7 @@ impl Manager {
|
||||||
b |= self.active_mut().parent.as_mut().map_or(false, |p| p.hover(&cwd));
|
b |= self.active_mut().parent.as_mut().map_or(false, |p| p.hover(&cwd));
|
||||||
b |= hovered.as_ref().map_or(false, |h| self.current_mut().hover(h));
|
b |= hovered.as_ref().map_or(false, |h| self.current_mut().hover(h));
|
||||||
|
|
||||||
if hovered != self.hovered().map(|h| h.path.clone()) {
|
if hovered != self.hovered().map(|h| h.path()) {
|
||||||
emit!(Hover);
|
emit!(Hover);
|
||||||
}
|
}
|
||||||
b
|
b
|
||||||
|
|
@ -238,8 +234,8 @@ impl Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_preview(&mut self, path: PathBuf, data: PreviewData) -> bool {
|
pub fn update_preview(&mut self, path: PathBuf, data: PreviewData) -> bool {
|
||||||
let hovered = if let Some(h) = self.current().hovered() {
|
let hovered = if let Some(ref h) = self.current().hovered {
|
||||||
h.path.clone()
|
h.path()
|
||||||
} else {
|
} else {
|
||||||
return self.active_mut().preview.reset();
|
return self.active_mut().preview.reset();
|
||||||
};
|
};
|
||||||
|
|
@ -275,8 +271,8 @@ impl Manager {
|
||||||
pub fn current_mut(&mut self) -> &mut Folder { &mut self.tabs.active_mut().current }
|
pub fn current_mut(&mut self) -> &mut Folder { &mut self.tabs.active_mut().current }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parent(&self) -> &Option<Folder> { &self.tabs.active().parent }
|
pub fn parent(&self) -> Option<&Folder> { self.tabs.active().parent.as_ref() }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn hovered(&self) -> Option<&File> { self.tabs.active().current.hovered() }
|
pub fn hovered(&self) -> Option<&File> { self.tabs.active().current.hovered.as_ref() }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use std::{collections::BTreeMap, mem, path::{Path, PathBuf}};
|
use std::{collections::BTreeMap, mem, path::{Path, PathBuf}};
|
||||||
|
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use indexmap::IndexMap;
|
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
use super::{Folder, Mode, Preview};
|
use super::{Folder, Mode, Preview};
|
||||||
use crate::{core::{external::{self, FzfOpt, ZoxideOpt}, files::{Files, FilesOp}, input::{Input, InputOpt}, Event, BLOCKER}, emit, misc::Defer};
|
use crate::{core::{external::{self, FzfOpt, ZoxideOpt}, files::{File, Files, FilesOp}, input::{Input, InputOpt}, Event, BLOCKER}, emit, misc::Defer};
|
||||||
|
|
||||||
pub struct Tab {
|
pub struct Tab {
|
||||||
pub(super) current: Folder,
|
pub(super) current: Folder,
|
||||||
|
|
@ -73,8 +73,23 @@ impl Tab {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cd(&mut self, target: PathBuf) -> bool {
|
pub async fn cd(&mut self, mut target: PathBuf) -> bool {
|
||||||
|
let file = if let Ok(f) = File::from(&target).await {
|
||||||
|
f
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut hovered = None;
|
||||||
|
if !file.meta.is_dir() {
|
||||||
|
hovered = Some(file);
|
||||||
|
target = target.parent().unwrap().to_path_buf();
|
||||||
|
}
|
||||||
|
|
||||||
if self.current.cwd == target {
|
if self.current.cwd == target {
|
||||||
|
if hovered.map(|h| self.current.hover_force(h)).unwrap_or(false) {
|
||||||
|
emit!(Hover);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,12 +107,15 @@ impl Tab {
|
||||||
self.parent = Some(self.history_new(parent));
|
self.parent = Some(self.history_new(parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(h) = hovered {
|
||||||
|
self.current.hover_force(h);
|
||||||
|
}
|
||||||
emit!(Refresh);
|
emit!(Refresh);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enter(&mut self) -> bool {
|
pub fn enter(&mut self) -> bool {
|
||||||
let hovered = if let Some(h) = self.current.hovered() {
|
let hovered = if let Some(ref h) = self.current.hovered {
|
||||||
h.clone()
|
h.clone()
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -125,7 +143,8 @@ impl Tab {
|
||||||
pub fn leave(&mut self) -> bool {
|
pub fn leave(&mut self) -> bool {
|
||||||
let current = self
|
let current = self
|
||||||
.current
|
.current
|
||||||
.hovered()
|
.hovered
|
||||||
|
.as_ref()
|
||||||
.and_then(|h| h.path.parent())
|
.and_then(|h| h.path.parent())
|
||||||
.and_then(|p| if p == self.current.cwd { None } else { Some(p) })
|
.and_then(|p| if p == self.current.cwd { None } else { Some(p) })
|
||||||
.or_else(|| self.current.cwd.parent());
|
.or_else(|| self.current.cwd.parent());
|
||||||
|
|
@ -214,7 +233,8 @@ impl Tab {
|
||||||
let _defer = Defer::new(|| Event::Stop(false, None).emit());
|
let _defer = Defer::new(|| Event::Stop(false, None).emit());
|
||||||
emit!(Stop(true)).await;
|
emit!(Stop(true)).await;
|
||||||
|
|
||||||
let rx = if global { external::fzf(FzfOpt {}) } else { external::zoxide(ZoxideOpt { cwd }) }?;
|
let rx =
|
||||||
|
if global { external::fzf(FzfOpt { cwd }) } else { external::zoxide(ZoxideOpt { cwd }) }?;
|
||||||
|
|
||||||
if let Ok(target) = rx.await? {
|
if let Ok(target) = rx.await? {
|
||||||
emit!(Cd(target));
|
emit!(Cd(target));
|
||||||
|
|
|
||||||
|
|
@ -105,13 +105,15 @@ impl Watcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn watch(&mut self, to_watch: BTreeSet<PathBuf>) {
|
pub(super) fn watch(&mut self, mut to_watch: BTreeSet<PathBuf>) {
|
||||||
let keys = self.watched.read().keys().cloned().collect::<BTreeSet<_>>();
|
let keys = self.watched.read().keys().cloned().collect::<BTreeSet<_>>();
|
||||||
for p in keys.difference(&to_watch) {
|
for p in keys.difference(&to_watch) {
|
||||||
self.watcher.unwatch(p).ok();
|
self.watcher.unwatch(p).ok();
|
||||||
}
|
}
|
||||||
for p in to_watch.difference(&keys) {
|
for p in to_watch.clone().difference(&keys) {
|
||||||
self.watcher.watch(&p, RecursiveMode::NonRecursive).ok();
|
if self.watcher.watch(&p, RecursiveMode::NonRecursive).is_err() {
|
||||||
|
to_watch.remove(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut todo = Vec::new();
|
let mut todo = Vec::new();
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ impl App {
|
||||||
let manager = &mut self.cx.manager;
|
let manager = &mut self.cx.manager;
|
||||||
match event {
|
match event {
|
||||||
Event::Cd(path) => {
|
Event::Cd(path) => {
|
||||||
manager.active_mut().cd(path);
|
manager.active_mut().cd(path).await;
|
||||||
}
|
}
|
||||||
Event::Refresh => {
|
Event::Refresh => {
|
||||||
manager.refresh();
|
manager.refresh();
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ impl Logs {
|
||||||
let (handle, guard) = tracing_appender::non_blocking(appender);
|
let (handle, guard) = tracing_appender::non_blocking(appender);
|
||||||
|
|
||||||
// let filter = EnvFilter::from_default_env();
|
// let filter = EnvFilter::from_default_env();
|
||||||
let subscriber = Registry::default().with(fmt::layer().compact().with_writer(handle));
|
let subscriber = Registry::default().with(fmt::layer().pretty().with_writer(handle));
|
||||||
|
|
||||||
tracing::subscriber::set_global_default(subscriber)
|
tracing::subscriber::set_global_default(subscriber)
|
||||||
.context("setting default subscriber failed")?;
|
.context("setting default subscriber failed")?;
|
||||||
|
|
|
||||||
|
|
@ -32,35 +32,35 @@ impl<'a> Widget for Folder<'a> {
|
||||||
.folder
|
.folder
|
||||||
.paginate()
|
.paginate()
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.map(|(k, v)| {
|
||||||
.map(|(i, (_, v))| {
|
|
||||||
let icon = THEME
|
let icon = THEME
|
||||||
.icons
|
.icons
|
||||||
.iter()
|
.iter()
|
||||||
.find(|x| x.name.match_path(&v.path, Some(v.meta.is_dir())))
|
.find(|x| x.name.match_path(k, Some(v.meta.is_dir())))
|
||||||
.map(|x| x.display.as_ref())
|
.map(|x| x.display.as_ref())
|
||||||
.unwrap_or("");
|
.unwrap_or("");
|
||||||
|
|
||||||
let name = readable_path(&v.path, &self.folder.cwd);
|
let name = readable_path(k, &self.folder.cwd);
|
||||||
let item = ListItem::new(if v.is_selected {
|
let item = ListItem::new(if v.is_selected {
|
||||||
format!("> {} {}", icon, name)
|
format!("> {} {}", icon, name)
|
||||||
} else {
|
} else {
|
||||||
format!("{} {}", icon, name)
|
format!("{} {}", icon, name)
|
||||||
});
|
});
|
||||||
|
let hovered = matches!(self.folder.hovered, Some(ref h) if h.path == *k);
|
||||||
|
|
||||||
let mut style = Style::default();
|
let mut style = Style::default();
|
||||||
if self.is_selection {
|
if self.is_selection {
|
||||||
if i == self.folder.rel_cursor() {
|
if hovered {
|
||||||
style = style.fg(Color::Black).bg(Color::Red);
|
style = style.fg(Color::Black).bg(Color::Red);
|
||||||
} else if v.is_selected {
|
} else if v.is_selected {
|
||||||
style = style.fg(Color::Red);
|
style = style.fg(Color::Red);
|
||||||
}
|
}
|
||||||
} else if self.is_preview {
|
} else if self.is_preview {
|
||||||
if i == self.folder.rel_cursor() {
|
if hovered {
|
||||||
style = style.add_modifier(Modifier::UNDERLINED)
|
style = style.add_modifier(Modifier::UNDERLINED)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if i == self.folder.rel_cursor() {
|
if hovered {
|
||||||
style = style.fg(Color::Black).bg(Color::Yellow);
|
style = style.fg(Color::Black).bg(Color::Yellow);
|
||||||
} else if v.is_selected {
|
} else if v.is_selected {
|
||||||
style = style.fg(Color::Red);
|
style = style.fg(Color::Red);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue