杀死名称以特定字符串开头的缓冲区

时间:2011-02-23 21:44:36

标签: emacs lisp elisp

这是我的问题: 我使用Emacs并获得大量无用的缓冲区,如* Messages *或* Completions *。

我想绑定\ C-y来关闭所有以*开头的缓冲区,除了* shell *(和* shell *< k>)缓冲区。

要做到这一点,我想在我的.emacs文件中添加一些Emacs-Lisp:

(defun string-prefix s1 s2
  (if (> (string-length s1) (string-length s2)) nil
    (string=? s1 (substring s2 0 (string-length s1))) ))

(defun curry2
  (lambda (f)
    (lambda (x)
      (lambda (y)
    (f x y) ))))

(defun filter
  (lambda (f l)
    (if (null? l) '()
      (let ((rest (cdr l)))
    (if (f (car l)) (cons (car l) rest)
      rest) ))))


(defun kill-useless (arg)
  (interactive "p")
  (map 'kill-buffer
       (filter
    (not ((curry2 string-prefix) "*shell*"))
    (list-buffers)
    ) ))

(global-set-key "\C-y" 'kill-useless)

我已经使用Scheme测试了string-prefixcurry2,而filter似乎非常简单。 可悲的是,我无法让kill-useless正常工作。

它说filter: Invalid function: (curry2 string-prefix)

现在,问题是我对Emacs-Lisp感到厌烦,除了Scheme之外我没有真正使用任何Lisp,而在Scheme(MIT)中,这有效:

(filter ((curry2 string-prefix?) "*shell") '("*shell*" "*sh22" "eel"))
;Value 5: ("*shell*")

我想:

  1. 修复我的代码的方法
  2. 有关如何以不同方式执行此操作的建议
  3. 谢谢!

6 个答案:

答案 0 :(得分:28)

C-h f kill-matching-buffers RET

  

kill-matching-buffers是一个交互式编译的Lisp函数   `files.el”。

     

(kill-matching-buffers REGEXP& optional INTERNAL-TOO)

     

终止名称与指定REGEXP匹配的缓冲区。   可选的第二个参数表示是否也杀死内部缓冲区。

答案 1 :(得分:12)

另一种方法:

(require 'cl)

(defun is-useless-buffer (buffer)
  (let ((name (buffer-name buffer)))
    (and (= ?* (aref name 0))
         (not (string-match "^\\*shell\\*" name)))))

(defun kill-useless-buffers ()
  (interactive)
  (loop for buffer being the buffers
        do (and (is-useless-buffer buffer) (kill-buffer buffer))))

答案 2 :(得分:5)

请记住,elisp不是方案,甚至不是普通的lisp。语法和语义不同。例如,defun需要括号括起来的参数列表。此外,在elisp中实际上不可能进行currying。

幸运的是,elisp已经建成了你想要做的大部分事情。对于string-prefix,您可以使用string-prefix-p内置版。对于filter,您可以使用remove-if-notremove-if作为反转。

对于currying,您可以使用apply-partially内置函数。要获得匹配前缀为"*shell*"的字符串的函数,请尝试以下操作:

(apply-partially 'string-prefix-p "*shell*")

你可以像这样使用它:

(mapcar
 (apply-partially 'string-prefix-p "*shell*")
 '("*shell*" "foo" "*shell*<2>"))

; results in
(t nil t)

(require 'cl) ; for remove-if
(remove-if
 (apply-partially 'string-prefix-p "*shell*")
 '("*shell*" "foo" "*shell*<2>"))

; results in
("foo")

答案 3 :(得分:0)

最好在删除之前查看删除内容,以便安全地播放。

Icicles 中,默认情况下C-x k是一个多命令,可用于杀死与迷你缓冲区输入匹配的任意数量的缓冲区。在这种情况下,您可以键入* TAB以查看以*开头的所有缓冲区名称作为完成候选项。

然后,您可以通过多种方式缩小比赛范围。如果剩下的所有匹配项都是您想要的,请点击C-!删除所有这些缓冲区。

如果您提供,则不希望删除名为*shell...的缓冲区。因此,在* TAB之后,您会点击S-SPC,然后输入另一个匹配的模式:shell,然后S-TAB。这只会缩小到 想要杀死的*shell...个缓冲区。然后,您点击C-~减去这些匹配(补码)。这会留下除shell缓冲区之外的所有缓冲区。点击C-!,他们都被杀了。

您也可以通过在*Completions* C-mouse-2 {@ 1}}中按住Ctrl键点击其名称来杀死个人缓冲区。

更一般地说,在 Icicles 中,每个读取缓冲区名称的多命令都允许您使用S-delete(Shift + Delete键)来杀死缓冲区候选项

http://www.emacswiki.org/emacs/Icicles_-_Multi-Commands

http://www.emacswiki.org/emacs/Icicles_-_More_About_Multi-Commands

答案 4 :(得分:0)

我发现kill-matching-functions提示我未经修改的缓冲区,这不是我想要的。下面的函数将终止匹配前缀的缓冲区(如问题标题中所示)。不完全是你想要的,但也许像我这样来自谷歌的人会觉得这很有用。

(require 'cl)
(defun kill-buffers-with-prefix (prefix)
  "Kill buffers whose names start with the given prefix"
  (interactive "sPrefix to kill: ")
  (loop for buffer in (buffer-list)
        do (if (string-prefix-p prefix (buffer-name buffer))
               (kill-buffer buffer))))

答案 5 :(得分:0)

杀死所有其他缓冲区

(defun px-kill-other-buffers ()
  "Kill all other buffers."
  (interactive)
  (mapc 'kill-buffer (delq (current-buffer) (buffer-list))))

搜索字符串的开头

(defun string-starts-with-p (string prefix)
    "Return t if STRING starts with prefix."
    (and
     (string-match (rx-to-string `(: bos ,prefix) t) string)
     t))