Skip to content
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

surround.vim: yszab) should surround around b #83

Closed
justinmk opened this issue Feb 19, 2014 · 16 comments
Closed

surround.vim: yszab) should surround around b #83

justinmk opened this issue Feb 19, 2014 · 16 comments
Labels
Milestone

Comments

@justinmk
Copy link
Owner

Given this text (cursor at |):

|fooab

yszab) should cause:

(fooab)

but instead it causes:

(foo)ab
@moll
Copy link

moll commented May 29, 2014

I don't think this should necessarily surround ab given that the reasoning behind jumping or sneaking to ab is to end before the given characters, not after. If that opposite were the case, then dzab should also delete ab, which it doesn't. What you're after probably needs another mapping to put the cursor after the given characters.

@moll
Copy link

moll commented May 29, 2014

But then again, perhaps dzab should indeed delete ab as dfb does...

@justinmk
Copy link
Owner Author

@moll I was thinking of special-handling this particular use-case, since it seems more intuitive. Other operations like dzab/czab will not be affected.

dzab should indeed delete ab as dfb does

For anything other than surround, I don't think it makes sense to make 2-character sneak an inclusive operation. Vim built-in d/ and c/ are also not inclusive.

Surround is a special case, because when you want to surround something, you don't want to target the next two characters after the surround target. Or do you? :)

@moll
Copy link

moll commented May 29, 2014

I don't know to be honest. Consistency beats intuition because intuition comes from consistency. ;)
But for things besides surround, I think, it might be more reasonable to be consistent with f, rather than /. yfb yanks the whole "fooab", perhaps so should yzab. By that logic, surround being inclusive would be consistent with sneak in other cases.

@justinmk
Copy link
Owner Author

yfb yanks the whole "fooab", perhaps so should yzab. By that logic, surround being inclusive would be consistent with sneak in other cases.

But ytb does not. That's just how f and t work. So currently we don't have a strong reason to diverge from the current behavior.

@moll
Copy link

moll commented May 29, 2014

Indeed, but wouldn't you say Sneak behaves more like f than t? When sneaking you end up on the pair, not before it as you would with t-ish behavior.

@justinmk
Copy link
Owner Author

Strictly speaking, it behaves like /.

When sneaking you end up on the pair, not before it as you would with t-ish behavior.

True, you land on the first character. But only the first character.

Thought experiment: given the text (cursor at column 2):

%foo bar% %baz%
  • To delete %foo bar%, I'd rather dzr% (your proprosal) than dz<space>% (current behavior)
  • To delete %foo bar%<space> I'd rather dz%b (current behavior) than dz<space>% (your proprosal)
  • (%foo bar)% would rarely be useful, so for surround, the current behavior is pretty much never desired

Built-in Vim motions can toggle inclusive/exclusive with v. This also works with Sneak, but only "includes" the first character; maybe Sneak should be totally inclusive with v.

@moll
Copy link

moll commented May 29, 2014

I'd say it might warrant another mapping for exclusive sneaking. We're trying to cram f and t to one mapping which truly have different use cases. I can imagine them both being useful, but in the spirit of Vim's language, things should be consistent.

/ has modifiers for an inclusive match, but Sneak's usefulness comes from its fixed number of letters. That makes me lean on following f's behavior rather than /.

@ghost
Copy link

ghost commented Jun 10, 2014

I agree with you, moil, with one exception. The way I see two-letter searching is that you wish for the cursor to be on/at the first character, and you're merely just giving the second character for higher efficiency in searching.

dzab should indeed delete ab as dfb does

I think this should actually be "should delete a, and leave the cursor on b" because there are very few circumstances in which the user desires to delete/yank/use BOTH of the characters they searched for, and it maintains consistency in design and implementation. While I realize that it currently follows the behavior of /, I'm not sure that's a consistent approach since it basically turns the plugin into a "fast and short-range / command" rather than a "much more powerful f/F t/T set of commands" which I would argue fills in the gap of movement in vim better than a short range / command, especially when operations are considered.

I would even argue that yszab) surrounding the entire whitespace word is not desired behavior, but that yszab_) (with _ being a space) should give the correct result of (fooab). It comes down to language, however, as vim is built off of language (in the sense that "caw" makes sense as it's "change around "). The question we're really discussing, I think, is what the commands should be interpreted as, in an English sense, and what that does in a editor's terms.

If yszab) is "surround the text from here up until the match with parenthesis" then the ending result of (fooab) would be correct. But then would the following be correct? (Cursor denoted with [x] )

Given: aVery[L]ongWord with more veryLongWords with the command yszre) what should the result be?

  1. aVery(LongWord with mo)re veryLongWords (assumes "from cursor position 'to' match. Behavior "t"-like)
  2. aVery(LongWord with mor)e veryLongWords (assumes "from cursor position 'forward to' match. Behavior "f"-like)
  3. aVery(LongWord with more) veryLongWords (assumes "from cursor position 'to' end of verb that match is contained in) [would this be word or Word? ]
  4. aVery(LongWord with more) veryLongWords (assumes from beginning of verb that cursor position is contained in, to end of verb that match is contained in)
  5. (aVeryLongWord with more) veryLongWords (assumes from beginning of verb that cursor position is contained in, to end of verb that match is contained in)

My suggestion is that since sab, in english, is "sneak forward to ab" with the cursor landing on [a], that everything "inclusive" be treated as inclusive (f-like behavior), and that usage with Surround.vim would act as "from cursor position until/forward-to the match" (depending on inclusive/exclusive behavior of sneaking).

Personally, I would also like to see inclusiveness/exclusiveness work in a way that would allow you to map a sneak inclusive and a sneak exclusive (e.g. a "f/F t/T" set of bindings) and have everything work seamlessly.

This would allow people to easily use sneak.vim as a two-char/one-char replacement for f/F t/T and have the operator actions work intuitively and it would also allow people to have a just inclusive/exclusive binding set or both inclusive/exclusive and have f/F t/T separate, according to their preferences.

Thoughts?

@moll
Copy link

moll commented Jun 14, 2014

So you, @thang1thang2, propose interpretation and behavior nr 2 from the above list?
You do raise a 3rd interpretation with it I didn't think of at all — to consider s to be a exactly like f (land on 1 character) just with added precision to help disambiguate the exact location.

Quite the set of options we have for s:

  1. Like f with inclusive on two-letters (e.g. deletes both characters)
  2. Like f with inclusive on one-letter (e.g. deletes first character)
  3. Like t or / with exclusive motion (e.g. deletes up to, but not the characters themselves)

I wouldn't be surprised if we end up having to have two different keys for inclusive and exclusive, like I said before, matching f and t. But that still leaves the problem @thang1thang2 brought up choosing between option 1 and 2.

@justinmk justinmk added this to the 2.0 milestone Jun 22, 2014
@ghost
Copy link

ghost commented Jun 30, 2014

So I forgot to reply to this, my bad. (tl;dr at bottom)

@moll, I do propose interpretation and behavior nr 2 from the above list. Not as the dominant and only behavior, but as the "f"-behavior side of the plugin with "t"-behavior being possible as well.

I've thought about the shortcuts. We currently have 's' to "sneak" and 'z' to "operate with sneak". Going forward towards f/t optional behavior, I might suggest simply overwriting f/t as it would be the easiest option.

Otherwise, looking at the mappings, mappings beginning with 'z' handle folds, spelling, and "moving the screen to the right or left", and the only thing capital 'Z' does is act as a speedier :q or :wq. As such, I think they could be safely used as a pair of bindings alongside 's/S' if one is aware of the fact that folds won't work without remapping. As such, using s/S for exclusive and 'z/Z' for inclusive searching could be done relatively seamlessly. Using 'z' and 'x' to work with operators could also be done as that doesn't get rid of any functionality I can see. On further digging through the vim help files, it appears that only a and i are bound natively as text objects which gives us much more flexibility when choosing a binding to work with.

As always, one of the larger problems of extending vim remains it's deep coverage of the existing keys. There's a suitable xkcd reference about breaking workflows that applies well here...

I would argue for the default overwriting of f/F and t/T going forward. Settings such as let g:sneak#f = () and let g:sneak#F = () could be implemented into a vimrc which would allow for the easy remapping of sneak to either get rid of certain functionality (e.g. removing 'f' behavior and making sneak behave like an older version). The settings would also allow an easy remapping of keys.

The reason I argue that this would be the most sensible way to go is because adding in the ability to choose inclusive/exclusive for any type of behavior of sneak would, in effect, negate the current implementations of f and t for all practical purposes. There is even a current implementation to make sneak one-character, which would be an identical usage of the current f/F t/T with the only change being multi-line behavior.

To me, implementing an entirely separate set of keybinds just for vim-sneak seems excessive. While sneak does indeed bridge the gap between f/t and /searching, with the extension of behavior discussed, it would completely emulate f/t, improve it, and extend upon it. It would seem that, at that point, it would be up to the end user to decide what keybinds to use and what features of the plugin to utilize.

Thoughts?

@justinmk
Copy link
Owner Author

implementing an entirely separate set of keybinds just for vim-sneak seems excessive

This isn't clear to me. Are you talking about this faq entry or about a proposed new feature?

@ghost
Copy link

ghost commented Jun 30, 2014

@justinmk sorry I wasn't clearer. I meant that having default keybinds for vim-sneak that are different than f/F or t/T seems extraneous if sneak was modified to work both inclusively and exclusively.

Right now sneak uses s/S and z for its keybinds. But adding in two extra keybinds just to avoid the usage of f/F and t/T seems largely unnecessary since it's easy for the user to remap the keybinds to whatever they want, anyway.

@justinmk
Copy link
Owner Author

justinmk commented Jul 1, 2014

Ok, thanks.

@justinmk
Copy link
Owner Author

justinmk commented Aug 8, 2014

@moll @thang1thang2 Not sure if it covers every scenario mentioned in this issue, but after the changes in #121 you can now toggle inclusive/exclusive behavior (with surround and any other movement/operation) using v. This is a standard Vim behavior, but until #121 Sneak didn't work quite correctly with it.

To see what I mean, compare yszab( with ysvzab(. The first is the typical "exclusive" behavior (the ) is placed before a), but the second is "inclusive" (the ) is placed after the a).

Try it with other operations too: dzab vs dvzab.

@justinmk justinmk changed the title yszab) should surround around b surround.vim: yszab) should surround around b Mar 1, 2018
@justinmk
Copy link
Owner Author

The current behavior is probably most correct, since it matches {op}/.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants