From f153843d010d98f47261616b8a67c7d4a3b4c28e Mon Sep 17 00:00:00 2001 From: JC-Chung <52159296+JC-Chung@users.noreply.github.com> Date: Fri, 31 Jul 2026 12:22:22 +0800 Subject: [PATCH 01/34] fix: off-by-one in commit message subject length calculation (#2596) --- src/Views/CommitMessageToolBox.axaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/CommitMessageToolBox.axaml.cs b/src/Views/CommitMessageToolBox.axaml.cs index 214f7fd8b..90128444f 100644 --- a/src/Views/CommitMessageToolBox.axaml.cs +++ b/src/Views/CommitMessageToolBox.axaml.cs @@ -243,7 +243,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang } } - if (lastLineStart < lastNonLineBreakCharIdx) + if (lastLineStart <= lastNonLineBreakCharIdx) { var validCharLen = text.Substring(lastLineStart).TrimEnd().Length; if (subjectLen > 0) From 13a95cd05de575a24748a1d4f22e54a68bd8fee2 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 31 Jul 2026 19:46:38 +0800 Subject: [PATCH 02/34] fix: the last auto-wrap character gets cropped in commit message editor (#2597) Signed-off-by: leo --- src/Views/CommitMessageToolBox.axaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/CommitMessageToolBox.axaml.cs b/src/Views/CommitMessageToolBox.axaml.cs index 90128444f..b8e8cd4dc 100644 --- a/src/Views/CommitMessageToolBox.axaml.cs +++ b/src/Views/CommitMessageToolBox.axaml.cs @@ -335,7 +335,7 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang // Sync the actual width to TextPresenter. Otherwise, `TextWrapping` will not work well without // a fixed width. See https://github.com/AvaloniaUI/Avalonia/issues/5819 if (_textPresenter != null) - _textPresenter.Width = Bounds.Width; + _textPresenter.Width = Bounds.Width - 10.0; } } From 18f178e0b314aab493478bfae7d2c66e8cada97a Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 31 Jul 2026 22:47:55 +0800 Subject: [PATCH 03/34] enhance: resize text presenter when scrollbar appeared/disappeared --- src/Views/CommitMessageToolBox.axaml.cs | 30 ++++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/Views/CommitMessageToolBox.axaml.cs b/src/Views/CommitMessageToolBox.axaml.cs index b8e8cd4dc..efdff3ba4 100644 --- a/src/Views/CommitMessageToolBox.axaml.cs +++ b/src/Views/CommitMessageToolBox.axaml.cs @@ -151,7 +151,7 @@ public override void Render(DrawingContext context) if (y >= 0.05) { - var w = Bounds.Width; + var w = _scrollViewer != null ? (_scrollViewer.Viewport.Width + 10) : Bounds.Width; var subjectEndTip = new FormattedText( "SUBJECT END", CultureInfo.CurrentCulture, @@ -160,7 +160,7 @@ public override void Render(DrawingContext context) 10, Brushes.Gray); context.DrawLine(pen, new Point(0, y), new Point(w, y)); - context.DrawText(subjectEndTip, new Point(w - subjectEndTip.WidthIncludingTrailingWhitespace - 18, y + 1)); + context.DrawText(subjectEndTip, new Point(w - subjectEndTip.WidthIncludingTrailingWhitespace - 8, y + 1)); } if (y == 0 && _subjectLen == 0) @@ -330,13 +330,6 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang Suggestions = null; } } - else if (change.Property == BoundsProperty) - { - // Sync the actual width to TextPresenter. Otherwise, `TextWrapping` will not work well without - // a fixed width. See https://github.com/AvaloniaUI/Avalonia/issues/5819 - if (_textPresenter != null) - _textPresenter.Width = Bounds.Width - 10.0; - } } protected override void OnLostFocus(RoutedEventArgs e) @@ -386,19 +379,34 @@ protected override void OnKeyDown(KeyEventArgs e) private void OnLayoutUpdated(object sender, EventArgs e) { + if (_textPresenter == null) + { + SubjectEndY = 0; + SuggestionPopupY = 0; + Suggestions = null; + return; + } + + var requiredWidth = _scrollViewer?.Viewport.Width ?? Bounds.Width; + if (Math.Abs(_textPresenter.Bounds.Width - requiredWidth) >= 0.01) + { + _textPresenter.Width = requiredWidth; + return; + } + if (_subjectEndCharIdx < 0) { SubjectEndY = 0; } else { - var y = _textPresenter?.TextLayout.HitTestTextPosition(_subjectEndCharIdx).Bottom ?? 0.0; + var y = _textPresenter.TextLayout.HitTestTextPosition(_subjectEndCharIdx).Bottom; var offset = _scrollViewer?.Offset.Y ?? 0; SubjectEndY = y - offset + 6; if (_suggestionMatchStartIdx >= 0) { - var popupY = _textPresenter?.TextLayout.HitTestTextPosition(_suggestionMatchStartIdx).Bottom ?? 0; + var popupY = _textPresenter.TextLayout.HitTestTextPosition(_suggestionMatchStartIdx).Bottom; y = popupY - offset; if (y < 0.05 || y > Bounds.Height - 0.05) { From fb2a9901939cdc82e893dcf73ddd036bdce460f8 Mon Sep 17 00:00:00 2001 From: Moritz Wieland <81433802+mowi12@users.noreply.github.com> Date: Mon, 3 Aug 2026 04:19:56 +0200 Subject: [PATCH 04/34] localization: complete German translations (#2600) --- src/Resources/Locales/de_DE.axaml | 107 ++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 57a344c63..8148d225a 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -25,10 +25,16 @@ Modell NEU GENERIEREN Verwende AI, um Commit-Nachrichten zu generieren + Übernehmen SourceGit minimieren + Andere ausblenden Alles anzeigen + 3-Way Merge Wähle die anzuwendende .patch-Datei Ignoriere Leerzeichen-Änderungen + Quelle: + Datei + Zwischenablage Patch anwenden Leerzeichen: Stash anwenden @@ -52,6 +58,8 @@ Schlecht Gut Überspringen + Bisecting. Einen anderen Commit auschecken und als gut oder schlecht markieren. + Bisecting. Aktuellen Commit als schlecht markieren oder einen anderen auschecken und als schlecht markieren. Bisecting. Aktuellen Commit als gut oder schlecht markieren und einen anderen auschecken. Bisecting. Ist der aktuelle HEAD gut oder schlecht? Blame @@ -62,6 +70,7 @@ Ausgewählte 2 Branches vergleichen Vergleichen mit… Vergleichen mit HEAD + Vergleichen mit ${0}$ Branch-Namen kopieren PR erstellen… PR für Upstream ${0}$ erstellen… @@ -113,6 +122,12 @@ Die folgenden Submodule müssen aktualisiert werden:{0}Möchtest du sie aktualisieren? Auschecken & Fast Forward Fast Forward zu: + Branch aus Stash auschecken + Neuer Branch: + Stash: + Commit oder Tag auschecken + Ziel: + Achtung: Danach ist HEAD losgelöst (‚detached‘) Cherry Pick Quelle an Commit-Nachricht anhängen Commit(s): @@ -124,6 +139,8 @@ Remote-Repository klonen Extra-Parameter: Zusätzliche Argumente für das Klonen des Repositorys. Optional. + Lesezeichen: + Gruppe: Lokaler Name: Repository-Name. Optional. Übergeordnetes Verzeichnis: @@ -131,14 +148,20 @@ Repository-URL: SCHLIESSEN Editor + Branches + Branches & Tags + Benutzerdefinierte Repository-Aktionen + Dateien der Revision Commit auschecken Diesen Commit cherry-picken Mehrere cherry-picken… Vergleiche mit HEAD Vergleiche mit Worktree Autor + Autor-Zeitpunkt Commit-Nachricht Committer + Committer-Zeitpunkt SHA Betreff Benutzerdefinierte Aktion @@ -158,6 +181,7 @@ ÄNDERUNGEN geänderte Datei(en) Änderungen durchsuchen… + Details einklappen DATEIEN LFS-DATEI Dateien durchsuchen… @@ -178,9 +202,15 @@ SHA Unterzeichner: Im Browser öffnen + SPALTE Commit-Nachricht eingeben. Leerzeile zum Trennen von Betreff und Beschreibung verwenden! BETREFF Vergleichen + ÄNDERUNGEN + COMMITS + NUR LINKS VORHANDENE COMMITS + NUR RECHTS VORHANDENE COMMITS + Tipp: Wenn die andere Seite HEAD ist, kannst du ausgewählte Commits über das Kontextmenü cherry-picken. Repository-Einstellungen COMMIT-VORLAGE Vordefinierte Parameter: @@ -225,6 +255,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Minute(n) Konventionelle Commit-Typen Standard-Remote + `--recursive` beim Auto-Aktualisieren von Submodulen verwenden Bevorzugter Merge-Modus TICKETSYSTEM Beispiel für Azure-DevOps-Regel hinzufügen @@ -257,8 +288,11 @@ $1, $2, … Werte der Eingabe-Steuerelemente Bezeichnung: Einträge: Nutze ‚|‘, um Einträge zu trennen + String-Formatierung: + Optional. Formatiert die Ausgabe. Wird ignoriert, wenn die Eingabe leer ist. Verwende bitte `${VALUE}` als Platzhalter für die Eingabe. Die vordefinierten Parameter ${REPO}, ${REMOTE}, ${BRANCH}, ${BRANCH_FRIENDLY_NAME}, ${SHA}, ${FILE} und ${TAG} bleiben hier verwendbar Typ: + Kurznamen verwenden: Arbeitsumgebungen Farbe Name @@ -266,6 +300,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente WEITER Leerer Commit erkannt! Möchtest du trotzdem fortfahren (--allow-empty)? ALLES STAGEN & COMMITTEN + AUSGEWÄHLTE STAGEN & COMMITTEN Leerer Commit erkannt! Möchtest du trotzdem fortfahren (--allow-empty) oder alle Änderungen stagen und dann committen? Neustart erforderlich Du musst dieses Programm neustarten, um die Änderungen zu übernehmen. @@ -278,6 +313,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Typ der Änderung: Kopieren Gesamten Text kopieren + Als Patch kopieren Ganzen Pfad kopieren Pfad kopieren Branch erstellen… @@ -309,7 +345,9 @@ $1, $2, … Werte der Eingabe-Steuerelemente Erzwinge Deinitialisierung, selbst wenn lokale Änderungen enthalten sind. Submodul: Branch löschen + Möchtest du auch den folgenden Remote-Branch löschen? Branch: + Löschen erzwingen, auch bei nicht gemergten Commits Du bist dabei, einen Remote-Branch zu löschen!!! Mehrere Branches löschen Du versuchst, mehrere Branches auf einmal zu löschen. Kontrolliere dies sorgfältig, bevor du fortfährst! @@ -330,6 +368,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Tag: Von Remote-Repositorys löschen BINÄRER VERGLEICH + LEERE DATEI Erster Unterschied Ignoriere Leerzeichen-Änderungen ÜBEREINANDER @@ -349,6 +388,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente SUBMODUL GELÖSCHT NEU + + {0} nicht committete Änderungen Seiten tauschen Syntax-Hervorhebung Zeilenumbruch @@ -365,6 +405,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Alle Änderungen in der Arbeitskopie. Änderungen: Ignorierte Dateien einbeziehen + Geänderte/gelöschte Dateien einbeziehen Nicht-verfolgte Dateien einbeziehen {0} Änderungen werden verworfen Du kannst das nicht rückgängig machen!!! @@ -400,14 +441,25 @@ $1, $2, … Werte der Eingabe-Steuerelemente Dateiverlauf ÄNDERUNG INHALT + Dateimodus-Änderung: + Gelöschter Dateimodus: + Verzeichnis + Ausführbar + Neuer Dateimodus: + Normal + Submodul + Symlink + Unbekannt Git Flow Development-Branch: Feature: Feature-Präfix: + Abschließen ${0}$ FLOW – Feature fertigstellen FLOW – Hotfix fertigstellen FLOW – Release fertigstellen Ziel: + Vor dem Mergen rebasen Squash beim Merge Hotfix: Hotfix-Präfix: @@ -416,10 +468,12 @@ $1, $2, … Werte der Eingabe-Steuerelemente Production-Branch: Release: Release-Präfix: + Beginnen bei: Feature beginnen… FLOW – Feature beginnen Hotfix beginnen… FLOW – Hotfix beginnen + Name: Namen eingeben Release beginnen… FLOW – Release beginnen @@ -453,17 +507,26 @@ $1, $2, … Werte der Eingabe-Steuerelemente Remote: Verfolge alle ‚{0}‘ Dateien Verfolge alle *{0} Dateien + Commit auswählen VERLAUF AUTOR AUTOR-ZEITPUNKT COMMIT-ZEITPUNKT VERLAUF & COMMIT-NACHRICHT SHA + HERVORHEBUNGEN IM GRAPHEN + Alle + Nur aktueller Branch + Aktueller Branch & ausgewählte Commits + Nur ausgewählte Commits {0} COMMITS AUSGEWÄHLT SPALTEN ANZEIGEN Halte ‚Strg‘ oder ‚Umschalt‘, um mehrere Commits auszuwählen. Halte ⌘ oder ⇧, um mehrere Commits auszuwählen TIPPS: + In separatem Fenster öffnen + Commit-Details + Revisionsvergleich Tastaturkürzel-Referenz GLOBAL Klone neues Repository @@ -471,6 +534,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Zur nächsten Registerkarte wechseln Zur vorherigen Registerkarte wechseln Neue Registerkarte erstellen + Lokales Repository öffnen Einstellungen öffnen Auswahlmenü für Arbeitsumgebungen anzeigen Aktive Registerkarte wechseln @@ -479,14 +543,17 @@ $1, $2, … Werte der Eingabe-Steuerelemente Gestagte Änderungen committen Gestagte Änderungen committen und pushen Alle Änderungen stagen und committen + Neuen Branch erstellen Fetch, wird direkt ausgeführt Dashboard-Modus (Standard) + Springe zum Nachfolger des ausgewählten Commits Springe zum Vorgänger des ausgewählten Commits Befehlspalette öffnen Commit-Suchmodus Pull, wird direkt ausgeführt Push, wird direkt ausgeführt Erzwinge Neuladen des Repositorys + Detailbereich im ‚VERLAUF‘ ein-/ausklappen Wechsle zu ‚Änderungen‘ Wechsle zu ‚Verlauf‘ Wechsle zu ‚Stashes‘ @@ -494,6 +561,8 @@ $1, $2, … Werte der Eingabe-Steuerelemente Stagen Unstagen Initialisiere Repository + Möchtest du `git init` in diesem Pfad ausführen? + Öffnen des Repositorys fehlgeschlagen. Grund: Pfad: Cherry-Pick wird durchgeführt. Verarbeite Commit @@ -505,6 +574,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Reverte Commit Interaktiver Rebase Lokale Änderungen stashen & wieder anwenden + pre-rebase Hook überspringen Auf: Drag & Drop zum Anordnen der Commits Ziel-Branch: @@ -513,6 +583,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Befehle FEHLER INFO + Neue Version verfügbar Repositorys öffnen Registerkarten Arbeitsumgebungen @@ -521,6 +592,10 @@ $1, $2, … Werte der Eingabe-Steuerelemente Ziel-Branch: Merge-Option: Quelle: + Merge wird geprüft… + Merge ist ohne Konflikte möglich + Unbekannter Fehler bei der Merge-Prüfung + Merge wird Konflikte verursachen Zuerst meine, dann deren Zuerst deren, dann meine BEIDE VERWENDEN @@ -554,6 +629,10 @@ $1, $2, … Werte der Eingabe-Steuerelemente Programmdaten-Ordner öffnen Datei öffnen Öffnen in externem Merge-Tool + Lokales Repository öffnen + Lesezeichen: + Gruppe: + Ordner: Optional. Neue Registerkarte erstellen Registerkarte schließen @@ -577,7 +656,10 @@ $1, $2, … Werte der Eingabe-Steuerelemente Gestern Einstellungen AI + Zusätzlicher Prompt (Verwende `-`, um deine Anforderungen aufzulisten) API-Schlüssel + Modell + Verfügbare Modell-IDs automatisch abrufen Name Der eingegebene Wert ist der Name der Umgebungsvariable, aus der der API-Schlüssel gelesen wird Server @@ -609,8 +691,11 @@ $1, $2, … Werte der Eingabe-Steuerelemente Commit-Historie Standardmäßig ‚ÄNDERUNGEN‘-Ansicht anzeigen Standardmäßig Registerkarte ‚ÄNDERUNGEN‘ in Commit-Details anzeigen + Relative Zeitangaben im Commit-Graphen anzeigen Zeige Tags im Commit-Verlauf Längenvorgabe für Commit-Nachrichten + 24-Stunden-Format + Kompakte Branch-Namen im Commit-Graphen verwenden Standard-Avatar im GitHub-Stil generieren GIT Aktiviere Auto-CRLF @@ -625,6 +710,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente git-credential-libsecret statt git-credential-manager verwenden Benutzername Globaler Git-Benutzername + Änderungen beim Auschecken oder Mergen von Branches standardmäßig stashen & wieder anwenden Git-Version GPG-SIGNIERUNG Commit-Signierung @@ -672,7 +758,12 @@ $1, $2, … Werte der Eingabe-Steuerelemente Schließen Aktuellen Branch rebasen Lokale Änderungen stashen & wieder anwenden + pre-rebase Hook überspringen Auf: + Rebase wird geprüft… + Rebase ist ohne Konflikte möglich + Unbekannter Fehler bei der Rebase-Prüfung + Rebase wird Konflikte verursachen Remote hinzufügen Remote bearbeiten Name: @@ -683,6 +774,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Benutzerdefinierte Aktion Löschen… Bearbeiten… + Auto-Fetch aktivieren Fetch Im Browser öffnen Prune @@ -711,9 +803,12 @@ $1, $2, … Werte der Eingabe-Steuerelemente Öffne im Datei-Browser Suche Branches / Tags / Submodule Sichtbarkeit im Verlauf + Filter einklappen Aufheben Im Verlauf ausblenden + Filter ausklappen Im Verlauf filtern + Filter aktiv LAYOUT Horizontal Vertikal @@ -811,6 +906,8 @@ $1, $2, … Werte der Eingabe-Steuerelemente Gestagte und ungestagte Änderungen der ausgewählten Datei(en) werden gestasht!!! Lokale Änderungen stashen Anwenden + Änderungen anwenden + Neuen Branch auschecken Kopiere Nachricht Entfernen Als Patch speichern… @@ -847,9 +944,12 @@ $1, $2, … Werte der Eingabe-Steuerelemente nicht gemerged Aktualisieren URL + Details der Submodul-Änderung + DETAILS ÖFFNEN OK TAGGER ZEIT + Tag auschecken… Vergleiche 2 Tags Vergleichen mit… Vergleichen mit HEAD @@ -860,11 +960,13 @@ $1, $2, … Werte der Eingabe-Steuerelemente Benutzerdefinierte Aktion Lösche ${0}$… Lösche ausgewählte {0} Tags… + Merge ${0}$ in ${1}$ hinein… Pushe ${0}$… Submodule aktualisieren Alle Submodule Bei Bedarf initialisieren Submodul: + Verschachtelte Submodule aktualisieren Auf verfolgten Remote-Branch des Submoduls aktualisieren URL: Logs @@ -891,6 +993,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Ignoriere *{0} Dateien im selben Ordner Ignoriere nicht-verfolgte Dateien in diesem Ordner Ignoriere nur diese Datei + Ignoriere alle nicht-verfolgten Dateien im selben Ordner Nachbesserung Du kannst diese Datei jetzt stagen. Verlauf löschen @@ -910,6 +1013,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente DATEI-KONFLIKTE SIND GELÖST MEINE VERSION VERWENDEN DEREN VERSION VERWENDEN + Änderungen filtern… NICHT-VERFOLGTE DATEIEN EINBEZIEHEN KEINE BISHERIGEN COMMIT-NACHRICHTEN KEINE COMMIT-VORLAGEN @@ -927,9 +1031,12 @@ $1, $2, … Werte der Eingabe-Steuerelemente ARBEITSUMGEBUNG: Arbeitsumgebungen konfigurieren… WORKTREE + BRANCH Pfad kopieren + HEAD Sperren Öffnen + PFAD Entfernen Entsperren JA From 4ade74dd848d347f023548dcc9dc527f9e03bd2b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 3 Aug 2026 02:20:05 +0000 Subject: [PATCH 05/34] doc: Update translation status and sort locale files --- TRANSLATION.md | 115 +------------------------------------------------ 1 file changed, 1 insertion(+), 114 deletions(-) diff --git a/TRANSLATION.md b/TRANSLATION.md index 47960c547..949216104 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -6,120 +6,7 @@ This document shows the translation status of each locale file in the repository ### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen) -### ![de__DE](https://img.shields.io/badge/de__DE-89.52%25-yellow) - -
-Missing keys in de_DE.axaml - -- Text.AIAssistant.Use -- Text.App.HideOthers -- Text.Apply.3Way -- Text.Apply.Source -- Text.Apply.Source.File -- Text.Apply.Source.Clipboard -- Text.Bisect.WaitingForCheckoutAnother -- Text.Bisect.WaitingForFirstBad -- Text.BranchCM.CompareWithSpecial -- Text.CheckoutBranchFromStash -- Text.CheckoutBranchFromStash.Branch -- Text.CheckoutBranchFromStash.Stash -- Text.CheckoutDetached -- Text.CheckoutDetached.Target -- Text.CheckoutDetached.Warning -- Text.Clone.Bookmark -- Text.Clone.Group -- Text.CommandPalette.Branches -- Text.CommandPalette.BranchesAndTags -- Text.CommandPalette.RepositoryActions -- Text.CommandPalette.RevisionFiles -- Text.CommitCM.CopyAuthorTime -- Text.CommitCM.CopyCommitterTime -- Text.CommitDetail.CollapseToBottom -- Text.CommitMessageTextBox.Column -- Text.Compare.Changes -- Text.Compare.Commits -- Text.Compare.Commits.LeftOnly -- Text.Compare.Commits.RightOnly -- Text.Compare.Commits.Tips -- Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules -- Text.ConfigureCustomActionControls.StringFormatter -- Text.ConfigureCustomActionControls.StringFormatter.Tip -- Text.ConfigureCustomActionControls.UseFriendlyName -- Text.ConfirmEmptyCommit.StageSelectedThenCommit -- Text.CopyAsPatch -- Text.DeleteBranch.AskForRemote -- Text.DeleteBranch.Force -- Text.Diff.EmptyFile -- Text.Diff.Submodule.UncommittedChanges -- Text.Discard.IncludeModified -- Text.FileModeChange -- Text.FileModeChange.Deleted -- Text.FileModeChange.Directory -- Text.FileModeChange.Executable -- Text.FileModeChange.New -- Text.FileModeChange.Normal -- Text.FileModeChange.Submodule -- Text.FileModeChange.Symlink -- Text.FileModeChange.Unknown -- Text.GitFlow.Finish -- Text.GitFlow.FinishWithRebase -- Text.GitFlow.StartAt -- Text.GitFlow.StartName -- Text.GotoRevisionSelector -- Text.Histories.HighlightsInGraph -- Text.Histories.HighlightsInGraph.All -- Text.Histories.HighlightsInGraph.CurrentBranchOnly -- Text.Histories.HighlightsInGraph.CurrentBranchAndSelectedCommits -- Text.Histories.HighlightsInGraph.SelectedCommitsOnly -- Text.HistoriesDetailsStandalone -- Text.HistoriesDetailsStandalone.CommitDetail -- Text.HistoriesDetailsStandalone.RevisionCompare -- Text.Hotkeys.Global.OpenLocalRepository -- Text.Hotkeys.Repo.CreateBranch -- Text.Hotkeys.Repo.GoToChild -- Text.Hotkeys.Repo.ToggleHistoriesDetailPanel -- Text.Init.CommandTip -- Text.Init.ErrorMessageTip -- Text.InteractiveRebase.NoVerify -- Text.Launcher.NewVersion -- Text.Merge.Test -- Text.Merge.Test.NoConflicts -- Text.Merge.Test.UnknownError -- Text.Merge.Test.WillCauseConflicts -- Text.OpenLocalRepository -- Text.OpenLocalRepository.Bookmark -- Text.OpenLocalRepository.Group -- Text.OpenLocalRepository.Path -- Text.Preferences.AI.AdditionalPrompt -- Text.Preferences.AI.Model -- Text.Preferences.AI.Model.AutoFetchAvailableModels -- Text.Preferences.General.ShowRelativeTimeInGraph -- Text.Preferences.General.Use24Hours -- Text.Preferences.General.UseCompactBranchNames -- Text.Preferences.Git.UseStashAndReapplyByDefault -- Text.Rebase.NoVerify -- Text.Rebase.Test -- Text.Rebase.Test.OK -- Text.Rebase.Test.UnknownError -- Text.Rebase.Test.WillCauseConflicts -- Text.RemoteCM.EnableAutoFetch -- Text.Repository.FilterCommits.Collapse -- Text.Repository.FilterCommits.Expand -- Text.Repository.FilterCommits.Summary -- Text.StashCM.ApplyFileChanges -- Text.StashCM.Branch -- Text.SubmoduleRevisionCompare -- Text.SubmoduleRevisionCompare.OpenDetails -- Text.TagCM.Checkout -- Text.TagCM.Merge -- Text.UpdateSubmodules.Recursive -- Text.WorkingCopy.AddToGitIgnore.UntrackedInSameFolder -- Text.WorkingCopy.FilterChanges -- Text.Worktree.Branch -- Text.Worktree.Head -- Text.Worktree.Path - -
+### ![de__DE](https://img.shields.io/badge/de__DE-%E2%88%9A-brightgreen) ### ![el__GR](https://img.shields.io/badge/el__GR-99.51%25-yellow) From 4a970e67d7af37e482e92ab33a207381110e0539 Mon Sep 17 00:00:00 2001 From: Moritz Wieland <81433802+mowi12@users.noreply.github.com> Date: Mon, 3 Aug 2026 04:20:15 +0200 Subject: [PATCH 06/34] fix: remove stray placeholder in de_DE MergeConflictEditor.Title translation (#2601) --- src/Resources/Locales/de_DE.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 8148d225a..2fbc94c69 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -607,7 +607,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente ERGEBNIS SPEICHERN & STAGEN DEREN - Merge-Konflikt – {0} + Merge-Konflikte Ungespeicherte Änderungen verwerfen? MEINE VERWENDEN DEREN VERWENDEN From 22dbdf72c300a4998f7063fb70a4b3d9b5714c83 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 3 Aug 2026 10:55:21 +0800 Subject: [PATCH 07/34] feature: add syntax highlighting for `erlang` and `OCaml` (#2598) (#2602) Signed-off-by: leo --- THIRD-PARTY-LICENSES.md | 14 + src/Models/TextMateHelper.cs | 2 + src/Resources/Grammars/erlang.json | 1753 ++++++++++++++++ src/Resources/Grammars/ocaml.json | 2961 ++++++++++++++++++++++++++++ 4 files changed, 4730 insertions(+) create mode 100644 src/Resources/Grammars/erlang.json create mode 100644 src/Resources/Grammars/ocaml.json diff --git a/THIRD-PARTY-LICENSES.md b/THIRD-PARTY-LICENSES.md index e2600fb4f..d10d08be2 100644 --- a/THIRD-PARTY-LICENSES.md +++ b/THIRD-PARTY-LICENSES.md @@ -112,3 +112,17 @@ The project uses the following third-party libraries or assets - **Commit**: 68d98dc57f8486c2946ae28dc86bf8e91d45da4d - **License**: MIT License - **License Link**: https://github.com/vuejs/language-tools/blob/68d98dc57f8486c2946ae28dc86bf8e91d45da4d/LICENSE + +### OCaml + +- **Source**: https://github.com/shentao/vue-multiselect/blob/master/docs/shiki/languages/ocaml.tmLanguage.json +- **Commit**: 8092917041f0ae02cbe4c6982deddc931c6adecd +- **License**: MIT License +- **License Link**: https://github.com/shentao/vue-multiselect/blob/master/LICENSE + +### Erlang + +- **Source**: https://github.com/shentao/vue-multiselect/blob/master/docs/shiki/languages/erlang.tmLanguage.json +- **Commit**: 8092917041f0ae02cbe4c6982deddc931c6adecd +- **License**: MIT License +- **License Link**: https://github.com/shentao/vue-multiselect/blob/master/LICENSE \ No newline at end of file diff --git a/src/Models/TextMateHelper.cs b/src/Models/TextMateHelper.cs index 5bb50da69..0dd3b5ac7 100644 --- a/src/Models/TextMateHelper.cs +++ b/src/Models/TextMateHelper.cs @@ -27,6 +27,8 @@ public static class GrammarUtility new ExtraGrammar("source.hxml", [".hxml"], "hxml.json"), new ExtraGrammar("text.html.jsp", [".jsp", ".jspf", ".tag"], "jsp.json"), new ExtraGrammar("source.vue", [".vue"], "vue.json"), + new ExtraGrammar("source.erlang", [".erl", ".escript", ".hrl"], "erlang.json"), + new ExtraGrammar("source.ocaml", [".ml", ".mli"], "ocaml.json"), ]; private static readonly Dictionary s_cachedRawGrammars = new(); diff --git a/src/Resources/Grammars/erlang.json b/src/Resources/Grammars/erlang.json new file mode 100644 index 000000000..216086ce5 --- /dev/null +++ b/src/Resources/Grammars/erlang.json @@ -0,0 +1,1753 @@ +{ + "comment": "The recognition of function definitions and compiler directives (such as module, record and macro definitions) requires that each of the aforementioned constructs must be the first string inside a line (except for whitespace). Also, the function/module/record/macro names must be given unquoted. -- desp", + "fileTypes": ["erl", "escript", "hrl", "xrl", "yrl"], + "keyEquivalent": "^~E", + "name": "erlang", + "patterns": [ + { + "include": "#module-directive" + }, + { + "include": "#import-export-directive" + }, + { + "include": "#behaviour-directive" + }, + { + "include": "#record-directive" + }, + { + "include": "#define-directive" + }, + { + "include": "#macro-directive" + }, + { + "include": "#directive" + }, + { + "include": "#function" + }, + { + "include": "#everything-else" + } + ], + "repository": { + "atom": { + "patterns": [ + { + "begin": "(')", + "beginCaptures": { + "1": { + "name": "punctuation.definition.symbol.begin.erlang" + } + }, + "end": "(')", + "endCaptures": { + "1": { + "name": "punctuation.definition.symbol.end.erlang" + } + }, + "name": "constant.other.symbol.quoted.single.erlang", + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.definition.escape.erlang" + }, + "3": { + "name": "punctuation.definition.escape.erlang" + } + }, + "match": "(\\\\)([bdefnrstv\\\\'\"]|(\\^)[@-_a-z]|[0-7]{1,3}|x[\\da-fA-F]{2})", + "name": "constant.other.symbol.escape.erlang" + }, + { + "match": "\\\\\\^?.?", + "name": "invalid.illegal.atom.erlang" + } + ] + }, + { + "match": "[a-z][a-zA-Z\\d@_]*+", + "name": "constant.other.symbol.unquoted.erlang" + } + ] + }, + "behaviour-directive": { + "captures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.behaviour.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + }, + "4": { + "name": "entity.name.type.class.behaviour.definition.erlang" + }, + "5": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "6": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "match": "^\\s*+(-)\\s*+(behaviour)\\s*+(\\()\\s*+([a-z][a-zA-Z\\d@_]*+)\\s*+(\\))\\s*+(\\.)", + "name": "meta.directive.behaviour.erlang" + }, + "binary": { + "begin": "(<<)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.binary.begin.erlang" + } + }, + "end": "(>>)", + "endCaptures": { + "1": { + "name": "punctuation.definition.binary.end.erlang" + } + }, + "name": "meta.structure.binary.erlang", + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.separator.binary.erlang" + }, + "2": { + "name": "punctuation.separator.value-size.erlang" + } + }, + "match": "(,)|(:)" + }, + { + "include": "#internal-type-specifiers" + }, + { + "include": "#everything-else" + } + ] + }, + "character": { + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.definition.character.erlang" + }, + "2": { + "name": "constant.character.escape.erlang" + }, + "3": { + "name": "punctuation.definition.escape.erlang" + }, + "5": { + "name": "punctuation.definition.escape.erlang" + } + }, + "match": "(\\$)((\\\\)([bdefnrstv\\\\'\"]|(\\^)[@-_a-z]|[0-7]{1,3}|x[\\da-fA-F]{2}))", + "name": "constant.character.erlang" + }, + { + "match": "\\$\\\\\\^?.?", + "name": "invalid.illegal.character.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.character.erlang" + } + }, + "match": "(\\$)[ \\S]", + "name": "constant.character.erlang" + }, + { + "match": "\\$.?", + "name": "invalid.illegal.character.erlang" + } + ] + }, + "comment": { + "begin": "(^[ \\t]+)?(?=%)", + "beginCaptures": { + "1": { + "name": "punctuation.whitespace.comment.leading.erlang" + } + }, + "end": "(?!\\G)", + "patterns": [ + { + "begin": "%", + "beginCaptures": { + "0": { + "name": "punctuation.definition.comment.erlang" + } + }, + "end": "\\n", + "name": "comment.line.percentage.erlang" + } + ] + }, + "define-directive": { + "patterns": [ + { + "begin": "^\\s*+(-)\\s*+(define)\\s*+(\\()\\s*+([a-zA-Z\\d@_]++)\\s*+", + "beginCaptures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.define.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + }, + "4": { + "name": "entity.name.function.macro.definition.erlang" + } + }, + "end": "(\\))\\s*+(\\.)", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "2": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "name": "meta.directive.define.erlang", + "patterns": [ + { + "include": "#everything-else" + } + ] + }, + { + "begin": "(?=^\\s*+-\\s*+define\\s*+\\(\\s*+[a-zA-Z\\d@_]++\\s*+\\()", + "end": "(\\))\\s*+(\\.)", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "2": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "name": "meta.directive.define.erlang", + "patterns": [ + { + "begin": "^\\s*+(-)\\s*+(define)\\s*+(\\()\\s*+([a-zA-Z\\d@_]++)\\s*+(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.define.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + }, + "4": { + "name": "entity.name.function.macro.definition.erlang" + }, + "5": { + "name": "punctuation.definition.parameters.begin.erlang" + } + }, + "end": "(\\))\\s*(,)", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "2": { + "name": "punctuation.separator.parameters.erlang" + } + }, + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.parameters.erlang" + }, + { + "include": "#everything-else" + } + ] + }, + { + "match": "\\|\\||\\||:|;|,|\\.|->", + "name": "punctuation.separator.define.erlang" + }, + { + "include": "#everything-else" + } + ] + } + ] + }, + "directive": { + "patterns": [ + { + "begin": "^\\s*+(-)\\s*+([a-z][a-zA-Z\\d@_]*+)\\s*+(\\(?)", + "beginCaptures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + } + }, + "end": "(\\)?)\\s*+(\\.)", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "2": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "name": "meta.directive.erlang", + "patterns": [ + { + "include": "#everything-else" + } + ] + }, + { + "captures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.erlang" + }, + "3": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "match": "^\\s*+(-)\\s*+([a-z][a-zA-Z\\d@_]*+)\\s*+(\\.)", + "name": "meta.directive.erlang" + } + ] + }, + "everything-else": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#record-usage" + }, + { + "include": "#macro-usage" + }, + { + "include": "#expression" + }, + { + "include": "#keyword" + }, + { + "include": "#textual-operator" + }, + { + "include": "#language-constant" + }, + { + "include": "#function-call" + }, + { + "include": "#tuple" + }, + { + "include": "#list" + }, + { + "include": "#binary" + }, + { + "include": "#parenthesized-expression" + }, + { + "include": "#character" + }, + { + "include": "#number" + }, + { + "include": "#atom" + }, + { + "include": "#string" + }, + { + "include": "#symbolic-operator" + }, + { + "include": "#variable" + } + ] + }, + "expression": { + "patterns": [ + { + "begin": "\\b(if)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.if.erlang" + } + }, + "end": "\\b(end)\\b", + "endCaptures": { + "1": { + "name": "keyword.control.end.erlang" + } + }, + "name": "meta.expression.if.erlang", + "patterns": [ + { + "include": "#internal-expression-punctuation" + }, + { + "include": "#everything-else" + } + ] + }, + { + "begin": "\\b(case)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.case.erlang" + } + }, + "end": "\\b(end)\\b", + "endCaptures": { + "1": { + "name": "keyword.control.end.erlang" + } + }, + "name": "meta.expression.case.erlang", + "patterns": [ + { + "include": "#internal-expression-punctuation" + }, + { + "include": "#everything-else" + } + ] + }, + { + "begin": "\\b(receive)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.receive.erlang" + } + }, + "end": "\\b(end)\\b", + "endCaptures": { + "1": { + "name": "keyword.control.end.erlang" + } + }, + "name": "meta.expression.receive.erlang", + "patterns": [ + { + "include": "#internal-expression-punctuation" + }, + { + "include": "#everything-else" + } + ] + }, + { + "captures": { + "1": { + "name": "keyword.control.fun.erlang" + }, + "4": { + "name": "entity.name.type.class.module.erlang" + }, + "5": { + "name": "variable.other.erlang" + }, + "6": { + "name": "punctuation.separator.module-function.erlang" + }, + "8": { + "name": "entity.name.function.erlang" + }, + "9": { + "name": "variable.other.erlang" + }, + "10": { + "name": "punctuation.separator.function-arity.erlang" + } + }, + "comment": "Implicit function expression with optional module qualifier when both module and function can be atom or variable", + "match": "\\b(fun)\\s+((([a-z][a-zA-Z\\d@_]*+)|(_[a-zA-Z\\d@_]++|[A-Z][a-zA-Z\\d@_]*+))\\s*+(:)\\s*+)?(([a-z][a-zA-Z\\d@_]*+|'[^']*+')|(_[a-zA-Z\\d@_]++|[A-Z][a-zA-Z\\d@_]*+))\\s*(/)", + "name": "meta.expression.fun.implicit.erlang" + }, + { + "begin": "\\b(fun)\\s+(([a-z][a-zA-Z\\d@_]*+)|(_[a-zA-Z\\d@_]++|[A-Z][a-zA-Z\\d@_]*+))\\s*+(:)", + "beginCaptures": { + "1": { + "name": "keyword.control.fun.erlang" + }, + "3": { + "name": "entity.name.type.class.module.erlang" + }, + "4": { + "name": "variable.other.erlang" + }, + "5": { + "name": "punctuation.separator.module-function.erlang" + } + }, + "comment": "Implicit function expression with module qualifier when module can be atom or variable and function can by anything", + "end": "(/)", + "endCaptures": { + "1": { + "name": "punctuation.separator.function-arity.erlang" + } + }, + "name": "meta.expression.fun.implicit.erlang", + "patterns": [ + { + "include": "#everything-else" + } + ] + }, + { + "begin": "\\b(fun)\\s+(?!\\()", + "beginCaptures": { + "1": { + "name": "keyword.control.fun.erlang" + } + }, + "comment": "Implicit function expression when both module and function can by anything", + "end": "(/)", + "endCaptures": { + "1": { + "name": "punctuation.separator.function-arity.erlang" + } + }, + "name": "meta.expression.fun.implicit.erlang", + "patterns": [ + { + "include": "#everything-else" + } + ] + }, + { + "begin": "\\b(fun)\\s*+(\\()(?=(\\s*+\\())", + "beginCaptures": { + "1": { + "name": "entity.name.function.erlang" + }, + "2": { + "name": "punctuation.definition.parameters.begin.erlang" + } + }, + "comment": "Function type in type specification", + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + } + }, + "patterns": [ + { + "include": "#everything-else" + } + ] + }, + { + "begin": "\\b(fun)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.fun.erlang" + } + }, + "comment": "Explicit function expression", + "end": "\\b(end)\\b", + "endCaptures": { + "1": { + "name": "keyword.control.end.erlang" + } + }, + "name": "meta.expression.fun.erlang", + "patterns": [ + { + "begin": "(?=\\()", + "end": "(;)|(?=\\bend\\b)", + "endCaptures": { + "1": { + "name": "punctuation.separator.clauses.erlang" + } + }, + "patterns": [ + { + "include": "#internal-function-parts" + } + ] + }, + { + "include": "#everything-else" + } + ] + }, + { + "begin": "\\b(try)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.try.erlang" + } + }, + "end": "\\b(end)\\b", + "endCaptures": { + "1": { + "name": "keyword.control.end.erlang" + } + }, + "name": "meta.expression.try.erlang", + "patterns": [ + { + "include": "#internal-expression-punctuation" + }, + { + "include": "#everything-else" + } + ] + }, + { + "begin": "\\b(begin)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.begin.erlang" + } + }, + "end": "\\b(end)\\b", + "endCaptures": { + "1": { + "name": "keyword.control.end.erlang" + } + }, + "name": "meta.expression.begin.erlang", + "patterns": [ + { + "include": "#internal-expression-punctuation" + }, + { + "include": "#everything-else" + } + ] + }, + { + "begin": "\\b(maybe)\\b", + "beginCaptures": { + "1": { + "name": "keyword.control.maybe.erlang" + } + }, + "end": "\\b(end)\\b", + "endCaptures": { + "1": { + "name": "keyword.control.end.erlang" + } + }, + "name": "meta.expression.maybe.erlang", + "patterns": [ + { + "include": "#internal-expression-punctuation" + }, + { + "include": "#everything-else" + } + ] + } + ] + }, + "function": { + "begin": "^\\s*+([a-z][a-zA-Z\\d@_]*+|'[^']*+')\\s*+(?=\\()", + "beginCaptures": { + "1": { + "name": "entity.name.function.definition.erlang" + } + }, + "end": "(\\.)", + "endCaptures": { + "1": { + "name": "punctuation.terminator.function.erlang" + } + }, + "name": "meta.function.erlang", + "patterns": [ + { + "captures": { + "1": { + "name": "entity.name.function.erlang" + } + }, + "match": "^\\s*+([a-z][a-zA-Z\\d@_]*+|'[^']*+')\\s*+(?=\\()" + }, + { + "begin": "(?=\\()", + "end": "(;)|(?=\\.)", + "endCaptures": { + "1": { + "name": "punctuation.separator.clauses.erlang" + } + }, + "patterns": [ + { + "include": "#parenthesized-expression" + }, + { + "include": "#internal-function-parts" + } + ] + }, + { + "include": "#everything-else" + } + ] + }, + "function-call": { + "begin": "(?=([a-z][a-zA-Z\\d@_]*+|'[^']*+'|_[a-zA-Z\\d@_]++|[A-Z][a-zA-Z\\d@_]*+)\\s*+(\\(|:\\s*+([a-z][a-zA-Z\\d@_]*+|'[^']*+'|_[a-zA-Z\\d@_]++|[A-Z][a-zA-Z\\d@_]*+)\\s*+\\())", + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + } + }, + "name": "meta.function-call.erlang", + "patterns": [ + { + "begin": "((erlang)\\s*+(:)\\s*+)?(is_atom|is_binary|is_constant|is_float|is_function|is_integer|is_list|is_number|is_pid|is_port|is_reference|is_tuple|is_record|abs|element|hd|length|node|round|self|size|tl|trunc)\\s*+(\\()", + "beginCaptures": { + "2": { + "name": "entity.name.type.class.module.erlang" + }, + "3": { + "name": "punctuation.separator.module-function.erlang" + }, + "4": { + "name": "entity.name.function.guard.erlang" + }, + "5": { + "name": "punctuation.definition.parameters.begin.erlang" + } + }, + "end": "(?=\\))", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.parameters.erlang" + }, + { + "include": "#everything-else" + } + ] + }, + { + "begin": "((([a-z][a-zA-Z\\d@_]*+|'[^']*+')|(_[a-zA-Z\\d@_]++|[A-Z][a-zA-Z\\d@_]*+))\\s*+(:)\\s*+)?(([a-z][a-zA-Z\\d@_]*+|'[^']*+')|(_[a-zA-Z\\d@_]++|[A-Z][a-zA-Z\\d@_]*+))\\s*+(\\()", + "beginCaptures": { + "3": { + "name": "entity.name.type.class.module.erlang" + }, + "4": { + "name": "variable.other.erlang" + }, + "5": { + "name": "punctuation.separator.module-function.erlang" + }, + "7": { + "name": "entity.name.function.erlang" + }, + "8": { + "name": "variable.other.erlang" + }, + "9": { + "name": "punctuation.definition.parameters.begin.erlang" + } + }, + "end": "(?=\\))", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.parameters.erlang" + }, + { + "include": "#everything-else" + } + ] + } + ] + }, + "import-export-directive": { + "patterns": [ + { + "begin": "^\\s*+(-)\\s*+(import)\\s*+(\\()\\s*+([a-z][a-zA-Z\\d@_]*+|'[^']*+')\\s*+(,)", + "beginCaptures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.import.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + }, + "4": { + "name": "entity.name.type.class.module.erlang" + }, + "5": { + "name": "punctuation.separator.parameters.erlang" + } + }, + "end": "(\\))\\s*+(\\.)", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "2": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "name": "meta.directive.import.erlang", + "patterns": [ + { + "include": "#internal-function-list" + } + ] + }, + { + "begin": "^\\s*+(-)\\s*+(export)\\s*+(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.export.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + } + }, + "end": "(\\))\\s*+(\\.)", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "2": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "name": "meta.directive.export.erlang", + "patterns": [ + { + "include": "#internal-function-list" + } + ] + } + ] + }, + "internal-expression-punctuation": { + "captures": { + "1": { + "name": "punctuation.separator.clause-head-body.erlang" + }, + "2": { + "name": "punctuation.separator.clauses.erlang" + }, + "3": { + "name": "punctuation.separator.expressions.erlang" + } + }, + "match": "(->)|(;)|(,)" + }, + "internal-function-list": { + "begin": "(\\[)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.list.begin.erlang" + } + }, + "end": "(\\])", + "endCaptures": { + "1": { + "name": "punctuation.definition.list.end.erlang" + } + }, + "name": "meta.structure.list.function.erlang", + "patterns": [ + { + "begin": "([a-z][a-zA-Z\\d@_]*+|'[^']*+')\\s*+(/)", + "beginCaptures": { + "1": { + "name": "entity.name.function.erlang" + }, + "2": { + "name": "punctuation.separator.function-arity.erlang" + } + }, + "end": "(,)|(?=\\])", + "endCaptures": { + "1": { + "name": "punctuation.separator.list.erlang" + } + }, + "patterns": [ + { + "include": "#everything-else" + } + ] + }, + { + "include": "#everything-else" + } + ] + }, + "internal-function-parts": { + "patterns": [ + { + "begin": "(?=\\()", + "end": "(->)", + "endCaptures": { + "1": { + "name": "punctuation.separator.clause-head-body.erlang" + } + }, + "patterns": [ + { + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.definition.parameters.begin.erlang" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + } + }, + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.parameters.erlang" + }, + { + "include": "#everything-else" + } + ] + }, + { + "match": ",|;", + "name": "punctuation.separator.guards.erlang" + }, + { + "include": "#everything-else" + } + ] + }, + { + "match": ",", + "name": "punctuation.separator.expressions.erlang" + }, + { + "include": "#everything-else" + } + ] + }, + "internal-record-body": { + "begin": "(\\{)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.class.record.begin.erlang" + } + }, + "end": "(\\})", + "endCaptures": { + "1": { + "name": "punctuation.definition.class.record.end.erlang" + } + }, + "name": "meta.structure.record.erlang", + "patterns": [ + { + "begin": "(([a-z][a-zA-Z\\d@_]*+|'[^']*+')|(_))", + "beginCaptures": { + "2": { + "name": "variable.other.field.erlang" + }, + "3": { + "name": "variable.language.omitted.field.erlang" + } + }, + "end": "(,)|(?=\\})", + "endCaptures": { + "1": { + "name": "punctuation.separator.class.record.erlang" + } + }, + "patterns": [ + { + "include": "#everything-else" + } + ] + }, + { + "include": "#everything-else" + } + ] + }, + "internal-type-specifiers": { + "begin": "(/)", + "beginCaptures": { + "1": { + "name": "punctuation.separator.value-type.erlang" + } + }, + "end": "(?=,|:|>>)", + "patterns": [ + { + "captures": { + "1": { + "name": "storage.type.erlang" + }, + "2": { + "name": "storage.modifier.signedness.erlang" + }, + "3": { + "name": "storage.modifier.endianness.erlang" + }, + "4": { + "name": "storage.modifier.unit.erlang" + }, + "5": { + "name": "punctuation.separator.unit-specifiers.erlang" + }, + "6": { + "name": "constant.numeric.integer.decimal.erlang" + }, + "7": { + "name": "punctuation.separator.type-specifiers.erlang" + } + }, + "match": "(integer|float|binary|bytes|bitstring|bits|utf8|utf16|utf32)|(signed|unsigned)|(big|little|native)|(unit)(:)(\\d++)|(-)" + } + ] + }, + "keyword": { + "match": "\\b(after|begin|case|catch|cond|end|fun|if|let|of|try|receive|when|maybe|else)\\b", + "name": "keyword.control.erlang" + }, + "language-constant": { + "match": "\\b(false|true|undefined)\\b", + "name": "constant.language" + }, + "list": { + "begin": "(\\[)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.list.begin.erlang" + } + }, + "end": "(\\])", + "endCaptures": { + "1": { + "name": "punctuation.definition.list.end.erlang" + } + }, + "name": "meta.structure.list.erlang", + "patterns": [ + { + "match": "\\||\\|\\||,", + "name": "punctuation.separator.list.erlang" + }, + { + "include": "#everything-else" + } + ] + }, + "macro-directive": { + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.ifdef.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + }, + "4": { + "name": "entity.name.function.macro.erlang" + }, + "5": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "6": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "match": "^\\s*+(-)\\s*+(ifdef)\\s*+(\\()\\s*+([a-zA-z\\d@_]++)\\s*+(\\))\\s*+(\\.)", + "name": "meta.directive.ifdef.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.ifndef.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + }, + "4": { + "name": "entity.name.function.macro.erlang" + }, + "5": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "6": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "match": "^\\s*+(-)\\s*+(ifndef)\\s*+(\\()\\s*+([a-zA-z\\d@_]++)\\s*+(\\))\\s*+(\\.)", + "name": "meta.directive.ifndef.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.undef.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + }, + "4": { + "name": "entity.name.function.macro.erlang" + }, + "5": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "6": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "match": "^\\s*+(-)\\s*+(undef)\\s*+(\\()\\s*+([a-zA-z\\d@_]++)\\s*+(\\))\\s*+(\\.)", + "name": "meta.directive.undef.erlang" + } + ] + }, + "macro-usage": { + "captures": { + "1": { + "name": "keyword.operator.macro.erlang" + }, + "2": { + "name": "entity.name.function.macro.erlang" + } + }, + "match": "(\\?\\??)\\s*+([a-zA-Z\\d@_]++)", + "name": "meta.macro-usage.erlang" + }, + "module-directive": { + "captures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.module.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + }, + "4": { + "name": "entity.name.type.class.module.definition.erlang" + }, + "5": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "6": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "match": "^\\s*+(-)\\s*+(module)\\s*+(\\()\\s*+([a-z][a-zA-Z\\d@_]*+)\\s*+(\\))\\s*+(\\.)", + "name": "meta.directive.module.erlang" + }, + "number": { + "begin": "(?=\\d)", + "end": "(?!\\d)", + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.separator.integer-float.erlang" + }, + "2": { + "name": "punctuation.separator.float-exponent.erlang" + } + }, + "match": "\\d++(\\.)\\d++([eE][\\+\\-]?\\d++)?", + "name": "constant.numeric.float.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "2(#)([0-1]++_)*[0-1]++", + "name": "constant.numeric.integer.binary.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "3(#)([0-2]++_)*[0-2]++", + "name": "constant.numeric.integer.base-3.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "4(#)([0-3]++_)*[0-3]++", + "name": "constant.numeric.integer.base-4.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "5(#)([0-4]++_)*[0-4]++", + "name": "constant.numeric.integer.base-5.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "6(#)([0-5]++_)*[0-5]++", + "name": "constant.numeric.integer.base-6.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "7(#)([0-6]++_)*[0-6]++", + "name": "constant.numeric.integer.base-7.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "8(#)([0-7]++_)*[0-7]++", + "name": "constant.numeric.integer.octal.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "9(#)([0-8]++_)*[0-8]++", + "name": "constant.numeric.integer.base-9.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "10(#)(\\d++_)*\\d++", + "name": "constant.numeric.integer.decimal.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "11(#)([\\daA]++_)*[\\daA]++", + "name": "constant.numeric.integer.base-11.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "12(#)([\\da-bA-B]++_)*[\\da-bA-B]++", + "name": "constant.numeric.integer.base-12.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "13(#)([\\da-cA-C]++_)*[\\da-cA-C]++", + "name": "constant.numeric.integer.base-13.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "14(#)([\\da-dA-D]++_)*[\\da-dA-D]++", + "name": "constant.numeric.integer.base-14.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "15(#)([\\da-eA-E]++_)*[\\da-eA-E]++", + "name": "constant.numeric.integer.base-15.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "16(#)([\\da-fA-F]++_)*[\\da-fA-F]++", + "name": "constant.numeric.integer.hexadecimal.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "17(#)([\\da-gA-G]++_)*[\\da-gA-G]++", + "name": "constant.numeric.integer.base-17.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "18(#)([\\da-hA-H]++_)*[\\da-hA-H]++", + "name": "constant.numeric.integer.base-18.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "19(#)([\\da-iA-I]++_)*[\\da-iA-I]++", + "name": "constant.numeric.integer.base-19.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "20(#)([\\da-jA-J]++_)*[\\da-jA-J]++", + "name": "constant.numeric.integer.base-20.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "21(#)([\\da-kA-K]++_)*[\\da-kA-K]++", + "name": "constant.numeric.integer.base-21.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "22(#)([\\da-lA-L]++_)*[\\da-lA-L]++", + "name": "constant.numeric.integer.base-22.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "23(#)([\\da-mA-M]++_)*[\\da-mA-M]++", + "name": "constant.numeric.integer.base-23.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "24(#)([\\da-nA-N]++_)*[\\da-nA-N]++", + "name": "constant.numeric.integer.base-24.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "25(#)([\\da-oA-O]++_)*[\\da-oA-O]++", + "name": "constant.numeric.integer.base-25.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "26(#)([\\da-pA-P]++_)*[\\da-pA-P]++", + "name": "constant.numeric.integer.base-26.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "27(#)([\\da-qA-Q]++_)*[\\da-qA-Q]++", + "name": "constant.numeric.integer.base-27.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "28(#)([\\da-rA-R]++_)*[\\da-rA-R]++", + "name": "constant.numeric.integer.base-28.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "29(#)([\\da-sA-S]++_)*[\\da-sA-S]++", + "name": "constant.numeric.integer.base-29.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "30(#)([\\da-tA-T]++_)*[\\da-tA-T]++", + "name": "constant.numeric.integer.base-30.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "31(#)([\\da-uA-U]++_)*[\\da-uA-U]++", + "name": "constant.numeric.integer.base-31.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "32(#)([\\da-vA-V]++_)*[\\da-vA-V]++", + "name": "constant.numeric.integer.base-32.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "33(#)([\\da-wA-W]++_)*[\\da-wA-W]++", + "name": "constant.numeric.integer.base-33.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "34(#)([\\da-xA-X]++_)*[\\da-xA-X]++", + "name": "constant.numeric.integer.base-34.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "35(#)([\\da-yA-Y]++_)*[\\da-yA-Y]++", + "name": "constant.numeric.integer.base-35.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.separator.base-integer.erlang" + } + }, + "match": "36(#)([\\da-zA-Z]++_)*[\\da-zA-Z]++", + "name": "constant.numeric.integer.base-36.erlang" + }, + { + "match": "\\d++#([\\da-zA-Z]++_)*[\\da-zA-Z]++", + "name": "invalid.illegal.integer.erlang" + }, + { + "match": "(\\d++_)*\\d++", + "name": "constant.numeric.integer.decimal.erlang" + } + ] + }, + "parenthesized-expression": { + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.section.expression.begin.erlang" + } + }, + "end": "(\\))", + "endCaptures": { + "1": { + "name": "punctuation.section.expression.end.erlang" + } + }, + "name": "meta.expression.parenthesized", + "patterns": [ + { + "include": "#everything-else" + } + ] + }, + "record-directive": { + "begin": "^\\s*+(-)\\s*+(record)\\s*+(\\()\\s*+([a-z][a-zA-Z\\d@_]*+|'[^']*+')\\s*+(,)", + "beginCaptures": { + "1": { + "name": "punctuation.section.directive.begin.erlang" + }, + "2": { + "name": "keyword.control.directive.import.erlang" + }, + "3": { + "name": "punctuation.definition.parameters.begin.erlang" + }, + "4": { + "name": "entity.name.type.class.record.definition.erlang" + }, + "5": { + "name": "punctuation.separator.parameters.erlang" + } + }, + "end": "(\\))\\s*+(\\.)", + "endCaptures": { + "1": { + "name": "punctuation.definition.parameters.end.erlang" + }, + "2": { + "name": "punctuation.section.directive.end.erlang" + } + }, + "name": "meta.directive.record.erlang", + "patterns": [ + { + "include": "#internal-record-body" + }, + { + "include": "#comment" + } + ] + }, + "record-usage": { + "patterns": [ + { + "captures": { + "1": { + "name": "keyword.operator.record.erlang" + }, + "2": { + "name": "entity.name.type.class.record.erlang" + }, + "3": { + "name": "punctuation.separator.record-field.erlang" + }, + "4": { + "name": "variable.other.field.erlang" + } + }, + "match": "(#)\\s*+([a-z][a-zA-Z\\d@_]*+|'[^']*+')\\s*+(\\.)\\s*+([a-z][a-zA-Z\\d@_]*+|'[^']*+')", + "name": "meta.record-usage.erlang" + }, + { + "begin": "(#)\\s*+([a-z][a-zA-Z\\d@_]*+|'[^']*+')", + "beginCaptures": { + "1": { + "name": "keyword.operator.record.erlang" + }, + "2": { + "name": "entity.name.type.class.record.erlang" + } + }, + "end": "(?<=\\})", + "name": "meta.record-usage.erlang", + "patterns": [ + { + "include": "#internal-record-body" + } + ] + } + ] + }, + "string": { + "begin": "(\")", + "beginCaptures": { + "1": { + "name": "punctuation.definition.string.begin.erlang" + } + }, + "end": "(\")", + "endCaptures": { + "1": { + "name": "punctuation.definition.string.end.erlang" + } + }, + "name": "string.quoted.double.erlang", + "patterns": [ + { + "captures": { + "1": { + "name": "punctuation.definition.escape.erlang" + }, + "3": { + "name": "punctuation.definition.escape.erlang" + } + }, + "match": "(\\\\)([bdefnrstv\\\\'\"]|(\\^)[@-_a-z]|[0-7]{1,3}|x[\\da-fA-F]{2})", + "name": "constant.character.escape.erlang" + }, + { + "match": "\\\\\\^?.?", + "name": "invalid.illegal.string.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.placeholder.erlang" + }, + "3": { + "name": "punctuation.separator.placeholder-parts.erlang" + }, + "4": { + "name": "punctuation.separator.placeholder-parts.erlang" + }, + "6": { + "name": "punctuation.separator.placeholder-parts.erlang" + }, + "8": { + "name": "punctuation.separator.placeholder-parts.erlang" + }, + "10": { + "name": "punctuation.separator.placeholder-parts.erlang" + }, + "12": { + "name": "punctuation.separator.placeholder-parts.erlang" + } + }, + "match": "(~)((\\-)?\\d++|(\\*))?((\\.)(\\d++|(\\*)))?((\\.)((\\*)|.))?[~cfegswpWPBX#bx\\+ni]", + "name": "constant.other.placeholder.erlang" + }, + { + "captures": { + "1": { + "name": "punctuation.definition.placeholder.erlang" + }, + "2": { + "name": "punctuation.separator.placeholder-parts.erlang" + } + }, + "match": "(~)(\\*)?(\\d++)?[~du\\-#fsacl]", + "name": "constant.other.placeholder.erlang" + }, + { + "match": "~[^\"]?", + "name": "invalid.illegal.string.erlang" + } + ] + }, + "symbolic-operator": { + "match": "\\+\\+|\\+|--|-|\\*|/=|/|=/=|=:=|==|=<|=|<-|<|>=|>|!|::|\\?=", + "name": "keyword.operator.symbolic.erlang" + }, + "textual-operator": { + "match": "\\b(andalso|band|and|bxor|xor|bor|orelse|or|bnot|not|bsl|bsr|div|rem)\\b", + "name": "keyword.operator.textual.erlang" + }, + "tuple": { + "begin": "(\\{)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tuple.begin.erlang" + } + }, + "end": "(\\})", + "endCaptures": { + "1": { + "name": "punctuation.definition.tuple.end.erlang" + } + }, + "name": "meta.structure.tuple.erlang", + "patterns": [ + { + "match": ",", + "name": "punctuation.separator.tuple.erlang" + }, + { + "include": "#everything-else" + } + ] + }, + "variable": { + "captures": { + "1": { + "name": "variable.other.erlang" + }, + "2": { + "name": "variable.language.omitted.erlang" + } + }, + "match": "(_[a-zA-Z\\d@_]++|[A-Z][a-zA-Z\\d@_]*+)|(_)" + } + }, + "scopeName": "source.erlang", + "uuid": "58EA597D-5158-4BF7-9FB2-B05135D1E166" +} \ No newline at end of file diff --git a/src/Resources/Grammars/ocaml.json b/src/Resources/Grammars/ocaml.json new file mode 100644 index 000000000..84d6f82f3 --- /dev/null +++ b/src/Resources/Grammars/ocaml.json @@ -0,0 +1,2961 @@ +{ + "name": "ocaml", + "scopeName": "source.ocaml", + "fileTypes": [".ml", ".mli"], + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "include": "#decl" + } + ], + "repository": { + "attribute": { + "begin": "(\\[)[[:space:]]*((?|~$])@{1,3}(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\]", + "beginCaptures": { + "1": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + }, + "2": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "endCaptures": { + "0": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + } + }, + "patterns": [ + { + "include": "#attributePayload" + } + ] + }, + "attributeIdentifier": { + "match": "((?|~$])%(?![#\\-:!?.@*/&%^+<=>|~$]))((?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*))", + "captures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "punctuation.definition.tag" + } + } + }, + "attributePayload": { + "patterns": [ + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]%|^%))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "((?|~$])[:\\?](?![#\\-:!?.@*/&%^+<=>|~$]))|(?<=[[:space:]])|(?=\\])", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#pathModuleExtended" + }, + { + "include": "#pathRecord" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?=\\])", + "patterns": [ + { + "include": "#signature" + }, + { + "include": "#type" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]\\?|^\\?))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?=\\])", + "patterns": [ + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]\\?|^\\?))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?=\\])|\\bwhen\\b", + "endCaptures": { + "1": {} + }, + "patterns": [ + { + "include": "#pattern" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]when|^when))(?![[:word:]]))", + "end": "(?=\\])", + "patterns": [ + { + "include": "#term" + } + ] + } + ] + }, + { + "include": "#term" + } + ] + }, + "bindClassTerm": { + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]and|^and|[^[:word:]]class|^class|[^[:word:]]type|^type))(?![[:word:]]))", + "end": "(?|~$])(:)|(=)(?![#\\-:!?.@*/&%^+<=>|~$])|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]and|^and|[^[:word:]]class|^class|[^[:word:]]type|^type))(?![[:word:]]))", + "end": "(?=(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)[[:space:]]*,|[^[:space:][:lower:]%])|(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)|(?=\\btype\\b)", + "endCaptures": { + "0": { + "name": "entity.name.function strong emphasis" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + } + ] + }, + { + "begin": "\\[", + "end": "\\]", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + }, + { + "include": "#bindTermArgs" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?|~$])=(?![#\\-:!?.@*/&%^+<=>|~$])|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|val)\\b)", + "endCaptures": { + "0": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#literalClassType" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\band\\b|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + } + ] + }, + "bindClassType": { + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]and|^and|[^[:word:]]class|^class|[^[:word:]]type|^type))(?![[:word:]]))", + "end": "(?|~$])(:)|(=)(?![#\\-:!?.@*/&%^+<=>|~$])|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]and|^and|[^[:word:]]class|^class|[^[:word:]]type|^type))(?![[:word:]]))", + "end": "(?=(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)[[:space:]]*,|[^[:space:][:lower:]%])|(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)|(?=\\btype\\b)", + "endCaptures": { + "0": { + "name": "entity.name.function strong emphasis" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + } + ] + }, + { + "begin": "\\[", + "end": "\\]", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + }, + { + "include": "#bindTermArgs" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?|~$])=(?![#\\-:!?.@*/&%^+<=>|~$])|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|val)\\b)", + "endCaptures": { + "0": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#literalClassType" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\band\\b|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + } + }, + "patterns": [ + { + "include": "#literalClassType" + } + ] + } + ] + }, + "bindConstructor": { + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]exception|^exception))(?![[:word:]]))|(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]\\+=|^\\+=|[^#\\-:!?.@*/&%^+<=>|~$]=|^=|[^#\\-:!?.@*/&%^+<=>|~$]\\||^\\|))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(:)|(\\bof\\b)|((?|~$])\\|(?![#\\-:!?.@*/&%^+<=>|~$]))|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "punctuation.definition.tag" + }, + "3": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + }, + { + "match": "\\.\\.", + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + { + "match": "\\b(?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)\\b(?![[:space:]]*(?:\\.|\\([^\\*]))", + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + }, + { + "include": "#type" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))|(?:(?<=(?:[^[:word:]]of|^of))(?![[:word:]]))", + "end": "(?|~$])\\|(?![#\\-:!?.@*/&%^+<=>|~$])|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "0": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + } + ] + }, + "bindSignature": { + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "(?:(?<=(?:[^[:word:]]type|^type))(?![[:word:]]))", + "end": "(?|~$])=(?![#\\-:!?.@*/&%^+<=>|~$])", + "endCaptures": { + "0": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pathModuleExtended" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\band\\b|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + } + }, + "patterns": [ + { + "include": "#signature" + } + ] + } + ] + }, + "bindStructure": { + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "(?:(?<=(?:[^[:word:]]and|^and))(?![[:word:]]))|(?=[[:upper:]])", + "end": "(?|~$])(:(?!=))|(:?=)(?![#\\-:!?.@*/&%^+<=>|~$])|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|open|type|val)\\b)", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "match": "\\bmodule\\b", + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + }, + { + "match": "(?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)", + "name": "entity.name.function strong emphasis" + }, + { + "begin": "\\((?!\\))", + "end": "\\)", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "(?|~$]):(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": "(?=\\))", + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + } + }, + "patterns": [ + { + "include": "#signature" + } + ] + }, + { + "include": "#variableModule" + } + ] + }, + { + "include": "#literalUnit" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\b(and)\\b|((?|~$])=(?![#\\-:!?.@*/&%^+<=>|~$]))|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#signature" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:=|^:=|[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\b(?:(and)|(with))\\b|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + }, + "2": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + } + }, + "patterns": [ + { + "include": "#structure" + } + ] + } + ] + }, + "bindTerm": { + "patterns": [ + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]!|^!))(?![#\\-:!?.@*/&%^+<=>|~$]))|(?:(?<=(?:[^[:word:]]and|^and|[^[:word:]]external|^external|[^[:word:]]let|^let|[^[:word:]]method|^method|[^[:word:]]val|^val))(?![[:word:]]))", + "end": "(\\bmodule\\b)|(\\bopen\\b)|(?|~$])(:)|((?|~$])=(?![#\\-:!?.@*/&%^+<=>|~$]))(?![#\\-:!?.@*/&%^+<=>|~$])|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "1": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + }, + "2": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "3": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "4": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]!|^!))(?![#\\-:!?.@*/&%^+<=>|~$]))|(?:(?<=(?:[^[:word:]]and|^and|[^[:word:]]external|^external|[^[:word:]]let|^let|[^[:word:]]method|^method|[^[:word:]]val|^val))(?![[:word:]]))", + "end": "(?=\\b(?:module|open)\\b)|(?=(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)[[:space:]]*,|[^[:space:][:lower:]%])|(\\brec\\b)|((?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*))", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "2": { + "name": "entity.name.function strong emphasis" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + }, + { + "include": "#comment" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]rec|^rec))(?![[:word:]]))", + "end": "((?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*))|(?=[^[:space:][:alpha:]])", + "endCaptures": { + "0": { + "name": "entity.name.function strong emphasis" + } + }, + "patterns": [ + { + "include": "#bindTermArgs" + } + ] + }, + { + "include": "#bindTermArgs" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]module|^module))(?![[:word:]]))", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "patterns": [ + { + "include": "#declModule" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]open|^open))(?![[:word:]]))", + "end": "(?=\\bin\\b)|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "patterns": [ + { + "include": "#pathModuleSimple" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?|~$])=(?![#\\-:!?.@*/&%^+<=>|~$])|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "0": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\btype\\b|(?=[^[:space:]])", + "endCaptures": { + "0": { + "name": "keyword.control" + } + } + }, + { + "begin": "(?:(?<=(?:[^[:word:]]type|^type))(?![[:word:]]))", + "end": "(?|~$])\\.(?![#\\-:!?.@*/&%^+<=>|~$])", + "endCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#pattern" + } + ] + }, + { + "include": "#type" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\band\\b|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + } + ] + }, + "bindTermArgs": { + "patterns": [ + { + "begin": "~|\\?", + "end": ":|(?=[^[:space:]])", + "applyEndPatternLast": true, + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "endCaptures": { + "0": { + "name": "keyword" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]~|^~|[^#\\-:!?.@*/&%^+<=>|~$]\\?|^\\?))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)|(?<=\\))", + "endCaptures": { + "0": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "\\((?!\\*)", + "end": "\\)", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "begin": "(?<=\\()", + "end": ":|=", + "endCaptures": { + "0": { + "name": "keyword" + } + }, + "patterns": [ + { + "match": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + } + ] + }, + { + "begin": "(?<=:)", + "end": "=|(?=\\))", + "endCaptures": { + "0": { + "name": "keyword" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?=\\))", + "patterns": [ + { + "include": "#term" + } + ] + } + ] + } + ] + } + ] + }, + { + "include": "#pattern" + } + ] + }, + "bindType": { + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]and|^and|[^[:word:]]type|^type))(?![[:word:]]))", + "end": "(?|~$])\\+=|=(?![#\\-:!?.@*/&%^+<=>|~$])|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "0": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + }, + { + "include": "#pathType" + }, + { + "match": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "name": "entity.name.function strong" + }, + { + "include": "#type" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]\\+=|^\\+=|[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\band\\b|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "endCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + } + }, + "patterns": [ + { + "include": "#bindConstructor" + } + ] + } + ] + }, + "comment": { + "patterns": [ + { + "include": "#attribute" + }, + { + "include": "#extension" + }, + { + "include": "#commentBlock" + }, + { + "include": "#commentDoc" + } + ] + }, + "commentBlock": { + "begin": "\\(\\*(?!\\*[^\\)])", + "end": "\\*\\)", + "name": "comment constant.regexp meta.separator.markdown", + "contentName": "emphasis", + "patterns": [ + { + "include": "#commentBlock" + }, + { + "include": "#commentDoc" + } + ] + }, + "commentDoc": { + "begin": "\\(\\*\\*", + "end": "\\*\\)", + "name": "comment constant.regexp meta.separator.markdown", + "patterns": [ + { + "match": "\\*" + }, + { + "include": "#comment" + } + ] + }, + "decl": { + "patterns": [ + { + "include": "#declClass" + }, + { + "include": "#declException" + }, + { + "include": "#declInclude" + }, + { + "include": "#declModule" + }, + { + "include": "#declOpen" + }, + { + "include": "#declTerm" + }, + { + "include": "#declType" + } + ] + }, + "declClass": { + "begin": "\\bclass\\b", + "end": ";;|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "entity.name.class constant.numeric markup.underline" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "begin": "(?:(?<=(?:[^[:word:]]class|^class))(?![[:word:]]))", + "end": "\\btype\\b|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|val)\\b)", + "beginCaptures": { + "0": { + "name": "entity.name.class constant.numeric markup.underline" + } + }, + "endCaptures": { + "0": { + "name": "keyword" + } + }, + "patterns": [ + { + "include": "#bindClassTerm" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]type|^type))(?![[:word:]]))", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "patterns": [ + { + "include": "#bindClassType" + } + ] + } + ] + }, + "declException": { + "begin": "\\bexception\\b", + "end": ";;|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "keyword markup.underline" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + }, + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "include": "#bindConstructor" + } + ] + }, + "declInclude": { + "begin": "\\binclude\\b", + "end": ";;|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + }, + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "include": "#signature" + } + ] + }, + "declModule": { + "begin": "(?:(?<=(?:[^[:word:]]module|^module))(?![[:word:]]))|\\bmodule\\b", + "end": ";;|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename markup.underline" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "begin": "(?:(?<=(?:[^[:word:]]module|^module))(?![[:word:]]))", + "end": "(\\btype\\b)|(?=[[:upper:]])", + "endCaptures": { + "0": { + "name": "keyword" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + }, + { + "include": "#comment" + }, + { + "match": "\\brec\\b", + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]type|^type))(?![[:word:]]))", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "patterns": [ + { + "include": "#bindSignature" + } + ] + }, + { + "begin": "(?=[[:upper:]])", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "patterns": [ + { + "include": "#bindStructure" + } + ] + } + ] + }, + "declOpen": { + "begin": "\\bopen\\b", + "end": ";;|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + }, + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "include": "#pathModuleExtended" + } + ] + }, + "declTerm": { + "begin": "\\b(?:(external|val)|(method)|(let))\\b(!?)", + "end": ";;|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "1": { + "name": "support.type markup.underline" + }, + "2": { + "name": "storage.type markup.underline" + }, + "3": { + "name": "keyword.control markup.underline" + }, + "4": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "include": "#bindTerm" + } + ] + }, + "declType": { + "begin": "(?:(?<=(?:[^[:word:]]type|^type))(?![[:word:]]))|\\btype\\b", + "end": ";;|(?=\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "keyword markup.underline" + } + }, + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "include": "#bindType" + } + ] + }, + "extension": { + "begin": "(\\[)((?|~$])%{1,3}(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\]", + "beginCaptures": { + "1": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + }, + "2": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "endCaptures": { + "0": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + } + }, + "patterns": [ + { + "include": "#attributePayload" + } + ] + }, + "literal": { + "patterns": [ + { + "include": "#termConstructor" + }, + { + "include": "#literalArray" + }, + { + "include": "#literalBoolean" + }, + { + "include": "#literalCharacter" + }, + { + "include": "#literalList" + }, + { + "include": "#literalNumber" + }, + { + "include": "#literalObjectTerm" + }, + { + "include": "#literalString" + }, + { + "include": "#literalRecord" + }, + { + "include": "#literalUnit" + } + ] + }, + "literalArray": { + "begin": "\\[\\|", + "end": "\\|\\]", + "captures": { + "0": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + }, + "literalBoolean": { + "match": "\\bfalse|true\\b", + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + }, + "literalCharacter": { + "begin": "(?|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename emphasis" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]with|^with))(?![[:word:]]))", + "end": "(:)|(=)|(;)|(?=\\})", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "support.type strong" + }, + "3": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "match": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename emphasis" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(;)|(=)|(?=\\})", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": ";|(?=\\})", + "endCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + } + ] + }, + "literalString": { + "patterns": [ + { + "begin": "\"", + "end": "\"", + "name": "string beginning.punctuation.definition.quote.markdown", + "patterns": [ + { + "include": "#literalStringEscape" + } + ] + }, + { + "begin": "(\\{)([_[:lower:]]*?)(\\|)", + "end": "(\\|)(\\2)(\\})", + "name": "string beginning.punctuation.definition.quote.markdown", + "patterns": [ + { + "include": "#literalStringEscape" + } + ] + } + ] + }, + "literalStringEscape": { + "match": "\\\\(?:[\\\\\"ntbr]|[[:digit:]][[:digit:]][[:digit:]]|x[[:xdigit:]][[:xdigit:]]|o[0-3][0-7][0-7])" + }, + "literalUnit": { + "match": "\\(\\)", + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + }, + "pathModuleExtended": { + "patterns": [ + { + "include": "#pathModulePrefixExtended" + }, + { + "match": "(?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)", + "name": "entity.name.class constant.numeric" + } + ] + }, + "pathModulePrefixExtended": { + "begin": "(?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)(?=[[:space:]]*\\.|$|\\()", + "end": "(?![[:space:]\\.]|$|\\()", + "beginCaptures": { + "0": { + "name": "entity.name.class constant.numeric" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "\\(", + "end": "\\)", + "captures": { + "0": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "match": "((?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)(?=[[:space:]]*\\)))", + "name": "string.other.link variable.language variable.parameter emphasis" + }, + { + "include": "#structure" + } + ] + }, + { + "begin": "(?|~$])\\.(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": "((?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)(?=[[:space:]]*\\.|$))|((?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)(?=[[:space:]]*(?:$|\\()))|((?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)(?=[[:space:]]*\\)))|(?![[:space:]\\.[:upper:]]|$|\\()", + "beginCaptures": { + "0": { + "name": "keyword strong" + } + }, + "endCaptures": { + "1": { + "name": "entity.name.class constant.numeric" + }, + "2": { + "name": "entity.name.function strong" + }, + "3": { + "name": "string.other.link variable.language variable.parameter emphasis" + } + } + } + ] + }, + "pathModulePrefixExtendedParens": { + "begin": "\\(", + "end": "\\)", + "captures": { + "0": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "match": "((?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)(?=[[:space:]]*\\)))", + "name": "string.other.link variable.language variable.parameter emphasis" + }, + { + "include": "#structure" + } + ] + }, + "pathModulePrefixSimple": { + "begin": "(?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)(?=[[:space:]]*\\.)", + "end": "(?![[:space:]\\.])", + "beginCaptures": { + "0": { + "name": "entity.name.class constant.numeric" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "(?|~$])\\.(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": "((?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)(?=[[:space:]]*\\.))|((?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)(?=[[:space:]]*))|(?![[:space:]\\.[:upper:]])", + "beginCaptures": { + "0": { + "name": "keyword strong" + } + }, + "endCaptures": { + "1": { + "name": "entity.name.class constant.numeric" + }, + "2": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + } + } + } + ] + }, + "pathModuleSimple": { + "patterns": [ + { + "include": "#pathModulePrefixSimple" + }, + { + "match": "(?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)", + "name": "entity.name.class constant.numeric" + } + ] + }, + "pathRecord": { + "patterns": [ + { + "begin": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "end": "(?=[^[:space:]\\.])(?!\\(\\*)", + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]\\.|^\\.))(?![#\\-:!?.@*/&%^+<=>|~$]))|(?|~$])\\.(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": "((?|~$])\\.(?![#\\-:!?.@*/&%^+<=>|~$]))|((?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|mutable|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*))|(?<=\\))|(?<=\\])", + "beginCaptures": { + "0": { + "name": "keyword strong" + } + }, + "endCaptures": { + "1": { + "name": "keyword strong" + }, + "2": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pathModulePrefixSimple" + }, + { + "begin": "\\((?!\\*)", + "end": "\\)", + "captures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + }, + { + "begin": "\\[", + "end": "\\]", + "captures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#pattern" + } + ] + } + ] + } + ] + } + ] + }, + "pattern": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#patternArray" + }, + { + "include": "#patternLazy" + }, + { + "include": "#patternList" + }, + { + "include": "#patternMisc" + }, + { + "include": "#patternModule" + }, + { + "include": "#patternRecord" + }, + { + "include": "#literal" + }, + { + "include": "#patternParens" + }, + { + "include": "#patternType" + }, + { + "include": "#variablePattern" + }, + { + "include": "#termOperator" + } + ] + }, + "patternArray": { + "begin": "\\[\\|", + "end": "\\|\\]", + "captures": { + "0": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + } + }, + "patterns": [ + { + "include": "#pattern" + } + ] + }, + "patternLazy": { + "match": "lazy", + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "patternList": { + "begin": "\\[", + "end": "\\]", + "captures": { + "0": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + } + }, + "patterns": [ + { + "include": "#pattern" + } + ] + }, + "patternMisc": { + "match": "((?|~$]),(?![#\\-:!?.@*/&%^+<=>|~$]))|([#\\-:!?.@*/&%^+<=>|~$]+)|\\b(as)\\b", + "captures": { + "1": { + "name": "string.regexp strong" + }, + "2": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "3": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + } + }, + "patternModule": { + "begin": "\\bmodule\\b", + "end": "(?=\\))", + "beginCaptures": { + "0": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + } + }, + "patterns": [ + { + "include": "#declModule" + } + ] + }, + "patternParens": { + "begin": "\\((?!\\))", + "end": "\\)", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "(?|~$]):(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": "(?=\\))", + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + }, + { + "include": "#pattern" + } + ] + }, + "patternRecord": { + "begin": "\\{", + "end": "\\}", + "captures": { + "0": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong strong" + } + }, + "patterns": [ + { + "begin": "(?<=\\{|;)", + "end": "(:)|(=)|(;)|(with)|(?=\\})", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "support.type strong" + }, + "3": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "4": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pathModulePrefixSimple" + }, + { + "match": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename emphasis" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]with|^with))(?![[:word:]]))", + "end": "(:)|(=)|(;)|(?=\\})", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "support.type strong" + }, + "3": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "match": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename emphasis" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(;)|(=)|(?=\\})", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": ";|(?=\\})", + "endCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#pattern" + } + ] + } + ] + }, + "patternType": { + "begin": "\\btype\\b", + "end": "(?=\\))", + "beginCaptures": { + "0": { + "name": "keyword" + } + }, + "patterns": [ + { + "include": "#declType" + } + ] + }, + "pragma": { + "begin": "(?|~$])#(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#literalNumber" + }, + { + "include": "#literalString" + } + ] + }, + "signature": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#signatureLiteral" + }, + { + "include": "#signatureFunctor" + }, + { + "include": "#pathModuleExtended" + }, + { + "include": "#signatureParens" + }, + { + "include": "#signatureRecovered" + }, + { + "include": "#signatureConstraints" + } + ] + }, + "signatureConstraints": { + "begin": "\\bwith\\b", + "end": "(?=\\))|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]with|^with))(?![[:word:]]))", + "end": "\\b(?:(module)|(type))\\b", + "endCaptures": { + "1": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + }, + "2": { + "name": "keyword" + } + } + }, + { + "include": "#declModule" + }, + { + "include": "#declType" + } + ] + }, + "signatureFunctor": { + "patterns": [ + { + "begin": "\\bfunctor\\b", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "keyword" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]functor|^functor))(?![[:word:]]))", + "end": "(\\(\\))|(\\((?!\\)))", + "endCaptures": { + "1": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + }, + "2": { + "name": "punctuation.definition.tag" + } + } + }, + { + "begin": "(?<=\\()", + "end": "(:)|(\\))", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#variableModule" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#signature" + } + ] + }, + { + "begin": "(?<=\\))", + "end": "(\\()|((?|~$])->(?![#\\-:!?.@*/&%^+<=>|~$]))", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag" + }, + "2": { + "name": "support.type strong" + } + } + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]->|^->))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "patterns": [ + { + "include": "#signature" + } + ] + } + ] + }, + { + "match": "(?|~$])->(?![#\\-:!?.@*/&%^+<=>|~$])", + "name": "support.type strong" + } + ] + }, + "signatureLiteral": { + "begin": "\\bsig\\b", + "end": "\\bend\\b", + "captures": { + "0": { + "name": "punctuation.definition.tag emphasis" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "include": "#decl" + } + ] + }, + "signatureParens": { + "begin": "\\((?!\\))", + "end": "\\)", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "(?|~$]):(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": "(?=\\))", + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + } + }, + "patterns": [ + { + "include": "#signature" + } + ] + }, + { + "include": "#signature" + } + ] + }, + "signatureRecovered": { + "patterns": [ + { + "begin": "\\(|(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:|[^#\\-:!?.@*/&%^+<=>|~$]->|^->))(?![#\\-:!?.@*/&%^+<=>|~$]))|(?:(?<=(?:[^[:word:]]include|^include|[^[:word:]]open|^open))(?![[:word:]]))", + "end": "\\bmodule\\b|(?!$|[[:space:]]|\\bmodule\\b)", + "endCaptures": { + "0": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + } + } + }, + { + "begin": "(?:(?<=(?:[^[:word:]]module|^module))(?![[:word:]]))", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]module|^module))(?![[:word:]]))", + "end": "\\btype\\b", + "endCaptures": { + "0": { + "name": "keyword" + } + } + }, + { + "begin": "(?:(?<=(?:[^[:word:]]type|^type))(?![[:word:]]))", + "end": "\\bof\\b", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + } + }, + { + "begin": "(?:(?<=(?:[^[:word:]]of|^of))(?![[:word:]]))", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "patterns": [ + { + "include": "#signature" + } + ] + } + ] + } + ] + }, + "structure": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#structureLiteral" + }, + { + "include": "#structureFunctor" + }, + { + "include": "#pathModuleExtended" + }, + { + "include": "#structureParens" + } + ] + }, + "structureFunctor": { + "patterns": [ + { + "begin": "\\bfunctor\\b", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "0": { + "name": "keyword" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]functor|^functor))(?![[:word:]]))", + "end": "(\\(\\))|(\\((?!\\)))", + "endCaptures": { + "1": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + }, + "2": { + "name": "punctuation.definition.tag" + } + } + }, + { + "begin": "(?<=\\()", + "end": "(:)|(\\))", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#variableModule" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\)", + "endCaptures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#signature" + } + ] + }, + { + "begin": "(?<=\\))", + "end": "(\\()|((?|~$])->(?![#\\-:!?.@*/&%^+<=>|~$]))", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag" + }, + "2": { + "name": "support.type strong" + } + } + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]->|^->))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "patterns": [ + { + "include": "#structure" + } + ] + } + ] + }, + { + "match": "(?|~$])->(?![#\\-:!?.@*/&%^+<=>|~$])", + "name": "support.type strong" + } + ] + }, + "structureLiteral": { + "begin": "\\bstruct\\b", + "end": "\\bend\\b", + "captures": { + "0": { + "name": "punctuation.definition.tag emphasis" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pragma" + }, + { + "include": "#decl" + } + ] + }, + "structureParens": { + "begin": "\\(", + "end": "\\)", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#structureUnpack" + }, + { + "include": "#structure" + } + ] + }, + "structureUnpack": { + "begin": "\\bval\\b", + "end": "(?=\\))", + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + } + }, + "term": { + "patterns": [ + { + "include": "#termLet" + }, + { + "include": "#termAtomic" + } + ] + }, + "termAtomic": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#termConditional" + }, + { + "include": "#termConstructor" + }, + { + "include": "#termDelim" + }, + { + "include": "#termFor" + }, + { + "include": "#termFunction" + }, + { + "include": "#literal" + }, + { + "include": "#termMatch" + }, + { + "include": "#termMatchRule" + }, + { + "include": "#termPun" + }, + { + "include": "#termOperator" + }, + { + "include": "#termTry" + }, + { + "include": "#termWhile" + }, + { + "include": "#pathRecord" + } + ] + }, + "termConditional": { + "match": "\\b(?:if|then|else)\\b", + "name": "keyword.control" + }, + "termConstructor": { + "patterns": [ + { + "include": "#pathModulePrefixSimple" + }, + { + "match": "(?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)", + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong" + } + ] + }, + "termDelim": { + "patterns": [ + { + "begin": "\\((?!\\))", + "end": "\\)", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + }, + { + "begin": "\\bbegin\\b", + "end": "\\bend\\b", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "include": "#attributeIdentifier" + }, + { + "include": "#term" + } + ] + } + ] + }, + "termFor": { + "patterns": [ + { + "begin": "\\bfor\\b", + "end": "\\bdone\\b", + "beginCaptures": { + "0": { + "name": "keyword.control" + } + }, + "endCaptures": { + "0": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]for|^for))(?![[:word:]]))", + "end": "(?|~$])=(?![#\\-:!?.@*/&%^+<=>|~$])", + "endCaptures": { + "0": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#pattern" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "\\b(?:downto|to)\\b", + "endCaptures": { + "0": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]to|^to))(?![[:word:]]))", + "end": "\\bdo\\b", + "endCaptures": { + "0": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]do|^do))(?![[:word:]]))", + "end": "(?=\\bdone\\b)", + "patterns": [ + { + "include": "#term" + } + ] + } + ] + } + ] + }, + "termFunction": { + "match": "\\b(?:(fun)|(function))\\b", + "captures": { + "1": { + "name": "storage.type" + }, + "2": { + "name": "storage.type" + } + } + }, + "termLet": { + "patterns": [ + { + "begin": "(?:(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=|[^#\\-:!?.@*/&%^+<=>|~$]->|^->))(?![#\\-:!?.@*/&%^+<=>|~$]))|(?<=;|\\())(?=[[:space:]]|\\blet\\b)|(?:(?<=(?:[^[:word:]]begin|^begin|[^[:word:]]do|^do|[^[:word:]]else|^else|[^[:word:]]in|^in|[^[:word:]]struct|^struct|[^[:word:]]then|^then|[^[:word:]]try|^try))(?![[:word:]]))|(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]@@|^@@))(?![#\\-:!?.@*/&%^+<=>|~$]))[[:space:]]+", + "end": "\\b(?:(and)|(let))\\b|(?=[^[:space:]])(?!\\(\\*)", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + }, + "2": { + "name": "storage.type markup.underline" + } + }, + "patterns": [ + { + "include": "#comment" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]and|^and|[^[:word:]]let|^let))(?![[:word:]]))|(let)", + "end": "\\b(?:(and)|(in))\\b|(?=\\}|\\)|\\]|\\b(?:end|class|exception|external|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "1": { + "name": "storage.type markup.underline" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp markup.underline" + }, + "2": { + "name": "storage.type markup.underline" + } + }, + "patterns": [ + { + "include": "#bindTerm" + } + ] + } + ] + }, + "termMatch": { + "begin": "\\bmatch\\b", + "end": "\\bwith\\b", + "captures": { + "0": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + }, + "termMatchRule": { + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]fun|^fun|[^[:word:]]function|^function|[^[:word:]]with|^with))(?![[:word:]]))", + "end": "(?|~$])(\\|)|(->)(?![#\\-:!?.@*/&%^+<=>|~$])", + "endCaptures": { + "1": { + "name": "support.type strong" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#attributeIdentifier" + }, + { + "include": "#pattern" + } + ] + }, + { + "begin": "(?:(?<=(?:[^\\[#\\-:!?.@*/&%^+<=>|~$]\\||^\\|))(?![#\\-:!?.@*/&%^+<=>|~$]))|(?|~$])\\|(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": "(?|~$])(\\|)|(->)(?![#\\-:!?.@*/&%^+<=>|~$])", + "beginCaptures": { + "0": { + "name": "support.type strong" + } + }, + "endCaptures": { + "1": { + "name": "support.type strong" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#pattern" + }, + { + "begin": "\\bwhen\\b", + "end": "(?=(?|~$])->(?![#\\-:!?.@*/&%^+<=>|~$]))", + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + } + ] + } + ] + }, + "termOperator": { + "patterns": [ + { + "begin": "(?|~$])#(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "beginCaptures": { + "0": { + "name": "keyword" + } + }, + "endCaptures": { + "0": { + "name": "entity.name.function" + } + } + }, + { + "match": "<-", + "captures": { + "0": { + "name": "keyword.control strong" + } + } + }, + { + "match": "(,|[#\\-:!?.@*/&%^+<=>|~$]+)|(;)", + "captures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "2": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + } + }, + { + "match": "\\b(?:and|assert|asr|land|lazy|lsr|lxor|mod|new|or)\\b", + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + ] + }, + "termPun": { + "begin": "(?|~$])\\?|~(?![#\\-:!?.@*/&%^+<=>|~$])", + "end": ":|(?=[^[:space:]:])", + "applyEndPatternLast": true, + "beginCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "endCaptures": { + "0": { + "name": "keyword" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]\\?|^\\?|[^#\\-:!?.@*/&%^+<=>|~$]~|^~))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "endCaptures": { + "0": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + } + } + } + ] + }, + "termTry": { + "begin": "\\btry\\b", + "end": "\\bwith\\b", + "captures": { + "0": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + }, + "termWhile": { + "patterns": [ + { + "begin": "\\bwhile\\b", + "end": "\\bdone\\b", + "beginCaptures": { + "0": { + "name": "keyword.control" + } + }, + "endCaptures": { + "0": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "begin": "(?:(?<=(?:[^[:word:]]while|^while))(?![[:word:]]))", + "end": "\\bdo\\b", + "endCaptures": { + "0": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#term" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]do|^do))(?![[:word:]]))", + "end": "(?=\\bdone\\b)", + "patterns": [ + { + "include": "#term" + } + ] + } + ] + } + ] + }, + "type": { + "patterns": [ + { + "include": "#comment" + }, + { + "match": "\\bnonrec\\b", + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + { + "include": "#pathModulePrefixExtended" + }, + { + "include": "#typeLabel" + }, + { + "include": "#typeObject" + }, + { + "include": "#typeOperator" + }, + { + "include": "#typeParens" + }, + { + "include": "#typePolymorphicVariant" + }, + { + "include": "#typeRecord" + }, + { + "include": "#typeConstructor" + } + ] + }, + "typeConstructor": { + "patterns": [ + { + "begin": "(_)|((?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*))|(')((?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*))|(?<=[^\\*]\\)|\\])", + "end": "(?=\\((?!\\*)|\\*|:|,|=|\\.|>|-|\\{|\\[|\\+|\\}|\\)|\\]|;|\\|)|((?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*))[:space:]*(?!\\(\\*|[[:word:]])|(?=;;|\\}|\\)|\\]|\\b(?:end|and|class|exception|external|in|include|inherit|initializer|let|method|module|open|type|val)\\b)", + "beginCaptures": { + "1": { + "name": "comment constant.regexp meta.separator.markdown" + }, + "3": { + "name": "string.other.link variable.language variable.parameter emphasis strong emphasis" + }, + "4": { + "name": "keyword.control emphasis" + } + }, + "endCaptures": { + "1": { + "name": "entity.name.function strong" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pathModulePrefixExtended" + } + ] + } + ] + }, + "typeLabel": { + "patterns": [ + { + "begin": "(\\??)((?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*))[[:space:]]*((?|~$]):(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(?=(?|~$])->(?![#\\-:!?.@*/&%^+<=>|~$]))", + "captures": { + "1": { + "name": "keyword strong emphasis" + }, + "2": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename emphasis" + }, + "3": { + "name": "keyword" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + } + ] + }, + "typeModule": { + "begin": "\\bmodule\\b", + "end": "(?=\\))", + "beginCaptures": { + "0": { + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename" + } + }, + "patterns": [ + { + "include": "#pathModuleExtended" + }, + { + "include": "#signatureConstraints" + } + ] + }, + "typeObject": { + "begin": "<", + "end": ">", + "captures": { + "0": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong strong" + } + }, + "patterns": [ + { + "begin": "(?<=<|;)", + "end": "(:)|(?=>)", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "3": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "4": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pathModulePrefixSimple" + }, + { + "match": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename emphasis" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(;)|(?=>)", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + } + ] + }, + "typeOperator": { + "patterns": [ + { + "match": ",|;|[#\\-:!?.@*/&%^+<=>|~$]+", + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + } + ] + }, + "typeParens": { + "begin": "\\(", + "end": "\\)", + "captures": { + "0": { + "name": "punctuation.definition.tag" + } + }, + "patterns": [ + { + "match": ",", + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + { + "include": "#typeModule" + }, + { + "include": "#type" + } + ] + }, + "typePolymorphicVariant": { + "begin": "\\[", + "end": "\\]", + "patterns": [] + }, + "typeRecord": { + "begin": "\\{", + "end": "\\}", + "captures": { + "0": { + "name": "constant.language constant.numeric entity.other.attribute-name.id.css strong strong" + } + }, + "patterns": [ + { + "begin": "(?<=\\{|;)", + "end": "(:)|(=)|(;)|(with)|(?=\\})", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "support.type strong" + }, + "3": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "4": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pathModulePrefixSimple" + }, + { + "match": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename emphasis" + } + ] + }, + { + "begin": "(?:(?<=(?:[^[:word:]]with|^with))(?![[:word:]]))", + "end": "(:)|(=)|(;)|(?=\\})", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp strong" + }, + "2": { + "name": "support.type strong" + }, + "3": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "match": "(?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*)", + "name": "markup.inserted constant.language support.constant.property-value entity.name.filename emphasis" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]:|^:))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": "(;)|(=)|(?=\\})", + "endCaptures": { + "1": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + }, + "2": { + "name": "support.type strong" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + }, + { + "begin": "(?:(?<=(?:[^#\\-:!?.@*/&%^+<=>|~$]=|^=))(?![#\\-:!?.@*/&%^+<=>|~$]))", + "end": ";|(?=\\})", + "endCaptures": { + "0": { + "name": "variable.other.class.js message.error variable.interpolation string.regexp" + } + }, + "patterns": [ + { + "include": "#type" + } + ] + } + ] + }, + "variableModule": { + "match": "(?:\\b(?=[[:upper:]])[[:alpha:]_][[:word:]']*)", + "captures": { + "0": { + "name": "string.other.link variable.language variable.parameter emphasis" + } + } + }, + "variablePattern": { + "match": "(\\b_\\b)|((?:(?!\\b(?:and|'|as|asr|assert|\\*|begin|class|:|,|@|constraint|do|done|downto|else|end|=|exception|external|false|for|\\.|fun|function|functor|>|-|if|in|include|inherit|initializer|land|lazy|\\{|\\(|\\[|<|let|lor|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|#|object|of|open|or|%|\\+|private|\\?|\"|rec|\\\\|\\}|\\)|\\]|;|sig|/|struct|then|~|to|true|try|type|val|\\||virtual|when|while|with)\\b(?:[^']|$))\\b(?=[[:lower:]_])[[:alpha:]_][[:word:]']*))", + "captures": { + "1": { + "name": "comment constant.regexp meta.separator.markdown" + }, + "2": { + "name": "string.other.link variable.language variable.parameter emphasis" + } + } + } + } +} \ No newline at end of file From 1b8ce0e52725b7ae79057d5cb61d5c8b25f929fb Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 3 Aug 2026 11:09:33 +0800 Subject: [PATCH 08/34] fix: when fallbacks to `Bounds.Width`, respect the padding of `TextBox` Signed-off-by: leo --- src/Views/CommitMessageToolBox.axaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/CommitMessageToolBox.axaml.cs b/src/Views/CommitMessageToolBox.axaml.cs index efdff3ba4..480192cfb 100644 --- a/src/Views/CommitMessageToolBox.axaml.cs +++ b/src/Views/CommitMessageToolBox.axaml.cs @@ -387,7 +387,7 @@ private void OnLayoutUpdated(object sender, EventArgs e) return; } - var requiredWidth = _scrollViewer?.Viewport.Width ?? Bounds.Width; + var requiredWidth = _scrollViewer?.Viewport.Width ?? (Bounds.Width - 10); if (Math.Abs(_textPresenter.Bounds.Width - requiredWidth) >= 0.01) { _textPresenter.Width = requiredWidth; From 78ffc2bf49f3bcb3af34a8932f9cc248731dc9fd Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 3 Aug 2026 14:19:20 +0800 Subject: [PATCH 09/34] ux: pressing `ESC` will also clear notifications Signed-off-by: leo --- src/Views/Launcher.axaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index 99ebf66d9..e5d1a1923 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -299,6 +299,7 @@ protected override async void OnKeyDown(KeyEventArgs e) else if (e.Key == Key.Escape) { vm.ActivePage.CancelPopup(); + vm.ActivePage.Notifications.Clear(); e.Handled = true; return; } From f7a4e66cc1ab3d2d90f9010545e1d8904b917208 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 3 Aug 2026 14:48:06 +0800 Subject: [PATCH 10/34] fix: fast checking local change list with `Amend` enabled must make sure the staged list does not changed too (#2563) Signed-off-by: leo --- src/ViewModels/WorkingCopy.cs | 36 +++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index c0f273529..3ab5ceee8 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -231,13 +231,45 @@ public WorkingCopy(Repository repo) public void SetData(List changes) { - if (!IsChanged(_cached, changes)) + do { + if (IsChanged(_cached, changes)) + break; + + if (_useAmend) + { + var testStaged = GetStagedChanges(_cached); + if (IsChanged(_staged, testStaged)) + { + var visibleStagedNew = GetVisibleChanges(testStaged); + var selectedStagedNew = new List(); + + if (_selectedStaged is { Count: > 0 }) + { + var set = new HashSet(); + foreach (var c in _selectedStaged) + set.Add(c.Path); + + foreach (var c in visibleStagedNew) + { + if (set.Contains(c.Path)) + selectedStagedNew.Add(c); + } + } + + _isLoadingData = true; + Staged = testStaged; + VisibleStaged = visibleStagedNew; + SelectedStaged = selectedStagedNew; + _isLoadingData = false; + } + } + HasUnsolvedConflicts = _cached.Find(x => x.IsConflicted) != null; UpdateInProgressState(); UpdateDetail(); return; - } + } while (false); var lastSelectedUnstaged = new HashSet(); if (_selectedUnstaged is { Count: > 0 }) From 5f611d9513c3cb99669f50e0570d2af3dedb9219 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 3 Aug 2026 17:45:42 +0800 Subject: [PATCH 11/34] code_style: make sure that all `Stream` objects will be disposed immediately after operation finished Signed-off-by: leo --- src/Commands/SaveRevisionFile.cs | 2 +- src/ViewModels/CommitDetail.cs | 2 +- src/ViewModels/FileHistories.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Commands/SaveRevisionFile.cs b/src/Commands/SaveRevisionFile.cs index 410d15b07..6c810289d 100644 --- a/src/Commands/SaveRevisionFile.cs +++ b/src/Commands/SaveRevisionFile.cs @@ -16,7 +16,7 @@ public static async Task RunAsync(string repo, string revision, string file, str var isLFSFiltered = await new IsLFSFiltered(repo, revision, file).GetResultAsync().ConfigureAwait(false); if (isLFSFiltered) { - var pointerStream = await QueryFileContent.RunAsync(repo, revision, file).ConfigureAwait(false); + await using var pointerStream = await QueryFileContent.RunAsync(repo, revision, file).ConfigureAwait(false); await ExecCmdAsync(repo, "lfs smudge", saveTo, pointerStream).ConfigureAwait(false); } else diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index b23465774..754d36cdc 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -694,7 +694,7 @@ private async Task SetViewingBlobAsync(Models.Object file) return; } - var contentStream = await Commands.QueryFileContent.RunAsync(_repo.FullPath, _commit.SHA, file.Path); + await using var contentStream = await Commands.QueryFileContent.RunAsync(_repo.FullPath, _commit.SHA, file.Path); var content = await new StreamReader(contentStream).ReadToEndAsync(); var lfs = Models.LFSObject.Parse(content); if (lfs != null) diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs index 374396f1f..6cd4b1b8e 100644 --- a/src/ViewModels/FileHistories.cs +++ b/src/ViewModels/FileHistories.cs @@ -131,7 +131,7 @@ private async Task GetRevisionFileContentAsync(Models.Object obj) return new FileHistoriesRevisionFile(_file, binaryFile, true); } - var contentStream = await Commands.QueryFileContent.RunAsync(_repo, _revision.SHA, _file).ConfigureAwait(false); + await using var contentStream = await Commands.QueryFileContent.RunAsync(_repo, _revision.SHA, _file).ConfigureAwait(false); var content = await new StreamReader(contentStream).ReadToEndAsync(); var lfs = Models.LFSObject.Parse(content); if (lfs != null) From 5f55e545ce81178e2b8bd3b08c4ddea7a643c85d Mon Sep 17 00:00:00 2001 From: leo Date: Tue, 4 Aug 2026 11:40:56 +0800 Subject: [PATCH 12/34] feature: add a built-in hex-viewer to preview content of a binary file (#2593) Signed-off-by: leo --- src/Models/RevisionFile.cs | 11 + src/Resources/Locales/en_US.axaml | 2 + src/Resources/Locales/zh_CN.axaml | 2 + src/Resources/Locales/zh_TW.axaml | 2 + src/ViewModels/BinaryFile.cs | 83 ++++++ src/ViewModels/CommitDetail.cs | 2 +- src/ViewModels/FileHistories.cs | 2 +- src/Views/BinaryFileViewer.axaml | 49 ++++ src/Views/BinaryFileViewer.axaml.cs | 318 ++++++++++++++++++++++ src/Views/RevisionFileContentViewer.axaml | 8 +- 10 files changed, 470 insertions(+), 9 deletions(-) create mode 100644 src/ViewModels/BinaryFile.cs create mode 100644 src/Views/BinaryFileViewer.axaml create mode 100644 src/Views/BinaryFileViewer.axaml.cs diff --git a/src/Models/RevisionFile.cs b/src/Models/RevisionFile.cs index 9a9fe7d20..f2fb464d7 100644 --- a/src/Models/RevisionFile.cs +++ b/src/Models/RevisionFile.cs @@ -6,7 +6,18 @@ namespace SourceGit.Models { public class RevisionBinaryFile { + public string Repository { get; set; } = string.Empty; + public string File { get; set; } = string.Empty; + public string Revision { get; set; } = string.Empty; public long Size { get; set; } = 0; + + public RevisionBinaryFile(string repo, string file, string revision, long size) + { + Repository = repo; + File = file; + Revision = revision; + Size = size; + } } public class RevisionImageFile diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 676bd57a0..5c76fa80a 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -420,6 +420,8 @@ Fetch without tags Remote: Fetch Remote Changes + BINARY FILE + HEX VIEWER Assume unchanged Custom Action Discard... diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index d77cd5418..c3f171325 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -424,6 +424,8 @@ 不拉取远程标签 远程仓库 : 拉取远程仓库内容 + 二进制文件 + 查看内容 不跟踪此文件的更改 自定义操作 放弃更改... diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index b07c82996..3155fe0b5 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -424,6 +424,8 @@ 不提取遠端標籤 遠端存放庫: 提取遠端存放庫內容 + 二進位檔案 + 檢視內容 不追蹤此檔案的變更 自訂動作 捨棄變更... diff --git a/src/ViewModels/BinaryFile.cs b/src/ViewModels/BinaryFile.cs new file mode 100644 index 000000000..5c1985d47 --- /dev/null +++ b/src/ViewModels/BinaryFile.cs @@ -0,0 +1,83 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace SourceGit.ViewModels +{ + public class BinaryFile : ObservableObject, IDisposable + { + public long FileSize + { + get => _fileSize; + private set => SetProperty(ref _fileSize, value); + } + + public static async Task LoadAsync(string repo, string path, string revision = "HEAD") + { + string saveTo = Path.GetTempFileName(); + await Commands.SaveRevisionFile.RunAsync(repo, revision, path, saveTo).ConfigureAwait(false); + return new BinaryFile(saveTo); + } + + public BinaryFile(string file) + { + _filePath = file; + + if (File.Exists(_filePath)) + { + _fileSize = new FileInfo(_filePath).Length; + _reader = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.Read, BUFFER_SIZE, FileOptions.RandomAccess); + _readedStart = 0; + _readedEnd = Math.Min(_fileSize, BUFFER_SIZE); + + if (_fileSize > 0) + { + _reader.Seek(_readedStart, SeekOrigin.Begin); + _reader.ReadExactly(_buffer, 0, (int)_readedEnd); + } + } + } + + public void Dispose() + { + _reader?.Dispose(); + _reader = null; + + if (File.Exists(_filePath)) + File.Delete(_filePath); + } + + public ArraySegment Read(long offset, long length) + { + if (_reader == null || _fileSize == 0 || offset >= _fileSize) + return Array.Empty(); + + if (length > 8192) + length = 8192; + + if (offset + length > _fileSize) + length = _fileSize - offset; + + if (_readedStart <= offset && _readedEnd >= offset + length) + return new ArraySegment(_buffer, (int)(offset - _readedStart), (int)length); + + _readedStart = (Math.Max(0, offset - 2048) / 1024) * 1024; + _readedEnd = Math.Min(_readedStart + BUFFER_SIZE, _fileSize); + + _reader.Seek(_readedStart, SeekOrigin.Begin); + _reader.ReadExactly(_buffer, 0, (int)(_readedEnd - _readedStart)); + + return new ArraySegment(_buffer, (int)(offset - _readedStart), (int)length); + } + + private const int BUFFER_SIZE = 16384; + + private string _filePath = string.Empty; + private FileStream _reader = null; + private long _fileSize = 0; + private long _readedStart = 0; + private long _readedEnd = 0; + private byte[] _buffer = new byte[BUFFER_SIZE]; + } +} diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 754d36cdc..0daf09cf9 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -688,7 +688,7 @@ private async Task SetViewingBlobAsync(Models.Object file) else { var size = await new Commands.QueryFileSize(_repo.FullPath, file.Path, _commit.SHA).GetResultAsync(); - ViewRevisionFileContent = new Models.RevisionBinaryFile() { Size = size }; + ViewRevisionFileContent = new Models.RevisionBinaryFile(_repo.FullPath, file.Path, _commit.SHA, size); } return; diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs index 6cd4b1b8e..1ed6f42af 100644 --- a/src/ViewModels/FileHistories.cs +++ b/src/ViewModels/FileHistories.cs @@ -127,7 +127,7 @@ private async Task GetRevisionFileContentAsync(Models.Object obj) } var size = await new Commands.QueryFileSize(_repo, _file, _revision.SHA).GetResultAsync().ConfigureAwait(false); - var binaryFile = new Models.RevisionBinaryFile() { Size = size }; + var binaryFile = new Models.RevisionBinaryFile(_repo, _file, _revision.SHA, size); return new FileHistoriesRevisionFile(_file, binaryFile, true); } diff --git a/src/Views/BinaryFileViewer.axaml b/src/Views/BinaryFileViewer.axaml new file mode 100644 index 000000000..697918b33 --- /dev/null +++ b/src/Views/BinaryFileViewer.axaml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + - - - - - - - - - - -