64

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")))
mpm
  • 3,534
  • 23
  • 33
Kabira K
  • 1,916
  • 2
  • 22
  • 38

6 Answers6

114

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.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Kirk Kelsey
  • 4,259
  • 1
  • 23
  • 26
  • This doesn't work too well with the right aligned prompt that things like zsh provide. – l0st3d Dec 06 '13 at 15:34
  • 25
    In Emacs 24, it appears that while in the terminal you need to press 'C-c C-j' to get to line mode, and then to get back, it is 'C-c C-k' as above. – djhaskin987 Feb 27 '14 at 01:16
17

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.

Glyph
  • 31,152
  • 11
  • 87
  • 129
5

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.

barracel
  • 1,831
  • 13
  • 24
user347585
  • 101
  • 1
  • Appreciate your response. A ")" was missing in the end. Unfortunately this doesn't seem to work for me. I am getting error C-c C-y is undefined. – Kabira K May 22 '10 at 04:15
  • Hm, I tried running "emacs -q" with emacs 23.2, and (after fixing the missing paren you pointed out), I evaluated, copied some random text, then started ansi-term. Pressing C-c C-y did in fact paste it. Since this is using a hook, make sure you have restarted ansi-term after you evaluate it. if that doesn't work, try it on an emacs started with -q. You can also try pressing C-c C-h, which list bindings starting with C-c. C-c C-y should be listed with ?? (?? because we're using an unnamed lambda). – user347585 May 23 '10 at 02:39
  • Hello. I tried restarting emacs both with and without -q. But it is still not working. I am using emacs 23.1 on ubuntu. R C-c C-h does not show any bindings when I start emacs normally. With -q I have several bindings but none about C-c C-y. Is there a log or debug output that I can look into to see whats missing. Thanks. -Sandeep – Kabira K May 25 '10 at 04:45
  • With emacs 24 the code works but you need to use `C-x C-y` or `C-x C-/` – barracel Jul 25 '13 at 14:17
  • Anyone know how to get this working without a prefix? I would like to rebind s-v (super = mac command key). – Random832 Aug 29 '15 at 00:05
1

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.

charliegreen
  • 494
  • 1
  • 5
  • 11
0

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))
junkgui
  • 179
  • 2
  • 7
0

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,

ahsankhan
  • 951
  • 1
  • 7
  • 5