branch: elpa/dirvish
commit c28654d29c4091a8fae1f41572c95480250e07c4
Author: Alex Lu <[email protected]>
Commit: Alex Lu <[email protected]>
feat: support font preview
---
dirvish-widgets.el | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++
dirvish.el | 7 +++++--
docs/CUSTOMIZING.org | 11 +++++-----
3 files changed, 68 insertions(+), 7 deletions(-)
diff --git a/dirvish-widgets.el b/dirvish-widgets.el
index 839808502d..c118c3f799 100644
--- a/dirvish-widgets.el
+++ b/dirvish-widgets.el
@@ -30,6 +30,7 @@
;; - requires `mtn' on Windows (special thanks to @samb233!)
;; - `audio': preview audio files with metadata, requires `mediainfo'
;; - `epub': preview epub documents, requires `epub-thumbnail'
+;; - `font': preview font files, requires `magick'
;; - `pdf': preview pdf documents via `pdf-tools'
;; - `archive': preview archive files, requires `tar' and `unzip'
;; - `dired': preview directories using `dired' (asynchronously)
@@ -78,6 +79,11 @@ This is used to generate thumbnail for epub files."
This is used to retrieve metadata for multiple types of media files."
:group 'dirvish :type 'string)
+(defcustom dirvish-magick-program "magick"
+ "Absolute or reletive name of the `magick' program.
+This is used to generate thumbnail for font files."
+ :group 'dirvish :type 'string)
+
(defcustom dirvish-pdfinfo-program "pdfinfo"
"Absolute or reletive name of the `pdfinfo' program.
This is used to retrieve pdf metadata."
@@ -93,11 +99,21 @@ This is used to generate thumbnails for pdf files."
This is used to list files and their attributes for .zip archives."
:group 'dirvish :type 'string)
+(defcustom dirvish-fc-query-program "fc-query"
+ "Absolute or reletive name of the `fc-query' program.
+This is used to generate metadata for font files."
+ :group 'dirvish :type 'string)
+
(defcustom dirvish-show-media-properties
(and (executable-find dirvish-mediainfo-program) t)
"Show media properties automatically in preview window."
:group 'dirvish :type 'boolean)
+(defcustom dirvish-font-preview-sample-text
+ "\nABCDEFGHIJKLMNOPQRSTUVWXYZ\nabcdefghijklmnopqrstuvwxyz\nThe quick brown
fox jumps over the lazy dog\n\n 枕上轻寒窗外雨 眼前春色梦中人
\n1234567890\n!@$\%(){}[]\nالسلام عليكم"
+ "Sample text for font preview."
+ :group 'dirvish :type 'string)
+
(defconst dirvish-media--img-max-width 2400)
(defconst dirvish-media--img-scale-h 0.75)
(defconst dirvish-media--img-scale-w 0.92)
@@ -106,6 +122,10 @@ This is used to list files and their attributes for .zip
archives."
Image;(Width . \"\"%Width/String%\"\")(Height .
\"\"%Height/String%\"\")(Bit-depth . \"\"%BitDepth/String%\"\")(Color-space .
\"\"%ColorSpace%\"\")(Chroma-subsampling .
\"\"%ChromaSubsampling%\"\")(Compression-mode .
\"\"%Compression_Mode/String%\"\")
Video;(Resolution . \"\"%Width% x %Height%\"\")(Video-codec .
\"\"%CodecID%\"\")(Framerate . \"\"%FrameRate%\"\")(Video-bitrate .
\"\"%BitRate/String%\"\")
Audio;(Audio-codec . \"\"%CodecID%\"\")(Audio-bitrate .
\"\"%BitRate/String%\"\")(Audio-sampling-rate .
\"\"%SamplingRate/String%\"\")(Audio-channels . \"\"%ChannelLayout%\"\")")
+(defconst dirvish--fc-query-format
+ "(Family . \"%{family}\")(Family-lang . \"%{familylang}\")(Style .
\"%{style}\")(Style-lang . \"%{stylelang}\")(Full-name . \"%{fullname}\")
+(Slant . \"%{slant}\")(Weight . \"%{weight}\")(Width . \"%{width}\")(Spacing .
\"%{spacing}\")
+(Foundry . \"%{foundry}\")(Capability . \"%{capability}\")(Font-format .
\"%{fontformat}\")(Decorative . \"%{decorative}\")")
(defface dirvish-free-space
'((t (:inherit font-lock-constant-face)))
@@ -506,6 +526,25 @@ GROUP-TITLES is a list of group titles."
(format "%s%s" (dirvish-media--group-heading '("PDF info"))
(dirvish-media--metadata-from-pdfinfo (cdr file))))
+(cl-defmethod dirvish-media-metadata ((file (head font)))
+ "Get metadata for font FILE."
+ (let ((finfo
+ (read (format "(%s)" (shell-command-to-string
+ (format "%s -f '%s' %s"
+ dirvish-fc-query-program
+ dirvish--fc-query-format
+ (shell-quote-argument (cdr file))))))))
+ (format "%s%s\n%s%s\n%s%s"
+ (dirvish-media--group-heading '("Family" "Style"))
+ (dirvish-media--format-metadata
+ finfo '(Family Family-lang Style Style-lang Full-name))
+ (dirvish-media--group-heading '("Characteristics"))
+ (dirvish-media--format-metadata
+ finfo '(Slant Weight Width Spacing))
+ (dirvish-media--group-heading '("Others"))
+ (dirvish-media--format-metadata
+ finfo '(Foundry Capability Font-format Decorative)))))
+
(cl-defmethod dirvish-preview-dispatch ((recipe (head img)) dv)
"Insert RECIPE as an image at preview window of DV."
(with-current-buffer (dirvish--special-buffer 'preview dv t)
@@ -526,6 +565,7 @@ GROUP-TITLES is a list of group titles."
(ext (downcase (or (file-name-extension file) "")))
(type (cond ((member ext dirvish-image-exts) 'image)
((member ext dirvish-video-exts) 'video)
+ ((member ext dirvish-font-exts) 'font)
((and (memq 'pdf-preface
dirvish-preview-dispatchers)
(equal ext "pdf") 'pdf))
@@ -583,6 +623,23 @@ Require: `vipsthumbnail'"
(t `(cache . (,dirvish-vipsthumbnail-program
,file "--size" ,(format "%sx" w) "--output" ,cache)))))))
+;; TODO: switch to `libvips' after its text rendering issues get solved
+(dirvish-define-preview font (file ext preview-window)
+ "Preview font files.
+Require: `magick' (from `imagemagick' suite)"
+ :require (dirvish-magick-program)
+ (when (member ext dirvish-font-exts)
+ (let* ((w (dirvish-media--img-size preview-window))
+ (h (dirvish-media--img-size preview-window 'height))
+ (cache (dirvish-media--cache-path file (format "images/%s" w)
".jpg")))
+ (if (file-exists-p cache)
+ `(img . ,(create-image cache nil nil :max-width w :max-height h))
+ `(cache . (,dirvish-magick-program
+ "-size" "1000x500" "xc:#ffffff" "-gravity" "center"
+ "-pointsize" "40" "-font" ,file "-fill" "#000000"
+ "-annotate" "+0+20" ,dirvish-font-preview-sample-text
+ "-flatten" ,cache))))))
+
(dirvish-define-preview gif (file ext)
"Preview gif images with animations."
(when (equal ext "gif")
diff --git a/dirvish.el b/dirvish.el
index e0c714dccb..bb3ab4bb6b 100644
--- a/dirvish.el
+++ b/dirvish.el
@@ -45,7 +45,7 @@ Dirvish ships with these attributes:
(defcustom dirvish-preview-dispatchers
`(,(if (memq system-type '(ms-dos windows-nt)) 'video-mtn 'video)
- image gif audio epub archive pdf dired)
+ image gif audio epub archive font pdf dired)
"List of preview dispatchers.
Each dispatcher in this list handles the validation and preview
content generation for the corresponding filetype.
@@ -59,6 +59,7 @@ The default value contains:
- audio: preview audio files with metadata, requires `mediainfo'.
- epub: preview epub documents, requires `epub-thumbnailer'.
- pdf: preview pdf documents via `pdf-tools'.
+- font: preview font files, requires `magick'.
- archive: preview archives such as .tar, .zip, requires `7z' (`7zz' on macOS).
- dired: preview directories using `emacs --batch'."
:group 'dirvish :type '(repeat (symbol :tag "Dirvish preview methods")))
@@ -214,8 +215,9 @@ Notice that it only take effects on the built-in `dired'
preview dispatcher."
(defconst dirvish-image-exts '("webp" "wmf" "pcx" "xif" "wbmp" "vtf" "tap"
"s1j" "sjp" "sjpg" "s1g" "sgi" "sgif" "s1n" "spn" "spng" "xyze" "rgbe" "hdr"
"b16" "mdi" "apng" "ico" "pgb" "rlc" "mmr" "fst" "fpx" "fbs" "dxf" "dwg" "djv"
"uvvg" "uvg" "uvvi" "uvi" "azv" "psd" "tfx" "t38" "svgz" "svg" "pti" "btf"
"btif" "ktx2" "ktx" "jxss" "jxsi" "jxsc" "jxs" "jxrs" "jxra" "jxr" "jxl" "jpf"
"jpx" "jpgm" "jpm" "jfif" "jhc" "jph" "jpg2" "jp2" "jls" "hsj2" "hej2" "heifs"
"heif" "heics" "heic" "fts" [...]
(defconst dirvish-audio-exts '("ape" "stm" "s3m" "ra" "rm" "ram" "wma" "wax"
"m3u" "med" "669" "mtm" "m15" "uni" "ult" "mka" "flac" "axa" "kar" "midi" "mid"
"s1m" "smp" "smp3" "rip" "multitrack" "ecelp9600" "ecelp7470" "ecelp4800" "vbk"
"pya" "lvp" "plj" "dtshd" "dts" "mlp" "eol" "uvva" "uva" "koz" "xhe" "loas"
"sofa" "smv" "qcp" "psid" "sid" "spx" "opus" "ogg" "oga" "mp1" "mpga" "m4a"
"mxmf" "mhas" "l16" "lbc" "evw" "enw" "evb" "evc" "dls" "omg" "aa3" "at3" "atx"
"aal" "acn" "awb" "amr" [...]
(defconst dirvish-video-exts '("f4v" "rmvb" "wvx" "wmx" "wmv" "wm" "asx"
"mk3d" "mkv" "fxm" "flv" "axv" "webm" "viv" "yt" "s1q" "smo" "smov" "ssw"
"sswf" "s14" "s11" "smpg" "smk" "bk2" "bik" "nim" "pyv" "m4u" "mxu" "fvt" "dvb"
"uvvv" "uvv" "uvvs" "uvs" "uvvp" "uvp" "uvvu" "uvu" "uvvm" "uvm" "uvvh" "uvh"
"ogv" "m2v" "m1v" "m4v" "mpg4" "mp4" "mjp2" "mj2" "m4s" "3gpp2" "3g2" "3gpp"
"3gp" "avi" "mov" "movie" "mpe" "mpeg" "mpegv" "mpg" "mpv" "qt" "vbs"))
+(defconst dirvish-font-exts '("ttf" "ttc" "otf" "woff" "eot"))
(defconst dirvish-archive-exts '("7z" "xz" "bzip2" "gzip" "tar" "zip" "wim"
"ar" "arj" "cab" "chm" "dmg" "ext" "fat" "gpt" "hfs" "ihex" "iso" "mbr" "msi"
"ntfs" "qcow2" "rar" "rpm" "udf" "uefi" "vdi" "vhd" "vmdk" "xar"))
-(defconst dirvish-binary-exts (append dirvish-image-exts dirvish-video-exts
dirvish-audio-exts dirvish-archive-exts '("pdf" "epub" "gif" "icns")))
+(defconst dirvish-binary-exts (append dirvish-image-exts dirvish-video-exts
dirvish-audio-exts dirvish-font-exts dirvish-archive-exts '("pdf" "epub" "gif"
"icns")))
(defcustom dirvish-open-with-programs
(let ((mpv (or (executable-find "mpv") "mpv")))
`((,dirvish-audio-exts . (,mpv "--profile=builtin-pseudo-gui" "%f"))
@@ -587,6 +589,7 @@ FROM-QUIT is used to signify the calling command."
(mapc #'dirvish--kill-buffer (dv-special-buffers dv))
(setf (dv-preview-hash dv) (dirvish--ht) (dv-parent-hash dv) (dirvish--ht)
(dv-preview-buffers dv) nil (dv-winconf dv) nil)
+ (dirvish--check-dependencies dv) ; update configs
(when (or (null dirvish-reuse-session)
(eq dirvish-reuse-session (if from-quit 'open 'quit)))
(mapc (pcase-lambda (`(,_ . ,b)) (kill-buffer b)) (dv-roots dv)))))
diff --git a/docs/CUSTOMIZING.org b/docs/CUSTOMIZING.org
index 8fc6081577..d9940d3a90 100644
--- a/docs/CUSTOMIZING.org
+++ b/docs/CUSTOMIZING.org
@@ -222,34 +222,35 @@ no longer prompt you to install the associated programs.
+ [[https://github.com/dirkvdb/ffmpegthumbnailer][ffmpegthumbnailer]]
(Linux/macOS) | [[https://gitlab.com/movie_thumbnailer/mtn][mtn]] (Windows) for
video preview
+ [[https://github.com/MediaArea/MediaInfo][mediainfo]] for audio/video
metadata generation
+ [[https://www.7-zip.org][7-zip]] for archive files preview
++ [[https://imagemagick.org/index.php][imagemagick]] for font preview
@@html:<details>@@
@@html:<summary>@@ @@html:<b>@@Toggle install instructions@@html:</b>@@
@@html:</summary>@@
@@html:<h2>@@macOS@@html:</h2>@@
#+begin_src bash
-brew install poppler ffmpegthumbnailer mediainfo vips 7zip
+brew install poppler ffmpegthumbnailer mediainfo vips 7zip imagemagick
#+end_src
@@html:<h2>@@Debian-based@@html:</h2>@@
#+begin_src bash
-apt install poppler-utils ffmpegthumbnailer mediainfo libvips-tools
+apt install poppler-utils ffmpegthumbnailer mediainfo libvips-tools imagemagick
#+end_src
@@html:<h2>@@Arch-based@@html:</h2>@@
#+begin_src bash
-pacman -S poppler ffmpegthumbnailer mediainfo libvips 7zip
+pacman -S poppler ffmpegthumbnailer mediainfo libvips 7zip imagemagick
#+end_src
@@html:<h2>@@FreeBSD@@html:</h2>@@
#+begin_src bash
-pkg install poppler ffmpegthumbnailer vips 7-zip
+pkg install poppler ffmpegthumbnailer vips 7-zip ImageMagick7
#+end_src
@@html:<h2>@@Windows@@html:</h2>@@
#+begin_src bash
# install via Scoop: https://scoop.sh/
-scoop install poppler mtn mediainfo libvips 7zip
+scoop install poppler mtn mediainfo libvips 7zip imagemagick
#+end_src
@@html:</details>@@