Doom-emacs: Evil-mode substitute (find-replace) wrong number of occurrences with/without global flag

Created on 3 Jul 2020  ·  6Comments  ·  Source: hlissner/doom-emacs

What did you expect to happen?

By default, the ":s" command changes only the first occurrence on each line. To change every occurrence on the line, you need to add the g (global) flag.

Documentation: vimdoc - substitution

What actually happened?

The ":s" command changes every occurrence on the line by default, and changes only one occurrence on the line with the global flag.

Additional details:

  • Screenshot without global flag
    evil-sub-without-g

  • Screenshot with global flag
    evil-sub-with-g

  • The "vanilla" evil mode doesn't suffer from this bug.
    vanilla-evil-sub

Steps to reproduce:

  1. Copy paste the following example into a buffer
foo bar foo foo bar
foo bar bar bar foo
bar foo foo
  1. Type ":%s/foo/fubar/", and press the enter.
  2. All occurrences of "foo" are now replaced by "fubar".
  3. Undo the change (press u)
  4. Type ":%s/foo/fubar/g", and press the enter.
  5. Only the first occurrence of "foo" on each line are now replaced by "fubar".

System information:

emacs   version    26.3
        features   XPM JPEG TIFF GIF PNG RSVG IMAGEMAGICK SOUND DBUS GSETTINGS GLIB NOTIFY ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT LIBOTF XFT ZLIB TOOLKIT_SCROLL_BARS GTK3 X11 XDBE XIM MODULES THREADS XWIDGETS LCMS2
        build      Dec 11, 2019
        buildopts  (--build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu --program-prefix= --disable-dependency-tracking --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib64 --libexecdir=/usr/libexec --localstatedir=/var --sharedstatedir=/var/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-dbus --with-gif --with-jpeg --with-png --with-rsvg --with-tiff --with-xft --with-xpm --with-x-toolkit=gtk3 --with-gpm=no --with-xwidgets --with-modules build_alias=x86_64-redhat-linux-gnu host_alias=x86_64-redhat-linux-gnu 'CFLAGS=-DMAIL_USE_LOCKF -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' LDFLAGS=-Wl,-z,relro PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig)
        windowsys  x
        daemonp    server-running
doom    version    2.0.9
        build      HEAD -> develop 46d6d0b58 2020-06-29 15:12:30 -0400
        dir        ~/.doom.d/
system  type       gnu/linux
        config     x86_64-redhat-linux-gnu
        shell      /usr/bin/zsh
        uname      Linux 5.6.18-200.fc31.x86_64 #1 SMP Wed Jun 10 22:18:55 UTC 2020 x86_64
        path       (~/.emacs.d/bin/../bin ~/.sdkman/candidates/scala/current/bin ~/.sdkman/candidates/sbt/current/bin ~/.sdkman/candidates/java/current/bin ~/kde/src/kdesrc-build ~/.plenv/shims /home/linuxbrew/.linuxbrew/Cellar/guile/3.0.2/bin ~/.cargo/bin ~/.cargo/bin /usr/local/bin /usr/bin /bin ~/bin /usr/local/sbin /usr/sbin ~/.composer/vendor/bin ~/.cargo/bin ~/go/bin ~/.plenv/bin ~/Applications/bin /home/linuxbrew/.linuxbrew/bin /home/linuxbrew/.linuxbrew/sbin ~/.emacs.d/bin /usr/libexec/emacs/26.3/x86_64-redhat-linux-gnu/)
config  envfile    envvar-file
        elc-files  0
        modules    (:input japanese :completion company ivy :ui doom doom-dashboard doom-quit hl-todo indent-guides modeline nav-flash ophints (popup +all +defaults) treemacs vc-gutter vi-tilde-fringe window-select workspaces zen :editor (evil +everywhere) file-templates fold (format +onsave) multiple-cursors rotate-text snippets :emacs dired electric ibuffer vc :term eshell shell :checkers syntax :tools (eval +overlay) (lookup +docsets) lsp magit :lang cc data emacs-lisp kotlin latex lua markdown (org +dragndrop +present) raku php qt scala scheme sh :config (default +bindings +smartparens))
        packages   ((dired-subtree) (dired-narrow) (lex) (bison-mode) (sbt-mode) (lsp-metals) (lsp-treemacs) (company-lsp) (yasnippet) (posframe))
        unpin      (n/a)
        elpa       (lex bison-mode)

new defaults resolved

Most helpful comment

I always type %s/<find>/<replace>/g when I want to replace every occurrence on a line. That's where false expectation happens, at least for me and @sarna . This bug report exists because we didn't know global flag can be set by default, and we didn't realize it's a customization problem.

My suggestion is to keep the evil-mode close to vim as much as possible by default, and let users to put their customization inside config.el.

If most of the doom-emacs users (I doubt) really think global flag should be set by default, it can still come with doom-emacs installation, but it should be put in a dedicated section inside config.el. In alternative to config.el, vimrc.el can be another feasible solution. The point is to make customization obvious, so people does not have false expectations and think there're bugs.

All 6 comments

The very same thing happened to me some time ago, I thought it was just how Emacs handles things. It’s really confusing when you first see it.

This is a setting that can be customized, set here in the evil module.

This is a setting that can be customized, set here in the evil module.

Is there any reason the flag is set to true by default? I'm sure that's against the habit of vim users.

I'm guessing most of the time you want to replace every occurrence of a word ? (When doing renaming)

I always type %s/<find>/<replace>/g when I want to replace every occurrence on a line. That's where false expectation happens, at least for me and @sarna . This bug report exists because we didn't know global flag can be set by default, and we didn't realize it's a customization problem.

My suggestion is to keep the evil-mode close to vim as much as possible by default, and let users to put their customization inside config.el.

If most of the doom-emacs users (I doubt) really think global flag should be set by default, it can still come with doom-emacs installation, but it should be put in a dedicated section inside config.el. In alternative to config.el, vimrc.el can be another feasible solution. The point is to make customization obvious, so people does not have false expectations and think there're bugs.

Is there any reason the flag is set to true by default?

It's an artifact from Doom's pre-distro days. I think global-by-default is the more common use case, but it certainly betray's the vim default. I've reverted it in 1a6f508.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

governorgoat picture governorgoat  ·  3Comments

Ptival picture Ptival  ·  3Comments

luisenrike picture luisenrike  ·  3Comments

rgrinberg picture rgrinberg  ·  3Comments

ashiklom picture ashiklom  ·  3Comments