Something went wrong. Try again.
source dump of claude code forked from oppi.li/claude-code
Something went wrong. Try again.
3.4 kB · 90 lines
TypeScript
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091import { logForDebugging } from '../../utils/debug.js'import { truncate } from '../../utils/format.js'import { getFsImplementation } from '../../utils/fsOperations.js'import { expandPath } from '../../utils/path.js'
const MAX_READ_BYTES = 64 * 1024
/** * Extracts the symbol/word at a specific position in a file. * Used to show context in tool use messages. * * @param filePath - The file path (absolute or relative) * @param line - 0-indexed line number * @param character - 0-indexed character position on the line * * Note: This uses synchronous file I/O because it is called from * renderToolUseMessage (a synchronous React render function). The read is * wrapped in try/catch so ENOENT and other errors fall back gracefully. * @returns The symbol at that position, or null if extraction fails */export function getSymbolAtPosition( filePath: string, line: number, character: number,): string | null { try { const fs = getFsImplementation() const absolutePath = expandPath(filePath)
// Read only the first 64KB instead of the whole file. Most LSP hover/goto // targets are near recent edits; 64KB covers ~1000 lines of typical code. // If the target line is past this window we fall back to null (the UI // already handles that by showing `position: line:char`). // eslint-disable-next-line custom-rules/no-sync-fs -- called from sync React render (renderToolUseMessage) const { buffer, bytesRead } = fs.readSync(absolutePath, { length: MAX_READ_BYTES, }) const content = buffer.toString('utf-8', 0, bytesRead) const lines = content.split('\n')
if (line < 0 || line >= lines.length) { return null } // If we filled the full buffer the file continues past our window, // so the last split element may be truncated mid-line. if (bytesRead === MAX_READ_BYTES && line === lines.length - 1) { return null }
const lineContent = lines[line] if (!lineContent || character < 0 || character >= lineContent.length) { return null }
// Extract the word/symbol at the character position // Pattern matches: // - Standard identifiers: alphanumeric + underscore + dollar // - Rust lifetimes: 'a, 'static // - Rust macros: macro_name! // - Operators and special symbols: +, -, *, etc. // This is more inclusive to handle various programming languages const symbolPattern = /[\w$'!]+|[+\-*/%&|^~<>=]+/g let match: RegExpExecArray | null
while ((match = symbolPattern.exec(lineContent)) !== null) { const start = match.index const end = start + match[0].length
// Check if the character position falls within this match if (character >= start && character < end) { const symbol = match[0] // Limit length to 30 characters to avoid overly long symbols return truncate(symbol, 30) } }
return null } catch (error) { // Log unexpected errors for debugging (permission issues, encoding problems, etc.) // Use logForDebugging since this is a display enhancement, not a critical error if (error instanceof Error) { logForDebugging( `Symbol extraction failed for ${filePath}:${line}:${character}: ${error.message}`, { level: 'warn' }, ) } // Still return null for graceful fallback to position display return null }}