Убивающие буферы, чьи имена начинаются с определенной строки
Здесь моя проблема:
Я использую Emacs и получаю много буферов, которые все время бесполезны, например * Messages * или * Completions *.
Я хочу привязать \C-y, чтобы закрыть все буферы, которые начинаются с *, за исключением буферов * shell * (и * shell * <k> ).
Чтобы сделать это, я хотел бы добавить 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, я действительно не использую никаких Lisp кроме Схемы, а в Scheme (MIT) это работает:
(filter ((curry2 string-prefix?) "*shell") '("*shell*" "*sh22" "eel"))
;Value 5: ("*shell*")
Мне бы хотелось:
- способ исправления кода
- предложения о том, как это сделать по-другому.
Спасибо!
Ответы
Ответ 1
Альтернативный подход:
(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
C-h f kill-matching-buffers
RET
kill-matching-buffers - это интерактивная скомпилированная функция Lisp в `Files.el".
(бит-совместимые буферы REGEXP и дополнительный INTERNAL-TOO)
Убить буферы, имя которых соответствует указанному REGEXP. Необязательный второй аргумент указывает, следует ли также убивать внутренние буферы.
Ответ 3
Имейте в виду, что elisp - это не схема или даже общий lisp. Синтаксис и семантика различны. Например, defun
требуется список параметров, окруженный скобками. Кроме того, каррирование не реально в elisp.
К счастью, elisp имеет встроенные функции для большей части того, что вы хотите сделать. Для string-prefix
вы можете использовать встроенный string-prefix-p
. Для filter
вы можете использовать remove-if-not
или remove-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")
Ответ 4
Это может быть хорошей идеей, чтобы увидеть, что вы удалите, прежде чем удалять его, чтобы играть безопасно.
В Icicles по умолчанию C-x k
- это многокомандная команда, которую вы можете использовать для уничтожения любого количества буферов, соответствующих вашему входу минибуфера. В этом случае вы должны набрать * TAB
, чтобы увидеть все имена буферов, начиная с *
в качестве кандидатов на завершение.
Затем вы можете сузить матчи несколькими способами. Когда все оставшиеся совпадения вы хотите, нажмите C-!
, чтобы удалить все эти буферы.
В представленном вами случае вы не хотите удалять буферы с именем *shell...
. Итак, после * TAB
вы нажмете S-SPC
, а затем введите другой шаблон, чтобы он соответствовал: shell
, затем S-TAB
. Это сужается только для буферов *shell...
, которые вы не хотите убивать. Затем вы ударите C-~
, чтобы вычесть эти соответствия (дополнение). Это оставляет все буферы, кроме буферов оболочки. Хит C-!
, и все они убиты.
Вы также можете убить отдельные буферы, просто щелкнув их имена в *Completions*
: C-mouse-2
.
В общем, в Icicles каждая команда, которая читает имя буфера, позволяет использовать S-delete
(Shift + клавишу Delete) для уничтожения кандидатов в буфер.
http://www.emacswiki.org/emacs/Icicles_-_Multi-Commands
http://www.emacswiki.org/emacs/Icicles_-_More_About_Multi-Commands
Ответ 5
Я обнаружил, что 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))))
Ответ 6
Чтобы убить все остальные буферы
(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))