refactor: add tmpfile function to Boot

This commit is contained in:
sxyazi 2023-08-13 18:59:25 +08:00
parent acb2eee65f
commit aa441cd7f0
No known key found for this signature in database
11 changed files with 66 additions and 38 deletions

2
Cargo.lock generated
View file

@ -348,6 +348,8 @@ dependencies = [
"crossterm 0.27.0",
"futures",
"glob",
"indexmap 2.0.0",
"md-5",
"once_cell",
"ratatui",
"regex",

View file

@ -1,13 +1,13 @@
use std::{path::{Path, PathBuf}, sync::atomic::{AtomicBool, Ordering}};
use anyhow::Result;
use config::{preview::PreviewAdaptor, PREVIEW};
use config::{preview::PreviewAdaptor, BOOT, PREVIEW};
use once_cell::sync::Lazy;
use ratatui::prelude::Rect;
use tokio::{fs, sync::mpsc::UnboundedSender};
use super::{Iterm2, Kitty, Ueberzug};
use crate::{Image, Sixel};
use crate::Sixel;
static IMAGE_SHOWN: AtomicBool = AtomicBool::new(false);
@ -25,7 +25,7 @@ impl Adaptor {
Self::image_hide(rect);
}
let cache = Image::cache(path);
let cache = BOOT.cache(path);
if fs::metadata(&cache).await.is_ok() {
path = cache.as_path();
}

View file

@ -1,9 +1,8 @@
use std::{path::{Path, PathBuf}, sync::Arc};
use std::{path::Path, sync::Arc};
use anyhow::Result;
use config::{BOOT, PREVIEW};
use config::PREVIEW;
use image::{imageops::FilterType, DynamicImage, ImageFormat};
use md5::{Digest, Md5};
use shared::tty_ratio;
use tokio::fs;
@ -54,11 +53,4 @@ impl Image {
_ => fs::write(cache, &*img).await?,
})
}
#[inline]
pub fn cache(path: &Path) -> PathBuf {
BOOT
.cache_dir
.join(format!("{:x}", Md5::new_with_prefix(path.to_string_lossy().as_bytes()).finalize()))
}
}

View file

@ -12,6 +12,8 @@ clap = { version = "^4", features = [ "derive" ] }
crossterm = "^0"
futures = "^0"
glob = "^0"
indexmap = "^2"
md-5 = "^0"
once_cell = "^1"
ratatui = "^0"
regex = "^1"

View file

@ -1,6 +1,7 @@
use std::{env, fs, path::PathBuf};
use std::{env, fs, path::{Path, PathBuf}, time::{self, SystemTime}};
use clap::Parser;
use md5::{Digest, Md5};
#[derive(Debug)]
pub struct Boot {
@ -37,3 +38,18 @@ impl Default for Boot {
boot
}
}
impl Boot {
#[inline]
pub fn cache(&self, path: &Path) -> PathBuf {
self
.cache_dir
.join(format!("{:x}", Md5::new_with_prefix(path.to_string_lossy().as_bytes()).finalize()))
}
#[inline]
pub fn tmpfile(&self) -> PathBuf {
let nanos = SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap().as_nanos();
self.cache_dir.join(format!("{:x}", Md5::new_with_prefix(nanos.to_le_bytes()).finalize()))
}
}

View file

@ -1,5 +1,6 @@
use std::{collections::{BTreeMap, BTreeSet}, path::Path};
use std::{collections::BTreeMap, path::Path};
use indexmap::IndexSet;
use serde::{Deserialize, Deserializer};
use shared::MIME_DIR;
@ -8,7 +9,7 @@ use crate::{Pattern, MERGED_YAZI};
#[derive(Debug)]
pub struct Open {
openers: BTreeMap<String, Vec<Opener>>,
openers: BTreeMap<String, IndexSet<Opener>>,
rules: Vec<OpenRule>,
}
@ -25,26 +26,36 @@ impl Default for Open {
}
impl Open {
pub fn openers<P, M>(&self, path: P, mime: M) -> Option<Vec<&Opener>>
pub fn openers<P, M>(&self, path: P, mime: M) -> Option<&IndexSet<Opener>>
where
P: AsRef<Path>,
M: AsRef<str>,
{
self.rules.iter().find_map(|rule| {
if rule.name.as_ref().map_or(false, |e| e.match_path(&path, Some(mime.as_ref() == MIME_DIR)))
|| rule.mime.as_ref().map_or(false, |m| m.matches(&mime))
let is_folder = Some(mime.as_ref() == MIME_DIR);
if rule.mime.as_ref().map_or(false, |m| m.matches(&mime))
|| rule.name.as_ref().map_or(false, |n| n.match_path(&path, is_folder))
{
self.openers.get(&rule.use_).map(|v| v.iter().collect())
self.openers.get(&rule.use_)
} else {
None
}
})
}
#[inline]
pub fn block_opener<P, M>(&self, path: P, mime: M) -> Option<&Opener>
where
P: AsRef<Path>,
M: AsRef<str>,
{
self.openers(path, mime).and_then(|o| o.iter().find(|o| o.block))
}
pub fn common_openers(&self, targets: &[(impl AsRef<Path>, impl AsRef<str>)]) -> Vec<&Opener> {
let grouped = targets.iter().filter_map(|(p, m)| self.openers(p, m)).collect::<Vec<_>>();
let flat = grouped.iter().flatten().cloned().collect::<BTreeSet<_>>();
flat.into_iter().filter(|o| grouped.iter().all(|g| g.contains(o))).collect()
let flat = grouped.iter().flat_map(|&g| g).collect::<IndexSet<_>>();
flat.into_iter().filter(|&o| grouped.iter().all(|g| g.contains(o))).collect()
}
}
@ -64,6 +75,7 @@ impl<'de> Deserialize<'de> for Open {
}
let outer = Outer::deserialize(deserializer)?;
Ok(Self { openers: outer.opener, rules: outer.open.rules })
let openers = outer.opener.into_iter().map(|(k, v)| (k, IndexSet::from_iter(v))).collect();
Ok(Self { openers, rules: outer.open.rules })
}
}

View file

@ -2,7 +2,8 @@
clippy::if_same_then_else,
clippy::len_without_is_empty,
clippy::module_inception,
clippy::option_map_unit_fn
clippy::option_map_unit_fn,
clippy::unit_arg
)]
mod blocker;

View file

@ -1,8 +1,8 @@
use std::{io::BufRead, mem, path::{Path, PathBuf}, sync::{atomic::{AtomicUsize, Ordering}, Arc}};
use adaptor::{Adaptor, Image};
use adaptor::Adaptor;
use anyhow::{anyhow, bail, Result};
use config::PREVIEW;
use config::{BOOT, PREVIEW};
use ratatui::prelude::Rect;
use shared::{tty_size, MimeKind};
use syntect::{easy::HighlightFile, util::as_24_bit_terminal_escaped};
@ -113,7 +113,7 @@ impl Preview {
}
pub async fn video(path: &Path) -> Result<PreviewData> {
let cache = Image::cache(path);
let cache = BOOT.cache(path);
if fs::metadata(&cache).await.is_err() {
external::ffmpegthumbnailer(path, &cache).await?;
}
@ -122,7 +122,7 @@ impl Preview {
}
pub async fn pdf(path: &Path) -> Result<PreviewData> {
let cache = Image::cache(path);
let cache = BOOT.cache(path);
if fs::metadata(&cache).await.is_err() {
external::pdftoppm(path, &cache).await?;
}

View file

@ -2,12 +2,12 @@ use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, io::{stdout, Wr
use config::{manager::SortBy, open::Opener, OPEN};
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use shared::{tty_size, MimeKind};
use shared::{tty_size, Defer, MimeKind};
use tokio::{io::AsyncReadExt, select, sync::mpsc, time};
use tracing::trace;
use super::{task::TaskSummary, Scheduler, TASKS_PADDING, TASKS_PERCENT};
use crate::{emit, files::{File, Files}, input::InputOpt, BLOCKER};
use crate::{emit, files::{File, Files}, input::InputOpt, Event, BLOCKER};
pub struct Tasks {
scheduler: Arc<Scheduler>,
@ -80,6 +80,11 @@ impl Tasks {
};
emit!(Stop(true)).await;
let _defer = Defer::new(|| {
disable_raw_mode().ok();
Event::Stop(false, None).emit()
});
stdout().write_all("\n".repeat(tty_size().ws_row as usize).as_bytes()).ok();
stdout().write_all(buffered.as_bytes()).ok();
enable_raw_mode().ok();
@ -112,9 +117,6 @@ impl Tasks {
while quit[0] != b'q' {
stdin.read(&mut quit).await.ok();
}
disable_raw_mode().ok();
emit!(Stop(false)).await;
});
false
}
@ -132,7 +134,7 @@ impl Tasks {
pub fn file_open(&self, targets: &[(impl AsRef<Path>, impl AsRef<str>)]) -> bool {
let mut openers = BTreeMap::new();
for (path, mime) in targets {
if let Some(opener) = OPEN.openers(path, mime).and_then(|o| o.first().cloned()) {
if let Some(opener) = OPEN.openers(path, mime).and_then(|o| o.first()) {
openers.entry(opener).or_insert_with(Vec::new).push(path.as_ref().as_os_str());
}
}

View file

@ -2,6 +2,7 @@ use std::{collections::{BTreeMap, BTreeSet}, path::PathBuf, sync::Arc};
use adaptor::Image;
use anyhow::Result;
use config::BOOT;
use parking_lot::Mutex;
use shared::{calculate_size, Throttle};
use tokio::{fs, sync::mpsc};
@ -73,7 +74,7 @@ impl Precache {
pub(crate) async fn work(&self, task: &mut PrecacheOp) -> Result<()> {
match task {
PrecacheOp::Image(task) => {
let cache = Image::cache(&task.target);
let cache = BOOT.cache(&task.target);
if fs::metadata(&cache).await.is_ok() {
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
}
@ -83,7 +84,7 @@ impl Precache {
self.sch.send(TaskOp::Adv(task.id, 1, 0))?;
}
PrecacheOp::Video(task) => {
let cache = Image::cache(&task.target);
let cache = BOOT.cache(&task.target);
if fs::metadata(&cache).await.is_ok() {
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
}
@ -92,7 +93,7 @@ impl Precache {
self.sch.send(TaskOp::Adv(task.id, 1, 0))?;
}
PrecacheOp::Pdf(task) => {
let cache = Image::cache(&task.target);
let cache = BOOT.cache(&task.target);
if fs::metadata(&cache).await.is_ok() {
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
}

View file

@ -1 +1 @@
{"language":"en","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","nocapture"],"version":"0.2"}
{"language":"en","version":"0.2","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"]}