mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
up
This commit is contained in:
parent
5c69beb104
commit
83cbef649d
11 changed files with 103 additions and 43 deletions
24
Cargo.lock
generated
24
Cargo.lock
generated
|
|
@ -382,9 +382,9 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
|||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
|
|
@ -665,15 +665,6 @@ version = "0.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
|
||||
dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.9"
|
||||
|
|
@ -1334,9 +1325,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.31"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
|
||||
checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
|
@ -2358,12 +2349,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "xdg"
|
||||
version = "2.5.0"
|
||||
version = "2.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "688597db5a750e9cad4511cb94729a078e274308099a0382b5b8203bbc767fee"
|
||||
dependencies = [
|
||||
"home",
|
||||
]
|
||||
checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
|
|
|
|||
|
|
@ -28,6 +28,25 @@ impl From<&str> for Exec {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToString for Exec {
|
||||
fn to_string(&self) -> String {
|
||||
let mut s = self.cmd.clone();
|
||||
for arg in &self.args {
|
||||
s.push(' ');
|
||||
s.push_str(arg);
|
||||
}
|
||||
for (name, value) in &self.named {
|
||||
s.push_str(" --");
|
||||
s.push_str(name);
|
||||
if !value.is_empty() {
|
||||
s.push('=');
|
||||
s.push_str(value);
|
||||
}
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl Exec {
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Exec>, D::Error>
|
||||
where
|
||||
|
|
|
|||
|
|
@ -106,7 +106,8 @@ impl TryFrom<String> for Key {
|
|||
impl ToString for Key {
|
||||
fn to_string(&self) -> String {
|
||||
if let Some(c) = self.plain() {
|
||||
return if self.shift { c.to_ascii_uppercase() } else { c }.to_string();
|
||||
let c = if self.shift { c.to_ascii_uppercase() } else { c };
|
||||
return if c == ' ' { "<Space>".to_string() } else { c.to_string() };
|
||||
}
|
||||
|
||||
let mut s = "<".to_string();
|
||||
|
|
@ -149,6 +150,7 @@ impl ToString for Key {
|
|||
KeyCode::F(12) => "F12",
|
||||
KeyCode::Esc => "Esc",
|
||||
|
||||
KeyCode::Char(c) if c == ' ' => "Space",
|
||||
KeyCode::Char(c) => {
|
||||
s.push(if self.shift { c.to_ascii_uppercase() } else { c });
|
||||
""
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ pub struct Theme {
|
|||
impl Theme {
|
||||
pub fn new() -> Self {
|
||||
let mut theme: Self = toml::from_str(&MERGED_THEME).unwrap();
|
||||
theme.preview.syntect_theme = absolute_path(&theme.preview.syntect_theme);
|
||||
theme.preview.syntect_theme =
|
||||
futures::executor::block_on(absolute_path(&theme.preview.syntect_theme));
|
||||
theme
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::{BTreeMap, BTreeSet, HashMap, HashSet}, mem, path::PathBuf};
|
||||
use std::{collections::{BTreeMap, BTreeSet, HashMap, HashSet}, env, mem, path::PathBuf};
|
||||
|
||||
use tokio::fs;
|
||||
|
||||
|
|
@ -25,6 +25,8 @@ impl Manager {
|
|||
}
|
||||
|
||||
pub fn refresh(&mut self) {
|
||||
env::set_current_dir(&self.current().cwd).ok();
|
||||
|
||||
self.watcher.trigger(&self.current().cwd);
|
||||
if let Some(p) = self.parent() {
|
||||
self.watcher.trigger(&p.cwd);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ impl Which {
|
|||
} else if self.cands.len() == 1 {
|
||||
self.visible = false;
|
||||
emit!(Ctrl(self.cands.remove(0), self.layer));
|
||||
} else if let Some(i) = self.cands.iter().position(|c| c.on.len() == self.times + 1) {
|
||||
emit!(Ctrl(self.cands.remove(i), self.layer));
|
||||
self.visible = false;
|
||||
}
|
||||
|
||||
self.times += 1;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ use std::{env, path::{Path, PathBuf}};
|
|||
|
||||
use tokio::fs;
|
||||
|
||||
pub fn absolute_path(p: &Path) -> PathBuf {
|
||||
pub async fn absolute_path(p: impl AsRef<Path>) -> PathBuf {
|
||||
let p = p.as_ref();
|
||||
if p.starts_with("~") {
|
||||
if let Ok(home) = env::var("HOME") {
|
||||
let mut expanded = PathBuf::new();
|
||||
|
|
@ -11,7 +12,7 @@ pub fn absolute_path(p: &Path) -> PathBuf {
|
|||
return expanded;
|
||||
}
|
||||
}
|
||||
p.to_path_buf()
|
||||
fs::canonicalize(p).await.unwrap_or_else(|_| p.to_path_buf())
|
||||
}
|
||||
|
||||
pub fn readable_path(p: &Path, base: &Path) -> String {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crossterm::event::KeyEvent;
|
|||
use tokio::sync::oneshot::{self};
|
||||
|
||||
use super::{root::Root, Ctx, Executor, Logs, Signals, Term};
|
||||
use crate::{config::keymap::{Control, Key, KeymapLayer}, core::{files::FilesOp, Event}, emit};
|
||||
use crate::{config::keymap::{Control, Key, KeymapLayer}, core::{files::FilesOp, Event}, emit, misc::absolute_path};
|
||||
|
||||
pub struct App {
|
||||
cx: Ctx,
|
||||
|
|
@ -84,7 +84,7 @@ impl App {
|
|||
let tasks = &mut self.cx.tasks;
|
||||
match event {
|
||||
Event::Cd(path) => {
|
||||
manager.active_mut().cd(path).await;
|
||||
manager.active_mut().cd(absolute_path(path).await).await;
|
||||
}
|
||||
Event::Refresh => {
|
||||
manager.refresh();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use super::Ctx;
|
||||
use crate::{config::{keymap::{Control, Exec, Key, KeymapLayer}, KEYMAP}, core::input::InputMode, misc::optional_bool};
|
||||
use crate::{config::{keymap::{Control, Exec, Key, KeymapLayer}, KEYMAP}, core::input::InputMode, emit, misc::optional_bool};
|
||||
|
||||
pub struct Executor;
|
||||
|
||||
|
|
@ -60,6 +62,11 @@ impl Executor {
|
|||
"enter" => cx.manager.active_mut().enter(),
|
||||
"back" => cx.manager.active_mut().back(),
|
||||
"forward" => cx.manager.active_mut().forward(),
|
||||
"cd" => {
|
||||
let path = exec.args.get(0).map(|s| PathBuf::from(s)).unwrap_or_default();
|
||||
emit!(Cd(path));
|
||||
false
|
||||
}
|
||||
|
||||
// Selection
|
||||
"select" => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, widgets::Widget};
|
||||
use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, widgets::{Clear, Widget}};
|
||||
|
||||
use super::Side;
|
||||
use crate::ui::Ctx;
|
||||
|
|
@ -13,20 +13,35 @@ impl<'a> Which<'a> {
|
|||
|
||||
impl Widget for Which<'_> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let chunks = layout::Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
||||
.split(area);
|
||||
let which = &self.cx.which;
|
||||
let mut cands: (Vec<_>, Vec<_>, Vec<_>) = Default::default();
|
||||
for (i, c) in which.cands.iter().enumerate() {
|
||||
match i % 3 {
|
||||
0 => cands.0.push(c),
|
||||
1 => cands.1.push(c),
|
||||
2 => cands.2.push(c),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
let height = cands.0.len() as u16 + 2;
|
||||
let area = Rect {
|
||||
x: 1,
|
||||
y: area.height.saturating_sub(height + 2),
|
||||
width: area.width.saturating_sub(2),
|
||||
height,
|
||||
};
|
||||
|
||||
let chunks = layout::Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
||||
.split(chunks[1]);
|
||||
|
||||
let which = &self.cx.which;
|
||||
let cands: (Vec<_>, Vec<_>) = which.cands.iter().enumerate().partition(|(i, _)| i % 2 == 0);
|
||||
.constraints(
|
||||
[Constraint::Ratio(1, 3), Constraint::Ratio(1, 3), Constraint::Ratio(1, 3)].as_ref(),
|
||||
)
|
||||
.split(area);
|
||||
|
||||
Clear.render(area, buf);
|
||||
Side::new(which.times, cands.0).render(chunks[0], buf);
|
||||
Side::new(which.times, cands.1).render(chunks[1], buf);
|
||||
Side::new(which.times, cands.2).render(chunks[2], buf);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use ratatui::{prelude::{Buffer, Rect}, widgets::{List, ListItem, Widget}};
|
||||
use ratatui::{prelude::{Buffer, Rect}, style::{Color, Style, Stylize}, text::{Line, Span}, widgets::{Block, List, ListItem, Padding, Widget}};
|
||||
|
||||
use crate::config::keymap::Control;
|
||||
|
||||
pub struct Side<'a> {
|
||||
times: usize,
|
||||
cands: Vec<(usize, &'a Control)>,
|
||||
cands: Vec<&'a Control>,
|
||||
}
|
||||
|
||||
impl<'a> Side<'a> {
|
||||
pub fn new(times: usize, cands: Vec<(usize, &'a Control)>) -> Self { Self { times, cands } }
|
||||
pub fn new(times: usize, cands: Vec<&'a Control>) -> Self { Self { times, cands } }
|
||||
}
|
||||
|
||||
impl Widget for Side<'_> {
|
||||
|
|
@ -16,12 +16,34 @@ impl Widget for Side<'_> {
|
|||
let items = self
|
||||
.cands
|
||||
.into_iter()
|
||||
.map(|(_, c)| {
|
||||
let s = c.on[self.times..].into_iter().map(ToString::to_string).collect::<String>();
|
||||
ListItem::new(format!("{:?}", s))
|
||||
.map(|c| {
|
||||
let mut spans = vec![];
|
||||
|
||||
// Keys
|
||||
let keys = c.on[self.times..].iter().map(ToString::to_string).collect::<Vec<_>>();
|
||||
spans.push(Span::raw(" ".repeat(10usize.saturating_sub(keys.join("").len()))));
|
||||
spans.push(Span::styled(keys[0].clone(), Style::default().fg(Color::LightCyan)));
|
||||
spans.extend(
|
||||
keys
|
||||
.iter()
|
||||
.skip(1)
|
||||
.map(|k| Span::styled(k.to_string(), Style::default().fg(Color::DarkGray))),
|
||||
);
|
||||
|
||||
// Separator
|
||||
spans.push(Span::styled(" ".to_string(), Style::default().fg(Color::DarkGray)));
|
||||
|
||||
// Exec
|
||||
let exec = c.exec.iter().map(ToString::to_string).collect::<Vec<_>>().join("; ");
|
||||
spans.push(Span::styled(exec, Style::default().fg(Color::Magenta)));
|
||||
|
||||
ListItem::new(Line::from(spans))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
List::new(items).render(area, buf);
|
||||
List::new(items)
|
||||
.block(Block::new().padding(Padding::new(0, 1, 1, 1)))
|
||||
.bg(Color::Rgb(47, 51, 73))
|
||||
.render(area, buf);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue