Open Sbozzolo opened 4 years ago
evil-collection
integrates with vterm
.
evil-collection/modes/vterm/evil-collection-vterm.el
Some evil-mode user use the cursor's shape and color as evil-state indicator, for example:
(setq evil-insert-state-cursor '(bar "#00FF00")
evil-visual-state-cursor '(box "#FF00FF")
evil-normal-state-cursor '(box "#E2E8EF"))
will set the cursor as a green bar in insert
state; a white box in normal
state; a magenta box in visual
state.
The problem with vterm is, sometimes it dose not respect the cursor shape. I don't know how to reproduce it consistently but sometimes after I leaved the vterm buffer then re-visit it, the cursor will change to bar shape while it should be a box shape.
One annoyance I have is the following scenario:
When doing step 3, the cursor jumps back to the end of the line when typing. I guess vterm doesn't track the cursor in normal mode as it does in insert mode (moving in insert mode using arrow keys work fine).
Using normal mode, it's possible to move the cursor out of the prompt (like vterm-copy-mode
), and in that case it makes sense that the cursor is reset when typing.
Ideally, when entering insert mode, the vterm cursor position should either be set to the current point if within the prompt, or to the last cursor position if outside it.
One annoyance I have is the following scenario:
- Enter insert mode, type some text
- Enter normal mode, move cursor back a bit
- Enter insert mode, start typing
When doing step 3, the cursor jumps back to the end of the line when typing. I guess vterm doesn't track the cursor in normal mode as it does in insert mode (moving in insert mode using arrow keys work fine).
Using normal mode, it's possible to move the cursor out of the prompt (like
vterm-copy-mode
), and in that case it makes sense that the cursor is reset when typing.Ideally, when entering insert mode, the vterm cursor position should either be set to the current point if within the prompt, or to the last cursor position if outside it.
Yes, we do not really support evil-mode
at the moment. My understanding is that the most common way to have it with vterm is to set evil-mode
to always use emacs-mode
(in vterm buffers), then, the shell is configured with a VI emulation mode.
One annoyance I have is the following scenario:
- Enter insert mode, type some text
- Enter normal mode, move cursor back a bit
- Enter insert mode, start typing
When doing step 3, the cursor jumps back to the end of the line when typing. I guess vterm doesn't track the cursor in normal mode as it does in insert mode (moving in insert mode using arrow keys work fine). Using normal mode, it's possible to move the cursor out of the prompt (like
vterm-copy-mode
), and in that case it makes sense that the cursor is reset when typing. Ideally, when entering insert mode, the vterm cursor position should either be set to the current point if within the prompt, or to the last cursor position if outside it.Yes, we do not really support
evil-mode
at the moment. My understanding is that the most common way to have it with vterm is to setevil-mode
to always useemacs-mode
(in vterm buffers), then, the shell is configured with a VI emulation mode.
Would someone be able to point to an example of how to set this up?
I think I can figure out the "always use emacs-mode
in vterm buffers" part, but how do I configure my shell for VI emulation? I'm using Oh My Zsh and vi-mode, which works in iTerm2, but I'm not sure how to get it to work in emacs vterm.
Some evil-mode user use the cursor's shape and color as evil-state indicator, for example:
(setq evil-insert-state-cursor '(bar "#00FF00") evil-visual-state-cursor '(box "#FF00FF") evil-normal-state-cursor '(box "#E2E8EF"))
will set the cursor as a green bar in
insert
state; a white box innormal
state; a magenta box invisual
state.The problem with vterm is, sometimes it dose not respect the cursor shape. I don't know how to reproduce it consistently but sometimes after I leaved the vterm buffer then re-visit it, the cursor will change to bar shape while it should be a box shape.
I have the same problem and I think I found a way to reproduce it.
git branch
q
to exit git branch
After doing that, the cursor is shaped like it's on normal state, even though it's actually on insert state
One annoyance I have is the following scenario:
- Enter insert mode, type some text
- Enter normal mode, move cursor back a bit
- Enter insert mode, start typing
When doing step 3, the cursor jumps back to the end of the line when typing. I guess vterm doesn't track the cursor in normal mode as it does in insert mode (moving in insert mode using arrow keys work fine). Using normal mode, it's possible to move the cursor out of the prompt (like
vterm-copy-mode
), and in that case it makes sense that the cursor is reset when typing. Ideally, when entering insert mode, the vterm cursor position should either be set to the current point if within the prompt, or to the last cursor position if outside it.Yes, we do not really support
evil-mode
at the moment. My understanding is that the most common way to have it with vterm is to setevil-mode
to always useemacs-mode
(in vterm buffers), then, the shell is configured with a VI emulation mode.Would someone be able to point to an example of how to set this up?
I think I can figure out the "always use
emacs-mode
in vterm buffers" part, but how do I configure my shell for VI emulation? I'm using Oh My Zsh and vi-mode, which works in iTerm2, but I'm not sure how to get it to work in emacs vterm.
@yosevu I have the opposite issue, could you share how you set it to always use emacs-mode in vterm buffers? Below are some links on how to setup vi emulation for your shell bash zsh
One annoyance I have is the following scenario:
- Enter insert mode, type some text
- Enter normal mode, move cursor back a bit
- Enter insert mode, start typing
When doing step 3, the cursor jumps back to the end of the line when typing. I guess vterm doesn't track the cursor in normal mode as it does in insert mode (moving in insert mode using arrow keys work fine).
Using normal mode, it's possible to move the cursor out of the prompt (like
vterm-copy-mode
), and in that case it makes sense that the cursor is reset when typing.Ideally, when entering insert mode, the vterm cursor position should either be set to the current point if within the prompt, or to the last cursor position if outside it.
Does anyone please have some workaround for this? evil-mode
is my main motivation for migrating my terminal from urxvt to emacs.
One annoyance I have is the following scenario:
- Enter insert mode, type some text
- Enter normal mode, move cursor back a bit
- Enter insert mode, start typing
When doing step 3, the cursor jumps back to the end of the line when typing. I guess vterm doesn't track the cursor in normal mode as it does in insert mode (moving in insert mode using arrow keys work fine). Using normal mode, it's possible to move the cursor out of the prompt (like
vterm-copy-mode
), and in that case it makes sense that the cursor is reset when typing. Ideally, when entering insert mode, the vterm cursor position should either be set to the current point if within the prompt, or to the last cursor position if outside it.Does anyone please have some workaround for this?
evil-mode
is my main motivation for migrating my terminal from urxvt to emacs.
We do, https://github.com/Sbozzolo/vterm-extra This pakcage provide a function that copy the current command line to a new buffer then when edit finished, replace the old command line with the new command line
One annoyance I have is the following scenario:
- Enter insert mode, type some text
- Enter normal mode, move cursor back a bit
- Enter insert mode, start typing
When doing step 3, the cursor jumps back to the end of the line when typing. I guess vterm doesn't track the cursor in normal mode as it does in insert mode (moving in insert mode using arrow keys work fine). Using normal mode, it's possible to move the cursor out of the prompt (like
vterm-copy-mode
), and in that case it makes sense that the cursor is reset when typing. Ideally, when entering insert mode, the vterm cursor position should either be set to the current point if within the prompt, or to the last cursor position if outside it.Yes, we do not really support
evil-mode
at the moment. My understanding is that the most common way to have it with vterm is to setevil-mode
to always useemacs-mode
(in vterm buffers), then, the shell is configured with a VI emulation mode.Would someone be able to point to an example of how to set this up? I think I can figure out the "always use
emacs-mode
in vterm buffers" part, but how do I configure my shell for VI emulation? I'm using Oh My Zsh and vi-mode, which works in iTerm2, but I'm not sure how to get it to work in emacs vterm.@yosevu I have the opposite issue, could you share how you set it to always use emacs-mode in vterm buffers? Below are some links on how to setup vi emulation for your shell bash zsh
I think evil-emacs-state-modes
can be used for this purpose. I haven't tried it, but saw it discussed in this article: Living in Emacs
I don't use evil
, but I would expect the following to work:
(add-hook 'vterm-mode-hook (lambda () (setq evil-default-state 'emacs)))
This should force evil
to be in the emacs
state in vterm buffers, which in practice means that vi
keybindings are disabled and you can enable them in your shell.
Currently this works reasonably well:
(evil-define-key 'normal vterm-mode-map "h" 'vterm-send-left)
(evil-define-key 'normal vterm-mode-map "l" 'vterm-send-right)
(evil-define-key 'normal vterm-mode-map "b" 'vterm-send-M-b)
(evil-define-key 'normal vterm-mode-map "e" 'vterm-send-M-f)
(evil-define-key 'normal vterm-mode-map "db" 'vterm-send-C-w)
(evil-define-key 'normal vterm-mode-map "de" 'vterm-send-M-d)
(evil-define-key 'normal vterm-mode-map "p" 'vterm-yank)
(evil-define-key 'normal vterm-mode-map "P" '(lambda ()
(interactive)
(vterm-send-C-b)
(vterm-yank)))
It's not a like for like replacement, but basic movement can be added like this. I think you could replace most of the functionality like this. Only thing I'm really missing is selections for visual mode, is there a vterm way to send C-Space
to set a mark?
Currently this works reasonably well:
(evil-define-key 'normal vterm-mode-map "h" 'vterm-send-left) (evil-define-key 'normal vterm-mode-map "l" 'vterm-send-right) (evil-define-key 'normal vterm-mode-map "b" 'vterm-send-M-b) (evil-define-key 'normal vterm-mode-map "e" 'vterm-send-M-f) (evil-define-key 'normal vterm-mode-map "db" 'vterm-send-C-w) (evil-define-key 'normal vterm-mode-map "de" 'vterm-send-M-d) (evil-define-key 'normal vterm-mode-map "p" 'vterm-yank) (evil-define-key 'normal vterm-mode-map "P" '(lambda () (interactive) (vterm-send-C-b) (vterm-yank)))
It's not a like for like replacement, but basic movement can be added like this. I think you could replace most of the functionality like this. Only thing I'm really missing is selections for visual mode, is there a vterm way to send
C-Space
to set a mark?
Okay this actually works as a solution to the visual mode deletion:
(evil-define-key 'visual vterm-mode-map "d" 'vterm-send-M-w)
I'll try and put together a complete set of bindings that you could add to the README or something?
Currently this works reasonably well:
(evil-define-key 'normal vterm-mode-map "h" 'vterm-send-left) (evil-define-key 'normal vterm-mode-map "l" 'vterm-send-right) (evil-define-key 'normal vterm-mode-map "b" 'vterm-send-M-b) (evil-define-key 'normal vterm-mode-map "e" 'vterm-send-M-f) (evil-define-key 'normal vterm-mode-map "db" 'vterm-send-C-w) (evil-define-key 'normal vterm-mode-map "de" 'vterm-send-M-d) (evil-define-key 'normal vterm-mode-map "p" 'vterm-yank) (evil-define-key 'normal vterm-mode-map "P" '(lambda () (interactive) (vterm-send-C-b) (vterm-yank)))
It's not a like for like replacement, but basic movement can be added like this. I think you could replace most of the functionality like this. Only thing I'm really missing is selections for visual mode, is there a vterm way to send
C-Space
to set a mark?Okay this actually works as a solution to the visual mode deletion:
(evil-define-key 'visual vterm-mode-map "d" 'vterm-send-M-w)
I'll try and put together a complete set of bindings that you could add to the README or something?
What is the difference between this approach and, say, this?
Currently this works reasonably well:
(evil-define-key 'normal vterm-mode-map "h" 'vterm-send-left) (evil-define-key 'normal vterm-mode-map "l" 'vterm-send-right) (evil-define-key 'normal vterm-mode-map "b" 'vterm-send-M-b) (evil-define-key 'normal vterm-mode-map "e" 'vterm-send-M-f) (evil-define-key 'normal vterm-mode-map "db" 'vterm-send-C-w) (evil-define-key 'normal vterm-mode-map "de" 'vterm-send-M-d) (evil-define-key 'normal vterm-mode-map "p" 'vterm-yank) (evil-define-key 'normal vterm-mode-map "P" '(lambda () (interactive) (vterm-send-C-b) (vterm-yank)))
It's not a like for like replacement, but basic movement can be added like this. I think you could replace most of the functionality like this. Only thing I'm really missing is selections for visual mode, is there a vterm way to send
C-Space
to set a mark?Okay this actually works as a solution to the visual mode deletion:
(evil-define-key 'visual vterm-mode-map "d" 'vterm-send-M-w)
I'll try and put together a complete set of bindings that you could add to the README or something?
What is the difference between this approach and, say, this?
The issue with that approach is that you have to disable evil mode for that to work properly, otherwise your escape key will trigger evil instead of zsh vi mode. When in emacs mode no evil bindings will work e.g. evil tab navigation, evil leader key binds. Personally I have most emacs navigation functions such as: kill window and buffer bound to leader combinations like ,kw
. Copy and paste also becomes a bit of a nightmare of which shortcut do I use between these three modes.
Currently this works reasonably well:
(evil-define-key 'normal vterm-mode-map "h" 'vterm-send-left) (evil-define-key 'normal vterm-mode-map "l" 'vterm-send-right) (evil-define-key 'normal vterm-mode-map "b" 'vterm-send-M-b) (evil-define-key 'normal vterm-mode-map "e" 'vterm-send-M-f) (evil-define-key 'normal vterm-mode-map "db" 'vterm-send-C-w) (evil-define-key 'normal vterm-mode-map "de" 'vterm-send-M-d) (evil-define-key 'normal vterm-mode-map "p" 'vterm-yank) (evil-define-key 'normal vterm-mode-map "P" '(lambda () (interactive) (vterm-send-C-b) (vterm-yank)))
It's not a like for like replacement, but basic movement can be added like this. I think you could replace most of the functionality like this. Only thing I'm really missing is selections for visual mode, is there a vterm way to send
C-Space
to set a mark?Okay this actually works as a solution to the visual mode deletion:
(evil-define-key 'visual vterm-mode-map "d" 'vterm-send-M-w)
I'll try and put together a complete set of bindings that you could add to the README or something?
What is the difference between this approach and, say, this?
The issue with that approach is that you have to disable evil mode for that to work properly, otherwise your escape key will trigger evil instead of zsh vi mode. When in emacs mode no evil bindings will work e.g. evil tab navigation, evil leader key binds. Personally I have most emacs navigation functions such as: kill window and buffer bound to leader combinations like
,kw
. Copy and paste also becomes a bit of a nightmare of which shortcut do I use between these three modes.
I see, thanks.
What about the following (temporary) solution:
In vterm-extra
, there is a command vterm-extra-edit-command-in-new-buffer
. If you bind this function to a key, a new buffer appear where you can edit freely the command that will be sent to the terminal. The annoyance with this function is that for each command two additional keys have to pressed (one to enter in this mode, and one to leave it). What if I develop a similar minor-mode vterm-extra-minibuffer
. With this minor mode, if you press enter on the prompt line in vterm buffers, you'll end up in the minibuffer, where you can use your evil commands, then, when you are done, you press enter again and the command is sent to the vterm buffer. When this minor mode is activated, this would be the only way to send commands to vterm.
I propose this because it should be an easy extension of what I already have in vterm-extra
..
I had another idea. This is a very minimal sketch of a new minor mode, which at the moment is called vterm-extra-line-mode
.
(defvar vterm-extra-line-mode-map nil)
(setq vterm-extra-line-mode-map (make-sparse-keymap))
(define-key vterm-extra-line-mode-map (kbd "<return>")
'vterm-extra-read-and-send)
(define-minor-mode vterm-extra-line-mode "VTermLine"
"Vterm extra line mode."
(read-only-mode -1))
(defun vterm-extra-read-and-send ()
(interactive)
(let ((command (buffer-substring-no-properties
(vterm--get-prompt-point) (vterm--get-end-of-line))))
(vterm-send-C-a)
(vterm-send-C-k)
(vterm-send-string command)
(vterm-send-return)))
With this minor mode, the buffer is turned into writable, and you can use any evil command. When you hit enter, what is on screen is sent to vterm.
There's A LOT to be polished, but I think that this may be the core idea to enable using evil in the smoothest way. The idea is to send the updated string every time there's some interaction with the term, like hitting tab.
I am going to develop this as part of vterm-extra
initially.
I had another idea. This is a very minimal sketch of a new minor mode, which at the moment is called
vterm-extra-line-mode
.(defvar vterm-extra-line-mode-map nil) (setq vterm-extra-line-mode-map (make-sparse-keymap)) (define-key vterm-extra-line-mode-map (kbd "<return>") 'vterm-extra-read-and-send) (define-minor-mode vterm-extra-line-mode "VTermLine" "Vterm extra line mode." (read-only-mode -1)) (defun vterm-extra-read-and-send () (interactive) (let ((command (buffer-substring-no-properties (vterm--get-prompt-point) (vterm--get-end-of-line)))) (vterm-send-C-a) (vterm-send-C-k) (vterm-send-string command) (vterm-send-return)))
With this minor mode, the buffer is turned into writable, and you can use any evil command. When you hit enter, what is on screen is sent to vterm.
There's A LOT to be polished, but I think that this may be the core idea to enable using evil in the smoothest way. The idea is to send the updated string every time there's some interaction with the term, like hitting tab.
I am going to develop this as part of
vterm-extra
initially.
This sounds like an ideal solution! Can you link to the branch in vterm-extra
so I can try it out when there is some done? :)
One annoyance I have is the following scenario:
- Enter insert mode, type some text
- Enter normal mode, move cursor back a bit
- Enter insert mode, start typing
When doing step 3, the cursor jumps back to the end of the line when typing. I guess vterm doesn't track the cursor in normal mode as it does in insert mode (moving in insert mode using arrow keys work fine). Using normal mode, it's possible to move the cursor out of the prompt (like
vterm-copy-mode
), and in that case it makes sense that the cursor is reset when typing. Ideally, when entering insert mode, the vterm cursor position should either be set to the current point if within the prompt, or to the last cursor position if outside it.Yes, we do not really support
evil-mode
at the moment. My understanding is that the most common way to have it with vterm is to setevil-mode
to always useemacs-mode
(in vterm buffers), then, the shell is configured with a VI emulation mode.Would someone be able to point to an example of how to set this up? I think I can figure out the "always use
emacs-mode
in vterm buffers" part, but how do I configure my shell for VI emulation? I'm using Oh My Zsh and vi-mode, which works in iTerm2, but I'm not sure how to get it to work in emacs vterm.@yosevu I have the opposite issue, could you share how you set it to always use emacs-mode in vterm buffers? Below are some links on how to setup vi emulation for your shell bash zsh
I think
evil-emacs-state-modes
can be used for this purpose. I haven't tried it, but saw it discussed in this article: Living in Emacs
This piece of code can roughly handle this problem. After insert command, just moving shell point to the current point.
(defun evil-collection-vterm-insert (count &optional vcount skip-empty-lines)
(interactive
(list (prefix-numeric-value current-prefix-arg)
(and (evil-visual-state-p)
(memq (evil-visual-type) '(line block))
(save-excursion
(let ((m (mark)))
;; go to upper-left corner temporarily so
;; `count-lines' yields accurate results
(evil-visual-rotate 'upper-left)
(prog1 (count-lines evil-visual-beginning evil-visual-end)
(set-mark m)))))
(evil-visual-state-p)))
(evil-insert count vcount skip-empty-lines)
(let ((p (point)))
(vterm-reset-cursor-point)
(while (< p (point))
(vterm-send-left)
(forward-char -1))
(while (> p (point))
(vterm-send-right)
(forward-char 1))))
(evil-collection-define-key 'normal 'vterm-mode-map "i" 'evil-collection-vterm-insert)
I don't think it's reasonable for vterm to support some vi mode keybindings for the shell. It's what the shell itself should do (bash, zsh, fish, etc. all supports some vi editing mode). It's like that it's not reasonable for iTerm2.app or urxvt to support vi mode keybindings. Vterm as a terminal emulator, does not (and should not) know anything about the content of it's program, which may not even be a shell.
vterm and shell works in two separated layers and evil works at the vterm layer. Vterm (maybe together with evil) provides raw keystroke input to shell and inspects the output of the shell.
Some good integration features between evil and vterm would be:
Some bad integration features between evil and vterm that we probably should not implement:
For these feature requirements, people should look for "vterm custom keybindings" instead of "vterm evil integration"
Hi, a solution that would work for alternative modal editing schemes, such as xah-fly-keys, would be much appreciated.
after #455 is merged, command d
c
a
I
should work with:
(defun vterm-evil-insert ()
(interactive)
(vterm-goto-char (point))
(call-interactively #'evil-insert))
(defun vterm-evil-append ()
(interactive)
(vterm-goto-char (1+ (point)))
(call-interactively #'evil-append))
(defun vterm-evil-delete ()
"Provide similar behavior as `evil-delete'."
(interactive)
(let ((inhibit-read-only t)
)
(cl-letf (((symbol-function #'delete-region) #'vterm-delete-region))
(call-interactively 'evil-delete))))
(defun vterm-evil-change ()
"Provide similar behavior as `evil-change'."
(interactive)
(let ((inhibit-read-only t))
(cl-letf (((symbol-function #'delete-region) #'vterm-delete-region))
(call-interactively 'evil-change))))
(defun my-vterm-hook()
(evil-local-mode 1)
(evil-define-key 'normal 'local "a" 'vterm-evil-append)
(evil-define-key 'normal 'local "d" 'vterm-evil-delete)
(evil-define-key 'normal 'local "i" 'vterm-evil-insert)
(evil-define-key 'normal 'local "c" 'vterm-evil-change))
(add-hook 'vterm-mode-hook 'my-vterm-hook)
EDIT: d
c
should not work when your evil
is byte compiled ,
see https://github.com/emacs-evil/evil-collection/pull/448#issuecomment-770144854
please use https://github.com/emacs-evil/evil-collection/blob/master/modes/vterm/evil-collection-vterm.el instead.
And vterm-delete-region
doesn't work for zsh user, you need put this in your .zshrc,
# bind DEL to delete-char make `vterm-send-delete` delete char
bindkey "\e[3~" delete-char
Hey, thanks for all the work.
I'm running master with evil-collection and @jixiuf 's snippets.
Some observations and problem reports:
I've added the following to my configuration and it might be useful to others.
(defun vterm-evil-append-line ()
"Provide similar behavior as `evil-append-line'."
(interactive)
(let ((inhibit-read-only t))
(vterm-end-of-line)
(vterm-evil-append)))
and then add (evil-define-key 'normal 'local "A" 'vterm-evil-append-line)
to the hook.
I've tried to define vterm-evil-insert-line
too, but I can't get vterm-beggining-of-line
to work, not even in Emacs mode.
Thanks again everyone.
@cobac I haven't gotten it working, I instead am trying to merge these changes upstream in evil-collection https://github.com/emacs-evil/evil-collection/pull/448
Note, I have a minimum test-case now where delete-region works/doesn't work. See: https://github.com/emacs-evil/evil-collection/pull/448#issuecomment-768765408
Evil mode works quite well for me in vterm.
I bound a bunch of additional emacs-libvterm functions in evil collection: https://github.com/emacs-evil/evil-collection/pull/448
And there was recently a follow-up PR which was recently merged: https://github.com/emacs-evil/evil-collection/pull/461
I'm not sure what remains to be done?
I'll post here a tip for users like me who don't need evil on the command line, but really would like to have it in copy-mode, which is also the behaviour that I use in the copy modes in tmux/alacritty. The vterm-mopy-mode-hook
is called for for both entering or exiting the mode, so I came up with the following use-package declaration:
(use-package vterm
:hook
(vterm-mode . evil-emacs-state)
(vterm-copy-mode . meliache/evil-normal-in-vterm-copy-mode)
:config
(defun meliache/evil-normal-in-vterm-copy-mode ()
(if (bound-and-true-p vterm-copy-mode)
(evil-normal-state)
(evil-emacs-state))))
I still seem to have issues when I ssh to another host from within vterm. Haven't debugged or looked into it to much yet...
I just tried out shell-mode
for the first time in a while and the evil integration there is seamless! Anyone know how it works and if the same approach could be applied to vterm? Is it because it's comint
-derived?
@mjlbach I really appreciate your evil-collection contribution -- it allowed me to switch from ZSH's vi emulation. But I think re-implementing evil operators one by one is ultimately a losing battle: we'll always be lagging behind, missing features, duplicating effort, etc, and users' customized evil bindings don't carry over. I don't have a better idea though 😞 (unless, again, we can somehow do what comint
/shell
does, which seems unlikely but idk).
Some evil-mode user use the cursor's shape and color as evil-state indicator, for example:
(setq evil-insert-state-cursor '(bar "#00FF00") evil-visual-state-cursor '(box "#FF00FF") evil-normal-state-cursor '(box "#E2E8EF"))
will set the cursor as a green bar in
insert
state; a white box innormal
state; a magenta box invisual
state.The problem with vterm is, sometimes it dose not respect the cursor shape. I don't know how to reproduce it consistently but sometimes after I leaved the vterm buffer then re-visit it, the cursor will change to bar shape while it should be a box shape.
For me this is reproducible with a simple ls command. After ls I am still in insert mode but the cursor shows normal mode. Here is a fix I found:
(use-package vterm
:config
(advice-add #'vterm--redraw :after (lambda (&rest args) (evil-refresh-cursor evil-state)))
)
I hope this is helpful to some :)
I had another idea. This is a very minimal sketch of a new minor mode, which at the moment is called
vterm-extra-line-mode
.(defvar vterm-extra-line-mode-map nil) (setq vterm-extra-line-mode-map (make-sparse-keymap)) (define-key vterm-extra-line-mode-map (kbd "<return>") 'vterm-extra-read-and-send) (define-minor-mode vterm-extra-line-mode "VTermLine" "Vterm extra line mode." (read-only-mode -1)) (defun vterm-extra-read-and-send () (interactive) (let ((command (buffer-substring-no-properties (vterm--get-prompt-point) (vterm--get-end-of-line)))) (vterm-send-C-a) (vterm-send-C-k) (vterm-send-string command) (vterm-send-return)))
With this minor mode, the buffer is turned into writable, and you can use any evil command. When you hit enter, what is on screen is sent to vterm.
There's A LOT to be polished, but I think that this may be the core idea to enable using evil in the smoothest way. The idea is to send the updated string every time there's some interaction with the term, like hitting tab.
I am going to develop this as part of
vterm-extra
initially.
Can anyone comment on this? Sounds promising!
I'm curious how it would compare to term
's term-line-mode
. As I recall term-line-mode
works pretty well with evil, but not great. I'm fuzzy on the details though as it's been a while since I used term
and for some reason it's crashing when I try to run it right now.
(vterm-goto-char (point))
was an easy solution for fixing the pointer location after moving with a command mode (evil/boon/fly-keys) which is the most annoying one
For those of us who don't want vterm ever messing with our cursor, we can use dynamic binding to prevent set_cursor_type
from changing the cursor:
(advice-add #'vterm--redraw :around (lambda (fun &rest args) (let ((cursor-type cursor-type)) (apply fun args))))
Idea courtesy of /u/wasamasa on the emacs subreddit.
This should be cheaper than tiku91's work around.
Where do I put this?
For those of us who don't want vterm ever messing with our cursor, we can use dynamic binding to prevent
set_cursor_type
from changing the cursor:(advice-add #'vterm--redraw :around (lambda (fun &rest args) (let ((cursor-type cursor-type)) (apply fun args))))
Idea courtesy of /u/wasamasa on the emacs subreddit.
This should be cheaper than tiku91's work around.
@luveti Thank you! It was a huge issue for me 🙏 Could you elaborate on why it's cheaper than tiku91's workaround.
(vterm-goto-char (point))
was an easy solution for fixing the pointer location after moving with a command mode (evil/boon/fly-keys) which is the most annoying one
(defadvice! +vterm-update-cursor (orig-fn &rest args) :before #'vterm-send-key (vterm-goto-char (point)))
@chaoky
(defadvice! +vterm-update-cursor (orig-fn &rest args) :before #'vterm-send-key (vterm-goto-char (point)))
I don't have defadvice!
, but I assume the nadvice.el
version of that would be
(define-advice vterm-send-key
(:before (orig-fn &rest args) +vterm-update-cursor)
(vterm-goto-char (point)))
Hello everyone,
Using a vanilla Emacs 28.1 configuration with only evil
, evil-collection
and vterm
installed, I don't seem to be able to insert
properly. This is what happens:
M-x vterm
insert-state
is entered automatically.i
.Backspace
, everything I typed in 3. suddenly gets displayed, with the point at the end of the line, as expected.RET
.I have the same issue under Doom Emacs, and have had it for as long as I can remember.
Has anyone experienced that?
Thanks a lot!
(let ((cursor-type cursor-type)) (apply fun args))
yep ty, I forgot that's a macro from doom
you can also add an advice for evil
/flykeys
/boon
insert command like
(defadvice! +vterm-update-cursor-boon (orig-fn &rest args) :before #'boon-insert (vterm-goto-char (point)))
this could also be buffer local to vterm
Many people use
evil-mode
, but unfortunately, I know almost nothing about it. It would be great to collect known problems/workarounds regarding vterm+evil and add them to the README. Help (PRs) would greatly be appreciated in this respect.In general, it would also be useful to know what vterm can do to support
evil-mode
better.Thanks