Skip to content

Commit 538fedb

Browse files
committed
Add line numbers when reading files and writing files
1 parent 27b4bb2 commit 538fedb

File tree

4 files changed

+39
-10
lines changed

4 files changed

+39
-10
lines changed

src/core/Cline.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { ApiHandler, buildApiHandler } from "../api"
1212
import { ApiStream } from "../api/transform/stream"
1313
import { DiffViewProvider } from "../integrations/editor/DiffViewProvider"
1414
import { findToolName, formatContentBlockToMarkdown } from "../integrations/misc/export-markdown"
15-
import { extractTextFromFile } from "../integrations/misc/extract-text"
15+
import { extractTextFromFile, addLineNumbers } from "../integrations/misc/extract-text"
1616
import { TerminalManager } from "../integrations/terminal/TerminalManager"
1717
import { UrlContentFetcher } from "../services/browser/UrlContentFetcher"
1818
import { listFiles } from "../services/glob/list-files"
@@ -1133,8 +1133,8 @@ export class Cline {
11331133
)
11341134
pushToolResult(
11351135
`The user made the following updates to your content:\n\n${userEdits}\n\n` +
1136-
`The updated content, which includes both your original modifications and the user's edits, has been successfully saved to ${relPath.toPosix()}. Here is the full, updated content of the file:\n\n` +
1137-
`<final_file_content path="${relPath.toPosix()}">\n${finalContent}\n</final_file_content>\n\n` +
1136+
`The updated content, which includes both your original modifications and the user's edits, has been successfully saved to ${relPath.toPosix()}. Here is the full, updated content of the file, including line numbers:\n\n` +
1137+
`<final_file_content path="${relPath.toPosix()}">\n${addLineNumbers(finalContent || '')}\n</final_file_content>\n\n` +
11381138
`Please note:\n` +
11391139
`1. You do not need to re-write the file with these changes, as they have already been applied.\n` +
11401140
`2. Proceed with the task using this updated file content as the new baseline.\n` +
@@ -1245,8 +1245,8 @@ export class Cline {
12451245
)
12461246
pushToolResult(
12471247
`The user made the following updates to your content:\n\n${userEdits}\n\n` +
1248-
`The updated content, which includes both your original modifications and the user's edits, has been successfully saved to ${relPath.toPosix()}. Here is the full, updated content of the file:\n\n` +
1249-
`<final_file_content path="${relPath.toPosix()}">\n${finalContent}\n</final_file_content>\n\n` +
1248+
`The updated content, which includes both your original modifications and the user's edits, has been successfully saved to ${relPath.toPosix()}. Here is the full, updated content of the file, including line numbers:\n\n` +
1249+
`<final_file_content path="${relPath.toPosix()}">\n${addLineNumbers(finalContent || '')}\n</final_file_content>\n\n` +
12501250
`Please note:\n` +
12511251
`1. You do not need to re-write the file with these changes, as they have already been applied.\n` +
12521252
`2. Proceed with the task using this updated file content as the new baseline.\n` +
@@ -2263,3 +2263,4 @@ export class Cline {
22632263
return `<environment_details>\n${details.trim()}\n</environment_details>`
22642264
}
22652265
}
2266+

src/core/prompts/system.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Usage:
4646
</execute_command>
4747
4848
## read_file
49-
Description: Request to read the contents of a file at the specified path. Use this when you need to examine the contents of an existing file you do not know the contents of, for example to analyze code, review text files, or extract information from configuration files. Automatically extracts raw text from PDF and DOCX files. May not be suitable for other types of binary files, as it returns the raw content as a string.
49+
Description: Request to read the contents of a file at the specified path. Use this when you need to examine the contents of an existing file you do not know the contents of, for example to analyze code, review text files, or extract information from configuration files. The output includes line numbers prefixed to each line (e.g. "1 | const x = 1"), making it easier to reference specific lines when creating diffs or discussing code. Automatically extracts raw text from PDF and DOCX files. May not be suitable for other types of binary files, as it returns the raw content as a string.
5050
Parameters:
5151
- path: (required) The path of the file to read (relative to the current working directory ${cwd.toPosix()})
5252
Usage:
@@ -361,3 +361,4 @@ The following additional instructions are provided by the user, and should be fo
361361
${joinedInstructions}`
362362
: ""
363363
}
364+

src/core/webview/__tests__/ClineProvider.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ jest.mock('../../Cline', () => {
7676
}
7777
})
7878

79+
// Mock extract-text
80+
jest.mock('../../../integrations/misc/extract-text', () => ({
81+
extractTextFromFile: jest.fn().mockImplementation(async (filePath: string) => {
82+
const content = 'const x = 1;\nconst y = 2;\nconst z = 3;'
83+
const lines = content.split('\n')
84+
return lines.map((line, index) => `${index + 1} | ${line}`).join('\n')
85+
})
86+
}))
87+
7988
// Spy on console.error and console.log to suppress expected messages
8089
beforeAll(() => {
8190
jest.spyOn(console, 'error').mockImplementation(() => {})
@@ -258,4 +267,10 @@ describe('ClineProvider', () => {
258267
expect(mockContext.globalState.update).toHaveBeenCalledWith('soundEnabled', false)
259268
expect(mockPostMessage).toHaveBeenCalled()
260269
})
270+
271+
test('file content includes line numbers', async () => {
272+
const { extractTextFromFile } = require('../../../integrations/misc/extract-text')
273+
const result = await extractTextFromFile('test.js')
274+
expect(result).toBe('1 | const x = 1;\n2 | const y = 2;\n3 | const z = 3;')
275+
})
261276
})

src/integrations/misc/extract-text.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export async function extractTextFromFile(filePath: string): Promise<string> {
2222
default:
2323
const isBinary = await isBinaryFile(filePath).catch(() => false)
2424
if (!isBinary) {
25-
return await fs.readFile(filePath, "utf8")
25+
return addLineNumbers(await fs.readFile(filePath, "utf8"))
2626
} else {
2727
throw new Error(`Cannot read text for file type: ${fileExtension}`)
2828
}
@@ -32,12 +32,12 @@ export async function extractTextFromFile(filePath: string): Promise<string> {
3232
async function extractTextFromPDF(filePath: string): Promise<string> {
3333
const dataBuffer = await fs.readFile(filePath)
3434
const data = await pdf(dataBuffer)
35-
return data.text
35+
return addLineNumbers(data.text)
3636
}
3737

3838
async function extractTextFromDOCX(filePath: string): Promise<string> {
3939
const result = await mammoth.extractRawText({ path: filePath })
40-
return result.value
40+
return addLineNumbers(result.value)
4141
}
4242

4343
async function extractTextFromIPYNB(filePath: string): Promise<string> {
@@ -51,5 +51,17 @@ async function extractTextFromIPYNB(filePath: string): Promise<string> {
5151
}
5252
}
5353

54-
return extractedText
54+
return addLineNumbers(extractedText)
5555
}
56+
57+
export function addLineNumbers(content: string): string {
58+
const lines = content.split('\n')
59+
const maxLineNumberWidth = String(lines.length).length
60+
return lines
61+
.map((line, index) => {
62+
const lineNumber = String(index + 1).padStart(maxLineNumberWidth, ' ')
63+
return `${lineNumber} | ${line}`
64+
}).join('\n')
65+
}
66+
67+

0 commit comments

Comments
 (0)