Отправлять вывод процесса в буфер * Messages *, но обходить область эха

9

Можно ли отправить вывод из фильтра процесса в *Messages*буфер и подавить вывод этого сообщения, появляясь в эхо-области, так что я могу одновременно использовать интерактивные команды, не minibuffer-promptстираясь при текущем выводе фильтра субпресса?

(defun rsync-process-filter (proc string)
  (when (not (or
      (string-match "files...\r" string)
      (string-match "files to consider\n" string)))
    (message "%s" string)))

РЕДАКТИРОВАТЬ (3 января 2015 г.): Ниже приведена ссылка на похожий вопрос, однако я пока не смог заставить его работать со строкой процесса, в которой точная строка неизвестна - заголовок темы: Emacs - Отключить некоторые сообщения минибуфера :

/superuser/669701/emacs-disable-some-minibuffer-messages

lawlist
источник
Я не думаю, что ты можешь. Почему бы просто не войти в другой буфер? Это то, что делают большинство режимов, которые имеют дело с процессами ...
lunaryorn
@lunaryorn - Спасибо за предложение - выделенный буфер является допустимым вариантом для решения проблемы. Есть несколько выходов процесса, которые я предпочитаю отправлять в *Messages*буфер - один из них связан с синхронизацией. Есть еще пара вещей, которые я не пробовал ( потому что я думал, что, возможно, было встроенное решение ), например, сделать *Messages*буфер временно доступным для записи inhibit-read-onlyи использовать insertat point-max- я не знаю, появится ли это в эхо-зона, а также. Я буду работать над этим снова этим вечером. , ,
юрист
Интересно отметить, что функции C для обмена сообщениями очень сильно разделены проблемами «echo» и «logging», но это различие не подвергается elisp. Возможно, вы могли бы M-x report-emacs-bugи запросить это как функцию?
Фил
@phils | @lunaryorn: Я смог достичь желаемого эффекта с помощью (let ((inhibit-read-only t)) (with-current-buffer (get-buffer-create "*Messages*") (goto-char (point-max)) (insert string)))и разместил черновой ответ, который будет приемлем для принятия после истечения обязательного периода ожидания по собственному вопросу пользователя. Я отправил запрос на добавлениеreport-emacs-bug : debbugs.gnu.org/cgi/bugreport.cgi?bug=19495
юрист
lawlist: я не собирался предлагать такой подход, потому что вы могли бы столкнуться с логикой обработки дубликатов сообщений и т. д. (но это также может быть хорошо; на самом деле я не знаю.) Вы, вероятно, должны использовать (messages-buffer)для получения буфера , если вы придерживаетесь этого метода и обратите внимание, что (point-max)это не всегда будет началом новой строки (например, использование C-g).
Филс

Ответы:

3

Вы можете подавить отображение в минибуфере, установив minibuffer-message-timeoutна 0.

Например, я использую что-то подобное в нескольких местах, где я хочу переключать второстепенный режим, когда в приглашении минибуфера (например, ido find-file) без прерывания сообщением «mode enabled»:

(let ((minibuffer-message-timeout 0))
    (toggle-some-mode))
glucas
источник
Спасибо за предложение; однако, это не достигло желаемого эффекта. При выводе (let ((minibuffer-message-timeout 0)) (message "%s" string))интерактивных функций, таких как execute-extended-commandили switch-to-buffer-other-window- т. Е. Подсказки и предлагаемые завершения стираются в выходных сообщениях процесса, текущая печать выходных данных процесса все еще отображается в эхо-области / минибуфере .
юрист
3

Первый предварительный черновик (3 января 2015 г.): пересмотрен первоначальный черновик на основе полезного комментария @phils относительно использования функции messages-bufferдля поиска или создания соответствующего буфера (и помещения его в messages-buffer-mode); и добавил проверку того, point-maxнаходится ли в начале строки (если нет, то вставьте новую строку перед вставкой строки сообщения).

РЕДАКТИРОВАНИЕ (4 января 2015 г.): существуют ситуации, когда вставленная строка не обязательно заканчивается новой строкой, и функция messageне имеет проверки, чтобы убедиться, что она находится в начале новой строки, поэтому мы позаботимся об этом. в этой функции. Таким образом, в любой момент, когда messageвставляется новая строка, указанная строка будет начинаться слева от буфера.

(defun rsync-process-filter (proc string)
  (let ((inhibit-read-only t))
    (when (not (or
        (string-match "files...\r" string)
        (string-match "files to consider\n" string)))
      (with-current-buffer (messages-buffer)
        (goto-char (point-max))
        (when (not (bolp))
          (insert "\n"))
        (insert string)
        (when (not (bolp))
          (insert "\n"))))))
lawlist
источник
2

Переход через строку документацию на messageнего , кажется , это должно быть возможно добиться того, что вы хотите, вызвав сообщение с nilаргументом сразу после вызова messageс нужным содержанием. Из документацииmessage

Если первый аргумент - ноль или пустая строка, функция очищает любое существующее сообщение; это позволяет показать содержимое минибуфера.

Поэтому изменение вашей функции на что-то вроде следующего должно работать

(defun rsync-process-filter (proc string)
  (when (not (or
      (string-match "files...\r" string)
      (string-match "files to consider\n" string)))
    (message "%s" string)
    (message nil)))

Я проверил это, выполнив следующее

(defun test ()
  (message "%s" "Test")
  (message nil))

(run-at-time 5 5 #'test)

И это похоже на работу

Икбал Ансари
источник
Спасибо за предложение. Эта идея, когда проверяется с запущенным процессом, выводимым в *Messages*буфер, а затем вызывающим интерактивную команду execute-extended-command, показывает следующее: интерактивное приглашение (т. Е. M-xИ любые частичные завершения) и выходные данные процесса - т. Е. Два переключаются назад и вперед со скоростью света, но мерцание между ними заметно. Похоже, что это так, потому что конкретный рассматриваемый процесс постоянно выплевывает новые сообщения, и это новое сообщение отображается в течение доли секунды в эхо-области.
юрист