Emacs 终止名称以特定字符串开头的缓冲区

Emacs 终止名称以特定字符串开头的缓冲区,emacs,lisp,elisp,Emacs,Lisp,Elisp,我的问题是: 我使用Emacs,得到很多一直都很无用的缓冲区,比如*消息*或*完成* 我想绑定\C-y以关闭所有以*开头的缓冲区,但*shell*(和*shell*)缓冲区除外 为此,我想在.Emacs文件中添加一些Emacs Lisp: (defun string-prefix s1 s2 (if (> (string-length s1) (string-length s2)) nil (string=? s1 (substring s2 0 (string-length

我的问题是: 我使用Emacs,得到很多一直都很无用的缓冲区,比如*消息*或*完成*

我想绑定\C-y以关闭所有以*开头的缓冲区,但*shell*(和*shell*)缓冲区除外

为此,我想在.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测试了
字符串前缀
curry2
,并且
过滤器
看起来非常简单。 可悲的是,我无法让
杀死无用的
正常工作

它显示
过滤器:无效函数:(curry2字符串前缀)

现在,问题是我在Emacs Lisp方面有点差劲,除了Scheme,我实际上不使用任何Lisp,在Scheme(麻省理工学院)中,这是有效的:

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

  • 修复我的代码的方法
  • 关于如何以不同方式执行此操作的建议

  • 谢谢

    请记住,elisp不是scheme,甚至不是常见的lisp。语法和语义是不同的。例如,
    defun
    需要一个用括号括起来的参数列表。此外,在elisp中,咖喱也不太可能

    幸运的是,elisp为您想做的大部分事情提供了内置功能。对于
    string-prefix
    ,可以使用
    string-prefix-p
    builtin。对于
    filter
    ,您可以使用
    remove if not
    ,或
    remove if
    进行反向操作

    对于currying,您可以使用
    部分应用
    内置功能。要获取与前缀为“
    ”*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")
    
    您可以这样使用它:

    (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")
    
    (地图车)
    (部分应用“字符串前缀-p”*shell*”)
    (“*shell*”foo“*shell*”)
    ; 导致
    (t零t)
    (要求“cl”);用于删除如果
    (如有必要,请删除。)
    (部分应用“字符串前缀-p”*shell*”)
    (“*shell*”foo“*shell*”)
    ; 导致
    (“富”)
    
    C-h f
    kill匹配缓冲区
    RET

    kill matching buffers是中的一个交互式编译Lisp函数 `文件.el'

    (kill匹配缓冲区REGEXP&可选内部-TOO)

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

    另一种方法:

    (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))))
    

    为了安全起见,最好在删除之前查看要删除的内容

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

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

    在您介绍的示例中,您不希望删除名为
    *shell…
    的缓冲区。因此,在
    *TAB
    之后,您将点击
    S-SPC
    ,然后输入另一个模式进行匹配:
    shell
    ,然后点击
    S-TAB
    。这仅限于您不想杀死的
    *shell…
    缓冲区。然后点击
    C-~
    减去这些匹配项(补码)。这将留下除shell缓冲区之外的所有缓冲区。点击
    C-
    您还可以通过在
    *Completions*
    中控制单击各个缓冲区的名称来杀死它们:
    C-mouse-2

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


    我发现
    终止匹配函数
    提示我输入未修改的缓冲区,这不是我想要的。下面的函数将杀死匹配前缀的缓冲区(如问题的标题所示)。这不完全是你想要的,但也许像我这样从谷歌来到这里的人会发现这很有用

    (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))))
    

    要杀死所有其他缓冲区

    (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))
    

    *消息*
    缓冲区非常有用:每次Emacs告诉你一些事情时,它都会让它出现在那里,因此你可以复制并粘贴到google上,在google上找到解决方案。还要注意的是,当你可能会使用一些模式(比如magit)时,谁会以一种有用的方式使用这种缓冲区。是的,我最终也保留了那个缓冲区。谢谢你的提示!我最喜欢这种方法。我还添加了一个检查,以保留*Messages*缓冲区。恭喜肖恩!你赢了:)另外,
    (require'cl)
    到底做了什么?它引入了Emacs的公共Lisp包,这就是(非常方便的)“loop”宏所在的地方。整个软件包非常有用;.emacs文件中的第一行是(require'cl)。请参阅@EmmanuelGoldstein,然后您可以添加一些日志记录,以查看您认为无用的缓冲区是否真的是无用的,根据
    是无用的缓冲区
    。例如,您可以在执行上述代码后(例如,运行Emacs时,将消息“Buffer%s%s无用”(Buffer name Buffer)(if(is无用的Buffer Buffer)“is”“is not”))将
    do(和…
    部分更改为
    do(消息“Buffer%s无用”(Buffer name Buffer)(if(is无用的Buffer Buffer)”更改为“\is not”)
    @EmmanuelGoldstein,如果不清楚的话),您仍然需要通过键入
    M-x
    (按住meta/alt并按
    x
    )、
    kill untible buffers
    和返回键来运行
    kill untible buffers
    命令。此外,除非您在运行该命令时碰巧看到缓冲区,否则不会显示缓冲区已被终止。我刚刚启动了Emacs,创建了一些名为
    *foo*
    *bar*
    *baz*
    的缓冲区,然后运行了该命令,这些缓冲区被删除。要更改此代码以删除除名称以星号开头的缓冲区以外的所有缓冲区,只需更改
    是无用的缓冲区
    函数的主体(从第二行的开始括号到下一个到最后一个结束括号