emacs-evil / evil

The extensible vi layer for Emacs.
GNU General Public License v3.0
3.33k stars 281 forks source link

diw kills above line's line ending #834

Closed ninrod closed 2 years ago

ninrod commented 7 years ago

Issue type

Environment

Emacs version: GNU Emacs 25.2.1 (x86_64-apple-darwin16.4.0, NS appkit-1504.81 Version 10.12.3 (Build 16D32)) of 2017-03-11

Operating System: macOS Sierra.

Evil version: 1.2.12 Evil installation type: MELPA through use package. Graphical/Terminal: Graphical Terminal multiplexer: does not apply.

Reproduction steps

Expected behavior

the buffer should now display:

foo
bar

Actual behavior

the buffer instead displays:

foobar

Further notes

vim behaves as expected. emacs eats the above line's line ending.

ninrod commented 7 years ago

Hi Folks. I'd really like to work on this even if I'm a lisp total begginer.

I'm trying to pinpoint the snippet I'd have to work on to write the fix, so here are my thoughts:

My first reaction was to look for the definition of the iw text-object which I've found here. Immediately I'm greeted with the symbol evil-word. So I M-x ag it and find nothing. C-h v and C-h f does not seem to help either.

As the definition of evil-word symbol is nowhere to be found on the code, which is weird, I'm really confused because the definition for evil-select-inner-object says that the first parameter, thing, which is evil-word, would be the anything understood by thing-at-point, which, C-h f tells me are:

Possibilities include `symbol', `list', `sexp', `defun',
`filename', `url', `email', `word', `sentence', `whitespace',
`line', `number', and `page'.

but there's no evil-word. How does evil even knows that there's an evil-word somewhere?

@edkolev @wasamasa @justbur, can you guys give me some pointers?

thanks in advance

wasamasa commented 7 years ago

The next step from here is finding out how new types for thingatpt are registered:

;; This file provides routines for getting the "thing" at the location of
;; point, whatever that "thing" happens to be.  The "thing" is defined by
;; its beginning and end positions in the buffer.
;;
;; The function bounds-of-thing-at-point finds the beginning and end
;; positions by moving first forward to the end of the "thing", and then
;; backwards to the beginning.  By default, it uses the corresponding
;; forward-"thing" operator (eg. forward-word, forward-line).
edkolev commented 7 years ago

@edkolev @wasamasa @justbur, can you guys give me some pointers?

Sure, here's a couple of tips:

justbur commented 7 years ago

A couple of more tips

There is a lot of evil-specific machinery in the evil repository, and unfortunately it takes some work to figure out how it all works together. The comments are helpful, but you have to read some code too.

ninrod commented 7 years ago

thanks guys!

ninrod commented 7 years ago

Ok, so I discovered that if I suppress the \n here, then it works as intended, except, as @edkolev has already mentioned, w does not jump over lines anymore. So my next thought is to duplicate the forward-evil-word definition and call it forward-evil-inner-word. It's the exact same function, but without the \n.

So I do that, and in here I change the inner-word text object definition to use my new forward function. All seems good. I restart emacs.

And it seems that I've done nothing. In fact, I even instrument the two forward functions, forward-evil-world and foward-evil-inner-word, and when I press diw only the foward-evil-world function gets debugged, which is all sorts of weird.

Is there some sort of cache thing going on? I find it very strange because if I go to the forward-evil-word function and pull out the \n, then it works.

Seems that some kind of cache is going on. Is that even possible?

here's how I bootstrap evil:

(use-package evil
    :load-path "lisp/emacs-evil/evil"
    :init
    (use-package goto-chg
      :ensure t)
    (use-package undo-tree
      :ensure t)
    :config
    (setcdr evil-insert-state-map nil) ;; emacsify insert state: http://stackoverflow.com/a/26573722/4921402
    (define-key evil-insert-state-map [escape] 'evil-normal-state);; but [escape] should switch back to normal state, obviously.
    (fset 'evil-visual-update-x-selection 'ignore);; Amazing hack lifted from: http://emacs.stackexchange.com/a/15054/12585

    (evil-mode)

    (evil-define-text-object ninrod/textobj-entire (count &optional beg end type)
      (evil-range (point-min) (point-max)))
    (define-key evil-outer-text-objects-map "e" 'ninrod/textobj-entire));; simulation of kana's textobj-entire

ps: lisp/emacs-evil/evil is just this repo git cloned.

thanks in advance for any help.

justbur commented 7 years ago

So my next thought is to duplicate the forward-evil-word definition and call it forward-evil-inner-word. It's the exact same function, but without the \n.

Seems reasonable to me.

Seems that some kind of cache is going on. Is that even possible?

Check if you have .elc files in the "lisp/emacs-evil/evil" directory. Emacs will prefer loading that.

ninrod commented 7 years ago

@justbur, there was no .elc file in that dir, but I just searched my ~/.emacs.d, and sure enough:

emacs.d ❯ w
 ~/.emacs.d at ninrod@ninbook using -zsh ❯
.emacs.d ❯ find . -name '*.elc' | ag evil | wc -l
60
.emacs.d ❯

among those 60 results:

./elpa/evil-20170512.1253/evil-command-window.elc
./elpa/evil-20170512.1253/evil-commands.elc
./elpa/evil-20170512.1253/evil-common.elc
./elpa/evil-20170512.1253/evil-core.elc
./elpa/evil-20170512.1253/evil-digraphs.elc
./elpa/evil-20170512.1253/evil-ex.elc
./elpa/evil-20170512.1253/evil-integration.elc
./elpa/evil-20170512.1253/evil-jumps.elc
./elpa/evil-20170512.1253/evil-macros.elc
./elpa/evil-20170512.1253/evil-maps.elc
./elpa/evil-20170512.1253/evil-repeat.elc
./elpa/evil-20170512.1253/evil-search.elc
./elpa/evil-20170512.1253/evil-states.elc
./elpa/evil-20170512.1253/evil-types.elc
./elpa/evil-20170512.1253/evil-vars.elc
./elpa/evil-20170512.1253/evil.elc
ninrod commented 7 years ago

but that is not the cause. I went ahead and deleted the elc files and restarted emacs. issue continues.

Also, I verified that if I create a new inner object with a different name, say, evil-inner-spaces, and bind that to, say, s, and press dis, then it works.

seems that diw is selecting forward-evil-word despite of what might be implemented in the evil-inner-word definition function.

wasamasa commented 7 years ago

From some cursory testing in Vim and Emacs, the issue appears to be that in Vim, the movement to figure out the bounds of that text object seem to be constrained to the current line. In Emacs they aren't. To prove this, extend the example by adding more whitespace lines between foo and bar.

I'd personally never caught that one because I'd delete whitespace with 0dw.

edkolev commented 7 years ago

@ninrod you can run counsel-find-symbol to go to the definition of the symbol under point. If you don't use counsel, there's probably another way to do this, with xref-find-definitions maybe.

This approach should be able to take you to the function emacs is using, rather than the function you think emacs is using.

ninrod commented 7 years ago

I'd personally never caught that one because I'd delete whitespace with 0dw.

@wasamasa yes! I have just discovered this combination while trying to fix this. At this point, I'm just trying to fix this for the evil learning value.

ninrod commented 7 years ago

@ninrod you can run counsel-find-symbol to go to the definition of the symbol under point.

@edkolev ok. but what symbol should be under point, in my case? I don't think I follow.

edkolev commented 7 years ago

Sorry, I wasn't clear enough - with your cursor on forward-evil-inner-word, counsel-find-symbol should take you to its definition - you'll be able to see if it's defined where you expect it to be (the evil git repo where you made your changes, or the .emacs.d/elpa/evil-123 dir, or someplace else).

ninrod commented 7 years ago

@edkolev, right. But the forward-evil-inner-word symbol is a function that I wrote in the git cloned repo. You are actually reffering to forward-evil-word, right?

So you are saying that I could write forward-evil-word in the scratch buffer and counsel-find-symbol it, is that correct?

edkolev commented 7 years ago

Correct :)