all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Frank Fischer <frank-fischer@shadow-soft.de>
To: emacs-devel@gnu.org
Subject: Eshell: copy output of visual commands
Date: Sat, 17 Aug 2013 10:07:24 +0200	[thread overview]
Message-ID: <20130817100724.620cd7c7@mawo> (raw)

I want to use certain commands from eshell that have colourized output.
Because eshell is not a full terminal emulator it relies on ansi-term
to execute these commands. However, when the command has finished the
ansi-term buffer is deleted. Hence, if a "visual" commands does not
wait for user input but just prints something to the screen and then
exits immediately, its output is lost (e.g. I use mercurial with
colourized output declared as visual commands, but commands like "hg
log" just print something to the screen and then exit). The idea is to
copy the final output of the commands, i.e. the content of the terminal
buffer after the command has finished, back to the eshell buffer. This
gives eshell a behaviour quite close to standard terminal emulators in
these situations. For those who are interested, I use the following
modifications of eshell (the changed lines are marked):


```
(defadvice eshell-exec-visual (around fifr (&rest args) activate)
  "Store insertion point for result of visual command."
  (let* (eshell-interpreter-alist
         (interp (eshell-find-interpreter (car args)))
         (program (car interp))
         (args (eshell-flatten-list
                (eshell-stringify-list (append (cdr interp)
                                               (cdr args)))))
         (term-buf
          (generate-new-buffer
           (concat "*" (file-name-nondirectory program) "*")))
         (eshell-buf (current-buffer)))
    (save-current-buffer
      (switch-to-buffer term-buf)
      (term-mode)
      (set (make-local-variable 'term-term-name) eshell-term-name)
      (make-local-variable 'eshell-parent-buffer)
      (setq eshell-parent-buffer eshell-buf)
      ;; CHANGED
      (make-local-variable 'eshell-visual-point)
      (setq eshell-visual-point
            (with-current-buffer eshell-buf
              (set-marker (make-marker) (1- (point)))))
      ;; CHANGED
      (term-exec term-buf program program nil args)
      (let ((proc (get-buffer-process term-buf)))
        (if (and proc (eq 'run (process-status proc)))
            (set-process-sentinel proc 'eshell-term-sentinel)
          (error "Failed to invoke visual command")))
      (term-char-mode)
      (if eshell-escape-control-x
          (term-set-escape-char ?\C-x))))
  nil)

(defun fifr/eshell-copy-visual-output (shell-buf proc-buf)
  "Copy result of visual command back to the shell buffer."
  (and (buffer-live-p shell-buf)
       (buffer-live-p proc-buf)
       (prog1 t
         (let ((txt (with-current-buffer proc-buf
                      (buffer-substring (point-min) (point-max))))
               (mrk (with-current-buffer proc-buf
                      eshell-visual-point)))
           ;; Remove useless empty lines at the end
           (save-match-data
             (setq txt (substring 
                        txt 0
                        (string-match "^[[:space:]\n]*\\'"txt)))) 
           (with-current-buffer shell-buf
             (save-excursion
               (goto-char (1+ mrk))
               (set-marker mrk nil)
               (insert txt)))))))

(defadvice eshell-term-sentinel (around fifr (proc string) activate)
  "Maybe copy the content of the term buffer back to the shell buffer."
  (let ((proc-buf (process-buffer proc)))
    (when (and proc-buf (buffer-live-p proc-buf)
               (not (eq 'run (process-status proc)))
               (= (process-exit-status proc) 0))
      (if (eq (current-buffer) proc-buf)
          (let ((buf (and (boundp 'eshell-parent-buffer)
                          eshell-parent-buffer
                          (buffer-live-p eshell-parent-buffer)
                          eshell-parent-buffer)))
            (if buf
                (switch-to-buffer buf))))
      ;; CHANGED
      (if (with-current-buffer proc-buf
            (fifr/eshell-copy-visual-output 
             eshell-parent-buffer
             proc-buf)) 
          (kill-buffer proc-buf)
        (with-current-buffer proc-buf
          (switch-to-buffer proc-buf)
          (local-set-key "q"
                         #'(lambda ()
                             (interactive)
                             (kill-buffer (current-buffer)))))))))
      ;; CHANGED
```

Best regards,
Frank





                 reply	other threads:[~2013-08-17  8:07 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130817100724.620cd7c7@mawo \
    --to=frank-fischer@shadow-soft.de \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.