Wyślij dane wyjściowe procesu do bufora * Messages *, ale pomiń obszar echa

9

Czy jest możliwe przesłanie danych wyjściowych z filtra procesu do *Messages*bufora i powstrzymanie pojawiania się tego komunikatu w obszarze echa, tak że jestem w stanie jednocześnie używać interaktywnych poleceń bez konieczności minibuffer-promptusuwania ich przez trwające wyjście filtra podciśnienia?

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

EDYCJA (3 stycznia 2015 r.): Poniżej znajduje się link do podobnego pytania, jednak nie byłem jeszcze w stanie sprawić, aby działał z łańcuchem procesu, w którym dokładny ciąg jest nieznany - tytuł wątku to: Emacs - Wyłącz niektóre komunikaty minibufora :

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

lista prawnicza
źródło
Nie sądzę, że możesz. Dlaczego nie zalogować się do innego bufora? To właśnie robi większość trybów, które zajmują się procesami…
lunaryorn
@lunaryorn - Dziękujemy za sugestię - dedykowany bufor jest prawidłową opcją rozwiązania problemu. Istnieje kilka wyników procesu, które osobiście preferuję wysyłanie do *Messages*bufora - jednym z nich są projekty związane z synchronizacją. Wciąż jest kilka rzeczy, których nie próbowałem ( ponieważ myślałem, że mogło istnieć wbudowane rozwiązanie ), takie jak *Messages*tymczasowe zapisywanie bufora inhibit-read-onlyi używanie insertw point-max- nie wiem, czy to się pojawi w obszar echa. Popracuję nad tym wieczorem. . .
prawnik
Jedną z interesujących uwag jest to, że funkcje C do przesyłania komunikatów są bardzo oddzielone problemami „echa” i „rejestrowania”, ale to rozróżnienie nie jest narażone na elisp. Być może mógłbyś M-x report-emacs-bugpoprosić o to jako funkcję?
phils
@phils | @lunaryorn: Byłem w stanie osiągnąć pożądany efekt za pomocą (let ((inhibit-read-only t)) (with-current-buffer (get-buffer-create "*Messages*") (goto-char (point-max)) (insert string)))i opublikowałem roboczą odpowiedź, która będzie kwalifikować się do akceptacji po upływie obowiązkowego okresu oczekiwania na własne pytanie użytkownika. Złożyłem wniosek o dodanie funkcji do report-emacs-bug: debbugs.gnu.org/cgi/bugreport.cgi?bug=19495
prawnik
lawlist: Nie zamierzałem sugerować takiego podejścia, ponieważ możesz popsuć logikę do obsługi zduplikowanych wiadomości itp. (Ale może być również w porządku; nie wiem.) Prawdopodobnie powinieneś użyć, (messages-buffer)aby uzyskać bufor , jeśli (point-max)pozostaniesz przy tej metodzie i zauważysz, że nie zawsze będzie to początek nowej linii (np. użyj C-g).
phils

Odpowiedzi:

3

Możesz ukryć wyświetlanie w minibuforze, ustawiając minibuffer-message-timeoutna 0.

Na przykład używam czegoś takiego w kilku miejscach, w których chcę przełączyć tryb pomocniczy w monicie bufora (np. Plik ido find-file) bez przerywania komunikatem „włączony tryb”:

(let ((minibuffer-message-timeout 0))
    (toggle-some-mode))
glucas
źródło
Dziękuję za sugestię; nie osiągnęło to jednak pożądanego efektu. Trwające drukowanie wyjściowego procesu z (let ((minibuffer-message-timeout 0)) (message "%s" string))nadal wyświetla się w obszarze echa / minibuforze podczas pisania interaktywnych funkcji, takich jak execute-extended-commandlub switch-to-buffer-other-window- tj. Monit i sugerowane zakończenia są usuwane przez komunikaty wyjściowe procesu.
prawnik
3

Pierwszy trudny szkic (3 stycznia 2015 r.): Zmieniony wstępny szkic w oparciu o pomocny komentarz @phils dotyczący użycia funkcji messages-bufferdo zlokalizowania lub utworzenia odpowiedniego bufora (i włożenia go messages-buffer-mode); i dodano sprawdzenie, czy point-maxjest na początku wiersza (jeśli nie, wstaw nowy wiersz przed wstawieniem ciągu wiadomości).

EDYCJA (4 stycznia 2015 r.): Są sytuacje, w których wstawiony ciąg niekoniecznie musi kończyć się nowym wierszem, a funkcja messagenie sprawdza, czy znajduje się na początku nowego wiersza, więc zajmujemy się tym w tej funkcji. Zatem w dowolnym momencie messagewstawiania nowej linii wspomniana linia zacznie się w lewo od bufora.

(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"))))))
lista prawnicza
źródło
2

Przechodząc przez dokumentację messagewydaje się, że powinno być możliwe osiągnięcie tego, co chcesz, poprzez wywołanie wiadomości z nilargumentem natychmiast po wywołaniu messagez pożądaną treścią. Z dokumentacjimessage

Jeśli pierwszym argumentem jest zero lub pusty ciąg, funkcja usuwa wszelki istniejący komunikat; pozwala to na wyświetlenie zawartości minibufora.

Tak więc modyfikacja funkcji do czegoś takiego jak poniżej powinna działać

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

Przetestowałem to, wykonując następujące czynności

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

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

I wydaje się, że działa

Iqbal Ansari
źródło
Dziękuję za sugestię. Pomysł ten, przetestowany z uruchomionym wyjściem procesu do *Messages*bufora, a następnie wywołaniem komendy interaktywnej execute-extended-command, pokazuje: interaktywny monit (tj. M-xI wszelkie częściowe uzupełnienia) oraz dane wyjściowe z procesu - tj. Dwa przełączniki z powrotem i z prędkością światła, ale migotanie między nimi jest zauważalne. Wydaje się, że dzieje się tak, ponieważ konkretny sporny proces ciągle wyrzuca nowe wiadomości, a nowa wiadomość jest wyświetlana przez ułamek sekundy w obszarze echa.
prawnik