mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-11 11:15:24 +03:00
Be more aggressive in determining suggested indent positions…
…at ends of transactions — instead of falling back to a transaction-wide auto-indent quite so easily.
This commit is contained in:
parent
2827e6a4c4
commit
afe6e1e7bf
@ -4120,43 +4120,93 @@ describe('WASMTreeSitterLanguageMode', () => {
|
|||||||
await grammar.setQueryForTest('indentsQuery', `
|
await grammar.setQueryForTest('indentsQuery', `
|
||||||
["{"] @indent
|
["{"] @indent
|
||||||
["}"] @dedent
|
["}"] @dedent
|
||||||
`);
|
`);
|
||||||
|
|
||||||
let emptyClassText = dedent`
|
let emptyClassText = dedent`
|
||||||
class Example {
|
class Example {
|
||||||
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
buffer.setText(emptyClassText);
|
buffer.setText(emptyClassText);
|
||||||
|
|
||||||
const languageMode = new WASMTreeSitterLanguageMode({ grammar, buffer });
|
const languageMode = new WASMTreeSitterLanguageMode({ grammar, buffer });
|
||||||
buffer.setLanguageMode(languageMode);
|
buffer.setLanguageMode(languageMode);
|
||||||
await languageMode.ready;
|
await languageMode.ready;
|
||||||
|
|
||||||
editor.setCursorBufferPosition([1, 0]);
|
editor.setCursorBufferPosition([1, 0]);
|
||||||
editor.indent();
|
editor.indent();
|
||||||
await languageMode.atTransactionEnd();
|
await languageMode.atTransactionEnd();
|
||||||
editor.insertText('// this is a comment', { autoIndent: true });
|
editor.insertText('// this is a comment', { autoIndent: true });
|
||||||
await languageMode.atTransactionEnd();
|
await languageMode.atTransactionEnd();
|
||||||
expect(editor.lineTextForBufferRow(1)).toEqual(' // this is a comment');
|
expect(editor.lineTextForBufferRow(1)).toEqual(' // this is a comment');
|
||||||
|
|
||||||
editor.insertNewline();
|
editor.insertNewline();
|
||||||
await languageMode.atTransactionEnd();
|
await languageMode.atTransactionEnd();
|
||||||
await wait(0);
|
await wait(0);
|
||||||
expect(editor.lineTextForBufferRow(2)).toEqual(' ');
|
expect(editor.lineTextForBufferRow(2)).toEqual(' ');
|
||||||
|
|
||||||
editor.insertNewline();
|
editor.insertNewline();
|
||||||
await languageMode.atTransactionEnd();
|
await languageMode.atTransactionEnd();
|
||||||
await wait(0);
|
await wait(0);
|
||||||
expect(editor.lineTextForBufferRow(3)).toEqual(' ');
|
expect(editor.lineTextForBufferRow(3)).toEqual(' ');
|
||||||
|
|
||||||
editor.insertNewline();
|
editor.insertNewline();
|
||||||
await languageMode.atTransactionEnd();
|
await languageMode.atTransactionEnd();
|
||||||
await wait(0);
|
await wait(0);
|
||||||
expect(editor.lineTextForBufferRow(4)).toEqual(' ');
|
expect(editor.lineTextForBufferRow(4)).toEqual(' ');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it(`can indent properly in a multi-cursor environment without auto-indenting large ranges of the buffer`, async () => {
|
||||||
|
jasmine.useRealClock();
|
||||||
|
const grammar = new WASMTreeSitterGrammar(atom.grammars, jsGrammarPath, jsConfig);
|
||||||
|
|
||||||
|
expect(editor.getUndoGroupingInterval()).toBe(300);
|
||||||
|
|
||||||
|
await grammar.setQueryForTest('indentsQuery', `
|
||||||
|
["{"] @indent
|
||||||
|
["}"] @dedent
|
||||||
|
`);
|
||||||
|
|
||||||
|
const languageMode = new WASMTreeSitterLanguageMode({ grammar, buffer });
|
||||||
|
buffer.setLanguageMode(languageMode);
|
||||||
|
await languageMode.ready;
|
||||||
|
|
||||||
|
// No spaces after the `{`s in these examples so that we can more easily
|
||||||
|
// compare expected output to actual output.
|
||||||
|
buffer.setText(dedent`
|
||||||
|
function test () {return }
|
||||||
|
|
||||||
|
function test () {return }
|
||||||
|
|
||||||
|
function test () {return }
|
||||||
|
`);
|
||||||
|
|
||||||
|
editor.setCursorBufferPosition([0, 18])
|
||||||
|
editor.addCursorAtBufferPosition([2, 18])
|
||||||
|
editor.addCursorAtBufferPosition([4, 18])
|
||||||
|
|
||||||
|
editor.insertNewline({
|
||||||
|
autoIndent: true,
|
||||||
|
autoIndentNewline: true,
|
||||||
|
autoDecreaseIndent: true
|
||||||
|
})
|
||||||
|
|
||||||
|
await wait(0);
|
||||||
|
|
||||||
|
expect(buffer.getText()).toBe(dedent`
|
||||||
|
function test () {
|
||||||
|
return }
|
||||||
|
|
||||||
|
function test () {
|
||||||
|
return }
|
||||||
|
|
||||||
|
function test () {
|
||||||
|
return }
|
||||||
|
`)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1270,6 +1270,7 @@ class WASMTreeSitterLanguageMode {
|
|||||||
if (!controllingLayer.treeIsDirty || options.forceTreeParse || !this.useAsyncParsing || !this.useAsyncIndent) {
|
if (!controllingLayer.treeIsDirty || options.forceTreeParse || !this.useAsyncParsing || !this.useAsyncIndent) {
|
||||||
indentTree = controllingLayer.getOrParseTree();
|
indentTree = controllingLayer.getOrParseTree();
|
||||||
} else {
|
} else {
|
||||||
|
let lineForRow = this.buffer.lineForRow(row)
|
||||||
// We can't answer this yet because we don't yet have a new syntax
|
// We can't answer this yet because we don't yet have a new syntax
|
||||||
// tree. Return a promise that will fulfill once we can determine the
|
// tree. Return a promise that will fulfill once we can determine the
|
||||||
// right indent level.
|
// right indent level.
|
||||||
@ -1278,23 +1279,31 @@ class WASMTreeSitterLanguageMode {
|
|||||||
// preliminary indent level and then follow up later with a more
|
// preliminary indent level and then follow up later with a more
|
||||||
// accurate one. It's a bit disorienting that the editor falls back to
|
// accurate one. It's a bit disorienting that the editor falls back to
|
||||||
// an indent level of `0` when a newline is inserted.
|
// an indent level of `0` when a newline is inserted.
|
||||||
return this.atTransactionEnd().then(({ changeCount }) => {
|
return this.atTransactionEnd().then(() => {
|
||||||
if (changeCount > 1) {
|
if (lineForRow !== this.buffer.lineForRow(row)) {
|
||||||
// There were multiple changes in this transaction, so it's not
|
// We're now revisiting this indentation question at the end of the
|
||||||
// safe to assume that the original row still needs its indentation
|
// transaction. Other changes may have taken place since we were
|
||||||
// adjusted. The row could've been shifted up or down by other
|
// first asked what the indent level should be for this line. So
|
||||||
// edits, or it could've been deleted entirely.
|
// how do we know if the question is still relevant? After all, the
|
||||||
|
// text that was on this row earlier might be on some other row
|
||||||
|
// now.
|
||||||
//
|
//
|
||||||
// Instead, we return `undefined` here, and the `TextEditor` will
|
// So we compare the text that was on the row when we were first
|
||||||
// understand that its only recourse is to auto-indent the whole
|
// called… to the text that is on the row now that the transaction
|
||||||
// extent of the transaction instead.
|
// is over. If they're the same, that's a _strong_ indicator that
|
||||||
|
// the result we return will still be relevant.
|
||||||
|
//
|
||||||
|
// If not, as is the case in this code path, we return `undefined`,
|
||||||
|
// signalling to the `TextEditor` that its only recourse is to
|
||||||
|
// auto-indent the whole extent of the transaction instead.
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
// Otherwise, it's safe to auto-indent this line alone, because it
|
// If we get this far, it's safe to auto-indent this line. Either it
|
||||||
// was the only change in this transaction. But we've retained the
|
// was the only change in its transaction or the other changes
|
||||||
// original values for `comparisonRow` and `comparisonRowIndent`
|
// happened on different lines. But we've retained the original
|
||||||
// because that's the proper basis from which to determine the given
|
// values for `comparisonRow` and `comparisonRowIndent` because
|
||||||
// row's indent level.
|
// that's the proper basis from which to determine the given row's
|
||||||
|
// indent level.
|
||||||
let result = this.suggestedIndentForBufferRow(row, tabLength, {
|
let result = this.suggestedIndentForBufferRow(row, tabLength, {
|
||||||
...rawOptions,
|
...rawOptions,
|
||||||
comparisonRow: comparisonRow,
|
comparisonRow: comparisonRow,
|
||||||
@ -1379,6 +1388,18 @@ class WASMTreeSitterLanguageMode {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
indentDelta--;
|
indentDelta--;
|
||||||
|
if (indentDelta < 0) {
|
||||||
|
// In the _indent_ phase, the delta won't ever go lower than `0`.
|
||||||
|
// This is because we assume that the previous line is correctly
|
||||||
|
// indented! The only function that `dedent` has for us is canceling
|
||||||
|
// out any `indent` and preventing false positives.
|
||||||
|
//
|
||||||
|
// So no matter how many `dedent` tokens we see on a particular line…
|
||||||
|
// if the _last_ token we see is an `indent` token, then it hints
|
||||||
|
// that the next line should be indented by one level.
|
||||||
|
indentDelta = 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user