又一种在 Emacs 中浏览、移动图片链接的方案 : image-slicing

由于 Emacs 当中显示一张图片,占用的是文本的一行,通过增加行高展示内容,导致在浏览、移动图片时很不方便。

虽然 pixel-scroll , iscroll 能够一定程度上改善这种情况。但是始终无法像移动文本一样自然。

因此想到,把一张图水平分割为若干张切片,然后通过 overlays 渲染这一系列的切片,当切片的高度接近行高时,我们的移动就和文本的移动相似了。

最开始,我使用的是 ImageMagick 切实的把图片分割为多张真实的切片。后来在开发的过程中发现有一个和我想法一样的包: org-sliced-images. ,大家也可以尝试一下这个包。

了解到 ('display . (list (list 'slice x y dx dy) image)) 可以直接展示图片的某一部分,而不是全部,因此就不再需要 ImageMagick。

目前我这个包和 org-sliced-images 比较优点有:

  1. 异步的下载所有网络图片,所以不会卡住 Emacs
  2. 支持非 org mode, 例如,通过配置,可以在 EWW 中使用。

我使用了懒猫的旅行博客作为 EWW 测试(因为一篇博客有上百张照片),使用还是比较丝滑的。欢迎大家试试看

blog

17 个赞

哈哈哈哈, 沙发是我的, 给大佬点赞👍

这个好! !

猫哥在哪里,流量就在哪里。

你的旅游博客简直是 eww 压测神器。默认情况下,不隐藏图片,打开你的博客会把 Emacs 卡死。看来 eww 默认下载图片的实现有大坑呀。

快来帮忙测试。

可以用类似 blink-search 的技术, 把这些图片片段保持在外部进程的内存对象中, 需要的时候, 外部进程发送图片数据给Emacs就好了。

这样避免生成很多临时图片文件到文件系统, Emacs还要读取, 读写文件的开销还是很大的。

改动之前: 解析图片 → 写入文件系统 → 读取图片 → Emacs渲染

改动之后: 解析图片到内存 → 直接发给Emacs渲染

大佬擅长 Deno , 也可以用 deno-bridge 来改进下。 :wink:

我其实一直都想用 blink-search 的框架重新实现一下 eww, 所以解析的工作都在外部进程, 永远只传输当前屏幕的内容给Emacs做类似eww的渲染, 这样多大的网页都可以秒开秒滚动哇。

哎, 最近卖货让我荒废了技术, 期待大佬新作哇!

大佬, 如果用类似 blink-search 的架构重写, 不光是 eww, 我觉得你可以解决 org-mode 图片渲染的问题。

org-mode 如果也用类似 blink-search 的技术, 可以实现大型 org-mode 文件打开不卡, 同时可以在 org-mode 里面预览图片、公式和视频。

哈哈。目前这个包用 curl 在后台默默的下载图片性能已经基本够用了。遇到瓶颈了再看看。坑开大了填不上。 :rofl:

1 个赞

不要怕, 坑大了, 我在旁边站着呢, 我绝对不会拉一把, 哈哈哈哈。 :wink:

哈哈,我这人常常会觉得某个想法很不错。然后搞个demo,然后就放在一边不动了。还是要少开坑。把旧坑填好,多用起来。然后四处吹嘘一波。:dog::dog::dog:

之前 org-sliced-images 会插入换行符号用来展示切片,所以每次展示图片就触发自动保存,用着不爽,我还 fork 了一个用来着 :joy:

去年我刚开始有这个想法时,我的实现更粗暴,直接插入一些字符用来占位。感觉太污染 buffer,自己用还行,没好意思分享出来,怕影响了别人的文件。

后来想到了可以把这些占位符去掉,才又改进了一下。

我是把 link 本身拆了,如果 link 本身长度不够的话,就让它大于一行的高度,反正我是自己用,能接受

我也是这么想的。 :handshake: 并且我觉得图片占用 2 倍行高挺好。只需要移动的感觉和操作文本一致就行。有时候一张图太长了。一行一行的移动还有点慢。

已测。非常丝滑。 大佬,

  1. 上下移动时这每行的红框框能去掉不?
  2. 如果设置了 '(line-spacing 4),则图片被切割了。不设置的话,行间距太紧了。咋破?

红框是 cursor。 把 cursor-type 设置为 nil ,它就消失了。但会影响文本的 cursor。

建议与红框共存。如果实在受不了:

可以写一个 post-command-hook, 检测当前位置是否有overlay,如果 overlay 在 image-slicing–overlay-list 里,则 cursor-type 设置为 nil,否则,设置为正常 cursor。

PS. 如果有用 meow-mode 设置 cursor-type 也无效,应该是它优先霸占了 cursor-type

这个好像没有办法解决。line-spacing 是个 buffer 级别的,它的功能就是在行间加空白。

唯一解法:换一个不需要调整行间距就看起来舒适的字体。(手动狗头🐶)

如果可以接受一整行高度的空白,其实可以利用开头的和结尾的 overlay 再加一个换行符

(overlay-put ov 'before-string "\n")
(overlay-put ov 'after-string "\n")
;; 可以同时设置display,不冲突
;; (overlay-put ov 'display "qwe")

感谢大佬,很流畅很好用

报个 bug:图片链接如果不是在一行最左边的话会错位,预期的情况后面应该跟随第一行缩进