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

Visualstar #1616

Merged
merged 15 commits into from
May 1, 2017
Merged

Visualstar #1616

merged 15 commits into from
May 1, 2017

Conversation

mikew
Copy link
Contributor

@mikew mikew commented Apr 30, 2017

The default behaviour of * and # isn't really intuitive, and Vim itself has many plugins to handle this.

This PR adds a new option to treat * and # as a new search when pressed in visual mode.

package.json Outdated
"vim.visualstar": {
"type": "boolean",
"description": "When pressing * or # in visual mode treat it as a new search",
"default": true
Copy link
Member

@Chillee Chillee May 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be "default": false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, that may be why the tests were inexplicably passing ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with toggling bonus features like this on, actually.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the difference is that this one affects default behavior.

Copy link
Member

@johnfn johnfn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for the PR!! It's really appreciated.

This looks great to me. Just a few stylistic comments and we should be good to go here. :)

README.md Outdated
@@ -180,6 +180,10 @@ These settings are specific to VSCodeVim.
}
```

#### `"vim.visualstar"`
* When pressing `*` or `#` in visual mode treat it as a new search
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we rephrase this slightly:

"In visual mode, start a search with * or # using the current selection."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gladly, I was never sure what the wording should be.

@@ -1739,6 +1781,10 @@ class CommandSearchCurrentWordExactForward extends BaseCommand {
runsOnceForEachCountPrefix = true;

public async exec(position: Position, vimState: VimState): Promise<VimState> {
if (Configuration.visualstar && vimState.currentMode !== ModeName.Normal) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a custom dispatch on current mode, can we have two separate commands, one for ModeName.Normal, and one for ModeName.Visual/Line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, that's how I had things originally.

});
}

interface IPerformSearchMovementArgs {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with inlining this in performSearchMovement arguments.

(When you extract it to an interface, I subconsciously think that we're using it elsewhere in the code.)

Copy link
Contributor Author

@mikew mikew May 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I asked about this on slack, because the inlined arguments made the linter complain about the line length. So the question was numerous arguments over a multiple lines versus an interface.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see. If you indent every line of the object you should be good right?

}

interface IPerformSearchMovementArgs {
needle: string | undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better written as needle?: string

searchStartCursorPosition: Position;
}

function performSearchMovement(args: IPerformSearchMovementArgs) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion to destructure args here e.g.

const { needle, isExact, vimState } = args

Removes a lot of args. throughout this function and should improve readability ever so slightly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll just go back to inlining them

}

function performSearchMovement(args: IPerformSearchMovementArgs) {
if (args.needle === undefined || args.needle === null || args.needle.length === 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to check against null because you said args is string | undefined

searchStartCursorPosition: Position;
}

function performSearchMovement(args: IPerformSearchMovementArgs) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give this function a better name? Possibly moveCursorToNextSearchMatch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with making the name more clear if you think it's ambiguous, but it's really doing two things: performing the search and making the movement.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just that "performing the search" feels a bit general to me. You mean we create the current search state right?

Maybe createSearchStateAndMoveToMatch?

@mikew
Copy link
Contributor Author

mikew commented May 1, 2017

All those changes are in, let me know what you think

return createSearchStateAndMoveToMatch(currentSelection, vimState, direction, false, searchStartCursorPosition);
}

function createSearchStateAndMoveToMatch(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh wait a sec. I mean like this:

function createSearchStateAndMoveToMatch(args: {
 needle: string | undefined,
 vimState: VimState,
 direction: SearchDirection,
 isExact: boolean,
 searchStartCursorPosition: Position,
}

IMO it's important to use an object here so we associate names with the arguments. Otherwise when we pass in the 5 different args to the function it's hard to remember what each one is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohhhhh, I didn't know that was possible in typescript.

Copy link
Member

@johnfn johnfn May 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah! :) Fun fact, if you can specify a good default for each, you can even auto-destructure the arguments:

function doStuff({ a = 1, b = "foo" }) { /* go on to use a and b */ }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(That's not possible here - you can't really get a default VimState - so don't worry about it)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I knew object destructuring defaults from ES6, wasn't sure how to use them in typescript with type information as well.

@johnfn
Copy link
Member

johnfn commented May 1, 2017

One last thing - sorry about that, I could have been more clear! Then we should be good to go. :)

@mikew
Copy link
Contributor Author

mikew commented May 1, 2017

Heck of a lot of work for a long line.

And in the end, a line was added that's just on the cusp of the limit.

@johnfn
Copy link
Member

johnfn commented May 1, 2017

To be fair, it's less about the length of the line, and more about trying to move this codebase in the direction of explicitly naming all arguments when argument length gets past a certain point. I find foo(bar, baz, undefined, true, 5) to be a lot less readable than (say) foo({ name: bar, type: baz, deleteLine: true }).

Thank you for making those changes, and thank you again for the great PR. I (and all VSCodeVim users!) will really appreciate it. :)

@johnfn johnfn merged commit a670b28 into VSCodeVim:master May 1, 2017
@mikew
Copy link
Contributor Author

mikew commented May 1, 2017

I'm with you on the number of arguments, any more than 2 or 3 really.

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

Successfully merging this pull request may close these issues.

3 participants