+CrowDesignAssembly/
+netcoredbg/
#Autosave files
*~
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFramework>net5</TargetFramework>
+ <TargetFramework>net9</TargetFramework>
<OutputType>WinExe</OutputType>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ProjectReference Include="plugins\CECrowPlugin\CECrowPlugin.csproj" >
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <Private>false</Private>
+ <ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
<ProjectReference Include="plugins\CEXmlPlugin\CEXmlPlugin.csproj" >
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <Private>false</Private>
+ <ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
<ProjectReference Include="plugins\CERoslynPlugin\CERoslynPlugin.csproj" >
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <Private>false</Private>
+ <ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
<ProjectReference Include="plugins\CENetcoreDbgPlugin\CENetcoreDbgPlugin.csproj" >
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <Private>false</Private>
+ <ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
+ <ProjectReference Include="plugins\CENugetPlugin\CENugetPlugin.csproj" >
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <Private>false</Private>
+ <ExcludeAssets>runtime</ExcludeAssets>
+ </ProjectReference>
+ <ProjectReference Include="plugins\CEEbnfPlugin\CEEbnfPlugin.csproj" >
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <Private>false</Private>
+ <ExcludeAssets>runtime</ExcludeAssets>
+ </ProjectReference>
</ItemGroup>
</Project>
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crow", "..\crow\Crow\Crow.csproj", "{5D8999F6-80D8-44CA-93F2-E18C9E44640C}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CENugetPlugin", "plugins\CENugetPlugin\CENugetPlugin.csproj", "{B0E09E4D-1907-46D4-B136-C7378A558201}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Drawing2D", "..\crow\Drawing2D\Drawing2D.csproj", "{22C1906B-BE08-4B31-AE02-2EE012CDA039}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CEEbnfPlugin", "plugins\CEEbnfPlugin\CEEbnfPlugin.csproj", "{CEE513F8-AE14-4588-8C9A-852455747A0B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
{5D8999F6-80D8-44CA-93F2-E18C9E44640C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D8999F6-80D8-44CA-93F2-E18C9E44640C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D8999F6-80D8-44CA-93F2-E18C9E44640C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B0E09E4D-1907-46D4-B136-C7378A558201}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B0E09E4D-1907-46D4-B136-C7378A558201}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B0E09E4D-1907-46D4-B136-C7378A558201}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B0E09E4D-1907-46D4-B136-C7378A558201}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22C1906B-BE08-4B31-AE02-2EE012CDA039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22C1906B-BE08-4B31-AE02-2EE012CDA039}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22C1906B-BE08-4B31-AE02-2EE012CDA039}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22C1906B-BE08-4B31-AE02-2EE012CDA039}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CEE513F8-AE14-4588-8C9A-852455747A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CEE513F8-AE14-4588-8C9A-852455747A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CEE513F8-AE14-4588-8C9A-852455747A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CEE513F8-AE14-4588-8C9A-852455747A0B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
{14E49365-6E22-4A27-B0E5-C6BBB347A85C} = {386C459C-4849-40C3-9D5A-4A8802A5A848}
{93105D4F-3015-4C37-A377-9E4BD63DB582} = {386C459C-4849-40C3-9D5A-4A8802A5A848}
{196D847E-D051-429B-892F-C405F036B8C2} = {386C459C-4849-40C3-9D5A-4A8802A5A848}
+ {B0E09E4D-1907-46D4-B136-C7378A558201} = {386C459C-4849-40C3-9D5A-4A8802A5A848}
+ {CEE513F8-AE14-4588-8C9A-852455747A0B} = {386C459C-4849-40C3-9D5A-4A8802A5A848}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {121E26CF-4A0F-4E74-BC0F-82BABEFDE8BF}
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
+ <TargetFrameworks>net9</TargetFrameworks>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Crow" Version="1.1.0-beta" />
- <PackageReference Include="Crow.CairoBackend" Version="1.1.0-beta" />
+ <ProjectReference Include="/mnt/sdata/devel/crow/Crow/Crow.csproj"/>
+ <!--<PackageReference Include="Crow" Version="1.3.2-beta" />-->
+ <PackageReference Include="Crow.CairoBackend" Version="1.2.1-beta" />
</ItemGroup>
+ <ItemGroup>
+ <AssemblyAttribute Include="Crow.CrowAssemblyPriority">
+ <_Parameter1>0</_Parameter1>
+ </AssemblyAttribute>
+ </ItemGroup>
</Project>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
+<path fill="#dddddd" d="M8 6h3c0.6 0 1-0.1 1-0.1 1.3-0.4 2-1.9 2-3.4 0-0.3-0.2-0.5-0.5-0.5s-0.5 0.2-0.5 0.5c0 1-0.5 2.5-1.8 2.5h-0.2c0 0 0.2-2.1-2-2.8v-1.7c0-0.3-0.2-0.5-0.5-0.5s-0.5 0.2-0.5 0.5v1.5c-0.2 0-0.3 0-0.5 0s-0.3 0-0.5 0v-1.5c0-0.3-0.2-0.5-0.5-0.5s-0.5 0.2-0.5 0.5v1.7c-2.2 0.7-2 2.8-2 2.8h-0.2c-1.3 0-1.8-1.5-1.8-2.5 0-0.3-0.2-0.5-0.5-0.5s-0.5 0.2-0.5 0.5c0 1.4 0.7 2.9 2 3.4 0 0 0.3 0.1 1 0.1h4zM8 3h1v1h-1v-1zM6 3h1v1h-1v-1z"></path>
+<path fill="#dddddd" d="M3 7v1c-2.8 0.1-3 1.4-3 3.5 0 0.2 0.2 0.5 0.5 0.5s0.5-0.3 0.5-0.5c0-1.8 0-2.4 2-2.5 0 0 0 1.6 0.6 3.1-0.4 0.1-0.7 0.2-0.9 0.5-0.7 0.6-0.7 1.7-0.7 2.7v0.1c0 0.3 0.2 0.6 0.5 0.6s0.5-0.3 0.5-0.5v-0.1c0-0.8 0-1.7 0.4-2.1 0.1-0.2 0.4-0.3 0.7-0.3 0.5 1 1.5 1.8 2.9 2v-8h-4z"></path>
+<path fill="#dddddd" d="M12 8v-1h-4v8c1.4-0.2 2.4-1 2.9-1.9 0.3 0 0.5 0.1 0.7 0.2 0.4 0.4 0.4 1.2 0.4 2.1v0.1c0 0.3 0.2 0.5 0.5 0.5s0.5-0.2 0.5-0.5v-0.1c0-1 0-2.1-0.7-2.8-0.2-0.2-0.6-0.4-0.9-0.5 0.6-1.5 0.6-3 0.6-3.1 2 0 2 0.7 2 2.5 0 0.3 0.2 0.5 0.5 0.5s0.5-0.2 0.5-0.5c0-2.1-0.2-3.4-3-3.5z"></path>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
+<path fill="#dddddd" d="M0 1h7v14h-7v-14z"></path>
+<path fill="#dddddd" d="M9 1h7v14h-7v-14z"></path>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
+<path fill="#dddddd" d="M2 1v14l12-7z"></path>
+</svg>
--- /dev/null
+<svg class="svg-icon" style="width: 1em; height: 1em;vertical-align: middle;fill: #dddddd;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 938.666667a85.333333 85.333333 0 0 1-85.333333-85.333334 85.333333 85.333333 0 0 1 85.333333-85.333333 85.333333 85.333333 0 0 1 85.333333 85.333333 85.333333 85.333333 0 0 1-85.333333 85.333334m42.666667-853.333334v469.333334l192-192 60.586666 60.586666L512 718.506667 216.746667 423.253333 277.333333 362.666667 469.333333 554.666667V85.333333h85.333334z" fill="" /></svg>
\ No newline at end of file
--- /dev/null
+<svg class="svg-icon" style="width: 1em; height: 1em;vertical-align: middle;fill: #dddddd;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 938.666667a85.333333 85.333333 0 0 1-85.333333-85.333334 85.333333 85.333333 0 0 1 85.333333-85.333333 85.333333 85.333333 0 0 1 85.333333 85.333333 85.333333 85.333333 0 0 1-85.333333 85.333334m42.666667-256h-85.333334V256l-192 192-60.586666-60.586667L512 92.16l295.253333 295.253333-60.586666 60.586667L554.666667 256v426.666667z" fill="" /></svg>
\ No newline at end of file
--- /dev/null
+<svg class="svg-icon" style="width: 1em; height: 1em;vertical-align: middle;fill: #dddddd;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 597.333333C558.933333 597.333333 597.333333 635.733333 597.333333 682.666667 597.333333 729.6 558.933333 768 512 768 465.066667 768 426.666667 729.6 426.666667 682.666667 426.666667 635.733333 465.066667 597.333333 512 597.333333M1000.96 378.026667 933.12 672 640 604.16 802.133333 502.613333C741.973333 405.333333 634.453333 341.333333 512 341.333333 343.466667 341.333333 203.52 463.36 175.786667 624.213333L91.733333 609.28C126.293333 408.746667 301.226667 256 512 256 664.746667 256 799.146667 336.64 874.666667 457.386667L1000.96 378.026667Z" /></svg>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16">
+<path fill="#dddddd" d="M1 1h14v14h-14v-14z"></path>
+</svg>
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512">
+ <path d="M448 341.37V170.61A32 32 0 00432.11 143l-152-88.46a47.94 47.94 0 00-48.24 0L79.89 143A32 32 0 0064 170.61v170.76A32 32 0 0079.89 369l152 88.46a48 48 0 0048.24 0l152-88.46A32 32 0 00448 341.37z"
+ fill="currentColor" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/>
+ <path fill="currentColor" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"
+ d="M69 153.99l187 110 187-110M256 463.99v-200"/>
+</svg>
\ No newline at end of file
Tokenizer tokenizer = CreateTokenizer ();
tokens = tokenizer.Tokenize (Source);
SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
+
+ if (syntaxAnalyser == null) {
+ RootNode = null;
+ return;
+ }
+
syntaxAnalyser.Process ();
+ NotifyValueChanged("Exceptions", syntaxAnalyser.Exceptions);
SyntaxNode newNode = syntaxAnalyser.Root.FindNodeIncludingSpan (TextSpan.FromStartAndLength (change.Start, change.ChangedText.Length));
currentTokenIndex = FindTokenIndexIncludingPosition (pos);
CurrentNode = FindNodeIncludingSpan (currentToken.Span);
NotifyValueChanged ("CurrentTokenString", (object)CurrentTokenString);
+ //NotifyValueChanged ("CurrentTokenType", (uint)(currentToken.Type)>>8);
+ NotifyValueChanged ("CurrentTokenType", (object)GetTokenTypeString(currentToken.Type));
}else {
currentTokenIndex = -1;
CurrentNode = null;
return Colors.DarkSlateBlue;
return Colors.Red;
}
+ public virtual string GetTokenTypeString (TokenType tokenType) => tokenType.ToString();
protected abstract Tokenizer CreateTokenizer ();
protected abstract SyntaxAnalyser CreateSyntaxAnalyser ();
public abstract IList GetSuggestions (CharLocation loc);
public abstract bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection);
void parse () {
Tokenizer tokenizer = CreateTokenizer ();
- tokens = tokenizer.Tokenize (Source);
-
+ tokens = tokenizer?.Tokenize (Source);
SyntaxAnalyser syntaxAnalyser = CreateSyntaxAnalyser ();
- //Stopwatch sw = Stopwatch.StartNew ();
- syntaxAnalyser.Process ();
- //sw.Stop();
- RootNode = syntaxAnalyser.Root;
-
- /*Console.WriteLine ($"Syntax Analysis done in {sw.ElapsedMilliseconds}(ms) {sw.ElapsedTicks}(ticks)");
+ Stopwatch sw = Stopwatch.StartNew ();
+ syntaxAnalyser?.Process ();
+ sw.Stop();
+ RootNode = syntaxAnalyser?.Root;
+
+ //CrowEditBase.App.Log (LogType.Low, $"Syntax Analysis done in {sw.ElapsedMilliseconds}(ms) {sw.ElapsedTicks}(ticks)");
+ if (syntaxAnalyser == null)
+ return;
+ LogItem log = CrowEditBase.App.GetLog(this.FileName);
+ log.ResetLog();
foreach (SyntaxException ex in syntaxAnalyser.Exceptions)
- Console.WriteLine ($"{ex}");*/
+ log.Add(LogType.Error, $"{ex}");
/*foreach (Token t in Tokens)
Console.WriteLine ($"{t,-40} {Source.AsSpan(t.Start, t.Length).ToString()}");
this.source = source;
}
public abstract void Process ();
+ protected Token curTok;
protected SyntaxNode currentNode;
protected int currentLine, tokIdx;
}
protected void setCurrentNodeEndLine (int endLine)
=> currentNode.EndLine = endLine;
+
+
+ //bool EOF => tokIdx == tokens.Length;
}
}
\ No newline at end of file
public int StartLine { get; private set; }
public virtual int LineCount => lineCount;
public virtual bool IsComplete => LastTokenOffset.HasValue;
- public virtual bool IsFoldable => Parent.StartLine != StartLine && lineCount > 1;
+ public virtual bool IsFoldable => IsComplete && Parent.StartLine != StartLine && lineCount > 1;
public virtual SyntaxRootNode Root => Parent.Root;
public virtual void UnfoldToTheTop () {
isFolded = false;
public TextSpan Span => new TextSpan (Start, End);
public string AsString (ReadOnlySpan<char> source)
=> source.Slice (Start, Length).ToString();
-
+ public char GetChar (ReadOnlySpan<char> source, int charIndex = 0)
+ => source[Start + charIndex];
public Token (TokenType type, int pos) {
Type = type;
Start = pos;
}
protected virtual void skipWhiteSpaces (ref SpanCharReader reader) {
while(!reader.EndOfSpan) {
- switch (reader.Peak) {
+ switch (reader.Peek) {
case '\x85':
case '\x2028':
case '\xA':
case '\x20':
case '\x9':
char c = reader.Read();
- while (reader.TryPeak (c))
+ while (reader.TryPeek (c))
reader.Read();
addTok (ref reader, c == '\x20' ? TokenType.WhiteSpace : TokenType.Tabulation);
break;
namespace CrowEditBase
{
public abstract class CrowEditBase : Interface {
- protected Dictionary<string, List<Type>> FileAssociations = new Dictionary<string, List<Type>> ();
- protected Dictionary<Type, List<string>> SupportedEditors = new Dictionary<Type, List<string>> ();
- ObservableList<LogEntry> logs = new ObservableList<LogEntry>();
- public ObservableList<LogEntry> MainLog => logs;
-
- public void Log(LogType type, string message) {
- lock (logs)
- logs.Add (new LogEntry(type, message));
+ public static CrowEditBase App;
+ public CrowEditBase (int width, int height, bool singleThreaded = true) : base (width, height, singleThreaded) {
+ App = this;
+ MainLog = GetLog("CrowEdit");
+ MainLog.IsOpened = true;
+ Log(LogType.Normal,"Crow edit started");
}
- public void ResetLog () {
- lock (logs)
- logs.Clear ();
+
+ #region logging
+ LogItem currentLog;
+ public LogItem CurrentLog {
+ get => currentLog;
+ set {
+ if (currentLog == value)
+ return;
+
+ if (currentLog != null)
+ currentLog.IsSelected = false;
+
+ currentLog = value;
+ NotifyValueChanged (currentLog);
+
+ if (currentLog == null)
+ return;
+
+ currentLog.IsSelected = true;
+ }
+ }
+ public ObservableList<LogItem> Logs = new ObservableList<LogItem>();
+ public ObservableList<LogItem> OpenedLogs = new ObservableList<LogItem>();
+ internal LogItem MainLog;
+ [Obsolete]public void Log(LogType type, string message) {
+ MainLog.Add (type, message);
+ }
+ [Obsolete]public void ResetLog () {
+ MainLog.ResetLog();
+ }
+ public LogItem GetLog(string name) {
+ LogItem li = Logs.FirstOrDefault(l=>string.Equals(l.Name,name,StringComparison.OrdinalIgnoreCase));
+ if (li == null) {
+ li = new LogItem(name);
+ lock (Logs) {
+ lock(UpdateMutex)
+ Logs.Add(li);
+ }
+ }
+ return li;
+ }
+ internal void OpenLog(LogItem li) {
+ lock(OpenedLogs)
+ OpenedLogs.Add(li);
+ }
+ internal void CloseLog(LogItem li) {
+ lock(OpenedLogs) {
+ if (li.IsSelected) {
+ int idx = OpenedLogs.IndexOf(li);
+ OpenedLogs.RemoveAt(idx);
+ int count = OpenedLogs.Count();
+ if (idx < count)
+ OpenedLogs[idx].IsSelected = true;
+ else if (count > 0)
+ OpenedLogs[count-1].IsSelected = true;
+ } else
+ OpenedLogs.Remove(li);
+ }
}
+ #endregion
+
+ #region File associations and supported editors
+ protected Dictionary<string, List<Type>> FileAssociations = new Dictionary<string, List<Type>> ();
+ protected Dictionary<Type, List<string>> SupportedEditors = new Dictionary<Type, List<string>> ();
public void AddFileAssociation (string extension, Type clientClass) {
if (!FileAssociations.ContainsKey (extension))
FileAssociations.Add (extension, new List<Type> ());
editorPath = SupportedEditors.ContainsKey (clientType) ? SupportedEditors[clientType].FirstOrDefault () : null;
return editorPath != null;
}
+ #endregion
-
- public static CrowEditBase App;
- public CrowEditBase (int width, int height) : base (width, height, true) {
- App = this;
- }
-
protected const string _defaultFileName = "unnamed.txt";
Document currentDocument;
NotifyValueChanged (CurrentDir);
}
}
- public string PluginsDirecory {
- get => Configuration.Global.Get<string>("PluginsDirecory", defaultPluginsDirectory);
+ public string PluginsDirectory {
+ get => Configuration.Global.Get<string>("PluginsDirectory", defaultPluginsDirectory);
set {
- if (PluginsDirecory == value)
+ if (PluginsDirectory == value)
return;
- Configuration.Global.Set ("PluginsDirecory", value);
- NotifyValueChanged (PluginsDirecory);
+ Configuration.Global.Set ("PluginsDirectory", value);
+ NotifyValueChanged (PluginsDirectory);
}
}
public string CurrentFilePath {
g.DataSource = dataSource;
return g as Window;
} catch (Exception ex) {
- Console.WriteLine (ex.ToString ());
+ Log (LogType.Error, ex.ToString ());
}
return null;
}
public ActionCommand CMDOptions_SelectPluginsDirectory => new ActionCommand ("...",
() => {
FileDialog dlg = App.LoadIMLFragment<FileDialog> (@"
- <FileDialog Caption='Select CrowEdit Directory' CurrentDirectory='{PluginsDirecory}'
+ <FileDialog Caption='Select CrowEdit Directory' CurrentDirectory='{PluginsDirectory}'
ShowFiles='false' ShowHidden='true' />");
- dlg.OkClicked += (sender, e) => PluginsDirecory = (sender as FileDialog).SelectedFileFullPath;
+ dlg.OkClicked += (sender, e) => PluginsDirectory = (sender as FileDialog).SelectedFileFullPath;
dlg.DataSource = this;
}
);
public ActionCommand CMDOptions_ResetPluginsDirectory => new ActionCommand ("Reset",
() => {
- PluginsDirecory = defaultPluginsDirectory;
+ PluginsDirectory = defaultPluginsDirectory;
}
);
static string defaultPluginsDirectory =>
Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".config", "CrowEdit", "plugins");
protected void loadPlugins () {
- if (!Directory.Exists (PluginsDirecory))
- return;
+ Log(LogType.Message, $"Searching for plugins in {PluginsDirectory}");
- foreach (string pluginDir in Directory.GetDirectories (PluginsDirecory)) {
+ if (!Directory.Exists (PluginsDirectory)) {
+ Log(LogType.Error, $"Plugins directory not found: {PluginsDirectory}");
+ return;
+ }
+
+ List<Plugin> pluginsToReload = new List<Plugin>();
+ foreach (string pluginDir in Directory.GetDirectories (PluginsDirectory)) {
Plugin plugin = new Plugin (pluginDir);
Plugins.Add (plugin);
- plugin.Load ();
+ if (!plugin.Load ())
+ pluginsToReload.Add(plugin);
+
}
+ foreach (Plugin p in pluginsToReload) {
+ p.Unload();
+ if (!p.Load())
+ App.Log(LogType.Warning, $"Plugin load failed: {p.Name}");
+ }
+
}
public IEnumerable<AssemblyLoadContext> AllLoadContexts =>
System.Runtime.Loader.AssemblyLoadContext.All;
- #region Editor item templates
- public string EditorItemTemplates {
- get {
- StringBuilder sb = new StringBuilder (1024);
- sb.Append (defaultEditorITemps);
- foreach (string editorPath in SupportedEditors.Values.SelectMany (a=>a).Distinct ())
- sb.Append ($"<ItemTemplate Path='{editorPath}' DataTest='EditorPath' DataType='{editorPath}'/>");
- return sb.ToString ();
+ #region Editor item templates
+ public string EditorItemTemplates {
+ get {
+ StringBuilder sb = new StringBuilder (1024);
+ sb.Append (defaultEditorITemps);
+ foreach (string editorPath in SupportedEditors.Values.SelectMany (a=>a).Distinct ())
+ sb.Append ($"<ItemTemplate Path='{editorPath}' DataTest='EditorPath' DataType='{editorPath}'/>");
+ return sb.ToString ();
+ }
}
- }
- string defaultEditorITemps = @"
- <ItemTemplate>
- <ListItem IsVisible='{IsSelected}' IsSelected='{²IsSelected}' Selected=""{/tb.HasFocus='true'}"">
- <VerticalStack Spacing='0'>
- <HorizontalStack Spacing='0' Background='White'>
- <Editor Name='tb' Font='consolas, 12' Margin='5'
- Document='{}' TextChanged='onTextChanged'/>
- <ScrollBar Value='{²../tb.ScrollY}'
- LargeIncrement='{../tb.PageHeight}' SmallIncrement='1'
- CursorRatio='{../tb.ChildHeightRatio}' Maximum='{../tb.MaxScrollY}' />
- </HorizontalStack>
- <ScrollBar Style='HScrollBar' Value='{²../tb.ScrollX}'
- LargeIncrement='{../tb.PageWidth}' SmallIncrement='1'
- CursorRatio='{../tb.ChildWidthRatio}' Maximum='{../tb.MaxScrollX}' />
- <HorizontalStack Height='Fit' Spacing='3'>
- <Widget Width='Stretched'/>
- <Label Text='Line:' Foreground='Grey'/>
- <Label Text='{../../tb.CurrentLine}' Margin='3'/>
- <Label Text='col:' Foreground='Grey'/>
- <Label Text='{../../tb.CurrentColumn}' Margin='3'/>
- </HorizontalStack>
- </VerticalStack>
- </ListItem>
- </ItemTemplate>
- ";
- #endregion
-
-
-#region main options
+ string defaultEditorITemps = @"
+ <ItemTemplate>
+ <ListItem IsVisible='{IsSelected}' IsSelected='{²IsSelected}' Selected=""{/tb.HasFocus='true'}"">
+ <VerticalStack Spacing='0'>
+ <HorizontalStack Spacing='0' Background='White'>
+ <Editor Name='tb' Font='consolas, 12' Margin='5'
+ Document='{}' TextChanged='onTextChanged'/>
+ <ScrollBar Value='{²../tb.ScrollY}'
+ LargeIncrement='{../tb.PageHeight}' SmallIncrement='1'
+ CursorRatio='{../tb.ChildHeightRatio}' Maximum='{../tb.MaxScrollY}' />
+ </HorizontalStack>
+ <ScrollBar Style='HScrollBar' Value='{²../tb.ScrollX}'
+ LargeIncrement='{../tb.PageWidth}' SmallIncrement='1'
+ CursorRatio='{../tb.ChildWidthRatio}' Maximum='{../tb.MaxScrollX}' />
+ <HorizontalStack Height='Fit' Spacing='3'>
+ <Widget Width='Stretched'/>
+ <Label Text='Line:' Foreground='Grey'/>
+ <Label Text='{../../tb.CurrentLine}' Margin='3'/>
+ <Label Text='col:' Foreground='Grey'/>
+ <Label Text='{../../tb.CurrentColumn}' Margin='3'/>
+ </HorizontalStack>
+ </VerticalStack>
+ </ListItem>
+ </ItemTemplate>
+ ";
+ #endregion
+
+ #region main options
public int CrowUpdateInterval {
get => Crow.Interface.UPDATE_INTERVAL;
set {
}
}
-#endregion
+ #endregion
}
}
\ No newline at end of file
Ready,
/// <summary>running state received</summary>
Running,
+ /// <summary> abort requested </summary>
+ Stopping,
/// <summary>stopped event received</summary>
Stopped,
}
public virtual CommandGroup Commands => new CommandGroup (
CMDDebugStart, CMDDebugPause, CMDDebugStop, CMDDebugStepIn, CMDDebugStepOver, CMDDebugStepOut);
protected virtual void initCommands () {
- CMDDebugStart = new ActionCommand ("Start", Start, "#Icons.debug-play.svg");
- CMDDebugPause = new ActionCommand ("Pause", Pause, "#Icons.debug-pause.svg", false);
- CMDDebugStop = new ActionCommand ("Stop", Stop, "#Icons.debug-stop.svg", false);
- CMDDebugStepIn = new ActionCommand ("Step in", StepIn, "#Icons.debug-step-into.svg", false);
- CMDDebugStepOut = new ActionCommand ("Step out", StepOut, "#Icons.debug-step-out.svg", false);
- CMDDebugStepOver = new ActionCommand ("Step over", StepOver, "#Icons.debug-step-over.svg", false);
+ CMDDebugStart = new ActionCommand ("Start", Start, "#icons.debug-play.svg");
+ CMDDebugPause = new ActionCommand ("Pause", Pause, "#icons.debug-pause.svg", false);
+ CMDDebugStop = new ActionCommand ("Stop", Stop, "#icons.debug-stop.svg", false);
+ CMDDebugStepIn = new ActionCommand ("Step in", StepIn, "#icons.debug-step-into.svg", false);
+ CMDDebugStepOut = new ActionCommand ("Step out", StepOut, "#icons.debug-step-out.svg", false);
+ CMDDebugStepOver = new ActionCommand ("Step over", StepOver, "#icons.debug-step-over.svg", false);
}
{
if (currentState == value)
return;
+
currentState = value;
CMDDebugStepIn.CanExecute = CMDDebugStepOut.CanExecute = CMDDebugStepOver.CanExecute =
(CurrentState == Status.Stopped);
CMDDebugStart.CanExecute = (CurrentState == Status.Ready || CurrentState == Status.Stopped);
- CMDDebugPause.CanExecute = CMDDebugStop.CanExecute = (CurrentState == Status.Running);
+ CMDDebugPause.CanExecute = (CurrentState == Status.Running);
+ CMDDebugStop.CanExecute = (CurrentState == Status.Running || CurrentState == Status.Stopped);
+
+ NotifyValueChanged(currentState);
}
}
StackFrame executingFile;
return;
currentThread = value;
NotifyValueChanged(currentThread);
+ onCurrentThreadChanged();
}
}
public StackFrame CurrentFrame
public void OnQueryClose (object sender, EventArgs e){
CloseEvent.Raise (this, null);
}
+ protected abstract void saveFileDialog_OkClicked (object sender, EventArgs e);
public void SaveAs () {
App.LoadIMLFragment (
- "<FileDialog Width='60%' Height='50%' Caption='Save File' CurrentDirectory='{FileDirectory}' OkClicked='saveFileDialog_OkClicked'/>"
+ @"<FileDialog Width='60%' Height='50%' Caption='Save File' CurrentDirectory='{FileDirectory}'
+ SelectedFile='{FileName}' OkClicked='saveFileDialog_OkClicked'/>"
).DataSource = this;
}
public void Save () {
selStart = selectionStart.Value;
selEnd = CurrentLoc.Value;
}
- } else
- IFace.forceTextCursor = true;
+ }
//}
if (document.Lenght > 0) {
if (l.Length > 0) {
int size = l.Length * 4 + 1;
if (bytes.Length < size)
- bytes = size > 512 ? new byte[size] : stackalloc byte[size];
+ bytes = new byte[size];
encodedBytes = document.GetText (l).ToUtf8 (bytes);
bytes[encodedBytes++] = 0;
}
//}
- Rectangle c = ScreenCoordinates (textCursor.Value + Slot.Position + ClientRectangle.Position);
- ctx.ResetClip ();
+ Rectangle c = ContextCoordinates (textCursor.Value + Slot.Position + ClientRectangle.Position);
Foreground.SetAsSource (IFace, ctx, c);
ctx.LineWidth = 1.0;
ctx.MoveTo (0.5 + c.X, c.Y);
DbgLogger.EndEvent(DbgEvtType.GOMeasure);
}
}
- public override void Paint (IContext ctx) {
- base.Paint (ctx);
- IFace.forceTextCursor = true;
- }
protected override void onDraw (IContext gr)
{
//base.onDraw (gr);
if (ClipToClientRect)
gr.Restore ();
}
+ public override bool Paint(IContext ctx)
+ {
+ bool painted = base.Paint(ctx);
+ if (HasFocus && painted && IFace.drawTextCursor) {
+ DrawCursor(ctx, out Rectangle r);
+ }
+ return painted;
+ }
#endregion
#region Mouse handling
if (HasFocus && IFace.IsDown (MouseButton.Left)) {
CurrentLoc = hoverLoc;
autoAdjustScroll = true;
- IFace.forceTextCursor = true;
+ IFace.forceTextCursor();
RegisterForRedraw ();
}
}
else if (!selectionStart.HasValue)
selectionStart = CurrentLoc;
CurrentLoc = hoverLoc;
- IFace.forceTextCursor = true;
+ IFace.forceTextCursor();
RegisterForRedraw ();
e.Handled = true;
}
return;
}
autoAdjustScroll = true;
- IFace.forceTextCursor = true;
+ IFace.forceTextCursor();
e.Handled = true;
/*} finally {
document.ExitReadLock ();
CurrentLoc = document.GetLocation (change.Start + change.ChangedText.Length);
textMeasureIsUpToDate = false;
- IFace.forceTextCursor = true;
+ IFace.forceTextCursor();
autoAdjustScroll = true;
RegisterForGraphicUpdate ();
using Drawing2D;
using System.Threading.Tasks;
using System.Linq;
+using System.Collections.Generic;
+using CrowEditBase;
+using System.Diagnostics;
namespace Crow
{
Custom1 = 0x0040,
Custom2 = 0x0080,
Custom3 = 0x0100,
+ code = 0x1000,
+ crowEdit = 0x2000,
+ Plugin = 0x4000,
+
+
Custom = Custom1 | Custom2 | Custom3,
- all = Message | WarnErr | Custom | Debug,
+ all = 0xffff
}
public class LogEntry {
public LogType Type;
}
public class LogViewerWidget : ScrollingObject
{
- ObservableList<LogEntry> lines;
- LogEntry[] filteredLines;
+ LogItem logger;
+ IEnumerable<LogEntry> filteredLines;
object filteredLinesMutex = new object ();
+ bool updateFilteredLinesRequest = true;
bool scrollOnOutput, caseSensitiveSearch, allWordSearch;
int visibleLines = 1;
FontExtents fe;
NotifyValueChanged ("ScrollOnOutput", scrollOnOutput);
}
}
+ public LogItem Logger {
+ get => logger;
+ set {
+ if (logger == value)
+ return;
+ if (logger != null) {
+ lock(logger.LogMutext) {
+ logger.log.ListAdd -= Lines_ListAdd;
+ logger.log.ListRemove -= Lines_ListRemove;
+ logger.log.ListClear -= Lines_ListClear;
+ }
+ }
+ logger = value;
+ if (logger != null) {
+ lock(logger.LogMutext) {
+ logger.log.ListAdd += Lines_ListAdd;
+ logger.log.ListRemove += Lines_ListRemove;
+ logger.log.ListClear += Lines_ListClear;
+ }
+ updateFilteredLinesRequest = true;
+ }
+ NotifyValueChanged("Logger", logger);
+ if (IsVisible)
+ RegisterForRedraw();
+ }
+ }
[DefaultValue(LogType.all)]
public LogType Filter {
get => filter;
RegisterForRedraw ();
}
}
- bool updateFilteredLinesRequest = true;
- void updateFilteredLines () {
- if (Lines != null) {
- lock (filteredLinesMutex)
- lock (lines)
- filteredLines = Lines.Where (l=>((int)l.Type & (int)filter) > 0).ToArray();
- MaxScrollY = filteredLines.Length - visibleLines;
- if (scrollOnOutput)
- ScrollY = MaxScrollY;
- }
- updateFilteredLinesRequest = false;
- }
- public virtual ObservableList<LogEntry> Lines {
- get => lines;
- set {
- if (lines == value)
- return;
- if (lines != null) {
- lines.ListAdd -= Lines_ListAdd;
- lines.ListRemove -= Lines_ListRemove;
- lines.ListClear -= Lines_ListClear;
- }
- lines = value;
- if (lines != null) {
- lines.ListAdd += Lines_ListAdd;
- lines.ListRemove += Lines_ListRemove;
- lines.ListClear += Lines_ListClear;
- updateFilteredLinesRequest = true;
- }
- NotifyValueChanged ("Lines", lines);
- RegisterForGraphicUpdate ();
- }
- }
public int CurrentEntryIndex {
get => curEntryIdx;
set {
RegisterForRedraw();
}
}
+
+ void updateFilteredLines () {
+ if (logger != null) {
+ lock (filteredLinesMutex) {
+ //Console.WriteLine("updatefilteredlines");
+ lock (logger.LogMutext)
+ filteredLines = logger.log.Where (l=>((int)l.Type & (int)filter) > 0);
+ MaxScrollY = filteredLines == null ? 0 : filteredLines.Count() - visibleLines;
+ NotifyValueChanged ("ChildHeightRatio", Math.Min (1.0, (double)visibleLines / filteredLines.Count()));
+ }
+ if (scrollOnOutput)
+ ScrollY = MaxScrollY;
+ }
+ updateFilteredLinesRequest = false;
+ }
+ void updateHoverEntryIdx (Point mpos) {
+ PointD mouseLocalPos = ScreenPointToLocal (mpos);
+ lock (filteredLinesMutex) {
+ if (filteredLines == null) {
+ hoverEntryIdx = -1;
+ return;
+ }
+ hoverEntryIdx = ScrollY + (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height)), filteredLines.Count() - 1);
+ }
+ RegisterForRedraw ();
+ }
+
+
+
+ #region Searching
[DefaultValue (true)]
public virtual bool CaseSensitiveSearch {
get { return caseSensitiveSearch; }
void performSearch (string str, bool next = false, bool backward = false) {
if (string.IsNullOrEmpty (str) || filteredLines == null)
return;
- LogEntry[] entries = filteredLines.ToArray ();
+ LogEntry[] entries;
+ lock(filteredLinesMutex)
+ entries = filteredLines.ToArray ();
if (entries.Length == 0) {
CurrentEntryIndex = -1;
return;
else
performSearchForward (entries, str, next);
}
-
+ #endregion
void Lines_ListAdd (object sender, ListChangedEventArg e)
{
updateFilteredLinesRequest = true;
- RegisterForRedraw();
- // try
- // {
- //updateFilteredLines();
-
- // }
- // catch (System.Exception ex)
- // {
- // Console.WriteLine ($"list add valueChange handler bug:{ex}");
- // }
+ if (IsVisible)
+ RegisterForRedraw();
}
-
void Lines_ListRemove (object sender, ListChangedEventArg e)
{
- /*updateFilteredLines();
- MaxScrollY = filteredLines.Length - visibleLines;*/
updateFilteredLinesRequest = true;
RegisterForRedraw ();
}
RegisterForRedraw ();
}
+ public Stopwatch perf = new Stopwatch ();
+ #region widget overrides
public override void OnLayoutChanges (LayoutingType layoutType)
{
base.OnLayoutChanges (layoutType);
gr.SetFontSize (Font.Size);
fe = gr.FontExtents;
}
+
+ visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / fe.Height);
+
if (updateFilteredLinesRequest)
updateFilteredLines ();
- visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / fe.Height);
- MaxScrollY = filteredLines == null ? 0 : filteredLines.Length - visibleLines;
+ else {
+ int count = 0;
+ lock (filteredLinesMutex)
+ count = filteredLines.Count();
+ MaxScrollY = filteredLines == null ? 0 : count - visibleLines;
+ NotifyValueChanged ("ChildHeightRatio", Math.Min (1.0, (double)visibleLines / count));
+ }
}
}
protected override void onDraw (IContext gr)
Rectangle r = ClientRectangle;
-
double y = ClientRectangle.Y;
double x = ClientRectangle.X - ScrollX;
+ IEnumerable<LogEntry> entries;
lock (filteredLinesMutex) {
- for (int i = 0; i < visibleLines; i++) {
- int idx = i + ScrollY;
- if (idx >= filteredLines.Length)
- break;
- LogEntry le = filteredLines[idx];
+ entries = filteredLines.Skip(ScrollY).Take(visibleLines);
+ }
- if (idx == curEntryIdx) {
- gr.Rectangle (x, y, r.Width, fe.Height);
- gr.SetSource (Color.Parse ("#5555ff55"));
- gr.Fill ();
- } else if (idx == hoverEntryIdx) {
- gr.Rectangle (x, y, r.Width, fe.Height);
- gr.SetSource (Color.Parse ("#8B451355"));
- gr.Fill ();
- }
+ //perf.Restart();
+
+ for (int i = 0; i < entries.Count(); i++) {
+ int idx = i + ScrollY;
+ LogEntry le = entries.ElementAt(i);
+ if (idx == curEntryIdx) {
+ gr.Rectangle (x, y, r.Width, fe.Height);
+ gr.SetSource (Color.Parse ("#5555ff55"));
+ gr.Fill ();
+ } else if (idx == hoverEntryIdx) {
+ gr.Rectangle (x, y, r.Width, fe.Height);
+ gr.SetSource (Color.Parse ("#8B451355"));
+ gr.Fill ();
+ }
+ if (!string.IsNullOrEmpty(le.msg)) {
switch (le.Type) {
case LogType.Low:
gr.SetSource (Colors.DimGrey);
case LogType.Custom3:
gr.SetSource (Colors.LightPink);
break;
+ default:
+ gr.SetSource (Colors.Grey);
+ break;
}
gr.MoveTo (x, y + fe.Ascent);
- gr.ShowText (le.msg);
- y += fe.Height;
+ ReadOnlySpan<char> tmp = le.msg.AsSpan(0, Math.Min (400, le.msg.Length));
+ gr.ShowText (tmp);
}
+ y += fe.Height;
}
+ /*perf.Stop();
+ Console.WriteLine($"log onDraw: {visibleLines} lines in {perf.ElapsedMilliseconds} ms");*/
+
}
+
public override void onMouseLeave(object sender, MouseMoveEventArgs e)
{
hoverEntryIdx = -1;
base.onMouseWheel(sender, e);
updateHoverEntryIdx (IFace.MousePosition);
}
- void updateHoverEntryIdx (Point mpos) {
- PointD mouseLocalPos = ScreenPointToLocal (mpos);
- lock (filteredLinesMutex) {
- if (filteredLines == null) {
- hoverEntryIdx = -1;
- return;
+ protected override void Dispose(bool disposing)
+ {
+ if (logger != null) {
+ lock(logger.LogMutext) {
+ logger.log.ListAdd -= Lines_ListAdd;
+ logger.log.ListRemove -= Lines_ListRemove;
+ logger.log.ListClear -= Lines_ListClear;
}
- hoverEntryIdx = ScrollY + (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / fe.Height)), filteredLines.Length - 1);
- }
- RegisterForRedraw ();
- }
- }
+ }
+ base.Dispose(disposing);
+ }
+ #endregion
+ }
}
--- /dev/null
+// Copyright (c) 2021-2025 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Crow;
+using CrowEditBase;
+using Drawing2D;
+using static CrowEditBase.CrowEditBase;
+
+namespace CrowEditBase
+{
+ public class LogItem : CrowEditComponent {
+ int selectedIndex = -1;
+ bool isOpened = false;
+ public Command CMDReset, CMDCopy;
+ public CommandGroup Commands => new CommandGroup (CMDCopy, CMDReset);
+
+ public int SelectedIndex {
+ get => selectedIndex;
+ set {
+ if (selectedIndex == value)
+ return;
+ selectedIndex = value;
+ NotifyValueChanged(selectedIndex);
+ CMDCopy.CanExecute = !(value < 0);
+ }
+ }
+ public bool IsOpened {
+ get => isOpened;
+ set {
+ if (isOpened == value)
+ return;
+ isOpened = value;
+ NotifyValueChanged(isOpened);
+ lock (LogMutext) {
+ if (isOpened) {
+ App.OpenLog(this);
+ } else
+ App.CloseLog(this);
+ }
+ IsSelected = value;
+ }
+ }
+
+ public string Name;
+ public ObservableList<LogEntry> log;
+
+ public object LogMutext = new object();
+ public LogItem(string name) {
+ Name = name;
+ log = new ObservableList<LogEntry>();
+ CMDReset = new ActionCommand ("Clear", ResetLog);
+ CMDCopy = new ActionCommand ("Copy message", CopyMessage);
+ }
+
+
+ public void Add(LogType type, string message) {
+ lock (LogMutext)
+ log.Add (new LogEntry(type, message));
+ }
+ public void ResetLog () {
+ lock (LogMutext)
+ log.Clear ();
+ }
+ public void CopyMessage () {
+ lock (LogMutext) {
+ if (selectedIndex < log.Count && selectedIndex >= 0)
+ App.Clipboard = log.ElementAt(selectedIndex).msg;
+ }
+ }
+ public void OnQueryClose (object sender, EventArgs e){
+ IsOpened = false;
+ }
+ }
+
+}
assembly = loadContext.Assemblies.FirstOrDefault (a=>a.GetName().Name == assemblyName.Name);
return assembly != null;
}
+ public Drawing2D.Color ColorStatus => isLoaded ? Drawing2D.Colors.Green : Drawing2D.Colors.Red;
public virtual bool IsLoaded {
get { return isLoaded; }
set {
isLoaded = value;
NotifyValueChanged (isLoaded);
+ NotifyValueChanged ("ColorStatus", ColorStatus);
+
CMDLoad.CanExecute = !IsLoaded;
CMDReload.CanExecute = CMDUnload.CanExecute = IsLoaded;
CMDLoad, CMDUnload, CMDReload);
protected virtual void initCommands () {
- CMDLoad = new ActionCommand ("Load", Load, "#icons.reply.svg", false);
+ CMDLoad = new ActionCommand ("Load", () => { Load(); }, "#icons.reply.svg", false);
CMDUnload = new ActionCommand ("Unload", Unload, "#icons.share-arrow.svg", false);
CMDReload = new ActionCommand ("Reload", () => { Unload(); Load();}, "#icons.refresh.svg", false);
}
- public void Load () {
+ // return false on type load exception so the plugin load will be retried 1 time
+ public bool Load () {
if (isLoaded)
- return;
+ return true;
if (loadContext == null)
loadContext = new PluginsLoadContext(FullPath);
foreach (string associations in fileAssociations.Split (';')) {
string[] typeExts = associations.Split (':');
Type clientClass = loadContext.MainAssembly.GetType (typeExts[0].Trim());
+ if (clientClass == null) {
+ App.Log(LogType.Plugin | LogType.Warning | LogType.Debug, $"Plugin first load failed: {Name}");
+ return false;
+ }
foreach (string ext in typeExts[1].Split (','))//supported extension comma separated list
App.AddFileAssociation (ext.Trim(), clientClass);
if (typeExts.Length < 3)
}
}
catch (System.Exception ex) {
- Console.WriteLine ($"[Plugin]Error reading 'default.conf' for {FullPath}: {ex.Message}");
+ App.Log (LogType.Error|LogType.Plugin, $"Error reading 'default.conf' for {FullPath}: {ex.Message}");
+ return true;
}
}
}
IsLoaded = true;
+ App.Log(LogType.Normal, $"Plugin loaded: {Name}");
+ return true;
}
public void Unload () {
if (!isLoaded)
App.GetService (serviceClass)?.Stop();
App.RemoveCrowAssembly (loadContext.MainAssembly);
-
+ App.Log(LogType.Plugin | LogType.Normal, $"Plugin unloaded: {Name}");
IsLoaded = false;
}
}
-// Copyright (c) 2021-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+// Copyright (c) 2021-2025 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
}
protected override Assembly Load(AssemblyName assemblyName) {
string assemblyPath = Path.Combine (fullPath, assemblyName.Name + ".dll");
+ //App.Log (LogType.Message, $"[PluginsLoadContext:{Name}] Trying: {assemblyName.ToString()} => {assemblyPath}");
return File.Exists (assemblyPath) ? LoadFromAssemblyPath (assemblyPath) : null;
}
-
}
}
Paused,
Stopped
}
+ LogItem log;
+ protected void Log(LogType type, string message) => log.Add(type, message);
protected Service () {
+ Name = this.GetType().Name;
+ log = CrowEditBase.App.MainLog;
CMDStart = new ActionCommand ("Start", Start, "#icons.play-button.svg", true);
CMDStop = new ActionCommand ("Stop", Stop, "#icons.stop.svg", false);
CMDPause = new ActionCommand ("Pause", Pause, "#icons.pause-symbol.svg", false);
CMDOpenConfig = new ActionCommand ("Service configuration",
() => CrowEditBase.App.LoadWindow (ConfigurationWindowPath, this), "#icons.cogwheel.svg", true);
Commands = new CommandGroup (CMDStart, CMDPause, CMDStop, CMDOpenConfig);
-
- if (CrowEditBase.App.TryGetWindow (ConfigurationWindowPath, out Window win))
- win.DataSource = this;
+ ensureConfigWinDataSource();
+ Log(LogType.Low, $"[{Name}] Service Instanciated");
}
public Command CMDStart, CMDStop, CMDPause, CMDOpenConfig;
public CommandGroup Commands;
CMDStart.CanExecute = !IsRunning;
CMDPause.CanExecute = IsRunning;
CMDStop.CanExecute = IsRunning || CurrentState == Status.Paused;
+ Log(LogType.High, $"[{Name}] Status: {previousState} -> {newState}");
}
-
+ protected void ensureConfigWinDataSource() {
+ if (CrowEditBase.App.TryGetWindow (ConfigurationWindowPath, out Window win))
+ win.DataSource = this;
+ }
+ public readonly string Name;
public abstract void Start ();
public abstract void Stop ();
public abstract void Pause ();
if (HasFocus && IFace.IsDown (MouseButton.Left)) {
CurrentLoc = hoverLoc;
autoAdjustScroll = true;
- IFace.forceTextCursor = true;
+ IFace.forceTextCursor();
RegisterForRedraw ();
}
}
case Key.Enter:
case Key.KeypadEnter:
//doc.updateCurrentTokAndNode (Selection.Start);
- Console.WriteLine ($"*** Current Token: {doc.CurrentToken} Current Node: {doc.CurrentNode}");
+ //Console.WriteLine ($"*** Current Token: {doc.CurrentToken} Current Node: {doc.CurrentNode}");
update (new TextChange (selection.Start, selection.Length, Document.GetLineBreak ()));
autoAdjustScroll = true;
- IFace.forceTextCursor = true;
+ IFace.forceTextCursor();
e.Handled = true;
return;
}
selStart = selectionStart.Value;
selEnd = CurrentLoc.Value;
}
- } else
- IFace.forceTextCursor = true;
+ }
double spacePixelWidth = gr.TextExtents (" ").XAdvance;
int size = buff.Length * 4 + 1;
if (bytes.Length < size)
- bytes = size > 512 ? new byte[size] : stackalloc byte[size];
+ bytes = new byte[size];
int encodedBytes = buff.ToUtf8 (bytes);
RectangleD lineRect = new RectangleD (cb.X, pixY, pixX - cb.X, lineHeight);
if (CurrentNode != null && l >= nodeStart.Value.Line && l <= nodeEnd.Value.Line)
- fillHighlight (gr, l, nodeStart.Value, nodeEnd.Value, lineRect, new Color(0.0,0.1,0.0,0.1));;
+ fillHighlight (gr, l, nodeStart.Value, nodeEnd.Value, lineRect, new Color(0.0,0.1,0.0,0.08));;
#if DEBUG_NODES
if (doc.EditedNode != null && l >= editNodeStart.Value.Line && l <= editNodeEnd.Value.Line)
fillHighlight (gr, l, editNodeStart.Value, editNodeEnd.Value, lineRect, new Color(0,0.5,0,0.2));;
}
//Console.WriteLine ($"{pos}: {suggestionTok.AsString (_text)} {suggestionTok}");
}
+
}
}
\ No newline at end of file
}
origSource = source;
NotifyValueChanged ("IsDirty", IsDirty);
+ CMDSave.CanExecute = IsDirty;
}
protected override void readFromDisk()
{
- protected void saveFileDialog_OkClicked (object sender, EventArgs e)
+ protected override void saveFileDialog_OkClicked (object sender, EventArgs e)
{
FileDialog fd = sender as FileDialog;
}
protected bool disableTextChangedEvent = false;
protected virtual void apply (TextChange change) {
+
Span<char> tmp = stackalloc char[source.Length + (change.ChangedText.Length - change.Length)];
ReadOnlySpan<char> src = source.AsSpan ();
src.Slice (0, change.Start).CopyTo (tmp);
source = tmp.ToString ();
lines.Update (change);
+
+ NotifyValueChanged ("IsDirty", IsDirty);
+ CMDSave.CanExecute = IsDirty;
}
protected void applyTextChange (TextChange change, object triggeringEditor = null) {
editorRWLock.EnterWriteLock ();
-SmallUIFont = "sans, 10";
-SmallFont = "consolas, 10";
+SmallUIFont = "sans, 12";
+SmallFont = "consolas, 12";
InactiveTabBackground = "DarkGrey";
SelectedTabBackground = "Onyx";
InactiveTabForeground = "Grey";
SelectedTabForeground = "White";
-MenuIconSize = "16";
+MenuIconSize = "22";
ControlForeground = "LightGrey";
ControlCaptionHoverColor = "White";
TreeItemBackground = "Transparent";
//TreeItemHighlight = "
+TxtInFileDialog {
+ Margin = "2";
+ Font = "mono, 14";
+}
+
Editor {
Focusable="true";
Height="Stretched";
IcoBut {
Template = "#ui.IcoBut.template";
MinimumSize = "10,10";
- Width = "8";
- Height = "14";
- Background = "White";
+ Width = "32";
+ Height = "32";
}
Spinner {
Template = "#ui.spinner.template";
Template= "#Crow.CheckBox2.template";
Width = "Stretched";
Height = "Fit";
- CornerRadius = "3";
+ CornerRadius = "0";
Background = "${ControlIdle}";
Foreground = "${ControlForeground}";
Checked = "{Background=${ControlHighlight}}";
}
LogViewerWidget {
Background = "0.01,0.01,0.01,1";
-}
\ No newline at end of file
+ MouseWheelSpeed = "2";
+}
<Button MinimumSize = "1,1" Font="${SmallUIFont}" Command="{}" >
<Template>
<Border Style="ButtonBorder" Background="{./Background}" CornerRadius="{../CornerRadius}" Name="Content">
- <Label Font="{./Font}" Name="caption" Margin="1" Foreground="{./Foreground}" Text="{./Caption}"/>
+ <Label Font="{./Font}" Name="caption" Margin="2" Foreground="{./Foreground}" Text="{./Caption}"/>
</Border>
</Template>
</Button>
<Border Name="SizeHandle" BorderWidth="1" Foreground="Black" CornerRadius="{./CornerRadius}"
StickyMouse="8" StickyMouseEnabled="{./IsFloating}" Background="{./Background}">
<VerticalStack Spacing="0" Name="MoveHandle">
- <HorizontalStack Visible="{./IsDockedInStack}" Height="Fit" Margin="1" Background="Jet">
+ <HorizontalStack Visible="{./IsDockedInStack}" Height="Fit" Margin="1" Background="Jet" Width="Stretched">
<Label Text="{./Caption}" TextAlignment="Left" Width="Stretched" Foreground="DimGrey" Font="${SmallUIFont}"/>
<ListBox Style="DockWinTitleBarIconMenu" Data="{./DockCommands}"/>
<ListBox Style="DockWinTitleBarIconMenu" Data="{./Commands}"/>
</HorizontalStack>
- <HorizontalStack Background="vgradient|0:0.5,0.4,0.6,0.5|1:0.2,0.3,0.3,0.7"
+ <HorizontalStack Background="vgradient|0:0.5,0.4,0.6,0.5|1:0.2,0.3,0.3,0.7" Width="Stretched"
Name="hs" Margin="0" Spacing="0" Height="Fit" Visible="{./IsFloating}">
<Widget Width="5"/>
<Image Margin="1" Width="10" Height="10" Path="{./Icon}"/>
BorderWidth="1" BorderStyle="Normal"
MouseDown="{BorderStyle=Sunken}"
MouseUp="{BorderStyle=Normal}">
- <Image Margin="1" Path="#icons.blank-file.svg" />
-</Border>
+ <Image Margin="1" Path="{./Icon}" Tooltip="{./Caption}" />
+</Border>
\ No newline at end of file
MouseEnter="{Background=${ControlHighlight}}"
MouseLeave="{Background=Transparent}">
<Image Style="MenuIcon" Picture="{./Icon}" />
- <Label Text="{./Caption}" Width="Stretched" Height="Stretched" Margin="1"/>
+ <Label Text="{./Caption}" Width="Stretched" Height="Fit" Margin="1"/>
</HorizontalStack>
</Template>
</Button>
<Template>
<HorizontalStack Background="{./Background}" Width="Stretched" Height="Fit" Margin="3">
<Image Style="MenuIcon" Picture="{./Icon}"/>
- <Label Text="{./Caption}" Height="Stretched"/>
+ <Label Text="{./Caption}" Height="Fit"/>
<Label Text="..." Width="Fit"/>
</HorizontalStack>
</Template>
<Template>
<HorizontalStack Background="{./Background}" Width="Stretched" Height="Stretched" Margin="3">
<Image Style="MenuIcon" Picture="{../../../../Icon}"/>
- <Label Text="{./Caption}" Width="Fit" Height="Stretched"/>
+ <Label Text="{./Caption}" Width="Fit" Height="Fit"/>
<Label Text="..."/>
</HorizontalStack>
</Template>
<ListItem IsVisible="{IsSelected}" IsSelected="{²IsSelected}" Selected="{/tb.HasFocus='true'}">
<VerticalStack Spacing="0">
<HorizontalStack Spacing="0" Background="White">
- <SourceEditor Name="tb" Font="consolas, 12" Margin='0' CurrentNode="{CurrentNode}"
+ <SourceEditor Name="tb" Font="mono, 14" Margin='0' CurrentNode="{CurrentNode}"
Document="{}" TextChanged="onTextChanged" />
<ScrollBar Value="{²../tb.ScrollY}"
LargeIncrement="{../tb.PageHeight}" SmallIncrement="1"
<ScrollBar Style="HScrollBar" Value="{²../tb.ScrollX}"
LargeIncrement="{../tb.PageWidth}" SmallIncrement="1"
CursorRatio="{../tb.ChildWidthRatio}" Maximum="{../tb.MaxScrollX}" />
+ <Splitter/>
+ <ListBox Data='{Exceptions}' Height='200' Width='Stretched'/>
<HorizontalStack Height="Fit" Spacing='3'>
<Widget Width="Stretched"/>
+ <Label Text="TokType" Foreground="Grey"/>
+ <Label Text="{CurrentTokenType}" Margin="3"/>
<Label Text="Tok" Foreground="Grey"/>
<Label Text="{CurrentTokenString}" Margin="3"/>
<Label Text="Node" Foreground="Grey"/>
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFrameworks>net5</TargetFrameworks>
+ <TargetFrameworks>net9</TargetFrameworks>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
{
public class CrowService : Service {
public CrowService () : base () {
-
- loadCrowAssemblies ();
-
+ restoreCrowAssemblies ();
initCommands ();
- //resolve other plugins dependencies
- //AssemblyLoadContext.GetLoadContext (Assembly.GetExecutingAssembly ()).Resolving += resolvePluginRefs;
+ crowLoadCtx = new AssemblyLoadContext("CrowDebuggerLoadContext");
- if (CrowEditBase.CrowEditBase.App.TryGetWindow ("#CECrowPlugin.ui.winLogGraph.crow", out Window win))
- win.DataSource = this;
}
- /*Assembly resolvePluginRefs (AssemblyLoadContext ctx, AssemblyName assemblyName)
- => App.TryGetPlugin ("CERoslynPlugin", out Plugin roslynPlugin) ?
- roslynPlugin.Load (assemblyName) : null;*/
-
- /*static IntPtr resolveUnmanaged(Assembly assembly, String libraryName)
- {
-
- switch (libraryName)
- {
- case "glfw3":
- return NativeLibrary.Load("glfw", assembly, null);
- case "rsvg-2.40":
- return NativeLibrary.Load("rsvg-2", assembly, null);
- }
- Console.WriteLine($"[UNRESOLVE] {assembly} {libraryName}");
- return IntPtr.Zero;
- }*/
-
- /*void updateCrowApp () {
- if (App.CurrentProject is CERoslynPlugin.SolutionProject sol) {
- if (sol.StartupProject is CERoslynPlugin.MSBuildProject csprj) {
-
- }
- }else if (App.CurrentProject is CERoslynPlugin.MSBuildProject csprj){
- CERoslynPlugin.MSBuildProject project = App.CurrentProject as CERoslynPlugin.MSBuildProject;
- Console.WriteLine ($"{project.Name}: {project.IsCrowProject}");
-
- }
-
+ public override string ConfigurationWindowPath => "#CECrowPlugin.ui.winConfiguration.crow";
- }*/
#region Commands
public Command CMDStartRecording, CMDStopRecording, CMDRefresh;
public Command CMDGotoParentEvent, CMDEventHistoryForward, CMDEventHistoryBackward;
dlg.DataSource = this;
}
);
-
public ActionCommand CMDViewPreview;
-
void initCommands ()
{
CMDViewPreview = new ActionCommand("Crow Preview", () => App.LoadWindow ("#CECrowPlugin.ui.winCrowPreview.crow", App));
if (CurrentState == Status.Running)
delSetSource (imlSource);
}
+ Project activeSolution;
Exception currentException;
public string ErrorMessage = "";
public bool ServiceIsInError;
Assembly crowAssembly, thisAssembly;
Type dbgIfaceType;
- #region dbgIface delegates
+#region dbgIface delegates
Action<int, int> delResize;
Func<int, int, bool> delMouseMove;
Func<float, bool> delMouseWheelChanged;
FieldInfo fiDbg_IncludedEvents, fiDbg_ConsoleOutput, fiDbgIFace_MaxLayoutingTries, fiDbgIFace_MaxDiscardCount, fiDbgIFace_Terminate;
- #endregion
+#endregion
+#region DebugLog
bool recording, debugLogIsEnabled;
IList<DbgEvtType> recordedEvents = new ObservableList<DbgEvtType>(new DbgEvtType[] {DbgEvtType.Widget} );
DbgEvtType addRecordedEvents = DbgEvtType.None;
- public bool HasVkvgBackend { get; private set; }
- public int RefreshRate {
- get => Configuration.Global.Get<int> ("RefreshRate", 10);
- set {
- if (RefreshRate == value)
- return;
- Configuration.Global.Set ("RefreshRate", value);
- NotifyValueChanged(value);
- }
- }
- public int MaxLayoutingTries {
- get => Configuration.Global.Get<int> ("MaxLayoutingTries", 30);
- set {
- if (MaxLayoutingTries == value)
- return;
- Configuration.Global.Set ("MaxLayoutingTries", value);
- NotifyValueChanged(value);
- fiDbgIFace_MaxLayoutingTries.SetValue (null, value);
- }
- }
- public int MaxDiscardCount {
- get => Configuration.Global.Get<int> ("MaxDiscardCount", 5);
- set {
- if (MaxDiscardCount == value)
- return;
- Configuration.Global.Set ("MaxDiscardCount", value);
- NotifyValueChanged(value);
- fiDbgIFace_MaxDiscardCount.SetValue (null, value);
- }
- }
- public bool PreviewHasError => currentException != null;
- public Exception CurrentException {
- get => currentException;
- private set {
- if (currentException == value)
- return;
- currentException = value;
- NotifyValueChanged (currentException);
- NotifyValueChanged ("PreviewHasError", PreviewHasError);
- }
- }
public bool DebugLogIsEnabled {
get => debugLogIsEnabled;
set {
NotifyValueChanged (value);
}
}
+#endregion
+
+ public bool HasVkvgBackend { get; private set; }
+ public int RefreshRate {
+ get => Configuration.Global.Get<int> ("RefreshRate", 10);
+ set {
+ if (RefreshRate == value)
+ return;
+ Configuration.Global.Set ("RefreshRate", value);
+ NotifyValueChanged(value);
+ }
+ }
+ public int MaxLayoutingTries {
+ get => Configuration.Global.Get<int> ("MaxLayoutingTries", 30);
+ set {
+ if (MaxLayoutingTries == value)
+ return;
+ Configuration.Global.Set ("MaxLayoutingTries", value);
+ NotifyValueChanged(value);
+ fiDbgIFace_MaxLayoutingTries.SetValue (null, value);
+ }
+ }
+ public int MaxDiscardCount {
+ get => Configuration.Global.Get<int> ("MaxDiscardCount", 5);
+ set {
+ if (MaxDiscardCount == value)
+ return;
+ Configuration.Global.Set ("MaxDiscardCount", value);
+ NotifyValueChanged(value);
+ fiDbgIFace_MaxDiscardCount.SetValue (null, value);
+ }
+ }
+ public double ZoomFactor {
+ get => Configuration.Global.Get<Double> ("CrowPreviewZoomFactor", 1.0);
+ set {
+ if (ZoomFactor == value)
+ return;
+ Configuration.Global.Set<Double> ("CrowPreviewZoomFactor", value);
+ NotifyValueChanged (value);
+ if (CurrentState == Status.Running)
+ delSetZoomFactor (value);
+ }
+ }
+ public bool PreviewHasError => currentException != null;
+ public Exception CurrentException {
+ get => currentException;
+ private set {
+ if (currentException == value)
+ return;
+ currentException = value;
+ NotifyValueChanged (currentException);
+ NotifyValueChanged ("PreviewHasError", PreviewHasError);
+ }
+ }
+ public ISurface MainSurface => IsRunning ? delGetMainSurface() : null;
+ public string CrowAssemblyName => IsRunning ? crowAssembly.FullName : null;
+ public void Resize (int width, int height) {
+ if (IsRunning)
+ delResize (width, height);
+ }
+ public void ResetDirtyState () {
+ if (IsRunning)
+ fiDbgIFace_IsDirty.SetValue (dbgIFace, false);
+ }
+ public bool GetDirtyState => IsRunning ? (bool)fiDbgIFace_IsDirty.GetValue (dbgIFace) : false;
void updateCrowDebuggerState (string errorMsg = null) {
ErrorMessage = errorMsg;
ServiceIsInError = errorMsg != null;
NotifyValueChanged ("ServiceErrorMessage", (object)ErrorMessage);
NotifyValueChanged ("ServiceIsInError", ServiceIsInError);
+ NotifyValueChanged ("CrowAssemblyName", (object)CrowAssemblyName);
}
#region DesignInterface callbacks
yield return style.FullPath;
}
}
+ /*foreach (String item in crowAssemblies)
+ {
+ yield return Assembly.LoadFile();
+ }*/
yield return crowAssembly;
}
Stream getStreamFromPath (string path) {
if (CurrentState == Status.Running)
return;
- if (!File.Exists (CrowDbgAssemblyLocation)) {
- DebugLogIsEnabled = false;
- updateCrowDebuggerState($"Crow.dll for debugging file not found");
- return;
- }
- List<string> additionalResolvePath = new List<string>();
+
+ /*List<string> additionalResolvePath = new List<string>();
additionalResolvePath.Add (System.IO.Path.GetDirectoryName(CrowDbgAssemblyLocation));
foreach (string assemblyPath in crowAssemblies)
- additionalResolvePath.Add (System.IO.Path.GetDirectoryName(assemblyPath));
+ additionalResolvePath.Add (System.IO.Path.GetDirectoryName(assemblyPath));*/
//crowLoadCtx?.Unload();
- crowLoadCtx = new AssemblyLoadContext("CrowDebuggerLoadContext");
- crowLoadCtx.Resolving += (context, assemblyName) => {
+
+ /*crowLoadCtx.Resolving += (context, assemblyName) => {
foreach (string path in additionalResolvePath) {
string assemblyPath = System.IO.Path.Combine (path, assemblyName.Name + ".dll");
if (!File.Exists (assemblyPath))
return crowLoadCtx.LoadFromAssemblyPath (assemblyPath);
}
return null;
- };
-
- //using (crowLoadCtx.EnterContextualReflection()) {
- crowAssembly = crowLoadCtx.LoadFromAssemblyPath (CrowDbgAssemblyLocation);
- thisAssembly = crowLoadCtx.LoadFromAssemblyPath (new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath);
-
- foreach (string assemblyPath in crowAssemblies)
- crowLoadCtx.LoadFromAssemblyPath (assemblyPath);
-
- Type debuggerType = crowAssembly.GetType("Crow.DbgLogger");
- DebugLogIsEnabled = (bool)debuggerType.GetField("IsEnabled").GetValue(null);
+ };*/
- dbgIfaceType = thisAssembly.GetType("CECrowPlugin.DebugInterface");
-
- dbgIFace = Activator.CreateInstance (dbgIfaceType, new object[] {CrowEditBase.CrowEditBase.App.WindowHandle});
-
- delResize = (Action<int, int>)Delegate.CreateDelegate(typeof(Action<int, int>),
- dbgIFace, dbgIfaceType.GetMethod("Resize"));
-
- delMouseMove = (Func<int, int, bool>)Delegate.CreateDelegate(typeof(Func<int, int, bool>),
- dbgIFace, dbgIfaceType.GetMethod("OnMouseMove"));
-
- delMouseWheelChanged = (Func<float, bool>)Delegate.CreateDelegate(typeof(Func<float, bool>),
- dbgIFace, dbgIfaceType.GetMethod("OnMouseWheelChanged"));
-
-
- delMouseDown = (Func<MouseButton, bool>)Delegate.CreateDelegate(typeof(Func<MouseButton, bool>),
- dbgIFace, dbgIfaceType.GetMethod("OnMouseButtonDown"));
-
- delMouseUp = (Func<MouseButton, bool>)Delegate.CreateDelegate(typeof(Func<MouseButton, bool>),
- dbgIFace, dbgIfaceType.GetMethod("OnMouseButtonUp"));
-
- delKeyDown = (Func<Key, int, Modifier, bool>)Delegate.CreateDelegate(typeof(Func<Key, int, Modifier, bool>),
- dbgIFace, dbgIfaceType.GetMethod("OnKeyDown", new Type[] { typeof(Key), typeof(int), typeof (Modifier)}));
- delKeyUp = (Func<Key, int, Modifier, bool>)Delegate.CreateDelegate(typeof(Func<Key, int, Modifier, bool>),
- dbgIFace, dbgIfaceType.GetMethod("OnKeyUp", new Type[] { typeof(Key), typeof(int), typeof (Modifier)}));
- delKeyPress = (Func<char, bool>)Delegate.CreateDelegate(typeof(Func<char, bool>),
- dbgIFace, dbgIfaceType.GetMethod("OnKeyPress"));
-
-
- delGetMainSurface = (Func<ISurface>)Delegate.CreateDelegate(typeof(Func<ISurface>),
- dbgIFace, dbgIfaceType.GetProperty("MainSurface").GetGetMethod());
- delSetSource = (Action<string>)Delegate.CreateDelegate(typeof(Action<string>),
- dbgIFace, dbgIfaceType.GetProperty("Source").GetSetMethod());
- delReloadIml = (Action)Delegate.CreateDelegate(typeof(Action), dbgIFace, dbgIfaceType.GetMethod("ReloadIml"));
-
- /*delGetZoomFactor = (Func<double>)Delegate.CreateDelegate(typeof(Func<double>),
- dbgIFace, dbgIfaceType.GetProperty("ZoomFactor").GetGetMethod());
- delSetZoomFactor = (Action<double>)Delegate.CreateDelegate(typeof(Action<double>),
- dbgIFace, dbgIfaceType.GetProperty("ZoomFactor").GetSetMethod());*/
-
- fiDbgIFace_Terminate = dbgIfaceType.GetField("Terminate");
- fiDbgIFace_IsDirty = dbgIfaceType.GetField("IsDirty");
- fiDbgIFace_MaxLayoutingTries = dbgIfaceType.GetField("MaxLayoutingTries", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
- fiDbgIFace_MaxDiscardCount = dbgIfaceType.GetField("MaxDiscardCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
-
- fiDbg_IncludedEvents = debuggerType.GetField("IncludedEvents");
- fiDbg_ConsoleOutput = debuggerType.GetField("ConsoleOutput");
- delResetDebugger = (Action)Delegate.CreateDelegate(typeof(Action), null, debuggerType.GetMethod("Reset"));
- /*delSaveDebugLog = (Action<object, string>)Delegate.CreateDelegate(typeof(Action<object, string>),
- null, debuggerType.GetMethod("Save", new Type[] {dbgIfaceType, typeof(string)}));*/
- //HasVkvgBackend = (bool)dbgIfaceType.GetField ("HaveVkvgBackend", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy).GetValue (null);
- dbgIfaceType.GetMethod("RegisterDebugInterfaceCallback").Invoke (dbgIFace, new object[] {this} );
- dbgIfaceType.GetMethod("Run").Invoke (dbgIFace, null);
-
- fiDbgIFace_MaxLayoutingTries.SetValue (null, MaxLayoutingTries);
- fiDbgIFace_MaxDiscardCount.SetValue (null, MaxDiscardCount);
+ if (!updateCrowDesignAssemblyLocation())
+ return;
- CurrentState = Status.Running;
+ CurrentState = Status.Running;
- App.ViewCommands.Add (CMDViewPreview);
+ App.ViewCommands.Add (CMDViewPreview);
- updateCrowDebuggerState();
+ updateCrowDebuggerState();
//delSetZoomFactor (ZoomFactor);
}
{
CurrentState = Status.Paused;
}
- public override string ConfigurationWindowPath => "#CECrowPlugin.ui.winConfiguration.crow";
- Project activeSolution;
+ protected override void onStateChange(Status previousState, Status newState)
+ {
+ base.onStateChange(previousState, newState);
+ CMDRefresh.CanExecute = IsRunning;
+ }
+
public Project ActiveSolution {
get => activeSolution;
set {
}
}
+ bool updateCrowDesignAssemblyLocation() {
+ if (!File.Exists (CrowDbgAssemblyLocation)) {
+ DebugLogIsEnabled = false;
+ updateCrowDebuggerState($"Crow.dll for debugging file not found");
+ return false;
+ }
+
+ if (crowAssembly != null)
+ crowLoadCtx.Unload();
+
+ crowAssembly = crowLoadCtx.LoadFromAssemblyPath (CrowDbgAssemblyLocation);
+
+ Type debuggerType = crowAssembly.GetType("Crow.DbgLogger");
+ DebugLogIsEnabled = (bool)debuggerType.GetField("IsEnabled").GetValue(null);
+
+ thisAssembly = crowLoadCtx.LoadFromAssemblyPath (Assembly.GetExecutingAssembly().Location);
+
+ foreach (string assemblyPath in crowAssemblies) {
+ if (File.Exists(assemblyPath)) {
+ crowLoadCtx.LoadFromAssemblyPath (assemblyPath);
+ } else {
+ Log(LogType.Error, $"[{Name}] crow assembly not found: {assemblyPath}");
+ }
+ }
+
+ dbgIfaceType = thisAssembly.GetType("CECrowPlugin.DebugInterface");
+
+ dbgIFace = Activator.CreateInstance (dbgIfaceType, new object[] {CrowEditBase.CrowEditBase.App.WindowHandle});
+
+ delResize = (Action<int, int>)Delegate.CreateDelegate(typeof(Action<int, int>),
+ dbgIFace, dbgIfaceType.GetMethod("Resize"));
+
+ delMouseMove = (Func<int, int, bool>)Delegate.CreateDelegate(typeof(Func<int, int, bool>),
+ dbgIFace, dbgIfaceType.GetMethod("OnMouseMove"));
+
+ delMouseWheelChanged = (Func<float, bool>)Delegate.CreateDelegate(typeof(Func<float, bool>),
+ dbgIFace, dbgIfaceType.GetMethod("OnMouseWheelChanged"));
+
+
+ delMouseDown = (Func<MouseButton, bool>)Delegate.CreateDelegate(typeof(Func<MouseButton, bool>),
+ dbgIFace, dbgIfaceType.GetMethod("OnMouseButtonDown"));
+
+ delMouseUp = (Func<MouseButton, bool>)Delegate.CreateDelegate(typeof(Func<MouseButton, bool>),
+ dbgIFace, dbgIfaceType.GetMethod("OnMouseButtonUp"));
+
+ delKeyDown = (Func<Key, int, Modifier, bool>)Delegate.CreateDelegate(typeof(Func<Key, int, Modifier, bool>),
+ dbgIFace, dbgIfaceType.GetMethod("OnKeyDown", new Type[] { typeof(Key), typeof(int), typeof (Modifier)}));
+ delKeyUp = (Func<Key, int, Modifier, bool>)Delegate.CreateDelegate(typeof(Func<Key, int, Modifier, bool>),
+ dbgIFace, dbgIfaceType.GetMethod("OnKeyUp", new Type[] { typeof(Key), typeof(int), typeof (Modifier)}));
+ delKeyPress = (Func<char, bool>)Delegate.CreateDelegate(typeof(Func<char, bool>),
+ dbgIFace, dbgIfaceType.GetMethod("OnKeyPress"));
+
+
+ delGetMainSurface = (Func<ISurface>)Delegate.CreateDelegate(typeof(Func<ISurface>),
+ dbgIFace, dbgIfaceType.GetProperty("MainSurface").GetGetMethod());
+ delSetSource = (Action<string>)Delegate.CreateDelegate(typeof(Action<string>),
+ dbgIFace, dbgIfaceType.GetProperty("Source").GetSetMethod());
+ delReloadIml = (Action)Delegate.CreateDelegate(typeof(Action), dbgIFace, dbgIfaceType.GetMethod("ReloadIml"));
+
+ /*delGetZoomFactor = (Func<double>)Delegate.CreateDelegate(typeof(Func<double>),
+ dbgIFace, dbgIfaceType.GetProperty("ZoomFactor").GetGetMethod());
+ delSetZoomFactor = (Action<double>)Delegate.CreateDelegate(typeof(Action<double>),
+ dbgIFace, dbgIfaceType.GetProperty("ZoomFactor").GetSetMethod());*/
+
+ fiDbgIFace_Terminate = dbgIfaceType.GetField("Terminate");
+ fiDbgIFace_IsDirty = dbgIfaceType.GetField("IsDirty");
+ fiDbgIFace_MaxLayoutingTries = dbgIfaceType.GetField("MaxLayoutingTries", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
+ fiDbgIFace_MaxDiscardCount = dbgIfaceType.GetField("MaxDiscardCount", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
+
+ fiDbg_IncludedEvents = debuggerType.GetField("IncludedEvents");
+ fiDbg_ConsoleOutput = debuggerType.GetField("ConsoleOutput");
+ delResetDebugger = (Action)Delegate.CreateDelegate(typeof(Action), null, debuggerType.GetMethod("Reset"));
+ /*delSaveDebugLog = (Action<object, string>)Delegate.CreateDelegate(typeof(Action<object, string>),
+ null, debuggerType.GetMethod("Save", new Type[] {dbgIfaceType, typeof(string)}));*/
+ //HasVkvgBackend = (bool)dbgIfaceType.GetField ("HaveVkvgBackend", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy).GetValue (null);
+ dbgIfaceType.GetMethod("RegisterDebugInterfaceCallback").Invoke (dbgIFace, new object[] {this} );
+ dbgIfaceType.GetMethod("Run").Invoke (dbgIFace, null);
+
+ fiDbgIFace_MaxLayoutingTries.SetValue (null, MaxLayoutingTries);
+ fiDbgIFace_MaxDiscardCount.SetValue (null, MaxDiscardCount);
+
+ return true;
+ }
+
public string CrowDbgAssemblyLocation {
get => Configuration.Global.Get<string> ("CrowDbgAssemblyLocation", defaultCrowAssemblyLocation);
set {
NotifyValueChanged(value);
}
}
- public double ZoomFactor {
- get => Configuration.Global.Get<Double> ("CrowPreviewZoomFactor", 1.0);
- set {
- if (ZoomFactor == value)
- return;
- Configuration.Global.Set<Double> ("CrowPreviewZoomFactor", value);
- NotifyValueChanged (value);
- if (CurrentState == Status.Running)
- delSetZoomFactor (value);
- }
- }
//assemblies with crow resources in order of loading
IList<string> crowAssemblies = new ObservableList<string> ();
public IList<string> CrowAssemblies => crowAssemblies;
else
Configuration.Global.Set ("CrowAssemblies", "");
}
- void loadCrowAssemblies () {
+ void restoreCrowAssemblies () {
crowAssemblies.Clear ();
if (!Configuration.Global.TryGet<string> ("CrowAssemblies", out string assemblies))
return;
crowAssemblies.Add (a);
}
- protected override void onStateChange(Status previousState, Status newState)
- {
- base.onStateChange(previousState, newState);
- CMDRefresh.CanExecute = IsRunning;
- }
#region Mouse & Keyboard
Point mouseScreenPos;//absolute on screen position.
}
catch (System.Exception ex)
{
- Console.WriteLine($"[Error][DebugIFace key down]{ex}");
+ Log(LogType.Error, $"[Error][DebugIFace key down]{ex}");
}
}
}
}
catch (System.Exception ex)
{
- Console.WriteLine($"[Error][DebugIFace key up]{ex}");
+ Log(LogType.Error, $"[Error][DebugIFace key up]{ex}");
}
}
}
}
catch (System.Exception ex)
{
- Console.WriteLine($"[Error][DebugIFace key press]{ex}");
+ Log(LogType.Error, $"[Error][DebugIFace key press]{ex}");
}
}
}
}
catch (System.Exception ex)
{
- Console.WriteLine($"[Error][DebugIFace mouse move]{ex}");
+ Log(LogType.Error, $"[Error][DebugIFace mouse move]{ex}");
}
}
}
}
catch (System.Exception ex)
{
- Console.WriteLine($"[Error][DebugIFace mouse down]{ex}");
+ Log(LogType.Error, $"[Error][DebugIFace mouse down]{ex}");
}
}
}
}
catch (System.Exception ex)
{
- Console.WriteLine($"[Error][DebugIFace mouse up]{ex}");
+ Log(LogType.Error, $"[Error][DebugIFace mouse up]{ex}");
}
}
}
}
catch (System.Exception ex)
{
- Console.WriteLine($"[Error][DebugIFace mouse wheel change]{ex}");
+ Log(LogType.Error, $"[Error][DebugIFace mouse wheel change]{ex}");
}
}
}
#endregion
- public ISurface MainSurface => IsRunning ? delGetMainSurface() : null;
- public void Resize (int width, int height) {
- if (IsRunning)
- delResize (width, height);
- }
- public void ResetDirtyState () {
- if (IsRunning)
- fiDbgIFace_IsDirty.SetValue (dbgIFace, false);
- }
- public bool GetDirtyState => IsRunning ? (bool)fiDbgIFace_IsDirty.GetValue (dbgIFace) : false;
-
#region Debug log
IList<DbgEvent> events;
IList<DbgWidgetRecord> widgets;
}
string ticksToMS(long ticks) => Math.Round ((double)ticks / Stopwatch.Frequency * 1000.0, 2).ToString();
- public override void Paint (IContext ctx)
+ public override bool Paint (IContext ctx)
{
base.Paint (ctx);
if (selStart < 0 || selEnd < 0) {
ctx.Operator = Operator.Over;
- return;
+ return true;
}
double selStartX = (double)(selStart - ScrollX - minTicks) * xScale + leftMargin + cb.Left;
double selEndX = (double)(selEnd - ScrollX - minTicks) * xScale + leftMargin + cb.Left;
ctx.SetSource (Colors.Black);
ctx.ShowText (str);
-
-
+ return true;
}
public override void OnLayoutChanges (LayoutingType layoutType)
{
}
protected override void initBackend()
{
- if (!tryFindBackendType (out Type backendType))
+ if (!tryFindBackend (out Type backendType))
throw new Exception ("No backend found.");
backend = (CrowBackend)Activator.CreateInstance (backendType, new object[] {clientRectangle.Width, clientRectangle.Height});
//hWin = backend.hWin;
public override void Run()
{
initBackend ();
-
+ Init();
Thread t = new Thread (interfaceThread) {
IsBackground = true
};
t.Start ();
-
- Init();
-
}
public bool Terminate;
string source;
protected override void onDraw(IContext gr)
{
- Console.WriteLine("onDraw");
+ //crowIFaceService.Log(LogType.Error, "onDraw");
gr.SetSource(Colors.RoyalBlue);
gr.Paint();
}
public override void onMouseUp(object sender, MouseButtonEventArgs e) => crowIFaceService?.onMouseUp(e);
public override void onMouseWheel(object sender, MouseWheelEventArgs e) => crowIFaceService?.onMouseWheel(e);
- public override void Paint(IContext ctx)
+ public override bool Paint(IContext ctx)
{
- base.Paint(ctx);
+ return base.Paint(ctx);
}
protected override void RecreateCache()
{
}*/
}
protected override Tokenizer CreateTokenizer() => new ImlTokenizer ();
+ protected override SyntaxAnalyser CreateSyntaxAnalyser() => new ImlSyntaxAnalyser (this);
+ public override string GetTokenTypeString (TokenType tokenType) => ((ImlTokenType)tokenType).ToString();
string[] allWidgetNames = typeof (Widget).Assembly.GetExportedTypes ().Where(t=>typeof(Widget).IsAssignableFrom (t))
.Select (s => s.Name).ToArray ();
if (sugs != null)
return sugs;
-#if DEBUG
- Console.WriteLine ($"Current Token: {CurrentTokenString} Current Node: {CurrentNode}");
-#endif
-
if (currentToken.GetTokenType() == XmlTokenType.ElementOpen)
return new List<string> (allWidgetNames);
if (currentToken.GetTokenType() == XmlTokenType.ElementName)
public override Color GetColorForToken(TokenType tokType)
{
+ switch ((ImlTokenType)tokType) {
+ case ImlTokenType.BindingOpen:
+ case ImlTokenType.BindingClose:
+ return Colors.DarkGreen;
+ case ImlTokenType.BindingName: return Colors.RoyalBlue;
+ case ImlTokenType.BindingDot:
+ case ImlTokenType.BindingDoubleDot:
+ case ImlTokenType.BindingLevel:
+ return Colors.MediumVioletRed;
+ case ImlTokenType.ConstantName:
+ case ImlTokenType.ConstantRefOpen:
+ case ImlTokenType.ConstantRefClose:
+ return Colors.Brown;
+ }
return base.GetColorForToken (tokType);
}
}
ElementName = 0x0201,
AttributeName = 0x0202,
PI_Target = 0x0203,
+ ConstantName = 0x0204,
Punctuation = 0x0400,
PI_Start = 0x0401,// '<?'
PI_End = 0x0402,// '?>'
BindingOpen = 0xA401,// '{'
BindingClose = 0xA402,// '}'
ConstantRefOpen = 0x2403,// '${'
+ ConstantRefClose = 0x2404,// '}'
BindingLevel = 0xA404,// '/'
BindingDot = 0xA405,// '.'
BindingDoubleDot = 0xA406,// '..'
+ TwoWayBinding = 0xA407,// ²
BindingName = 0xA203,// 'Identifier in binding expression'
BindingExpression = 0xA001,// 'unparsed binding expression
}
using System.Collections.Generic;
using CrowEditBase;
using CrowEdit.Xml;
+using Crow;
namespace CECrowPlugin
{
enum status {
init,
attribute,
+ BindingAdress,
+ BindingName,
bindingTarget,
+ bindingValue,
bindingSource,
-
+ constantRef,
};
- /*protected override void parseAttributeValue (ref SpanCharReader reader) {
- char q = reader.Read();
- addTok (ref reader, XmlTokenType.AttributeValueOpen);
- status curState = status.init;
+
+ void parseBindingExpression (ref SpanCharReader reader, char q) {
+
+ reader.Advance ();
+ addTok (ref reader, ImlTokenType.BindingOpen);
+
+ if (reader.TryPeek ('²')) {
+ reader.Advance ();
+ addTok (ref reader, ImlTokenType.TwoWayBinding);
+ }
+
+ status curState = status.BindingAdress;
while (!reader.EndOfSpan) {
- if (reader.TryPeak ('{')) {
- curState = status.bindingSource;
+ if (curState == status.BindingAdress) {
+ if (reader.TryPeek ('.')) {
+ reader.Advance();
+ if (reader.TryPeek ('.')) {
+ reader.Advance();
+ addTok (ref reader, ImlTokenType.BindingDoubleDot);
+ } else {
+ addTok (ref reader, ImlTokenType.BindingDot);
+ }
+ continue;
+ }
+ if (reader.TryPeek ('/')) {
+ reader.Advance();
+ addTok (ref reader, ImlTokenType.BindingLevel);
+ continue;
+ }
+ }
+
+ if (reader.TryPeek ('=')) {
+ if (curState == status.BindingName) {
+ addTok (ref reader, ImlTokenType.BindingName);
+ reader.Advance ();
+ addTok (ref reader, ImlTokenType.EqualSign);
+ curState = status.BindingAdress;
+ continue;
+ } else
+ return;
+ }
+
+ if (reader.TryPeek ('$')) {
reader.Advance ();
- addTok (ref reader, ImlTokenType.BindingOpen);
+ if (reader.TryPeek ('{')) {
+ reader.Advance ();
+ addTok (ref reader, ImlTokenType.ConstantRefOpen);
+ curState = status.constantRef;
+ }
continue;
}
- if (reader.TryPeak ('}')) {
- addTok (ref reader, ImlTokenType.BindingExpression);
- reader.Read();
- addTok (ref reader, ImlTokenType.BindingClose);
+ if (reader.TryPeek ('}')) {
+ if (curState == status.BindingName || curState == status.bindingValue) {
+ addTok (ref reader, ImlTokenType.BindingName);
+ reader.Read();
+ addTok (ref reader, ImlTokenType.BindingClose);
+ curState = status.attribute;
+ } else if (curState == status.constantRef) {
+ addTok (ref reader, ImlTokenType.ConstantName);
+ reader.Advance ();
+ addTok (ref reader, ImlTokenType.ConstantRefClose);
+ curState = status.BindingName;
+ continue;
+ }
+ return;
+ }
+ if (reader.Eol() || reader.TryPeek (q)) {
+ return;
+ }
+ if (curState == status.BindingAdress)
+ curState = status.BindingName;
+ reader.Read ();
+ }
+ }
+
+ protected override void parseAttributeValue (ref SpanCharReader reader) {
+ char q = reader.Read();
+ status curState = status.attribute;
+ addTok (ref reader, XmlTokenType.AttributeValueOpen);
+ while (!reader.EndOfSpan) {
+ if (reader.TryPeek ('{')) {
+ parseBindingExpression(ref reader, q);
+ }
+ if (reader.TryPeek ('$')) {
+ reader.Advance ();
+ if (reader.TryPeek ('{')) {
+ reader.Advance ();
+ addTok (ref reader, ImlTokenType.ConstantRefOpen);
+ curState = status.constantRef;
+ }
continue;
}
+ if (reader.TryPeek ('}')) {
+ if (curState == status.constantRef) {
+ addTok (ref reader, ImlTokenType.ConstantName);
+ reader.Advance ();
+ addTok (ref reader, ImlTokenType.ConstantRefClose);
+ curState = status.attribute;
+ continue;
+ }
+ }
+
if (reader.Eol()) {
addTok (ref reader, XmlTokenType.AttributeValue);
reader.ReadEol();
addTok (ref reader, XmlTokenType.LineBreak);
continue;
}
- if (reader.TryPeak (q)) {
+ if (reader.TryPeek (q)) {
addTok (ref reader, XmlTokenType.AttributeValue);
reader.Advance ();
addTok (ref reader, XmlTokenType.AttributeValueClose);
return;
- } else
- reader.Read ();
+ }
+ reader.Read ();
}
- }*/
+ }
}
}
--- /dev/null
+// Copyright (c) 2021-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using CrowEditBase;
+using CrowEdit.Xml;
+
+namespace CECrowPlugin
+{
+ public class ImlSyntaxAnalyser : XmlSyntaxAnalyser {
+ public ImlSyntaxAnalyser (ImlDocument source) : base (source) {
+ this.source = source;
+ }
+
+
+ public override void Process () {
+
+ base.Process();
+
+/*
+ ImlDocument xmlDoc = source as ImlDocument;
+ Exceptions = new List<SyntaxException> ();
+ currentNode = new XMLRootSyntax (xmlDoc);
+ currentLine = 0;
+ Span<Token> toks = source.Tokens;
+ tokIdx = 0;
+
+ while (tokIdx < toks.Length) {
+ Token curTok = toks[tokIdx];
+ if (curTok.Type == TokenType.LineBreak)
+ currentLine++;
+ else if (!curTok.Type.HasFlag (TokenType.Trivia)) {
+ if (currentNode is ElementStartTagSyntax tag) {
+ if (curTok.GetTokenType() == XmlTokenType.AttributeName) {
+ AttributeSyntax attribute = new AttributeSyntax (currentLine, tokIdx);
+ attribute.name = 0;
+ currentNode = currentNode.AddChild (attribute);
+ } else if (curTok.GetTokenType() == XmlTokenType.ElementName)
+ tag.name = tokIdx - tag.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
+ storeCurrentNode ();
+ currentNode.RemoveChild (tag);
+ currentNode = currentNode.AddChild (new ElementSyntax (tag));
+ } else if (curTok.GetTokenType() == XmlTokenType.EmptyElementClosing) {
+ storeCurrentNode ();
+ currentNode.RemoveChild (tag);
+ currentNode = currentNode.AddChild (new EmptyElementSyntax (tag));
+ setCurrentNodeEndLine (currentLine);
+ currentNode = currentNode.Parent;
+ } else {
+ Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
+ storeCurrentNode (-1);
+ continue;
+ }
+ } else if (currentNode is ElementSyntax elt) {
+ if (curTok.GetTokenType() == XmlTokenType.ElementOpen)
+ currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, tokIdx));
+ else if (curTok.GetTokenType() == XmlTokenType.EndElementOpen) {
+ elt.EndTag = new ElementEndTagSyntax (currentLine, tokIdx);
+ currentNode = elt.AddChild (elt.EndTag);
+ }
+ } else if (currentNode is AttributeSyntax attrib) {
+ if (curTok.GetTokenType() == XmlTokenType.EqualSign)
+ if (attrib.equal.HasValue)
+ Exceptions.Add (new SyntaxException ("Extra equal sign in attribute syntax", curTok));
+ else
+ attrib.equal = tokIdx - attrib.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.AttributeValueOpen)
+ attrib.valueOpen = tokIdx - attrib.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.AttributeValue)
+ attrib.valueTok = tokIdx - attrib.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.AttributeValueClose) {
+ attrib.valueClose = tokIdx - attrib.TokenIndexBase;
+ storeCurrentNode ();
+ } else {
+ Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
+ storeCurrentNode (-1);
+ continue;
+ }
+ } else if (currentNode is ElementEndTagSyntax eltEndTag) {
+ if (curTok.GetTokenType() == XmlTokenType.ElementName)
+ eltEndTag.name = tokIdx - eltEndTag.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
+ //go up 2 times
+ storeCurrentNode (); storeCurrentNode ();
+ } else {
+ Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
+ storeCurrentNode (-1);
+ storeCurrentNode (-1);
+ continue;
+ }
+ } else if (currentNode is XMLRootSyntax) {
+ switch (curTok.GetTokenType()) {
+ case XmlTokenType.ElementOpen:
+ currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, tokIdx));
+ break;
+ case XmlTokenType.PI_Start:
+ currentNode = currentNode.AddChild (new ProcessingInstructionSyntax (currentLine, tokIdx));
+ break;
+ default:
+ Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
+ break;
+ }
+ } else if (currentNode is ProcessingInstructionSyntax pi) {
+ if (curTok.GetTokenType() == XmlTokenType.PI_Target)
+ pi.name = tokIdx - pi.TokenIndexBase;
+ else if (curTok.GetTokenType() == XmlTokenType.PI_End) {
+ storeCurrentNode ();
+ } else if (curTok.GetTokenType() == XmlTokenType.AttributeName) {
+ AttributeSyntax attribute = new AttributeSyntax (currentLine, tokIdx);
+ attribute.name = 0;
+ currentNode = currentNode.AddChild (attribute);
+ } else {
+ Exceptions.Add (new SyntaxException ("Unexpected Token", curTok));
+ storeCurrentNode (-1);
+ continue;
+ }
+ }
+ }
+ tokIdx++;
+ }
+ while (currentNode.Parent != null) {
+ if (!currentNode.LastTokenOffset.HasValue)
+ storeCurrentNode (-1);
+ else
+ currentNode = currentNode.Parent;
+ }
+ setCurrentNodeEndLine (currentLine);
+ */
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System.Linq;
+using Crow.Text;
+using CrowEditBase;
+
+namespace CECrowPlugin
+{
+
+
+
+ public class AttributeSyntax : SyntaxNode {
+ internal int? name, equal, valueOpen, valueClose, valueTok;
+ public string Name => name.HasValue ? Root.GetTokenStringByIndex (TokenIndexBase + name.Value) : null;
+ public string Value => valueTok.HasValue ? Root.GetTokenStringByIndex (TokenIndexBase + valueTok.Value) : null;
+ public Token? ValueToken => valueTok.HasValue ? Root.GetTokenByIndex (TokenIndexBase + valueTok.Value) : null;
+ public AttributeSyntax (int startLine, int tokenBase)
+ : base (startLine, tokenBase) {}
+ public override bool IsComplete => base.IsComplete & name.HasValue & equal.HasValue & valueTok.HasValue & valueOpen.HasValue & valueClose.HasValue;
+ }
+}
\ No newline at end of file
bool readName (ref SpanCharReader reader) {
if (reader.EndOfSpan)
return false;
- char c = reader.Peak;
+ char c = reader.Peek;
if (char.IsLetter(c) || c == '_' ) {
reader.Advance ();
- while (reader.TryPeak (ref c)) {
+ while (reader.TryPeek (ref c)) {
if (!char.IsLetterOrDigit(c)) {
UnicodeCategory uc = Char.GetUnicodeCategory (c);
if (uc != UnicodeCategory.NonSpacingMark &&
if (reader.EndOfSpan)
break;
- switch (reader.Peak) {
+ switch (reader.Peek) {
case '/':
reader.Advance ();
- if (reader.TryPeak ('/')) {
+ if (reader.TryPeek ('/')) {
reader.Advance ();
addTok (ref reader, StyleTokenType.LineCommentStart);
reader.AdvanceUntilEol ();
addTok (ref reader, StyleTokenType.LineComment);
- } else if (reader.TryPeak ('*')) {
+ } else if (reader.TryPeek ('*')) {
reader.Advance ();
addTok (ref reader, StyleTokenType.BlockCommentStart);
while (!reader.EndOfSpan) {
addTok (ref reader, StyleTokenType.LineBreak);
continue;
}
- if (reader.TryPeak ("*/")) {
+ if (reader.TryPeek ("*/")) {
addTok (ref reader, StyleTokenType.BlockComment);
reader.Advance (2);
addTok (ref reader, StyleTokenType.BlockCommentEnd);
addTok (ref reader, StyleTokenType.MemberValueOpen);
while (!reader.EndOfSpan) {
- if (reader.TryPeak ("${")) {
+ if (reader.TryPeek ("${")) {
addTok (ref reader, StyleTokenType.MemberValuePart);
reader.Advance (2);
addTok (ref reader, StyleTokenType.ConstantRefOpen);
while (!reader.EndOfSpan) {
- if (reader.TryPeak ('}')) {
+ if (reader.TryPeek ('}')) {
addTok (ref reader, StyleTokenType.ConstantName);
reader.Read ();
addTok (ref reader, StyleTokenType.ClosingBrace);
reader.Advance ();
}
continue;
- } else if (reader.TryPeak ('\"')) {
+ } else if (reader.TryPeek ('\"')) {
addTok (ref reader, StyleTokenType.MemberValuePart);
reader.Advance ();
addTok (ref reader, StyleTokenType.MemberValueClose);
<?xml version="1.0"?>
-<DockWindow Caption="Crow Preview Configuration" Width="60%" Height="400">
+<DockWindow Caption="Crow Preview Configuration" Width="400" Height="400">
<VerticalStack RootDataLevel="true" Margin="5">
<HorizontalStack Height="Fit" Margin="5">
<Label Text="Crow Service" Width="Stretched"/>
<ItemTemplate Path="#ui.IconCommand.itmp"/>
</ListBox>
</HorizontalStack>
- <HorizontalStack Height="Fit">
- <Label Fit="true" Text="Crow assembly path:"/>
- <TextBox Height="Fit" Text="{²CrowDbgAssemblyLocation}" Margin="2"/>
- <Image Width="30" Height="20" Path="#Crow.Icons.IconAlerte.svg" Visible="{ServiceIsInError}"/>
- <Button Command="{CMDOptions_SelectCrowAssemblyLocation}" MinimumSize="0,0"/>
- </HorizontalStack>
+ <GroupBox Caption="In design Crow Assembly" Height="Fit">
+ <VerticalStack>
+ <HorizontalStack Height="Fit" Spacing="5">
+ <Label Fit="true" Text="Assembly Path:"/>
+ <TextBox Height="Fit" Text="{²CrowDbgAssemblyLocation}" Margin="2"/>
+ <Image Width="30" Height="20" Path="#Crow.Icons.IconAlerte.svg" Visible="{ServiceIsInError}"/>
+ <Button Command="{CMDOptions_SelectCrowAssemblyLocation}" MinimumSize="0,0"/>
+ </HorizontalStack>
+ <HorizontalStack Height="Fit" Spacing="5">
+ <Label Fit="true" Text="Assembly Name:"/>
+ <Label Fit="true" Text="{CrowAssemblyName}"/>
+ </HorizontalStack>
+ </VerticalStack>
+ </GroupBox>
<Label Background="Red" Foreground="White" Margin="5" Width="Stretched" Text="{ServiceErrorMessage}"
IsVisible="{ServiceIsInError}"/>
- <ListBox Style="ScrollingListBox" Data="{CrowAssemblies}"/>
+ <ListBox Style="ScrollingListBox" Data="{CrowAssemblies}" MinimumSize="100,200"/>
<HorizontalStack Height="Fit" Width="Fit" HorizontalAlignment="Right">
- <Button Command="{CMDOptions_AddCrowAssembly}" Fit="true"/>
+ <Button Command="{CMDOptions_AddCrowAssembly}"/>
</HorizontalStack>
<Spinner Caption="Zoom Factor" Value="{²ZoomFactor}" Minimum="0.2" Maximum="4.0" SmallIncrement="0.1" LargeIncrement="0.2"/>
<Spinner Caption="Refresh Rate (ms)" Value="{²RefreshRate}" Maximum="1000"/>
<Button/>
</HorizontalStack>
</VerticalStack>
-
- <!--<HorizontalStack Height="Fit"> BitFieldExcludeMask="255"
- <CheckBox Caption="Recording" IsChecked="{²Recording}" Height="24" Width="30"
- Checked="{sh.Path='A 8,8,7.5,0,6.3 O 0.8,0,0,1 f O 0,0,0,0.5 G'}"
- Unchecked="{sh.Path='R 0.5,0.5,15,15 f O 0,0,0,1 G'}">
- <Template>
- <Border Background="Onyx" Margin="2" CornerRadius="5">
- <Shape Name="sh" Foreground="Grey" Size="16,16" Path="R 0.5,0.5,15,15 f O 0,0,0,1 G"/>
- </Border>
- </Template>
- </CheckBox>
- <Menu Data="{LoggerCommands}" Height="Fit" Width="Stretched">
- <Template>
- <Wrapper Orientation="Vertical" Name="ItemsContainer" Margin="0" Background="{./Background}"/>
- </Template>
- <ItemTemplate>
- <Button Command="{}" Height="Fit" Width="Fit"/>
- </ItemTemplate>
- </Menu>
- </HorizontalStack>-->
</HorizontalStack>
</GroupBox>
</VerticalStack>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFrameworks>net9</TargetFrameworks>
+ <EnableDefaultItems>false</EnableDefaultItems>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="src\**\*.cs" />
+ <EmbeddedResource Include="default.conf" />
+ </ItemGroup>
+</Project>
--- /dev/null
+FileAssociations=CrowEdit.Ebnf.EbnfDocument:.ebnf:#ui.sourceEditor.itmp
--- /dev/null
+// Copyright (c) 2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace CrowEdit.Ebnf
+{
+ public abstract class CharRangeElement {
+ public class SingleChar : CharRangeElement {
+ public int CodePoint;
+ public char AsChar => (char)CodePoint;
+ public SingleChar (char c) {
+ CodePoint = (int)c;
+ }
+ public SingleChar (int c) {
+ CodePoint = c;
+ }
+ public SingleChar (ReadOnlySpan<char> ebnfUcsCodePoint) {
+ CodePoint = int.Parse (ebnfUcsCodePoint.Slice (2), System.Globalization.NumberStyles.HexNumber);
+ }
+ public override string ToString() => $"#x{CodePoint:X}";
+ }
+ public class CharRange : CharRangeElement {
+ public SingleChar RangeStart;
+ public SingleChar RangeEnd;
+
+ public CharRange (SingleChar rangeStart, SingleChar rangeEnd) {
+ RangeStart = rangeStart;
+ RangeEnd = rangeEnd;
+ }
+ public override string ToString() => $"{RangeStart}-{RangeEnd}";
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2025 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using Crow.Text;
+using System.Collections;
+using CrowEditBase;
+using Drawing2D;
+
+namespace CrowEdit.Ebnf
+{
+ public static class Extensions {
+ public static EbnfTokenType GetTokenType (this Token tok) {
+ return (EbnfTokenType)tok.Type;
+ }
+ public static void SetTokenType (this Token tok, EbnfTokenType type) {
+ tok.Type = (TokenType)type;
+ }
+ }
+ public class EbnfDocument : SourceDocument {
+
+ public EbnfDocument (string fullPath, string editorPath) : base (fullPath, editorPath) {
+
+ }
+ protected override Tokenizer CreateTokenizer() => new EbnfTokenizer ();
+ protected override SyntaxAnalyser CreateSyntaxAnalyser() => new EbnfSyntaxAnalyser (this);
+
+ public override IList GetSuggestions (CharLocation loc) {
+ return null;
+ }
+ public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection) {
+ newSelection = null;
+ change = default;
+ return false;
+ }
+
+ public override Color GetColorForToken(TokenType tokType)
+ {
+ EbnfTokenType xmlTokType = (EbnfTokenType)tokType;
+ if (xmlTokType.HasFlag (EbnfTokenType.Punctuation))
+ return Colors.DarkGrey;
+ if (xmlTokType.HasFlag (EbnfTokenType.Trivia))
+ return Colors.DimGrey;
+ return Colors.Black;
+
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Collections.Generic;
+using CrowEditBase;
+
+namespace CrowEdit.Ebnf
+{
+ public class EbnfSyntaxAnalyser : SyntaxAnalyser {
+ public override SyntaxNode Root => currentNode;
+ public EbnfSyntaxAnalyser (EbnfDocument source) : base (source) {
+ this.source = source;
+ }
+ public override void Process()
+ {
+ EbnfDocument doc = source as EbnfDocument;
+ Exceptions = new List<SyntaxException>();
+ currentNode = new EbnfRootSyntax (doc);
+ currentLine = 0;
+ source2 = doc.Source;
+
+ Span<Token> toks = source.Tokens;
+ tokIdx = 0;
+
+ while (tokIdx < toks.Length) {
+ curTok = toks[tokIdx];
+
+ switch (curTok.GetTokenType())
+ {
+ case EbnfTokenType.LineBreak:
+ currentLine++;
+ break;
+ case EbnfTokenType.SymbolName:
+ currentNode = currentNode.AddChild(new ProductionSyntax(0, currentLine, tokIdx));
+ break;
+
+
+ }
+ tokIdx++;
+ }
+
+
+ setCurrentNodeEndLine (currentLine);
+ }
+
+ Token[] tokens;
+ Stack<object> resolveStack;//expression resolutions
+ string source2;
+
+ bool EOF => tokIdx == tokens.Length;
+ bool EndOfExpression =>
+ EOF || tokIdx > tokens.Length - 2 || tokens[tokIdx + 1].GetTokenType() == EbnfTokenType.SymbolAffectation;
+ bool tryRead (out Token tok) {
+ if (EOF) {
+ tok = default;
+ return false;
+ }
+ tok = tokens [tokIdx++];
+ return true;
+ }
+ bool tryPeek (out Token tok) {
+ if (EOF) {
+ tok = default;
+ return false;
+ }
+ tok = tokens [tokIdx];
+ return true;
+ }
+ bool tryRead (out Token tok, EbnfTokenType expectedType) {
+ if (EOF) {
+ tok = default;
+ return false;
+ }
+ tok = tokens [tokIdx++];
+ return tok.GetTokenType() == expectedType;
+ }
+ bool tryPeek (out Token tok, EbnfTokenType expectedType) {
+ if (EOF) {
+ tok = default;
+ return false;
+ }
+ tok = tokens [tokIdx];
+ return tok.GetTokenType() == expectedType;
+ }
+ bool resolvStackPeekIsOpenBracket =>
+ resolveStack.TryPeek (out object elt) && elt is Token tok && tok.GetTokenType() == EbnfTokenType.OpenBracket;
+ bool resolvStackPeekIsSequenceOperator =>
+ resolveStack.TryPeek (out object elt) && elt is Expression;
+
+ Expression resolveStackPopExpression () {
+ if (resolveStack.TryPeek (out object ro)) {
+ if (ro is Expression exp) {
+ resolveStack.Pop ();
+ return exp;
+ } else
+ throw new EbnfParserException ($"resolve: expecting expression, having {ro}");
+ } else
+ throw new EbnfParserException ($"resolve: empty stack");
+ }
+ Expression resolveStackPeekExpression () {
+ if (resolveStack.TryPeek (out object ro)) {
+ if (ro is Expression exp)
+ return exp;
+ else
+ throw new EbnfParserException ($"resolve: expecting expression, having {ro}");
+ } else
+ throw new EbnfParserException ($"resolve: empty stack");
+ }
+ bool resolveStackTryPeek<T> (out T obj) {
+ if (resolveStack.TryPeek (out object ro)) {
+ if (ro is T t) {
+ obj = t;
+ return true;
+ }
+ }
+ obj = default;
+ return false;
+ }
+
+
+ Expression resolve (Expression rightOp = null) {
+ CompoundExpression compExp = default;
+ if (rightOp == null)
+ rightOp = resolveStackPopExpression ();
+
+ if (resolveStack.TryPeek (out object obj)) {
+ if (obj is Token tok) {
+
+ if (tok.GetTokenType() == EbnfTokenType.OpenBracket)
+ return rightOp;
+
+ resolveStack.Pop ();
+ if (tok.GetTokenType() == EbnfTokenType.ChoiceOp)
+ compExp = new CompoundExpression (CompoundExpression.Type.Choice) { SecondOperand = rightOp };
+ else if (tok.GetTokenType() == EbnfTokenType.ExclusionOp)
+ compExp = new CompoundExpression (CompoundExpression.Type.Exclusion) { SecondOperand = rightOp };
+ else
+ throw new EbnfParserException ($"resolve: expecting operator, having {tok.Type}, {tok.AsString (source2)}");
+
+ if (resolveStack.TryPop (out obj) && obj is Expression exp)
+ compExp.FirstOperand = exp;
+ else
+ throw new EbnfParserException ($"resolve: expecting expression, having {obj}");
+ } else if (obj is Expression exp) {
+ resolveStack.Pop ();
+ compExp = new CompoundExpression (CompoundExpression.Type.Sequence) {
+ FirstOperand = exp,
+ SecondOperand = rightOp
+ };
+ } else
+ throw new EbnfParserException ($"resolve: unexpected stack element: {obj}");
+
+ return compExp;
+ }
+ return rightOp;
+ }
+ Token Read () => tokens [tokIdx++];
+ Token Peek => tokens [tokIdx];
+
+ int operatorPrecedance (Token tok) {
+ if (tok.GetTokenType().HasFlag (EbnfTokenType.WhiteSpace))//sequence operator
+ return 3;
+ if (tok.GetTokenType() == EbnfTokenType.ExclusionOp)
+ return 2;
+ if (tok.GetTokenType() == EbnfTokenType.ChoiceOp)
+ return 4;
+ throw new EbnfParserException ($"unknow operator: {tok}");
+ }
+
+ void checkCardinalityAndPushNewExpression (Expression exp) {
+ if (tryPeek (out Token tok, EbnfTokenType.CardinalityOp)) {
+ Read ();
+ switch (tok.AsString (source2)) {
+ case "?":
+ exp.Optional = exp.Single = true;
+ break;
+ case "+":
+ exp.Optional = exp.Single = false;
+ break;
+ case "*":
+ exp.Optional = true;
+ exp.Single = false;
+ break;
+ }
+ }
+ if (resolveStackTryPeek<Expression> (out Expression leftOp)) {//if exp on the stack, the implicit operator is sequence with precedence=3
+ resolveStack.Pop ();
+ if (resolveStackTryPeek<Token> (out tok)) {
+ if (tok.GetTokenType().HasFlag (EbnfTokenType.Operator)) {
+ if (operatorPrecedance (tok) <= 3)
+ resolveStack.Push (resolve (leftOp));
+ else
+ resolveStack.Push (leftOp);
+ } else if (tok.GetTokenType() == EbnfTokenType.OpenBracket)
+ resolveStack.Push (leftOp);
+ } else //so theres an expression on the stack, the operator is sequenceOp (whitespace) with precedence = 3
+ resolveStack.Push (resolve (leftOp));
+ }
+ resolveStack.Push (exp);
+ }
+ void storeSymbol () {
+ Expression rightOp = resolve ();
+ while (resolveStack.Count > 0)
+ rightOp = resolve (rightOp);
+ curSymbol.Expression = rightOp;
+ symbols.Add (curSymbol);
+ curSymbol = null;
+ resolveStack = null;
+ }
+ List<SymbolDecl> symbols;
+ SymbolDecl curSymbol;
+ public SymbolDecl[] GetSymbols () {
+ tokIdx = 0;
+ resolveStack = null;
+
+ symbols = new List<SymbolDecl> (100);
+ curSymbol = null;
+ Token tok = default;
+
+ while (!EOF) {
+ if (Peek.GetTokenType() == EbnfTokenType.TokenSectionStart) {
+ Read ();
+ continue;
+ }
+
+ if (resolveStack == null) {
+ //no current symbol
+ if (Peek.GetTokenType() != EbnfTokenType.SymbolName)
+ throw new EbnfParserException ($"expecing symbol name, having {Peek.GetTokenType()}, {Peek.AsString (source2)}");
+ curSymbol = new SymbolDecl (Read ().AsString (source2));
+ if (!tryRead (out tok, EbnfTokenType.SymbolAffectation))
+ throw new EbnfParserException ($"expecing '::='");
+ resolveStack = new Stack<object> (16);
+ } else if (Peek.GetTokenType() == EbnfTokenType.OpenBracket) {
+ tok = Read ();
+ resolveStack.Push (tok);
+ } else if (Peek.GetTokenType() == EbnfTokenType.ClosingBracket) {
+ tok = Read ();
+ Expression rightOp = resolve ();
+ while (!resolvStackPeekIsOpenBracket)
+ rightOp = resolve (rightOp);
+ if (resolveStack.TryPop (out object obj) && obj is Token tk && tk.GetTokenType() == EbnfTokenType.OpenBracket)
+ checkCardinalityAndPushNewExpression (rightOp);
+ else
+ throw new EbnfParserException ($"expecing open bracket.");
+ } else if (Peek.GetTokenType().HasFlag (EbnfTokenType.Punctuation)) {
+ tok = Read ();
+ Expression te = default;
+ if (tok.GetTokenType() == EbnfTokenType.CharMatchOpen) {
+ bool negative = false;
+ if (tryPeek (out tok, EbnfTokenType.CharMatchNegation)) {
+ Read ();
+ negative = true;
+ }
+ List<CharRangeElement> elts = new List<CharRangeElement> ();
+ CharRangeElement.SingleChar leftOp = null;
+ while (tryRead (out tok)) {
+ if (tok.GetTokenType() == EbnfTokenType.CharMatchClose) {
+ if (leftOp != null)
+ elts.Add (leftOp);
+ if (elts.Count == 0)
+ throw new EbnfParserException ($"empty character range match");
+ te = new CharMatchExpression (negative, elts.ToArray());
+ break;
+ }
+ if (tok.GetTokenType() == EbnfTokenType.CharMatchRangeOperator) {
+ if (leftOp == null) {
+ elts.Add (new CharRangeElement.SingleChar ('-'));
+ continue;
+ }
+ if (tryRead (out tok)) {
+ if (tok.GetTokenType() == EbnfTokenType.CharMatch)
+ elts.Add (new CharRangeElement.CharRange (leftOp,
+ new CharRangeElement.SingleChar(tok.GetChar (source2))));
+ else if (tok.GetTokenType() == EbnfTokenType.CodePointMatch)
+ elts.Add (new CharRangeElement.CharRange (leftOp,
+ new CharRangeElement.SingleChar(tok.AsString (source2))));
+ else
+ throw new EbnfParserException ($"malformed character range match, expecting end range after '-'");
+ leftOp = null;
+ continue;
+ }
+ throw new EbnfParserException ($"malformed character range match");
+
+ } else if (leftOp != null)
+ elts.Add (leftOp);
+
+ if (tok.GetTokenType() == EbnfTokenType.CharMatch)
+ leftOp = new CharRangeElement.SingleChar(tok.GetChar (source2));
+ else if (tok.GetTokenType() == EbnfTokenType.CodePointMatch)
+ leftOp = new CharRangeElement.SingleChar(tok.AsString (source2));
+ else
+ throw new EbnfParserException ($"malformed character range match");
+ }
+ }
+ if (tok.GetTokenType() == EbnfTokenType.StringMatchOpen) {
+ if (tryRead (out tok, EbnfTokenType.StringMatch)) {
+ te = new StringMatch (tok.AsString (source2));
+ if (!tryRead (out tok, EbnfTokenType.StringMatchClose))
+ throw new EbnfParserException ($"malformed string match");
+ } else
+ throw new EbnfParserException ($"malformed string match");
+ }
+ checkCardinalityAndPushNewExpression (te);
+ } else if (Peek.GetTokenType() == EbnfTokenType.CodePointMatch) {
+ tok = Read ();
+ checkCardinalityAndPushNewExpression (
+ new CharMatchExpression (false, new CharRangeElement.SingleChar(tok.AsString (source2))));
+ } else if (Peek.GetTokenType() == EbnfTokenType.SymbolName) {
+ if (EndOfExpression) {
+ storeSymbol ();
+ continue;
+ }
+ tok = Read ();
+ checkCardinalityAndPushNewExpression (new SymbolMatch (tok.AsString (source2)));
+ } else if (Peek.GetTokenType().HasFlag (EbnfTokenType.Operator)) {
+ Token newOp = Read ();
+ if (newOp.GetTokenType() == EbnfTokenType.SymbolAffectation || newOp.GetTokenType() == EbnfTokenType.CardinalityOp)
+ System.Diagnostics.Debugger.Break ();
+
+ if (resolveStackTryPeek<Expression> (out Expression exp)) {
+ if (resolveStack.Count > 1) {
+ resolveStack.Pop ();
+ if (resolveStackTryPeek<Token> (out tok)) {
+ if (tok.GetTokenType().HasFlag (EbnfTokenType.Operator)) {
+ if (operatorPrecedance (tok) <= operatorPrecedance (newOp))
+ resolveStack.Push (resolve (exp));
+ else
+ resolveStack.Push (exp);
+ } else if (tok.GetTokenType() == EbnfTokenType.OpenBracket)
+ resolveStack.Push (exp);
+ } else if (3 <= operatorPrecedance (newOp)) { //so theres an expression on the stack, the operator is sequenceOp (whitespace) with precedence = 3
+ resolveStack.Push (resolve (exp));
+ } else
+ resolveStack.Push (exp);
+ }
+
+ resolveStack.Push (newOp);
+ } else
+ System.Diagnostics.Debugger.Break ();
+ } else
+ System.Diagnostics.Debugger.Break ();
+ }
+
+ if (resolveStack != null && resolveStack.Count > 0)
+ storeSymbol ();
+
+ return symbols.ToArray ();
+ }
+
+ }
+}
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace CrowEdit.Ebnf
+{
+ [Flags]
+ public enum EbnfTokenType {
+ Unknown,
+ Trivia = 0x0100,
+ WhiteSpace = 0x4100,
+ Tabulation = 0x4101,
+ LineBreak = 0x4102,
+ EndOfFile = 0x4103,
+ LineComment = 0x0103,
+ BlockCommentStart = 0x0104,
+ BlockComment = 0x0105,
+ BlockCommentEnd = 0x0106,
+ Name = 0x0200,
+ SymbolName = 0x0201,
+
+ Punctuation = 0x0400,
+ OpenBracket = 0x0401,
+ ClosingBracket = 0x0402,
+ CharMatchOpen = 0x0403,// '['
+ CharMatchClose = 0x0404,// ']'
+ StringMatchOpen = 0x0405,
+ StringMatchClose = 0x0406,
+ CharMatchNegation = 0x0407,// '^'
+ CharMatchRangeOperator = 0x0C01,// '-'
+ //CharMatch = 0x0C01,// '-'
+
+ Operator = 0x0800,
+ SymbolAffectation = 0x0801,
+ ChoiceOp = 0x0802,
+ ExclusionOp = 0x0803,
+ SequenceOp = 0x0804, //never parsed (it's only a white space) but use in syntaxAnalyser
+ CardinalityOp = 0x0805,
+
+ Match = 0x2000,
+ StringMatch = 0x2001,
+ CharMatch = 0x2002,
+ CodePointMatch = 0x2003,
+ TokenSectionStart,
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using Crow.Text;
+using System.Collections.Generic;
+using CrowEditBase;
+
+namespace CrowEdit.Ebnf
+{
+ public class EbnfTokenizer : Tokenizer {
+ public EbnfTokenizer () {}
+ bool readName (ref SpanCharReader reader) {
+ if (reader.EndOfSpan)
+ return false;
+ char c = reader.Peek;
+ if (char.IsLetter(c) || c == '_') {
+ reader.Advance ();
+ while (reader.TryPeek (ref c)) {
+ if (!(char.IsLetterOrDigit(c)|| c == '_'))
+ return true;
+ reader.Advance ();
+ }
+ return true;
+ }
+ return false;
+ }
+ //first '#' character must have been read
+ void readUcsCodePoint (ref SpanCharReader reader) {
+ if (reader.TryRead ('x')) {
+ if (readHexNumber (ref reader)) {
+ addTok (ref reader, EbnfTokenType.CodePointMatch);
+ return;
+ }
+ }
+ throw new EbnfParserException ("malform ucs character codepoint, expecting '#xN'.");
+ }
+ bool readHexNumber (ref SpanCharReader reader) {
+ if (reader.EndOfSpan)
+ return false;
+ if (IsValidHexDigit (reader.Peek)) {
+ reader.Advance ();
+ while (IsValidHexDigit (reader.Peek))
+ reader.Advance ();
+ return true;
+ }
+ return false;
+ }
+
+ public static bool IsValidHexDigit (char c) =>
+ char.IsDigit (c) || (c > 64 && c < 71) || (c > 96 && c < 103);
+
+ public override Token[] Tokenize (string source) {
+ SpanCharReader reader = new SpanCharReader(source);
+
+ startOfTok = 0;
+ Toks = new List<Token>(100);
+
+ while(!reader.EndOfSpan) {
+
+ skipWhiteSpaces (ref reader);
+
+ if (reader.EndOfSpan)
+ break;
+
+ switch (reader.Peek) {
+ case '/':
+ reader.Advance ();
+ if (reader.TryRead ('*')) {
+ addTok (ref reader, EbnfTokenType.BlockCommentStart);
+ while (!reader.EndOfSpan) {
+ if (reader.Eol()) {
+ addTok (ref reader, EbnfTokenType.BlockComment);
+ reader.ReadEol();
+ addTok (ref reader, EbnfTokenType.LineBreak);
+ continue;
+ }
+ if (reader.TryPeek ("*/")) {
+ addTok (ref reader, EbnfTokenType.BlockComment);
+ reader.Advance (3);
+ addTok (ref reader, EbnfTokenType.BlockCommentEnd);
+ break;
+ } else
+ reader.Read ();
+ }
+ }
+ break;
+ case '"':
+ case '\'':
+ char q = reader.Read();
+ addTok (ref reader, EbnfTokenType.StringMatchOpen);
+ if (reader.TryReadUntil (q)) {
+ addTok (ref reader, EbnfTokenType.StringMatch);
+ reader.Advance ();
+ addTok (ref reader, EbnfTokenType.StringMatchClose);
+ } else
+ addTok (ref reader, EbnfTokenType.StringMatch);
+ break;
+ case ':':
+ reader.Advance();
+ if (!reader.TryRead (":="))
+ throw new EbnfParserException ("malform symbol declaration, expecting '::='.");
+ addTok (ref reader, EbnfTokenType.SymbolAffectation);
+ break;
+ case '<':
+ reader.Advance();
+ if (!reader.TryRead ("?TOKENS?>"))
+ throw new EbnfParserException ("malform token section start, expecting '<?TOKENS?>'.");
+ addTok (ref reader, EbnfTokenType.TokenSectionStart);
+ break;
+ case '(':
+ reader.Advance();
+ addTok (ref reader, EbnfTokenType.OpenBracket);
+ break;
+ case ')':
+ reader.Advance();
+ addTok (ref reader, EbnfTokenType.ClosingBracket);
+ break;
+ case '|':
+ reader.Advance();
+ addTok (ref reader, EbnfTokenType.ChoiceOp);
+ break;
+ case '-':
+ reader.Advance();
+ addTok (ref reader, EbnfTokenType.ExclusionOp);
+ break;
+ case '?':
+ case '+':
+ case '*':
+ reader.Advance();
+ addTok (ref reader, EbnfTokenType.CardinalityOp);
+ break;
+ case '[':
+ reader.Advance();
+ addTok (ref reader, EbnfTokenType.CharMatchOpen);
+ if (reader.TryPeek ('^')) {
+ reader.Advance();
+ addTok (ref reader, EbnfTokenType.CharMatchNegation);
+ }
+ while(!reader.EndOfSpan) {
+ char c = reader.Read ();
+ if (c == ']') {
+ addTok (ref reader, EbnfTokenType.CharMatchClose);
+ break;
+ } else if (c == '-')
+ addTok (ref reader, EbnfTokenType.CharMatchRangeOperator);
+ else if (c == '#' && reader.TryPeek ('x'))
+ readUcsCodePoint (ref reader);
+ else
+ addTok (ref reader, EbnfTokenType.CharMatch);
+ }
+ /*if (reader.TryReadUntil ("]")) {
+ addTok (ref reader, TokenType.CharMatch);
+ reader.Advance (1);
+ addTok (ref reader, TokenType.CharMatchClose);
+ break;
+ }*/
+ break;
+ case '#':
+ reader.Advance ();
+ readUcsCodePoint (ref reader);
+ break;
+ case '$':
+ reader.Advance ();
+ addTok (ref reader, EbnfTokenType.EndOfFile);
+ break;
+ case '.':
+ reader.Advance ();
+ addTok (ref reader, EbnfTokenType.CodePointMatch); // '.' is any char
+ break;
+ default:
+ if (readName(ref reader))
+ addTok (ref reader, EbnfTokenType.SymbolName);
+ else if (reader.TryAdvance())
+ addTok (ref reader, EbnfTokenType.Unknown);
+ break;
+ }
+ }
+
+ return Toks.ToArray();
+ }
+
+ }
+}
--- /dev/null
+// Copyright (c) 2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace CrowEdit.Ebnf
+{
+ public abstract class Expression {
+ public bool Optional, Single = true;
+ public bool HasCardinality => !(Single && !Optional);
+ public string CardinalityString => Single ? Optional ? "?" : "" : Optional ? "*" : "+";
+ public override string ToString() => Single ? Optional ? "?" : "" : Optional ? "*" : "+";
+
+ public virtual IEnumerable<Expression> Flatten {
+ get {
+ yield return this;
+ }
+ }
+ public virtual bool IsAllCharMatch => false;
+ }
+ public class CharMatchExpression : Expression {
+ public readonly bool Negative;
+ public readonly CharRangeElement[] Elements;
+ public CharMatchExpression (bool negative, params CharRangeElement[] elements) {
+ Negative = negative;
+ Elements = elements;
+ }
+ public override string ToString() =>
+ $"{(Negative ? "[^" : "[")}{Elements.Select (e=>e.ToString()).Aggregate ((a,b) => $"{a}{b}")}]";
+ public override bool IsAllCharMatch => true;
+ }
+ public class SymbolMatch : Expression {
+ public readonly string SymbolName;
+ public SymbolMatch (string symbolName) {
+ SymbolName = symbolName;
+ }
+ public override string ToString() =>
+ $"{SymbolName}{CardinalityString}";
+ }
+ public class StringMatch : Expression {
+ public readonly string MatchString;
+ public StringMatch (string matchString) {
+ MatchString = matchString;
+ }
+ public override string ToString() => $"'{MatchString}'{CardinalityString}";
+
+ }
+ public class CompoundExpression : Expression {
+ public enum Type { Exclusion = 2, Sequence = 3, Choice = 4 }
+ public readonly Type CompExpType;
+ public Expression FirstOperand;
+ public Expression SecondOperand;
+ public CompoundExpression (Type comoundExpressionType) {
+ CompExpType = comoundExpressionType;
+ }
+ public int OpPrecedence => (int)CompExpType;
+ public override string ToString()
+ {
+ StringBuilder tmp = new StringBuilder (32);
+ if (HasCardinality)
+ tmp.Append ("(");
+ if (FirstOperand is CompoundExpression cmpExp) {
+ if ((OpPrecedence < cmpExp.OpPrecedence) && !cmpExp.HasCardinality)
+ tmp.Append ($"({cmpExp}){cmpExp.CardinalityString}");
+ else
+ tmp.Append ($"{cmpExp}");
+ } else
+ tmp.Append ($"{FirstOperand}");
+
+ switch (CompExpType)
+ {
+ case Type.Sequence:
+ tmp.Append ($" ");
+ break;
+ case Type.Choice:
+ tmp.Append ($" | ");
+ break;
+ default:
+ tmp.Append ($" - ");
+ break;
+ }
+ if (SecondOperand is CompoundExpression cmpExp2) {
+ if ((OpPrecedence < cmpExp2.OpPrecedence) && !cmpExp2.HasCardinality)
+ tmp.Append ($"({cmpExp2})");
+ else
+ tmp.Append ($"{cmpExp2}");
+ } else
+ tmp.Append ($"{SecondOperand}");
+
+ if (HasCardinality)
+ tmp.Append ($"){CardinalityString}");
+
+ return tmp.ToString ();
+ }
+ public override IEnumerable<Expression> Flatten {
+ get {
+ foreach (Expression e in FirstOperand.Flatten)
+ yield return e;
+ foreach (Expression e in SecondOperand.Flatten)
+ yield return e;
+ }
+ }
+
+ public override bool IsAllCharMatch => FirstOperand.IsAllCharMatch & SecondOperand == null ? true : SecondOperand.IsAllCharMatch;
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2021-2025 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+
+namespace CrowEdit.Ebnf
+{
+ class EbnfParserException : Exception {
+ public int Line, Column;
+ public EbnfParserException (string message, int line = 0, int column = 0) : base (message) {
+ Line = line;
+ Column = column;
+ }
+ public override string ToString() => $"{base.ToString()} ({Line},{Column})";
+ }
+}
--- /dev/null
+// Copyright (c) 2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System.Collections.Generic;
+using CrowEditBase;
+
+namespace CrowEdit.Ebnf
+{
+ public class ExpressionSyntax : SyntaxNode {
+ public ExpressionSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ }
+ public class ProductionSyntax : SyntaxNode {
+ public int? ncname, equal;
+ public ExpressionSyntax expression;
+ public ProductionSyntax(int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ public ProductionSyntax(int name, int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ ncname = name;
+ }
+
+ }
+ public class SymbolDecl {
+ public readonly string Name;
+ public Expression Expression;
+ public SymbolDecl(string name) {
+ Name = name;
+ }
+
+ public override string ToString() => $"{Name} ::= {Expression.ToString()}";
+
+ public IEnumerable<Expression> FlattenedExpressions {
+ get {
+ foreach (Expression e in Expression.Flatten)
+ yield return e;
+ }
+ }
+
+ /*public virtual void SortChilds ()
+ {
+ foreach (TreeNode pn in Childs)
+ pn.SortChilds ();
+ Childs = new ObservableList<TreeNode> (Childs.OrderBy (c => c, new NodeComparer()));
+ }
+
+ public class NodeComparer : IComparer<TreeNode>
+ {
+ public int Compare (TreeNode x, TreeNode y)
+ {
+ int typeCompare = x.NodeType.CompareTo (y.NodeType);
+ return typeCompare != 0 ? typeCompare : string.Compare (x.Caption, y.Caption);
+ }
+ }*/
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using CrowEditBase;
+
+namespace CrowEdit.Ebnf
+{
+
+ public class EbnfRootSyntax : SyntaxRootNode {
+ public EbnfRootSyntax (EbnfDocument source)
+ : base (source) {
+ }
+ }
+ public class ConstantDefinitionSyntax : SyntaxNode {
+ internal int? name, equal, valueOpen, valueClose;
+ public override bool IsComplete => base.IsComplete & name.HasValue & equal.HasValue &
+ valueOpen.HasValue & valueClose.HasValue;
+ public ConstantDefinitionSyntax (int startLine, int tokenBase)
+ : base (startLine, tokenBase) {
+ }
+ }
+ public class AttributeSyntax : SyntaxNode {
+ public Token? NameToken { get; internal set; }
+ public Token? EqualToken { get; internal set; }
+ public Token? ValueOpenToken { get; internal set; }
+ public Token? ValueCloseToken { get; internal set; }
+ public Token? ValueToken { get; internal set; }
+ public AttributeSyntax (int startLine, int startTok) : base (startLine, startTok) {}
+ public override bool IsComplete => base.IsComplete & NameToken.HasValue & EqualToken.HasValue &
+ ValueToken.HasValue & ValueOpenToken.HasValue & ValueCloseToken.HasValue;
+ }
+}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFrameworks>net5</TargetFrameworks>
+ <TargetFrameworks>net9</TargetFrameworks>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
public override string ConfigurationWindowPath => "#CENetcoreDbgPlugin.ui.winConfiguration.crow";
public NetcoreDbgService () : base () {
initCommands();
- App.ViewCommands.Add (CMDViewDebug);
+ App.ValueChanged += app_ValueChanged;
+ }
+ ~NetcoreDbgService() {
+ App.ValueChanged -= app_ValueChanged;
}
#region commands
- public ActionCommand CMDViewDebug;
+ public ActionCommand CMDViewDebug,CMDViewBreakPoints,CMDViewWatches,CMDViewThreads,CMDViewStackFrames;
+ public CommandGroup ViewCommands;
+ //public Command CMDDebugStart, CMDDebugPause, CMDDebugStop, CMDDebugStepIn, CMDDebugStepOver, CMDDebugStepOut;
public Command CMDOptions_SelectNetcoredbgPath => new ActionCommand ("...",
() => {
FileDialog dlg = App.LoadIMLFragment<FileDialog> (@"
);
void initCommands ()
{
- CMDViewDebug = new ActionCommand("Debug Window", () => App.LoadWindow ("#CENetcoreDbgPlugin.ui.winDebugging.crow", dbg));
+ CMDViewDebug = new ActionCommand("Debug Window", () => App.LoadWindow ("#CENetcoreDbgPlugin.ui.winDebugging.crow", this));
+ CMDViewBreakPoints = new ActionCommand("Break Points", () => App.LoadWindow ("#CENetcoreDbgPlugin.ui.winBreakPoints.crow", this));
+ CMDViewStackFrames = new ActionCommand("Stack Frames", () => App.LoadWindow ("#CENetcoreDbgPlugin.ui.winStackFrames.crow", this));
+ CMDViewWatches = new ActionCommand("Watches", () => App.LoadWindow ("#CENetcoreDbgPlugin.ui.winWatches.crow", this));
+ CMDViewThreads = new ActionCommand("Threads", () => App.LoadWindow ("#CENetcoreDbgPlugin.ui.winThreads.crow", this));
+ ViewCommands = new CommandGroup("Debugger", CMDViewDebug, CMDViewWatches, CMDViewBreakPoints, CMDViewStackFrames, CMDViewThreads);
}
#endregion
- public string NetcoredbgPath {
- get => Configuration.Global.Get<string> ("NetcoredbgPath");
+
+ Project currentSolution;
+ Project CurrentSolution {
+ get => currentSolution;
set {
- if (value == NetcoredbgPath)
+ if (currentSolution == value)
return;
- Configuration.Global.Set ("NetcoredbgPath", value);
- NotifyValueChanged (value);
+ if (currentSolution != null)
+ currentSolution.ValueChanged -= currentSolution_ValueChanged;
+ currentSolution = value;
+ if (currentSolution != null) {
+ currentSolution.ValueChanged += currentSolution_ValueChanged;
+ if (CurrentState == Status.Init)
+ Start();
+ else if (CurrentState == Status.Running && currentSolution is CERoslynPlugin.SolutionProject sol) {
+ if (sol.StartupProject is CERoslynPlugin.MSBuildProject csprj) {
+ DbgSession.Project = csprj;
+ }
+ }
+ }
+ }
+ }
+ void currentSolution_ValueChanged(object instance, ValueChangeEventArgs e) {
+ if (CurrentState != Status.Running)
+ return;
+ if (e.MemberName == "StartupProject") {
+ if (e.NewValue is CERoslynPlugin.MSBuildProject csprj)
+ DbgSession.Project = csprj;
+ else
+ DbgSession.Project = null;
+ }
+ }
+
+ void app_ValueChanged(object instance, ValueChangeEventArgs e) {
+ if (e.MemberName == "CurrentProject") {
+ if (e.NewValue is CERoslynPlugin.SolutionProject sol)
+ CurrentSolution = sol;
+ else
+ CurrentSolution = null;
}
}
- NetcoredbgDebugger dbg;
public override void Start() {
if (CurrentState == Status.Running)
return;
- dbg = new NetcoredbgDebugger ();
+
+ DbgSession = new NetcoredbgDebugger ();
+
+ if (CurrentState != Status.Paused)
+ App.ViewCommands.Add (ViewCommands);
+
+ if (App.TryGetWindow("#CENetcoreDbgPlugin.ui.winDebugging.crow", out Window win) ) {
+ win.DataSource = DbgSession;
+ }
+ if (App.TryGetWindow("#CENetcoreDbgPlugin.ui.winWatch.crow", out Window win2) ) {
+ win2.DataSource = DbgSession;
+ }
+ if (App.TryGetWindow("#CENetcoreDbgPlugin.ui.winBreakPoints.crow", out Window win3) ) {
+ win3.DataSource = DbgSession;
+ }
+ if (App.TryGetWindow("#CENetcoreDbgPlugin.ui.winStackFrames.crow", out Window win4) ) {
+ win4.DataSource = DbgSession;
+ }
+ if (App.TryGetWindow("#CENetcoreDbgPlugin.ui.winThreads.crow", out Window win5) ) {
+ win5.DataSource = DbgSession;
+ }
+
+
+ if (App.CurrentProject is CERoslynPlugin.SolutionProject sol) {
+ if (sol.StartupProject is CERoslynPlugin.MSBuildProject csprj) {
+ DbgSession.Project = csprj;
+ }
+ }
+
CurrentState = Status.Running;
}
public override void Stop()
{
if (CurrentState != Status.Running)
return;
+
+ App.ViewCommands.Remove (ViewCommands);
+ App.CloseWindow("#CENetcoreDbgPlugin.ui.winDebugging.crow");
+ DbgSession.Terminate ();
+ DbgSession = null;
- dbg.Terminate ();
- dbg = null;
CurrentState = Status.Stopped;
}
public override void Pause()
if (CurrentState != Status.Running)
return;
- dbg.Terminate ();
+ DbgSession.Terminate ();
CurrentState = Status.Paused;
}
+ #region Debugging session
+ NetcoredbgDebugger dbg;
+ public ObservableList<BreakPoint> BreakPoints = new ObservableList<BreakPoint> ();
+ public string NetcoredbgPath {
+ get => Configuration.Global.Get<string> ("NetcoredbgPath");
+ set {
+ if (value == NetcoredbgPath)
+ return;
+ Configuration.Global.Set ("NetcoredbgPath", value);
+ NotifyValueChanged (value);
+ }
+ }
+ public NetcoredbgDebugger DbgSession {
+ get => dbg;
+ set {
+ if (dbg == value)
+ return;
+ dbg = value;
+ NotifyValueChanged ("DbgSession", dbg);
+ }
+ }
+ #endregion
}
}
\ No newline at end of file
base.Project = value;
}
}
- void initDebugSession () {
- if (CurrentState != Status.Init || msbProject == null)
- return;
-
- bool result = procdbg.Start();
-
- procdbg.BeginOutputReadLine();
-
- CreateNewRequest($"-file-exec-and-symbols {msbProject.OutputAssembly}");
- CreateNewRequest($"-environment-cd {Path.GetDirectoryName(msbProject.OutputAssembly)}");
+ LogItem log;
- foreach (BreakPoint bp in BreakPoints)
- InsertBreakPoint(bp);
-
- CurrentState = Status.Starting;
- }
#region CTOR
public NetcoredbgDebugger()
{
+ log = App.GetLog("NetcoredbgDebugger");
+
procdbg = new System.Diagnostics.Process();
procdbg.StartInfo.FileName = App.GetService<NetcoreDbgService>().NetcoredbgPath;
procdbg.StartInfo.Arguments = "--interpreter=mi";
BreakPoints.ListAdd += BreakPoints_ListAdd;
BreakPoints.ListRemove += BreakPoints_ListRemove;
+
+ initCommands();
}
#endregion
/// </summary>
void sendRequest(Request request)
{
- DebuggerLog.Add($"<- {request}");
+ log.Add(LogType.Custom1, $"<- {request}");
procdbg.StandardInput.WriteLine(request);
}
sendRequest(pendingRequest.Peek());
}
}
+ void initDebugSession () {
+ if (CurrentState != Status.Init || msbProject == null)
+ return;
+
+ bool result = procdbg.Start();
+
+ procdbg.BeginOutputReadLine();
+
+ CreateNewRequest($"-file-exec-and-symbols {msbProject.OutputAssembly}");
+ CreateNewRequest($"-environment-cd {Path.GetDirectoryName(msbProject.TargetPath)}");
+
+ foreach (BreakPoint bp in BreakPoints)
+ InsertBreakPoint(bp);
+
+ CurrentState = Status.Starting;
+ CreateNewRequest($"-exec-run");
+ }
#region Debugger abstract class implementation
public override void Start()
{
- initDebugSession ();
- CreateNewRequest($"-exec-run");
+ if (CurrentState == Status.Init)
+ initDebugSession ();
+ else if (CurrentState == Status.Ready) {
+ CurrentState = Status.Starting;
+ CreateNewRequest($"-exec-run");
+ } else if (CurrentState == Status.Stopped)
+ Continue();
}
public override void Pause()
{
}
public override void Stop()
{
+ CurrentState = Status.Stopping;
CreateNewRequest($"-exec-abort");
}
}
private void Procdbg_Exited(object sender, EventArgs e)
{
- DebuggerLog.Add("GDB process Terminated.");
+ log.Add(LogType.Custom1, "GDB process Terminated.");
CurrentState = Status.Init;
}
}
void Procdbg_ErrorDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) {
- DebuggerLog.Add($"-> Error: {e.Data}");
+ log.Add(LogType.Error, $"-> Error: {e.Data}");
}
void Procdbg_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) {
if (string.IsNullOrEmpty(e.Data))
return;
-
- DebuggerLog.Add($"-> {e.Data}");
+
+ log.Add(LogType.Custom1, $"-> {e.Data}");
char firstChar = e.Data[0];
ReadOnlySpan<char> data = e.Data.AsSpan(1);
bp.Update (obj["bkpt"] as MITupple);
} else
- DebuggerLog.Add($"=> request result not handled: {request}");
+ log.Add(LogType.Warning, $"=> request result not handled: {request}");
}
}
else if (data_id.SequenceEqual("exit"))
{
- DebuggerLog.Add($"=> exit request done: {request}");
+ log.Add(LogType.Custom1, $"=> exit request done: {request}");
CreateNewRequest($"-gdb-exit");
}
else
if (reason == "exited")
{
CurrentState = Status.Ready;
- DebuggerLog.Add($"Exited({obj.GetAttributeValue("exit-code")})");
+ log.Add(LogType.Custom1, $"Exited({obj.GetAttributeValue("exit-code")})");
//CreateNewRequest($"-gdb-exit");
}
else if (reason == "entry-point-hit" && !BreakOnStartup) {
Continue();
} else {
- DebuggerLog.Add($"Stopped reason:{reason}");
+ log.Add(LogType.Custom1, $"Stopped reason:{reason}");
StackFrame frame = new StackFrame(obj["frame"] as MITupple);
if (reason == "breakpoint-hit") {
print_unknown_datas(e.Data);
} else if (firstChar == '=') {//EVENTS
if (data_id.SequenceEqual("message")) {
- OutputLog.Add(obj.GetAttributeValue("text").ToString().Replace(@"\0", ""));
+ log.Add(LogType.Custom2, obj.GetAttributeValue("text").ToString().Replace(@"\0", ""));
} else if (data_id.SequenceEqual("breakpoint-modified")) {
- OutputLog.Add($"{e.Data}");
+ log.Add(LogType.Custom2, $"{e.Data}");
MITupple bkpt = obj["bkpt"] as MITupple;
BreakPoint bp = (BreakPoint)BreakPoints.FirstOrDefault (bk=>bk.Index == int.Parse (bkpt.GetAttributeValue("number")));
bp.Update (bkpt);
void print_unknown_datas(string data)
{
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine(data);
- Console.ResetColor();
+ log.Add(LogType.Message, $"unknown datas: {data}");
}
public void WatchRequest(Watch w)
--- /dev/null
+<?xml version="1.0"?>
+<DockWindow Caption="BreakPoints" Width="60%">
+ <ListBox DataSource="{DbgSession}" Data="{BreakPoints}" SelectedItem="{²CurrentBreakPoint}"
+ ContextCommands="{Commands}">
+ <Template>
+ <Scroller Name="scroller1" >
+ <Table Columns="Num,Fit;File,Stretched;Line,Fit;State,Fit"
+ Height="Fit" Name="ItemsContainer" VerticalAlignment="Top"/>
+ </Scroller>
+ </Template>
+ <ItemTemplate>
+ <TableRow Selected = "{Background=${ControlHighlight}}"
+ Unselected = "{Background=Transparent}">
+ <Label Text="{Index}" TextAlignment="Right"/>
+ <Label Text="{FileName}" />
+ <Label Text="{Line}" TextAlignment="Right"/>
+ <Widget Width="10" Height="10" Background="Green" IsVisible="{IsEnabled}"/>
+ </TableRow>
+ </ItemTemplate>
+ </ListBox>
+
+</DockWindow>
<?xml version="1.0"?>
-<Window Caption="Netcore Debugger" Width="Fit" Height="Fit" Resizable="false">
- <Template>
- <Border Margin="5">
- <HorizontalStack Fit="true">
- <Image Name="MoveHandle" Path="#icons.move-arrows.svg" Width="12" Height="12"/>
- <Container Name="Content"/>
- </HorizontalStack>
- </Border>
- </Template>
- <HorizontalStack Fit="true">
+<DockWindow Caption="Netcore Debugger" Width="Fit" Height="Fit" Resizable="false" >
+ <HorizontalStack Fit="true" DataSource="{DbgSession}" Margin="0" Spacing="5">
<Button Style="IcoBut" Command="{CMDDebugStart}"/>
<Button Style="IcoBut" Command="{CMDDebugPause}"/>
<Button Style="IcoBut" Command="{CMDDebugStop}"/>
<Button Style="IcoBut" Command="{CMDDebugStepIn}"/>
<Button Style="IcoBut" Command="{CMDDebugStepOut}"/>
<Button Style="IcoBut" Command="{CMDDebugStepOver}"/>
+ <Label Text="{CurrentState}" Margin="2"/>
</HorizontalStack>
-</kWindow>
+</DockWindow>
--- /dev/null
+<?xml version="1.0"?>
+<DockWindow Caption="Call Stack" Width="60%">
+ <Container DataSource="{DbgSession}">
+ <ListBox Data="{Frames}" SelectedItem="{²CurrentFrame}">
+ <Template>
+ <Scroller Name="scroller1" >
+ <Table Columns="Level,Fit;Address,Fit;Function,Stretched;File,Fit;Line,Fit"
+ Height="Fit" Name="ItemsContainer" VerticalAlignment="Top"/>
+ </Scroller>
+ </Template>
+ <ItemTemplate>
+ <TableRow Selected = "{Background=${ControlHighlight}}"
+ Unselected = "{Background=Transparent}">
+ <Label Text="{Level}" TextAlignment="Right" />
+ <Label Text="{Address}" />
+ <Label Text="{Function}" />
+ <Label Text="{File}" />
+ <Label Text="{Line}" />
+ </TableRow>
+ </ItemTemplate>
+ </ListBox>
+ </Container>
+</DockWindow>
+<!--<HorizontalStack DataSource="{ClrAddress}" Background="Onyx" IsVisible="{HasCLRAddress}" Fit="true">
+ <Label Text="{ModuleID}" />
+ <Label Text="{MethodToken}" />
+ <Label Text="{IlOffset}" />
+ <Label Text="{NativeOffset}" />
+</HorizontalStack>-->
+
--- /dev/null
+<?xml version="1.0"?>
+<DockWindow Caption="Threads" Width="60%">
+ <ListBox DataSource="{DbgSession}" Data="{Threads}" SelectedItem="{²CurrentThread}">
+ <Template>
+ <Scroller Name="scroller1" >
+ <Table Columns="Id,Fit;Title,Stretched;State,Fit"
+ Height="Fit" Name="ItemsContainer" VerticalAlignment="Top"/>
+ </Scroller>
+ </Template>
+ <ItemTemplate>
+ <TableRow Selected = "{Background=${ControlHighlight}}"
+ Unselected = "{Background=Transparent}">
+ <Label Text="{Id}" />
+ <Label Text="{Name}" />
+ <Label Text="{IsRunning}" />
+ </TableRow>
+ </ItemTemplate>
+ </ListBox>
+</DockWindow>
--- /dev/null
+<?xml version="1.0"?>
+<DockWindow Caption="Watches" Width="60%">
+ <VerticalStack RootDataLevel="true" DataSource="{DbgSession}" >
+ <TreeView IsRoot="true" Data="{Watches}" >
+ <ItemTemplate Data="Children" >
+ <Expandable IsExpanded="{²IsExpanded}" >
+ <Template>
+ <VerticalStack>
+ <ListItem Height="Fit" Margin="0" Focusable="true" HorizontalAlignment="Left" IsSelected="{IsSelected}"
+ ContextCommands = "{Commands}"
+ Selected = "{Background=${ControlHighlight}}"
+ Unselected = "{Background=Transparent}">
+ <HorizontalStack Spacing="5" MouseDoubleClick="./onClickForExpand">
+ <Image Margin="1" Width="9" Height="9" Focusable="true" MouseDown="./onClickForExpand" IsVisible="{HasChildren}"
+ Path="{./Image}" SvgSub="{./IsExpanded}" MouseEnter="{Background=LightGrey}" MouseLeave="{Background=Transparent}" />
+ <Label Text="{Expression}" Foreground="White" MinimumSize="120,0"/>
+ <TextBox Text="{Value}" IsEnabled="{IsEditable}" Width="Stretched"/>
+ <Label Text="{Name}" Foreground="LightGrey"/>
+ </HorizontalStack>
+ </ListItem>
+ <Container Name="Content" Visible="false" />
+ </VerticalStack>
+ </Template>
+ <HorizontalStack Height="Fit">
+ <Widget Width="16" Height="10" />
+ <VerticalStack Height="Fit" Name="ItemsContainer" />
+ </HorizontalStack>
+ </Expandable>
+ </ItemTemplate>
+ </TreeView>
+ <TextBox Validate="OnValidateNewWatch"/>
+ </VerticalStack>
+</DockWindow>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFrameworks>net9</TargetFrameworks>
+ <EnableDefaultItems>false</EnableDefaultItems>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="src\**\*.cs" />
+ <EmbeddedResource Include="ui\**\*.*" />
+ <EmbeddedResource Include="default.conf" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="NuGet.Protocol" Version="6.*" />
+ <ProjectReference Include="../CERoslynPlugin\CERoslynPlugin.csproj" />
+ </ItemGroup>
+</Project>
--- /dev/null
+MainService=NugetPlugin.NugetService
\ No newline at end of file
--- /dev/null
+using System.Net.Http;
+using Crow;
+using NuGet.Protocol.Core.Types;
+
+namespace NugetPlugin
+{
+ public static class Extensions
+ {
+ public static string GetNugetPackageIcon (this IPackageSearchMetadata pkg) {
+ return "url:" + pkg.IconUrl;
+ }
+ }
+}
--- /dev/null
+// Copyright (c) 2013-2019 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Loader;
+using CrowEditBase;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using static CrowEditBase.CrowEditBase;
+using Crow;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGet.Protocol.Core.Types;
+using NuGet.Protocol;
+using NuGet.Versioning;
+using NuGet.Packaging.Core;
+using System.IO.Compression;
+using NuGet.Common;
+using System.Net.Http;
+
+namespace NugetPlugin
+{
+ public class NugetService : Service {
+ public override string ConfigurationWindowPath => "#CENugetPlugin.ui.winConfiguration.crow";
+
+ public NugetService () : base () {
+ initCommands();
+
+ App.ViewCommands.Add (CMDViewNuget);
+
+ if (App.TryGetWindow("#CENugetPlugin.ui.winNugetExplorer.crow", out Window win))
+ win.DataSource = this;
+ }
+ #region commands
+ public ActionCommand CMDViewNuget, CMDSearchPackage;
+ void initCommands ()
+ {
+ CMDViewNuget = new ActionCommand("Nuget Explorer", () => App.LoadWindow ("#CENugetPlugin.ui.winNugetExplorer.crow", this));
+ CMDSearchPackage = new ActionCommand("Search Package", () => SearchPackage(searchString));
+ }
+ #endregion
+
+ public override void Start() {
+ if (CurrentState == Status.Running)
+ return;
+ CurrentState = Status.Running;
+ }
+ public override void Stop()
+ {
+ if (CurrentState != Status.Running)
+ return;
+
+ CurrentState = Status.Stopped;
+ }
+ public override void Pause()
+ {
+ if (CurrentState != Status.Running)
+ return;
+
+ CurrentState = Status.Paused;
+ }
+ string searchString;
+ IEnumerable<IPackageSearchMetadata> searchResults;
+ public string SearchString {
+ get => searchString;
+ set {
+ if (searchString == value)
+ return;
+ searchString = value;
+ NotifyValueChanged(searchString);
+ }
+ }
+ public IEnumerable<IPackageSearchMetadata> SearchResults {
+ get => searchResults;
+ }
+ public async Task<Assembly> LoadFromNuget(string id, string version, string? nugetFeedUrl = null, CancellationToken cancellationToken = default)
+ {
+ ILogger _nugetLogger = NullLogger.Instance;
+ var repository = Repository.Factory.GetCoreV3(nugetFeedUrl ?? "https://api.nuget.org/v3/index.json");
+ var downloadResource = await repository.GetResourceAsync<DownloadResource>();
+ if (!NuGetVersion.TryParse(version, out var nuGetVersion))
+ {
+ throw new Exception($"invalid version {version} for nuget package {id}");
+ }
+ using (var downloadResourceResult = await downloadResource.GetDownloadResourceResultAsync(
+ new PackageIdentity(id, nuGetVersion),
+ new PackageDownloadContext(new SourceCacheContext()),
+ globalPackagesFolder: Path.GetTempPath(),
+ logger: _nugetLogger,
+ token: cancellationToken)){
+
+
+ if (downloadResourceResult.Status != DownloadResourceResultStatus.Available)
+ {
+ throw new Exception($"Download of NuGet package failed. DownloadResult Status: {downloadResourceResult.Status}");
+ }
+
+ var reader = downloadResourceResult.PackageReader;
+
+ var archive = new ZipArchive(downloadResourceResult.PackageStream);
+
+ var lib = reader.GetLibItems().First()?.Items.First();
+
+ var entry = archive.GetEntry(lib);
+
+ using (MemoryStream decompressed = new MemoryStream()) {
+ entry.Open().CopyTo(decompressed);
+ var assemblyLoadContext = new System.Runtime.Loader.AssemblyLoadContext(null, isCollectible: true);
+ decompressed.Position = 0;
+ return assemblyLoadContext.LoadFromStream(decompressed);
+ }
+ }
+ }
+ async void ListPackages() {
+ ILogger logger = NullLogger.Instance;
+ CancellationToken cancellationToken = CancellationToken.None;
+
+ SourceCacheContext cache = new SourceCacheContext();
+ SourceRepository repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
+ PackageMetadataResource resource = await repository.GetResourceAsync<PackageMetadataResource>();
+
+ IEnumerable<IPackageSearchMetadata> packages = await resource.GetMetadataAsync(
+ "Newtonsoft.Json",
+ includePrerelease: true,
+ includeUnlisted: false,
+ cache,
+ logger,
+ cancellationToken);
+
+ foreach (IPackageSearchMetadata package in packages)
+ {
+ Console.WriteLine($"Version: {package.Identity.Version}");
+ Console.WriteLine($"Listed: {package.IsListed}");
+ Console.WriteLine($"Tags: {package.Tags}");
+ Console.WriteLine($"Description: {package.Description}");
+ }
+ }
+ async void SearchPackage(string searchString) {
+ ILogger logger = NullLogger.Instance;
+ CancellationToken cancellationToken = CancellationToken.None;
+
+ SourceCacheContext cache = new SourceCacheContext();
+ SourceRepository repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
+ PackageSearchResource resource = await repository.GetResourceAsync<PackageSearchResource>();
+ SearchFilter searchFilter = new SearchFilter(includePrerelease: true);
+
+ searchResults = await resource.SearchAsync(
+ searchString,
+ searchFilter,
+ skip: 0,
+ take: 20,
+ logger,
+ cancellationToken);
+
+ lock(App.UpdateMutex)
+ NotifyValueChanged("SearchResults", searchResults);
+ }
+
+
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0"?>
+<DockWindow Caption="NetcoreDbg plugin configuration" Width="80%" Height="400" Resizable="false">
+ <VerticalStack RootDataLevel="true" Margin="5">
+ <HorizontalStack Height="Fit">
+ <Label Width="200" Text="Netcoredbg path"/>
+ <TextBox Width="Stretched" Text="{²NetcoredbgPath}"/>
+ <Button Command="{CMDOptions_SelectNetcoredbgPath}" MinimumSize="0,0"/>
+ </HorizontalStack>
+ </VerticalStack>
+</DockWindow>
+
+
--- /dev/null
+<?xml version="1.0"?>
+<DockWindow Caption="Nuget explorer" Width="80%" Height="400" Resizable="true">
+ <VerticalStack RootDataLevel="true" Margin="5">
+ <HorizontalStack Height="Fit" Spacing="10">
+ <Label Text="Search" Margin="5"/>
+ <TextBox Width="Stretched" MaximumSize="300,0" Text="{²SearchString}"/>
+ <Button Command="{CMDSearchPackage}" MinimumSize="0,0"/>
+ </HorizontalStack>
+ <ListBox Style="ScrollingListBox" Height="Stretched" Width="Stretched" Data="{SearchResults}">
+ <Template>
+ <Border BorderWidth="1" Background="{./Background}">
+ <HorizontalStack Margin="1">
+ <Scroller Name="ItemsScroller" Margin="2">
+ <VerticalStack Height="Fit" MinimumSize="10,10" Spacing="10"
+ Name="ItemsContainer" Margin="0" VerticalAlignment="Top"/>
+ </Scroller>
+ <ScrollBar Name="scrollbar1" Value="{²../ItemsScroller.ScrollY}"
+ LargeIncrement="{../ItemsScroller.PageHeight}" SmallIncrement="30" CursorRatio="{../ItemsScroller.ChildHeightRatio}"
+ Maximum="{../ItemsScroller.MaxScrollY}" Orientation="Vertical"
+ Width="12" />
+ </HorizontalStack>
+ </Border>
+ </Template>
+ <ItemTemplate>
+ <!--<TableRow Selected = "{Background=${ControlHighlight}}"
+ Unselected = "{Background=Transparent}">
+ <Label Text="{Title}" VerticalAlignment="Top" />
+ <Label Text="{Summary}" Multiline="true"/>
+ </TableRow>-->
+ <ListItem Selected = "{Background=${ControlHighlight}}"
+ Unselected = "{Background=Transparent}">
+ <Border CornerRadius="2" Margin="0" Height="Fit"
+ Foreground="Transparent"
+ MouseEnter="{Foreground=DimGrey}"
+ MouseLeave="{Foreground=Transparent}">
+ <HorizontalStack Height="50" Spacing="10" Margin="5">
+ <Image Height="Stretched" Width="50" Path="{GetNugetPackageIcon}" Background="White"/>
+ <Label VerticalAlignment="Top" Text="{Title}" Width="20%" />
+ <Label Height="Stretched" Text="{Summary}" Multiline="true"/>
+ </HorizontalStack>
+ </Border>
+ </ListItem>
+ </ItemTemplate>
+ </ListBox>
+ </VerticalStack>
+</DockWindow>
+
+
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
+ <TargetFrameworks>net9</TargetFrameworks>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<PackageReference Include="Enums.NET" Version="4.0.0" />
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
- <PackageReference Include="Microsoft.Build" Version="15.1.*">
+ <PackageReference Include="Microsoft.Build" Version="15.1.*" ExcludeAssets="runtime" />
+ <PackageReference Include="Microsoft.Build.Runtime" Version="15.1.*" ExcludeAssets="runtime" />
+ <!--<PackageReference Include="Microsoft.Build.Tasks.Core" Version="15.1.*"/> -->
+ <PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.1.*" ExcludeAssets="runtime" />
+
+ <!--<PackageReference Include="Microsoft.Build" Version="15.1.*">
<PrivateAssets>all</PrivateAssets>
<Private>true</Private>
<Visible>False</Visible>
<Visible>False</Visible>
<Private>true</Private>
<ExcludeAssets>runtime</ExcludeAssets>
- </PackageReference>
+ </PackageReference>-->
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.7.*" >
+ <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.7.*" >
<IncludeAssets>all</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
<ExcludeAssets>runtime</ExcludeAssets>
<Visible>False</Visible>
</PackageReference>
- <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.7.*" >
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.*" >
<IncludeAssets>all</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
<ExcludeAssets>runtime</ExcludeAssets>
MainService=CERoslynPlugin.RoslynService
-FileAssociations=CERoslynPlugin.CSDocument:.cs;CERoslynPlugin.SolutionProject:.sln
\ No newline at end of file
+FileAssociations=CERoslynPlugin.CSDocument:.cs:#ui.sourceEditor.itmp;CERoslynPlugin.SolutionProject:.sln
\ No newline at end of file
}
}
public string Parameters { get; set; }
-
+ CrowEditBase.LogItem logger;
public CELogger (LoggerVerbosity verbosity = LoggerVerbosity.Detailed)
{
+ logger = App.GetLog("MSBuild");
Verbosity = verbosity;
}
public void Initialize (IEventSource eventSource) {
eventSource.TargetFinished += EventSource_TargetFinished;
eventSource.TaskStarted += EventSource_TaskStarted;
eventSource.TaskFinished += EventSource_TaskFinished;
+ eventSource.CustomEventRaised += EventSource_CusomEvent;
+ //eventSource.AnyEventRaised += EventSource_AnyEvent;
}
void unregisterHandles () {
eventSource.TargetFinished -= EventSource_TargetFinished;
eventSource.TaskStarted -= EventSource_TaskStarted;
eventSource.TaskFinished -= EventSource_TaskFinished;
+ eventSource.CustomEventRaised -= EventSource_CusomEvent;
+ //eventSource.AnyEventRaised -= EventSource_AnyEvent;
}
void log (LogType type, string message) {
string[] lines = Regex.Split (message, "\r\n|\r|\n");//|\r|\n|\\\\n");
for (int i=0; i<lines.Length;i++)
- App.Log (type, lines[i]);
+ logger.Add (type, lines[i]);
}
+ void EventSource_AnyEvent (object sender, BuildEventArgs e)
+ {
+ log (LogType.Custom3, e.Message);
+ }
+ void EventSource_CusomEvent (object sender, CustomBuildEventArgs e)
+ {
+ if (Verbosity == LoggerVerbosity.Diagnostic)
+ log (LogType.Custom3, e.Message);
+ }
+
void EventSource_Progress_BuildStarted (object sender, BuildStartedEventArgs e)
{
- App.ResetLog ();
+ logger.ResetLog ();
log (LogType.High, "Build starting.");
}
void EventSource_Progress_BuildFinished (object sender, BuildFinishedEventArgs e)
using System.Collections;
using System.Reflection;
using CrowEditBase;
+using Drawing2D;
//using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static CrowEditBase.CrowEditBase;
+using CrowEdit.Xml;
namespace CERoslynPlugin
{
public static CSTokenType GetTokenType (this Token tok) => (XmlTokenType)tok.Type;
public static void SetTokenType (this Token tok, CSTokenType type) => tok.Type = (TokenType)type;
}*/
- public class CSDocument : TextDocument {
+ public class CSDocument : SourceDocument {
static CSDocument () {
App.GetService<RoslynService> ()?.Start ();
CSharpSyntaxTree tree;
public CSDocument (string fullPath, string editorPath) : base (fullPath, editorPath) {
- //tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText (Source, CSharpParseOptions.Default);
+ tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText (Source, CSharpParseOptions.Default);
+ var root = tree.GetRoot();
+ /*foreach (SyntaxKind v in Enum.GetValues<SyntaxKind>().OrderBy(k=>(uint)k)) {
+ Console.WriteLine($"{v,50} {(((uint)v) ).ToString("B16") } {(((uint)v) ).ToString("X4") }");
+ }*/
}
#region SourceDocument abstract class implementation
- /*protected override Tokenizer CreateTokenizer() => new CSTokenizer ();
- protected override SyntaxAnalyser CreateSyntaxAnalyser() => null;// new XmlSyntaxAnalyser (this);
+ protected override Tokenizer CreateTokenizer() => new CSTokenizer ();
+ protected override SyntaxAnalyser CreateSyntaxAnalyser() => new CSSyntaxAnalyser (this);
- public override IList GetSuggestions(int pos)
+ public override IList GetSuggestions (CharLocation loc)
{
throw new NotImplementedException();
}
-
- public override TextChange? GetCompletionForCurrentToken(object suggestion, out TextSpan? newSelection)
+ public override bool TryGetCompletionForCurrentToken (object suggestion, out TextChange change, out TextSpan? newSelection)
{
throw new NotImplementedException();
- }*/
+ }
#endregion
+ public override Color GetColorForToken (TokenType tokType) {
+ uint rawkind = (uint)tokType;
+ uint tokCat = rawkind & 0xFF;
+ CSTokenType cat = (CSTokenType)tokCat;
+ SyntaxKind k = (SyntaxKind)tokType;
- /*ProjectCollection tree;
- public CSDocument (string fullPath) : base (fullPath) {
- tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText (Source, CSharpParseOptions.Default);
- }*/
+ //Console.WriteLine($"{k,50} {(((uint)tokType) ).ToString("B16") } {cat}");
+
+ switch (cat) {
+ case CSTokenType.Trivia: return Colors.Grey;
+ case CSTokenType.Keyword: return Colors.DarkSlateBlue;
+ default: return Colors.Black;
+ }
+ }
}
}
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2013-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace CrowEdit.Xml
+{
+ [Flags]
+ public enum CSTokenType {
+ Unknown,
+
+ Trivia = 0x0100,
+ WhiteSpace = 0x4100,
+ Tabulation = 0x4101,
+ LineBreak = 0x4102,
+ LineComment = 0x0103,
+ BlockCommentStart = 0x0104,
+ BlockComment = 0x0105,
+ BlockCommentEnd = 0x0106,
+ Name = 0x0200,
+ Punctuation = 0x0400,
+ Operator = 0x0800,
+ Keyword = 0x1000,
+ }
+}
\ No newline at end of file
{
public class CSTokenizer : Tokenizer
{
- //CsharpSyntaxWalkerBridge bridge = new CsharpSyntaxWalkerBridge();
+
+
int startOfTok;
protected List<Token> Toks;
void addTok (ref SpanCharReader reader, Enum tokType) {
}
void skipWhiteSpacesAndLineBreaks (ref SpanCharReader reader) {
while(!reader.EndOfSpan) {
- switch (reader.Peak) {
+ switch (reader.Peek) {
case '\x85':
case '\x2028':
case '\xA':
case '\x20':
case '\x9':
char c = reader.Read();
- while (reader.TryPeak (c))
+ while (reader.TryPeek (c))
reader.Read();
addTok (ref reader, c == '\x20' ? TokenType.WhiteSpace : TokenType.Tabulation);
break;
}
void skipWhiteSpaces (ref SpanCharReader reader) {
while(!reader.EndOfSpan) {
- switch (reader.Peak) {
+ switch (reader.Peek) {
case '\x20':
case '\x9':
char c = reader.Read();
- while (reader.TryPeak (c))
+ while (reader.TryPeek (c))
reader.Read();
addTok (ref reader, c == '\x20' ? TokenType.WhiteSpace : TokenType.Tabulation);
break;
public override Token[] Tokenize(string source)
{
- SpanCharReader reader = new SpanCharReader(source);
+ var tree = CSharpSyntaxTree.ParseText(source);
+ CsharpSyntaxWalkerBridge bridge = new CsharpSyntaxWalkerBridge();
+ bridge.Visit(tree.GetRoot());
+ //SpanCharReader reader = new SpanCharReader(source);
- startOfTok = 0;
+ //startOfTok = 0;
//curState = States.Init;
- Toks = new List<Token>(100);
+
/*while(!reader.EndOfSpan) {
if (reader.EndOfSpan)
break;
- switch (reader.Peak) {
+ switch (reader.Peek) {
case '/':
reader.Advance ();
break;
}
}*/
+ Toks = bridge.Toks;
return Toks.ToArray();
}
}
class CsharpSyntaxWalkerBridge : CSharpSyntaxWalker
{
- List<Token> Toks;
+ public List<Token> Toks;
public CsharpSyntaxWalkerBridge () : base (SyntaxWalkerDepth.StructuredTrivia)
{
Toks = new List<Token>(100);
{
base.Visit (node);
}
+
public override void VisitToken (SyntaxToken token)
{
+ /*Console.ForegroundColor = ConsoleColor.Blue;
+ Console.Write(((uint)token.Kind()));
+ Console.ForegroundColor = ConsoleColor.Gray;
+ Console.Write(token.ToFullString());*/
+
+
+
VisitLeadingTrivia (token);
if (SyntaxFacts.IsLiteralExpression (token.Kind ())) {
}
void addMultilineTok (SyntaxTrivia trivia) {
-
+ Microsoft.CodeAnalysis.Text.TextSpan span = trivia.Span;
+ Toks.Add (new Token(span.Start, span.Length, (TokenType)trivia.RawKind));
}
void addMultilineTok (SyntaxToken token) {
-
+ Microsoft.CodeAnalysis.Text.TextSpan span = token.Span;
+ Toks.Add (new Token(span.Start, span.Length, (TokenType)token.RawKind));
}
}
Console.WriteLine (e.Message);
}
private void EventSource_AnyEventRaised (object sender, BuildEventArgs e) {
+ if (e is TaskStartedEventArgs tse)
+ Console.ForegroundColor = ConsoleColor.Green;
+ else if (e is TaskFinishedEventArgs tfe)
+ Console.ForegroundColor = ConsoleColor.Green;
+ else if (e is TargetStartedEventArgs tase)
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ else if (e is TargetFinishedEventArgs tafe)
+ Console.ForegroundColor = ConsoleColor.Yellow;
+ else if (e is BuildMessageEventArgs bme)
+ Console.ForegroundColor = ConsoleColor.Gray;
+ else if (e is ProjectStartedEventArgs pse)
+ Console.ForegroundColor = ConsoleColor.White;
+ else if (e is ProjectFinishedEventArgs pfe)
+ Console.ForegroundColor = ConsoleColor.White;
+ else if (e is BuildErrorEventArgs bee)
+ Console.ForegroundColor = ConsoleColor.Red;
+ else if (e is BuildWarningEventArgs bwe)
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ else
+ Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine (e.Message);
}
return;
try
{
+ //string test = System.Runtime.Loader.AssemblyLoadContext.CurrentContextualReflectionContext.Name;
using (var ctx = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext (this.GetType().Assembly).EnterContextualReflection()) {
ProjectRootElement projectRootElt = ProjectRootElement.Open (projectInSolution.AbsolutePath);
- project = new Microsoft.Build.Evaluation.Project (projectInSolution.AbsolutePath, null, null, solutionProject.projectCollection);
-
+ project = new Microsoft.Build.Evaluation.Project (projectInSolution.AbsolutePath, null, "Current", solutionProject.projectCollection);
+
ProjectProperty msbuildProjExtPath = project.GetProperty ("MSBuildProjectExtensionsPath");
ProjectProperty msbuildProjFile = project.GetProperty ("MSBuildProjectFile");
if (constants != null)
parseOptions = parseOptions.WithPreprocessorSymbols (constants.EvaluatedValue.Split (';'));
+
/*ProjectProperty targetPath = project.GetProperty ("TargetPath");
+
printEvaluatedProperties(project.CreateProjectInstance());*/
populateTreeNodes ();
}
catch (System.Exception ex)
{
- Console.WriteLine (ex);
+ //App.Log(LogType.Error, $"[MSBuildProject.Load] Error: {ex.ToString()}");
}
}
public void Build () => Build ("Build");
public void Build (params string[] targets)
{
- BuildManager.DefaultBuildManager.ResetCaches ();
- //using (var ctx = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext (this.GetType().Assembly).EnterContextualReflection()) {
+ using (var ctx = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext (this.GetType().Assembly).EnterContextualReflection()) {
+ BuildManager.DefaultBuildManager.ResetCaches ();
+
ProjectInstance pi = BuildManager.DefaultBuildManager.GetProjectInstanceForBuild (project);
+
+ Console.ForegroundColor = ConsoleColor.Green;
+ /*Console.WriteLine ($"Initial properties");
+ printEvaluatedProperties (pi);*/
+
BuildRequestData request = new BuildRequestData (pi, targets, null,
BuildRequestDataFlags.ProvideProjectStateAfterBuild);
lastBuildResult = BuildManager.DefaultBuildManager.Build (solutionProject.buildParams, request);
- printEvaluatedProperties (lastBuildResult.ProjectStateAfterBuild);
+ /*printEvaluatedProperties (lastBuildResult.ProjectStateAfterBuild);
- var test = lastBuildResult.ProjectStateAfterBuild.GetItems ("Reference");
+ var test = lastBuildResult.ProjectStateAfterBuild.GetItems ("Reference");*/
- Console.WriteLine (IsCrowProject);
+ //Console.WriteLine (IsCrowProject);
- //}
+ }
}
public async void DesignBuild () {
lastBuildResult = await Task.Run (()=> designBuild());
curNode.AddChild (new ProjectItemNode (pn));
} catch (Exception ex) {
+
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine (ex);
Console.ResetColor ();
public string DefaultTargets => project.Xml.DefaultTargets;
public ICollection<ProjectProperty> Properties => project.Properties;
public ICollection<ProjectProperty> PropertiesSorted => project.Properties.OrderBy(p=>p.Name).ToList();
+ public string TargetPath => project.GetProperty ("TargetPath").EvaluatedValue;
public string AssemblyName => project.GetProperty ("AssemblyName").EvaluatedValue;
public string OutputPath => project.GetProperty ("OutputPath").EvaluatedValue;
public string IntermediateOutputPath => project.GetProperty ("IntermediateOutputPath").EvaluatedValue;
public string OutputType => project.GetProperty ("OutputType").EvaluatedValue;
public string OutputAssembly =>
- Path.Combine (project.GetPropertyValue ("OutputPath"), project.GetPropertyValue ("TargetFrameworks"), AssemblyName + AssemblyExtension);
+ Path.Combine (project.GetProperty ("TargetDir").EvaluatedValue, project.GetProperty ("TargetName").EvaluatedValue);
public string AssemblyExtension => RuntimeInformation.IsOSPlatform (OSPlatform.Windows) ? ".exe" : "";
public OutputKind OutputKind {
get {
Console.WriteLine ($"{item.EvaluatedValue}");
}
- ICollection<ProjectItemInstance> pii = pi.GetItems ("InnerOutput");
+ /*ICollection<ProjectItemInstance> pii = pi.GetItems ("InnerOutput");
ProjectRootElement pre = pi.ToProjectRootElement();
pre.FullPath = "/home/jp/test.csproj";
- pre.Save();
+ pre.Save();*/
}
#endregion
}
}
-
-
-
public override string Icon {
get {
switch (NodeType) {
/*case NodeType.Reference:
return CrowIDE.IcoReference;*/
case NodeType.ProjectReference:
- return "#Crow.Icons.projectRef.svg";
+ return "#icons.file-cube.svg";
case NodeType.PackageReference:
return "#icons.file_type_package.svg";
case NodeType.ReferenceGroup:
break;
}
}*/
-
public RoslynService () : base () {
configureDefaultSDKPathes ();
//TODO static init to prevent rebinding on Service multiple instantiation
AssemblyLoadContext pluginCtx = AssemblyLoadContext.GetLoadContext (Assembly.GetExecutingAssembly());
- pluginCtx.Resolving += msbuildResolve;
+ AssemblyLoadContext.Default.Resolving += msbuildResolve;
+
- /*foreach (string dll in Directory.GetFiles ("/usr/share/dotnet/shared/Microsoft.NETCore.App/5.0.17/", "*.dll")) {
- try {
- pluginCtx.LoadFromAssemblyPath (dll);
- } catch (Exception ex) {
- App.Log(LogType.Error, $"[RoslynService]{ex}");
- }
- }*/
-
- foreach (string dll in Directory.GetFiles (MSBuildRoot, "*.dll")) {
- try {
- pluginCtx.LoadFromAssemblyPath (dll);
- } catch (Exception ex) {
- App.Log(LogType.Error, $"[RoslynService]{ex}");
- }
- }
- string capath = Path.Combine (MSBuildRoot, "Roslyn");
- foreach (string dll in Directory.GetFiles (capath, "*.dll")) {
- try {
- pluginCtx.LoadFromAssemblyPath (dll);
- } catch (Exception ex) {
- App.Log(LogType.Error, $"[RoslynService]{ex}");
- }
- }
- capath = Path.Combine (MSBuildRoot, "Roslyn", "bincore");
- foreach (string dll in Directory.GetFiles (capath, "*.dll")) {
- try {
- pluginCtx.LoadFromAssemblyPath (dll);
- } catch (Exception ex) {
- App.Log(LogType.Error, $"[RoslynService]{ex}");
- }
- }
}
Assembly msbuildResolve (AssemblyLoadContext context, AssemblyName assemblyName) {
string assemblyPath = Path.Combine (MSBuildRoot, assemblyName.Name + ".dll");
//return File.Exists (assemblyPath) ? context.LoadFromAssemblyPath (assemblyPath) : null;
- if (!File.Exists (assemblyPath))
- return null;
+ if (!File.Exists (assemblyPath)) {
+ assemblyPath = Path.Combine (MSBuildRoot, "Roslyn","bincore", assemblyName.Name + ".dll");
+ if (!File.Exists (assemblyPath)) {
+ foreach (string file in Directory.EnumerateFiles(MSBuildRoot, assemblyName.Name + ".dll", new EnumerationOptions { RecurseSubdirectories = true }))
+ {
+ try {
+
+ AssemblyName an = AssemblyName.GetAssemblyName(file);
+ /*if (an.ProcessorArchitecture != ProcessorArchitecture.Amd64)
+ continue;*/
+ if (string.Equals(an.ToString(), assemblyName.ToString())) {
+ Assembly aa = context.LoadFromAssemblyPath (file);
+ //App.Log (LogType.Message, $"[MSBuildResolve]{aa},{aa.CodeBase}");
+ return aa;
+ }
+ } catch (Exception e) {
+ System.Diagnostics.Debug.WriteLine(e.Message);
+ }
+ }
+ //App.Log (LogType.Error, $"[MSBuild Unresolved]{assemblyName.Name}");
+ return null;
+ }
+ }
+
Assembly a = context.LoadFromAssemblyPath (assemblyPath);
- App.Log (LogType.Message, $"[MSBuildResolve]{a},{a.CodeBase}");
+ //App.Log (LogType.Message, $"[MSBuildResolve]{a},{a.CodeBase}");
return a;
+ /*string dotnetRoot = "/usr/share/dotnet";
+ string assemblyFile = Path.Combine (assemblyName.Name + ".dll");
+ foreach (string file in Directory.EnumerateFiles(dotnetRoot, assemblyFile, new EnumerationOptions { RecurseSubdirectories = true }))
+ {
+ try {
+
+ AssemblyName an = AssemblyName.GetAssemblyName(file);
+ if (an.ProcessorArchitecture != ProcessorArchitecture.Amd64)
+ continue;
+ if (string.Equals(an.ToString(), assemblyName.ToString())) {
+ Assembly a = context.LoadFromAssemblyPath (file);
+ App.Log (LogType.Message, $"[MSBuildResolve]{a},{a.CodeBase}");
+ return a;
+ }
+ } catch (Exception e) {
+ Debug.WriteLine(e.Message);
+ }
+
+ }
+ return null;*/
}
public override void Start() {
Environment.SetEnvironmentVariable ("MSBUILD_EXE_PATH", Path.Combine (MSBuildRoot, "MSBuild.dll"));
Environment.SetEnvironmentVariable ("MSBuildSDKsPath", Path.Combine (MSBuildRoot, "Sdks"));
+ Environment.SetEnvironmentVariable ("MSBuildExtensionsPath", Path.Combine (MSBuildRoot));
+ Environment.SetEnvironmentVariable ("MSBuildExtensionsPath32", Path.Combine (MSBuildRoot));
+ Environment.SetEnvironmentVariable ("MSBuildExtensionsPath64", Path.Combine (MSBuildRoot));
+ Environment.SetEnvironmentVariable ("MSBUILDUSESERVER", "0");
+ Environment.SetEnvironmentVariable ("DOTNET_HOST_PATH", @"/usr/share/dotnet/dotnet");
+
+
- if (Environment.OSVersion.Platform == PlatformID.Unix)
- Environment.SetEnvironmentVariable ("FrameworkPathOverride", "/usr/lib/mono/4.5/");
+ /*if (Environment.OSVersion.Platform == PlatformID.Unix)
+ Environment.SetEnvironmentVariable ("FrameworkPathOverride", "/usr/lib/mono/4.5/");*/
CurrentState = Status.Running;
using Project = CrowEditBase.Project;
+
+using System.Runtime.Loader;
+
namespace CERoslynPlugin
{
public class SolutionProject : Project {
RoslynService roslynService;
+
public SolutionProject (string fullPath) : base (fullPath) {
roslynService = App.GetService<RoslynService> ();
roslynService?.Start ();
Load();
- if (FlattenProjetcs.OfType<MSBuildProject>().Any (msb => msb.IsCrowProject)) {
+ /*if (FlattenProjetcs.OfType<MSBuildProject>().Any (msb => msb.IsCrowProject)) {
Console.WriteLine ("Is crow project!!");
- }
+ }*/
}
SolutionFile solutionFile;
if (ActiveConfiguration == value)
return;
UserConfig.Set ("ActiveConfiguration", value);
+ projectCollection.SetGlobalProperty ("Configuration", value);
NotifyValueChanged (value);
}
}
if (ActiveConfiguration == value)
return;
UserConfig.Set ("ActivePlatform", value);
+ projectCollection.SetGlobalProperty ("Platform", value);
NotifyValueChanged (value);
}
}
}
public override void Load () {
- //Dictionary<string,string> globalProperties = new Dictionary<string, string>();
- //globalProperties.Add ("Configuration", "Debug");
- projectCollection = new ProjectCollection (
- null,//globalProperties,
- new ILogger [] { roslynService.Logger },
- ToolsetDefinitionLocations.Default
- );
+ using (var ctx = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext (this.GetType().Assembly).EnterContextualReflection()) {
+
+ //Dictionary<string,string> globalProperties = new Dictionary<string, string>();
+ //globalProperties.Add ("Configuration", "Debug");
+ projectCollection = new ProjectCollection (
+ null,//globalProperties,
+ new ILogger [] { roslynService.Logger}, //new ConsoleLogger (Microsoft.Build.Framework.LoggerVerbosity.Diagnostic) },
+ ToolsetDefinitionLocations.Default
+ );
- solutionFile = SolutionFile.Parse (FullPath);
- UserConfig = new Configuration (FullPath + ".user");
+ solutionFile = SolutionFile.Parse (FullPath);
+ UserConfig = new Configuration (FullPath + ".user");
- //IDE.ProgressNotify (10);
+ //IDE.ProgressNotify (10);
- //projectCollection has to be recreated to change global properties
- if (string.IsNullOrEmpty (ActiveConfiguration))
- ActiveConfiguration = solutionFile.GetDefaultConfigurationName ();
- if (string.IsNullOrEmpty (ActivePlatform))
- ActivePlatform = solutionFile.GetDefaultPlatformName ();
+ //projectCollection has to be recreated to change global properties
+ if (string.IsNullOrEmpty (ActiveConfiguration))
+ ActiveConfiguration = solutionFile.GetDefaultConfigurationName ();
+ if (string.IsNullOrEmpty (ActivePlatform))
+ ActivePlatform = solutionFile.GetDefaultPlatformName ();
- projectCollection.SetGlobalProperty ("RestoreConfigFile", Path.Combine (
- Path.Combine (
- Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".nuget"), "NuGet"),
- "NuGet.Config"));
+ projectCollection.SetGlobalProperty ("RestoreConfigFile", Path.Combine (
+ Path.Combine (
+ Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.UserProfile), ".nuget"), "NuGet"),
+ "NuGet.Config"));
- projectCollection.SetGlobalProperty ("DefaultItemExcludes", "obj/**/*;bin/**/*");
+ projectCollection.SetGlobalProperty ("DefaultItemExcludes", "obj/**/*;bin/**/*");
- //projectCollection.SetGlobalProperty ("RoslynTargetsPath", Path.Combine(roslynService.MSBuildRoot, "Roslyn"));
+ projectCollection.SetGlobalProperty ("RoslynTargetsPath", Path.Combine(roslynService.MSBuildRoot, "Roslyn"));
+ //projectCollection.SetGlobalProperty ("NoWarn", "");
+
- //IDE.ProgressNotify (10);
+ //IDE.ProgressNotify (10);
- //ide.projectCollection.HostServices
- buildParams = new BuildParameters (projectCollection) {
- Loggers = projectCollection.Loggers,
- LogInitialPropertiesAndItems = true,
- LogTaskInputs = true,
- UseSynchronousLogging = true,
- ResetCaches = true,
- DetailedSummary = true
- };
+ //ide.projectCollection.HostServices
+ buildParams = new BuildParameters (projectCollection) {
+ Loggers = projectCollection.Loggers,
+ LogInitialPropertiesAndItems = true,
+ LogTaskInputs = true,
+ UseSynchronousLogging = true,
+ ResetCaches = true,
+ DetailedSummary = true
+ };
- //projectCollection.IsBuildEnabled = false;
+ //projectCollection.IsBuildEnabled = false;
- BuildManager.DefaultBuildManager.ResetCaches ();
+ BuildManager.DefaultBuildManager.ResetCaches ();
+ }
//IDE.ProgressNotify (10);
//ide.projectCollection.SetGlobalProperty ("RoslynTargetsPath", Path.Combine (Startup.msbuildRoot, @"Roslyn\"));
IsLoaded = true;
//Console.WriteLine (projectCollection.Get ("Configuration"));
- /*if (StartupProject is MSBuildProject msbProj)
- msbProj?.DesignBuild();*/
+ if (StartupProject is MSBuildProject msbProj)
+ msbProj?.DesignBuild();
}
void build (params string[] targets) {
--- /dev/null
+// Copyright (c) 2021-2021 Bruyère Jean-Philippe <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using CrowEditBase;
+
+namespace CERoslynPlugin
+{
+ public class CSRootSyntax : SyntaxRootNode {
+ public CSRootSyntax (SourceDocument source)
+ : base (source) {
+ }
+ }
+ public class CSSyntaxAnalyser : SyntaxAnalyser {
+ public override SyntaxNode Root => currentNode;
+ public CSSyntaxAnalyser (CSDocument source) : base (source) {
+ this.source = source;
+ }
+
+ public override void Process () {
+ Exceptions = new List<SyntaxException> ();
+ currentNode = new CSRootSyntax (source);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0"?>
+<DockWindow Caption="Roslyn Syntax Tree" Width="40%" Height="80%" DataSource="{CurrentSolution}" Background="DimGrey" >
+ <Container DataSource="{SelectedItem}">
+ <TreeView Name="treeview" IsRoot="true" DataSource="{RootNode}" Data="{GetChilNodesOrTokens}">
+ <ItemTemplate DataType="Microsoft.CodeAnalysis.SyntaxToken" >
+ <Border Style="TreeItemBorder" Focusable="true">
+ <HorizontalStack>
+ <Widget Width="5" Height="5"/>
+ <Label Style="TreeLabel" Foreground="White" Background="Jet" Text="{CSKind}" />
+ <Label Style="TreeLabel" Text="{}" Width="Stretched"/>
+ </HorizontalStack>
+ </Border>
+ </ItemTemplate>
+ <!--<ItemTemplate DataType="Microsoft.CodeAnalysis.SyntaxTrivia" >
+ <Border Style="TreeItemBorder" Focusable="true">
+ <HorizontalStack>
+ <Widget Width="5" Height="5"/>
+ <Label Style="TreeLabel" Foreground="Yellow" Background="Grey" Text="{CSKind}" />
+ <Label Style="TreeLabel" Text="{}" Width="Fit"/>
+ </HorizontalStack>
+ </Border>
+ </ItemTemplate>-->
+ <ItemTemplate DataType="Microsoft.CodeAnalysis.SyntaxTrivia" Data="GetStructureAsList">
+ <Expandable Caption="{}">
+ <Template>
+ <VerticalStack>
+ <Border Style="TreeItemBorder" Focusable="true">
+ <Group>
+ <HorizontalStack Spacing="5" MouseDoubleClick="./onClickForExpand">
+ <Image Margin="1" Width="9" Height="9" Focusable="true" MouseDown="./onClickForExpand" Path="{./Image}" Visible="{HasStructure}" SvgSub="{./IsExpanded}" MouseEnter="{Background=LightGrey}" MouseLeave="{Background=Transparent}" />
+ <Widget Width="10" Height="10" Background="Red" Visible="{IsPartOfStructuredTrivia}" />
+ <Label Style="TreeLabel" Foreground="Yellow" Background="Grey" Text="{CSKind}" />
+ <Label Style="TreeLabel" Text="{./Caption}" />
+ </HorizontalStack>
+ </Group>
+ </Border>
+ <Container Name="Content" Visible="false" />
+ </VerticalStack>
+ </Template>
+ <HorizontalStack Height="Fit">
+ <Widget Width="16" Height="10" />
+ <VerticalStack Height="Fit" Name="ItemsContainer" />
+ </HorizontalStack>
+ </Expandable>
+ </ItemTemplate>
+ <ItemTemplate DataType="Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode" Data="GetChilNodesOrTokens">
+ <Expandable Caption="{}">
+ <Template>
+ <VerticalStack>
+ <Border Style="TreeItemBorder" Focusable="true">
+ <Group>
+ <HorizontalStack Spacing="5" MouseDoubleClick="./onClickForExpand">
+ <Image Margin="1" Width="9" Height="9" Focusable="true" MouseDown="./onClickForExpand" Path="{./Image}" Visible="{./IsExpandable}" SvgSub="{./IsExpanded}" MouseEnter="{Background=LightGrey}" MouseLeave="{Background=Transparent}" />
+ <Label Style="TreeLabel" Foreground="SkyBlue" Text="{Kind}" />
+ <Label Style="TreeLabel" Text="{./Caption}" />
+ </HorizontalStack>
+ </Group>
+ </Border>
+ <Container Name="Content" Visible="false" />
+ </VerticalStack>
+ </Template>
+ <HorizontalStack Height="Fit">
+ <Widget Width="16" Height="10" />
+ <VerticalStack Height="Fit" Name="ItemsContainer" />
+ </HorizontalStack>
+ </Expandable>
+ </ItemTemplate>
+ </TreeView>
+ </Container>
+</DockWindow>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
- <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
+ <TargetFrameworks>net9</TargetFrameworks>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<Compile Include="src\**\*.cs" />
<EmbeddedResource Include="default.conf" />
</ItemGroup>
- <ItemGroup>
- <PackageReference Include="Enums.NET" Version="4.0.0" >
- <ExcludeAssets>runtime</ExcludeAssets>
- </PackageReference>
- </ItemGroup>
</Project>
-FileAssociations=CrowEdit.Xml.XmlDocument:.xml
\ No newline at end of file
+FileAssociations=CrowEdit.Xml.XmlDocument:.xml:#ui.sourceEditor.itmp
\ No newline at end of file
/*public virtual SyntaxNode Process (SyntaxNode startingNode) {
}*/
-
+ public virtual void ProcessAttributeValueSyntax(AttributeSyntax attrib) {
+ attrib.valueTok = tokIdx - attrib.TokenIndexBase;
+ }
public override void Process () {
XmlDocument xmlDoc = source as XmlDocument;
Exceptions = new List<SyntaxException> ();
- currentNode = new IMLRootSyntax (xmlDoc);
+ currentNode = new XMLRootSyntax (xmlDoc);
currentLine = 0;
Span<Token> toks = source.Tokens;
tokIdx = 0;
while (tokIdx < toks.Length) {
- Token curTok = toks[tokIdx];
+ curTok = toks[tokIdx];
if (curTok.Type == TokenType.LineBreak)
currentLine++;
else if (!curTok.Type.HasFlag (TokenType.Trivia)) {
} else if (curTok.GetTokenType() == XmlTokenType.ElementName)
tag.name = tokIdx - tag.TokenIndexBase;
else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
+ tag.close = tokIdx - tag.TokenIndexBase;
storeCurrentNode ();
currentNode.RemoveChild (tag);
currentNode = currentNode.AddChild (new ElementSyntax (tag));
else if (curTok.GetTokenType() == XmlTokenType.AttributeValueOpen)
attrib.valueOpen = tokIdx - attrib.TokenIndexBase;
else if (curTok.GetTokenType() == XmlTokenType.AttributeValue)
- attrib.valueTok = tokIdx - attrib.TokenIndexBase;
+ ProcessAttributeValueSyntax (attrib);
else if (curTok.GetTokenType() == XmlTokenType.AttributeValueClose) {
attrib.valueClose = tokIdx - attrib.TokenIndexBase;
storeCurrentNode ();
if (curTok.GetTokenType() == XmlTokenType.ElementName)
eltEndTag.name = tokIdx - eltEndTag.TokenIndexBase;
else if (curTok.GetTokenType() == XmlTokenType.ClosingSign) {
+ eltEndTag.close = tokIdx - eltEndTag.TokenIndexBase;
//go up 2 times
storeCurrentNode (); storeCurrentNode ();
} else {
storeCurrentNode (-1);
continue;
}
- } else if (currentNode is IMLRootSyntax) {
+ } else if (currentNode is XMLRootSyntax) {
switch (curTok.GetTokenType()) {
case XmlTokenType.ElementOpen:
currentNode = currentNode.AddChild (new ElementStartTagSyntax (currentLine, tokIdx));
if (curTok.GetTokenType() == XmlTokenType.PI_Target)
pi.name = tokIdx - pi.TokenIndexBase;
else if (curTok.GetTokenType() == XmlTokenType.PI_End) {
+ pi.PIClose = tokIdx - pi.TokenIndexBase;
storeCurrentNode ();
} else if (curTok.GetTokenType() == XmlTokenType.AttributeName) {
AttributeSyntax attribute = new AttributeSyntax (currentLine, tokIdx);
namespace CrowEdit.Xml
{
- public class IMLRootSyntax : SyntaxRootNode {
- public IMLRootSyntax (XmlDocument source)
+ public class XMLRootSyntax : SyntaxRootNode {
+ public XMLRootSyntax (XmlDocument source)
: base (source) {
}
}
public class ProcessingInstructionSyntax : SyntaxNode {
- internal int? PIOpen, PIClose, name;
- public override bool IsComplete => base.IsComplete & name.HasValue & PIOpen.HasValue & PIClose.HasValue;
+ public int? PIClose, name;
+ public override bool IsComplete => base.IsComplete & name.HasValue & PIClose.HasValue;
public ProcessingInstructionSyntax (int startLine, int tokenBase)
: base (startLine, tokenBase) {
}
}
public abstract class ElementTagSyntax : SyntaxNode {
- internal int? name, close;
+ public int? name, close;
public override bool IsComplete => base.IsComplete & name.HasValue & close.HasValue;
public string Name => Root.GetTokenStringByIndex (TokenIndexBase + name.Value);
protected ElementTagSyntax (int startLine, int tokenBase)
public class ElementSyntax : SyntaxNode {
public readonly ElementStartTagSyntax StartTag;
- public ElementEndTagSyntax EndTag { get; internal set; }
+ public ElementEndTagSyntax EndTag { get; set; }
public override bool IsComplete => base.IsComplete & StartTag.IsComplete & (EndTag != null && EndTag.IsComplete);
}
public class AttributeSyntax : SyntaxNode {
- internal int? name, equal, valueOpen, valueClose, valueTok;
- /*public Token? NameToken => name.HasValue ? getTokenByIndex (TokenIndexBase + name.Value) : default;
- public int? EqualToken { get; internal set; }
- public int? ValueOpenToken { get; internal set; }
- public int? ValueCloseToken { get; internal set; }
- public int? ValueToken { get; internal set; }*/
+ public int? name, equal, valueOpen, valueClose, valueTok;
public string Name => name.HasValue ? Root.GetTokenStringByIndex (TokenIndexBase + name.Value) : null;
public string Value => valueTok.HasValue ? Root.GetTokenStringByIndex (TokenIndexBase + valueTok.Value) : null;
public Token? ValueToken => valueTok.HasValue ? Root.GetTokenByIndex (TokenIndexBase + valueTok.Value) : null;
bool readName (ref SpanCharReader reader) {
if (reader.EndOfSpan)
return false;
- char c = reader.Peak;
+ char c = reader.Peek;
if (char.IsLetter(c) || c == '_' || c == ':') {
reader.Advance ();
- while (reader.TryPeak (ref c)) {
+ while (reader.TryPeek (ref c)) {
if (!(char.IsLetterOrDigit(c) || c == '.' || c == '-' || c == '\xB7'))
return true;
reader.Advance ();
addTok (ref reader, XmlTokenType.LineBreak);
continue;
}
- if (reader.TryPeak ('<')) {
+ if (reader.TryPeek ('<')) {
addTok (ref reader, XmlTokenType.AttributeValue);
return;
}
- if (reader.TryPeak (q)) {
+ if (reader.TryPeek (q)) {
addTok (ref reader, XmlTokenType.AttributeValue);
reader.Advance (1);
addTok (ref reader, XmlTokenType.AttributeValueClose);
if (reader.EndOfSpan)
break;
- switch (reader.Peak) {
+ switch (reader.Peek) {
case '<':
reader.Advance ();
- if (reader.TryPeak ('?')) {
+ if (reader.TryPeek ('?')) {
reader.Advance ();
addTok (ref reader, XmlTokenType.PI_Start);
readName (ref reader);
addTok (ref reader, XmlTokenType.PI_Target);
curState = States.ProcessingInstrucitons;
- } else if (reader.TryPeak ('!')) {
+ } else if (reader.TryPeek ('!')) {
reader.Advance ();
- if (reader.TryPeak ("--")) {
+ if (reader.TryPeek ("--")) {
reader.Advance (2);
addTok (ref reader, XmlTokenType.BlockCommentStart);
while (!reader.EndOfSpan) {
addTok (ref reader, XmlTokenType.LineBreak);
continue;
}
- if (reader.TryPeak ("-->")) {
+ if (reader.TryPeek ("-->")) {
addTok (ref reader, XmlTokenType.BlockComment);
reader.Advance (3);
addTok (ref reader, XmlTokenType.BlockCommentEnd);
curState = States.DTDObject;
}
}
- } else if (reader.TryPeak('/')) {
+ } else if (reader.TryPeek('/')) {
reader.Advance ();
addTok (ref reader, XmlTokenType.EndElementOpen);
if (readName (ref reader)) {
addTok (ref reader, XmlTokenType.ElementName);
- if (reader.TryPeak('>')) {
+ if (reader.TryPeek('>')) {
reader.Advance ();
addTok (ref reader, XmlTokenType.ClosingSign);
break;
case '?':
reader.Advance ();
- if (reader.TryPeak ('>')){
+ if (reader.TryPeek ('>')){
reader.Advance ();
addTok (ref reader, XmlTokenType.PI_End);
}else
break;
case '/':
reader.Advance();
- if (reader.TryPeak ('>')) {
+ if (reader.TryPeek ('>')) {
reader.Advance();
addTok (ref reader, XmlTokenType.EmptyElementClosing);
if (--curObjectLevel > 0)
addTok (ref reader, XmlTokenType.LineBreak);
continue;
}
- if (reader.TryPeak ("<")) {
+ if (reader.TryPeek ("<")) {
addTok (ref reader, XmlTokenType.Content);
break;
} else
<SolutionDir>$(MSBuildThisFileDirectory)..\</SolutionDir>
<License>MIT</License>
<Authors>Jean-Philippe Bruyère</Authors>
- <LangVersion>7.2</LangVersion>
+ <EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
-
<ItemGroup>
<ProjectReference Include="$(SolutionDir)CrowEditBase\CrowEditBase.csproj" />
</ItemGroup>
-
-
</Project>
<DestinationFolder>$(SolutionDir)build\plugins\</DestinationFolder>
</PropertyGroup>
<Target Name="AfterBuild">
- <MakeDir Directories="$(DestinationFolder)$(ProjectName)\"/>
+ <MakeDir Directories="$(DestinationFolder)\"/>
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(DestinationFolder)$(ProjectName)\" ContinueOnError="true" />
+ <Copy SourceFiles="$(ProjectDir)$(OutputPath)$(TargetName).pdb" DestinationFolder="$(DestinationFolder)$(ProjectName)\" ContinueOnError="true" />
</Target>
</Project>
-// Copyright (c) 2013-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+// Copyright (c) 2013-2025 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
DbgEvtType.WidgetMouseClick,
DbgEvtType.HoverWidget
});*/
-
- CrowEdit.CrowAssemblyNames = new string[] {"CrowEditBase"};
using (CrowEdit app = new CrowEdit ())
app.Run ();
}
- public CrowEdit () : base (Configuration.Global.Get<int>("MainWinWidth", 800), Configuration.Global.Get<int>("MainWinHeight", 600)) {
-
+ public CrowEdit () : base (Configuration.Global.Get<int>("MainWinWidth", 800), Configuration.Global.Get<int>("MainWinHeight", 600), true) {
}
public override void ProcessResize(Rectangle bounds)
reloadWinConfigs ();
+ foreach (Service service in Services) {
+ if (TryGetWindow (service.ConfigurationWindowPath, out Window win))
+ win.DataSource = service;
+ }
+
+ reloadLogsConfigs ();
+
reopenLastProjectList ();
reopenLastDocumentList ();
{
saveProjectList ();
saveOpenedDocumentList ();
+ saveLogsConfig ();
saveWinConfigs ();
}
DockStack mainDock;
);
}
-
static void loadWindowWithThisDataSource(object sender, string path) {
Widget w = sender as Widget;
CrowEdit e = w.IFace as CrowEdit;
Configuration.Global.Save ();
}
-
void reloadWinConfigs() {
if (Configuration.Global.TryGet<string>("WinConfigs", out string conf) && !string.IsNullOrEmpty(conf))
for (int i = 0; i < floatings.Length; i++)
DockWindow.CreateFromFloatingConfigString (this, floatings[i], this);
}
-
}
+ void reloadLogsConfigs() {
+
+ if (Configuration.Global.TryGet<string>("OpenedLogs", out string conf) && !string.IsNullOrEmpty(conf)) {
+ string[] logs = conf.Split ('|');
+ for (int i = 0; i < logs.Length; i++)
+ App.GetLog(logs[i]).IsOpened = true;
+ if (Configuration.Global.TryGet<string>("CurrentLog", out string curLog) && !string.IsNullOrEmpty(curLog))
+ App.GetLog(curLog).IsSelected = true;
+ }
+ }
+ void saveLogsConfig() {
+ lock (OpenedLogs) {
+ string openLogs = OpenedLogs.Count > 0 ?
+ OpenedLogs.Select(li=>li.Name).Aggregate((a,b) => a + "|" + b) : null;
+ Configuration.Global.Set("OpenedLogs", openLogs);
+ Configuration.Global.Set("CurrentLog", CurrentLog?.Name);
+ }
+ }
protected override Document openOrCreateFile (string filePath, string editorPath = null) {
Document doc = null;
CurrentDocument = doc;
} catch (Exception ex) {
MessageBox.ShowModal (this, MessageBox.Type.Alert, $"Unable to open {filePath}.\n{ex.Message}");
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine (ex);
- Console.ResetColor();
+ Log(LogType.Error, $"Unable to open {filePath}.\n{ex.Message}");
}
return doc;
}
if (prj != null)
CurrentProject = prj;
}
-
- }
+ public override Stream GetStreamFromPath(string path)
+ {
+ return base.GetStreamFromPath(path);
+ }
+ }
}
Unselected="{.DataSource.IsVisible='false'};{Background=${InactiveTabBackground}};{Foreground=${InactiveTabForeground}}"
BubbleEvents="MouseWheel">
<HorizontalStack DataSource="{DataSource}" Margin="3" Spacing="5">
-
+ <!--<Image Style="TreeIcon" Path="{Icon}" SvgSub="{IconSub}"/> No icon in Document class-->
+ <Label Text="{FileName}" Tooltip="{FullPath}" ContextCommands="{TabCommands}" Foreground="{../../Foreground}" Margin="3" />
<Widget Width="10" Height="10" Background="RoyalBlue" IsVisible="{IsDirty}"/>
- <Label Text="{FileName}" Tooltip="{FullPath}" ContextCommands="{TabCommands}" Foreground="{../../Foreground}" />
<Border CornerRadius="5" BorderWidth="1" Foreground="Transparent" Height="12" Width="12"
MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}">
<Image Focusable="true" Name="Image" Margin="0" Width="Stretched" Height="Stretched" Path="#Crow.Icons.exit2.svg"
ContextCommands="{GetCommands}"
Selected="{Background=${ControlHighlight}}"
Unselected="{Background=Transparent}">
- <HorizontalStack>
- <Image Margin="1" Width="14" Height="14" Path="#Crow.Icons.file.svg"/>
- <Label Text="{Name}" Width="Stretched"/>
- </HorizontalStack>
+ <Border CornerRadius="2" Margin="0" Height="Fit"
+ Foreground="Transparent"
+ MouseEnter="{Foreground=DimGrey}"
+ MouseLeave="{Foreground=Transparent}">
+ <HorizontalStack>
+ <Image Margin="1" Width="14" Height="14" Path="#Crow.Icons.file.svg"/>
+ <Label Text="{Name}" Width="Stretched"/>
+ </HorizontalStack>
+ </Border>
</ListItem>
</ItemTemplate>
<ItemTemplate DataType="System.IO.DirectoryInfo" Data="GetFileSystemInfosOrdered">
<?xml version="1.0"?>
-<DockWindow Style="DockWindow2" Caption="Logs" Width="80%" >
- <VerticalStack RootDataLevel="true" >
- <HorizontalStack Height="Fit" Spacing="2" Margin="1">
- <Label Text="{../../../Caption}" Fit="true" Foreground="DimGrey" Font="${SmallUIFont}"/>
- <Widget Width="Stretched"/>
- <EnumSelector Caption="Filter:" EnumValue="{²../../log.Filter}" />
- <TextBox Background="Grey" Foreground="Black" MinimumSize="100,1" Text="{²../../log.SearchString}" Width="40%" KeyDown="../../log.onSearch" Font="${SmallUIFont}"/>
- <CheckBox Fit="true" Caption="Case Sensitive" IsChecked="{²../../log.CaseSensitiveSearch}" Font="${SmallUIFont}"/>
- <CheckBox Fit="true" Caption="All Word" IsChecked="{²../../log.AllWordSearch}" Font="${SmallUIFont}"/>
+<DockWindow Style="DockWindow" Caption="Logs" Width="80%" >
+ <VerticalStack>
- <Menu Style="DockWinTitleBarMenu" Data="{../../log.SearchCommands}" Fit="true" Background="Transparent"/>
-
- <ListBox Style="DockWinTitleBarIconMenu" Data="{./DockCommands}"/>
- <ListBox Style="DockWinTitleBarIconMenu" Data="{./Commands}"/>
- <!--<ListBox Data="{./DockCommands}" Fit="true">
- <Template>
- <HorizontalStack Name="ItemsContainer" />
- </Template>
- <ItemTemplate Path="#Crow.WindowButton.template"/>
- </ListBox>
- <ListBox Data="{./Commands}" Fit="true">
- <Template>
- <HorizontalStack Name="ItemsContainer" />
- </Template>
- <ItemTemplate Path="#Crow.WindowButton.template"/>
- </ListBox>-->
- </HorizontalStack>
- <HorizontalStack Spacing="0">
- <LogViewerWidget Name="log" Lines="{MainLog}" Font="${SmallFont}" MaxScrollX="3000"/>
- <ScrollBar Name="scrollbarY" Value="{²../log.ScrollY}" CursorRatio="{../log.ChildHeightRatio}" Maximum="{../log.MaxScrollY}" />
- </HorizontalStack>
- <ScrollBar Style="HScrollBar" Name="scrollbarX" Value="{²../log.ScrollX}" Maximum="{../log.MaxScrollX}" SmallIncrement="30"/>
+ <TabView Data="{OpenedLogs}" SelectedItem="{²CurrentLog}">
+ <Template>
+ <VerticalStack Spacing="0" >
+ <HorizontalStack Height="Fit">
+ <ListBox Data="{./Items}" >
+ <Template>
+ <VerticalStack Spacing="0" >
+ <ScrollBar Orientation="Horizontal" Foreground="RoyalBlue" Height="6" Width="Stretched" CornerRadius="3"
+ Value="{²../ItemsScroller.ScrollX}"
+ LargeIncrement="{../ItemsScroller.PageWidth}" SmallIncrement="1"
+ CursorRatio="{../ItemsScroller.ChildWidthRatio}" Maximum="{../ItemsScroller.MaxScrollX}">
+ <Template>
+ <Container Margin="1" Background="{./Background}">
+ <Widget Name="Cursor" Background="{./Foreground}" CornerRadius="{./CornerRadius}"/>
+ </Container>
+ </Template>
+ </ScrollBar>
+ <Scroller Name="ItemsScroller" Height="Fit" Width="Stretched">
+ <HorizontalStack Name="ItemsContainer" Width="Fit" HorizontalAlignment="Left"/>
+ </Scroller>
+ </VerticalStack>
+ </Template>
+ <ItemTemplate>
+ <ListItem RootDataLevel="true" Fit="true" Background="${InactiveTabBackground}" Foreground="${InactiveTabForeground}" IsSelected="{IsVisible}"
+ Selected="{.DataSource.IsVisible='true'};{Background=${SelectedTabBackground}};{Foreground=${SelectedTabForeground}}"
+ Unselected="{.DataSource.IsVisible='false'};{Background=${InactiveTabBackground}};{Foreground=${InactiveTabForeground}}"
+ BubbleEvents="MouseWheel">
+ <HorizontalStack DataSource="{DataSource}" Margin="3" Spacing="5">
+ <!--<Image Style="TreeIcon" Path="{Icon}" SvgSub="{IconSub}"/> No icon in Document class-->
+ <Label Text="{Name}" ContextCommands="{TabCommands}" Foreground="{../../Foreground}" />
+ <Border CornerRadius="5" BorderWidth="1" Foreground="Transparent" Height="12" Width="12"
+ MouseEnter="{Foreground=White}" MouseLeave="{Foreground=Transparent}">
+ <Image Focusable="true" Name="Image" Margin="0" Width="Stretched" Height="Stretched" Path="#Crow.Icons.exit2.svg"
+ MouseClick="OnQueryClose"/>
+ </Border>
+ </HorizontalStack>
+ </ListItem>
+ </ItemTemplate>
+ </ListBox>
+ <Popper Caption="Available Logs">
+ <ListBox Data="{Logs}" Style="ScrollingListBox" Height="100" Width="200" Background="Jet" BubbleEvents="none" >
+ <ItemTemplate>
+ <Border CornerRadius="2" Margin="0" Height="Fit"
+ Foreground="Transparent"
+ MouseEnter="{Foreground=DimGrey}"
+ MouseLeave="{Foreground=Transparent}">
+ <CheckBox Caption="{Name}" Width="Stretched" IsChecked="{²IsOpened}"/>
+ </Border>
+ </ItemTemplate>
+ </ListBox>
+ </Popper>
+ </HorizontalStack>
+ <Group Name="ItemsContainer" Background="${SelectedTabBackground}"/>
+ </VerticalStack>
+ </Template>
+ <ItemTemplate>
+ <ListItem IsVisible="{IsSelected}" IsSelected="{²IsSelected}">
+ <VerticalStack RootDataLevel="true" >
+ <HorizontalStack Height="Fit" Spacing="5" Margin="0">
+ <Widget Width="Stretched"/>
+ <EnumSelector Caption="Filter:" EnumValue="{²../../log.Filter}" />
+ <TextBox Background="Grey" Foreground="Black" Text="{²../../log.SearchString}" Width="200" KeyDown="../../log.onSearch" Font="${SmallUIFont}"/>
+ <CheckBox Fit="true" Caption="Case Sensitive" IsChecked="{²../../log.CaseSensitiveSearch}" Font="${SmallUIFont}"/>
+ <CheckBox Fit="true" Caption="All Word" IsChecked="{²../../log.AllWordSearch}" Font="${SmallUIFont}"/>
+ <Menu Style="DockWinTitleBarMenu" Data="{../../log.SearchCommands}" Fit="true" Background="Transparent"/>
+ </HorizontalStack>
+ <HorizontalStack Spacing="0">
+ <LogViewerWidget Name="log" Logger="{}" Font="${SmallFont}" MaxScrollX="6000" ContextCommands="{Commands}" CurrentEntryIndex="{²SelectedIndex}"/>
+ <ScrollBar Name="scrollbarY" Value="{²../log.ScrollY}" CursorRatio="{../log.ChildHeightRatio}" Maximum="{../log.MaxScrollY}" />
+ </HorizontalStack>
+ <ScrollBar Style="HScrollBar" Name="scrollbarX" Value="{²../log.ScrollX}" Maximum="{../log.MaxScrollX}" SmallIncrement="30"/>
+ <HorizontalStack Height="Fit">
+ <Label Text="MaxScrollY:"/>
+ <Label Text="{../../log.MaxScrollY}"/>
+ <Label Text="ScrollY:"/>
+ <Label Text="{../../log.ScrollY}"/>
+ </HorizontalStack>
+ </VerticalStack>
+ </ListItem>
+ </ItemTemplate>
+ </TabView>
</VerticalStack>
</DockWindow>
<VerticalStack Margin="5">
<Label Fit="true" Text="Plugins directory path:"/>
<HorizontalStack Height="Fit">
- <TextBox Height="Fit" Text="{²PluginsDirecory}" Margin="2"/>
+ <TextBox Height="Fit" Text="{²PluginsDirectory}" Margin="2"/>
<Button Command="{CMDOptions_SelectPluginsDirectory}" MinimumSize="0,0"/>
<Button Command="{CMDOptions_ResetPluginsDirectory}" MinimumSize="0,0"/>
</HorizontalStack>
<ListBox Data="{Plugins}" Height="50%">
<ItemTemplate>
- <HorizontalStack Height="Fit">
- <Label Text="{Name}" Width="Stretched"/>
- <ListBox Data="{Commands}" Fit="true">
- <Template>
- <HorizontalStack Name="ItemsContainer" />
- </Template>
- <ItemTemplate Path="#ui.IconCommand.itmp"/>
- </ListBox>
- </HorizontalStack>
+ <ListItem CornerRadius="2" Margin="0" Height="Fit" Width="Stretched"
+ Selected="{Background=${ControlHighlight}}"
+ Unselected="{Background=Transparent}">
+ <HorizontalStack Height="Fit" Spacing="10" ContextCommands="{Commands}">
+ <Border Width="30" Height="20" Background='{ColorStatus}' Margin='1' BorderWidth="2" Foreground="White" CornerRadius="2"/>
+ <Label Text="{Name}" Width="Stretched"/>
+ <ListBox Data="{Commands}" Fit="true">
+ <Template>
+ <HorizontalStack Name="ItemsContainer" />
+ </Template>
+ <ItemTemplate Path="#ui.IconCommand.itmp"/>
+ </ListBox>
+ </HorizontalStack>
+ </ListItem>
</ItemTemplate>
</ListBox>
<Splitter/>
<Label Style="TreeLabel" Text="{IsComplete}"/>
<Label Style="TreeLabel" Text="span:"/>
<Label Style="TreeLabel" Text="{Span}"/>
+ <Label Style="TreeLabel" Text="foldable:"/>
+ <Label Style="TreeLabel" Text="{IsFoldable}"/>
</HorizontalStack>
</Border>
<Container Name="Content" Visible="false"/>