多个“交互式”选项

时间:2012-12-03 13:13:37

标签: emacs elisp

我编写了一个小函数,使用逗号作为项目分隔符来反转标记区域中的项目。功能代码是:

(defun reverse-list (beg end)
  "Reverses a list in-place, where comma ',' is the list item separator."
  (interactive "r")
  (if (region-active-p)
    (let ((region-list (reverse (split-string (region-as-string) ","))))
      (kill-region beg end)
      (loop for s in region-list do (progn
                                      (insert (chomp s))
                                      (insert ", ")))
      (delete-char -2))
    (message "Error: No region selected!")))  

其中chomp从字符串中删除前导/尾随空格,region-as-string将该区域作为字符串。

该功能非常有用,但是能够动态选择分隔符会很棒。我正在寻找的行为是:

  • 如果在没有通用参数的情况下调用,则使用逗号作为项目分隔符
  • 如果使用通用参数(C-u)调用,则要求用户输入(可能是多字符)分隔符字符串

我试图实现这一目标,但没有成功。如果你能提供帮助会很棒!

提前致谢,
elemakil

2 个答案:

答案 0 :(得分:7)

您可以使用interactive code P阅读"raw" prefix argument。如果没有前缀参数,则为nil,如果有前缀参数,则为nil,因此您可以对此进行测试,并决定是将分隔符设置为","还是使用read-string提示用户输入。

另外,我会对您的代码发表以下评论:

  1. 只有交互式调用您的函数才有效,因此begend实际上是区域的开头和结尾。如果以非交互方式调用,这些可能不匹配(或者甚至可能没有区域),在这种情况下,您的函数将出错(因为它会删除begend之间的缓冲区,但会插入逆转该地区)。因此,您需要致电(buffer-substring beg end),而不是(region-as-string)

  2. [已编辑,请参阅注释]在区域处于非活动状态时引发错误并不是一个好主意。在Emacs中,即使处于非活动状态(即不再突出显示),该区域仍然存在。或者用户可能已关闭transient-mark-mode,因此根本没有活动区域。在这两种情况下,用户可能仍希望运行您的命令。

    最多可以在区域处于活动状态时更改命令的行为(例如,参见comment-dwim)。

  3. 您可以通过调用kill-region来删除该区域,delete-region会将删除的文本复制到kill-ring。这真的是你想要做的吗?它可能会让用户感到惊讶。除非您实际上是要保存已删除的文本,否则最好拨打insert

  4. 在开始调用save-excursion之前,您无法确保该点位于正确的位置。在交互式使用中,你可以使用它,但对于非交互式使用点可以在任何地方,所以你应该明确地移动它。当然也可以使用", "

  5. 插入额外的(defun reverse-list (beg end read-separator) "Reverse the region in-place, treating it as a list of items separated by commas. With a prefix argument, prompt for the separator." (interactive "r\nP") (save-excursion (let* ((separator (if read-separator (read-string "Separator: ") ",")) (region-list (nreverse (split-string (buffer-substring beg end) separator))) (separator (concat separator " "))) (goto-char beg) (delete-region beg end) (loop for s in region-list for sep = "" then separator do (insert sep) (insert (chomp s)))))) 然后必须删除它似乎非常不优雅。最好不要首先插入它。

  6. 以下是修正以上所有内容的修订代码:

    {{1}}

答案 1 :(得分:-1)

r -- Region: point and mark as 2 numeric args, smallest first.  Does no I/O.

因为r始终是前两个参数。如果使用 C-u 传递参数。然后,您可能需要将参数作为分隔符传递给第三个参数。但是如果没有第一个和第二个参数,你就无法传递第三个参数。 (我不确定。我也是初学者)

我的目的是使用rs选项来实现它。虽然您总是需要提供分隔符参数。

示例:

(defun reverse-list (beg end &optional sepeartor )
  (interactive "r
ssepeartor:")
  (princ beg)
  (princ "*")
  (princ end)
  (princ sepeartor))