Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vterm: bypass line wraps in the prompt line #717

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 48 additions & 4 deletions modes/vterm/evil-collection-vterm.el
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@

(defvar vterm--process)

(defcustom evil-collection-vterm-prompt-line-continuation t
"Make movements within prompt behave like it was one line.
This option becomes relevant when the command in prompt is so long that it wraps
to multiple lines. If the value is `t', movements such as `h', `l', `^', `$',
etc allows to move between lines (like it would be in any other terminal
emulator outside of Emacs or in Vterm without Evil)."
:type 'boolean
:group 'vterm)

(defun evil-collection-vterm-escape-stay ()
"Go back to normal state but don't move cursor backwards.
Moving cursor backwards is the default vim behavior but
Expand Down Expand Up @@ -74,10 +83,18 @@ also uses `evil-mode'."
"Move the cursor to the first non-blank character
after the prompt."
:type exclusive
(if (vterm-cursor-in-command-buffer-p (point))
(if (and evil-collection-vterm-prompt-line-continuation
(vterm-cursor-in-command-buffer-p (point)))
(vterm-beginning-of-line)
(evil-first-non-blank)))

(evil-define-motion evil-collection-vterm-end-of-line (count)
"Move the cursor to the end of the current line."
:type inclusive
(if evil-collection-vterm-prompt-line-continuation
(vterm-end-of-line)
(evil-end-of-line count)))

(defun evil-collection-vterm-insert ()
"Insert character before cursor."
(interactive)
Expand Down Expand Up @@ -223,6 +240,28 @@ But don't allow the cursor to move bellow the last prompt line."
(when (> (count-words (point) (point-max)) 0)
(evil-next-line count)))

(evil-define-motion evil-collection-vterm-forward-char
(count &optional crosslines noerror)
"Move cursor to the right by COUNT characters, bypassing line wraps."
:type exclusive
(if (and evil-collection-vterm-prompt-line-continuation
(get-text-property (1+ (point)) 'vterm-line-wrap))
(forward-char 2)
(evil-forward-char count crosslines noerror)))

(evil-define-motion evil-collection-vterm-backward-char
(count &optional crosslines noerror)
"Move cursor to the left by COUNT characters, bypassing line wraps."
:type exclusive
;; Check if one character to the left is a vterm's line wrap.
;; The `bobp' part is a special case for the first row and first character
;; of the buffer - `evil-backward-char' would throw an error otherwise.
(if (and evil-collection-vterm-prompt-line-continuation
(get-text-property (1- (point)) 'vterm-line-wrap)
(not (bobp)))
(forward-char -1)
(evil-backward-char count crosslines noerror)))

;;;###autoload
(defun evil-collection-vterm-setup ()
"Set up `evil' bindings for `vterm'."
Expand Down Expand Up @@ -265,12 +304,10 @@ But don't allow the cursor to move bellow the last prompt line."
"P" 'vterm-yank
"a" 'evil-collection-vterm-append
"A" 'evil-collection-vterm-append-line
"d" 'evil-collection-vterm-delete
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we removing this line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it from

  (evil-collection-define-key 'normal 'vterm-mode-map

to

  (evil-collection-define-key '(normal visual) 'vterm-mode-map

since I was creating this section, and it makes sense for d to work in visual mode as well.

"D" 'evil-collection-vterm-delete-line
"x" 'evil-collection-vterm-delete-char
"X" 'evil-collection-vterm-delete-backward-char
(kbd "RET") 'vterm-send-return
"^" 'evil-collection-vterm-first-non-blank
"i" 'evil-collection-vterm-insert
"I" 'evil-collection-vterm-insert-line
"u" 'vterm-undo
Expand All @@ -282,8 +319,15 @@ But don't allow the cursor to move bellow the last prompt line."
"G" 'vterm-reset-cursor-point)

(evil-collection-define-key 'visual 'vterm-mode-map
"x" 'evil-collection-vterm-delete-backward-char)

(evil-collection-define-key '(normal visual) 'vterm-mode-map
"d" 'evil-collection-vterm-delete
"x" 'evil-collection-vterm-delete-backward-char))
"l" 'evil-collection-vterm-forward-char
"h" 'evil-collection-vterm-backward-char
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last thing, can you add a flag (can default to true), to conditionally enable this.

Something like:

if flag:
bind l h $ ^ to -> new feature
else:
bind ^ (whatever other key needs to be deleted from thsi CL)

This cl is moving some lines to other parts so hard to tell what's missing/gained easily. (Not taking too close a look)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, that sounds like a good idea. Please take a look.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should create 2 separate flags (one for ^ $ and one for h l) and then check the flags only in evil-collection-vterm-setup to conditionally bind the functions.

One use case I'm thinking (which is one I'd be using) is to only bind this for h & l movements but keep ^ and $ movements alone.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should create 2 separate flags (one for ^ $ and one for h l)
One use case I'm thinking (which is one I'd be using) is to only bind this for h & l movements but keep ^ and $ movements alone.

It doesn't really make sense to me, separating the configuration into two options. In my case, I either want the prompt to behave like one long line or not :-). That being said, if you are interested in having this behavior just for h, k and not ^, $, maybe others will as well. So sure, no problem with me. Do you have any preference for the option names?

check the flags only in evil-collection-vterm-setup to conditionally bind the functions.

I am trying to find some other key bind that is done this way but not seeing any. Have you seen this approach somewhere else in evil-collection? I'd like to be consistent with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump @jojojames

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(if evil-collection-elpaca-want-u-unmark

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't be as easy as we thought. Or at least as I thought.

We would have to define two variants for every movement. I am proposing hj^$ in this PR but I forgot X, 0, operations till the end of the line like C, S, D, Y, jumps like t<char>, T<char>, or line operations like yy, dd, and whatever else. That would be too many vterm specific key binds. But more importantly too many key binds for this line-continuation feature. Imagine how much would the number of key binds blow up if we want to add some other feature with conditional keybinds. There must be a smarter way of doing this but I am struggling to find it.

I am playing with overriding something like evil-line-expand but without much success. It may be a dead end as well.

You have much more experience with Evil than me, do you have any idea @jojojames, please?

"$" 'evil-collection-vterm-end-of-line
"^" 'evil-collection-vterm-first-non-blank))


(provide 'evil-collection-vterm)
;;; evil-collection-vterm.el ends here