@@ -3,7 +3,7 @@ import * as vscode from "vscode"
3
3
import * as utilities from '../utilities' ;
4
4
import * as formatter from '../calva-fmt/src/format' ;
5
5
import { LispTokenCursor } from "../cursor-doc/token-cursor" ;
6
- import { ModelEdit , EditableDocument , EditableModel , ModelEditOptions , LineInputModel , ModelEditSelection } from "../cursor-doc/model" ;
6
+ import { ModelEdit , EditableDocument , EditableModel , ModelEditOptions , LineInputModel , ModelEditSelection , StringDocument } from "../cursor-doc/model" ;
7
7
import * as parinfer from "../calva-fmt/src/infer" ;
8
8
import * as formatConfig from '../calva-fmt/src/config' ;
9
9
import statusbar from '../statusbar' ;
@@ -29,8 +29,6 @@ export class DocumentModel implements EditableModel {
29
29
this . _parinferReadiness = readiness ;
30
30
}
31
31
32
- performInferParens = formatConfig . getConfig ( ) [ "infer-parens-as-you-type" ] ;
33
-
34
32
isWritable = false ;
35
33
36
34
constructor ( private document : MirroredDocument ) {
@@ -43,9 +41,6 @@ export class DocumentModel implements EditableModel {
43
41
const undoStopBefore = ! ! options . undoStopBefore ;
44
42
return editor . edit ( builder => {
45
43
for ( const modelEdit of modelEdits ) {
46
- if ( ! options . performInferParens ) {
47
- this . document . model . performInferParens = false ;
48
- }
49
44
switch ( modelEdit . editFn ) {
50
45
case 'insertString' :
51
46
this . insertEdit . apply ( this , [ builder , ...modelEdit . args ] ) ;
@@ -116,6 +111,9 @@ export class DocumentModel implements EditableModel {
116
111
export class MirroredDocument implements EditableDocument {
117
112
constructor ( public document : vscode . TextDocument ) { }
118
113
114
+ parensInferred = false ;
115
+ rangeFormatted = false ;
116
+
119
117
get selectionLeft ( ) : number {
120
118
return this . document . offsetAt ( vscode . window . activeTextEditor . selection . anchor ) ;
121
119
}
@@ -180,7 +178,7 @@ function processChanges(event: vscode.TextDocumentChangeEvent) {
180
178
const parinferOn = formatConfig . getConfig ( ) [ "infer-parens-as-you-type" ] ;
181
179
const formatAsYouTypeOn = formatConfig . getConfig ( ) [ "format-as-you-type" ] ;
182
180
const performFormatAsYouType = formatAsYouTypeOn && event . reason != vscode . TextDocumentChangeReason . Undo ;
183
- const performInferParens = parinferOn && event . reason != vscode . TextDocumentChangeReason . Undo && model . performInferParens ;
181
+ const performInferParens = parinferOn && event . reason != vscode . TextDocumentChangeReason . Undo && ! mirroredDoc . parensInferred ;
184
182
let performHealthCheck = ! performFormatAsYouType ;
185
183
const edits : ModelEdit [ ] = event . contentChanges . map ( change => {
186
184
// vscode may have a \r\n marker, so it's line offsets are all wrong.
@@ -192,20 +190,27 @@ function processChanges(event: vscode.TextDocumentChangeEvent) {
192
190
performInferParens : ! vscode . TextDocumentChangeReason . Undo
193
191
} ) . then ( async _v => {
194
192
if ( event . document === vscode . window . activeTextEditor ?. document ) {
195
- if ( performFormatAsYouType ) {
193
+ if ( performFormatAsYouType && ! mirroredDoc . rangeFormatted ) {
196
194
if ( event . contentChanges . length === 1 && event . contentChanges [ 0 ] . text . match ( / [ \[ \] ( ) { } ] / ) ) {
197
195
const change = event . contentChanges [ 0 ] ;
198
196
const start = event . document . offsetAt ( change . range . start ) ;
199
197
const formatForwardIndex = formatter . indexForFormatForward ( mirroredDoc ) ;
200
198
const end = formatForwardIndex !== mirroredDoc . selection . active ? formatForwardIndex + 1 : mirroredDoc . selection . active ;
201
- await formatter . formatRangeEditableDoc ( mirroredDoc , [ start , end ] , true ) ;
199
+ const checkDoc = new StringDocument ( mirroredDoc . model . getText ( start , end ) ) ;
200
+ if ( parinfer . getParinferReadiness ( checkDoc ) . isStructureHealthy ) {
201
+ await formatter . formatRangeEditableDoc ( mirroredDoc , [ start , end ] , true ) ;
202
+ } else {
203
+ await formatter . formatForward ( mirroredDoc ) ;
204
+ }
205
+ mirroredDoc . rangeFormatted = true ;
202
206
} else {
203
207
await formatter . formatForward ( mirroredDoc ) ;
204
208
}
205
209
performHealthCheck = true ;
206
210
}
207
211
if ( ( mirroredDoc . model . parinferReadiness . isIndentationHealthy || performHealthCheck ) && performInferParens ) {
208
212
await parinfer . inferParens ( mirroredDoc ) ;
213
+ mirroredDoc . parensInferred = true ;
209
214
}
210
215
if ( ! performFormatAsYouType ) {
211
216
performHealthCheck = true ;
@@ -216,9 +221,8 @@ function processChanges(event: vscode.TextDocumentChangeEvent) {
216
221
statusBar . update ( vscode . window . activeTextEditor ?. document ) ;
217
222
}
218
223
} ) ;
219
- if ( event . contentChanges . length > 0 ) {
220
- model . performInferParens = formatConfig . getConfig ( ) [ "infer-parens-as-you-type" ] ;
221
- }
224
+ mirroredDoc . parensInferred = false ;
225
+ mirroredDoc . rangeFormatted = false ;
222
226
model . lineInputModel . flushChanges ( )
223
227
224
228
// we must clear out the repaint cache data, since we don't use it.
0 commit comments