3

I'm running a (start-process) which spits out terminal escape codes into a buffer and it looks ugly. Is there a mode that will interpret these codes into colors? Something similar to whatever ansi-term does?

  • You do need to set up the plumbing with ansi-color but I don't know how that works when you aren't in Comint mode. – Gilles 'SO- stop being evil' Jun 3 '17 at 21:30
2

You can use "process sentinel" mentioned in @steve-lorimer's answer if it is OK for you to get color AFTER the process is finished, otherwise you should use "process filter" instead.

Take command echo -e "\e[31mHello World\e[0m" as an example, you can simply use comint-output-filter (I learnt this by reading shell-command's source code)

(let ((process
       (start-process "echo" "*echo*"
                      "echo" "-e" "\e[31mHello World\e[0m")))
  (with-current-buffer (process-buffer process)
    (display-buffer (current-buffer))
    (require 'shell)
    (shell-mode)
    (set-process-filter process 'comint-output-filter)))

besides colors, comint-output-filter can also handle progress bar (used by commands like wget) correctly.

Or you can also make your own filter:

(let ((process
       (start-process "echo" "*echo*"
                      "echo" "-e" "\e[31mHello World\e[0m")))
  (with-current-buffer (process-buffer process)
    (display-buffer (current-buffer))
    (font-lock-mode)
    (set-process-filter
     process
     #'echo-output-filter)))

;; Base on `ordinary-insertion-filter' from (info "(elisp) Filter Functions")
(defun echo-output-filter (proc string)
  (when (buffer-live-p (process-buffer proc))
    (with-current-buffer (process-buffer proc)
      (let ((moving (= (point) (process-mark proc))))
        (save-excursion
          ;; Insert the text, advancing the process marker.
          (goto-char (process-mark proc))
          (insert (ansi-color-apply string))
          (set-marker (process-mark proc) (point)))
        (if moving (goto-char (process-mark proc)))))))

Both of them work from here.

0

This SO answer makes reference to ansi-color-apply-on-region.

The idea is you use set-process-sentinel to get notified when your process exits, and then use ansi-color-apply-on-region on the buffer

(set-process-sentinel
 (start-process "foo" "*Foo*" foo-command foo-args)
 (lambda (p _m)
   (when (eq 0 (process-exit-status p))
     (with-current-buffer (process-buffer p)
       (ansi-color-apply-on-region (point-min) (point-max))))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.