Vrapper-sneak Mk. II #764

Merged
merged 20 commits into from Oct 20, 2016

Conversation

Projects
None yet
3 participants
@albertdev
Contributor

albertdev commented Oct 19, 2016

This has been in progress since September 2015 with Mark 1 being implemented in May 2016. I've rewritten it the past few weeks and added to it so that f/F/t/T now work as well, giving you a zippy way to navigate your files!

Currently it runs on a cache, doing a search 250 times in a row to find all close occurrences in a single direction. The limit is 500 search items, but it does search for extra items if you use a count value before invoking s.

To use the plugin, put this in your .vrapperrc:

nmap s <Plug>(sneak_s)
nmap S <Plug>(sneak_S)

nmap ; <Plug>(sneak-next)
nmap , <Plug>(sneak-prev)

vmap s <Plug>(sneak_s)
vmap Z <Plug>(sneak_S)

vmap ; <Plug>(sneak-next)
vmap , <Plug>(sneak-prev)

nmap f <Plug>(sneak_f)
nmap F <Plug>(sneak_F)
nmap t <Plug>(sneak_t)
nmap T <Plug>(sneak_T)

vmap f <Plug>(sneak_f)
vmap F <Plug>(sneak_F)
vmap t <Plug>(sneak_t)
vmap T <Plug>(sneak_T)

omap z <Plug>(sneak_s)
omap Z <Plug>(sneak_S)

I'm still wondering if I can register these mappings by default (at least the s and ; ones) or provide another configuration command.

Suggestions are welcome!

albertdev added some commits May 16, 2016

NormalMode accepts multiple hints, find command with new utils method
A new plugin mode would pass in a hint for visual mode as the first item
in the hints list but Normal mode only checks for commands in the very
first position. Simply introduce an utility method which will scan all
hints to find the the first of a specific type.
Move t / T repetition fix to FindCharMotion itself
The ContinueFindingMotion had to access internal state for it to work,
complicating matters.
Extract interface from FindCharMotion into Reversible
Since the future vim-sneak and easymotion plugins offer new motions
which can go both forward and backward, this interface method helps at
abstracting away their differences.
Add command which remembers last active selection
Other code tends to remember the last active selection upon entry, but
that means we need to pass what mode we're coming from. Having a command
which we add or don't add to do this saves on duplicated code.
Log before and after loading state providers if debuglog is on
This should help in debugging state provider loading.
Change remapped keystroke to convert to string using delegate
This should better display Plug keys as they contain an extra plug-id.
PlatformVrapperLifecycleListener fires on EditorAdaptor creation / close
Instances of this class can now check the state of the EditorAdaptor
just after configuration without having to be triggered by a command.

This can be useful to set up default remaps or other listeners.
HighlightRegions call should keep internal ordering
A temporary HashMap would shuffle up the order of the regions, using a
LinkedHashMap with strict ordering fixes this without performance loss
as Eclipse will use a simple EntrySet iterator to go through that Map.
Introduce Adaptable (and AbstractMotion to provide a default)
This makes each motion Adaptable, providing a way to convert a given
Motion to another type even if that motion is wrapped in a CountedMotion
instance.

This is an idea borrowed from Eclipse. We don't use IAdaptable though
because that would make Vrapper Core depend on Eclipse itself.
Introduce NavigatingMotion, generalize ContinueFindingMotion
This interface can later be implemented by sneak or easymotion so that
the ContinueFindingMotion can launch the previous invocation stored in
the RegisterManager.

MotionCommand will check for an adapter to NavigationMotion each time a
motion is run through the GoThereState and, if available, store that
motion in the lastNavigatingMotion register. As a result the
lastNavigatingMotion register will contain the last FindCharMotion which
was invoked as `fX`, but it won't be clobbered when using dfX unlike the
default lastFindCharMotion register.

This way the enhanced ContinueFindingMotion could be used to mix fX and
dfX without continuously clobbering the last character.
Add equals and equalsIgnoreDirection to Search
Necessary when you want to compare if the keywords and other parameters
match. `equalsIgnoreDirection` is for when you are not interested in the
actual direction of the search.
Move extension mode initialization to getMode(x) call
Sneak mode will need a custom mode instance to store its state in the
current editor. However, the current editor might not have an instance
of that mode yet when it is freshly initialized. However, we might want
to try to invoke a SneakMotion stored in the lastNavigatingMotion
register yet that would raise a NullPointerException because the custom
mode is null.

Moving the extension loading code to getMode(x) means that retrieving
the mode will actually request the custom mode to be created,
immediately initializing its state and preventing null pointers in the
case of a vim-sneak port.
Implement vrapper-sneak Mk. II
Add a motion which will retrieve the currently cached sneak state and
jumps to the next location.

State is kept inside the SneakInputMode which should be created for each
editor. This mode will also accept input for interactive sneak usage.

It is necessary to bind `<Plug>(sneak-next)` to `;` before sneak can be
repeated quickly. This will still allow to use the last fX motion but
will not pick up on dfX like Vim does. This can be handy to sneak around
and use dfx using the repeat-command (the dot key).

The SneakStateManager is a helper interface which
EditorAdaptorStateManagder implements, this way tests don't need to know
where Sneak's cache / state is kept; they can just provide their own
stub which returns a correctly intialized state.

SneakMotion is not a jumping motion, especially not when repeating it
using `<Plug>(sneak-next)`. A decorator is used instead to pass off the
first invocation of SneakMotion as a jump so that MotionCommand stores
our previous location. After that MotionCommand will request an adaptor
to NavigatingMotion which will unwrap the decorator, this way repeating
won't add to the jump list again.

Note that SneakInputMode will still keep a global copy of the
SneakMotion even though we have a reserved spot for NavigatingMotions in
RegisterManager. This copy is meant for when the user does `s<CR>` to
reuse the last sneak search keyword without the risk of some other
plugin clobbering the last instance in RegisterManager.
Implement f/t/F/T alternative based on vim-sneak
This works great with a count value as well.
Implement sneak text object
This text object is commonly bound to z / Z so as not to conflict with
surround.vim. It doesn't prompt for input like interactive sneak,
instead there is a state which will capture keys until a given threshold
is reached (default 2) or RETURN is pressed.

Note that this doesn't bind an alternative to d; or d, - those commands
will still use the Vrapper default ; motion, which is to use whatever fX
or dfX motion was executed last.
Implement sneak vertical search
Passing a count to the 's' or 'S' commands will start vertical search,
in this submode the search will be restricted to the [count] columns /
visual offsets to the left and right of the caret.
Clean up commandbasedmode's key state upon reentry
Vim-sneak's <Plug>sneak_s visual motion would conflict with the
<Plug>sneak_s textobject bind because the latter state still has a few
more transitions which in turn expect keys.

Because there are still transitions remaining, CommandBasedMode wouldn't
reset the state upon calling ChangeToSneakModeCommand. This leaves
VisualMode in a weird state where you can't repeat sneak, the input keys
would simply go to the textobject states.
Register jumps when sneak is reactivated with `s<Return>`
Surprisingly this only happens through `s` and not through `;` or `,` -
it also won't register as a jump when `s` is used while sneak is active.
@albertdev

This comment has been minimized.

Show comment
Hide comment
@albertdev

albertdev Oct 19, 2016

Contributor

Paging @mmbradle because I believe he was the first one to propose porting vim-sneak (admittedly back in 2015).

Contributor

albertdev commented Oct 19, 2016

Paging @mmbradle because I believe he was the first one to propose porting vim-sneak (admittedly back in 2015).

@keforbes

This comment has been minimized.

Show comment
Hide comment
@keforbes

keforbes Oct 20, 2016

Contributor

I'll go ahead and merge this in and upload an unstable build so we can test this. I'll release the next stable version when we're confident with this feature.

Contributor

keforbes commented Oct 20, 2016

I'll go ahead and merge this in and upload an unstable build so we can test this. I'll release the next stable version when we're confident with this feature.

@keforbes keforbes merged commit e77d306 into vrapper:master Oct 20, 2016

@keforbes

This comment has been minimized.

Show comment
Hide comment
@keforbes

keforbes Oct 20, 2016

Contributor

Unstable build 0.71.20161019 is ready for testing.

Contributor

keforbes commented Oct 20, 2016

Unstable build 0.71.20161019 is ready for testing.

@loonies

This comment has been minimized.

Show comment
Hide comment
@loonies

loonies Oct 21, 2016

Contributor

Nice. Much easier to move vertically. One thing I have to get used to is
pressing ; and , instead of n and N to move forward / backward.

Contributor

loonies commented Oct 21, 2016

Nice. Much easier to move vertically. One thing I have to get used to is
pressing ; and , instead of n and N to move forward / backward.

@loonies

This comment has been minimized.

Show comment
Hide comment
@loonies

loonies Oct 21, 2016

Contributor

Vim should have highlighting enabled by default for f, F, t and T
movements.

/edit

I like "progressive" / "get out of the way" highlighting.

Contributor

loonies commented Oct 21, 2016

Vim should have highlighting enabled by default for f, F, t and T
movements.

/edit

I like "progressive" / "get out of the way" highlighting.

@albertdev

This comment has been minimized.

Show comment
Hide comment
@albertdev

albertdev Nov 28, 2016

Contributor

I had the chance to use Eclipse at the day job today which caused me to notice sneak being broken at some point.

I'll have to check if I can reproduce it but it had something to do with s<x><y>, pressing ;, gg and then ; a few more times. The next time I tried to use it, vrapper-sneak would no longer jump to the next match using ; though it would highlight all nearby matches.

If others noticed the same problem then I'd still like to hear about it.

Contributor

albertdev commented Nov 28, 2016

I had the chance to use Eclipse at the day job today which caused me to notice sneak being broken at some point.

I'll have to check if I can reproduce it but it had something to do with s<x><y>, pressing ;, gg and then ; a few more times. The next time I tried to use it, vrapper-sneak would no longer jump to the next match using ; though it would highlight all nearby matches.

If others noticed the same problem then I'd still like to hear about it.

@keforbes

This comment has been minimized.

Show comment
Hide comment
@keforbes

keforbes Mar 12, 2017

Contributor

Hey @albertdev, I finally released 0.72.0 so I tried writing the documentation for this plugin (http://vrapper.sourceforge.net/documentation/?topic=optional_plugins#sneak). Did we ever define a custom command to set all the default mappings for this like we did with :subwordmappings?

Contributor

keforbes commented Mar 12, 2017

Hey @albertdev, I finally released 0.72.0 so I tried writing the documentation for this plugin (http://vrapper.sourceforge.net/documentation/?topic=optional_plugins#sneak). Did we ever define a custom command to set all the default mappings for this like we did with :subwordmappings?

@albertdev

This comment has been minimized.

Show comment
Hide comment
@albertdev

albertdev Mar 12, 2017

Contributor

@keforbes, it seems I forgot about that part.

I was originally going to register the sneak shortcuts automatically by implementing something like Vim's mapcheck, but I never got a round Tuit.

Contributor

albertdev commented Mar 12, 2017

@keforbes, it seems I forgot about that part.

I was originally going to register the sneak shortcuts automatically by implementing something like Vim's mapcheck, but I never got a round Tuit.

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