diff --git a/val_highlight/CHANGELOG.md b/val_highlight/CHANGELOG.md index bb2f4e9..6046b4d 100644 --- a/val_highlight/CHANGELOG.md +++ b/val_highlight/CHANGELOG.md @@ -1,3 +1,26 @@ +## Unreleased + +### Added + +* **`EditingSyntax`** — how a language is edited: its line and block + comment markers, bracket pairs and quote characters. Every built-in + language declares one; set `Grammar.editing` on your own, or let + `EditingSyntax.of` derive it from the grammar's `LineComment`, + `BlockComment` and `QuotedString` blocks. `Grammar.extend` takes an + `editing` argument. +* **`HighlightResult.matchingBracket`** — finds the matching bracket by + walking tokens, skipping brackets inside strings and comments. +* **`HighlightResult.isStringOrCommentAt`**, **`isCommentAt`** and + **`isInsideStringOrComment`** — tell code apart from strings and + comments, at a character or at a caret position. Interpolations inside + strings count as code. +* **`ScopeTable.isStringOrComment`** and **`isComment`** — the same + questions for a scope stack, answered from a table built once per stack. + +### Changed + +* Markdown highlights HTML comments (``) as comments. + ## 0.1.0 First release. diff --git a/val_highlight/README.md b/val_highlight/README.md index b25abda..0e57ed6 100644 --- a/val_highlight/README.md +++ b/val_highlight/README.md @@ -162,6 +162,28 @@ final document = IncrementalHighlighter(language: dartLanguage, text: source); final updated = document.update(editedSource); ``` +Results also answer the questions an editor asks, using the tokens, so +brackets and quotes inside strings and comments are never mistaken for +code: + +```dart +result.matchingBracket(offset); // the matching bracket, or -1 +result.isStringOrCommentAt(offset); // the character at offset +result.isInsideStringOrComment(caret); // text typed at a caret position +``` + +Each language also describes how it is edited — its comment markers, +bracket pairs and quote characters — as an `EditingSyntax`: + +```dart +final syntax = EditingSyntax.of(pythonLanguage); +syntax.lineComment; // '#' +syntax.quotes; // '"\'' +``` + +Set `editing:` on your own grammar, or leave it out and it is derived from +the grammar's `LineComment`, `BlockComment` and `QuotedString` blocks. + ## 🔧 Changing a built-in language ```dart @@ -178,6 +200,11 @@ final withTodos = dartLanguage.extend( // Replace a named part of a grammar. `grammar.repository.keys` lists them. final quiet = dartLanguage.extend(repository: {'numbers': []}); + +// Change how it is edited: comment markers, brackets and quotes. +final backticks = dartLanguage.extend( + editing: EditingSyntax.cStyle.copyWith(quotes: '"\'`'), +); ``` A new scope such as `todo` only needs a theme entry: diff --git a/val_highlight/lib/languages/bash.dart b/val_highlight/lib/languages/bash.dart index d8b20bc..910b413 100644 --- a/val_highlight/lib/languages/bash.dart +++ b/val_highlight/lib/languages/bash.dart @@ -3,6 +3,7 @@ import '../advanced.dart'; /// Bash and POSIX shell scripts. const bashLanguage = Grammar( name: 'bash', + editing: EditingSyntax(lineComment: '#', quotes: '"\'`'), aliases: ['sh', 'shell', 'zsh', 'console'], fileExtensions: ['sh', 'bash', 'zsh'], shebangs: ['bash', 'sh', 'zsh', 'dash', 'ksh'], diff --git a/val_highlight/lib/languages/batch.dart b/val_highlight/lib/languages/batch.dart index 2b40aa8..59f4f06 100644 --- a/val_highlight/lib/languages/batch.dart +++ b/val_highlight/lib/languages/batch.dart @@ -3,6 +3,7 @@ import '../advanced.dart'; /// Windows batch files (`.bat`, `.cmd`). const batchLanguage = Grammar( name: 'batch', + editing: EditingSyntax(lineComment: 'REM', quotes: '"'), aliases: ['bat', 'cmd', 'dos'], fileExtensions: ['bat', 'cmd'], caseInsensitive: true, diff --git a/val_highlight/lib/languages/c.dart b/val_highlight/lib/languages/c.dart index 5846c8c..12e6df6 100644 --- a/val_highlight/lib/languages/c.dart +++ b/val_highlight/lib/languages/c.dart @@ -38,6 +38,7 @@ const cCommonRules = [ /// C. const cLanguage = Grammar( name: 'c', + editing: EditingSyntax.cStyle, aliases: ['h'], fileExtensions: ['c', 'h'], signatures: [ diff --git a/val_highlight/lib/languages/clojure.dart b/val_highlight/lib/languages/clojure.dart index c103444..37d76c1 100644 --- a/val_highlight/lib/languages/clojure.dart +++ b/val_highlight/lib/languages/clojure.dart @@ -3,6 +3,7 @@ import '../advanced.dart'; /// Clojure, ClojureScript and EDN. const clojureLanguage = Grammar( name: 'clojure', + editing: EditingSyntax(lineComment: ';', quotes: '"'), aliases: ['clj', 'cljs', 'cljc', 'edn'], fileExtensions: ['clj', 'cljs', 'cljc', 'edn'], signatures: [ diff --git a/val_highlight/lib/languages/cmake.dart b/val_highlight/lib/languages/cmake.dart index 265ca8e..6ce318a 100644 --- a/val_highlight/lib/languages/cmake.dart +++ b/val_highlight/lib/languages/cmake.dart @@ -10,6 +10,7 @@ const _controlCommands = [ /// CMake. const cmakeLanguage = Grammar( name: 'cmake', + editing: EditingSyntax(lineComment: '#', quotes: '"'), aliases: ['cmakelists'], fileExtensions: ['cmake'], fileNames: ['CMakeLists.txt'], diff --git a/val_highlight/lib/languages/cpp.dart b/val_highlight/lib/languages/cpp.dart index ba455bc..65a12fa 100644 --- a/val_highlight/lib/languages/cpp.dart +++ b/val_highlight/lib/languages/cpp.dart @@ -4,6 +4,7 @@ import 'c.dart'; /// C++ (C++23). const cppLanguage = Grammar( name: 'cpp', + editing: EditingSyntax.cStyle, aliases: ['c++', 'cxx', 'hpp', 'cc', 'hh'], fileExtensions: ['cpp', 'cc', 'cxx', 'hpp', 'hh', 'hxx', 'ipp', 'ixx'], signatures: [ diff --git a/val_highlight/lib/languages/csharp.dart b/val_highlight/lib/languages/csharp.dart index 0dd7ba0..5cc2154 100644 --- a/val_highlight/lib/languages/csharp.dart +++ b/val_highlight/lib/languages/csharp.dart @@ -3,6 +3,7 @@ import '../advanced.dart'; /// C# (12+). const csharpLanguage = Grammar( name: 'csharp', + editing: EditingSyntax.cStyle, aliases: ['cs', 'c#'], fileExtensions: ['cs', 'csx'], signatures: [ diff --git a/val_highlight/lib/languages/css.dart b/val_highlight/lib/languages/css.dart index cf1a655..b999055 100644 --- a/val_highlight/lib/languages/css.dart +++ b/val_highlight/lib/languages/css.dart @@ -3,6 +3,7 @@ import '../advanced.dart'; /// CSS, including nesting and custom properties. const cssLanguage = Grammar( name: 'css', + editing: EditingSyntax(blockComment: ('/*', '*/')), fileExtensions: ['css'], caseInsensitive: true, signatures: [ diff --git a/val_highlight/lib/languages/dart.dart b/val_highlight/lib/languages/dart.dart index e963da5..f7f0e2c 100644 --- a/val_highlight/lib/languages/dart.dart +++ b/val_highlight/lib/languages/dart.dart @@ -3,6 +3,7 @@ import '../advanced.dart'; /// Dart. const dartLanguage = Grammar( name: 'dart', + editing: EditingSyntax.cStyle, fileExtensions: ['dart'], rules: [ IncludeRule('comments'), diff --git a/val_highlight/lib/languages/diff.dart b/val_highlight/lib/languages/diff.dart index 5265860..872a2ca 100644 --- a/val_highlight/lib/languages/diff.dart +++ b/val_highlight/lib/languages/diff.dart @@ -3,6 +3,7 @@ import '../advanced.dart'; /// Unified and git diffs. const diffLanguage = Grammar( name: 'diff', + editing: EditingSyntax.none, aliases: ['patch'], fileExtensions: ['diff', 'patch'], signatures: [r'^@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@', r'^diff --git '], diff --git a/val_highlight/lib/languages/dockerfile.dart b/val_highlight/lib/languages/dockerfile.dart index 301a267..8b0c4ce 100644 --- a/val_highlight/lib/languages/dockerfile.dart +++ b/val_highlight/lib/languages/dockerfile.dart @@ -6,6 +6,7 @@ import '../advanced.dart'; /// following `\` continuations. Heredocs (`RUN <` and JavaScript in `