@@ -8,6 +8,9 @@ import { getLogger } from '../../shared/logger/logger'
8
8
import vscode from 'vscode'
9
9
import { fs } from '../../shared/fs/fs'
10
10
import { Writable } from 'stream'
11
+ import { Change , diffLines } from 'diff'
12
+ import { getDiffMarkdown } from '../../shared/utilities/diffUtils'
13
+ import { getLanguageForFilePath } from '../../shared/utilities/textDocumentUtilities'
11
14
12
15
interface BaseParams {
13
16
path : string
@@ -69,114 +72,40 @@ export class FsWrite {
69
72
}
70
73
}
71
74
72
- // TODO: Refactor the fsWrite.ts file "queueDescription" method to use existing diffLines and diff library to get the diff preview. or reuse existing diff view logic in cwchat. This will be part of next PR.
73
- private showStrReplacePreview ( oldStr : string , newStr : string ) : string {
74
- // Split both strings into arrays of lines
75
- const oldStrLines = oldStr . split ( '\n' )
76
- const newStrLines = newStr . split ( '\n' )
77
- let result = ''
78
-
79
- // If strings are identical, return empty string
80
- if ( oldStr === newStr ) {
81
- return result
82
- }
83
-
84
- let oldLineIndex = 0
85
- let newLineIndex = 0
86
- // Loop through both arrays until we've processed all lines
87
- while ( oldLineIndex < oldStrLines . length || newLineIndex < newStrLines . length ) {
88
- if (
89
- oldLineIndex < oldStrLines . length &&
90
- newLineIndex < newStrLines . length &&
91
- oldStrLines [ oldLineIndex ] === newStrLines [ newLineIndex ]
92
- ) {
93
- // Line is unchanged - prefix with space
94
- result += ` ${ oldStrLines [ oldLineIndex ] } \n`
95
- oldLineIndex ++
96
- newLineIndex ++
97
- } else {
98
- // Line is different
99
- if ( oldLineIndex < oldStrLines . length ) {
100
- // Remove line - prefix with minus
101
- result += `- ${ oldStrLines [ oldLineIndex ] } \n`
102
- oldLineIndex ++
103
- }
104
- if ( newLineIndex < newStrLines . length ) {
105
- // Add line - prefix with plus
106
- result += `+ ${ newStrLines [ newLineIndex ] } \n`
107
- newLineIndex ++
108
- }
109
- }
110
- }
111
-
112
- return result
113
- }
114
-
115
- private async showInsertPreview ( path : string , insertLine : number , newStr : string ) : Promise < string > {
116
- const fileContent = await fs . readFileText ( path )
117
- const lines = fileContent . split ( '\n' )
118
- const startLine = Math . max ( 0 , insertLine - 2 )
119
- const endLine = Math . min ( lines . length , insertLine + 3 )
120
-
121
- const contextLines : string [ ] = [ ]
122
-
123
- // Add lines before insertion point
124
- for ( let index = startLine ; index < insertLine ; index ++ ) {
125
- contextLines . push ( ` ${ lines [ index ] } ` )
126
- }
127
-
128
- // Add the new line with a '+' prefix
129
- contextLines . push ( `+ ${ newStr } ` )
130
-
131
- // Add lines after insertion point
132
- for ( let index = insertLine ; index < endLine ; index ++ ) {
133
- contextLines . push ( ` ${ lines [ index ] } ` )
134
- }
75
+ public async queueDescription ( updates : Writable ) : Promise < void > {
76
+ const sanitizedPath = sanitizePath ( this . params . path )
77
+ const changes = await this . getDiffChanges ( )
78
+ const language = await getLanguageForFilePath ( sanitizedPath )
135
79
136
- return contextLines . join ( '\n' )
80
+ const diff = getDiffMarkdown ( changes , language )
81
+ updates . write ( diff )
82
+ updates . end ( )
137
83
}
138
84
139
- private async showAppendPreview ( sanitizedPath : string , newStr : string ) {
140
- const fileContent = await fs . readFileText ( sanitizedPath )
141
- const needsNewline = fileContent . length !== 0 && ! fileContent . endsWith ( '\n' )
142
-
143
- let contentToAppend = newStr
144
- if ( needsNewline ) {
145
- contentToAppend = '\n' + contentToAppend
85
+ public async getDiffChanges ( ) : Promise < Change [ ] > {
86
+ const sanitizedPath = sanitizePath ( this . params . path )
87
+ let newContent
88
+ let oldContent
89
+ try {
90
+ oldContent = await fs . readFileText ( sanitizedPath )
91
+ } catch ( err ) {
92
+ oldContent = ''
146
93
}
147
-
148
- // Get the last 3 lines from existing content for better UX
149
- const lines = fileContent . split ( '\n' )
150
- const linesForContext = lines . slice ( - 3 )
151
-
152
- return `${ linesForContext . join ( '\n' ) } \n+ ${ contentToAppend . trim ( ) } `
153
- }
154
-
155
- public async queueDescription ( updates : Writable ) : Promise < void > {
156
94
switch ( this . params . command ) {
157
95
case 'create' :
158
- updates . write ( `\`\`\`diff-typescript
159
- ${ '+' + this . params . fileText ?. replace ( / \n / g, '\n+' ) }
160
- ` )
96
+ newContent = this . getCreateCommandText ( this . params )
161
97
break
162
98
case 'strReplace' :
163
- updates . write ( `\`\`\`diff-typescript
164
- ${ this . showStrReplacePreview ( this . params . oldStr , this . params . newStr ) }
165
- \`\`\`
166
- ` )
99
+ newContent = await this . getStrReplaceContent ( this . params , sanitizedPath )
167
100
break
168
101
case 'insert' :
169
- updates . write ( `\`\`\`diff-typescript
170
- ${ await this . showInsertPreview ( this . params . path , this . params . insertLine , this . params . newStr ) }
171
- \`\`\`` )
102
+ newContent = await this . getInsertContent ( this . params , sanitizedPath )
172
103
break
173
104
case 'append' :
174
- updates . write ( `\`\`\`diff-typescript
175
- ${ await this . showAppendPreview ( this . params . path , this . params . newStr ) }
176
- \`\`\`` )
105
+ newContent = await this . getAppendContent ( this . params , sanitizedPath )
177
106
break
178
107
}
179
- updates . end ( )
108
+ return diffLines ( oldContent , newContent )
180
109
}
181
110
182
111
public async validate ( ) : Promise < void > {
@@ -224,6 +153,11 @@ ${await this.showAppendPreview(this.params.path, this.params.newStr)}
224
153
}
225
154
226
155
private async handleStrReplace ( params : StrReplaceParams , sanitizedPath : string ) : Promise < void > {
156
+ const newContent = await this . getStrReplaceContent ( params , sanitizedPath )
157
+ await fs . writeFile ( sanitizedPath , newContent )
158
+ }
159
+
160
+ private async getStrReplaceContent ( params : StrReplaceParams , sanitizedPath : string ) : Promise < string > {
227
161
const fileContent = await fs . readFileText ( sanitizedPath )
228
162
229
163
const matches = [ ...fileContent . matchAll ( new RegExp ( this . escapeRegExp ( params . oldStr ) , 'g' ) ) ]
@@ -235,11 +169,15 @@ ${await this.showAppendPreview(this.params.path, this.params.newStr)}
235
169
throw new Error ( `${ matches . length } occurrences of oldStr were found when only 1 is expected` )
236
170
}
237
171
238
- const newContent = fileContent . replace ( params . oldStr , params . newStr )
239
- await fs . writeFile ( sanitizedPath , newContent )
172
+ return fileContent . replace ( params . oldStr , params . newStr )
240
173
}
241
174
242
175
private async handleInsert ( params : InsertParams , sanitizedPath : string ) : Promise < void > {
176
+ const newContent = await this . getInsertContent ( params , sanitizedPath )
177
+ await fs . writeFile ( sanitizedPath , newContent )
178
+ }
179
+
180
+ private async getInsertContent ( params : InsertParams , sanitizedPath : string ) : Promise < string > {
243
181
const fileContent = await fs . readFileText ( sanitizedPath )
244
182
const lines = fileContent . split ( '\n' )
245
183
@@ -252,11 +190,15 @@ ${await this.showAppendPreview(this.params.path, this.params.newStr)}
252
190
} else {
253
191
newContent = [ ...lines . slice ( 0 , insertLine ) , params . newStr , ...lines . slice ( insertLine ) ] . join ( '\n' )
254
192
}
193
+ return newContent
194
+ }
255
195
196
+ private async handleAppend ( params : AppendParams , sanitizedPath : string ) : Promise < void > {
197
+ const newContent = await this . getAppendContent ( params , sanitizedPath )
256
198
await fs . writeFile ( sanitizedPath , newContent )
257
199
}
258
200
259
- private async handleAppend ( params : AppendParams , sanitizedPath : string ) : Promise < void > {
201
+ private async getAppendContent ( params : AppendParams , sanitizedPath : string ) : Promise < string > {
260
202
const fileContent = await fs . readFileText ( sanitizedPath )
261
203
const needsNewline = fileContent . length !== 0 && ! fileContent . endsWith ( '\n' )
262
204
@@ -265,8 +207,7 @@ ${await this.showAppendPreview(this.params.path, this.params.newStr)}
265
207
contentToAppend = '\n' + contentToAppend
266
208
}
267
209
268
- const newContent = fileContent + contentToAppend
269
- await fs . writeFile ( sanitizedPath , newContent )
210
+ return fileContent + contentToAppend
270
211
}
271
212
272
213
private getCreateCommandText ( params : CreateParams ) : string {
0 commit comments