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/TRANSLATION.md b/TRANSLATION.md index 47960c547..f9cf17f91 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -6,126 +6,27 @@ 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) +### ![de__DE](https://img.shields.io/badge/de__DE-99.61%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 +- Text.Diff.Binary.ViewContentOfNew +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress
-### ![el__GR](https://img.shields.io/badge/el__GR-99.51%25-yellow) +### ![el__GR](https://img.shields.io/badge/el__GR-99.12%25-yellow)
Missing keys in el_GR.axaml +- Text.Diff.Binary.ViewContentOfNew +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.Launcher.NewVersion - Text.Repository.FilterCommits.Collapse - Text.Repository.FilterCommits.Expand @@ -134,16 +35,20 @@ This document shows the translation status of each locale file in the repository
-### ![es__ES](https://img.shields.io/badge/es__ES-99.90%25-yellow) +### ![es__ES](https://img.shields.io/badge/es__ES-99.51%25-yellow)
Missing keys in es_ES.axaml +- Text.Diff.Binary.ViewContentOfNew +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.WorkingCopy.FilterChanges
-### ![fr__FR](https://img.shields.io/badge/fr__FR-95.49%25-yellow) +### ![fr__FR](https://img.shields.io/badge/fr__FR-95.21%25-yellow)
Missing keys in fr_FR.axaml @@ -160,9 +65,12 @@ This document shows the translation status of each locale file in the repository - Text.CommitCM.CopyCommitterTime - Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules - Text.CopyAsPatch -- Text.DeleteBranch.AskForRemote - Text.DeleteBranch.Force +- Text.Diff.Binary.ViewContentOfNew - Text.Diff.EmptyFile +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.FileModeChange - Text.FileModeChange.Deleted - Text.FileModeChange.Directory @@ -197,7 +105,7 @@ This document shows the translation status of each locale file in the repository
-### ![he__IL](https://img.shields.io/badge/he__IL-95.49%25-yellow) +### ![he__IL](https://img.shields.io/badge/he__IL-95.21%25-yellow)
Missing keys in he_IL.axaml @@ -214,9 +122,12 @@ This document shows the translation status of each locale file in the repository - Text.CommitCM.CopyCommitterTime - Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules - Text.CopyAsPatch -- Text.DeleteBranch.AskForRemote - Text.DeleteBranch.Force +- Text.Diff.Binary.ViewContentOfNew - Text.Diff.EmptyFile +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.FileModeChange - Text.FileModeChange.Deleted - Text.FileModeChange.Directory @@ -251,16 +162,20 @@ This document shows the translation status of each locale file in the repository
-### ![id__ID](https://img.shields.io/badge/id__ID-99.90%25-yellow) +### ![id__ID](https://img.shields.io/badge/id__ID-99.51%25-yellow)
Missing keys in id_ID.axaml +- Text.Diff.Binary.ViewContentOfNew +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.WorkingCopy.FilterChanges
-### ![it__IT](https://img.shields.io/badge/it__IT-89.03%25-yellow) +### ![it__IT](https://img.shields.io/badge/it__IT-88.77%25-yellow)
Missing keys in it_IT.axaml @@ -302,11 +217,14 @@ This document shows the translation status of each locale file in the repository - Text.ConfigureCustomActionControls.UseFriendlyName - Text.ConfirmEmptyCommit.StageSelectedThenCommit - Text.CopyAsPatch -- Text.DeleteBranch.AskForRemote - Text.DeleteBranch.Force +- Text.Diff.Binary.ViewContentOfNew - Text.Diff.EmptyFile - Text.Diff.Submodule.UncommittedChanges - Text.Discard.IncludeModified +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.FileModeChange - Text.FileModeChange.Deleted - Text.FileModeChange.Directory @@ -380,11 +298,15 @@ This document shows the translation status of each locale file in the repository
-### ![ja__JP](https://img.shields.io/badge/ja__JP-99.51%25-yellow) +### ![ja__JP](https://img.shields.io/badge/ja__JP-99.12%25-yellow)
Missing keys in ja_JP.axaml +- Text.Diff.Binary.ViewContentOfNew +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.Launcher.NewVersion - Text.Repository.FilterCommits.Collapse - Text.Repository.FilterCommits.Expand @@ -393,7 +315,7 @@ This document shows the translation status of each locale file in the repository
-### ![ko__KR](https://img.shields.io/badge/ko__KR-96.96%25-yellow) +### ![ko__KR](https://img.shields.io/badge/ko__KR-96.68%25-yellow)
Missing keys in ko_KR.axaml @@ -404,9 +326,12 @@ This document shows the translation status of each locale file in the repository - Text.CheckoutDetached.Target - Text.CheckoutDetached.Warning - Text.Configure.Git.EnableRecursiveWhenAutoUpdatingSubmodules -- Text.DeleteBranch.AskForRemote - Text.DeleteBranch.Force +- Text.Diff.Binary.ViewContentOfNew - Text.Diff.EmptyFile +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.FileModeChange - Text.FileModeChange.Deleted - Text.FileModeChange.Directory @@ -432,7 +357,7 @@ This document shows the translation status of each locale file in the repository
-### ![pt__BR](https://img.shields.io/badge/pt__BR-62.78%25-red) +### ![pt__BR](https://img.shields.io/badge/pt__BR-62.60%25-red)
Missing keys in pt_BR.axaml @@ -553,7 +478,6 @@ This document shows the translation status of each locale file in the repository - Text.DeinitSubmodule - Text.DeinitSubmodule.Force - Text.DeinitSubmodule.Path -- Text.DeleteBranch.AskForRemote - Text.DeleteBranch.Force - Text.DeleteMultiTags - Text.DeleteMultiTags.DeleteFromRemotes @@ -561,6 +485,7 @@ This document shows the translation status of each locale file in the repository - Text.DeleteRepositoryNode.Path - Text.DeleteRepositoryNode.TipForGroup - Text.DeleteRepositoryNode.TipForRepository +- Text.Diff.Binary.ViewContentOfNew - Text.Diff.EmptyFile - Text.Diff.First - Text.Diff.Image.Blend @@ -583,6 +508,9 @@ This document shows the translation status of each locale file in the repository - Text.ExecuteCustomAction.Target - Text.ExecuteCustomAction.Repository - Text.Fetch.Force +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.FileCM.CustomAction - Text.FileCM.ResolveUsing - Text.FileModeChange @@ -822,7 +750,7 @@ This document shows the translation status of each locale file in the repository ### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) -### ![ta__IN](https://img.shields.io/badge/ta__IN-64.45%25-red) +### ![ta__IN](https://img.shields.io/badge/ta__IN-64.26%25-red)
Missing keys in ta_IN.axaml @@ -965,11 +893,11 @@ This document shows the translation status of each locale file in the repository - Text.DeinitSubmodule - Text.DeinitSubmodule.Force - Text.DeinitSubmodule.Path -- Text.DeleteBranch.AskForRemote - Text.DeleteBranch.Force - Text.DeleteMultiTags - Text.DeleteMultiTags.DeleteFromRemotes - Text.DeleteMultiTags.Tip +- Text.Diff.Binary.ViewContentOfNew - Text.Diff.EmptyFile - Text.Diff.Image.Blend - Text.Diff.Image.Difference @@ -989,6 +917,9 @@ This document shows the translation status of each locale file in the repository - Text.EditBranchDescription.Target - Text.ExecuteCustomAction.Target - Text.ExecuteCustomAction.Repository +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.FileCM.CustomAction - Text.FileModeChange - Text.FileModeChange.Deleted @@ -1193,7 +1124,7 @@ This document shows the translation status of each locale file in the repository
-### ![uk__UA](https://img.shields.io/badge/uk__UA-65.23%25-red) +### ![uk__UA](https://img.shields.io/badge/uk__UA-65.04%25-red)
Missing keys in uk_UA.axaml @@ -1332,11 +1263,11 @@ This document shows the translation status of each locale file in the repository - Text.DeinitSubmodule - Text.DeinitSubmodule.Force - Text.DeinitSubmodule.Path -- Text.DeleteBranch.AskForRemote - Text.DeleteBranch.Force - Text.DeleteMultiTags - Text.DeleteMultiTags.DeleteFromRemotes - Text.DeleteMultiTags.Tip +- Text.Diff.Binary.ViewContentOfNew - Text.Diff.EmptyFile - Text.Diff.Image.Blend - Text.Diff.Image.Difference @@ -1356,6 +1287,9 @@ This document shows the translation status of each locale file in the repository - Text.EditBranchDescription.Target - Text.ExecuteCustomAction.Target - Text.ExecuteCustomAction.Repository +- Text.File.Binary +- Text.File.HexViewer +- Text.File.HexViewer.GotoAddress - Text.FileCM.CustomAction - Text.FileModeChange - Text.FileModeChange.Deleted diff --git a/src/App.axaml.cs b/src/App.axaml.cs index a22f764d6..c8d94d78c 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; @@ -14,6 +15,7 @@ using Avalonia.Platform; using Avalonia.Styling; using Avalonia.Threading; +using SourceGit.Models; namespace SourceGit { @@ -117,17 +119,21 @@ app.Resources[finalLocaleKey] is not ResourceDictionary targetLocale || app._activeLocale = targetLocale; } - public static void SetTheme(string theme, string themeOverridesFile) + public static void SetTheme(ThemeOverrides theme) { if (Current is not App app) return; - if (theme.Equals("Light", StringComparison.OrdinalIgnoreCase)) + string themeOverridesFile = string.Empty; + + if (theme.Name.Equals("Light", StringComparison.OrdinalIgnoreCase)) app.RequestedThemeVariant = ThemeVariant.Light; - else if (theme.Equals("Dark", StringComparison.OrdinalIgnoreCase)) + else if (theme.Name.Equals("Dark", StringComparison.OrdinalIgnoreCase)) app.RequestedThemeVariant = ThemeVariant.Dark; - else + else if (theme.Name.Equals("Default", StringComparison.OrdinalIgnoreCase)) app.RequestedThemeVariant = ThemeVariant.Default; + else + themeOverridesFile = theme.FilePath; if (app._themeOverrides != null) { @@ -243,7 +249,7 @@ public override void Initialize() var pref = ViewModels.Preferences.Instance; SetLocale(pref.Locale); - SetTheme(pref.Theme, pref.ThemeOverrides); + SetTheme(pref.Themes.FirstOrDefault(m=> m.Name == pref.Theme) ?? new ThemeOverrides("Default")); SetFonts(pref.DefaultFontFamily, pref.MonospaceFontFamily); } diff --git a/src/Commands/QueryFileSize.cs b/src/Commands/QueryFileSize.cs index c1ad51dfe..c2afe2650 100644 --- a/src/Commands/QueryFileSize.cs +++ b/src/Commands/QueryFileSize.cs @@ -1,29 +1,21 @@ -using System.Text.RegularExpressions; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace SourceGit.Commands { - public partial class QueryFileSize : Command + public class QueryFileSize : Command { - [GeneratedRegex(@"^\d+\s+\w+\s+[0-9a-f]+\s+(\d+)\s+.*$")] - private static partial Regex REG_FORMAT(); - public QueryFileSize(string repo, string file, string revision) { WorkingDirectory = repo; Context = repo; - Args = $"ls-tree {revision} -l -- {file.Quoted()}"; + Args = $"cat-file -s {revision}:{file.Quoted()}"; } public async Task GetResultAsync() { var rs = await ReadToEndAsync().ConfigureAwait(false); - if (rs.IsSuccess) - { - var match = REG_FORMAT().Match(rs.StdOut); - if (match.Success) - return long.Parse(match.Groups[1].Value); - } + if (rs.IsSuccess && long.TryParse(rs.StdOut.Trim(), out var size)) + return size; return 0; } diff --git a/src/Commands/QueryLocalChanges.cs b/src/Commands/QueryLocalChanges.cs index d1bd30a2c..31d72a095 100644 --- a/src/Commands/QueryLocalChanges.cs +++ b/src/Commands/QueryLocalChanges.cs @@ -34,9 +34,24 @@ public QueryLocalChanges(string repo, bool includeUntracked = true, bool noOptio try { using var proc = new Process(); + var captured = new CapturedProcess() { Process = proc }; + var capturedLock = new object(); + proc.StartInfo = CreateGitStartInfo(true); proc.Start(); + if (CancellationToken.CanBeCanceled) + { + CancellationToken.Register(() => + { + lock (capturedLock) + { + if (captured is { Process: { HasExited: false } }) + captured.Process.Kill(true); + } + }); + } + while (await proc.StandardOutput.ReadLineAsync().ConfigureAwait(false) is { } line) { var match = REG_FORMAT().Match(line); @@ -165,6 +180,11 @@ public QueryLocalChanges(string repo, bool includeUntracked = true, bool noOptio if (change.Index != Models.ChangeState.None || change.WorkTree != Models.ChangeState.None) outs.Add(change); } + + lock (capturedLock) + { + captured.Process = null; + } } catch { @@ -173,5 +193,10 @@ public QueryLocalChanges(string repo, bool includeUntracked = true, bool noOptio return outs; } + + private class CapturedProcess + { + public Process Process { get; set; } = null; + } } } 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/Converters/LongConverters.cs b/src/Converters/LongConverters.cs index 05a55e95b..fb72aadb7 100644 --- a/src/Converters/LongConverters.cs +++ b/src/Converters/LongConverters.cs @@ -18,6 +18,11 @@ public static class LongConverters return $"{(bytes / GB):G3} GB ({bytes:N0})"; }); + public static readonly FuncValueConverter IsGreaterThanZero = new(bytes => + { + return bytes > 0; + }); + private const double KB = 1024; private const double MB = 1024 * 1024; private const double GB = 1024 * 1024 * 1024; diff --git a/src/Models/BinaryFile.cs b/src/Models/BinaryFile.cs new file mode 100644 index 000000000..d875ac2f5 --- /dev/null +++ b/src/Models/BinaryFile.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; + +namespace SourceGit.Models +{ + public class BinaryFile : IDisposable + { + public long Size + { + get => _size; + } + + public BinaryFile(string file, bool needDeleteFile = false) + { + _filePath = file; + _needDeleteFile = needDeleteFile; + + if (File.Exists(_filePath)) + { + _size = new FileInfo(_filePath).Length; + _reader = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.Read, BUFFER_SIZE, FileOptions.RandomAccess); + _readedStart = 0; + _readedEnd = Math.Min(_size, BUFFER_SIZE); + + if (_size > 0) + { + _reader.Seek(_readedStart, SeekOrigin.Begin); + _reader.ReadExactly(_buffer, 0, (int)_readedEnd); + } + } + } + + public void Dispose() + { + _reader?.Dispose(); + _reader = null; + + if (_needDeleteFile && File.Exists(_filePath)) + File.Delete(_filePath); + } + + public ArraySegment Read(long offset, long length) + { + if (_reader == null || _size == 0 || offset >= _size) + return Array.Empty(); + + if (length > 8192) + length = 8192; + + if (offset + length > _size) + length = _size - 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, _size); + + _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 bool _needDeleteFile = false; + private FileStream _reader = null; + private long _size = 0; + private long _readedStart = 0; + private long _readedEnd = 0; + private byte[] _buffer = new byte[BUFFER_SIZE]; + } +} diff --git a/src/Models/DiffResult.cs b/src/Models/DiffResult.cs index ddb3d7e07..35b175c53 100644 --- a/src/Models/DiffResult.cs +++ b/src/Models/DiffResult.cs @@ -63,6 +63,10 @@ public class LFSDiff public class BinaryDiff { + public string Repository { get; set; } = string.Empty; + public string FilePath { get; set; } = string.Empty; + public string NewRevision { get; set; } = string.Empty; + public long OldSize { get; set; } = 0; public long NewSize { get; set; } = 0; } diff --git a/src/Models/ExternalTool.cs b/src/Models/ExternalTool.cs index 7f93cf8bd..7f30963a5 100644 --- a/src/Models/ExternalTool.cs +++ b/src/Models/ExternalTool.cs @@ -186,7 +186,7 @@ public void Cursor(Func platformFinder) public void FindJetBrainsFromToolbox(Func platformFinder) { - var supported = new List { "CL", "DB", "DL", "DS", "GO", "JB", "PC", "PS", "PY", "QA", "QD", "RD", "RM", "RR", "WRS", "WS" }; + var supported = new List { "AI", "CL", "DB", "DL", "DS", "GO", "IC", "IU", "JB", "PC", "PS", "PY", "QA", "QD", "RD", "RM", "RR", "WRS", "WS" }; var state = Path.Combine(platformFinder(), "state.json"); if (File.Exists(state)) { 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/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/Models/ThemeOverrides.cs b/src/Models/ThemeOverrides.cs index c80576dc8..80f3d40c0 100644 --- a/src/Models/ThemeOverrides.cs +++ b/src/Models/ThemeOverrides.cs @@ -5,9 +5,23 @@ namespace SourceGit.Models { public class ThemeOverrides { + public ThemeOverrides() + { + + } + + public ThemeOverrides(string name) + { + Name = name; + } + public string Version { get; set; } + public string Name { get; set; } + public string Author { get; set; } + public string Url { get; set; } public Dictionary BasicColors { get; set; } = new Dictionary(); public double GraphPenThickness { get; set; } = 2; public double OpacityForNotMergedCommits { get; set; } = 0.5; public List GraphColors { get; set; } = new List(); + public string FilePath { get; set; } } } 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 diff --git a/src/Resources/Icons.axaml b/src/Resources/Icons.axaml index 6852b6a51..2109df7cf 100644 --- a/src/Resources/Icons.axaml +++ b/src/Resources/Icons.axaml @@ -1,5 +1,6 @@ M41 512c0-128 46-241 138-333C271 87 384 41 512 41s241 46 333 138c92 92 138 205 138 333s-46 241-138 333c-92 92-205 138-333 138s-241-46-333-138C87 753 41 640 41 512zm87 0c0 108 36 195 113 271s164 113 271 113c108 0 195-36 271-113s113-164 113-271-36-195-113-271c-77-77-164-113-271-113-108 0-195 36-271 113C164 317 128 404 128 512zm256 148V292l195 113L768 512l-195 113-195 113v-77zm148-113-61 36V440l61 36 61 36-61 36z + M306 761c3-3 8-7 16-11 15-7 35-14 60-19 4-1 14-3 11-18l-3-16c-4-18-13-14-18-13C301 699 256 724 256 763c0 58 112 91 252 91 140 0 252-33 252-91 0-38-45-64-116-78-5-1-16-3-18 13-1 6-2 11-3 15-4 18 8 18 14 19 24 5 44 11 58 18 8 4 13 8 16 11 1 2 2 2 2 1 0 3-17 15-50 24-40 12-95 19-155 19-59 0-114-7-155-19-32-9-49-21-50-24 0 0 0-0 2-2zm73-123c54 79 107 142 129 142 22 0 75-62 129-142 62-91 101-173 101-231C738 280 635 176 508 176c-127 0-230 104-230 232 0 57 39 139 101 231zm150 64a446 446 0 01-21 23c-6-6-13-14-21-23-21-25-46-57-68-91-57-84-92-159-92-204 0-102 82-184 182-184 100 0 182 82 182 184 0 45-36 120-92 204-23 33-47 66-68 91zm-21-200a102 102 0 100-204 102 102 0 000 204zm0-48a54 54 0 110-108 54 54 0 010 108z M304 464a128 128 0 01128-128c71 0 128 57 128 128v224a32 32 0 01-64 0V592h-128v95a32 32 0 01-64 0v-224zm64 1v64h128v-64a64 64 0 00-64-64c-35 0-64 29-64 64zM688 337c18 0 32 14 32 32v319a32 32 0 01-32 32c-18 0-32-14-32-32v-319a32 32 0 0132-32zM84 911l60-143A446 446 0 0164 512C64 265 265 64 512 64s448 201 448 448-201 448-448 448c-54 0-105-9-153-27l-242 22a32 32 0 01-32-44zm133-150-53 126 203-18 13 5c41 15 85 23 131 23 212 0 384-172 384-384S724 128 512 128 128 300 128 512c0 82 26 157 69 220l20 29z M233 163h560c11 0 20-9 20-20V63h-226c-6-36-37-63-74-63s-68 27-74 63h-226v80c0 11 9 20 20 20zM883 63h-10v112c0 33-27 60-60 60h-600c-33 0-60-27-60-60V63h-10c-44 0-80 36-80 80v801c0 44 36 80 80 80h740c44 0 80-36 80-80V143c0-44-36-80-80-80zm-720 469c0-24 20-44 44-44h62v-72c0-24 20-44 44-44s44 20 44 44v72h62c24 0 44 20 44 44s-20 44-44 44h-62v72c0 24-20 44-44 44s-44-20-44-44v-72h-62c-24 0-44-20-44-44zm700 307c0 24-20 44-44 44h-612c-24 0-44-20-44-44s20-44 44-44h612c24 0 44 20 44 44zm0-191c0 24-20 44-44 44h-232c-24 0-44-20-44-44s20-44 44-44h232c24 0 44 20 44 44zm0-191c0 24-20 44-44 44h-162c-24 0-44-20-44-44s20-44 44-44h162c24 0 44 20 44 44z M366 146l293 0 0-73-293 0 0 73zm658 366 0 274q0 38-27 65t-65 27l-841 0q-38 0-65-27t-27-65l0-274 384 0 0 91q0 15 11 26t26 11l183 0q15 0 26-11t11-26l0-91 384 0zm-439 0 0 73-146 0 0-73 146 0zm439-274 0 219-1024 0 0-219q0-38 27-65t65-27l201 0 0-91q0-23 16-39t39-16l329 0q23 0 39 16t16 39l0 91 201 0q38 0 65 27t27 65z diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/AI.png b/src/Resources/Images/ExternalToolIcons/JetBrains/AI.png new file mode 100644 index 000000000..64390ed32 Binary files /dev/null and b/src/Resources/Images/ExternalToolIcons/JetBrains/AI.png differ diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/IC.png b/src/Resources/Images/ExternalToolIcons/JetBrains/IC.png new file mode 100644 index 000000000..62e50e936 Binary files /dev/null and b/src/Resources/Images/ExternalToolIcons/JetBrains/IC.png differ diff --git a/src/Resources/Images/ExternalToolIcons/JetBrains/IU.png b/src/Resources/Images/ExternalToolIcons/JetBrains/IU.png new file mode 100644 index 000000000..62e50e936 Binary files /dev/null and b/src/Resources/Images/ExternalToolIcons/JetBrains/IU.png differ diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index 57a344c63..eeb9a43f7 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 @@ -46,12 +52,13 @@ KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN Bild laden… Aktualisieren - BINÄRE DATEI WIRD NICHT UNTERSTÜTZT!!! Bisect Abbrechen 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 +69,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 +121,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 +138,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 +147,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 +180,7 @@ ÄNDERUNGEN geänderte Datei(en) Änderungen durchsuchen… + Details einklappen DATEIEN LFS-DATEI Dateien durchsuchen… @@ -178,9 +201,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 +254,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 +287,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 +299,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 +312,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Typ der Änderung: Kopieren Gesamten Text kopieren + Als Patch kopieren Ganzen Pfad kopieren Pfad kopieren Branch erstellen… @@ -310,7 +345,9 @@ $1, $2, … Werte der Eingabe-Steuerelemente Submodul: Branch löschen Branch: + Löschen erzwingen, auch bei nicht gemergten Commits Du bist dabei, einen Remote-Branch zu löschen!!! + Auch Remote-Branch ${0}$ löschen Mehrere Branches löschen Du versuchst, mehrere Branches auf einmal zu löschen. Kontrolliere dies sorgfältig, bevor du fortfährst! Mehrere Tags löschen @@ -330,6 +367,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 +387,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente SUBMODUL GELÖSCHT NEU + + {0} nicht committete Änderungen Seiten tauschen Syntax-Hervorhebung Zeilenumbruch @@ -365,6 +404,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 +440,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 +467,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 +506,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 +533,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 +542,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 +560,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 +573,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 +582,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Befehle FEHLER INFO + Neue Version verfügbar Repositorys öffnen Registerkarten Arbeitsumgebungen @@ -521,6 +591,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 @@ -532,7 +606,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente ERGEBNIS SPEICHERN & STAGEN DEREN - Merge-Konflikt – {0} + Merge-Konflikte Ungespeicherte Änderungen verwerfen? MEINE VERWENDEN DEREN VERWENDEN @@ -554,6 +628,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 +655,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 +690,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 +709,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 +757,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 +773,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente Benutzerdefinierte Aktion Löschen… Bearbeiten… + Auto-Fetch aktivieren Fetch Im Browser öffnen Prune @@ -711,9 +802,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 +905,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 +943,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 +959,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 +992,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 +1012,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 +1030,12 @@ $1, $2, … Werte der Eingabe-Steuerelemente ARBEITSUMGEBUNG: Arbeitsumgebungen konfigurieren… WORKTREE + BRANCH Pfad kopieren + HEAD Sperren Öffnen + PFAD Entfernen Entsperren JA diff --git a/src/Resources/Locales/el_GR.axaml b/src/Resources/Locales/el_GR.axaml index 4de2a9003..2b40a9811 100644 --- a/src/Resources/Locales/el_GR.axaml +++ b/src/Resources/Locales/el_GR.axaml @@ -52,7 +52,6 @@ ΚΑΝΕΝΑ ΑΡΧΕΙΟ ΔΕΝ ΘΕΩΡΕΙΤΑΙ ΑΜΕΤΑΒΛΗΤΟ Φόρτωση εικόνας... Ανανέωση - ΤΟ ΔΥΑΔΙΚΟ ΑΡΧΕΙΟ ΔΕΝ ΥΠΟΣΤΗΡΙΖΕΤΑΙ!!! Bisect Ματαίωση Κακό @@ -345,10 +344,10 @@ Εξαναγκασμός απο-αρχικοποίησης ακόμη κι αν περιέχει τοπικές αλλαγές. Υπομονάδα: Διαγραφή κλάδου - Θέλετε να διαγράψετε και τον ακόλουθο απομακρυσμένο κλάδο; Κλάδος: Εξαναγκασμένη διαγραφή ακόμη κι αν περιέχει μη συγχωνευμένα commit Πρόκειται να διαγράψετε έναν απομακρυσμένο κλάδο!!! + Διαγραφή και του απομακρυσμένου κλάδου ${0}$ Διαγραφή πολλαπλών κλάδων Προσπαθείτε να διαγράψετε πολλούς κλάδους ταυτόχρονα. Βεβαιωθείτε ότι ελέγξατε ξανά πριν προχωρήσετε! Διαγραφή πολλαπλών ετικετών diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 676bd57a0..80a17f794 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -48,7 +48,6 @@ NO FILES ASSUMED AS UNCHANGED Load Image... Refresh - BINARY FILE NOT SUPPORTED!!! Bisect Abort Bad @@ -341,10 +340,10 @@ Force de-init even if it contains local changes. Submodule: Delete Branch - Do you want to also delete the following remote branch? Branch: Force delete even if it contains unmerged commit(s) You are about to delete a remote branch!!! + Also delete remote branch ${0}$ Delete Multiple Branches You are trying to delete multiple branches at one time. Be sure to double-check before taking action! Delete Multiple Tags @@ -364,6 +363,7 @@ Tag: Delete from remote repositories BINARY DIFF + VIEW NEW CONTENT EMPTY FILE First Difference Ignore Whitespace Changes @@ -420,6 +420,9 @@ Fetch without tags Remote: Fetch Remote Changes + BINARY FILE + HEX VIEWER + Go to address... Assume unchanged Custom Action Discard... diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index ac2e7d76f..9579d594f 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -52,7 +52,6 @@ NO HAY ARCHIVOS ASUMIDOS COMO SIN CAMBIOS Cargar Imagen... Refrescar - ¡ARCHIVO BINARIO NO SOPORTADO! Bisect Abortar Malo @@ -345,10 +344,10 @@ Forzar desinicialización incluso si contiene cambios locales. Submódulo: Eliminar Rama - ¿Quieres que también se elimine la siguiente rama remota? Rama: Forzar la eliminación incluso si contiene commit(s) sin fusionar ¡Estás a punto de eliminar una rama remota! + También eliminar la rama remota ${0}$ Eliminar Múltiples Ramas Estás intentando eliminar múltiples ramas a la vez. ¡Asegúrate de comprobar dos veces antes de realizar esta acción! Eliminar Múltiples Etiquetas diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index a094fb2ae..1fcf148d9 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -49,7 +49,6 @@ PAS DE FICHIERS PRÉSUMÉS INCHANGÉS Charger l'Image... Rafraîchir - FICHIER BINAIRE NON SUPPORTÉ !!! Bisect Annuler Mauvais @@ -335,6 +334,7 @@ Supprimer la branche Branche : Vous êtes sur le point de supprimer une branche distante !!! + Supprimer également la branche distante ${0}$ Supprimer plusieurs branches Vous essayez de supprimer plusieurs branches à la fois. Assurez-vous de revérifier avant de procéder ! Supprimer plusieurs tags diff --git a/src/Resources/Locales/he_IL.axaml b/src/Resources/Locales/he_IL.axaml index 64346545d..988942439 100644 --- a/src/Resources/Locales/he_IL.axaml +++ b/src/Resources/Locales/he_IL.axaml @@ -49,7 +49,6 @@ אין קבצים בהנחת assume-unchanged טען תמונה... רענן - קובץ בינארי אינו נתמך!!! Bisect ביטול פגום (Bad) @@ -335,6 +334,7 @@ מחק Branch Branch: פעולה זו תמחק branch מרוחק!!! + למחוק גם את ה־branch המרוחק ${0}$ מחק מספר Branches פעולה זו תמחק מספר branches בו זמנית. בדוק היטב לפני הביצוע! מחק מספר Tags diff --git a/src/Resources/Locales/id_ID.axaml b/src/Resources/Locales/id_ID.axaml index 383ae256d..31c1bc55c 100644 --- a/src/Resources/Locales/id_ID.axaml +++ b/src/Resources/Locales/id_ID.axaml @@ -52,7 +52,6 @@ TIDAK ADA BERKAS YANG DIASUMSIKAN TIDAK BERUBAH Muat Gambar... Segarkan - BERKAS BINARY TIDAK DIDUKUNG!!! Bisect Batalkan Buruk @@ -345,10 +344,10 @@ Paksa de-init meski mengandung perubahan lokal. Submodule: Hapus Branch - Apakah Anda juga ingin menghapus remote branch berikut? Branch: Paksa hapus meskipun berisi commit yang belum di-merge Anda akan menghapus remote branch!!! + Juga hapus remote branch ${0}$ Hapus Beberapa Branch Anda akan menghapus beberapa branch sekaligus. Pastikan untuk memeriksa ulang sebelum bertindak! Hapus Beberapa Tag diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index 46b2fa9a5..59fba4f54 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -46,7 +46,6 @@ NESSUN FILE ASSUNTO COME INVARIATO Carico l'Immagine... Aggiorna - FILE BINARIO NON SUPPORTATO!!! Biseca Annulla Cattiva @@ -310,6 +309,7 @@ ${pure_files:N} Come ${files:N}, ma senza cartelle Elimina Branch Branch: Stai per eliminare un branch remoto!!! + Elimina anche il branch remoto ${0}$ Elimina Branch Multipli Stai per eliminare più branch contemporaneamente. Controlla attentamente prima di procedere! Elimina Tag Multipli diff --git a/src/Resources/Locales/ja_JP.axaml b/src/Resources/Locales/ja_JP.axaml index 844e70874..ef1389569 100644 --- a/src/Resources/Locales/ja_JP.axaml +++ b/src/Resources/Locales/ja_JP.axaml @@ -52,7 +52,6 @@ 未変更と見なしたファイルはありません 画像を選択... 再読み込み - バイナリファイルはサポートされていません!!! 問題の発生源を特定 中止 問題あり @@ -345,10 +344,10 @@ ローカルの変更の有無に関わらず、強制的に解除 サブモジュール: ブランチを削除 - 次のリモートブランチも削除しますか? ブランチ: 未マージのコミットがあっても強制的に削除 リモートブランチを削除しようとしています!!! + リモートブランチの ${0}$ も削除 複数のブランチを削除 複数のブランチをまとめて削除しようとしています。操作を行う前によく確認してください! 複数のタグを削除 diff --git a/src/Resources/Locales/ko_KR.axaml b/src/Resources/Locales/ko_KR.axaml index 5a1d7b053..cecfefb98 100644 --- a/src/Resources/Locales/ko_KR.axaml +++ b/src/Resources/Locales/ko_KR.axaml @@ -52,7 +52,6 @@ 변경되지 않음으로 간주된 파일 없음 이미지 불러오기... 새로 고침 - 바이너리 파일은 지원되지 않습니다!!! 이진 탐색 중단 나쁨 @@ -334,6 +333,7 @@ 브랜치 삭제 브랜치: 원격 브랜치를 삭제하려고 합니다!!! + 원격 브랜치 ${0}$도 함께 삭제 여러 브랜치 삭제 한 번에 여러 브랜치를 삭제하려고 합니다. 실행하기 전에 다시 한번 확인하세요! 여러 태그 삭제 diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index 8155dc647..c4904c975 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -46,7 +46,6 @@ NENHUM ARQUIVO CONSIDERADO SEM ALTERAÇÕES Carregar imagem... Atualizar - ARQUIVO BINÁRIO NÃO SUPORTADO!!! Bisect Abortar Inválido @@ -215,6 +214,7 @@ Excluir Branch Branch: Você está prestes a excluir uma branch remota!!! + Também excluir branch remoto ${0}$ Excluir Múltiplos Branches Você está tentando excluir vários branches de uma vez. Certifique-se de verificar antes de agir! Excluir Remoto diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 525796412..4166f03c7 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -52,7 +52,6 @@ СПИСОК ПУСТ Загрузить картинку... Обновить - ДВОИЧНЫЙ ФАЙЛ НЕ ПОДДЕРЖИВАЕТСЯ!!! Раздвоить О Плохая @@ -345,10 +344,10 @@ Принудительно удалить даже если содержит локальные изменения. Подмодуль: Удалить ветку - Вы хотите также удалить следующую удалённую ветку? Ветка: Принудительно удалить, даже если содержит неслитые ревизии Вы собираетесь удалить внешнюю ветку!!! + Также удалите внешнюю ветку ${0}$ Удаление нескольких веток Вы пытаетесь удалить несколько веток одновременно. Обязательно перепроверьте, прежде чем предпринимать какие-либо действия! Удалить несколько меток @@ -368,6 +367,7 @@ Метка: Удалить из внешнего репозитория СРАВНЕНИЕ БИНАРНИКОВ + ПРОСМОТР НОВОГО СОДЕРЖИМОГО ФАЙЛ ПУСТ Первое сравнение Игнорировать изменения пробелов @@ -424,6 +424,9 @@ Извлечь без меток Внешний репозиторий: Извлечь внешние изменения + ДВОИЧНЫЙ ФАЙЛ + ПРОСМОТР В ШЕСТНАДЦАТЕРИЧНОМ ФОРМАТЕ + Перейти по адресу... Не отслеживать Пользовательское действие Отклонить... diff --git a/src/Resources/Locales/ta_IN.axaml b/src/Resources/Locales/ta_IN.axaml index 5cbea045b..9606d3f54 100644 --- a/src/Resources/Locales/ta_IN.axaml +++ b/src/Resources/Locales/ta_IN.axaml @@ -37,7 +37,6 @@ கோப்புகள் மாற்றப்படவில்லை எனக் கருதப்படுகிறது எந்த கோப்புகளும் மாற்றப்படவில்லை எனக் கருதப்படுகிறது புதுப்பி - இருமம் கோப்பு ஆதரிக்கப்படவில்லை!!! குற்றச்சாட்டு இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!! ${0}$ சரிபார்... @@ -193,6 +192,7 @@ கிளையை நீக்கு கிளை: நீங்கள் ஒரு தொலை கிளையை நீக்கப் போகிறீர்கள்!!! + தொலை ${0}$ கிளையையும் நீக்கு பல கிளைகளை நீக்கு நீங்கள் ஒரே நேரத்தில் பல கிளைகளை நீக்க முயற்சிக்கிறீர்கள் நடவடிக்கை எடுப்பதற்கு முன் மீண்டும் சரிபார்! தொலையை நீக்கு diff --git a/src/Resources/Locales/uk_UA.axaml b/src/Resources/Locales/uk_UA.axaml index 9cad040c7..47288eb9c 100644 --- a/src/Resources/Locales/uk_UA.axaml +++ b/src/Resources/Locales/uk_UA.axaml @@ -37,7 +37,6 @@ ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ НЕМАЄ ФАЙЛІВ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ Оновити - БІНАРНИЙ ФАЙЛ НЕ ПІДТРИМУЄТЬСЯ!!! Автор рядка ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!! Перейти на ${0}$... @@ -197,6 +196,7 @@ Видалити гілку Гілка: Ви збираєтеся видалити віддалену гілку!!! + Також видалити віддалену гілку ${0}$ Видалити кілька гілок Ви намагаєтеся видалити кілька гілок одночасно. Перевірте ще раз перед виконанням! Видалити віддалене сховище diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index d77cd5418..1da3f3c5d 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -52,7 +52,6 @@ 没有不跟踪更改的文件 加载本地图片 重新加载 - 二进制文件不支持该操作!!! 二分定位(bisect) 终止 标记错误 @@ -345,10 +344,10 @@ 强制取消,即使包含本地变更 子模块 : 删除分支确认 - 是否同时删除以下远程分支? 分支名 : 强制删除,即使包含未合并的提交 您正在删除远程上的分支,请务必小心!!! + 同时删除远程分支 ${0}$ 删除多个分支 您正在尝试一次性删除多个分支,请务必仔细检查后再执行操作! 删除多个标签 @@ -368,6 +367,7 @@ 标签名 : 同时删除远程仓库中的此标签 二进制文件 + 查看新内容 空文件 首个差异 忽略空白符号变化 @@ -424,6 +424,9 @@ 不拉取远程标签 远程仓库 : 拉取远程仓库内容 + 二进制文件 + 查看内容 + 定位地址... 不跟踪此文件的更改 自定义操作 放弃更改... diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index b07c82996..a9d3bf364 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -52,7 +52,6 @@ 沒有不追蹤變更的檔案 載入本機圖片... 重新載入 - 二進位檔案不支援該操作! 二分搜尋 (bisect) 中止 標記為錯誤 @@ -345,10 +344,10 @@ 強制取消,即使包含本機變更 子模組: 刪除分支確認 - 您是否也想刪除以下遠端分支? 分支名稱: 強制刪除,即使包含未合併的提交 您正在刪除遠端上的分支,請務必小心! + 同時刪除遠端分支 ${0}$ 刪除多個分支 您正在嘗試一次性刪除多個分支,請務必仔細檢查後再刪除! 刪除多個標籤 @@ -368,6 +367,7 @@ 標籤名稱: 同時刪除遠端存放庫中的此標籤 二進位檔案 + 查看新內容 空檔案 第一個差異 忽略空白符號變化 @@ -424,6 +424,9 @@ 不提取遠端標籤 遠端存放庫: 提取遠端存放庫內容 + 二進位檔案 + 檢視內容 + 前往地址... 不追蹤此檔案的變更 自訂動作 捨棄變更... diff --git a/src/ViewModels/BinaryFileViewer.cs b/src/ViewModels/BinaryFileViewer.cs new file mode 100644 index 000000000..076887970 --- /dev/null +++ b/src/ViewModels/BinaryFileViewer.cs @@ -0,0 +1,66 @@ +using System.IO; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace SourceGit.ViewModels +{ + public class BinaryFileViewer : ObservableObject + { + public string File + { + get => _file; + } + + public bool IsLoading + { + get => _isLoading; + private set => SetProperty(ref _isLoading, value); + } + + public Models.BinaryFile Content + { + get => _content; + private set => SetProperty(ref _content, value); + } + + public BinaryFileViewer(string repo, string file, string revision) + { + _repo = repo; + _file = file; + _revision = revision; + } + + public async Task LoadAsync() + { + if (_revision != null) + { + string saveTo = Path.GetTempFileName(); + await Commands.SaveRevisionFile.RunAsync(_repo, _revision, _file, saveTo); + + Content = new Models.BinaryFile(saveTo, true); + } + else + { + Content = new Models.BinaryFile(Path.Combine(_repo, _file), false); + } + + IsLoading = false; + } + + public void Cleanup() + { + _repo = null; + _file = null; + _revision = null; + + _content?.Dispose(); + _content = null; + } + + private bool _isLoading = true; + private string _repo = null; + private string _file = null; + private string _revision = null; + private Models.BinaryFile _content = null; + } +} diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index b23465774..0daf09cf9 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -688,13 +688,13 @@ 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; } - 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/DeleteBranch.cs b/src/ViewModels/DeleteBranch.cs index ed8e8ff0b..57e29e023 100644 --- a/src/ViewModels/DeleteBranch.cs +++ b/src/ViewModels/DeleteBranch.cs @@ -1,5 +1,4 @@ using System; -using System.Text; using System.Threading.Tasks; namespace SourceGit.ViewModels @@ -11,6 +10,22 @@ public Models.Branch Target get; } + public Models.Branch Upstream + { + get; + } + + public string DeleteUpstreamTip + { + get; + } + + public bool DeleteUpstream + { + get; + set; + } + public bool Force { get; @@ -21,6 +36,16 @@ public DeleteBranch(Repository repo, Models.Branch branch) { _repo = repo; Target = branch; + + if (branch.IsLocal && !string.IsNullOrEmpty(branch.Upstream)) + { + var upstream = _repo.Branches.Find(x => x.FullName.Equals(branch.Upstream, StringComparison.Ordinal)); + if (upstream != null && upstream.Name.Equals(branch.Name, StringComparison.Ordinal)) + { + Upstream = upstream; + DeleteUpstreamTip = App.Text("DeleteBranch.WithTrackingRemote", upstream.FriendlyName); + } + } } public override async Task Sure() @@ -34,33 +59,26 @@ public override async Task Sure() var succ = false; if (Target.IsLocal) { - succ = await new Commands.Branch(_repo.FullPath, Target.Name) - .Use(log) - .DeleteLocalAsync(Force); - - if (succ) + do { + succ = await new Commands.Branch(_repo.FullPath, Target.Name) + .Use(log) + .DeleteLocalAsync(Force); + + if (!succ) + break; + _repo.UIStates.RemoveHistoryFilter(Target.FullName, Models.FilterType.LocalBranch); - var upstream = Target.Upstream ?? string.Empty; - var tracking = _repo.Branches.Find(x => x.FullName.Equals(upstream, StringComparison.Ordinal)); - if (tracking != null && tracking.Name.Equals(Target.Name, StringComparison.Ordinal)) - { - var msgBuilder = new StringBuilder(); - msgBuilder - .AppendLine(App.Text("DeleteBranch.AskForRemote")) - .AppendLine() - .Append("• ").Append(tracking.FriendlyName); - - var deleteTracking = await App.AskConfirmAsync(msgBuilder.ToString(), Models.ConfirmButtonType.YesNo); - if (deleteTracking) - { - succ = await DeleteRemoteBranchAsync(tracking, log); - if (succ) - _repo.UIStates.RemoveHistoryFilter(tracking.FullName, Models.FilterType.RemoteBranch); - } - } - } + if (!DeleteUpstream || Upstream == null) + break; + + succ = await DeleteRemoteBranchAsync(Upstream, log); + if (!succ) + break; + + _repo.UIStates.RemoveHistoryFilter(Upstream.FullName, Models.FilterType.RemoteBranch); + } while (false); } else { diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index 27eb93b8d..d943f2007 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -251,26 +251,47 @@ private void LoadContent() var binaryDiff = new Models.BinaryDiff(); var fullPath = Path.Combine(_repo, _option.Path); + binaryDiff.Repository = _repo; + binaryDiff.FilePath = _option.Path; + if (_option.Revisions.Count == 2) { if (_option.Revisions[0].Equals("-R", StringComparison.Ordinal)) { binaryDiff.OldSize = File.Exists(fullPath) ? new FileInfo(fullPath).Length : 0; binaryDiff.NewSize = await new Commands.QueryFileSize(_repo, _option.Path, _option.Revisions[1]).GetResultAsync().ConfigureAwait(false); + binaryDiff.NewRevision = _option.Revisions[1]; } else { binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, _option.Revisions[0]).GetResultAsync().ConfigureAwait(false); if (string.IsNullOrEmpty(_option.Revisions[1])) + { binaryDiff.NewSize = File.Exists(fullPath) ? new FileInfo(fullPath).Length : 0; + binaryDiff.NewRevision = null; + } else + { binaryDiff.NewSize = await new Commands.QueryFileSize(_repo, _option.Path, _option.Revisions[1]).GetResultAsync().ConfigureAwait(false); + binaryDiff.NewRevision = _option.Revisions[1]; + } } } else { - binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, "HEAD").GetResultAsync().ConfigureAwait(false); - binaryDiff.NewSize = File.Exists(fullPath) ? new FileInfo(fullPath).Length : 0; + if (!oldPath.Equals("/dev/null", StringComparison.Ordinal)) + binaryDiff.OldSize = await new Commands.QueryFileSize(_repo, oldPath, "HEAD").GetResultAsync().ConfigureAwait(false); + + if (_option.IsUnstaged) + { + binaryDiff.NewSize = File.Exists(fullPath) ? new FileInfo(fullPath).Length : 0; + binaryDiff.NewRevision = null; + } + else + { + binaryDiff.NewSize = await new Commands.QueryFileSize(_repo, _option.Path, string.Empty).GetResultAsync().ConfigureAwait(false); + binaryDiff.NewRevision = string.Empty; + } } return binaryDiff; diff --git a/src/ViewModels/FileHistories.cs b/src/ViewModels/FileHistories.cs index 374396f1f..1ed6f42af 100644 --- a/src/ViewModels/FileHistories.cs +++ b/src/ViewModels/FileHistories.cs @@ -127,11 +127,11 @@ 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); } - 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) diff --git a/src/ViewModels/Preferences.cs b/src/ViewModels/Preferences.cs index 25bbb431f..6c7fa7d2e 100644 --- a/src/ViewModels/Preferences.cs +++ b/src/ViewModels/Preferences.cs @@ -1,11 +1,14 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; +using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; using Avalonia.Collections; using CommunityToolkit.Mvvm.ComponentModel; +using SourceGit.Models; namespace SourceGit.ViewModels { @@ -41,26 +44,33 @@ public string Locale } } - public string Theme + [JsonIgnore] + public List Themes { - get => _theme; + get => _themes; set { - if (SetProperty(ref _theme, value) && !_isLoading) - App.SetTheme(_theme, _themeOverrides); + SetProperty(ref _themes, value); } } - public string ThemeOverrides + [JsonIgnore] + public ThemeOverrides SelectedTheme { - get => _themeOverrides; + get + { + return Themes.FirstOrDefault(m => m.Name == Theme) ?? new ThemeOverrides("Default"); + } set { - if (SetProperty(ref _themeOverrides, value) && !_isLoading) - App.SetTheme(_theme, value); + if (SetProperty(ref _selectedTheme, value) && !_isLoading) + App.SetTheme(_selectedTheme); + Theme = _selectedTheme.Name; } } - + + public string Theme { get; set; } + public string DefaultFontFamily { get => _defaultFontFamily; @@ -566,10 +576,7 @@ public RepositoryNode FindOrAddNodeByRepositoryPath(string repo, RepositoryNode { node = new RepositoryNode() { - Id = normalized, - Name = Path.GetFileName(normalized), - Bookmark = 0, - IsRepository = true, + Id = normalized, Name = Path.GetFileName(normalized), Bookmark = 0, IsRepository = true, }; AddNode(node, parent, save); @@ -649,6 +656,25 @@ public void Save() private static Preferences Load() { + try + { + var themesPath = Path.Combine(Native.OS.DataDir, "themes"); + var themeFiles = Directory.GetFiles(themesPath, "theme.json", SearchOption.AllDirectories); + foreach (var file in themeFiles) + { + using var stream = File.OpenRead(file); + var theme = JsonSerializer.Deserialize(stream, JsonCodeGen.Default.ThemeOverrides); + if (theme == null) + continue; + theme.FilePath = file; + _themes.Add(theme); + } + } + catch + { + // ignored + } + var path = Path.Combine(Native.OS.DataDir, "preference.json"); if (!File.Exists(path)) return new Preferences(); @@ -791,7 +817,8 @@ private bool RemoveInvalidRepositoriesRecursive(List collection) private bool _isLoading = true; private bool _isReadonly = true; private string _locale = "en_US"; - private string _theme = "Default"; + private ThemeOverrides _selectedTheme = new("Default"); + private static List _themes = new() { new ThemeOverrides("Default"), new ThemeOverrides("Dark"), new ThemeOverrides("Light") }; private string _themeOverrides = string.Empty; private string _defaultFontFamily = string.Empty; private string _monospaceFontFamily = string.Empty; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 99a3a47e2..526a9dbd2 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1330,6 +1330,7 @@ public void RefreshWorkingCopyChanges() Task.Run(async () => { var changes = await new Commands.QueryLocalChanges(FullPath, _uiStates.IncludeUntrackedInLocalChanges, noOptionalLocks) + .WithCancellation(token) .GetResultAsync() .ConfigureAwait(false); 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 }) diff --git a/src/Views/BinaryFileViewer.axaml b/src/Views/BinaryFileViewer.axaml new file mode 100644 index 000000000..962f60109 --- /dev/null +++ b/src/Views/BinaryFileViewer.axaml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/BinaryFileViewer.axaml.cs b/src/Views/BinaryFileViewer.axaml.cs new file mode 100644 index 000000000..8e2adde3d --- /dev/null +++ b/src/Views/BinaryFileViewer.axaml.cs @@ -0,0 +1,410 @@ +using System; +using System.Globalization; +using System.Text; + +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Input; +using Avalonia.Input.Platform; +using Avalonia.Interactivity; +using Avalonia.Media; +using Avalonia.Threading; +using Avalonia.VisualTree; + +namespace SourceGit.Views +{ + public class BinaryFileAddressTextBox : TextBox + { + protected override Type StyleKeyOverride => typeof(TextBox); + + protected override void OnLoaded(RoutedEventArgs e) + { + base.OnLoaded(e); + PastingFromClipboard += OnPastingFromClipboard; + } + + protected override void OnUnloaded(RoutedEventArgs e) + { + PastingFromClipboard -= OnPastingFromClipboard; + base.OnUnloaded(e); + } + + protected override void OnTextInput(TextInputEventArgs e) + { + if (string.IsNullOrEmpty(e.Text)) + return; + + var builder = new StringBuilder(e.Text.Length); + var chars = e.Text.ToCharArray(); + foreach (var ch in chars) + { + if ((ch >= '0' && ch <= '9') || + (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F')) + builder.Append(ch); + + if (builder.Length >= 8) + break; + } + + e.Text = builder.ToString(); + base.OnTextInput(e); + } + + private async void OnPastingFromClipboard(object sender, RoutedEventArgs e) + { + e.Handled = true; + + try + { + var clipboard = TopLevel.GetTopLevel(this)?.Clipboard; + if (clipboard != null) + { + var text = await clipboard.TryGetTextAsync(); + if (!string.IsNullOrEmpty(text)) + OnTextInput(new TextInputEventArgs() { Text = text }); + } + } + catch + { + // Ignore exceptions + } + } + } + + public class HexViewer : Control + { + public static readonly DirectProperty OffsetProperty = + AvaloniaProperty.RegisterDirect( + nameof(Offset), + static o => o.Offset, + static (o, v) => o.Offset = v); + + public long Offset + { + get => _offset; + set + { + if (SetAndRaise(OffsetProperty, ref _offset, value)) + InvalidateVisual(); + } + } + + public static readonly StyledProperty HeaderForegroundProperty = + AvaloniaProperty.Register(nameof(HeaderForeground), Brushes.White); + + public IBrush HeaderForeground + { + get => GetValue(HeaderForegroundProperty); + set => SetValue(HeaderForegroundProperty, value); + } + + public static readonly StyledProperty ForegroundProperty = + AvaloniaProperty.Register(nameof(Foreground), Brushes.White); + + public IBrush Foreground + { + get => GetValue(ForegroundProperty); + set => SetValue(ForegroundProperty, value); + } + + public const double HEADER_HEIGHT = 24.0; + public const double LINE_HEIGHT = 18.0; + public const double BYTE_CELL_WIDTH = 22.0; + public const int BYTES_PER_LINE = 16; + public const int BYTES_PER_LINE_HALF = 8; + public const double FONT_SIZE = 13; + + public void SetHighlightedIndex(long idx) + { + if (idx == _highlightedIdx) + return; + + _highlightedIdx = idx; + InvalidateVisual(); + } + + public override void Render(DrawingContext context) + { + base.Render(context); + + if (DataContext is not Models.BinaryFile vm) + return; + + context.FillRectangle(Brushes.Transparent, new Rect(0, 0, Bounds.Width, Bounds.Height)); + + var typeface = new Typeface("fonts:SourceGit#JetBrains Mono NL"); + var foreground = Foreground; + var headerForeground = HeaderForeground; + var highlightedBackground = new SolidColorBrush(Colors.Red, 0.2); + var highlightedBorder = new Pen(Brushes.Red, 0.5); + + var test = new FormattedText( + "F", + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + typeface, + FONT_SIZE, + foreground); + + var addrColumnWidth = test.Width * 9; + var x = addrColumnWidth + 16.0; + + _charWidth = test.Width; + _first8BytesX = x; + _second8BytesX = x + (BYTE_CELL_WIDTH * BYTES_PER_LINE_HALF) + 16.0; + _asciiColumnX = _second8BytesX + (BYTE_CELL_WIDTH * BYTES_PER_LINE_HALF) + 16.0; + + for (int i = 0; i < BYTES_PER_LINE; i++) + { + var hexLabel = new FormattedText( + i.ToString("X1"), + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + typeface, + FONT_SIZE, + headerForeground); + + var startX = x + (BYTE_CELL_WIDTH - hexLabel.Width) * 0.5; + var startY = (HEADER_HEIGHT - hexLabel.Height) * 0.5; + context.DrawText(hexLabel, new Point(startX, startY)); + x += BYTE_CELL_WIDTH; + + if (i == 7 || i == 15) + x += 16.0; + } + + var dataSize = (long)Math.Ceiling((Bounds.Height - HEADER_HEIGHT) / LINE_HEIGHT) * BYTES_PER_LINE; + var data = vm.Read(_offset, dataSize); + if (data.Count == 0) + return; + + x = 0.0; + var y = HEADER_HEIGHT - LINE_HEIGHT; + var columnIdx = 0; + for (var i = 0; i < data.Count; i++) + { + if (i % BYTES_PER_LINE == 0) + { + columnIdx = 0; + x = 0; + y += LINE_HEIGHT; + + var addr = new FormattedText( + (_offset + i).ToString("X8") + ":", + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + typeface, + FONT_SIZE, + headerForeground); + + context.DrawText(addr, new Point(x, y + (LINE_HEIGHT - addr.Height) * 0.5)); + x += addrColumnWidth + 16.0; + } + + var isHighlighted = (i + _offset) == _highlightedIdx; + var hex = data[i]; + var hexLabel = new FormattedText( + hex.ToString("X2"), + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + typeface, + FONT_SIZE, + hex == 0 ? Brushes.Gray : foreground); + + var ch = (char)hex; + var isPrintable = (hex >= 0x20 && hex <= 0x7E); + var chLabel = new FormattedText( + isPrintable ? ch.ToString() : ".", + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + typeface, + FONT_SIZE, + isPrintable ? Brushes.Green : Brushes.Gray); + + var hexX = x + (BYTE_CELL_WIDTH - hexLabel.Width) * 0.5; + var hexY = y + (LINE_HEIGHT - hexLabel.Height) * 0.5; + if (isHighlighted) + context.DrawRectangle(highlightedBackground, highlightedBorder, new Rect(x, y, BYTE_CELL_WIDTH, LINE_HEIGHT), 2, 2); + + context.DrawText(hexLabel, new Point(hexX, hexY)); + + var asciiX = _asciiColumnX + columnIdx * test.Width; + var asciiY = y + (LINE_HEIGHT - chLabel.Height) * 0.5; + if (isHighlighted) + context.DrawRectangle(highlightedBackground, highlightedBorder, new Rect(asciiX, y, test.Width, LINE_HEIGHT), 2, 2); + + context.DrawText(chLabel, new Point(asciiX, asciiY)); + + x += BYTE_CELL_WIDTH; + + if (columnIdx == 7 || columnIdx == 15) + x += 16.0; + + columnIdx++; + } + } + + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + base.OnPointerPressed(e); + + if (DataContext is not Models.BinaryFile vm) + return; + + var pos = e.GetPosition(this); + var testX = pos.X; + var testY = pos.Y - HEADER_HEIGHT; + if (testX <= _first8BytesX || testY <= 0) + return; + + long columnIdx = -1; + + if (testX >= _asciiColumnX) + { + var column = (testX - _asciiColumnX) / _charWidth; + if (column < 16) + columnIdx = (long)Math.Floor(column); + } + else if (testX >= _second8BytesX) + { + var column = (testX - _second8BytesX) / BYTE_CELL_WIDTH; + if (column < 8) + columnIdx = (long)Math.Floor(column) + 8; + } + else + { + var column = (testX - _first8BytesX) / BYTE_CELL_WIDTH; + if (column < 8) + columnIdx = (long)Math.Floor(column); + } + + if (columnIdx < 0) + return; + + var rowIdx = (long)Math.Floor(testY / LINE_HEIGHT); + var idx = _offset + rowIdx * BYTES_PER_LINE + columnIdx; + if (idx >= vm.Size) + return; + + SetHighlightedIndex(idx); + } + + private long _offset = 0; + private double _charWidth = 0; + private double _first8BytesX = 0; + private double _second8BytesX = 0; + private double _asciiColumnX = 0; + private long _highlightedIdx = -1; + } + + public partial class BinaryFileViewer : ChromelessWindow + { + public BinaryFileViewer() + { + CloseOnESC = true; + InitializeComponent(); + } + + protected override void OnOpened(EventArgs e) + { + base.OnOpened(e); + + // Queue loading to the next frame to avoid blocking the window-opening. + Dispatcher.UIThread.Post(async () => + { + if (DataContext is ViewModels.BinaryFileViewer vm) + await vm.LoadAsync(); + }); + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + + if (DataContext is ViewModels.BinaryFileViewer vm) + vm.Cleanup(); + } + + private void OnContentPointerWheelChanged(object sender, PointerWheelEventArgs e) + { + if (sender is not Grid grid) + return; + + var scroller = grid.FindDescendantOfType(); + if (scroller == null || !scroller.IsVisible) + return; + + scroller.Value -= e.Delta.Y * HexViewer.LINE_HEIGHT; + } + + private void OnContentSizeChanged(object sender, SizeChangedEventArgs e) + { + if (sender is not Grid { DataContext: Models.BinaryFile file } grid) + return; + + var scroller = grid.FindDescendantOfType(); + if (scroller == null) + return; + + var viewport = grid.Bounds.Height - HexViewer.HEADER_HEIGHT; + var max = Math.Ceiling(file.Size * 1.0 / HexViewer.BYTES_PER_LINE) * HexViewer.LINE_HEIGHT - viewport; + + if (max <= 0) + { + scroller.IsVisible = false; + } + else + { + scroller.IsVisible = true; + scroller.ViewportSize = viewport; + scroller.Maximum = max; + } + } + + private void OnScrollBarValueChanged(object sender, RangeBaseValueChangedEventArgs e) + { + if (sender is ScrollBar scroller) + { + var viewer = this.FindDescendantOfType(); + if (viewer != null) + viewer.Offset = (long)(Math.Ceiling(scroller.Value / HexViewer.LINE_HEIGHT) * HexViewer.BYTES_PER_LINE); + } + } + + private void OnGotoAddressTextChanged(object sender, TextChangedEventArgs e) + { + if (sender is BinaryFileAddressTextBox textBox && + DataContext is ViewModels.BinaryFileViewer { Content: { } file }) + { + var text = textBox.Text; + if (string.IsNullOrEmpty(text)) + return; + + long idx = 0; + try + { + idx = Convert.ToInt64(text, 16); + } + catch + { + // Ignore parsing errors + } + + if (idx < 0 || idx >= file.Size) + return; + + var scroller = ContentPanel.FindDescendantOfType(); + if (scroller is { IsVisible: true }) + { + var offset = Math.Floor(idx * 1.0 / HexViewer.BYTES_PER_LINE) * HexViewer.LINE_HEIGHT - (scroller.ViewportSize * 0.5); + scroller.Value = Math.Max(0, offset); + } + + var viewer = this.FindDescendantOfType(false); + viewer?.SetHighlightedIndex(idx); + } + } + } +} diff --git a/src/Views/CommitMessageToolBox.axaml.cs b/src/Views/CommitMessageToolBox.axaml.cs index 214f7fd8b..480192cfb 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) @@ -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) @@ -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; - } } 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 - 10); + 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) { diff --git a/src/Views/DeleteBranch.axaml b/src/Views/DeleteBranch.axaml index 3cd83e73d..d27b11ea7 100644 --- a/src/Views/DeleteBranch.axaml +++ b/src/Views/DeleteBranch.axaml @@ -18,7 +18,7 @@ Text="{DynamicResource Text.DeleteBranch}"/> - + @@ -37,24 +37,36 @@ - + + - - - - - + + + + + + + + + + diff --git a/src/Views/DiffView.axaml b/src/Views/DiffView.axaml index baf10f9b2..721891303 100644 --- a/src/Views/DiffView.axaml +++ b/src/Views/DiffView.axaml @@ -246,6 +246,13 @@ + + + + + - - - - - - - - - - - - - + + +