Skip to content

Commit eacc60f

Browse files
committed
Add breadcrumbs for datacard sections
1 parent dc224db commit eacc60f

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

images/datacard_outline.png

88.3 KB
Loading

src/extension.js

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ function activate(context) {
170170
})
171171
);
172172

173+
// Register the document symbol provider for outline view and breadcrumbs
174+
context.subscriptions.push(
175+
vscode.languages.registerDocumentSymbolProvider(
176+
{ language: 'combine-datacard' },
177+
new CombineDocumentSymbolProvider()
178+
)
179+
);
173180
}
174181

175182
function hasShapeSection(document) {
@@ -454,6 +461,145 @@ class CombineCompletionItemProvider {
454461
}
455462
}
456463

464+
class CombineDocumentSymbolProvider {
465+
provideDocumentSymbols(document, token) {
466+
const symbols = [];
467+
const dashLineRegex = /^-{3,}$/;
468+
const dashLineNumbers = [];
469+
const hasShape = hasShapeSection(document);
470+
471+
// Find all section dividers
472+
for (let i = 0; i < document.lineCount; i++) {
473+
const lineText = document.lineAt(i).text.trim();
474+
if (dashLineRegex.test(lineText)) {
475+
dashLineNumbers.push(i);
476+
}
477+
}
478+
479+
// Create symbols for each section
480+
if (dashLineNumbers.length > 0) {
481+
// Handle content before first divider as a section
482+
if (dashLineNumbers[0] > 0) {
483+
const preHeaderRange = new vscode.Range(0, 0, dashLineNumbers[0] - 1, document.lineAt(dashLineNumbers[0] - 1).text.length);
484+
let isHeader = false;
485+
486+
// Check if this section contains the header block (imax/jmax/kmax)
487+
for (let i = 0; i <= Math.min(dashLineNumbers[0] - 3, document.lineCount - 3); i++) {
488+
if (document.lineAt(i).text.trim().startsWith('imax') &&
489+
document.lineAt(i+1).text.trim().startsWith('jmax') &&
490+
document.lineAt(i+2).text.trim().startsWith('kmax')) {
491+
isHeader = true;
492+
break;
493+
}
494+
}
495+
496+
symbols.push(new vscode.DocumentSymbol(
497+
isHeader ? "Header section" : "Pre-header section",
498+
"",
499+
vscode.SymbolKind.String,
500+
preHeaderRange,
501+
preHeaderRange
502+
));
503+
}
504+
505+
// Handle sections between dividers
506+
for (let i = 0; i < dashLineNumbers.length - 1; i++) {
507+
const startLine = dashLineNumbers[i] + 1;
508+
const endLine = dashLineNumbers[i + 1] - 1;
509+
510+
if (endLine >= startLine) {
511+
const sectionRange = new vscode.Range(startLine, 0, endLine, document.lineAt(endLine).text.length);
512+
const sectionInfo = getSectionIndex(document, startLine);
513+
const adjustedSection = calculateAdjustedSection(sectionInfo, hasShape);
514+
515+
// Get section name using the same logic as CombineCompletionItemProvider
516+
let sectionName = "Other section";
517+
switch (adjustedSection) {
518+
case -1:
519+
sectionName = "Pre-header section";
520+
break;
521+
case 0:
522+
sectionName = "Header section";
523+
break;
524+
case 1:
525+
sectionName = "Shapes section";
526+
break;
527+
case 2:
528+
sectionName = "Channel definition section";
529+
break;
530+
case 3:
531+
sectionName = "Process definition section";
532+
break;
533+
case 4:
534+
sectionName = "Systematics section";
535+
break;
536+
}
537+
538+
symbols.push(new vscode.DocumentSymbol(
539+
sectionName,
540+
"",
541+
vscode.SymbolKind.Struct,
542+
sectionRange,
543+
sectionRange
544+
));
545+
}
546+
}
547+
548+
// Handle content after last divider
549+
if (dashLineNumbers[dashLineNumbers.length - 1] < document.lineCount - 1) {
550+
const startLine = dashLineNumbers[dashLineNumbers.length - 1] + 1;
551+
const endLine = document.lineCount - 1;
552+
const sectionRange = new vscode.Range(startLine, 0, endLine, document.lineAt(endLine).text.length);
553+
const sectionInfo = getSectionIndex(document, startLine);
554+
const adjustedSection = calculateAdjustedSection(sectionInfo, hasShape);
555+
556+
// Get section name using the same logic as CombineCompletionItemProvider
557+
let sectionName = "Other section";
558+
switch (adjustedSection) {
559+
case -1:
560+
sectionName = "Pre-header section";
561+
break;
562+
case 0:
563+
sectionName = "Header section";
564+
break;
565+
case 1:
566+
sectionName = "Shapes section";
567+
break;
568+
case 2:
569+
sectionName = "Channel definition section";
570+
break;
571+
case 3:
572+
sectionName = "Process definition section";
573+
break;
574+
case 4:
575+
sectionName = "Systematics section";
576+
break;
577+
}
578+
579+
symbols.push(new vscode.DocumentSymbol(
580+
sectionName,
581+
"",
582+
vscode.SymbolKind.Struct,
583+
sectionRange,
584+
sectionRange
585+
));
586+
}
587+
} else {
588+
// If no dividers, treat the whole document as one section
589+
const docRange = new vscode.Range(0, 0, document.lineCount - 1, document.lineAt(document.lineCount - 1).text.length);
590+
symbols.push(new vscode.DocumentSymbol(
591+
"Datacard",
592+
"",
593+
vscode.SymbolKind.File,
594+
docRange,
595+
docRange
596+
));
597+
}
598+
599+
return symbols;
600+
}
601+
}
602+
457603
function deactivate() {}
458604

459605
module.exports = {

0 commit comments

Comments
 (0)