Уничтожение буферов, имена которых начинаются с определенной строки - PullRequest
14 голосов
/ 24 февраля 2011

Вот моя проблема: Я использую Emacs и получаю множество буферов, которые все время бесполезны, например * Messages * или * Completions *.

Я хочу связать \ C-y, чтобы закрыть все буферы, начинающиеся с *, за исключением * буферов * shell * (и * shell * ).

Для этого я бы хотел добавить Emacs-Lisp в мой файл .emacs:

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

Я уже тестировал string-prefix и curry2 с использованием Scheme, и filter кажется довольно простым. К сожалению, я просто не могу заставить kill-useless работать должным образом.

Там написано filter: Invalid function: (curry2 string-prefix).

Теперь, я просто отстой в Emacs-Lisp, я действительно не использую Лисп, кроме Scheme, и в Scheme (MIT) это работает:

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

Я бы хотел:

  1. способ исправить мой код
  2. предложения о том, как сделать это по-другому

Спасибо!

Ответы [ 6 ]

28 голосов
/ 24 февраля 2011

C-h f kill-matching-buffers RET

kill-Match-buffers - это интерактивная скомпилированная функция Lisp в `Files.el».

(буферы уничтожения соответствия REGEXP и необязательный INTERNAL-TOO)

Убить буферы, чье имя совпадает с указанным REGEXP. Необязательный второй аргумент указывает, следует ли также уничтожать внутренние буферы.

12 голосов
/ 24 февраля 2011

Альтернативный подход:

(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))))
5 голосов
/ 24 февраля 2011

Имейте в виду, что elisp - это не схема, или даже обычный lisp. Синтаксис и семантика разные. Например, defun требует список параметров в круглых скобках. Кроме того, карри на самом деле не возможно в elisp.

К счастью, в elisp есть встроенные функции для большей части того, что вы хотите сделать. Для string-prefix вы можете использовать встроенный string-prefix-p. Для filter вы можете использовать remove-if-not или remove-if для обратного.

Для карри вы можете использовать встроенную функцию 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")
0 голосов
/ 23 августа 2014

Для уничтожения всех других буферов

(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))
0 голосов
/ 19 ноября 2013

Я обнаружил, kill-matching-functions запросил у меня неизмененные буферы, а это не то, что я хотел.Функция ниже убьет буферы, соответствующие префиксу (как в заголовке вопроса).Не совсем то, что вы хотели, но, возможно, такие люди, как я, пришедшие сюда из Google, сочтут это полезным.

(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))))
0 голосов
/ 20 августа 2011

Это может быть хорошей идеей, чтобы увидеть, что вы удаляете перед удалением, чтобы быть в безопасности.

В Сосульки , по умолчанию C-x k - это многокомандная команда, которую вы можете использовать для уничтожения любого количества буферов, соответствующих вводу вашего минибуфера. В этом случае вы должны набрать * TAB, чтобы увидеть все имена буферов, начинающиеся с * в качестве кандидатов на завершение.

Затем вы можете сузить совпадения несколькими способами. Когда все оставшиеся совпадения соответствуют вашим требованиям, нажмите C-!, чтобы удалить все эти буферы.

В представленном случае вы не хотите удалять буферы с именем *shell.... Таким образом, после * TAB вы нажимаете S-SPC, а затем вводите другой шаблон для сопоставления: shell, затем S-TAB. Это сужает только те *shell... буферы, которые вы делаете , а не , которые хотите убить. Затем вы нажимаете C-~, чтобы вычесть эти совпадения (дополнение). Это оставляет все буферы, кроме буферов оболочки. Хит C-! и они все убиты.

Вы также можете уничтожить отдельные буферы, просто нажав и удерживая их имена в *Completions*: C-mouse-2.

В целом, в Сосульках каждая мультикоманда, которая читает имя буфера, позволяет использовать S-delete (Shift + клавиша Delete) для уничтожения кандидатов в буфер.

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

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

...