diff --git a/.paket/Paket.Restore.targets b/.paket/Paket.Restore.targets index 305e736c..52f41c60 100644 --- a/.paket/Paket.Restore.targets +++ b/.paket/Paket.Restore.targets @@ -11,23 +11,49 @@ $(MSBuildThisFileDirectory)..\ $(PaketRootPath)paket-files\paket.restore.cached $(PaketRootPath)paket.lock + classic + proj + assembly + native /Library/Frameworks/Mono.framework/Commands/mono mono - - $(PaketRootPath)paket.exe - $(PaketToolsPath)paket.exe - "$(PaketExePath)" - $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" - + + $(PaketRootPath)paket.bootstrapper.exe + $(PaketToolsPath)paket.bootstrapper.exe + $([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\ + + + + + $(PaketRootPath)paket.exe + $(PaketToolsPath)paket.exe + $(PaketToolsPath)paket.exe + $(_PaketBootStrapperExeDir)paket.exe + paket.exe + + + $(PaketRootPath)paket + $(PaketToolsPath)paket + $(PaketToolsPath)paket + + + $(PaketRootPath)paket.exe + $(PaketToolsPath)paket.exe + + + $(PaketBootStrapperExeDir)paket.exe + + + paket + + <_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)")) - dotnet "$(PaketExePath)" + dotnet "$(PaketExePath)" + $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" + "$(PaketExePath)" - - "$(PaketExePath)" - $(PaketRootPath)paket.bootstrapper.exe - $(PaketToolsPath)paket.bootstrapper.exe "$(PaketBootStrapperExePath)" $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)" @@ -36,9 +62,16 @@ true true + + + True - + + + + + @@ -72,12 +105,16 @@ true - + + true - + @@ -141,16 +178,19 @@ + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length) $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0]) $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1]) $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4]) - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5]) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5]) %(PaketReferencesFileLinesInfo.PackageVersion) All - runtime + runtime + runtime true + true @@ -182,19 +222,27 @@ false + $(MSBuildVersion) + 15.8.0 <_NuspecFilesNewLocation Include="$(BaseIntermediateOutputPath)$(Configuration)\*.nuspec"/> + + $(MSBuildProjectDirectory)/$(MSBuildProjectFile) true - false - true + false + true + false + true + false + true $(BaseIntermediateOutputPath)$(Configuration) $(BaseIntermediateOutputPath) @@ -209,9 +257,52 @@ - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \@\* + \*\@ + + + + + \@\{ + \} + + + + + \@\( + \) + + + + + @@ + + + + \@ + \)|\< + + + + + + + . + + + + + @@ + + + + \@\* + \*\@ + + + @ + + + " + " + + + + + + + + ' + ' + + + + + + + + this + base + + + + as + is + new + sizeof + typeof + stackalloc + + + + true + false + + + + else + if + switch + case + default + do + for + foreach + in + while + lock + + + + break + continue + goto + return + + + + yield + partial + global + where + select + group + by + into + from + ascending + descending + orderby + let + join + on + equals + var + dynamic + + + + try + throw + catch + finally + + + + checked + unchecked + + + + fixed + unsafe + + + + bool + byte + char + decimal + double + enum + float + int + long + sbyte + short + struct + uint + ushort + ulong + + + + class + interface + delegate + object + string + void + + + + explicit + implicit + operator + + + + params + ref + out + + + + abstract + const + event + extern + override + readonly + sealed + static + virtual + volatile + + + + public + protected + private + internal + + + + namespace + using + + + + get + set + add + remove + + + + null + value + + + + + \b + [\d\w_]+ # an identifier + (?=\s*\() # followed by ( + + + + + \b0[xX][0-9a-fA-F]+ # hex number + | + ( \b\d+(\.[0-9]+)? #number with optional floating point + | \.[0-9]+ #or just starting with floating point + ) + ([eE][+-]?[0-9]+)? # optional exponent + + + + [?,.;()\[\]{}+\-/%*<>^+~!|&]+ + + + + + + \ No newline at end of file diff --git a/REAL.NET.sln b/REAL.NET.sln index 73878130..44d7ace9 100644 --- a/REAL.NET.sln +++ b/REAL.NET.sln @@ -40,6 +40,9 @@ EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Repo", "src\Repo\Repo.fsproj", "{9E7065A4-BA5E-4752-84BF-54D5C00DB60C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{F12CD406-E1CD-43B7-B4BC-E2991723C56E}" + ProjectSection(SolutionItems) = preProject + Highlighter.xshd = Highlighter.xshd + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginManager", "src\PluginManager\PluginManager.csproj", "{8B9C8D76-65B3-4A01-9D6F-B6192A823642}" EndProject @@ -55,6 +58,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AirSim", "src\AirSim\AirSim EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfControlsLib.Tests", "tests\WpfControlsLib.Tests\WpfControlsLib.Tests.csproj", "{8EDF4429-251A-416D-BB68-93F227191BCF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenerationRulesPlugin", "src\plugins\GenerationRulesPlugin\GenerationRulesPlugin.csproj", "{073FFD76-E332-4D14-B90E-08636940D330}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -193,6 +198,18 @@ Global {8EDF4429-251A-416D-BB68-93F227191BCF}.Release|Any CPU.Build.0 = Release|Any CPU {8EDF4429-251A-416D-BB68-93F227191BCF}.Release|x64.ActiveCfg = Release|Any CPU {8EDF4429-251A-416D-BB68-93F227191BCF}.Release|x64.Build.0 = Release|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.Debug|Any CPU.Build.0 = Debug|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.Debug|x64.ActiveCfg = Debug|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.Debug|x64.Build.0 = Debug|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.MonoRelease|Any CPU.ActiveCfg = Release|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.MonoRelease|Any CPU.Build.0 = Release|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.MonoRelease|x64.ActiveCfg = Release|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.MonoRelease|x64.Build.0 = Release|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.Release|Any CPU.ActiveCfg = Release|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.Release|Any CPU.Build.0 = Release|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.Release|x64.ActiveCfg = Release|Any CPU + {073FFD76-E332-4D14-B90E-08636940D330}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -204,6 +221,7 @@ Global {A0056C25-4EF7-4AF9-99E4-C13B937A3343} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} {C57410A1-A86F-418B-9AC7-38249450C497} = {F12CD406-E1CD-43B7-B4BC-E2991723C56E} {8EDF4429-251A-416D-BB68-93F227191BCF} = {ED8079DD-2B06-4030-9F0F-DC548F98E1C4} + {073FFD76-E332-4D14-B90E-08636940D330} = {F12CD406-E1CD-43B7-B4BC-E2991723C56E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D0B60BC3-B119-4CD6-8FC4-CD8FA1429BE4} diff --git a/src/WpfEditor/View/MainWindow.xaml.cs b/src/WpfEditor/View/MainWindow.xaml.cs index 81cf0f2f..40333e42 100644 --- a/src/WpfEditor/View/MainWindow.xaml.cs +++ b/src/WpfEditor/View/MainWindow.xaml.cs @@ -88,8 +88,8 @@ public MainWindow() this.modelSelector.Init(this.model); this.modelSelector.ChangeModel(2); - this.InitAndLaunchPlugins(); this.InitToolbar(); + this.InitAndLaunchPlugins(); } private void Reinit(object sender, EventArgs e) @@ -130,7 +130,7 @@ private void InitAndLaunchPlugins() foreach (var plugindir in pluginDirs) { var dirs = new List(System.IO.Directory.GetDirectories(plugindir + "/bin")); - var config = new PluginConfig(this.model, null, null, this.Console, null); + var config = new PluginConfig(this.model, null, this.Toolbar, this.Console, null); foreach (var dir in dirs) { libs.LaunchPlugins(dir, config); diff --git a/src/plugins/GenerationRulesPlugin/GenerationRulesPlugin.cs b/src/plugins/GenerationRulesPlugin/GenerationRulesPlugin.cs new file mode 100644 index 00000000..152faa86 --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/GenerationRulesPlugin.cs @@ -0,0 +1,153 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using EditorPluginInterfaces.Toolbar; +using GenerationRulesPlugin.plugins.GenerationRulesPlugin; +using ICSharpCode.AvalonEdit.CodeCompletion; +using RazorEngine; +using RazorEngine.Templating; +using Repo; + +namespace GenerationRulesPlugin +{ + using System; + using EditorPluginInterfaces; + using WpfControlsLib.Controls.Toolbar; + + /// + /// + /// Represents model for Generation Rules Plugin. + /// + public class GenerationRulesPlugin : IPlugin + { + public string Name => "Generation Rules Plugin"; + + private GenerationRulesWindow window; + + private IConsole console; + private IModel model; + + public void SetConfig(PluginConfig config) + { + if (config == null) + { + throw new ArgumentException("This is not correct type of configuration"); + } + + this.console = config.Console; + this.console.SendMessage($"{this.Name} successfully launched"); + + this.model = config.Model; + IToolbar toolbar = config.Toolbar; + + var command = new Command(() => + { + this.window = new GenerationRulesWindow { Plugin = this }; + this.window.Show(); + }); + var button = new Button(command, "Opens code generation rules editor", "redo.png"); + toolbar.AddButton(button); + } + + /// + /// Compiles template from input and returns the result. + /// + /// Input to compile from. + /// Compilation result. + public string CompileTemplate(string input) + { + input = "@using GenerationRulesPlugin\n" + input; + IRepo repo = this.model.Repo; + Repo.IModel currentModel = repo.Model("RobotsTestModel"); + var regex = new Regex(@"@Model\.(?\w+)\.(?\w+)(?\W?)"); + MatchCollection matches = regex.Matches(input); + string template = input; + foreach (Match match in matches) + { + string attribute = match.Groups["attribute"].Captures[0].Value; + string element = match.Groups["element"].Captures[0].Value; + Group lastCharacterMatchGroup = match.Groups["lastCharacter"]; + string lastCharacter = lastCharacterMatchGroup.Success + ? lastCharacterMatchGroup.Captures[0].Value + : string.Empty; + // TODO Fix: match.Value is not valid pattern value (it has not escaped parentheses) + if (match.Value.Last() == ')') + { + template = Regex.Replace(template, match.Value.Substring(0, match.Value.Length - 1) + @"\)", + $"@Model.FindElement(\"{element}\").FindAttribute(\"{attribute}\").StringValue{lastCharacter}"); + continue; + } + + template = Regex.Replace(template, match.Value, + $"@Model.FindElement(\"{element}\").FindAttribute(\"{attribute}\").StringValue{lastCharacter}"); + } + + try + { + return Engine.Razor.RunCompile(template, $"key{new Random().Next()}", typeof(Repo.IModel), + currentModel).Trim(); + } + catch (Exception e) + { + return $"[Compiling error]\n{e.Message}"; + } + } + + /// + /// Fills IList<ICompletionData> with proper elements or element attributes. + /// + /// List to fill. + /// Defines whether element or attribute data is needed. + /// Element name which attributes is needed. + public void GenerateCompletionList(IList data, bool isElement, string element = null) + { + if (isElement) + { + foreach (IElement el in this.model.Repo.Model("RobotsTestModel").Elements) + { + data.Add(new GenerationRulesCompletionData(el.Name)); + } + } + else + { + try + { + foreach (IAttribute attribute in this.model.Repo.Model("RobotsTestModel").FindElement(element).Attributes) + { + data.Add(new GenerationRulesCompletionData(attribute.Name)); + } + } + catch (MultipleElementsException) + { + data.Clear(); + } + } + + return; + } + } + + /// + /// Represents auxiliary class which contains extension method to find attribute of element. + /// + public static class ElementExtension + { + /// + /// Finds attribute of the element. + /// + /// Element to find attribute of. + /// Name of the attribute. + /// Required attribute. + public static IAttribute FindAttribute(this IElement element, string attributeName) + { + foreach (IAttribute attribute in element.Attributes.Where(a => a.Name == attributeName)) + { + return attribute; + } + + throw new AttributeNotFoundException(attributeName); + } + } + + +} diff --git a/src/plugins/GenerationRulesPlugin/GenerationRulesPlugin.csproj b/src/plugins/GenerationRulesPlugin/GenerationRulesPlugin.csproj new file mode 100644 index 00000000..06329406 --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/GenerationRulesPlugin.csproj @@ -0,0 +1,121 @@ + + + + + Debug + AnyCPU + {073FFD76-E332-4D14-B90E-08636940D330} + library + GenerationRulesPlugin + GenerationRulesPlugin + v4.7.2 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\..\packages\FSharp.Core.4.5.0\lib\net45\FSharp.Core.dll + + + ..\..\..\packages\AvalonEdit.5.0.4\lib\Net40\ICSharpCode.AvalonEdit.dll + + + ..\..\..\packages\RazorEngine.3.10.0\lib\net45\RazorEngine.dll + + + + + ..\..\..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll + + + + + + + + + 4.0 + + + + + + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + + GenerationRulesWindow.xaml + + + + + UserControl1.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + {6e5f1b5d-f165-4cec-a240-8887ebd28e3b} + EditorPluginInterfaces + + + {9e7065a4-ba5e-4752-84bf-54d5c00db60c} + Repo + + + {1dcb1d77-ab11-404c-bce4-8eb7bf8f549d} + WpfControlsLib + + + + \ No newline at end of file diff --git a/src/plugins/GenerationRulesPlugin/GenerationRulesWindow.xaml b/src/plugins/GenerationRulesPlugin/GenerationRulesWindow.xaml new file mode 100644 index 00000000..2577a1d1 --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/GenerationRulesWindow.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/GenerationRulesPlugin/GenerationRulesWindow.xaml.cs b/src/plugins/GenerationRulesPlugin/GenerationRulesWindow.xaml.cs new file mode 100644 index 00000000..84c2e05b --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/GenerationRulesWindow.xaml.cs @@ -0,0 +1,11 @@ +namespace GenerationRulesPlugin +{ + using System.Windows; + + /// + /// Interaction logic for GenerationRulesWindow.xaml + /// + public partial class GenerationRulesWindow : Window + { + } +} \ No newline at end of file diff --git a/src/plugins/GenerationRulesPlugin/Properties/AssemblyInfo.cs b/src/plugins/GenerationRulesPlugin/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..83292a62 --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("GenerationRulesPlugin")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("GenerationRulesPlugin")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly:ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/plugins/GenerationRulesPlugin/Properties/Resources.Designer.cs b/src/plugins/GenerationRulesPlugin/Properties/Resources.Designer.cs new file mode 100644 index 00000000..5dbba0ba --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/Properties/Resources.Designer.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace GenerationRulesPlugin.Properties { + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if ((resourceMan == null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GenerationRulesPlugin.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/src/plugins/GenerationRulesPlugin/Properties/Resources.resx b/src/plugins/GenerationRulesPlugin/Properties/Resources.resx new file mode 100644 index 00000000..af7dbebb --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/plugins/GenerationRulesPlugin/Properties/Settings.Designer.cs b/src/plugins/GenerationRulesPlugin/Properties/Settings.Designer.cs new file mode 100644 index 00000000..2748611d --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace GenerationRulesPlugin.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/src/plugins/GenerationRulesPlugin/Properties/Settings.settings b/src/plugins/GenerationRulesPlugin/Properties/Settings.settings new file mode 100644 index 00000000..033d7a5e --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/plugins/GenerationRulesPlugin/UserControl1.xaml b/src/plugins/GenerationRulesPlugin/UserControl1.xaml new file mode 100644 index 00000000..b2fc7cc0 --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/UserControl1.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/plugins/GenerationRulesPlugin/UserControl1.xaml.cs b/src/plugins/GenerationRulesPlugin/UserControl1.xaml.cs new file mode 100644 index 00000000..fcc1a0f8 --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/UserControl1.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace GenerationRulesPlugin +{ + /// + /// Interaction logic for UserControl1.xaml + /// + public partial class UserControl1 : UserControl + { + public UserControl1() + { + InitializeComponent(); + } + } +} diff --git a/src/plugins/GenerationRulesPlugin/packages.config b/src/plugins/GenerationRulesPlugin/packages.config new file mode 100644 index 00000000..1023f919 --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/plugins/GenerationRulesPlugin/plugins/GenerationRulesPlugin/GenerationRulesCompletionData.cs b/src/plugins/GenerationRulesPlugin/plugins/GenerationRulesPlugin/GenerationRulesCompletionData.cs new file mode 100644 index 00000000..a3b99726 --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/plugins/GenerationRulesPlugin/GenerationRulesCompletionData.cs @@ -0,0 +1,41 @@ +using System; +using System.Windows.Media; +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Editing; + +namespace GenerationRulesPlugin.plugins.GenerationRulesPlugin +{ + /// + /// Describes an entry in the specified for Generation Rules Plugin. + /// + /// + internal class GenerationRulesCompletionData : ICompletionData + { + public GenerationRulesCompletionData(string text) + { + this.Text = text; + } + + + public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) + { + if (completionSegment.Offset == completionSegment.EndOffset) + { + textArea.Document.Insert(completionSegment.Offset, this.Text); + } + else + { + textArea.Document.Replace(completionSegment, this.Text); + } + } + + public ImageSource Image { get; } + public string Text { get; } + public object Content => this.Text; + + public object Description => "Model property" + this.Text; + + public double Priority { get; } + } +} diff --git a/src/plugins/GenerationRulesPlugin/plugins/GenerationRulesPlugin/GenerationRulesWindow.cs b/src/plugins/GenerationRulesPlugin/plugins/GenerationRulesPlugin/GenerationRulesWindow.cs new file mode 100644 index 00000000..e5d34500 --- /dev/null +++ b/src/plugins/GenerationRulesPlugin/plugins/GenerationRulesPlugin/GenerationRulesWindow.cs @@ -0,0 +1,145 @@ +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using System.Windows; +using System.Windows.Input; +using System.Xml; +using GenerationRulesPlugin.plugins.GenerationRulesPlugin; +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.AvalonEdit.Highlighting.Xshd; +using Microsoft.Win32; + +namespace GenerationRulesPlugin +{ + /// + /// Represents Window for Generations Rules Plugin. + /// + public partial class GenerationRulesWindow + { + /// + /// Window's plugin + /// + public GenerationRulesPlugin Plugin { get; set; } + + private CompletionWindow completionWindow; + + public GenerationRulesWindow() + { + this.InitializeComponent(); + using (var stream = new FileStream(@"..\..\..\..\Highlighter.xshd", FileMode.Open)) + { + try + { + this.CodeEditor.SyntaxHighlighting = + HighlightingLoader.Load(HighlightingLoader.LoadXshd(new XmlTextReader(stream)), + HighlightingManager.Instance); + } + catch (HighlightingDefinitionInvalidException e) + { + this.CodeEditor.Text = $"[Invalid Syntax Highlighting Definition]\n{e.Message}"; + } + } + + this.CodeEditor.TextArea.TextEntering += TextEntering; + this.CodeEditor.TextArea.TextEntered += TextEntered; + } + + private void OnSaveClick(object sender, RoutedEventArgs e) + { + var saveFileDialog = new SaveFileDialog(); + if (saveFileDialog.ShowDialog() != true) + { + return; + } + + string filename = saveFileDialog.FileName; + File.WriteAllText(filename, this.CodeEditor.Text); + MessageBox.Show("File Saved"); + } + + private void OnSaveGeneratedCodeClick(object sender, RoutedEventArgs e) + { + var saveFileDialog = new SaveFileDialog(); + if (saveFileDialog.ShowDialog() != true) + { + return; + } + + string filename = saveFileDialog.FileName; + File.WriteAllText(filename, this.ResultBox.Text); + MessageBox.Show("File Saved"); + } + + private void OnGenerateCodeClick(object sender, RoutedEventArgs e) + { + string result = this.Plugin.CompileTemplate(this.CodeEditor.Text); + this.ResultBox.Text = result; + } + + private void TextEntered(object sender, TextCompositionEventArgs e) + { + if (e.Text == "@") + { + completionWindow = new CompletionWindow(this.CodeEditor.TextArea); + IList data = completionWindow.CompletionList.CompletionData; + data.Add(new GenerationRulesCompletionData("Model")); + data.Add(new GenerationRulesCompletionData("for")); + data.Add(new GenerationRulesCompletionData("if")); + data.Add(new GenerationRulesCompletionData("while")); + data.Add(new GenerationRulesCompletionData("Include")); + completionWindow.Show(); + completionWindow.Closed += (o, args) => this.completionWindow = null; + } + + if (e.Text == ".") + { + completionWindow = new CompletionWindow(this.CodeEditor.TextArea); + IList data = completionWindow.CompletionList.CompletionData; + DocumentLine line = + this.CodeEditor.TextArea.Document.GetLineByNumber(this.CodeEditor.TextArea.Caret.Line); + int lineCaretPosition = this.CodeEditor.TextArea.Caret.Offset - line.Offset; + MatchCollection matches = new Regex(@"@Model\.").Matches(this.CodeEditor.TextArea.Document.GetText(line)); + foreach (Match match in matches) + { + if (match.Index + match.Length == lineCaretPosition) + { + Plugin.GenerateCompletionList(data, true, null); + } + } + + if (data.Count != 0) + { + completionWindow.Show(); + completionWindow.Closed += (o, args) => this.completionWindow = null; + return; + } + + var regex = new Regex(@"@Model\.(?\w+)\."); + matches = regex.Matches(this.CodeEditor.TextArea.Document.GetText(line)); + foreach (Match match in matches) + { + if (match.Index + match.Length == lineCaretPosition) + { + Plugin.GenerateCompletionList(data, false, match.Groups["element"].Captures[0].Value); + } + } + + if (data.Count != 0) + { + completionWindow.Show(); + completionWindow.Closed += (o, args) => this.completionWindow = null; + } + } + } + + private void TextEntering(object sender, TextCompositionEventArgs e) + { + if (!char.IsLetterOrDigit(e.Text[0])) + { + completionWindow?.CompletionList.RequestInsertion(e); + } + } + } +} \ No newline at end of file