Copy/Paste in emacs ansi-term shell
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 ()(interac开发者_如何学运维tive)(ansi-term "/bin/zsh")))
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.
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.
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.
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.
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))
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,
精彩评论