-
Notifications
You must be signed in to change notification settings - Fork 92
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
Fix non-sticky outdent action for OnEnter
rules
#2619
Conversation
@@ -165,8 +168,33 @@ export function getInheritIndentForLine( | |||
} | |||
|
|||
if (honorIntentialIndent) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW when I was playing with this I left everything in this if statement the same and instead put this chunk of code right above this if statement. I'm not sure if honorIntentionalIndent
is supposed to matter here
// --- Start Positron ---
// Check for onEnter rules that should decrease the indent by looking at the rule
// used on the last unignored line.
// Adapted from https://github.com/microsoft/vscode/pull/136593/.
if (indentConverter) {
const richEditSupport = languageConfigurationService.getLanguageConfiguration(model.tokenization.getLanguageId());
if (richEditSupport) {
const previousLineText = precedingUnIgnoredLine < 1 ? '' : model.getLineContent(precedingUnIgnoredLine - 1);
const beforeEnterText = precedingUnIgnoredLineContent;
const afterEnterText = '';
const enterResult = richEditSupport.onEnter(autoIndent, previousLineText, beforeEnterText, afterEnterText);
if (enterResult) {
const precedingUnIgnoredLineIndentation = strings.getLeadingWhitespace(precedingUnIgnoredLineContent);
if (enterResult.indentAction === IndentAction.Outdent) {
return {
indentation: indentConverter.unshiftIndent(precedingUnIgnoredLineIndentation),
action: null,
line: precedingUnIgnoredLine
};
} else if (enterResult.removeText && precedingUnIgnoredLineIndentation.length >= enterResult.removeText) {
return {
indentation: precedingUnIgnoredLineIndentation.substring(0, precedingUnIgnoredLineIndentation.length - enterResult.removeText - 1),
action: null,
line: precedingUnIgnoredLine
};
}
}
}
}
// --- End Positron ---
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems plausible but when I follow the code paths where honorIntentionalIndent
would be false
, I can't really produce any unintended behaviour. Since we're not sure, and if we are not otherwise changing the PR (if you agree with my notes on the other comment), I would keep this as is to make it easier to track the upstream PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine by me!
const richEditSupport = languageConfigurationService.getLanguageConfiguration(model.tokenization.getLanguageId()); | ||
if (richEditSupport) { | ||
const previousLineText = precedingUnIgnoredLine < 1 ? '' : model.getLineContent(precedingUnIgnoredLine - 1); | ||
const afterEnterText = model.getLineContent(lineNumber); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This afterEnterText
also felt weird to me. I thought it should just be ""
.
The way I see it is:
beforeEnterText
is everything on the preceding unignored lineafterEnterText
is then""
, because there is nothing else on the line.
I changed it to ""
in my rewrite
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC the intent is to reproduce the OnEnter matching that initially splitted the line from which we are inheriting indentation. When you type Enter, OnEnter rules are processed by matching the text before cursor to the beforeText
regexp, and the text after cursor to afterText
(usually but not necessarily empty). If there is a match, a newline and indentation are inserted. But here we are trying to reproduce the matching that occurred in the past, with the line already split. So that's why we are passing that whole line (the previous beforeText
) to the current whole line (the previous afterText
) to the enter action matcher, ignoring the whitespace in between. Does this make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we have this example, with the cursor at |
df %>%
mutate(x = 1) %>%
mutate(y = 2)
|foo
Then when I hit Enter at the |
, I was expecting it to replay the past enter behavior by:
- Effectively moving the cursor to
mutate(y = 2)|
- Setting
beforeEnterText
asmutate(y = 2)
- Setting
afterEnterText
as''
- Setting
previousLineText
asmutate(x = 1) %>%
i.e. this recreates the scenario of being at the end of mutate(y = 2)
and hitting Enter, and in my head that doesn't have anything to do with foo
at all. In other words, if I'm replaying the past then I should not be looking at anything in the present to figure out what happened.
In practice, I'm not sure this will affect very many scenarios (certainly not ours, since we don't use afterEnterText
) but it seemed off.
Do you interpret that differently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep this makes sense.
I think the current implementation also makes sense in a different way. It assumes that no changes to the code has been done besides hitting enter multiple times. If that's the case, that means the starting state was
df %>%
mutate(x = 1) %>%
mutate(y = 2)|foo
Then Enter is hit multiple times. And in that case it's more consistent to apply exactly the same OnEnter rule for outdent as you keep hitting Enter, otherwise subsequent Enters might behave differently.
I think both approaches are valid and I agree that it should not matter most of the times. I could not find any "outdent" rules that inspect afterText
inside the Code/Positron repository. So personally I would just follow the upstream PR unless it had an unambiguous flaw, for simplicity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, what you are saying about "hitting enter multiple times" also makes sense.
Agree about following the upstream PR for consistency and simplicity, let's do that!
85f7895
to
fca4853
Compare
@DavisVaughan I've fixed the issue you noticed about typing Enter with the cursor on the last line. We're passing a Does that look good? If so I'll suggest this change to the upstream PR as well. Unfortunately for some reason I couldn't reproduce the faulty behaviour in the snapshot tests, so I've not added one. @jmcphers If you get a chance you might also want to take a look at this since this is modifying VS Code and might pop up in merge conflicts. |
@lionel- when I dug into this I understood df %>%
mutate(x = 1) %>%
mutate(y = 2)
|foo
bar <- this is what lineNumber points to so I thought we just wanted |
yes it's the next line fed as |
We went over this in a video chat and it seems I was confused. We decided to just go with empty |
Fixes `Illegal value for lineNumber` error when fetching `model.getLineContent(lineNumber)`
This reverts commit fca4853.
8d517b2
to
74e78f2
Compare
Addresses #1727
@DavisVaughan found that the indentation issue described in #1727 is caused by a bug that causes outdent actions of on-enter rules to be non-sticky. He also discovered this long-open PR that fixes the issues: microsoft/vscode#136593
I've brought attention to this PR to the VS Code dev who is currently working on indentation, with a reprex and motivation: microsoft/vscode#136593 (comment). So hopefully this will be fixed upstream.
In the meantime, this PR includes the fix into Positron. The alternative would be to use a format-on-type correction as we plan to do for other indent issues, but this approach doesn't seem like a good fit for this issue.