emacs-evil / evil

The extensible vi layer for Emacs.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to reliably check if at the beginning of the line in Evil visual state?

hubisan opened this issue · comments

Issue type

  • Question

Environment

Emacs version: 30.0.50 and 29.2
Operating System:
Evil version: 1.15
Evil installation type: With Straight
Graphical/Terminal: Graphical
Tested in a make emacs session (see CONTRIBUTING.md): No (but with emacs -q)

Reproduction steps

  • Place the cursor at the beginning of a line in normal state.
  • Evaluate (bolp) (Return t if point is at the beginning of a line).
  • It returns t.
  • Switch to visual state.
  • Evaluate (bolp)
  • It returns nil.

Expected behavior

  • Expected (bolp) to return t after switching to visual state.

Actual behavior

  • It returns nil instead.

Question

  • How can I reliably check if I'm at the beginning of a line even in that case?
  • Am I doing something wrong?
  • Is there maybe a variable I can configure to change this behaviour?

Further notes

  • After switching to visual (point) is increased by 1
  • If I switch to visual state when I am not at the beginning of the line and then move to the beginning of the line with 0, bolp correctly returns t. So, this is only a problem when the cursor is at the beginning of the line when entering visual state and the marked region is only the first character..

For the time being I am using an advice to get around this edge case (answer to question on stackexchange, slightly modified):

  (defun my-feat-evil/bolp-fix (orig-fn)
    "Fix `bolp' sometimes not returning `t' if in Evil visual state.
If only the first character of a line is marked, else it works."
    (save-excursion
      (when (and (eq evil-state 'visual)
                 (= (- (region-end) (region-beginning)) 1)
                 (= (line-beginning-position) (- (point) 1)))
        (backward-char))
      (funcall orig-fn)))
  (advice-add 'bolp :around #'my-feat-evil/bolp-fix)

I understand the problem now. Without evil-mode setting the mark doesn't mark the first character, one has to move forward one char to do so. Evil automatically marks the first character to copy the behaviour of vim. So it moves forward by one character when switching to visual state. Unfortunately this is not so clear for the user when using evil-mode as the cursor only switches the color and doesn't seem to move.

While in Visual(-line) state before each command, the point&mark are temporarily adjusted such that delete-region etc. work as expected. The original values are stored in evil-visual-point and evil-visual-mark. So you could do e.g.

M-: (save-excursion (goto-char evil-visual-point) (bolp)) RET

If I switch to visual state when I am not at the beginning of the line and then move to the beginning of the line with 0, bolp correctly returns t.

This is a question of whether the point or the mark is at BOL.

Edit

Unfortunately this function causes the face of the keyword in org-mode to change incorrectly when using org-metaright if in visual state. With multiple selected lines, it even breaks apart entire headings.

-> Using the previous function from above, as it doesn't have these issues.


Thanks.

I changed my code to:

(defun my-feat-evil/bolp-fix (orig-fn)
  "Fix `bolp' not returning `t' if in Evil visual state.
This occurs when only the first character is marked."
  (save-excursion
    (when (eq evil-state 'visual)
      (goto-char evil-visual-point))
    (funcall orig-fn)))

(advice-add 'bolp :around #'my-feat-evil/bolp-fix)