feat: add pdf preview with pdftoppm (#18)

This commit is contained in:
Yifan Song 2023-08-03 22:01:36 +08:00 committed by GitHub
parent 4af79f8f4a
commit 0485259302
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 0 deletions

View file

@ -5,6 +5,7 @@ mod file;
mod fzf; mod fzf;
mod jq; mod jq;
mod lsar; mod lsar;
mod pdftoppm;
mod rg; mod rg;
mod unar; mod unar;
mod zoxide; mod zoxide;
@ -16,6 +17,7 @@ pub use file::*;
pub use fzf::*; pub use fzf::*;
pub use jq::*; pub use jq::*;
pub use lsar::*; pub use lsar::*;
pub use pdftoppm::*;
pub use rg::*; pub use rg::*;
pub use unar::*; pub use unar::*;
pub use zoxide::*; pub use zoxide::*;

22
core/src/external/pdftoppm.rs vendored Normal file
View file

@ -0,0 +1,22 @@
use std::path::Path;
use anyhow::{bail, Result};
use tokio::process::Command;
pub async fn pdftoppm(path: &Path, dest: &Path) -> Result<()> {
let output = Command::new("pdftoppm")
.args(["-png", "-singlefile"])
.arg(path)
.arg(dest)
.kill_on_drop(true)
.output()
.await?;
if !output.status.success() {
bail!(
"failed to get pdf: {}",
String::from_utf8_lossy(&output.stderr)
);
}
Ok(())
}

View file

@ -63,6 +63,7 @@ impl Preview {
MimeKind::JSON => Self::json(&path).await.map(PreviewData::Text), MimeKind::JSON => Self::json(&path).await.map(PreviewData::Text),
MimeKind::Text => Self::highlight(&path).await.map(PreviewData::Text), MimeKind::Text => Self::highlight(&path).await.map(PreviewData::Text),
MimeKind::Image => Self::image(&path).await, MimeKind::Image => Self::image(&path).await,
MimeKind::Pdf => Self::pdf(&path).await,
MimeKind::Video => Self::video(&path).await, MimeKind::Video => Self::video(&path).await,
MimeKind::Archive => Self::archive(&path).await.map(PreviewData::Text), MimeKind::Archive => Self::archive(&path).await.map(PreviewData::Text),
MimeKind::Others => Err(anyhow!("Unsupported mimetype: {mime}")), MimeKind::Others => Err(anyhow!("Unsupported mimetype: {mime}")),
@ -117,6 +118,19 @@ impl Preview {
Self::image(&cache).await Self::image(&cache).await
} }
pub async fn pdf(path: &Path) -> Result<PreviewData> {
let cache = Image::cache(path);
if fs::metadata(&cache).await.is_err() {
external::pdftoppm(path, &cache).await?;
}
let mut dest = cache.into_os_string();
dest.push(".png");
let dest = Path::new(&dest);
Self::image(dest).await
}
pub async fn json(path: &Path) -> Result<String> { pub async fn json(path: &Path) -> Result<String> {
Ok( Ok(
external::jq(path) external::jq(path)

View file

@ -7,6 +7,7 @@ pub enum MimeKind {
Text, Text,
Image, Image,
Video, Video,
Pdf,
Archive, Archive,
Others, Others,
} }
@ -27,6 +28,7 @@ impl MimeKind {
"message" => true, "message" => true,
"model" => true, "model" => true,
"multipart" => true, "multipart" => true,
"pdf" => true,
"text" => true, "text" => true,
"video" => true, "video" => true,
_ => false, _ => false,
@ -39,6 +41,8 @@ impl MimeKind {
Self::Dir Self::Dir
} else if s == "application/json" { } else if s == "application/json" {
Self::JSON Self::JSON
} else if s == "application/pdf" {
Self::Pdf
} else if s.starts_with("text/") || s.ends_with("/xml") { } else if s.starts_with("text/") || s.ends_with("/xml") {
Self::Text Self::Text
} else if s.starts_with("image/") { } else if s.starts_with("image/") {