function highlightMatchesInEditor()

in playground/tree-sitter/concrete-syntax.js [342:468]


function highlightMatchesInEditor(matches) {
    debugLog('highlightMatchesInEditor called with:', matches);
    
    // Clear previous highlights first
    clearHighlights();
    
    if (!matches || matches.length === 0) return;

    // Find CodeMirror instance directly
    const codeMirrorElements = document.querySelectorAll('.CodeMirror');
    let codeEditor = null;
    
    for (let cmElement of codeMirrorElements) {
        if (cmElement.CodeMirror) {
            codeEditor = cmElement.CodeMirror;
            break;
        }
    }
    
    if (!codeEditor) {
        debugLog('No CodeMirror instance found');
        return;
    }

    debugLog('Found CodeMirror, highlighting matches');

    // Use tree-sitter colors
    const colors = [
        "#0550ae", "#ab5000", "#116329", "#844708", "#6639ba", 
        "#7d4e00", "#0969da", "#1a7f37", "#cf222e", "#8250df"
    ];

    matches.forEach((match, index) => {
        debugLog('Processing match', index, ':', match);
        // Handle both snake_case and camelCase field names
        const range = match.range;
        const startPoint = range.startPoint || range.start_point;
        const endPoint = range.endPoint || range.end_point;
        
        if (range && startPoint && endPoint) {
            const from = {
                line: startPoint.row,
                ch: startPoint.column
            };
            const to = {
                line: endPoint.row, 
                ch: endPoint.column
            };

            // Highlight the full match with primary color
            codeEditor.markText(from, to, {
                css: `background-color: ${colors[0]}20; border: 1px solid ${colors[0]}60;`,
                title: `Concrete Syntax Match ${index + 1}`,
                className: 'concrete-syntax-match'
            });

            // Highlight captured variables with different colors
            const captures = match.matches;
            if (captures && typeof captures === 'object') {
                let colorIndex = 1;
                debugLog('Match captures:', captures);
                
                // Handle both Map and plain object
                const captureEntries = captures instanceof Map ? 
                    Array.from(captures.entries()) : 
                    Object.entries(captures);
                
                captureEntries.forEach(([key, captureData]) => {
                    debugLog('Capture:', key, captureData);
                    if (key !== '*' && captureData) {
                        const captureColor = colors[colorIndex % colors.length];
                        
                        // Check if captureData has range information (CapturedNode structure)
                        const captureRange = captureData.range;
                        const captureStartPoint = captureRange?.startPoint || captureRange?.start_point;
                        const captureEndPoint = captureRange?.endPoint || captureRange?.end_point;
                        
                        if (captureRange && captureStartPoint && captureEndPoint) {
                            // Use exact range from capture data
                            const captureFrom = {
                                line: captureStartPoint.row,
                                ch: captureStartPoint.column
                            };
                            const captureTo = {
                                line: captureEndPoint.row,
                                ch: captureEndPoint.column
                            };
                            
                            debugLog(`Highlighting capture ${key} from (${captureFrom.line},${captureFrom.ch}) to (${captureTo.line},${captureTo.ch})`);
                            
                            codeEditor.markText(captureFrom, captureTo, {
                                css: `background-color: ${captureColor}30; border: 1px solid ${captureColor}; border-radius: 2px;`,
                                title: `${key}: ${captureData.text || captureData}`,
                                className: 'concrete-syntax-capture'
                            });
                        } else if (typeof captureData === 'string') {
                            // Fallback: find the capture text within the match
                            const matchText = match.matchedString || match.matched_string || '';
                            const captureStart = matchText.indexOf(captureData);
                            
                            if (captureStart >= 0) {
                                const captureFrom = {
                                    line: from.line,
                                    ch: from.ch + captureStart
                                };
                                const captureTo = {
                                    line: from.line, 
                                    ch: from.ch + captureStart + captureData.length
                                };
                                
                                debugLog(`Highlighting string capture ${key} from (${captureFrom.line},${captureFrom.ch}) to (${captureTo.line},${captureTo.ch})`);
                                
                                codeEditor.markText(captureFrom, captureTo, {
                                    css: `background-color: ${captureColor}30; border: 1px solid ${captureColor}; border-radius: 2px;`,
                                    title: `${key}: ${captureData}`,
                                    className: 'concrete-syntax-capture'
                                });
                            }
                        }
                        
                        colorIndex++;
                    }
                });
            }
        }
    });
}