Introduce SourceRegion
This commit is contained in:
parent
9939f6c97f
commit
a439f15c5f
1 changed files with 41 additions and 9 deletions
50
src/index.ts
50
src/index.ts
|
|
@ -97,6 +97,22 @@ export class SourceText {
|
|||
return { index, line, column };
|
||||
}
|
||||
|
||||
// Creates a SourceRegion from a Span.
|
||||
makeRegion(span: Span): SourceRegion {
|
||||
// Basic validation
|
||||
if (span.start.index < 0 || span.end.index > this.length) {
|
||||
throw new Error(`Span out of bounds: ${span.start.index}-${span.end.index} (length: ${this.length})`);
|
||||
}
|
||||
return new SourceRegion(this, span);
|
||||
}
|
||||
|
||||
// Creates a SourceRegion covering the entire SourceText.
|
||||
fullRegion(): SourceRegion {
|
||||
const start = this.getLocation(0);
|
||||
const end = this.getLocation(this.length);
|
||||
return this.makeRegion({ start, end });
|
||||
}
|
||||
|
||||
// Returns the full text of a specific line (1-based index)
|
||||
getLineText(line: number): string {
|
||||
const lineIndex = line - 1;
|
||||
|
|
@ -132,17 +148,28 @@ export function sourceText(s: string): SourceText {
|
|||
}
|
||||
|
||||
export class SourceRegion {
|
||||
// TODO
|
||||
readonly sourceText: SourceText;
|
||||
readonly span: Span;
|
||||
constructor(
|
||||
public readonly source: SourceText,
|
||||
public readonly span: Span
|
||||
) {}
|
||||
|
||||
constructor(sourceText: SourceText, span: Span) {
|
||||
this.sourceText = sourceText;
|
||||
// TODO: What about span validation?
|
||||
this.span = span;
|
||||
}
|
||||
get length(): number {
|
||||
return this.span.end.index - this.span.start.index;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this.source.sliceByCp(this.span.start.index, this.span.end.index);
|
||||
}
|
||||
|
||||
// Creates a sub-region within this region.
|
||||
// Validates that the new span is contained within the current region.
|
||||
subRegion(span: Span): SourceRegion {
|
||||
if (span.start.index < this.span.start.index || span.end.index > this.span.end.index) {
|
||||
throw new Error(`Sub-region span ${span.start.index}-${span.end.index} is not within parent region ${this.span.start.index}-${this.span.end.index}`);
|
||||
}
|
||||
return this.source.makeRegion(span);
|
||||
}
|
||||
}
|
||||
|
||||
export type Span = {
|
||||
start: SourceLocation;
|
||||
|
|
@ -190,7 +217,12 @@ export type LineView = {
|
|||
underline: string; // The literal "^^^" string for CLI usage
|
||||
};
|
||||
|
||||
export function renderSpan(text: SourceText, span: Span, contextLines = 1): LineView[] {
|
||||
export function renderRegion(region: SourceRegion, contextLines = 1): LineView[] {
|
||||
return renderSpan(region, region.span, contextLines);
|
||||
}
|
||||
|
||||
export function renderSpan(region: SourceRegion, span: Span, contextLines = 1): LineView[] {
|
||||
const text = region.source;
|
||||
const views: LineView[] = [];
|
||||
|
||||
// Determine range of lines to show (including context)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue