2

This happens on the Emacs splash page primarily. I can move back to the end of the previous line with M-b but cannot move onto the beginning of the next with M-f.

As an experiment, I'm going through and replacing some vim emulation commands in evil-mode with their vanilla emacs equivalents.

(setq package-archives 
      '(("melpa" . "http://melpa.milkbox.net/packages/")
        ("gnu" . "http://elpa.gnu.org/packages/")))

(require 'package)
(package-initialize)

(require 'evil)
(evil-mode +1)

;; experiment with rebinding the normal state keys.
(define-key evil-normal-state-map (kbd "w") #'forward-word)
(define-key evil-normal-state-map (kbd "b") #'backward-word)
(define-key evil-normal-state-map (kbd "W") #'forward-sexp)
(define-key evil-normal-state-map (kbd "B") #'backward-sexp)

I noticed that M-f and M-b (and w and b) no longer move onto the next line and I'm wondering why that is. The help text for M-f seems to suggest that the value of inhibit-field-text-motion may play a role, but it's nil regardless of whether evil-mode is enabled.

M-f runs the command forward-word, which is an interactive built-in
function in `syntax.c'.

It is bound to w, M-f, ESC <right>.

(forward-word &optional ARG)

Move point forward ARG words (backward if ARG is negative).
If ARG is omitted or nil, move point forward one word.
Normally returns t.
If an edge of the buffer or a field boundary is reached, point is left there
and the function returns nil.  Field boundaries are not noticed if
`inhibit-field-text-motion' is non-nil.

Still confused, I checked the source code to see how forward-word is actually implemented and to see what variable or bit of emacs state might be changing to influence the behavior of forward-word. The source code is here https://github.com/emacs-mirror/emacs/blob/c8874e2113221a08252113b6d46ecc7066c62c8c/src/syntax.c (reproduced below for convenience).

DEFUN ("forward-word", Fforward_word, Sforward_word, 0, 1, "^p",
       doc: /* Move point forward ARG words (backward if ARG is negative).
If ARG is omitted or nil, move point forward one word.
Normally returns t.
If an edge of the buffer or a field boundary is reached, point is
left there and the function returns nil.  Field boundaries are not
noticed if `inhibit-field-text-motion' is non-nil.
The word boundaries are normally determined by the buffer's syntax
table, but `find-word-boundary-function-table', such as set up
by `subword-mode', can change that.  If a Lisp program needs to
move by words determined strictly by the syntax table, it should
use `forward-word-strictly' instead.  */)
  (Lisp_Object arg)
{
  Lisp_Object tmp;
  ptrdiff_t orig_val, val;

  if (NILP (arg))
    XSETFASTINT (arg, 1);
  else
    CHECK_NUMBER (arg);

  val = orig_val = scan_words (PT, XINT (arg));
  if (! orig_val)
    val = XINT (arg) > 0 ? ZV : BEGV;

  /* Avoid jumping out of an input field.  */
  tmp = Fconstrain_to_field (make_number (val), make_number (PT),
                 Qnil, Qnil, Qnil);
  val = XFASTINT (tmp);

  SET_PT (val);
  return val == orig_val ? Qt : Qnil;
}

So it looks like the logic that could be making the behavior of foward-word differ in evil normal state and vanilla emacs must be contained within scan-words (https://github.com/emacs-mirror/emacs/blob/c8874e2113221a08252113b6d46ecc7066c62c8c/src/syntax.c#L1417). This function is really long so I won't paste it here.

I'm wondering how exactly evil-mode is changing the behavior of forward-word and how to prevent it from doing that? It seems unlikely that messing with the syntax tables would enable or disable line-wrapping for forward-word, but I'm really not sure.

1 Answer 1

1

Evil prevents the cursor from moving to the last position in a line when in normal mode, which causes the cursor to be placed inside of the last word on the line instead of after it. This makes forward-word think it needs to move to the end of the line, but because it can't, it doesn't move at all.

To fix this, set evil-move-beyond-eol to t, which will allow the cursor to move to the final position on the line.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.