[分享] selected.el

当选中一个区别之后,可以绑定一些键进行选区的操作。我的配置如下:

(use-package selected
  :load-path "packages/selected.el/"
  :hook (post-select-region . selected-minor-mode)
  :bind (:map selected-keymap
              ("q" . selected-off)
              ("u" . upcase-region)
              ("d" . downcase-region)
              ("c" . kill-ring-save)
              ("x" . kill-region)
              ("w" . count-words-region)
              ("s" . my/search)
              ("t" . my/gts-do-translate)
              ("m" . apply-macro-to-region-lines)
              ("\\" . indent-region)
              (";" . comment-dwim)))

my/search 的内容如下:

  (setq my/browser-engines
        '((DoubanMovie . "https://search.douban.com/movie/subject_search?search_text=")
          (DoubanBook . "https://search.douban.com/book/subject_search?search_text=")
          (Zhihu . "https://www.zhihu.com/search?type=content&q=")
          (Google . "https://www.google.com/search?q=")
          (Scholar . "https://scholar.google.com/scholar?hl=zh-CN&as_sdt=0%2C33&q=")
          (Github . "github.com/search?q=")
          (Youtube . "http://www.youtube.com/results?aq=f&oq=&search_query=")))

  ;;;###autoload
  (defun my/search ()
    "Search using the specified engine for the text in the currently selected region or user input."
    (interactive)
    (let* ((selected-engine (completing-read "Choose a search engine: " (mapcar 'car my/browser-engines) nil t))
           (selected-url (cdr (assoc (intern selected-engine) my/browser-engines))))
      (let* ((region (if (region-active-p)
                         (buffer-substring-no-properties (region-beginning) (region-end))
                       (read-string "Enter search terms: ")))
             (encoded-region (url-encode-url region))
             (search-url (concat selected-url encoded-region)))
        (browse-url search-url)))
    (when (region-active-p)
      (deactivate-mark)))

流程示例:比如 Telega 关注了一些影视频道,有时候看到电影名想知道这个电影怎样,就选中电影名然后按“s”,调用 DoubanMovie 查看下评分和影评。原先的操作需要选中区域、复制区域,使用 webjump 选用 doubanmovie 再粘贴复制的内容进行搜索,略显复杂。

4 个赞

这个有按键提示语吗?我用的是hydra,绑定的键太多,根本记不住每个键是做什么的(也没必要记),虽然按了很多回了,但每次按的时候还是会习惯扫一下提示语,确定下没按错

这个需求直接用hydra+绑定快捷键或者自动触发就可以实现了,不需要minor mode

1 个赞

hydra需要绑定一个leader-key来触发吧,我理解的selected.el的区别在于没有leader-key,选中文本后即可以直接通过按键触发绑定的函数,更适用于那些基于当前选中文本的操作。

有什么包能提供方便地文本选择功能?

不太清楚你说的“文本选择”具体指什么,如果是选中一个region,我一般用 expand-region

和selected一样的原理,用hook就可以自动触发

我发现了,所有一切与搜索相关的操作, 如: m-x fd rg swiper iserach buffer切换等…,跳转谷歌,维基等第三方搜索等,全部都可以把用户二次输入文字在回车确定这一步省略,都可以加一个判断 if mark-active, 如果当前有选中文字就自动执行下一步, 没有就等待用户输入。

所以 "当文字选中后自动触发某些操作", 这个需求存在的问题是: 与搜索相同的命令实在太多了,没法在一个函数里把这些操作全部都列出来。

这里又发现一个问题,我自己写的自用的搜索命令我把 if mark-active这个判断加上了,有选中文字就自动执行下一步, 但emacs里我好像还从来没有见过有与搜索相关的命令会默认加上 if mark-active 这个判断,以至于这个功能需要单独出一个包。是大家都忽略了这个问题吗?

这个判断感觉还是很有用的, 可以少打很多字。

(defvar nasy/active-region--on nil)

(defun nasy/on--active-region ()
  (nasy/active-region--mode 1))

(defun nasy/off--active-region ()
  (nasy/active-region--mode -1))

(defvar nasy/active-region-map (make-sparse-keymap))


;;;###autoload
(define-minor-mode nasy/active-region--mode
  "Actized region or not."
  :keymap nasy/active-region-map)


;;;###autoload
(define-minor-mode nasy/active-region-mode
  "Actived region or not."
  :lighter "n/ar"
  (if nasy/active-region-mode
      (progn
        (nasy/off--active-region)
        (add-hook 'activate-mark-hook   #'nasy/on--active-region)
        (add-hook 'deactivate-mark-hook #'nasy/off--active-region))
    (remove-hook 'activate-mark-hook   #'nasy/on--active-region)
    (remove-hook 'deactivate-mark-hook #'nasy/off--active-region)
    (nasy/off--active-region)))

我有一个忘了从哪儿抄来的x

后来开始用embark后,这个minor mode就再也没开过了x

找了一圈,发现与这个功能最接近的是搜索相关的命令是 c-h f,c-h v, 会自动获取光标处的词自动输入, 但是光标处的词必须是一个完整的elisp函数名|变量名时才可用, 名字只要缺了一个字符, 就还要在minibuffer把名字完整的再输入一次,很不友好。

我尝试其它软件,浏览器、notepad+、windows记事本,发现按快捷键打开搜索时都会自动检查有没有文本被选中,有的话就自动键入执行搜索. 可见这应该是很多软件对于搜索这个功能的默认设计。

有啊,rg.el 中的rg-dwim就可以自动搜索当前选择中的文字,如果没有选中就搜索当前光标下的符号。

感谢指正,我也觉得应该有才对,一个都找不出来这个太奇怪了点

可以试试这个,在 minibuffer 中预填充当前选择中的文字或当前光标下的符号,需要输入时自动清除预填充文本。

isearch-forward-thing-at-point

consult-line-thing-at-point

swiper-thing-at-point

这三个自动获取获取光标下的值,如果设成搜索绑定快捷键的默认值并不好用,比如说我当前打这段文字时打开搜索会把整个句子都自动填充进去,显然不符合使用习惯(英文用户可能没这感觉)。

建议这两个不要放在一起,区别开, 看起来行为差不多以为都一样,但实际情况不是这样的,取当前光标下的词不适合作为搜索的默认设置,特别是中文情况不知道会取到什么,而当前选择的文字自动填充这个作为搜索默认设置是没问题的,已经有很多软件这样设计。输入时自动清空预填充文本这个操作应该是不需要的