1- import { isUndefined , max , min } from 'lodash' ;
1+ import { isUndefined , max , min , isNumber } from 'lodash' ;
22import { deepEqual as equal } from '../util/object' ;
33import { Scanner , ScannerState , Token } from './clojure-lexer' ;
44import { LispTokenCursor } from './token-cursor' ;
5+ import type { Selection , TextDocument } from 'vscode' ;
56
67let scanner : Scanner ;
78
@@ -45,26 +46,59 @@ export class ModelEdit {
4546 *
4647 * This will be in line with vscode when it comes to anchor/active, but introduce our own terminology for the span of the selection. It will also keep the tradition of paredit with backward/forward and up/down.
4748 */
48-
4949export class ModelEditSelection {
5050 private _anchor : number ;
5151 private _active : number ;
52-
53- constructor ( anchor : number , active ?: number ) {
54- this . _anchor = anchor ;
55- if ( active !== undefined ) {
56- this . _active = active ;
52+ private _start : number ;
53+ private _end : number ;
54+ private _isReversed : boolean ;
55+
56+ constructor ( anchor : number , active ?: number , start ?: number , end ?: number , isReversed ?: boolean ) ;
57+ constructor ( selection : Selection , doc : TextDocument ) ;
58+ constructor (
59+ anchorOrSelection : number | Selection ,
60+ activeOrDoc ?: number | TextDocument ,
61+ start ?: number ,
62+ end ?: number ,
63+ isReversed ?: boolean
64+ ) {
65+ if ( isNumber ( anchorOrSelection ) ) {
66+ const anchor = anchorOrSelection ;
67+ this . _anchor = anchor ;
68+ if ( activeOrDoc !== undefined && isNumber ( activeOrDoc ) ) {
69+ this . _active = activeOrDoc ;
70+ } else {
71+ this . _active = anchor ;
72+ }
73+ isReversed = isReversed ?? this . _anchor > this . _active ;
74+ this . _isReversed = isReversed ;
75+ this . _start = start ?? isReversed ? this . _active : Math . min ( anchor , this . _active ) ;
76+ this . _end = end ?? isReversed ? anchor : Math . max ( anchor , this . _active ) ;
5777 } else {
58- this . _active = anchor ;
78+ const { active, anchor, start, end, isReversed } = anchorOrSelection ;
79+ // const doc = getActiveTextEditor().document;
80+ const doc = activeOrDoc as TextDocument ;
81+ this . _active = doc . offsetAt ( active ) ;
82+ this . _anchor = doc . offsetAt ( anchor ) ;
83+ this . _start = doc . offsetAt ( start ) ;
84+ this . _end = doc . offsetAt ( end ) ;
85+ this . _isReversed = isReversed ;
5986 }
6087 }
6188
89+ private _updateDirection ( ) {
90+ this . _start = Math . min ( this . _anchor , this . _active ) ;
91+ this . _end = Math . max ( this . _anchor , this . _active ) ;
92+ this . _isReversed = this . _active < this . _anchor ;
93+ }
94+
6295 get anchor ( ) {
6396 return this . _anchor ;
6497 }
6598
6699 set anchor ( v : number ) {
67100 this . _anchor = v ;
101+ this . _updateDirection ( ) ;
68102 }
69103
70104 get active ( ) {
@@ -73,6 +107,67 @@ export class ModelEditSelection {
73107
74108 set active ( v : number ) {
75109 this . _active = v ;
110+ this . _updateDirection ( ) ;
111+ }
112+
113+ get start ( ) {
114+ this . _updateDirection ( ) ;
115+ return this . _start ;
116+ }
117+
118+ /* set start(v: number) {
119+ // TODO: figure out .start setter logic
120+ this._start = v;
121+ if (this._start === this._anchor) {
122+ this._isReversed = false;
123+ } else if (this._start === this._active) {
124+ this._isReversed = true;
125+ } else if (this._isReversed) {
126+ this._active = this._start;
127+ } else if (!this._isReversed) {
128+ this._anchor = this._start;
129+ }
130+ } */
131+
132+ get end ( ) {
133+ this . _updateDirection ( ) ;
134+ return this . _end ;
135+ }
136+
137+ /* set end(v: number) {
138+ // TODO: figure out .end setter logic
139+ // TODO: figure out .start setter logic
140+ this.end = v;
141+
142+ if (this._end < this._start) {
143+ this._start;
144+ }
145+
146+ if (this.end === this._anchor) {
147+ this._isReversed = true;
148+ } else if (this.end === this._active) {
149+ this._isReversed = false;
150+ } else if (this._isReversed) {
151+ this._anchor = this.end;
152+ } else if (!this._isReversed) {
153+ this._active = this.end;
154+ }
155+ } */
156+
157+ get isReversed ( ) {
158+ this . _updateDirection ( ) ;
159+ return this . _isReversed ;
160+ }
161+
162+ set isReversed ( isReversed : boolean ) {
163+ this . _isReversed = isReversed ;
164+ if ( this . _isReversed ) {
165+ this . _start = this . _active ;
166+ this . _end = this . _anchor ;
167+ } else {
168+ this . _start = this . _anchor ;
169+ this . _end = this . _active ;
170+ }
76171 }
77172
78173 clone ( ) {
@@ -88,6 +183,11 @@ export type ModelEditOptions = {
88183 selections ?: ModelEditSelection [ ] ;
89184} ;
90185
186+ export type ModelEditResult = {
187+ edits : ModelEdit [ ] ;
188+ selections : ModelEditSelection [ ] ;
189+ success : boolean ;
190+ } ;
91191export interface EditableModel {
92192 readonly lineEndingLength : number ;
93193
@@ -96,7 +196,7 @@ export interface EditableModel {
96196 * For some EditableModel's these are performed as one atomic set of edits.
97197 * @param edits
98198 */
99- edit : ( edits : ModelEdit [ ] , options : ModelEditOptions ) => Thenable < boolean > ;
199+ edit : ( edits : ModelEdit [ ] , options : ModelEditOptions ) => Thenable < ModelEditResult > ;
100200
101201 getText : ( start : number , end : number , mustBeWithin ?: boolean ) => string ;
102202 getLineText : ( line : number ) => string ;
@@ -105,10 +205,8 @@ export interface EditableModel {
105205}
106206
107207export interface EditableDocument {
108- selection : ModelEditSelection ;
109208 selections : ModelEditSelection [ ] ;
110209 model : EditableModel ;
111- // selectionStack: ModelEditSelection[];
112210 /**
113211 * A stack of selections - that is, a 2d array, where the outer array index is a point in "selection/form nesting order" and the inner array index is which cursor that ModelEditSelection belongs to. That "selection/form nesting order" axis can be thought of as the axis for time, or something close to that. That is, .selectionStacks
114212 * is only used when the user invokes the "Expand Selection" or "Shrink Selection" Paredit commands, such that each time the user invokes "Expand", it pushes an item onto the stack. Similarly, when "Shrink" is invoked, the last item
@@ -124,10 +222,10 @@ export interface EditableDocument {
124222 selectionsStack : ModelEditSelection [ ] [ ] ;
125223 getTokenCursor : ( offset ?: number , previous ?: boolean ) => LispTokenCursor ;
126224 insertString : ( text : string ) => void ;
127- getSelectionText : ( ) => string ;
128225 getSelectionTexts : ( ) => string [ ] ;
129- delete : ( ) => Thenable < boolean > ;
130- backspace : ( ) => Thenable < boolean > ;
226+ getSelectionText : ( index : number ) => string ;
227+ delete : ( index ?: number ) => Thenable < ModelEditResult > ;
228+ backspace : ( index ?: number ) => Thenable < ModelEditResult > ;
131229}
132230
133231/** The underlying model for the REPL readline. */
@@ -372,7 +470,7 @@ export class LineInputModel implements EditableModel {
372470 * Doesn't need to be atomic in the LineInputModel.
373471 * @param edits
374472 */
375- edit ( edits : ModelEdit [ ] , options : ModelEditOptions ) : Thenable < boolean > {
473+ edit ( edits : ModelEdit [ ] , options : ModelEditOptions ) : Thenable < ModelEditResult > {
376474 return new Promise ( ( resolve , reject ) => {
377475 for ( const edit of edits ) {
378476 switch ( edit . editFn ) {
@@ -396,9 +494,9 @@ export class LineInputModel implements EditableModel {
396494 }
397495 }
398496 if ( this . document && options . selections ) {
399- this . document . selections = [ options . selections [ 0 ] ] ;
497+ this . document . selections = options . selections ;
400498 }
401- resolve ( true ) ;
499+ resolve ( { edits , selections : options . selections , success : true } ) ;
402500 } ) ;
403501 }
404502
@@ -548,7 +646,6 @@ export class StringDocument implements EditableDocument {
548646 }
549647 }
550648
551- selection : ModelEditSelection ;
552649 selections : ModelEditSelection [ ] ;
553650
554651 model : LineInputModel = new LineInputModel ( 1 , this ) ;
@@ -563,30 +660,43 @@ export class StringDocument implements EditableDocument {
563660 return this . model . getTokenCursor ( offset ) ;
564661 }
565662
566- getSelectionsText : ( ) => string [ ] ;
567663 insertString ( text : string ) {
568664 this . model . insertString ( 0 , text ) ;
569665 }
570666
571667 getSelectionTexts : ( ) => string [ ] ;
572- getSelectionText : ( ) => string ;
573-
574- delete ( ) {
575- return this . model . edit (
576- [ this . selection ] . map ( ( { anchor : p } ) => new ModelEdit ( 'deleteRange' , [ p , 1 ] ) ) ,
577- {
578- selections : this . selections . map ( ( { anchor : p } ) => new ModelEditSelection ( p ) ) ,
579- }
580- ) ;
668+ getSelectionText : ( index : number ) => string ;
669+
670+ delete ( index ?: number ) {
671+ if ( isUndefined ( index ) ) {
672+ return this . model . edit (
673+ this . selections . map ( ( { anchor : p } ) => new ModelEdit ( 'deleteRange' , [ p , 1 ] ) ) ,
674+ {
675+ selections : this . selections . map ( ( { anchor : p } ) => new ModelEditSelection ( p ) ) ,
676+ }
677+ ) ;
678+ } else {
679+ return this . model . edit ( [ new ModelEdit ( 'deleteRange' , [ ( this . selections [ index ] . anchor , 1 ) ] ) ] , {
680+ selections : [ new ModelEditSelection ( this . selections [ index ] . anchor ) ] ,
681+ } ) ;
682+ }
581683 }
582- getSelectionText : ( ) => string ;
583684
584- backspace ( ) {
585- return this . model . edit (
586- [ this . selection ] . map ( ( { anchor : p } ) => new ModelEdit ( 'deleteRange' , [ p - 1 , 1 ] ) ) ,
587- {
588- selections : [ this . selection ] . map ( ( { anchor : p } ) => new ModelEditSelection ( p - 1 ) ) ,
589- }
590- ) ;
685+ backspace ( index ?: number ) {
686+ if ( isUndefined ( index ) ) {
687+ return this . model . edit (
688+ this . selections . map ( ( { anchor : p } ) => new ModelEdit ( 'deleteRange' , [ p - 1 , 1 ] ) ) ,
689+ {
690+ selections : this . selections . map ( ( { anchor : p } ) => new ModelEditSelection ( p - 1 ) ) ,
691+ }
692+ ) ;
693+ } else {
694+ return this . model . edit (
695+ [ new ModelEdit ( 'deleteRange' , [ this . selections [ index ] . anchor - 1 , 1 ] ) ] ,
696+ {
697+ selections : [ new ModelEditSelection ( this . selections [ index ] . anchor - 1 ) ] ,
698+ }
699+ ) ;
700+ }
591701 }
592702}
0 commit comments