]> O.S.I.I.S - jp/crowedit.git/commitdiff
wip
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 22 Feb 2025 08:17:04 +0000 (09:17 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 22 Feb 2025 08:17:04 +0000 (09:17 +0100)
99 files changed:
.gitignore
CrowEdit.csproj
CrowEdit.sln
CrowEditBase/CrowEditBase.csproj
CrowEditBase/icons/debug-bug.svg [new file with mode: 0644]
CrowEditBase/icons/debug-pause.svg [new file with mode: 0644]
CrowEditBase/icons/debug-play.svg [new file with mode: 0644]
CrowEditBase/icons/debug-step-into.svg [new file with mode: 0644]
CrowEditBase/icons/debug-step-out.svg [new file with mode: 0644]
CrowEditBase/icons/debug-step-over.svg [new file with mode: 0644]
CrowEditBase/icons/debug-stop.svg [new file with mode: 0644]
CrowEditBase/icons/file-cube.svg [new file with mode: 0644]
CrowEditBase/src/Compiler/SourceDocument.cs
CrowEditBase/src/Compiler/SyntaxAnalyser.cs
CrowEditBase/src/Compiler/SyntaxNode.cs
CrowEditBase/src/Compiler/Token.cs
CrowEditBase/src/Compiler/Tokenizer.cs
CrowEditBase/src/CrowEditBase.cs
CrowEditBase/src/Debug/Debugger.cs
CrowEditBase/src/Document.cs
CrowEditBase/src/Editor.cs
CrowEditBase/src/LogViewerWidget.cs
CrowEditBase/src/Logger.cs [new file with mode: 0644]
CrowEditBase/src/Plugin.cs
CrowEditBase/src/PluginsLoadContext.cs
CrowEditBase/src/Service.cs
CrowEditBase/src/SourceEditor.cs
CrowEditBase/src/TextDocument.cs
CrowEditBase/ui/CrowEdit.style
CrowEditBase/ui/DockWinTitleBarMenu.itemp
CrowEditBase/ui/DockWindow.template
CrowEditBase/ui/IcoBut.template
CrowEditBase/ui/MenuButton.template
CrowEditBase/ui/MenuItem.itmp
CrowEditBase/ui/MenuItem.template
CrowEditBase/ui/sourceEditor.itmp
plugins/CECrowPlugin/CECrowPlugin.csproj
plugins/CECrowPlugin/src/CrowService.cs
plugins/CECrowPlugin/src/DbgLogViewer.cs
plugins/CECrowPlugin/src/DebugInterface.cs
plugins/CECrowPlugin/src/DebugInterfaceWidget.cs
plugins/CECrowPlugin/src/ImlDocument.cs
plugins/CECrowPlugin/src/Parsing/IML/ImlTokenType.cs
plugins/CECrowPlugin/src/Parsing/IML/ImlTokenizer.cs
plugins/CECrowPlugin/src/Parsing/IML/SyntaxAnalyser.cs [new file with mode: 0644]
plugins/CECrowPlugin/src/Parsing/IML/SyntaxNodes.cs [new file with mode: 0644]
plugins/CECrowPlugin/src/Parsing/Styling/StyleTokenizer.cs
plugins/CECrowPlugin/ui/winConfiguration.crow
plugins/CEEbnfPlugin/CEEbnfPlugin.csproj [new file with mode: 0644]
plugins/CEEbnfPlugin/default.conf [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/CharRange.cs [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/EbnfDocument.cs [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/EbnfSyntaxAnalyser.cs [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/EbnfTokenType.cs [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/EbnfTokenizer.cs [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/Expression.cs [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/ParserException.cs [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/SymbolDecl.cs [new file with mode: 0644]
plugins/CEEbnfPlugin/src/Parsing/SyntaxNodes.cs [new file with mode: 0644]
plugins/CENetcoreDbgPlugin/CENetcoreDbgPlugin.csproj
plugins/CENetcoreDbgPlugin/src/NetcoreDbgService.cs
plugins/CENetcoreDbgPlugin/src/NetcoredbgDebugger.cs
plugins/CENetcoreDbgPlugin/ui/winBreakPoints.crow [new file with mode: 0644]
plugins/CENetcoreDbgPlugin/ui/winDebugging.crow
plugins/CENetcoreDbgPlugin/ui/winStackFrames.crow [new file with mode: 0644]
plugins/CENetcoreDbgPlugin/ui/winThreads.crow [new file with mode: 0644]
plugins/CENetcoreDbgPlugin/ui/winWatches.crow [new file with mode: 0644]
plugins/CENugetPlugin/CENugetPlugin.csproj [new file with mode: 0644]
plugins/CENugetPlugin/default.conf [new file with mode: 0644]
plugins/CENugetPlugin/src/Extensions.cs [new file with mode: 0644]
plugins/CENugetPlugin/src/NugetService.cs [new file with mode: 0644]
plugins/CENugetPlugin/ui/winConfiguration.crow [new file with mode: 0644]
plugins/CENugetPlugin/ui/winNugetExplorer.crow [new file with mode: 0644]
plugins/CERoslynPlugin/CERoslynPlugin.csproj
plugins/CERoslynPlugin/default.conf
plugins/CERoslynPlugin/src/CELogger.cs
plugins/CERoslynPlugin/src/CSDocument.cs
plugins/CERoslynPlugin/src/CSTokenType.cs [new file with mode: 0644]
plugins/CERoslynPlugin/src/CSTokenizer.cs
plugins/CERoslynPlugin/src/ConsoleLogger.cs
plugins/CERoslynPlugin/src/MSBuildProject.cs
plugins/CERoslynPlugin/src/ProjectTree/ProjectItemNodes.cs
plugins/CERoslynPlugin/src/RoslynService.cs
plugins/CERoslynPlugin/src/SolutionProject.cs
plugins/CERoslynPlugin/src/SyntaxAnalyser.cs [new file with mode: 0644]
plugins/CERoslynPlugin/ui/winSyntaxTree.crow [new file with mode: 0644]
plugins/CEXmlPlugin/CEXmlPlugin.csproj
plugins/CEXmlPlugin/default.conf
plugins/CEXmlPlugin/src/Parsing/SyntaxAnalyser.cs
plugins/CEXmlPlugin/src/Parsing/SyntaxNodes.cs
plugins/CEXmlPlugin/src/Parsing/XmlTokenizer.cs
plugins/Directory.Build.props
plugins/Directory.Build.targets
src/CrowEdit.cs
ui/windows/winEditor.crow
ui/windows/winFileExplorer.crow
ui/windows/winLogs.crow
ui/windows/winPlugins.crow
ui/windows/winSyntaxExplorer.crow

index 69b037a4cfc18f967ac49069e14a81f8c03d676b..78de650055006945b2245bc828959d3e61e5fc1d 100644 (file)
@@ -1,3 +1,5 @@
+CrowDesignAssembly/
+netcoredbg/
 #Autosave files
 *~
 
index 4132a1d5a15d3deaff56bffb30fb76da535ad7a2..9415782d393f7f53a22ac1588866d1b6490c17ed 100644 (file)
@@ -1,6 +1,6 @@
 <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>
index 7f96d42b919114daf8746aba475da4068ddb2731..db0e9fbc3bcf720cd4edf618a26805bf5adbba7a 100644 (file)
@@ -25,6 +25,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CEXmlPlugin", "plugins\CEXm
 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
@@ -59,6 +65,18 @@ Global
                {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
@@ -68,6 +86,8 @@ Global
                {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}
index 0ba3dc6686a887b9c6e27c2918693fd016c0c865..569c244f9a9d685013d33d5b1f90132267882262 100644 (file)
@@ -1,7 +1,7 @@
 <?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>
diff --git a/CrowEditBase/icons/debug-bug.svg b/CrowEditBase/icons/debug-bug.svg
new file mode 100644 (file)
index 0000000..8c73946
--- /dev/null
@@ -0,0 +1,8 @@
+<?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>
diff --git a/CrowEditBase/icons/debug-pause.svg b/CrowEditBase/icons/debug-pause.svg
new file mode 100644 (file)
index 0000000..33f4c86
--- /dev/null
@@ -0,0 +1,7 @@
+<?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>
diff --git a/CrowEditBase/icons/debug-play.svg b/CrowEditBase/icons/debug-play.svg
new file mode 100644 (file)
index 0000000..91ee85d
--- /dev/null
@@ -0,0 +1,6 @@
+<?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>
diff --git a/CrowEditBase/icons/debug-step-into.svg b/CrowEditBase/icons/debug-step-into.svg
new file mode 100644 (file)
index 0000000..f60dbf4
--- /dev/null
@@ -0,0 +1 @@
+<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
diff --git a/CrowEditBase/icons/debug-step-out.svg b/CrowEditBase/icons/debug-step-out.svg
new file mode 100644 (file)
index 0000000..8d052bf
--- /dev/null
@@ -0,0 +1 @@
+<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
diff --git a/CrowEditBase/icons/debug-step-over.svg b/CrowEditBase/icons/debug-step-over.svg
new file mode 100644 (file)
index 0000000..6deaf2a
--- /dev/null
@@ -0,0 +1 @@
+<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
diff --git a/CrowEditBase/icons/debug-stop.svg b/CrowEditBase/icons/debug-stop.svg
new file mode 100644 (file)
index 0000000..27d810a
--- /dev/null
@@ -0,0 +1,6 @@
+<?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>
diff --git a/CrowEditBase/icons/file-cube.svg b/CrowEditBase/icons/file-cube.svg
new file mode 100644 (file)
index 0000000..6df0f4a
--- /dev/null
@@ -0,0 +1,6 @@
+<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
index 40b0773e27caadb0513cc99446c941504de12b8f..6a28378c5eb3aa62bfcdc40d7215ee24290ce523 100644 (file)
@@ -95,7 +95,14 @@ namespace CrowEditBase
                        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));
 
@@ -137,6 +144,8 @@ namespace CrowEditBase
                                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;
@@ -153,6 +162,7 @@ namespace CrowEditBase
                                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);
@@ -168,17 +178,20 @@ namespace CrowEditBase
                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()}");
index 371a8f370d3167fb722aded3864cd701e278ed9d..dcac0eb560e939041053bf8e3feef0f78a9ce848 100644 (file)
@@ -22,6 +22,7 @@ namespace CrowEditBase
                        this.source = source;
                }
                public abstract void Process ();
+               protected Token curTok;
                protected SyntaxNode currentNode;
                protected int currentLine, tokIdx;
 
@@ -37,5 +38,8 @@ namespace CrowEditBase
                }
                protected void setCurrentNodeEndLine (int endLine)
                        => currentNode.EndLine = endLine;
+
+
+               //bool EOF => tokIdx == tokens.Length;
        }
 }
\ No newline at end of file
index a771f8db3fd18eb9da4e253b2d82066cf03404c4..4f10b435e5086d00e520365bfd9f10b138ae43ab 100644 (file)
@@ -44,7 +44,7 @@ namespace CrowEditBase
                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;
index a1a86d0110623b7d1a9be775762b64bc7af04688..7f117215946353b748bc61afae4a06b1f692e637 100644 (file)
@@ -16,7 +16,8 @@ namespace CrowEditBase
                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;
index 80b9d24148ed326f7c6e785c216af9ca19c63d7e..b62d05c64c9b1788f2976f9dff1c2d28a706fbb4 100644 (file)
@@ -41,7 +41,7 @@ namespace CrowEditBase
                }
                protected virtual void skipWhiteSpaces (ref SpanCharReader reader) {
                        while(!reader.EndOfSpan) {
-                               switch (reader.Peak) {
+                               switch (reader.Peek) {
                                        case '\x85':
                                        case '\x2028':
                                        case '\xA':
@@ -57,7 +57,7 @@ namespace CrowEditBase
                                        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;
index d18e5a5aef67ea2efa041f1f6fa7397dc1b66e5e..fc8086962dc4ae7c58c902bba65a9f9802e163f8 100644 (file)
@@ -15,20 +15,78 @@ using Drawing2D;
 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> ());
@@ -55,14 +113,9 @@ namespace CrowEditBase
                        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;
@@ -179,13 +232,13 @@ namespace CrowEditBase
                                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 {
@@ -270,7 +323,7 @@ namespace CrowEditBase
                                g.DataSource = dataSource;
                                return g as Window;
                        } catch (Exception ex) {
-                               Console.WriteLine (ex.ToString ());
+                               Log (LogType.Error, ex.ToString ());
                        }
                        return null;
                }
@@ -287,72 +340,84 @@ namespace CrowEditBase
                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 {
@@ -441,6 +506,6 @@ namespace CrowEditBase
                        }
                }
 
-#endregion
+               #endregion
        }
 }
\ No newline at end of file
index 3fe227aa6504477b2fc09da6cdf33f75145a4691..221c5d8dc59321fcce399301f79079a0be95895d 100644 (file)
@@ -19,6 +19,8 @@ namespace CrowEditBase
                        Ready,
                        /// <summary>running state received</summary>
                        Running,
+                       /// <summary> abort requested </summary>
+                       Stopping,
                        /// <summary>stopped event received</summary>
                        Stopped,
                }
@@ -28,12 +30,12 @@ namespace CrowEditBase
                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);
                }
 
 
@@ -47,12 +49,16 @@ namespace CrowEditBase
                        {
                                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;
@@ -80,6 +86,7 @@ namespace CrowEditBase
                                        return;
                                currentThread = value;
                                NotifyValueChanged(currentThread);
+                               onCurrentThreadChanged();
                        }
                }
                public StackFrame CurrentFrame
index 5aa101cf51231d4b8064f933682f07822afe5371..56ef87845e104a4d94c25593c95d847c73ad31bd 100644 (file)
@@ -63,9 +63,11 @@ namespace CrowEditBase
                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 () {
index f00adfbf4edc5cbf3002081103dece7b1387667c..a9bbb771cdac3192b92065ad8063bf0cc0a98a3a 100644 (file)
@@ -338,8 +338,7 @@ namespace Crow
                                                        selStart = selectionStart.Value;
                                                        selEnd = CurrentLoc.Value;
                                                }
-                                       } else
-                                               IFace.forceTextCursor = true;
+                                       }
                                //}
 
                                if (document.Lenght > 0) {
@@ -356,7 +355,7 @@ namespace Crow
                                                        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;
@@ -477,8 +476,7 @@ namespace Crow
                        }
                        //}
 
-                       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);
@@ -576,10 +574,6 @@ namespace Crow
                                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);
@@ -602,6 +596,14 @@ namespace Crow
                        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
@@ -638,7 +640,7 @@ namespace Crow
                        if (HasFocus && IFace.IsDown (MouseButton.Left)) {
                                CurrentLoc = hoverLoc;
                                autoAdjustScroll = true;
-                               IFace.forceTextCursor = true;
+                               IFace.forceTextCursor();
                                RegisterForRedraw ();
                        }
                }
@@ -652,7 +654,7 @@ namespace Crow
                                        else if (!selectionStart.HasValue)
                                                selectionStart = CurrentLoc;
                                        CurrentLoc = hoverLoc;
-                                       IFace.forceTextCursor = true;
+                                       IFace.forceTextCursor();
                                        RegisterForRedraw ();
                                        e.Handled = true;
                                }
@@ -808,7 +810,7 @@ namespace Crow
                                        return;
                                }
                                autoAdjustScroll = true;
-                               IFace.forceTextCursor = true;
+                               IFace.forceTextCursor();
                                e.Handled = true;
                        /*} finally {
                                document.ExitReadLock ();
@@ -890,7 +892,7 @@ namespace Crow
                        CurrentLoc = document.GetLocation (change.Start + change.ChangedText.Length);
 
                        textMeasureIsUpToDate = false;
-                       IFace.forceTextCursor = true;
+                       IFace.forceTextCursor();
                        autoAdjustScroll = true;
 
                        RegisterForGraphicUpdate ();
index c63d67e0882e6334cb3a24a57ddbd5bc247659a4..835d2f4e85ab5000a5c1287d0b038b19e064b689 100644 (file)
@@ -9,6 +9,9 @@ using System.Collections;
 using Drawing2D;
 using System.Threading.Tasks;
 using System.Linq;
+using System.Collections.Generic;
+using CrowEditBase;
+using System.Diagnostics;
 
 namespace Crow
 {
@@ -30,8 +33,13 @@ 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;
@@ -44,9 +52,10 @@ namespace Crow
        }
        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;
@@ -69,6 +78,32 @@ namespace Crow
                                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;
@@ -81,39 +116,6 @@ namespace Crow
                                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 {
@@ -128,6 +130,36 @@ namespace Crow
                                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; }
@@ -207,7 +239,9 @@ namespace Crow
                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;
@@ -217,27 +251,16 @@ namespace Crow
                        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 ();
                }
@@ -248,7 +271,9 @@ namespace Crow
                        RegisterForRedraw ();
                }
 
+               public Stopwatch perf = new Stopwatch ();
 
+               #region widget overrides
                public override void OnLayoutChanges (LayoutingType layoutType)
                {
                        base.OnLayoutChanges (layoutType);
@@ -259,10 +284,18 @@ namespace Crow
                                        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)
@@ -280,27 +313,30 @@ namespace Crow
 
                        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);
@@ -329,13 +365,21 @@ namespace Crow
                                                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;
@@ -360,17 +404,18 @@ namespace Crow
                        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
+    }
 }
 
diff --git a/CrowEditBase/src/Logger.cs b/CrowEditBase/src/Logger.cs
new file mode 100644 (file)
index 0000000..1b8cc73
--- /dev/null
@@ -0,0 +1,78 @@
+// 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;
+                       }
+               }
+
+}
index aa67fc3cbf09d3d8e840e71a5f27fc775383a117..be21bf960d70d8ab817e46e7901f96e5c62a645c 100644 (file)
@@ -27,6 +27,7 @@ namespace CrowEditBase
                        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 {
@@ -36,6 +37,8 @@ namespace CrowEditBase
                                isLoaded = value;
 
                                NotifyValueChanged (isLoaded);
+                               NotifyValueChanged ("ColorStatus", ColorStatus);
+                               
 
                                CMDLoad.CanExecute = !IsLoaded;
                                CMDReload.CanExecute = CMDUnload.CanExecute = IsLoaded;
@@ -52,14 +55,15 @@ namespace CrowEditBase
                        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);
@@ -81,6 +85,10 @@ namespace CrowEditBase
                                                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)
@@ -90,12 +98,15 @@ namespace CrowEditBase
                                                }
                                        }
                                        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)
@@ -105,7 +116,7 @@ namespace CrowEditBase
                                App.GetService (serviceClass)?.Stop();
 
                        App.RemoveCrowAssembly (loadContext.MainAssembly);
-
+                       App.Log(LogType.Plugin | LogType.Normal, $"Plugin unloaded: {Name}");
                        IsLoaded = false;
                }
        }
index be4fd16adea6e18cf4bf526a458080461187faea..030b88250e110182497f1f9cd11c0ecf39ceda49 100644 (file)
@@ -1,4 +1,4 @@
-// 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)
 
@@ -37,8 +37,8 @@ namespace CrowEditBase
                }
                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;
                }
-
        }
 }
index fa33fd165349ea47672b9be9461fdde95b143b06..7d8f1cc8d6974edf6405dcf8bf84217ec29248b6 100644 (file)
@@ -18,16 +18,19 @@ namespace CrowEditBase
                        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;
@@ -50,8 +53,13 @@ namespace CrowEditBase
                        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 ();
index 94b200bc0288c7b55ddb0d9da3d353668c4d5848..24319dc8b905a9864d4540e14123dac940f466fb 100644 (file)
@@ -241,7 +241,7 @@ namespace Crow
                        if (HasFocus && IFace.IsDown (MouseButton.Left)) {
                                CurrentLoc = hoverLoc;
                                autoAdjustScroll = true;
-                               IFace.forceTextCursor = true;
+                               IFace.forceTextCursor();
                                RegisterForRedraw ();
                        }
                }
@@ -345,10 +345,10 @@ namespace Crow
                                                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;
                                        }
@@ -590,8 +590,7 @@ namespace Crow
                                                selStart = selectionStart.Value;
                                                selEnd = CurrentLoc.Value;
                                        }
-                               } else
-                                       IFace.forceTextCursor = true;
+                               }
 
 
                                double spacePixelWidth = gr.TextExtents (" ").XAdvance;
@@ -643,7 +642,7 @@ namespace Crow
 
                                                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);
 
@@ -663,7 +662,7 @@ namespace Crow
 
                                        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));;
@@ -796,5 +795,6 @@ namespace Crow
                        }
                        //Console.WriteLine ($"{pos}: {suggestionTok.AsString (_text)} {suggestionTok}");
                }
+               
        }
 }
\ No newline at end of file
index dfc31465733f6e3527ce8b93e36a6acafba537e2..84cfb3a16ff02abfb07ba8c1c05231a03f023593 100644 (file)
@@ -89,6 +89,7 @@ namespace CrowEditBase
                        }
                        origSource = source;
                        NotifyValueChanged ("IsDirty", IsDirty);
+                       CMDSave.CanExecute = IsDirty;
                }
                protected override void readFromDisk()
                {
@@ -120,7 +121,7 @@ namespace CrowEditBase
 
 
 
-               protected void saveFileDialog_OkClicked (object sender, EventArgs e)
+               protected override void saveFileDialog_OkClicked (object sender, EventArgs e)
                {
                        FileDialog fd = sender as FileDialog;
 
@@ -180,6 +181,7 @@ namespace CrowEditBase
                }
                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);
@@ -189,6 +191,9 @@ namespace CrowEditBase
                        source = tmp.ToString ();
 
                        lines.Update (change);
+
+                       NotifyValueChanged ("IsDirty", IsDirty);
+                       CMDSave.CanExecute = IsDirty;                   
                }
                protected void applyTextChange (TextChange change, object triggeringEditor = null) {
                        editorRWLock.EnterWriteLock ();
index 70f574f03c6d6dc10dab7edebfba288350a3a2dc..3895519553b47f72b4d7a8babfe40bd6d29588f3 100644 (file)
@@ -1,10 +1,10 @@
-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";
@@ -20,6 +20,11 @@ TreeItemBorderHighlightFG    = "DimGrey";
 TreeItemBackground                     = "Transparent";
 //TreeItemHighlight                    = "
 
+TxtInFileDialog {
+       Margin = "2";
+       Font = "mono, 14";
+}
+
 Editor {
        Focusable="true";
        Height="Stretched";
@@ -54,9 +59,8 @@ MemberViewHStack {
 IcoBut {
        Template = "#ui.IcoBut.template";
        MinimumSize = "10,10";
-       Width = "8";
-       Height = "14";
-       Background = "White";
+       Width = "32";
+       Height = "32";
 }
 Spinner {
        Template = "#ui.spinner.template";
@@ -133,7 +137,7 @@ CheckBox {
        Template= "#Crow.CheckBox2.template";
        Width = "Stretched";
        Height = "Fit";
-       CornerRadius = "3";
+       CornerRadius = "0";
        Background = "${ControlIdle}";
        Foreground = "${ControlForeground}";
        Checked = "{Background=${ControlHighlight}}";
@@ -143,4 +147,5 @@ CheckBox {
 }
 LogViewerWidget {
        Background = "0.01,0.01,0.01,1";
-}
\ No newline at end of file
+       MouseWheelSpeed = "2";
+}
index 9ecd7886229d8d88b916ff5d6b96555a9ae08678..c62e17105c9d8899c9e86ae6f45e5113a8b08f57 100644 (file)
@@ -3,7 +3,7 @@
 <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>
index 354014082bd8478d90f81c02676a841635114074..befd6e02823f2121e28dcbd0ff5bd5d24c4a2f6b 100644 (file)
@@ -3,12 +3,12 @@
 <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}"/>
index 325381a09b6077d1f5e77252fa0c58d72bb5e89b..8cd0f1fd744b44933c09388d58e8d07a250c3ac9 100644 (file)
@@ -3,5 +3,5 @@
        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
index 6a9f05d0832cf822e542bf7c97d00227a49e5ac4..d220f1a75c332af6661c43a41b45a39aab4f2f2f 100644 (file)
@@ -5,7 +5,7 @@
                                                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>
index cdfb33a10549e6caf6f02dbe11901b961ab4e938..85d42cd1109496cc72fbdfe6ab908d6236806d41 100644 (file)
@@ -7,7 +7,7 @@
                <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>
index 21e61af5df23af8791c8f6fd6695a0577bb80f2a..3a3ac738ddf679e6dcf64d8b5e0dbba45663b257 100644 (file)
@@ -5,7 +5,7 @@
        <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>
index 151f751d41d34b74a5bbc6f34985f8a9ead1799a..02b65436d170784934b73df01aaa7e59a1b6e405 100644 (file)
@@ -2,7 +2,7 @@
 <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"/>
index 67b653ff8eca59f9641973e6eb7e1eadee4cacd5..ad99b95b6a0c2225e16ffc70903daf8ba315d8ba 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
-               <TargetFrameworks>net5</TargetFrameworks>
+               <TargetFrameworks>net9</TargetFrameworks>
                <EnableDefaultItems>false</EnableDefaultItems>
        </PropertyGroup>
 
index b94452819a079b9e777d8489ff13949a278329d4..c1aa4e2417f6edc42632dc2fc0d5637d10d6cecb 100644 (file)
@@ -23,48 +23,14 @@ namespace Crow
 {
        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;
@@ -92,9 +58,7 @@ namespace Crow
                                dlg.DataSource = this;
                        }
                );
-
                public ActionCommand CMDViewPreview;
-
                void initCommands ()
                {
                        CMDViewPreview = new ActionCommand("Crow Preview", () => App.LoadWindow ("#CECrowPlugin.ui.winCrowPreview.crow", App));
@@ -113,6 +77,7 @@ namespace Crow
                        if (CurrentState == Status.Running)
                                delSetSource (imlSource);
                }
+               Project activeSolution;
                Exception currentException;
                public string ErrorMessage = "";
                public bool ServiceIsInError;
@@ -121,7 +86,7 @@ namespace Crow
                Assembly crowAssembly, thisAssembly;
                Type dbgIfaceType;
 
-               #region dbgIface delegates
+#region dbgIface delegates
                Action<int, int> delResize;
                Func<int, int, bool> delMouseMove;
                Func<float, bool> delMouseWheelChanged;
@@ -139,52 +104,12 @@ namespace Crow
 
 
                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 {
@@ -243,11 +168,77 @@ namespace Crow
                                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
@@ -264,6 +255,10 @@ namespace Crow
                                                yield return style.FullPath;
                                }
                        }
+                       /*foreach (String item in crowAssemblies)
+                       {
+                               yield return Assembly.LoadFile();
+                       }*/
                        yield return crowAssembly;
                }
                Stream getStreamFromPath (string path) {
@@ -282,19 +277,15 @@ namespace Crow
                        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))
@@ -302,79 +293,16 @@ namespace Crow
                                        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);
                }
@@ -393,8 +321,12 @@ namespace Crow
                {
                        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 {
@@ -406,6 +338,90 @@ namespace Crow
                        }
                }
 
+               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 {
@@ -415,17 +431,6 @@ namespace Crow
                                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;
@@ -435,7 +440,7 @@ namespace Crow
                        else
                                Configuration.Global.Set ("CrowAssemblies", "");
                }
-               void loadCrowAssemblies () {
+               void restoreCrowAssemblies () {
                        crowAssemblies.Clear ();
                        if (!Configuration.Global.TryGet<string> ("CrowAssemblies", out string assemblies))
                                return;
@@ -443,11 +448,6 @@ namespace Crow
                                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.
@@ -460,7 +460,7 @@ namespace Crow
                                }
                                catch (System.Exception ex)
                                {
-                                       Console.WriteLine($"[Error][DebugIFace key down]{ex}");
+                                       Log(LogType.Error, $"[Error][DebugIFace key down]{ex}");
                                }
                        }
                }
@@ -473,7 +473,7 @@ namespace Crow
                                }
                                catch (System.Exception ex)
                                {
-                                       Console.WriteLine($"[Error][DebugIFace key up]{ex}");
+                                       Log(LogType.Error, $"[Error][DebugIFace key up]{ex}");
                                }
                        }
                }
@@ -486,7 +486,7 @@ namespace Crow
                                }
                                catch (System.Exception ex)
                                {
-                                       Console.WriteLine($"[Error][DebugIFace key press]{ex}");
+                                       Log(LogType.Error, $"[Error][DebugIFace key press]{ex}");
                                }
                        }
                }
@@ -500,7 +500,7 @@ namespace Crow
                                }
                                catch (System.Exception ex)
                                {
-                                       Console.WriteLine($"[Error][DebugIFace mouse move]{ex}");
+                                       Log(LogType.Error, $"[Error][DebugIFace mouse move]{ex}");
                                }
                        }
                }
@@ -513,7 +513,7 @@ namespace Crow
                                }
                                catch (System.Exception ex)
                                {
-                                       Console.WriteLine($"[Error][DebugIFace mouse down]{ex}");
+                                       Log(LogType.Error, $"[Error][DebugIFace mouse down]{ex}");
                                }
                        }
                }
@@ -526,7 +526,7 @@ namespace Crow
                                }
                                catch (System.Exception ex)
                                {
-                                       Console.WriteLine($"[Error][DebugIFace mouse up]{ex}");
+                                       Log(LogType.Error, $"[Error][DebugIFace mouse up]{ex}");
                                }
                        }
                }
@@ -539,23 +539,12 @@ namespace Crow
                                }
                                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;
index 5df0be2ddb905f3c9e95e598854e8cfe79bf5e6a..26e7ae83fe52ed1f66a8ce8988eb99d060ded488 100644 (file)
@@ -330,7 +330,7 @@ namespace Crow
 
                }
                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);
 
@@ -399,7 +399,7 @@ namespace Crow
 
                        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;
@@ -425,8 +425,7 @@ namespace Crow
                        ctx.SetSource (Colors.Black);
                        ctx.ShowText (str);
 
-
-
+                       return true;
                }
                public override void OnLayoutChanges (LayoutingType layoutType)
                {
index 8f5d8d34d1bcb71d416e69c91cc0e97904db73ab..2f5ba944f11ca2298af7c72b8e0d4b7e211dcbed 100644 (file)
@@ -24,7 +24,7 @@ namespace CECrowPlugin
                }
                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;
@@ -34,14 +34,11 @@ namespace CECrowPlugin
                public override void Run()
                {
                        initBackend ();
-
+                       Init();
                        Thread t = new Thread (interfaceThread) {
                                IsBackground = true
                        };
                        t.Start ();
-
-                       Init();
-
                }
                public bool Terminate;
                string source;
index 849f72ed0cd358e9e92af71d9331b5491b2309dc..815cb3ac85d98afc56ff758134dc8cf87d63abbd 100644 (file)
@@ -139,7 +139,7 @@ namespace Crow
 
                protected override void onDraw(IContext gr)
                {
-                       Console.WriteLine("onDraw");
+                       //crowIFaceService.Log(LogType.Error, "onDraw");
                        gr.SetSource(Colors.RoyalBlue);
                        gr.Paint();
                }
@@ -156,9 +156,9 @@ namespace Crow
                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()
                {
index a5d30f6ba118a001368c9c7c92575528f3d12277..1519a75d48fd513aba5831db673c2f0ac0a9e68b 100644 (file)
@@ -32,6 +32,8 @@ namespace CECrowPlugin
                        }*/
                }
                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 ();
@@ -54,10 +56,6 @@ namespace CECrowPlugin
                        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)
@@ -129,6 +127,20 @@ namespace CECrowPlugin
 
                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);
                }
        }
index 9e79a2c59b94227c18c73b58ceb589e772e8169f..52849a5fee44ac07c9c1676c35a7ad7c586f161b 100644 (file)
@@ -21,6 +21,7 @@ namespace CECrowPlugin
                ElementName                             = 0x0201,
                AttributeName                   = 0x0202,
                PI_Target                               = 0x0203,
+               ConstantName                    = 0x0204,
                Punctuation                             = 0x0400,
                PI_Start                                = 0x0401,// '<?'
                PI_End                                  = 0x0402,// '?>'
@@ -39,9 +40,11 @@ namespace CECrowPlugin
                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
        }
index a9f74a66b3ab1b985d4260e3a6b39a7a622b095d..378e9f347af693501506b4ea840d95c5eeabd319 100644 (file)
@@ -7,6 +7,7 @@ using Crow.Text;
 using System.Collections.Generic;
 using CrowEditBase;
 using CrowEdit.Xml;
+using Crow;
 
 namespace CECrowPlugin
 {
@@ -14,43 +15,131 @@ 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 ();
                        }
-               }*/
+               }
 
        }
 }
diff --git a/plugins/CECrowPlugin/src/Parsing/IML/SyntaxAnalyser.cs b/plugins/CECrowPlugin/src/Parsing/IML/SyntaxAnalyser.cs
new file mode 100644 (file)
index 0000000..db7aa17
--- /dev/null
@@ -0,0 +1,134 @@
+// 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
diff --git a/plugins/CECrowPlugin/src/Parsing/IML/SyntaxNodes.cs b/plugins/CECrowPlugin/src/Parsing/IML/SyntaxNodes.cs
new file mode 100644 (file)
index 0000000..7885d98
--- /dev/null
@@ -0,0 +1,22 @@
+// 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
index a49628b0aceb897a1814b0a547ba1fa88b8b64b3..823bb865ff9e2d18bf46b8c1a82b355ce408509b 100644 (file)
@@ -22,10 +22,10 @@ namespace CECrowPlugin.Style {
                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 &&
@@ -67,15 +67,15 @@ namespace CECrowPlugin.Style {
                                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) {
@@ -85,7 +85,7 @@ namespace CECrowPlugin.Style {
                                                                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);
@@ -120,13 +120,13 @@ namespace CECrowPlugin.Style {
                                        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);
@@ -135,7 +135,7 @@ namespace CECrowPlugin.Style {
                                                                reader.Advance ();
                                                        }
                                                        continue;
-                                               } else if (reader.TryPeak ('\"')) {
+                                               } else if (reader.TryPeek ('\"')) {
                                                        addTok (ref reader, StyleTokenType.MemberValuePart);
                                                        reader.Advance ();
                                                        addTok (ref reader, StyleTokenType.MemberValueClose);
index 03c5c9951e353290e66bc9fca47502c94e261225..9d4e7fa30067cbb88d5ee4193b312ebefe146cd0 100644 (file)
@@ -1,5 +1,5 @@
 <?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>
diff --git a/plugins/CEEbnfPlugin/CEEbnfPlugin.csproj b/plugins/CEEbnfPlugin/CEEbnfPlugin.csproj
new file mode 100644 (file)
index 0000000..7752c0c
--- /dev/null
@@ -0,0 +1,11 @@
+<?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>
diff --git a/plugins/CEEbnfPlugin/default.conf b/plugins/CEEbnfPlugin/default.conf
new file mode 100644 (file)
index 0000000..9356bae
--- /dev/null
@@ -0,0 +1 @@
+FileAssociations=CrowEdit.Ebnf.EbnfDocument:.ebnf:#ui.sourceEditor.itmp
diff --git a/plugins/CEEbnfPlugin/src/Parsing/CharRange.cs b/plugins/CEEbnfPlugin/src/Parsing/CharRange.cs
new file mode 100644 (file)
index 0000000..bd9d61b
--- /dev/null
@@ -0,0 +1,36 @@
+// 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
diff --git a/plugins/CEEbnfPlugin/src/Parsing/EbnfDocument.cs b/plugins/CEEbnfPlugin/src/Parsing/EbnfDocument.cs
new file mode 100644 (file)
index 0000000..b0af947
--- /dev/null
@@ -0,0 +1,48 @@
+// 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
diff --git a/plugins/CEEbnfPlugin/src/Parsing/EbnfSyntaxAnalyser.cs b/plugins/CEEbnfPlugin/src/Parsing/EbnfSyntaxAnalyser.cs
new file mode 100644 (file)
index 0000000..f29c291
--- /dev/null
@@ -0,0 +1,354 @@
+// 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 ();
+               }               
+               
+       }
+}
diff --git a/plugins/CEEbnfPlugin/src/Parsing/EbnfTokenType.cs b/plugins/CEEbnfPlugin/src/Parsing/EbnfTokenType.cs
new file mode 100644 (file)
index 0000000..40e7d63
--- /dev/null
@@ -0,0 +1,48 @@
+// 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
diff --git a/plugins/CEEbnfPlugin/src/Parsing/EbnfTokenizer.cs b/plugins/CEEbnfPlugin/src/Parsing/EbnfTokenizer.cs
new file mode 100644 (file)
index 0000000..01a5435
--- /dev/null
@@ -0,0 +1,185 @@
+// 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();
+               }
+
+       }
+}
diff --git a/plugins/CEEbnfPlugin/src/Parsing/Expression.cs b/plugins/CEEbnfPlugin/src/Parsing/Expression.cs
new file mode 100644 (file)
index 0000000..bc4b32f
--- /dev/null
@@ -0,0 +1,109 @@
+// 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
diff --git a/plugins/CEEbnfPlugin/src/Parsing/ParserException.cs b/plugins/CEEbnfPlugin/src/Parsing/ParserException.cs
new file mode 100644 (file)
index 0000000..5e20b18
--- /dev/null
@@ -0,0 +1,16 @@
+// 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})";
+       }
+}
diff --git a/plugins/CEEbnfPlugin/src/Parsing/SymbolDecl.cs b/plugins/CEEbnfPlugin/src/Parsing/SymbolDecl.cs
new file mode 100644 (file)
index 0000000..4319909
--- /dev/null
@@ -0,0 +1,58 @@
+// 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
diff --git a/plugins/CEEbnfPlugin/src/Parsing/SyntaxNodes.cs b/plugins/CEEbnfPlugin/src/Parsing/SyntaxNodes.cs
new file mode 100644 (file)
index 0000000..17036ca
--- /dev/null
@@ -0,0 +1,36 @@
+// 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
index b057d4f8cb2ad2e6c5bdfe85190c1b935e1fc3ca..891c3a0e0efe5f4be2ccfaa6c0326cb623b3ba52 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
-               <TargetFrameworks>net5</TargetFrameworks>
+               <TargetFrameworks>net9</TargetFrameworks>
                <EnableDefaultItems>false</EnableDefaultItems>
        </PropertyGroup>
 
index 1e374bce56d787b3da0a5e0fbf2672195032078b..eeb42f8a21095042a8ef64a2654b9d92808e4d67 100644 (file)
@@ -21,10 +21,15 @@ namespace NetcoreDbgPlugin
                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> (@"
@@ -36,32 +41,99 @@ namespace NetcoreDbgPlugin
                );
                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()
@@ -69,9 +141,31 @@ namespace NetcoreDbgPlugin
                        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
index 5ba207c1dd503805bac131774b43cc5a12587ecf..2984b2b4ad407e0b813ea633ca900c7f6331e042 100644 (file)
@@ -42,25 +42,13 @@ namespace NetcoreDbgPlugin
                                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";
@@ -79,6 +67,8 @@ namespace NetcoreDbgPlugin
 
                        BreakPoints.ListAdd += BreakPoints_ListAdd;
                        BreakPoints.ListRemove += BreakPoints_ListRemove;
+
+                       initCommands();
                }
                #endregion
 
@@ -99,7 +89,7 @@ namespace NetcoreDbgPlugin
                /// </summary>
                void sendRequest(Request request)
                {
-                       DebuggerLog.Add($"<- {request}");
+                       log.Add(LogType.Custom1, $"<- {request}");
                        procdbg.StandardInput.WriteLine(request);
                }
 
@@ -124,12 +114,34 @@ namespace NetcoreDbgPlugin
                                        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()
                {
@@ -141,6 +153,7 @@ namespace NetcoreDbgPlugin
                }
                public override void Stop()
                {
+                       CurrentState = Status.Stopping;
                        CreateNewRequest($"-exec-abort");
                }
 
@@ -201,7 +214,7 @@ namespace NetcoreDbgPlugin
                }
                private void Procdbg_Exited(object sender, EventArgs e)
                {
-                       DebuggerLog.Add("GDB process Terminated.");
+                       log.Add(LogType.Custom1, "GDB process Terminated.");
 
                        CurrentState = Status.Init;
                }
@@ -254,14 +267,14 @@ namespace NetcoreDbgPlugin
                }
 
                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);
@@ -330,14 +343,14 @@ namespace NetcoreDbgPlugin
                                                        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
@@ -353,13 +366,13 @@ namespace NetcoreDbgPlugin
                                        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") {
@@ -379,9 +392,9 @@ namespace NetcoreDbgPlugin
                                        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);
@@ -392,9 +405,7 @@ namespace NetcoreDbgPlugin
 
                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)
diff --git a/plugins/CENetcoreDbgPlugin/ui/winBreakPoints.crow b/plugins/CENetcoreDbgPlugin/ui/winBreakPoints.crow
new file mode 100644 (file)
index 0000000..785420f
--- /dev/null
@@ -0,0 +1,22 @@
+<?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>
index 08a6cc5a98c064260401b80a2e7547fa01c56912..130890bb7ec68e99c084cdadaa74e95778f9cfdf 100644 (file)
@@ -1,21 +1,14 @@
 <?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>
 
 
diff --git a/plugins/CENetcoreDbgPlugin/ui/winStackFrames.crow b/plugins/CENetcoreDbgPlugin/ui/winStackFrames.crow
new file mode 100644 (file)
index 0000000..a5705e3
--- /dev/null
@@ -0,0 +1,30 @@
+<?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>-->
+
diff --git a/plugins/CENetcoreDbgPlugin/ui/winThreads.crow b/plugins/CENetcoreDbgPlugin/ui/winThreads.crow
new file mode 100644 (file)
index 0000000..d9c7a2c
--- /dev/null
@@ -0,0 +1,19 @@
+<?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>
diff --git a/plugins/CENetcoreDbgPlugin/ui/winWatches.crow b/plugins/CENetcoreDbgPlugin/ui/winWatches.crow
new file mode 100644 (file)
index 0000000..67480d4
--- /dev/null
@@ -0,0 +1,33 @@
+<?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>
diff --git a/plugins/CENugetPlugin/CENugetPlugin.csproj b/plugins/CENugetPlugin/CENugetPlugin.csproj
new file mode 100644 (file)
index 0000000..5baba23
--- /dev/null
@@ -0,0 +1,18 @@
+<?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>
diff --git a/plugins/CENugetPlugin/default.conf b/plugins/CENugetPlugin/default.conf
new file mode 100644 (file)
index 0000000..16be3e0
--- /dev/null
@@ -0,0 +1 @@
+MainService=NugetPlugin.NugetService
\ No newline at end of file
diff --git a/plugins/CENugetPlugin/src/Extensions.cs b/plugins/CENugetPlugin/src/Extensions.cs
new file mode 100644 (file)
index 0000000..06e4eb2
--- /dev/null
@@ -0,0 +1,13 @@
+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;
+               }
+    }
+}
diff --git a/plugins/CENugetPlugin/src/NugetService.cs b/plugins/CENugetPlugin/src/NugetService.cs
new file mode 100644 (file)
index 0000000..de3e586
--- /dev/null
@@ -0,0 +1,166 @@
+// 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
diff --git a/plugins/CENugetPlugin/ui/winConfiguration.crow b/plugins/CENugetPlugin/ui/winConfiguration.crow
new file mode 100644 (file)
index 0000000..b5935f5
--- /dev/null
@@ -0,0 +1,12 @@
+<?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>
+
+
diff --git a/plugins/CENugetPlugin/ui/winNugetExplorer.crow b/plugins/CENugetPlugin/ui/winNugetExplorer.crow
new file mode 100644 (file)
index 0000000..f0467c8
--- /dev/null
@@ -0,0 +1,48 @@
+<?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>
+
+
index 03295c02060b3a3639215ca5964df9aed685c434..c693127ee355069f3b2a3ece72fd4ef312249cf7 100644 (file)
@@ -1,7 +1,7 @@
 <?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>
index cd4b1a1668c3a6873dbe317ae810078a82fef457..2e0b4c4a592a6dc9e65c275a8bdfef5712ba339d 100644 (file)
@@ -1,2 +1,2 @@
 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
index c9353942df708a29e0d629caa2bc60cc3dae7d0a..919ae7d1abbe573a31353decb5cf7aade7993a8a 100644 (file)
@@ -52,9 +52,10 @@ namespace CERoslynPlugin
                        }
                }
                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) {
@@ -75,6 +76,8 @@ namespace CERoslynPlugin
                        eventSource.TargetFinished += EventSource_TargetFinished;
                        eventSource.TaskStarted += EventSource_TaskStarted;
                        eventSource.TaskFinished += EventSource_TaskFinished;
+                       eventSource.CustomEventRaised += EventSource_CusomEvent;
+                       //eventSource.AnyEventRaised += EventSource_AnyEvent;
                }
 
                void unregisterHandles () {
@@ -89,15 +92,27 @@ namespace CERoslynPlugin
                        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)
index 1f6afc81ce5c592b0c3c62490822990e0f44e0da..e9ebb21ef7e0bba2cf9cd0fba7e102e57623efea 100644 (file)
@@ -12,12 +12,14 @@ using IML = Crow.IML;
 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
 {
@@ -25,7 +27,7 @@ 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 ();
@@ -34,30 +36,42 @@ namespace CERoslynPlugin
                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
diff --git a/plugins/CERoslynPlugin/src/CSTokenType.cs b/plugins/CERoslynPlugin/src/CSTokenType.cs
new file mode 100644 (file)
index 0000000..fee4ed1
--- /dev/null
@@ -0,0 +1,26 @@
+// 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
index 68b386da3e0b32fdf6c74d26366c6dfeaf5f7720..3a219a004c0983a14dc73f4fc373ed33b889442c 100644 (file)
@@ -15,7 +15,8 @@ namespace CERoslynPlugin
 {
        public class CSTokenizer : Tokenizer
        {
-               //CsharpSyntaxWalkerBridge bridge = new CsharpSyntaxWalkerBridge();
+               
+
                int startOfTok;
                protected List<Token> Toks;
                void addTok (ref SpanCharReader reader, Enum tokType) {
@@ -26,7 +27,7 @@ namespace CERoslynPlugin
                }
                void skipWhiteSpacesAndLineBreaks (ref SpanCharReader reader) {
                        while(!reader.EndOfSpan) {
-                               switch (reader.Peak) {
+                               switch (reader.Peek) {
                                        case '\x85':
                                        case '\x2028':
                                        case '\xA':
@@ -42,7 +43,7 @@ namespace CERoslynPlugin
                                        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;
@@ -53,11 +54,11 @@ namespace CERoslynPlugin
                }
                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;
@@ -69,11 +70,14 @@ namespace CERoslynPlugin
 
                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) {
 
@@ -82,20 +86,21 @@ namespace CERoslynPlugin
                                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);
@@ -104,8 +109,16 @@ namespace CERoslynPlugin
                {
                        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 ())) {
@@ -132,10 +145,12 @@ namespace CERoslynPlugin
                }
 
                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));
                }
 
        }
index 0fbea81a2152b540b2f99a37036ae263a635d4c2..901dff2b5a276de68274b1cd02367ef806089277 100644 (file)
@@ -116,6 +116,26 @@ namespace CERoslynPlugin
                        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);
                }
 
index 6a6685a20bacfb5a6ef2a667c5a205d0e401f1e4..d85da1633843576437f6e02701d04fdd4ea189d3 100644 (file)
@@ -69,10 +69,11 @@ namespace CERoslynPlugin
                                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");
 
@@ -98,7 +99,9 @@ namespace CERoslynPlugin
                                        if (constants != null)
                                                parseOptions = parseOptions.WithPreprocessorSymbols (constants.EvaluatedValue.Split (';'));
 
+
                                        /*ProjectProperty targetPath = project.GetProperty ("TargetPath");
+                                       
                                        printEvaluatedProperties(project.CreateProjectInstance());*/
 
                                        populateTreeNodes ();
@@ -113,7 +116,7 @@ namespace CERoslynPlugin
                        }
                        catch (System.Exception ex)
                        {
-                               Console.WriteLine (ex);
+                               //App.Log(LogType.Error, $"[MSBuildProject.Load] Error: {ex.ToString()}");
                        }
                }
 
@@ -131,21 +134,27 @@ namespace CERoslynPlugin
                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());
@@ -255,6 +264,7 @@ namespace CERoslynPlugin
                                                curNode.AddChild (new ProjectItemNode (pn));
 
                                        } catch (Exception ex) {
+                                               
                                                Console.ForegroundColor = ConsoleColor.DarkRed;
                                                Console.WriteLine (ex);
                                                Console.ResetColor ();
@@ -281,12 +291,13 @@ namespace CERoslynPlugin
                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 {
@@ -345,10 +356,10 @@ namespace CERoslynPlugin
                                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
index 959bdf5f2c3276e4a10019bf281f7c57de058887..4cb272c5a5f6efac3d571ec603f11efa8effa47e 100644 (file)
@@ -53,16 +53,13 @@ namespace CERoslynPlugin
                        }
                }
 
-
-
-
                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:
index 1efd147f9a1de1263424ac76e7526939364fcb67..2fb5d41dd55f286b00cbff15c30ca7c695a2a412 100644 (file)
@@ -54,53 +54,64 @@ namespace CERoslynPlugin
                                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() {
@@ -111,9 +122,16 @@ namespace CERoslynPlugin
 
                        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;
 
index d1e931bd0f5ea40182bd790a5a5404dc734619b7..4ca5f376309bf797b6df999621eb87eebc6c5cff 100644 (file)
@@ -21,19 +21,23 @@ using static CrowEditBase.CrowEditBase;
 
 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;
@@ -49,6 +53,7 @@ namespace CERoslynPlugin
                                if (ActiveConfiguration == value)
                                        return;
                                UserConfig.Set ("ActiveConfiguration", value);
+                               projectCollection.SetGlobalProperty ("Configuration", value);
                                NotifyValueChanged (value);
                        }
                }
@@ -58,6 +63,7 @@ namespace CERoslynPlugin
                                if (ActiveConfiguration == value)
                                        return;
                                UserConfig.Set ("ActivePlatform", value);
+                               projectCollection.SetGlobalProperty ("Platform", value);
                                NotifyValueChanged (value);
                        }
                }
@@ -92,51 +98,56 @@ namespace CERoslynPlugin
                }
 
                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\"));
@@ -180,8 +191,8 @@ namespace CERoslynPlugin
 
                        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) {
diff --git a/plugins/CERoslynPlugin/src/SyntaxAnalyser.cs b/plugins/CERoslynPlugin/src/SyntaxAnalyser.cs
new file mode 100644 (file)
index 0000000..30a7694
--- /dev/null
@@ -0,0 +1,27 @@
+// 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
diff --git a/plugins/CERoslynPlugin/ui/winSyntaxTree.crow b/plugins/CERoslynPlugin/ui/winSyntaxTree.crow
new file mode 100644 (file)
index 0000000..de64165
--- /dev/null
@@ -0,0 +1,70 @@
+<?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
index bf08eacaac64fb3af8806a01062883f661b96489..3b9707f27efe861c989db9a798ca38563ebf993f 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
-               <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
+               <TargetFrameworks>net9</TargetFrameworks>
                <EnableDefaultItems>false</EnableDefaultItems>
        </PropertyGroup>
 
@@ -9,9 +9,4 @@
                <Compile Include="src\**\*.cs" />
                <EmbeddedResource Include="default.conf" />
        </ItemGroup>
-       <ItemGroup>
-               <PackageReference Include="Enums.NET" Version="4.0.0" >
-                       <ExcludeAssets>runtime</ExcludeAssets>
-               </PackageReference>
-       </ItemGroup>
 </Project>
index 6b5d97174124db4d24458b24e32e0d5ecbc41c02..2b24cbf82610f630b89b692660f639e5bdc3a0cc 100644 (file)
@@ -1 +1 @@
-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
index d3296b504d71a13a28acc79bf1e942d4b6d1450b..745015509c946e15db7f2a39adeea2b5026bc558 100644 (file)
@@ -17,17 +17,19 @@ namespace CrowEdit.Xml
                /*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)) {
@@ -39,6 +41,7 @@ namespace CrowEdit.Xml
                                                } 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));
@@ -69,7 +72,7 @@ namespace CrowEdit.Xml
                                                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 ();
@@ -82,6 +85,7 @@ namespace CrowEdit.Xml
                                                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 {
@@ -90,7 +94,7 @@ namespace CrowEdit.Xml
                                                        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));
@@ -106,6 +110,7 @@ namespace CrowEdit.Xml
                                                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);
index b9483d3c3358a4bc0f491c20c74db8292c300e9c..166f09d7823205bbd02cf1bc1a412a1b51df7c75 100644 (file)
@@ -8,21 +8,21 @@ using CrowEditBase;
 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)
@@ -50,7 +50,7 @@ namespace CrowEdit.Xml
 
        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);
 
@@ -62,12 +62,7 @@ namespace CrowEdit.Xml
        }
 
        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;
index 7e190171066c7c7186c230b6e29610ede44d8548..46f287ea6152e4aaa1bd937d9c322d98b894930e 100644 (file)
@@ -29,10 +29,10 @@ namespace CrowEdit.Xml
                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 ();
@@ -51,11 +51,11 @@ namespace CrowEdit.Xml
                                        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);
@@ -77,18 +77,18 @@ namespace CrowEdit.Xml
                                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) {
@@ -98,7 +98,7 @@ namespace CrowEdit.Xml
                                                                        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);
@@ -113,12 +113,12 @@ namespace CrowEdit.Xml
                                                                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);
 
@@ -138,7 +138,7 @@ namespace CrowEdit.Xml
                                        break;
                                case '?':
                                        reader.Advance ();
-                                       if (reader.TryPeak ('>')){
+                                       if (reader.TryPeek ('>')){
                                                reader.Advance ();
                                                addTok (ref reader, XmlTokenType.PI_End);
                                        }else
@@ -161,7 +161,7 @@ namespace CrowEdit.Xml
                                        break;
                                case '/':
                                        reader.Advance();
-                                       if (reader.TryPeak ('>')) {
+                                       if (reader.TryPeek ('>')) {
                                                reader.Advance();
                                                addTok (ref reader, XmlTokenType.EmptyElementClosing);
                                                if (--curObjectLevel > 0)
@@ -185,7 +185,7 @@ namespace CrowEdit.Xml
                                                                addTok (ref reader, XmlTokenType.LineBreak);
                                                                continue;
                                                        }
-                                                       if (reader.TryPeak ("<")) {
+                                                       if (reader.TryPeek ("<")) {
                                                                addTok (ref reader, XmlTokenType.Content);
                                                                break;
                                                        } else
index 3d2bd9a6a39cf8e8784c122174fc5169437e00b2..8aaba23e9a99ff9b7f9d4aa3bf190ec15fc2143e 100644 (file)
@@ -3,13 +3,10 @@
                <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>
index 3b4cc64df6d699be550feaf9674fef149ddb5493..5f142b0903439ad6fb9f09c076a132c708219e02 100644 (file)
@@ -3,7 +3,8 @@
                <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>
index 19c133cb2ed9032ca87a215f1c65df72180de05e..a1377a349e0544b2408609d6f9cd8d4ede496396 100644 (file)
@@ -1,4 +1,4 @@
-// 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)
 
@@ -44,13 +44,10 @@ namespace CrowEdit
                                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)
@@ -79,6 +76,13 @@ namespace CrowEdit
 
                        reloadWinConfigs ();
 
+                       foreach (Service service in Services) {
+                               if (TryGetWindow (service.ConfigurationWindowPath, out Window win))
+                                       win.DataSource = service;
+                       }
+
+                       reloadLogsConfigs ();
+
                        reopenLastProjectList ();
 
                        reopenLastDocumentList ();
@@ -87,6 +91,7 @@ namespace CrowEdit
                {
                        saveProjectList ();
                        saveOpenedDocumentList ();
+                       saveLogsConfig ();
                        saveWinConfigs ();
                }
                DockStack mainDock;
@@ -128,7 +133,6 @@ namespace CrowEdit
                        );
                }
 
-
                static void loadWindowWithThisDataSource(object sender, string path) {
                        Widget w = sender as Widget;
                        CrowEdit e = w.IFace as CrowEdit;
@@ -150,7 +154,6 @@ namespace CrowEdit
 
                        Configuration.Global.Save ();
                }
-
                void reloadWinConfigs() {
 
                        if (Configuration.Global.TryGet<string>("WinConfigs", out string conf) && !string.IsNullOrEmpty(conf))
@@ -160,8 +163,25 @@ namespace CrowEdit
                                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;
@@ -189,9 +209,7 @@ namespace CrowEdit
                                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;
                }
@@ -303,7 +321,10 @@ namespace CrowEdit
                        if (prj != null)
                                CurrentProject = prj;
                }
-
-       }
+        public override Stream GetStreamFromPath(string path)
+        {
+            return base.GetStreamFromPath(path);
+        }
+    }
 }
 
index bd16c817dd136348bbec766a7cca54a4b97f1f16..8734e7d65640ce2b97a88b76284668d466249939 100644 (file)
@@ -33,9 +33,9 @@
                                                                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"
index 70729c899182ea0743f1e2cba0aef00c507f6209..b00d43ae3192685467a5210d13e15f67df9aa431 100644 (file)
                                                                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">
index f547e5204e3e0986e9361b724829ac1f6ee674f2..de66b595d0de124bf2863127bd9e1d22b803dc0f 100644 (file)
@@ -1,36 +1,88 @@
 <?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>
 
index b4e587751272059ad2829afd15413f5cf076546f..fc22be213ec081daaa1b5a3277496e949562c013 100644 (file)
@@ -3,21 +3,26 @@
        <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/>
index 61be6df37670e16f6d2b3257ae32314d462e5e03..e60c384d8818e151ce3615327b278e5899ba0b5f 100644 (file)
@@ -30,6 +30,8 @@
                                                                                <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"/>