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++;
}
});
}
}
});
}