cm-tarnation
Version:
An alternative parser for CodeMirror 6
148 lines (147 loc) • 6.1 kB
TypeScript
import type { CompletionSource } from "@codemirror/autocomplete";
import type { LanguageDescription } from "@codemirror/language";
import type { Extension, Facet } from "@codemirror/state";
import type { Input, NodePropSource, SyntaxNodeRef } from "@lezer/common";
import type { TarnationCompletionContext } from "./completion/context";
import type { Grammar } from "./grammar/definition";
import type { Node } from "./grammar/node";
import type { Rule } from "./grammar/rules/rule";
import type { State } from "./grammar/rules/state";
import type { TarnationLanguage } from "./language";
export interface ParserConfiguration {
/** Node props to add to the emitted nodes of the grammar. */
props?: NodePropSource[];
/**
* A record of variables to pass to the grammar. They can be referenced
* in the grammar using the `$var:foo` syntax.
*/
variables?: VariableTable;
/**
* A special function that can be provided for nesting languages. It is
* given a node, in the form of a `SyntaxNodeRef`, and the document `Input`.
* It should return `null` (skip this node) or an object with a `name`
* string and optionally a list of ranges in the `overlay` property.
*
* If the latter is returned, that information will be used to nest, if
* possible, the given language (by name) in the ranges specified.
*/
nest?: (cursor: SyntaxNodeRef, input: Input) => null | {
name: string;
overlay?: {
from: number;
to: number;
}[];
};
/**
* Autocompletion source functions. The key is name of the autocomplete
* handler as given by the grammar definition. A key name can also be a
* whitespace separated list of autocomplete handler names.
*
* The value is a function that takes a completion context and returns a
* completion source.
*
* There are a few special keys, which can be used to provide
* configuration for the autocompletion. This is why the index signature
* has `boolean`, when it shouldn't. This is a TypeScript limitation.
*/
autocomplete?: {
/** If true, you can use the grammar type names as autocompletion handlers. */
_alsoTypeNames?: boolean;
/** If true, you can use the emitted names of nodes as autocompletion handlers. */
_alsoEmitNames?: boolean;
/**
* If true, autocomplete will try to be invoked for the entire node
* stack at the cursor, rather than just the current node.
*/
_traverseUpwards?: boolean;
/** Default autocompletion handler if nothing else can used. */
"*"?: AutocompleteHandler;
[key: string]: AutocompleteHandler | boolean | undefined;
};
}
/** The options / interface required to create a Tarnation language. */
export interface TarnationLanguageDefinition {
/**
* The name of the language. This property is important for CodeMirror,
* so make sure it's reasonable.
*/
name: string;
/**
* The grammar that will be used to tokenize the language.
*
* This value can be provided as a function, which will cause the grammar
* to be lazily evaluated.
*/
grammar: Grammar | (() => Grammar);
/**
* A list (or facet) of `LanguageDescription` objects that will be used
* when the parser nests in a language.
*/
nestLanguages?: LanguageDescription[] | Facet<LanguageDescription>;
/** Configuration options for the parser, such as node props. */
configure?: ParserConfiguration;
/** A list of aliases for the name of the language. (e.g. 'go' - `['golang']`) */
alias?: string[];
/** A list of file extensions. (e.g. `['.ts']`) */
extensions?: string[];
/**
* The 'languageData' field inherit to the {@link Language}. CodeMirror
* plugins are defined by, or use, the data in this field. e.g.
* indentation, autocomplete, etc.
*/
languageData?: Record<string, any>;
/** Extra extensions to be loaded. */
supportExtensions?: Extension[];
}
export declare type AutocompleteHandler = (this: TarnationLanguage, context: TarnationCompletionContext) => ReturnType<CompletionSource>;
/**
* Standard interface for a matcher of some kind. Takes a string input and
* matches it against some sort of internal pattern.
*/
export interface Matcher {
/** Returns if the given string is matched by a pattern. */
test(str: string, pos?: number): boolean;
/**
* Returns a {@link MatchOutput}, describing how a string matched against
* a pattern (if it did at all).
*/
match(str: string, pos?: number): MatchOutput;
}
/** Standard output for a {@link Matcher}. */
export declare type MatchOutput = null | {
/** The entirety of the substring matched. */
total: string;
/**
* Captures for this match, if any. Captures must be contiguous
* substrings of the total match.
*/
captures: string[] | null;
/** The length of the match. */
length: number;
};
/** A variable for use by a {@link Grammar}. */
export declare type Variable = Matcher | string | string[] | RegExp;
/** A simple record of {@link Variable}s. */
export declare type VariableTable = Record<string, Variable>;
/** An individual element in a {@link GrammarStack}. */
export interface GrammarStackElement {
/** The current parent {@link Node}. */
node: Node;
/** The rules to loop parsing with. */
rules: (Rule | State)[];
/**
* A specific {@link Rule} that, when matched, should pop this element off
* the stack.
*/
end: Rule | State | null;
}
/** Represents how the parser should nest tokens. */
export declare type ParserAction = number[];
/** Token emitted by a {@link Matched} when compiled. */
export declare type GrammarToken = [
id: number | null,
from: number,
to: number,
open?: ParserAction,
close?: ParserAction
];