Подтвердить что ты не робот

Убивающие буферы, чьи имена начинаются с определенной строки

Здесь моя проблема: Я использую 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*")

Мне бы хотелось:

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

Спасибо!

4b9b3361

Ответ 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))