popweb,基于Web技术的弹窗框架

关于popweb

我写的sdcv应该是Emacs里面最早的弹窗翻译插件,一直想要一个Web版的弹窗翻译插件,需要满足如下要求:

  1. 用Web技术来绘制美观的界面
  2. 长期稳定使用,不需要破解翻译网站的API或者单独申请Key
  3. 支持例句显示和自动发声
  4. 支持光标处单词自动提取,支持选中状态
  5. 支持代理配置,国内有道直连,国外翻译服务走代理

苦于没有想好第二条需求的方案,迟迟没有开动,今天突然想到其实可以利用CSS来隐藏不要的广告,这样既可以保证界面干净,又不用破解每个翻译网站的API。

得益于Emacs Application Framework过去2年的研究,我直接提取了EAF浏览器相关的代码,很快就实现了Web版的弹窗翻译插件。

安装

  1. 从你的操作系统中安装PyQt5(注意不要用PIP安装PyQt5, PIP版的有bug会导致浏览器崩溃)
  2. 下载popweb仓库代码: https://github.com/manateelazycat/popweb
  3. 在你的配置文件 ~/.emacs 中添加以下配置
(add-to-list 'load-path "<path-to-popweb>") ; add popweb to your load-path
(require 'popweb-dict-bing)
(require 'popweb-dict-youdao)

使用

  • popweb-dict-bing-input: 用Bing来翻译输入单词
  • popweb-dict-youdao-input: 用有道来翻译输入单词
  • popweb-dict-bing-pointer: 用Bing来翻译光标处单词
  • popweb-dict-youdao-pointer: 用有道来翻译光标处单词

代理

代理设置,目前Bing和Youdao还用不上,主要是为国外的其他翻译服务做准备。

(setq popweb-proxy-type "http")
(setq popweb-proxy-host "127.0.0.1")
(setq popweb-proxy-port "1080")

如果你是socks5代理,可以像下面这样更换类型:

(setq popweb-proxy-type "socks5")

截图

Bing翻译

有道翻译

后续

其实popweb是一个通用框架,不光可以展示翻译内容,也可以加载任意Web页面,欢迎大家贡献新的想法和插件。

Enjoy!

23赞

666, 另外一个可能的实现方式就是基于 xwidget,不过要等到 emacs 29 之后了,29 之前的 xwidget 闪烁严重,几乎不可用, 这几天一个大牛对 xwidget 感兴趣,进行了重构,已经解决了闪烁问题,就我粗浅的感觉,重构可能采用了类似 EAF 的解决方式,就是粘窗口,因为分屏之后,滚动一边,另一边自动滚动。

同步更新了EAF,更新EAF后设置下面的代码:

(defun eaf-translate-text (text)
  (popweb-dict-youdao text))

在网页中取词翻译的感觉终于对了。

这不就是可以移动的eaf browser窗口嘛,@fuxialexander的https://github.com/fuxialexander/emacs-webkit-katex-render可以移植过来了。

相当于把EAF里面浏览器、EPC多进程通讯、跨平台的代码单独提取出来了,不用遵循EAF的架构设计,只是简单的弹出一个Web窗口,加载任意网页。

2赞

如果这样的话,fuxialexander的https://github.com/fuxialexander/emacs-webkit-katex-render就可以不用移植到eaf了。我前两天才在eaf上把它跑通。 :joy:这是个好消息!

我始终觉得 xwidget 的代码就不应该弄到Emacs里面去,要像EAF在外部维护,这样Emacs的核心更干净一点,因为Web相关的代码提交都会大大超过 elisp 本身的代码量。

这个要看xwidget的维护者的喜好了,也许重构后xwidget的c代码能做成动态模块也说不定。

我这有两个问题,一个是提示 lambda 的写法 Warning: (lambda nil ...) quoted with ’ rather than with #'

还有一个是窗口弹出的问题,会报类似这样的错误 aref: Args out of range: #<buffer scratch>, 65, 66

这个问题我也遇到了,经过一番尝试之后发现和光标的位置有关。就是因为emacs允许光标所在位置是没有字符的情况(比如emacs -Q的scratch buffer只有3行,但是光标可以显示在第四行),当光标在这个位置的时候就会报这个错,如果将光标移到有字符的位置,工作就正常(目前只是发现这个问题,也不知道怎么解决)不知道自己有没有说清楚 :joy:

晚上回家修一下,小问题

1赞

又试了一下,发现还需要当前buffer与文件是关联的,如果是一个在与文件不关联的buffer(如eshell,没有保存的buffer,magit等)中使用也会报错

两个问题都修复了。

1赞

已经支持根据Emacs的主题自动选择亮色还是暗色,避免强对比度伤害眼睛。

1赞

@manateelazycat 我在尝试在popweb框架上移植fuxialexander的公式预览功能。我读了一下popweb的代码,发现似乎暂时没有单独发送js代码到页面的API。能不能添加一下?

有啊,你把你要做的事情先告诉我,我得先理解

我要用katex.js渲染光标下面的公式。每次移动光标之后会检测光标处是否有公式,如果有就立刻调用katex.js的函数发送到网页去渲染。网页窗口跟随光标变换位置。

如果每次都打开一个新网页会比较耗时,体验不好,体现不出katex.js的实时渲染优势。另外,根据eaf上面的经验,每次都开一个新网页往往还会伴随闪烁。

或者你告诉我latex文本demo,怎么用katex.js渲染,我晚上看看能否✍一个插件出来,同时因为我知道怎么改popweb的架构,所以比这种盲猜要快很多

他要的是这个页面上的效果

@manateelazycat

我要的效果其实就是 fuxialexander/emacs-webkit-katex-render 实现的效果。可以看视频

emacs-webkit-katex-render里面关于渲染的代码都是可以用的。fuxialexander在渲染方面 已经做得很不错了。 可以直接使用的代码包括:

  • index.html
  • webkit-katex-render.el
    • Variables
      • webkit-katex-render–org-math-preprocess-function
      • webkit-katex-render–previous-math
    • Functions
      • webkit-katex-render–render
      • webkit-katex-render–tex-math-preprocess
      • webkit-katex-render–tex-math-at-point
      • webkit-katex-render–org-math-preprocess
      • webkit-katex-render–org-math-at-point
      • webkit-katex-render–math-at-point
      • webkit-katex-render-show
      • webkit-katex-render-update

webkit-katex-render–render负责实际渲染公式,渲染的时候直接调用index.html里面的js函数try_render(math)就可以了。webkit-katex-render–render需要重新实现。下面是我在eaf适配时实现的。

  (eaf-call-async "call_function_with_args" (katex-viewer--get-buffer-id) "katex_render" (url-hexify-string math)))

这里katex_rende是buffer.py里面的函数。

def katex_render(self, math):
    math_js = "try_render('{0}')".format(math)
    self.buffer_widget.eval_js(math_js)

webkit-katex-render-update是入口,用 post-command-hook 保证实时更新。

(add-hook 'post-command-hook #'webkit-katex-render-update nil t)

webkit-katex-render-update需要调整。下面是我在eaf上面适配的时候做过精简的代码。

(defun webkit-katex-render-update ()
  (let* ((math-at-point (webkit-katex-render--math-at-point))
         (pos (car math-at-point))
         (math (cdr math-at-point)))
    (if math
        (if (not (eq math webkit-katex-render--previous-math))
            (progn
              (webkit-katex-render-show math-at-point)
              (setq webkit-katex-render--previous-math math))))))

至于公式文本,倒没什么特别的。

\(x^2+y^2=z^\)
\[x^2+y^2=z^\]
$x^2+y^2$
\begin{equation}
x^2+y^2=z^2
\end{equation}

分别放在org文件和tex文件里面,只要光标在公式里面能够正确渲染就没问题了。