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

[RFC] Incsub 4 (renamed to 'inccommand') #5561

Merged
merged 16 commits into from Nov 9, 2016

Conversation

Projects
None yet
10 participants
@justinmk
Member

justinmk commented Nov 3, 2016

  • rename to 'inccommand'
  • back out special cases in do_ecmd() and buflist_new()
  • reduce shared/global state
  • preserve b:changedtick #5561 (comment)
  • add tests for feedkeys(':%s/foo/bar/'), feedkeys(":%s/foo/bar/\<CR>"), ...
    • check KeyTyped to avoid preview-mode during feedkeys()
  • should preview split appear if :{range} is in the viewport? (answer: yes, be predictable)
  • disable 'cursorline', 'spell' in preview window
  • set buffer name to [Preview] instead of [inc_sub]
  • change [lnum] display to |lnum| (like quickfix window)
  • highlight/multiline bug #7231 #5226 (comment)
  • re-use window id for preview buffer (:h win_getid())
    • best approach here would be to keep the window open and close it when command ends
  • should NOT change 'modified' (punting this for now; too risky)
  • ctrl-p/ctrl-n/up/down in : should not trigger 'inccommand' until user edits the command
    • going to wait for feedback before doing this

Renamed 'incsubstitute' to 'inccommand'

So that we can expand it to other commands besides :substitute without adding new options (that was already implied in the implementation, re eap->is_live).

Future considerations

  • block RPCs/events during incremental/live preview (eap->is_live)?
    • the buffer is in a weird state during the preview, don't want plugins interacting with it
  • instead of u_undo_and_forget(), it might be more robust to create a special/dummy buffer and throw it away
    • crazy talk: to show live previews of multi-buffer commands like :argdo, :cdo, overlay a new, temporary instance of nvim?

KillTheMule added some commits Aug 12, 2016

Incsubsitution feature
Originally implemented by

* Clement0
* DesbyP
* aym7
* Adrey06
* Robinhola

in #4811. Major reworkings and bug
fixes by

* bfredl

Most tests suggested by ZyX-l, suggestions for improvements by oni-link.

@marvim marvim added the WIP label Nov 3, 2016

@justinmk justinmk force-pushed the justinmk:incsub branch 2 times, most recently from 135721d to b65f169 Nov 3, 2016

} else { // create new
(void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);
}
(void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);

This comment has been minimized.

@justinmk

justinmk Nov 5, 2016

Member

This seems to work fine when combined with setlocal bufhidden=hide to prevent unloading the buffer.

The switch_to_win_for_buf() approach caused a double-free and other invalid access pain arising from some unknown interaction where the fragile order-of-operations for buffer creation/re-use falls apart.

emsg_off--;
if (save_changedtick != curbuf->b_changedtick
&& !u_undo_and_forget(1)) {

This comment has been minimized.

@justinmk

justinmk Nov 5, 2016

Member

u_undo_and_forget() does not restore b:changedtick, which is used by some plugins like repeat.vim. @bfredl @KillTheMule should we restore it in u_undo_and_forget() or would it not be appropriate there?

This comment has been minimized.

@bfredl

bfredl Nov 5, 2016

Member

No, undo_and_forget should work in a branch that's not the latest, and so can't manage changedtick. ex_substitute should restore it.

@justinmk

This comment has been minimized.

Member

justinmk commented Nov 5, 2016

Only 2 tests failing, and valgrind seems OK.

@justinmk justinmk force-pushed the justinmk:incsub branch from b65f169 to b12400e Nov 5, 2016

@justinmk justinmk changed the title from [WIP] Incsub 4 to [RFC] Incsub 4 Nov 5, 2016

@marvim marvim added RFC and removed WIP labels Nov 5, 2016

@justinmk justinmk force-pushed the justinmk:incsub branch 3 times, most recently from e009c26 to 7ccb428 Nov 6, 2016

@KillTheMule

This comment has been minimized.

Contributor

KillTheMule commented Nov 6, 2016

add tests for feedkeys(':%s/foo/bar/'), feedkeys(":%s/foo/bar/"), ...

If you could elaborate on this (I'm not sure what you mean), I could see if I can write them.

@justinmk

This comment has been minimized.

Member

justinmk commented Nov 6, 2016

@KillTheMule Generally, to verify that "live" substitution (or any "live" handling in general) should not be invoked during anything except actual interactive : use.

@KillTheMule

This comment has been minimized.

Contributor

KillTheMule commented Nov 6, 2016

Ok we have some basics: 561c1e3#diff-4dbe255ebfc94f6664c66ffeab750809R83

You mean along the lines of 561c1e3#diff-4dbe255ebfc94f6664c66ffeab750809R818, just with incsubstute=''? Note sure what to do about any "live" handling in general though.

@justinmk

This comment has been minimized.

Member

justinmk commented Nov 6, 2016

Ok we have some basics: 561c1e3#diff-4dbe255ebfc94f6664c66ffeab750809R83

Confusingly, the helpers.feed() method is not equivalent to VimL feedkeys(). helpers.feed() simulates actual user input. Whereas I would like to verify that if plugins call :substitute or feedkeys(':s...'), incsub should not be invoked. Easy way to verify this is to check if the incsub buffer exists after either of those scenarios. (With this PR, the incsub buffer hangs around as an unlisted buffer.)

@justinmk justinmk force-pushed the justinmk:incsub branch from 0b3d25c to 45e7812 Nov 6, 2016

@justinmk

This comment has been minimized.

Member

justinmk commented Nov 6, 2016

Woo, ASAN looks good. Going to wrap this up now.

@justinmk justinmk force-pushed the justinmk:incsub branch 3 times, most recently from 33d93bd to 2fa9778 Nov 6, 2016

@KillTheMule

This comment has been minimized.

Contributor

KillTheMule commented Nov 6, 2016

highlight bug #5226 (comment)

Note that this is a highlighting bug for single-line substitutions containing escaped chars, but makes the whole thing totally break down with multiline matches.

@justinmk

This comment has been minimized.

Member

justinmk commented Nov 6, 2016

Damn, that's disappointing. I would guess that multiline searches aren't common for many users, but it's still a bad bug.

update: Multiline matches seem to work mostly ok, actually.

@KillTheMule

This comment has been minimized.

Contributor

KillTheMule commented Nov 6, 2016

It still works as a substitution, just the preview is borked :) But it also means the data structure needs to be reworked, because right now it can only save one line that contains the whole match.

end
end)
it('work then mappings move the cursor', function()

This comment has been minimized.

@KillTheMule

KillTheMule Nov 6, 2016

Contributor

Small typo there: then -> when

@justinmk justinmk force-pushed the justinmk:incsub branch from ab76b6b to f70c402 Nov 6, 2016

KillTheMule and others added some commits Nov 6, 2016

'inccommand': preserve 'modified'
During the live preview, the buffer-local 'modified' flag
should not be changed.
perf: do_sub(): avoid work, avoid screen updates
- Don't fill matched_lines if not showing a preview (!eap->is_live).
- Encapsulate: Move cursor placement logic to show_sub().
'inccommand': Preserve curbuf->b_u_newhead.
Add tests for undotree().

Helped-by: Björn Linse <bjorn.linse@gmail.com>

When "curhead" points to a valid head, the value of "newhead" is
meaningless (and really should be set to null). The undo state for
a buffer is _logically_ the enum:

  enum UndoState {
    CurrentHead(head),
    NewHead(head),
    EmptyTree
  }

nvim _represents_ this as: whenever `curbuf->b_u_curhead` is nonnull it
should be used as the current head, and `curbuf->b_u_newhead` is
ignored. If the there is a current head, then this will be redoed on the
next redo, and its parent will be undone on next undo. Only if
`b_u_curhead` is NULL, `b_u_newhead` will be used as the head to undo
(and it is not possible to redo). Also both can be NULL, to indicate an
empty undotree. (To be fair, this only strictly true when calling undo.c
from the outside, in some places _within_ a function in undo.c both
values might be meaningful)

Apparently `undotree()` breaks this non-abstraction, this _cosmetic_
issue can easily be fixed by `ex_substitute` also saving and restoring
`b_u_newhead`, but is doesn't reflect any error really how
`u_undo_and_forget` manipulates the _actual_ state of the undo tree.

@justinmk justinmk force-pushed the justinmk:incsub branch from 0104540 to 4709c7e Nov 9, 2016

Merge #5561 'inccommand'
Initial work by:
  Robin Elrharbi-Fleury (Robinhola)
  Audrey Rayé (Adrey06)
  Philémon Hullot (DesbyP)
  Aymeric Collange (aym7)
  Clément Guyomard (Clement0)

Major revisions by:
  KillTheMule
  Björn Linse <bjorn.linse@gmail.com>
  Justin M. Keyes <justinkz@gmail.com>

@justinmk justinmk force-pushed the justinmk:incsub branch from 4709c7e to 0213e99 Nov 9, 2016

@justinmk justinmk merged commit 0213e99 into neovim:master Nov 9, 2016

3 of 6 checks passed

QuickBuild Build pr-5561 finished with status FAILED
Details
continuous-integration/appveyor/branch Waiting for AppVeyor build to complete
Details
continuous-integration/travis-ci/push The Travis CI build is in progress
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
coverage/coveralls Coverage increased (+0.1%) to 71.241%
Details

@justinmk justinmk removed the RFC label Nov 9, 2016

@justinmk

This comment has been minimized.

Member

justinmk commented Nov 9, 2016

Merging this, but I think the cursor movement should be revisited. The "jumping around" while building the :sub command is not really helpful. Especially with inccommand=split where results are shown without moving the cursor at all. (Updated: fixed)

Thank you @KillTheMule @bfredl and the original contributors!

@justinmk justinmk deleted the justinmk:incsub branch Nov 9, 2016

@balta2ar

This comment has been minimized.

balta2ar commented on runtime/syntax/vim.vim in 0213e99 Nov 9, 2016

@justinmk I'm not sure, but maybe this should be Substitute? That's what I would think after this commit: 6a3f8d4

This comment has been minimized.

Member

justinmk replied Nov 9, 2016

Yes, thanks.

@dmerejkowsky

This comment has been minimized.

Contributor

dmerejkowsky commented on 0213e99 Nov 9, 2016

For the curious, here's what it looks like:
https://asciinema.org/a/92207

@alok

This comment has been minimized.

alok commented Nov 10, 2016

Could this be used to extend the incsearch option to highlight all candidate matches rather than just the current one (I think emacsdoes this)?

@justinmk

This comment has been minimized.

Member

justinmk commented Nov 10, 2016

@alok that's being discussed on vim_dev so we'll wait for it to land there.

@gaving

This comment has been minimized.

gaving commented Nov 11, 2016

Congrats on the merge of this rockin' feature, this [and the associated PR's] are a great example of OSS done right!

justinmk added a commit to justinmk/neovim that referenced this pull request Nov 27, 2016

NVIM v0.1.7
FEATURES:
0213e99 PR neovim#5561 'inccommand'

FIXES:
c685879 PR neovim#5632 SECURITY FIX
d28d108 CheckHealth: Fix version comparison.
7be113d PR neovim#5670 shell_write_cb: Schedule error message.
1d45637 jobs: ensure calling jobclose() on a pty job sends SIGHUP.
36c0ec6 tui/suspend_event(): set STDIN to "blocking"
7a4d069, cf52b88 man.vim: avoid errors in unusual circumstances
ed19873 PR neovim#5546 ex_global: Catch CTRL-C even if it is mapped.

CHANGES:
9147331 PR neovim#2905 encoding: only allow encoding=utf-8
5f02608 PR neovim#5636 build: Upgrade jemalloc
f1fed42 PR neovim#5567 l10n: Update Ukrainian translation

meribold added a commit to meribold/dotfiles that referenced this pull request Nov 29, 2016

meribold added a commit to meribold/dotfiles that referenced this pull request Nov 29, 2016

@AnakinXL

This comment has been minimized.

AnakinXL commented Jan 13, 2017

Thanks for the work! This feature rocks!!

Though, I wonder how hard would it be to make it work with the :Subvert command from tpope's abolish plugin, which is immensely helpful in real-life substitution use cases.

@dsifford

This comment has been minimized.

dsifford commented Apr 23, 2018

@justinmk

that's being discussed on vim_dev so we'll wait for it to land there.

You wouldn't happen to have a link to that discussion thread and/or an update on the status of that, would you?

Thanks in advance!

@justinmk

This comment has been minimized.

Member

justinmk commented Apr 23, 2018

@dsifford It's already implemented in Vim and Nvim 0.3: #7463

@dsifford

This comment has been minimized.

dsifford commented Apr 23, 2018

@justinmk Is there a visual example of this somewhere I can take a look at? I'm thinking that maybe what I'm expecting is different than what's already implemented. I've got both hlsearch and incsearch enabled and it's still not doing what I'd expect.

@justinmk

This comment has been minimized.

Member

justinmk commented Apr 23, 2018

@dsifford Please always mention the exact version you're using. Also for questions about usage/configuration, try https://vi.stackexchange.com and the resources listed at https://neovim.io/community/.

@dsifford

This comment has been minimized.

dsifford commented Apr 23, 2018

@justinmk Thanks for the info.

I think I may have found a bug in 0.2.2. (everything works as expected in vim proper, but not neovim -- even when running with -u NONE).

I'm gonna compile nightly here in a few and test and see if it's already been fixed before opening an issue on this.

@justinmk

This comment has been minimized.

Member

justinmk commented Apr 23, 2018

@dsifford I mentioned in #5561 (comment) the feature requires Nvim 0.3.

@dsifford

This comment has been minimized.

dsifford commented Apr 23, 2018

D'oh! 😖

I apologize for the noise. Thanks so much for your patience and kind feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment