using System.Collections.Frozen;
namespace AIStudio.Tools.CodeHighlighting;
///
/// How a language looks to the CodeTokenizer: its words, comments, strings, and the few habits of its
/// own, such as the dollar sign of a shell variable.
///
///
/// The rules describe what a reader recognizes at a glance, not the grammar of the language. Whatever
/// they leave out stays plain, which is no error.
///
public sealed class CodeLanguageRules
{
private static readonly FrozenSet NO_WORDS = Words();
///
/// The keywords, such as if or return.
///
public FrozenSet Keywords { get; init; } = NO_WORDS;
///
/// The names of built-in types, such as int.
///
public FrozenSet Types { get; init; } = NO_WORDS;
///
/// The words which stand for a value, such as true or null.
///
public FrozenSet Literals { get; init; } = NO_WORDS;
///
/// The keywords after which the name of a function follows, such as def. Each of them has to be one
/// of the keywords, too.
///
public FrozenSet FunctionDeclarations { get; init; } = NO_WORDS;
///
/// The keywords after which the name of a type follows, such as class. Each of them has to be one of
/// the keywords, too.
///
public FrozenSet TypeDeclarations { get; init; } = NO_WORDS;
///
/// What starts a comment to the end of its line, such as //.
///
public IReadOnlyList LineComments { get; init; } = [];
///
/// Whether a line comment starts only at the beginning of a word, as the # of a shell does: in $# or
/// a#b, it starts none.
///
public bool LineCommentsNeedSeparator { get; init; }
///
/// The kinds of block comments, such as /* … */.
///
public IReadOnlyList BlockComments { get; init; } = [];
///
/// The kinds of strings. The first one whose opening matches wins, so a longer opening, such as three
/// quotation marks, has to come before a shorter one.
///
public IReadOnlyList Strings { get; init; } = [];
///
/// The kinds of quoted names, such as "column" in SQL. They stay plain, but no keyword within them
/// gets a color.
///
public IReadOnlyList QuotedNames { get; init; } = [];
///
/// The words which may stand right before a string and belong to it, such as the f of an f-string in
/// Python.
///
public FrozenSet StringPrefixes { get; init; } = NO_WORDS;
///
/// Whether the language writes long strings and comments in brackets, as Lua does with [[ … ]] and
/// --[==[ … ]==].
///
public bool HasLongBrackets { get; init; }
///
/// The character which starts the name of a variable, such as $, or null when there is none.
///
public char? VariablePrefix { get; init; }
///
/// The characters which may appear within the name of a variable beyond letters, digits, and the
/// underscore, such as the colon of $env:PATH.
///
public string VariableNameCharacters { get; init; } = string.Empty;
///
/// The character which starts an annotation or decorator, such as @, or null when there is none.
///
public char? AnnotationPrefix { get; init; }
///
/// Whether a # at the start of a line begins a directive to the end of the line, as #include does.
///
public bool HasPreprocessor { get; init; }
///
/// The characters which may start a word beyond letters and the underscore, such as the $ of
/// JavaScript. A hyphen starts a word only when a letter, an underscore, or another hyphen follows it.
///
public string WordStartCharacters { get; init; } = string.Empty;
///
/// The characters which may appear within a word beyond letters, digits, and the underscore, such as
/// the hyphen of a CSS property.
///
public string WordCharacters { get; init; } = string.Empty;
///
/// Whether a name followed directly by an opening parenthesis is a function.
///
public bool HighlightFunctionCalls { get; init; } = true;
///
/// Whether a name in PascalCase is a type, as in Java.
///
public bool HighlightPascalCaseTypes { get; init; }
///
/// Whether a word of the form Verb-Noun is a command, as in PowerShell.
///
public bool HighlightCommandNames { get; init; }
///
/// The operators written as a word after a hyphen, such as -eq in PowerShell. Any other word after a
/// hyphen is the name of a parameter and stays plain.
///
public FrozenSet HyphenOperators { get; init; } = NO_WORDS;
///
/// Whether a name in square brackets is a type, as [string] in PowerShell.
///
public bool HasBracketTypes { get; init; }
///
/// Whether the code is a style sheet: selectors, properties, and values instead of statements.
///
public bool IsStyleSheet { get; init; }
///
/// A set of words which match exactly as they are written.
///
/// The words.
/// The set of words.
public static FrozenSet Words(params string[] words) => words.ToFrozenSet(StringComparer.Ordinal);
///
/// A set of words which match in any case, for the languages which ignore it, such as SQL.
///
/// The words.
/// The set of words.
public static FrozenSet WordsInAnyCase(params string[] words) => words.ToFrozenSet(StringComparer.OrdinalIgnoreCase);
}