【问题标题】:How do I get the region (selection) programmatically in Emacs Lisp?如何在 Emacs Lisp 中以编程方式获取区域(选择)?
【发布时间】:2012-05-22 13:54:29
【问题描述】:

我需要访问 Emacs 缓冲区中的选择。 我找到了这篇文章How do I access the contents of the current region in Emacs Lisp? 对我帮助很大。

但是有一个问题。第一次选择(突出显示)一个区域时,它可以正常工作,但是当我按 Cg 并将光标正常移动到另一个位置而不突出显示任何字符时,我得到了一个从最后一个标记到当前点的字符串,而我期望一个空的.

实际上我需要实现一个函数,它将当前选择(突出显示)作为字符串返回,如果没有突出显示,则返回空字符串。下面的代码可能会更清楚地表达我。


(defun get-search-term ()
  (interactive)
  (let (
        (selection (buffer-substring-no-properties (region-beginning) (region-end))))
    (if (= (length selection) 0)
        (message "empty string")
      (message selection))))

有什么建议吗?非常感谢!

【问题讨论】:

  • 您没有使用 Gareth Rees 在您链接到的问题中显示的 interactive 表单的任何原因?
  • 感谢您的回复,也很抱歉没有仔细阅读该文章。 (交互式“r”)解决了我的问题。我需要阅读有关交互式的更多信息。
  • 似乎还没有。我修改了我的代码并测试了 Gareth Rees 的,问题仍然存在。也许我需要在获取区域之前清除点和标记?
  • 顺便说一句,很抱歉我的第一条评论,也许我没有足够的测试。

标签: emacs elisp


【解决方案1】:

“r”的交互规范是愚蠢的。你明白为什么了。

(defun get-search-term (beg end)
  "message region or \"empty string\" if none highlighted"
  (interactive (if (use-region-p)
                   (list (region-beginning) (region-end))
                 (list (point-min) (point-min))))
  (let ((selection (buffer-substring-no-properties beg end)))
    (if (= (length selection) 0)
        (message "empty string")
      (message selection))))

我的意思不是愚蠢和无用的“愚蠢”;只是它不在乎 关于标记是否有效。我认为它早于 瞬态标记模式。

编辑:上面两次使用(point-min)会使代码更难理解 重读时。这是一个更好的实现:

(defun get-search-term (beg end)
  "message region or \"empty string\" if none highlighted"
  (interactive (if (use-region-p)
                   (list (region-beginning) (region-end))
                 (list nil nil)))
  (message "%s" (if (and beg end)
                    (buffer-substring-no-properties beg end)
                  "empty string")))

【讨论】:

  • @ramen 我刚刚纠正了它。然后我重新阅读了这个问题,并且 point-min 是正确的,因为它会生成一个空字符串。
  • 现在我添加了一个更易于理解的实现。
  • 为什么不在if 调用的if 条件中只使用use-region-p?使用use-region-pbegend 设置为nil 以便稍后检查它们是否是nil 似乎是多余的。
  • @ceving:这是因为您不希望非交互式调用依赖于交互式上下文。适用于此的更一般规则是:不要两次执行相同的测试:如果您绝对 100% 完全确定两次测试将始终返回完全相同的值,无论情况如何,那么通常更可取提升测试并避免执行两次,如果您不确定,那么您需要开始考虑当它们不返回相同的值时该怎么办。例如。如果beg/end 为nil 但use-region-p 返回非nil,你会怎么做?
【解决方案2】:

检查变量标记激活例如。 C-h v 标记激活

==> mark-active 是在“C 源代码”中定义的变量。 它的值为 nil 本地缓冲区 Apropos;全局值为 nil

以任何方式设置时自动变为缓冲区本地。

文档: 非零表示标记和区域当前在此缓冲区中处于活动状态。

(defun get-search-term ()
  (interactive)
  (if mark-active
      (let (
        (selection (buffer-substring-no-properties (region-beginning) (region-end))))
    (if (= (length selection) 0)
        (message "empty string")
      (message selection))
    )
    (error "mark not active"))
  )

【讨论】:

  • mark-active 仅在您使用瞬态标记模式时才有效,因此您自己使用没问题,但如果代码应该可供他人使用,您应该使用region-active-p(或@ 987654324@) 代替。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-26
  • 2012-10-16
  • 1970-01-01
  • 2016-01-20
  • 1970-01-01
相关资源
最近更新 更多