Emacs: 封装 webjump 搜索 symbol-at-point
webjump 是 Emacs 里内置的一个包,你可以配置想要搜索的网站,然后通过 webjump 选择搜索。
例如这是我设置的网站:
(setq webjump-sites '(("Kagi" . [simple-query "kagi.com" "kagi.com/search?q=" ""]) ("Kagi Translate" . [simple-query "translate.kagi.com" "translate.kagi.com/?from=auto&to=zh_cn&text=" ""]) ("Wikipedia" . [simple-query "wikipedia.org" "wikipedia.org/wiki/" ""]) ("Kagi(site:github.com)" . [simple-query "kagi.com" "kagi.com/search?q=site:github.com+" ""]) ("Album" . [simple-query "kagi.com" "kagi.com/images?q=" "&size=large"]) ("MDN" . [simple-query "developer.mozilla.org" "developer.mozilla.org/en-US/search?q=" ""]) ("Haici" . [simple-query "dict.cn" "dict.cn/search?q=" ""])))
当我调用 webjump 时,它会让我从上面的选项里选一个,然后输入搜索关键字,之后就会跳转到对应的网站搜索。
可以将一些比较高频的搜索条件内置在搜索链接里。如果经常搜索 GitHub 上的内容,可以加上 site:github.com ,使得总是搜索 github.com 的内容;或者也可以直接用 GitHub 本身的搜索 https://github.com/search?q=%s 。
symbol-at-point 也是 Emacs 里内置的一个函数,可以获取当前指针下的内容。
结合两者,我写了一个函数,获取指针下的内容,然后调用 webjump 去搜索,这样在 Emacs 里碰到什么我想要查询的,就可以快速调用常用的网站进行搜索。例如写页面的时候快速去 MDN 查询一些 API 的使用。
代码
(use-package webjump :bind (("C-M-?" . spike-leung/webjump-symbol-at-point)) :config (setq webjump-sites '(("Kagi" . [simple-query "kagi.com" "kagi.com/search?q=" ""]) ("Kagi Translate" . [simple-query "translate.kagi.com" "translate.kagi.com/?from=auto&to=zh_cn&text=" ""]) ("Wikipedia" . [simple-query "wikipedia.org" "wikipedia.org/wiki/" ""]) ("Kagi(site:github.com)" . [simple-query "kagi.com" "kagi.com/search?q=site:github.com+" ""]) ("Album" . [simple-query "kagi.com" "kagi.com/images?q=" "&size=large"]) ("MDN" . [simple-query "developer.mozilla.org" "developer.mozilla.org/en-US/search?q=" ""]) ("Haici" . [simple-query "dict.cn" "dict.cn/search?q=" ""]))) (defun spike-leung/webjump-symbol-at-point () "获取光标下的 symbol 并通过 webjump 搜索。" (interactive) (let* ((completion-ignore-case t) (query (if (use-region-p) (buffer-substring-no-properties (region-beginning) (region-end)) (thing-at-point 'symbol t))) ;; (query (read-string (format "Webjump search (%s): " (or content "")) ;; nil nil content)) (item (assoc-string (completing-read "WebJump to site: " webjump-sites nil t) webjump-sites t)) (name (car item)) (expr (cdr item)) (query-prefix (aref expr 2)) (query-suffix (aref expr 3)) (fun (if webjump-use-internal-browser (apply-partially #'browse-url-with-browser-kind 'internal) #'browse-url))) (funcall fun (webjump-url-fix (cond ((concat query-prefix (webjump-url-encode query) query-suffix)) (t (error "WebJump URL expression for \"%s\" invalid" name))))))))
更新:
因为是针对 point 下的内容操作,所以很适合用 embark,可以不用记忆额外的快捷键,更容易想起来用。
embark 可以理解成 Emacs 里的右键菜单,在任何位置都可以调用 embark-act 唤起这个菜单,菜单中的内容是可以自己定制的,这样就可以快速进行一些操作。
最近还经常用 Kagi Assistant,所以把 Kagi Assistant 的链接也加入到了 webjump,这样我就可以随时从 Emacs 中获取上下文,然后去 Kagi Assistant 进行对话。
现在我的操作流程是:
- 在 Emacs 中,按下 C-.,这会调用
embark-act。 embark 会自动帮我选择 point 下的内容,可能是一个符号,可能是一个 region(选中的区域)。 - 按下 W,这个按键绑定了
spike-leung/webjump-symbol-at-point。 - 选择 「Kagi LLM」,输入 prompt,然后就会带着上下文和 prompt,跳转到 Kagi Assistant 开始对话
具体代码:
webjump 部分
(use-package webjump :after embark :defer nil :config (setq webjump-sites '(("Kagi" . [simple-query "kagi.com" "kagi.com/search?q=" ""]) ("Kagi Translate Text" . [simple-query "translate.kagi.com" "translate.kagi.com/?from=auto&to=zh_cn&text=" ""]) ("Kagi Translate Page" . [simple-query "translate.kagi.com" "translate.kagi.com/zh_cn/" "?kt_view=both_vertical?kt_view=both_vertical"]) ("Kagi LLM" . [simple-query "kagi.com" "kagi.com/assistant?q=" "&profile=kimi-k2.5-reasoning&internet=on"]) ("Kagi Summary" . [simple-query "kagi.com" "kagi.com/summarizer?url=" "&target_language=ZH&summary=takeaway"]) ("Wikipedia" . [simple-query "wikipedia.org" "wikipedia.org/wiki/" ""]) ("Kagi(site:github.com)" . [simple-query "kagi.com" "kagi.com/search?q=site:github.com+" ""]) ("Album" . [simple-query "kagi.com" "kagi.com/images?q=" "&size=large"]) ("MDN" . [simple-query "developer.mozilla.org" "developer.mozilla.org/en-US/search?q=" ""]) ("Haici" . [simple-query "dict.cn" "dict.cn/search?q=" ""]))) (defun spike-leung/webjump-symbol-at-point (target) "获取光标下的 symbol 并通过 webjump 搜索。TARGET 是 `embark-act' 的对象。" (let* ((completion-ignore-case t) ;; 从 WebJump 列表选项 (item (assoc-string (completing-read "WebJump to site: " webjump-sites nil t) webjump-sites t)) ;; 选项名称 (name (car item)) ;; 选项配置 (expr (cdr item)) ;; 选项的第 3 个参数,获取查询前缀 (query-prefix (aref expr 2)) ;; 选项的第 4 个参数,获取查询后缀 (query-suffix (aref expr 3)) (fun (if webjump-use-internal-browser (apply-partially #'browse-url-with-browser-kind 'internal) #'browse-url)) ;; 如果选择的是 LLM 相关的 URL,则需要输入 Prompt (prompt (and (string-match-p "LLM" name) (read-string "Prompt: " "解释" t))) ;; 如果存在 prompt 则拼接 prompt (query (or (and prompt (concat target "\n" prompt)) target))) (funcall fun (webjump-url-fix (cond ((concat query-prefix (webjump-url-encode query) query-suffix)) (t (error "WebJump URL expression for \"%s\" invalid" name))))))))
embark 部分
(use-package embark :bind (("C-." . embark-act) ("M-." . embark-dwim) ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings' :init ;; Optionally replace the key help with a completing-read interface (setq prefix-help-command #'embark-prefix-help-command) :config (keymap-set embark-general-map "W" #'spike-leung/webjump-symbol-at-point) (keymap-set embark-region-map "W" #'spike-leung/webjump-symbol-at-point))
webjump 和浏览器或者搜索引擎中的 Search Shortcuts 差不多, 可以保存常用的搜索条件便于快速搜索。
例如我经常需要从 Kagi 找专辑封面的图片,而且希望图片尺寸尽可能大。
我平常的操作是:
- 触发搜索栏
- 输入关键字搜索
- 切换到图片搜索
- 设置尺寸为 large 进行过滤
通过 Search Shortcuts,我设置了 https://kagi.com/images?q=%s&size=large ,并绑定 @a 。
我的操作就变成:
- 触发搜索栏
- 输入
@a快捷键触发 Search Shortcuts,输入关键字搜索,结束
可以了解一下搜索引擎的搜索操作符,例如这是 Kagi Search Operators:
site:可以搜索指定域名filetype:可以搜索指定的文件类型- …
然后将平时频繁使用的一些搜索条件保存到 Search Shortcuts,这样下次使用就会方便一些。