58
votes

I have configured my emacs to run zsh shell within ansi-term. However, copy/paste no longer works i.e. nothing is getting pasted from kill-ring to the terminal. Changing the TERM to vt100, or eterm doesn't solve the problem.

Would appreciate any ideas or solution.

To provide context I have configured ansi-term as follows:

(global-set-key "\C-x\C-a" '(lambda ()(interactive)(ansi-term "/bin/zsh")))
(global-set-key "\C-x\ a" '(lambda ()(interactive)(ansi-term "/bin/zsh")))
6

6 Answers

99
votes

You may want to simply switch between character mode and line mode while using the terminal. C-c C-j will run term-line-mode, which treats the terminal buffer more like a normal text-buffer in which you can move the cursor and yank text. You can switch back to character mode by running term-char-mode with C-c C-k.

13
votes

As described in this lovely blog snippet, there's a function, term-paste, in term.el, that does exactly what you want. By default it's bound only to S-insert but the blog's recommended C-c C-y seems like a good suggestion.

5
votes

ansi-term, in char-mode, takes the ordinary bindings for the terminal emulation. You need a new binding, plus a way to output to ansi-term correctly. I use this:

(defun ash-term-hooks ()
  ;; dabbrev-expand in term
  (define-key term-raw-escape-map "/"
    (lambda ()
      (interactive)
      (let ((beg (point)))
        (dabbrev-expand nil)
        (kill-region beg (point)))
      (term-send-raw-string (substring-no-properties (current-kill 0)))))
  ;; yank in term (bound to C-c C-y)
  (define-key term-raw-escape-map "\C-y"
    (lambda ()
       (interactive)
       (term-send-raw-string (current-kill 0)))))
  (add-hook 'term-mode-hook 'ash-term-hooks)

When you do this, C-c C-y will yank. It only does one yank, though, and you can't cycle through your kill-buffer. It's possible to do this, but I haven't implemented it yet.

1
votes

The above solutions work well for copying text from some buffer to ansi-term, but they aren't able to copy text from ansi-term to another buffer (eg copy a command you just ran to a shell script you're editing). Adding this to my .emacs file solved that problem for me (in Emacs 24.4):

(defun my-term-mode-hook ()
  (define-key term-raw-map (kbd "C-y") 'term-paste)
  (define-key term-raw-map (kbd "C-k")
    (lambda ()
      (interactive)
      (term-send-raw-string "\C-k")
      (kill-line))))
(add-hook 'term-mode-hook 'my-term-mode-hook)

Note that if you want to bind kill/yank to a keystroke that starts with the ansi-term escape characters (by default C-c and C-x), and want this to work in the unlikely event that those change, you can instead define your keystrokes (without the leading escape) to term-raw-escape-map, as is done in user347585's answer.

0
votes

These other solutions don't work well for me, switching between character mode and line mode causes ansi-term to stop working properly randomly, and setting ansi-term's term-paste to C-c C-y (based on Glyph's link), didn't work the code snippet was for term, not ansi-term:

    (eval-after-load "ansi-term"
    '(define-key ansi-term-raw-map (kbd "C-c C-y") 'term-paste))
0
votes

I enabled xterm-mouse-mode, after that I was able to select text using mouse and copy using standard Mac command C button in ansi-term in emacs GUI in Mac OS X,