mirror of
https://github.com/sxyazi/yazi.git
synced 2024-10-27 03:27:42 +03:00
Compare commits
10 Commits
a577464325
...
c09437d55f
Author | SHA1 | Date | |
---|---|---|---|
|
c09437d55f | ||
|
52681b19e4 | ||
|
cda7d3f2ea | ||
|
cc50f94de6 | ||
|
8ac8ffa236 | ||
|
3f6498bc17 | ||
|
0abe1e3cde | ||
|
97e622a03d | ||
|
da6976302a | ||
|
11838092cf |
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3253,6 +3253,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"toml_edit",
|
||||
"url",
|
||||
"vergen-gitcl",
|
||||
"yazi-boot",
|
||||
"yazi-dds",
|
||||
|
@ -1 +1 @@
|
||||
{"flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM"],"language":"en","version":"0.2"}
|
||||
{"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek"],"version":"0.2","language":"en","flagWords":[]}
|
@ -1,5 +1,5 @@
|
||||
name: yazi
|
||||
base: core22
|
||||
base: core24
|
||||
adopt-info: yazi
|
||||
summary: Blazing fast terminal file manager written in Rust, based on async I/O.
|
||||
description: |
|
||||
@ -9,9 +9,9 @@ license: MIT
|
||||
grade: stable
|
||||
confinement: classic
|
||||
|
||||
architectures:
|
||||
- amd64
|
||||
# - arm64
|
||||
platforms:
|
||||
amd64:
|
||||
# arm64:
|
||||
|
||||
apps:
|
||||
yazi:
|
||||
|
@ -199,10 +199,10 @@ impl Emulator {
|
||||
bail!("unexpected EOF");
|
||||
}
|
||||
buf.push(c[0]);
|
||||
if c[0] != b'c' || !buf.contains(&b'\x1b') {
|
||||
if c[0] != b'c' || !buf.contains(&0x1b) {
|
||||
continue;
|
||||
}
|
||||
if buf.rsplitn(2, |&b| b == b'\x1b').next().is_some_and(|s| s.starts_with(b"[?")) {
|
||||
if buf.rsplitn(2, |&b| b == 0x1b).next().is_some_and(|s| s.starts_with(b"[?")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ md-5 = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
toml_edit = "0.22.20"
|
||||
url = "2.5.2"
|
||||
|
||||
[build-dependencies]
|
||||
yazi-shared = { path = "../yazi-shared", version = "0.3.0" }
|
||||
|
@ -9,7 +9,7 @@ impl Package {
|
||||
|
||||
let path = self.local();
|
||||
if !must_exists(&path).await {
|
||||
Git::clone(&self.remote(), &path).await?;
|
||||
Git::clone(&self.remote, &path).await?;
|
||||
} else {
|
||||
Git::pull(&path).await?;
|
||||
};
|
||||
|
@ -9,7 +9,7 @@ impl Package {
|
||||
|
||||
let path = self.local();
|
||||
if !must_exists(&path).await {
|
||||
Git::clone(&self.remote(), &path).await?;
|
||||
Git::clone(&self.remote, &path).await?;
|
||||
} else {
|
||||
Git::fetch(&path).await?;
|
||||
};
|
||||
|
@ -2,28 +2,59 @@ use std::{borrow::Cow, io::BufWriter, path::PathBuf};
|
||||
|
||||
use anyhow::Result;
|
||||
use md5::{Digest, Md5};
|
||||
use url::Url;
|
||||
use yazi_shared::Xdg;
|
||||
|
||||
pub(crate) struct Package {
|
||||
pub(crate) repo: String,
|
||||
pub(crate) child: String,
|
||||
pub(crate) remote: String,
|
||||
pub(crate) commit: String,
|
||||
pub(super) is_flavor: bool,
|
||||
}
|
||||
|
||||
impl Package {
|
||||
pub(super) fn new(url: &str, commit: Option<&str>) -> Self {
|
||||
let mut parts = url.splitn(2, '#');
|
||||
match Url::parse(url) {
|
||||
Ok(mut url) => {
|
||||
let repo = url.path().trim_start_matches('/').to_string();
|
||||
let child = match url.fragment() {
|
||||
Some(fragment) => format!("{fragment}.yazi"),
|
||||
None => String::new(),
|
||||
};
|
||||
url.set_fragment(None);
|
||||
let remote = url.to_string();
|
||||
|
||||
let mut repo = parts.next().unwrap_or_default().to_owned();
|
||||
let child = if let Some(s) = parts.next() {
|
||||
format!("{s}.yazi")
|
||||
} else {
|
||||
repo.push_str(".yazi");
|
||||
String::new()
|
||||
};
|
||||
return Self {
|
||||
repo,
|
||||
child,
|
||||
remote,
|
||||
commit: commit.unwrap_or_default().to_owned(),
|
||||
is_flavor: false,
|
||||
};
|
||||
}
|
||||
Err(_) => {
|
||||
let mut parts = url.splitn(2, '#');
|
||||
|
||||
Self { repo, child, commit: commit.unwrap_or_default().to_owned(), is_flavor: false }
|
||||
let mut repo = parts.next().unwrap_or_default().to_owned();
|
||||
let child = if let Some(s) = parts.next() {
|
||||
format!("{s}.yazi")
|
||||
} else {
|
||||
repo.push_str(".yazi");
|
||||
String::new()
|
||||
};
|
||||
|
||||
let remote = format!("https://github.com/{}.git", repo);
|
||||
|
||||
return Self {
|
||||
repo,
|
||||
child,
|
||||
remote,
|
||||
commit: commit.unwrap_or_default().to_owned(),
|
||||
is_flavor: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -50,13 +81,7 @@ impl Package {
|
||||
pub(super) fn local(&self) -> PathBuf {
|
||||
Xdg::state_dir()
|
||||
.join("packages")
|
||||
.join(format!("{:x}", Md5::new_with_prefix(self.remote()).finalize()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn remote(&self) -> String {
|
||||
// Support more Git hosting services in the future
|
||||
format!("https://github.com/{}.git", self.repo)
|
||||
.join(format!("{:x}", Md5::new_with_prefix(&self.remote).finalize()))
|
||||
}
|
||||
|
||||
pub(super) fn header(&self, s: &str) -> Result<()> {
|
||||
|
@ -21,6 +21,9 @@ impl Package {
|
||||
if !package.commit.is_empty() {
|
||||
table.insert("commit", package.commit.into());
|
||||
}
|
||||
if !package.remote.starts_with("https://github.com") {
|
||||
table.insert("remote", package.remote.into());
|
||||
}
|
||||
|
||||
if package.is_flavor {
|
||||
doc["flavor"]["deps"].as_array_mut().unwrap().push(table);
|
||||
@ -47,9 +50,10 @@ impl Package {
|
||||
for dep in deps.iter_mut() {
|
||||
let dep = dep.as_inline_table_mut().context("Dependency must be an inline table")?;
|
||||
let use_ = dep.get("use").and_then(|d| d.as_str()).context("Missing `use` field")?;
|
||||
let remote = dep.get("remote").and_then(|d| d.as_str());
|
||||
let commit = dep.get("commit").and_then(|d| d.as_str());
|
||||
|
||||
let mut package = Package::new(use_, commit);
|
||||
let mut package = Package::new(if let Some(remote) = remote { remote } else { use_ }, commit);
|
||||
if upgrade {
|
||||
package.upgrade().await?;
|
||||
} else {
|
||||
|
@ -92,7 +92,7 @@ fetchers = [
|
||||
]
|
||||
preloaders = [
|
||||
# Image
|
||||
{ mime = "image/{avif,heic,jxl,svg+xml}", run = "magick" },
|
||||
{ mime = "image/{avif,hei?,jxl,svg+xml}", run = "magick" },
|
||||
{ mime = "image/*", run = "image" },
|
||||
# Video
|
||||
{ mime = "video/*", run = "video" },
|
||||
@ -110,7 +110,7 @@ previewers = [
|
||||
# JSON
|
||||
{ mime = "application/{json,x-ndjson}", run = "json" },
|
||||
# Image
|
||||
{ mime = "image/{avif,heic,jxl,svg+xml}", run = "magick" },
|
||||
{ mime = "image/{avif,hei?,jxl,svg+xml}", run = "magick" },
|
||||
{ mime = "image/*", run = "image" },
|
||||
# Video
|
||||
{ mime = "video/*", run = "video" },
|
||||
|
@ -28,7 +28,7 @@ impl Manager {
|
||||
self.current_mut().tracing = true;
|
||||
}
|
||||
|
||||
// Re-peek
|
||||
// Repeek
|
||||
self.peek(false);
|
||||
|
||||
// Refresh watcher
|
||||
|
@ -50,9 +50,12 @@ impl Manager {
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
let repeek = self.hovered().is_some_and(|f| updates.contains_key(&f.url));
|
||||
self.mimetype.extend(updates);
|
||||
self.peek(false);
|
||||
|
||||
if repeek {
|
||||
self.peek(false);
|
||||
}
|
||||
tasks.prework_affected(&affected, &self.mimetype);
|
||||
render!();
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ impl Watcher {
|
||||
|
||||
async fn fan_out(rx: UnboundedReceiver<Url>) {
|
||||
// TODO: revert this once a new notification is implemented
|
||||
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(1000, Duration::from_millis(50));
|
||||
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(1000, Duration::from_millis(100));
|
||||
pin!(rx);
|
||||
|
||||
while let Some(chunk) = rx.next().await {
|
||||
|
@ -89,25 +89,11 @@ impl Preview {
|
||||
matches!(self.lock, Some(ref lock) if lock.url == *url)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn content_unchanged(&self, url: &Url, cha: &Cha) -> bool {
|
||||
let Some(lock) = &self.lock else {
|
||||
return false;
|
||||
};
|
||||
|
||||
*url == lock.url
|
||||
&& self.skip == lock.skip
|
||||
&& cha.len == lock.cha.len
|
||||
&& cha.mtime == lock.cha.mtime
|
||||
&& cha.kind == lock.cha.kind
|
||||
&& {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
cha.perm == lock.cha.perm
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
true
|
||||
}
|
||||
}
|
||||
match &self.lock {
|
||||
Some(l) => *url == l.url && self.skip == l.skip && cha.hits(l.cha),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use std::ops::Range;
|
||||
use anyhow::{bail, Result};
|
||||
use ratatui::{buffer::Buffer, layout::Rect, text::Line, widgets::{Block, BorderType, Paragraph, Widget}};
|
||||
use syntect::easy::HighlightLines;
|
||||
use yazi_config::THEME;
|
||||
use yazi_config::{PREVIEW, THEME};
|
||||
use yazi_core::input::InputMode;
|
||||
use yazi_plugin::external::Highlighter;
|
||||
|
||||
@ -21,11 +21,11 @@ impl<'a> Input<'a> {
|
||||
bail!("Highlighting is disabled");
|
||||
}
|
||||
|
||||
let (theme, syntaxes) = Highlighter::init();
|
||||
let (theme, syntaxes) = futures::executor::block_on(Highlighter::init());
|
||||
if let Some(syntax) = syntaxes.find_syntax_by_name("Bourne Again Shell (bash)") {
|
||||
let mut h = HighlightLines::new(syntax, theme);
|
||||
let regions = h.highlight_line(self.cx.input.value(), syntaxes)?;
|
||||
return Ok(Highlighter::to_line_widget(regions));
|
||||
return Ok(Highlighter::to_line_widget(regions, &" ".repeat(PREVIEW.tab_size as usize)));
|
||||
}
|
||||
bail!("Failed to find syntax")
|
||||
}
|
||||
|
@ -264,19 +264,18 @@ impl Files {
|
||||
|
||||
macro_rules! go {
|
||||
($dist:expr, $src:expr, $inc:literal) => {
|
||||
let mut b = false;
|
||||
let mut b = true;
|
||||
for i in 0..$dist.len() {
|
||||
if let Some(f) = $src.remove(&$dist[i].url) {
|
||||
if $dist[i] != f {
|
||||
b = true;
|
||||
$dist[i] = f;
|
||||
}
|
||||
b &= $dist[i].cha.hits(f.cha);
|
||||
$dist[i] = f;
|
||||
|
||||
if $src.is_empty() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.revision += if b { $inc } else { 0 };
|
||||
self.revision += if b { 0 } else { $inc };
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ function M:preload()
|
||||
string.format("%dx%d^", PREVIEW.max_width, PREVIEW.max_height),
|
||||
"-quality",
|
||||
tostring(PREVIEW.image_quality),
|
||||
"-auto-orient",
|
||||
"JPG:" .. tostring(cache),
|
||||
}):spawn()
|
||||
|
||||
|
55
yazi-plugin/src/external/highlighter.rs
vendored
55
yazi-plugin/src/external/highlighter.rs
vendored
@ -1,15 +1,14 @@
|
||||
use std::{io::Cursor, mem, path::{Path, PathBuf}, sync::{atomic::{AtomicUsize, Ordering}, OnceLock}};
|
||||
use std::{io::Cursor, mem, path::{Path, PathBuf}, sync::atomic::{AtomicUsize, Ordering}};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use ratatui::text::{Line, Span, Text};
|
||||
use syntect::{dumps, easy::HighlightLines, highlighting::{self, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}};
|
||||
use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}};
|
||||
use syntect::{dumps, easy::HighlightLines, highlighting::{self, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}, LoadingError};
|
||||
use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}, sync::OnceCell};
|
||||
use yazi_config::{PREVIEW, THEME};
|
||||
use yazi_shared::PeekError;
|
||||
|
||||
static INCR: AtomicUsize = AtomicUsize::new(0);
|
||||
static SYNTECT_SYNTAX: OnceLock<SyntaxSet> = OnceLock::new();
|
||||
static SYNTECT_THEME: OnceLock<Theme> = OnceLock::new();
|
||||
static SYNTECT: OnceCell<(Theme, SyntaxSet)> = OnceCell::const_new();
|
||||
|
||||
pub struct Highlighter {
|
||||
path: PathBuf,
|
||||
@ -19,27 +18,28 @@ impl Highlighter {
|
||||
#[inline]
|
||||
pub fn new(path: &Path) -> Self { Self { path: path.to_owned() } }
|
||||
|
||||
pub fn init() -> (&'static Theme, &'static SyntaxSet) {
|
||||
#[inline]
|
||||
fn from_file() -> Result<Theme> {
|
||||
let file = std::fs::File::open(&THEME.manager.syntect_theme)?;
|
||||
Ok(ThemeSet::load_from_reader(&mut std::io::BufReader::new(file))?)
|
||||
}
|
||||
pub async fn init() -> (&'static Theme, &'static SyntaxSet) {
|
||||
let fut = async {
|
||||
tokio::task::spawn_blocking(|| {
|
||||
let theme = std::fs::File::open(&THEME.manager.syntect_theme)
|
||||
.map_err(LoadingError::Io)
|
||||
.and_then(|f| ThemeSet::load_from_reader(&mut std::io::BufReader::new(f)))
|
||||
.or_else(|_| ThemeSet::load_from_reader(&mut Cursor::new(yazi_prebuild::ansi_theme())));
|
||||
|
||||
let theme = SYNTECT_THEME.get_or_init(|| {
|
||||
from_file().unwrap_or_else(|_| {
|
||||
ThemeSet::load_from_reader(&mut Cursor::new(yazi_prebuild::ansi_theme())).unwrap()
|
||||
let syntaxes = dumps::from_uncompressed_data(yazi_prebuild::syntaxes());
|
||||
|
||||
(theme.unwrap(), syntaxes.unwrap())
|
||||
})
|
||||
});
|
||||
.await
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let syntaxes = SYNTECT_SYNTAX
|
||||
.get_or_init(|| dumps::from_uncompressed_data(yazi_prebuild::syntaxes()).unwrap());
|
||||
|
||||
(theme, syntaxes)
|
||||
let r = SYNTECT.get_or_init(|| fut).await;
|
||||
(&r.0, &r.1)
|
||||
}
|
||||
|
||||
async fn find_syntax(path: &Path) -> Result<&'static SyntaxReference> {
|
||||
let (_, syntaxes) = Self::init();
|
||||
let (_, syntaxes) = Self::init().await;
|
||||
let name = path.file_name().map(|n| n.to_string_lossy()).unwrap_or_default();
|
||||
if let Some(s) = syntaxes.find_syntax_by_extension(&name) {
|
||||
return Ok(s);
|
||||
@ -73,7 +73,7 @@ impl Highlighter {
|
||||
break;
|
||||
}
|
||||
|
||||
if !plain && buf.len() > 6000 {
|
||||
if !plain && (buf.len() > 5000 || buf.contains(&0x1b)) {
|
||||
plain = true;
|
||||
drop(mem::take(&mut before));
|
||||
}
|
||||
@ -98,7 +98,7 @@ impl Highlighter {
|
||||
|
||||
if plain {
|
||||
let indent = " ".repeat(PREVIEW.tab_size as usize);
|
||||
Ok(Text::from(after.join("").replace('\t', &indent)))
|
||||
Ok(Text::from(after.join("").replace('\x1b', "^[").replace('\t', &indent)))
|
||||
} else {
|
||||
Self::highlight_with(before, after, syntax.unwrap()).await
|
||||
}
|
||||
@ -110,11 +110,10 @@ impl Highlighter {
|
||||
syntax: &'static SyntaxReference,
|
||||
) -> Result<Text<'static>, PeekError> {
|
||||
let ticket = INCR.load(Ordering::Relaxed);
|
||||
let (theme, syntaxes) = Self::init().await;
|
||||
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let (theme, syntaxes) = Self::init();
|
||||
let mut h = HighlightLines::new(syntax, theme);
|
||||
|
||||
for line in before {
|
||||
if ticket != INCR.load(Ordering::Relaxed) {
|
||||
return Err("Highlighting cancelled".into());
|
||||
@ -122,6 +121,7 @@ impl Highlighter {
|
||||
h.highlight_line(&line, syntaxes).map_err(|e| anyhow!(e))?;
|
||||
}
|
||||
|
||||
let indent = " ".repeat(PREVIEW.tab_size as usize);
|
||||
let mut lines = Vec::with_capacity(after.len());
|
||||
for line in after {
|
||||
if ticket != INCR.load(Ordering::Relaxed) {
|
||||
@ -129,7 +129,7 @@ impl Highlighter {
|
||||
}
|
||||
|
||||
let regions = h.highlight_line(&line, syntaxes).map_err(|e| anyhow!(e))?;
|
||||
lines.push(Self::to_line_widget(regions));
|
||||
lines.push(Self::to_line_widget(regions, &indent));
|
||||
}
|
||||
|
||||
Ok(Text::from(lines))
|
||||
@ -182,8 +182,7 @@ impl Highlighter {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_line_widget(regions: Vec<(highlighting::Style, &str)>) -> Line<'static> {
|
||||
let indent = " ".repeat(PREVIEW.tab_size as usize);
|
||||
pub fn to_line_widget(regions: Vec<(highlighting::Style, &str)>, indent: &str) -> Line<'static> {
|
||||
let spans: Vec<_> = regions
|
||||
.into_iter()
|
||||
.map(|(style, s)| {
|
||||
@ -199,7 +198,7 @@ impl Highlighter {
|
||||
}
|
||||
|
||||
Span {
|
||||
content: s.replace('\t', &indent).into(),
|
||||
content: s.replace('\t', indent).into(),
|
||||
style: ratatui::style::Style {
|
||||
fg: Self::to_ansi_color(style.foreground),
|
||||
// bg: Self::to_ansi_color(style.background),
|
||||
|
@ -120,6 +120,20 @@ impl Cha {
|
||||
self.kind |= kind;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hits(self, c: Self) -> bool {
|
||||
self.len == c.len && self.mtime == c.mtime && self.ctime == c.ctime && self.kind == c.kind && {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
self.perm == c.perm
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Cha {
|
||||
|
@ -25,13 +25,6 @@ impl AsRef<File> for File {
|
||||
fn as_ref(&self) -> &File { self }
|
||||
}
|
||||
|
||||
impl PartialEq for File {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.cha == other.cha && self.url == other.url && self.link_to == other.link_to
|
||||
}
|
||||
}
|
||||
|
||||
impl File {
|
||||
#[inline]
|
||||
pub async fn from(url: Url) -> Result<Self> {
|
||||
|
Loading…
Reference in New Issue
Block a user