如何实现MediaWiki 的弹出提示和页面预览功能

语文老师?!

其实不是很难,大概也就是几个函数的事情

一个大概思路是复用 org 的脚注,给 [fn:\d+] 加上 help-echohelp-echo 的内容为找到对应脚注位置,然后就可以实现移到脚注就显示了

又或者你喜欢用 org-roam,也可以给 org-mode [[id:*][*]] 的链接加上 help-echo,内容为对应标题或者描述

个人没需求懒得折腾 想了想第二个有空时会考虑给 org-roam 加上,先随手搜了两个链接供参考

3 个赞

诗词字数短,一页内能看到注释,如果是长篇大论的正文,注释在后面,学习起来,你就不停的翻来翻去,前后乱翻。

并且注释的小字,字号虽然少,但也影响排版,不如用[[ ]] 等特殊符号包起来,字体颜色稍微有一点点变化。这样效果就很好了。

谢谢指点,看视频是我需要的效果,好像之前大佬还发了一个视频,还没看完就删除了,那个也很像。

脚注有一个缺点是还要显示[1],我还设想用文内链接[[ ]] , 将注释写到一个标题的正文中,也是一种办法。

敢问org-roam是大佬写的吗?太厉害了,我之前还以为是外国人写的呢

没有,你理解错了😂,不是我写的,我的意思给我的配置加上,或者提个 PR。但是想想本身链接就有文字了,我需要描述的需求是否还大,我还在思考。

视频也是这个作者的,类似的东西,感觉换成博客更清楚点

1 个赞

文章的注解和注释,挺常用的,尤其是古书。兹举两例:

1 个赞

反正我短期不是特别,你可以先试着研究下能不能实现你的需求

从 sacha 那发现了一个包:org-super-links-peek,可能是lz需要的

3 个赞

写了个简单的 demo 显示 id 指向 roam node 的 title


  (defun org-roam-tip (window object position)
    (save-excursion
      (goto-char position)
      (let* ((link (org-element-context))
             (id (org-element-property :path link))
             (node (org-roam-node-from-id id)))
        (org-roam-node-title node))))

  (org-link-set-parameters "id" :help-echo 'org-roam-tip)

不过需要鼠标移动过去才显示,如果想要光标移动到链接🔗上面才显示的可能需要结合 eldoc Re: bug#42484: org-mode should display value of links in mini-buffer - Samuel Wales

2 个赞

org roam 有个函数可以返回 node 下的内容字符串,然后将这个字符串用 posframe 显示出来,就像 youdao-dictionary 这个包中处理翻译结果一样。

是不是效果会更好?

自己小小尝试了一下,可以实现两种链接的预览功能。

  1. org-roam ID 类型链接。
  2. 同一 org 文件内 footnote。

代码中使用到了 org-transclusion-content-org-marker 这个函数获取相关页面的 content,所以必须先安装 org-transclusion 包。

代码如下:

(defun org-roam-tip ()
  (interactive)
  (save-excursion
    (let* ((plist)
           (link (org-element-context))
           (id (org-element-property :path link))
           (label (org-element-property :label link))
           (mkr (ignore-errors (org-id-find id t)))
           (content (plist-get (org-transclusion-content-org-marker mkr plist) :src-content))
           (footnote (ignore-errors (buffer-substring-no-properties
                                     (nth 1 (org-footnote-get-definition label))
                                     (nth 2 (org-footnote-get-definition label))))))
      (-posframe-tip (or content footnote))
      )))

(defun -posframe-tip (string)
  "Show STRING using posframe-show."
  (unless (and (require 'posframe nil t) (posframe-workable-p))
    (error "Posframe not workable"))

    (if string
        (progn
          (with-current-buffer (get-buffer-create "Org Roam Tip")
            (let ((inhibit-read-only t))
              (erase-buffer)
              (insert string)
              (goto-char (point-min))))
          (posframe-show "Org Roam Tip"
                         :left-fringe 8
                         :right-fringe 8
                         :internal-border-color (face-foreground 'default)
                         :internal-border-width 1)
          (unwind-protect
              (push (read-event) unread-command-events)
            (progn
              (posframe-delete "Org Roam Tip")
              (other-frame 0))))
      (message "Nothing to look up")))

-posframe-tip 函数是从 youdao-dictionary 抄来的,ღ( ´・ᴗ・` )比心。

移动光标到需要预览的 ID 链接或者 footnote label 上,M-x 调用 org-roam-tip 函数,不过将该函数绑定到 F1-F9 快捷键会更方便。就能看到效果。

效果如下:

  1. org-roam ID 类型链接预览。

  2. 同一 org 文件内 footnote 预览。

不足:

  1. ID 类型链接中的 content 如果有图片,是无法显示的。
  2. ID 类型链接中的 content 如果过多,超出 posframe 范围的显示部分是无法显示的,并且没有办法滚动查看。

不知道如何解决?

6 个赞

org-roam-ui 的侧边栏预览做的挺不错的,可以渲染预览整个文件,渲染速度很快,还可以上下滑动内容。可以参考参考。

弹出页面还可以用懒猫的 popweb

2 个赞

我也有看古文的需求,是采用的导出的方式。

我参照了 懒猫大神 popweb,基于Web技术的弹窗框架 extension 中插件的写法,完成了 使用 popweb 弹出预览 Org-Roam ID link 和 footnote link 的功能。 仓库地址如下:GitHub - czqhurricnae/popweb: Show popup web window for Emacs ,因为还不知道有没有致命的 bug,所以没有提交 pull request。

配置

配置,我用的是 Spacemacs,还需要另外安装 org-transclusion 这个包:

(defconst hurricane-org-packages
  `(
    (org-transclusion :location (recipe
                                 :fetcher github
                                 :repo "nobiot/org-transclusion"))
    (popweb :location (recipe
                       :fetcher github
                       :repo "czqhurricnae/popweb"
                       :files ("*.*" "extension")))
    )
  )

(defun hurricane-org/init-org-transclusion ()
  (use-package org-transclusion
    :config
    (setq org-transclusion-include-first-section t)
    (setq org-transclusion-exclude-elements '(property-drawer keyword))))

;; /usr/bin/env python3 -m pip install PyQt5 PyQtWebEngine epc
(defun hurricane-org/init-popweb ()
  (use-package popweb
    :ensure t
    :load-path ("elpa/27.2/develop/popweb-20220125.2025" "elpa/27.2/develop/popweb-20220125.2025/extension/latex" "elpa/27.2/develop/popweb-20220125.2025/extension/dict" "elpa/27.2/develop/popweb-20220125.2025/extension/org-roam")
    :init
    (add-hook 'latex-mode-hook #'popweb-latex-mode)
    :config
    (require 'popweb-latex)
    (require 'popweb-dict-youdao)
    (require 'popweb-dict-bing)
    (require 'popweb-org-roam-link)))

安装依赖,在终端运行命令,我用的是 Mac:

/usr/bin/env python3 -m pip install PyQt5 PyQtWebEngine epc

或者参考 懒猫大神 的文档进行配置。 预览调用的命令是:popweb-org-roam-link-show

效果

效果如下:

  1. 弹出预览 Org-Roam ID link,只支持 ID 类型,不支持 file 类型。 2022-01-25 20.36.04

  2. 弹出预览 footnote link。 2022-01-25 20.57.43

不足

  1. 没有办法光标移动到支持的链接上时自动弹出预览。
  2. 预览内容中的图片如果过大不好查看,不知道如何调节预览窗口大小?(在 popweb 的代码中没有找到可以配置的地方)或者使用 org-export-string-as 时对导出图片大小进行调整?自己没有仔细研究,希望有人可以提下意见。
3 个赞

试了下有报错,你瞅瞅啥原因。目前是用的最新的emacs-29

Debugger entered--Lisp error: (wrong-type-argument arrayp nil)
  file-truename(nil)
  (format "file:%s" (file-truename (plist-get (cdr (car org-publish-project-alist)) :base-directory)))
  (let* ((popweb-org-roam-link-index-path (format "file:%s" (file-truename (plist-get (cdr (car org-publish-project-alist)) :base-directory)))) (position (popweb-get-cursor-coordinate)) (x (car position)) (y (cdr position)) (x-offset (popweb-get-cursor-x-offset)) (y-offset (popweb-get-cursor-y-offset)) (frame-x (car (frame-position))) (frame-y (cdr (frame-position))) (frame-w (frame-outer-width)) (frame-h (frame-outer-height)) (show-window (nth 0 info)) (html-string (nth 1 info)) (new-html (not (string= html-string org-roam-link-preview--previous-html)))) (popweb-call-async "call_module_method" popweb-org-roam-link-module-path "pop_org_roam_link_window" (list "org_roam" popweb-org-roam-link-index-path x y x-offset y-offset frame-x frame-y frame-w frame-h show-window new-html html-string)) (popweb-org-roam-link-preview-window-can-hide))
  popweb-org-roam-link-preview((t "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE h..."))
  popweb-start(popweb-org-roam-link-preview (t "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE h..."))
  (progn (popweb-start 'popweb-org-roam-link-preview (list t html-string)) (setq org-roam-link-preview--previous-html html-string))
  (if (not (eq html-string org-roam-link-preview--previous-html)) (progn (popweb-start 'popweb-org-roam-link-preview (list t html-string)) (setq org-roam-link-preview--previous-html html-string)))
  (if html-string (if (not (eq html-string org-roam-link-preview--previous-html)) (progn (popweb-start 'popweb-org-roam-link-preview (list t html-string)) (setq org-roam-link-preview--previous-html html-string))) (popweb-start 'popweb-org-roam-link-preview (list nil "Hello world")))
  (let* ((html-string (get-html-from-link))) (if html-string (if (not (eq html-string org-roam-link-preview--previous-html)) (progn (popweb-start 'popweb-org-roam-link-preview (list t html-string)) (setq org-roam-link-preview--previous-html html-string))) (popweb-start 'popweb-org-roam-link-preview (list nil "Hello world"))))
  popweb-org-roam-link-show()
  funcall-interactively(popweb-org-roam-link-show)
  call-interactively(popweb-org-roam-link-show record nil)
  command-execute(popweb-org-roam-link-show record)
  counsel-M-x-action("popweb-org-roam-link-show")
  ivy-call()

1 个赞

(setq popweb-org-roam-link-index-path (concat "file:" (file-truename default-directory)))

配置中先添加这个试下。因为你的 org-publish 包没有配置 base-directory 变量,无法读取到这个默认值。

popweb-org-roam-link.el 第56行改成下面就可以用了

(popweb-org-roam-link-index-path (concat "file:" (file-truename default-directory)))

但是位置不太对,弹出的窗口在emacs 窗口最左上角,而不是在当前位置。

感觉都可以参考popweb-latexpopweb-latex是可以自适应的创建不同大小窗口的,也能根据当前位置自动弹出预览窗口

1 个赞

修改了部分代码,可以通过配置 org-roam-link-popup-window-width-scaleorg-roam-link-popup-window-height-scale 改变预览窗口的大小。 弹出窗口的位置应该也有改进,拉取试试看。

popweb-latex 窗口自适应大小的方法好像不适用于这种情况。不知道我代码阅读理解的对不对,毕竟我不是专业程序员。

1 个赞

现在能正常使用啦,固定窗口大小挺好的。

图片大小可以通过设置 #+attr_html: :width xxx

但是设置 #+attr_org: :width xxxpopweb-org-roam-link-show 没有作用,不知道有没有什么解决方法

增加了新功能,通过调用 popweb-org-roam-link-preview-select 命令可以对整个文件中的 ID link 和 footnote 搜索并使用 ivy 来选择预览哪个,这样就不必费力的移动光标到自己需要预览的链接上再调用 popweb-org-roam-link-show 了。

简单的视频演示地址:https://www.bilibili.com/video/BV1Cu41117ab/

不足:popweb-org-roam-link-preview-select 命令会让 Emacs 失去 focus 而手动调用 popweb-org-roam-link-show 命令却不会,不知道如何解决?

是不是和 ivy-read,ivy-call 有关?