enhancements to ICARUS script editor

This commit is contained in:
Michael Becker 2020-08-31 04:42:32 -04:00
parent 0ca87e490f
commit 04b76e2cb1
No known key found for this signature in database
GPG Key ID: 506F54899E2BFED7
13 changed files with 350 additions and 51 deletions

View File

@ -5,6 +5,8 @@
<Command ID="Icarus_ContextMenu_Comment" Title="Comment Selected Items" />
<Command ID="Icarus_ContextMenu_TEST_EXPRESSION_EDITOR" Title="Test E_xpression Editor" />
<Command ID="Icarus_ContextMenu_Insert_From_File" Title="Insert Commands from File..." />
<Command ID="Icarus_ContextMenu">
<Items>
<CommandReference CommandID="EditCut" />
@ -12,6 +14,8 @@
<CommandReference CommandID="EditPaste" />
<CommandReference CommandID="EditDelete" />
<Separator />
<CommandReference CommandID="Icarus_ContextMenu_Insert_From_File" />
<Separator />
<CommandReference CommandID="Icarus_ContextMenu_Comment" />
<CommandReference CommandID="Icarus_ContextMenu_TEST_EXPRESSION_EDITOR" />

View File

@ -29,7 +29,9 @@
<property name="can_focus">True</property>
<property name="model">tm</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
<object class="GtkTreeSelection">
<property name="mode">multiple</property>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="tvcCommand">

View File

@ -7,7 +7,7 @@
<Command ID="Icarus_Debug_StopDebugging" Title="Stop D_ebugging" />
<Command ID="Icarus_Debug_StepInto" Title="Step _Into" />
<Command ID="Icarus_Debug_StepOver" Title="Step _Over" />
<Command ID="Icarus_Debug">
<Command ID="Icarus_Debug" Title="_Debug">
<Items>
<CommandReference CommandID="Icarus_Debug_StartDebugging" />
<CommandReference CommandID="Icarus_Debug_BreakExecution" />

View File

@ -75,7 +75,11 @@ namespace UniversalEditor.Plugins.RavenSoftware.UserInterface.Editors.Icarus
IcarusScriptEditorCommand cmd = e.Item.GetExtraData<IcarusScriptEditorCommand>("command");
BeginEdit();
RecursiveAddCommand(ScriptEditorCommandToOMCommand(cmd));
IcarusCommand omcmd = ScriptEditorCommandToOMCommand(cmd);
RecursiveAddCommand(omcmd);
(ObjectModel as IcarusScriptObjectModel).Commands.Add(omcmd);
EndEdit();
}
@ -210,6 +214,13 @@ namespace UniversalEditor.Plugins.RavenSoftware.UserInterface.Editors.Icarus
}
public override void UpdateSelections()
{
// FIXME: BehavEd writes three or more lines to the system clipboard with the following values:
// //(BHVD)
// (command text)
// ...
//
}
public IcarusScriptEditor()
@ -238,13 +249,118 @@ namespace UniversalEditor.Plugins.RavenSoftware.UserInterface.Editors.Icarus
Application.AttachCommandEventHandler("Icarus_Debug_StepInto", mnuDebugStepInto_Click);
Application.AttachCommandEventHandler("Icarus_Debug_StepOver", mnuDebugStepOver_Click);
Context.AttachCommandEventHandler("Icarus_ContextMenu_Comment", Icarus_ContextMenu_Comment);
Context.AttachCommandEventHandler("Icarus_ContextMenu_TEST_EXPRESSION_EDITOR", TestExpressionEditor);
Context.AttachCommandEventHandler("Icarus_ContextMenu_Insert_From_File", Icarus_ContextMenu_Insert_From_File);
// Commands["Icarus_Debug_BreakExecution"].Visible = false;
// Commands["Icarus_Debug_BreakExecution"].Visible = false;
// Commands["Icarus_Debug_StopDebugging"].Visible = false;
}
private void Icarus_ContextMenu_Comment(object sender, EventArgs e)
{
// we loop twice here because of the way BehavEd handles the "comment" feature -
// if at least one item is commented, it uncomments ALL selected lines; otherwise, it comments all selected lines.
// TODO: determine if we should follow original BehavEd warning
bool uncomment = false;
for (int i = 0; i < tv.SelectedRows.Count; i++)
{
TreeModelRow row = tv.SelectedRows[i];
IcarusCommand cmd = row.GetExtraData<IcarusCommand>("cmd");
if (cmd != null)
{
if (cmd.IsCommented)
uncomment = true;
}
}
for (int i = 0; i < tv.SelectedRows.Count; i++)
{
TreeModelRow row = tv.SelectedRows[i];
IcarusCommand cmd = row.GetExtraData<IcarusCommand>("cmd");
if (cmd != null)
{
BeginEdit();
cmd.IsCommented = !uncomment;
if (cmd is IIcarusContainerCommand)
{
IIcarusContainerCommand cnt = (cmd as IIcarusContainerCommand);
if (!(e is MBS.Framework.UserInterface.Input.Keyboard.KeyEventArgs && (((e as MBS.Framework.UserInterface.Input.Keyboard.KeyEventArgs).ModifierKeys & MBS.Framework.UserInterface.Input.Keyboard.KeyboardModifierKey.Control) == MBS.Framework.UserInterface.Input.Keyboard.KeyboardModifierKey.Control)))
{
for (int j = 0; j < cnt.Commands.Count; j++)
{
cnt.Commands[j].IsCommented = !uncomment;
row.Rows[j].RowColumns[0].Value = GetCommandText(cnt.Commands[j]);
}
}
}
EndEdit();
row.RowColumns[0].Value = GetCommandText(cmd);
}
}
}
[EventHandler(nameof(tv), "KeyDown")]
private void tv_KeyDown(object sender, MBS.Framework.UserInterface.Input.Keyboard.KeyEventArgs e)
{
if (e.Key == MBS.Framework.UserInterface.Input.Keyboard.KeyboardKey.Back)
{
Icarus_ContextMenu_Comment(sender, e);
}
}
private void Icarus_ContextMenu_Insert_From_File(object sender, EventArgs e)
{
FileDialog dlg = new FileDialog();
dlg.Mode = FileDialogMode.Open;
dlg.Text = "Insert Script from File";
dlg.FileNameFilters.Add("ICARUS scripts", "*.ibi; *.icarus");
if (dlg.ShowDialog() == DialogResult.OK)
{
string ext = System.IO.Path.GetExtension(dlg.SelectedFileName).ToLower();
if (ext.Equals(".icarus") || ext.Equals(".txt"))
{
using (System.IO.FileStream fs = System.IO.File.OpenRead(dlg.SelectedFileName))
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(fs))
{
string signature = sr.ReadLine();
sr.Close();
if (signature != "//Generated by BehavEd")
{
if (MessageDialog.ShowDialog(String.Format("The following file has NOT been written by BehavEd !!!:\r\n\r\n(\"{0}\" )\r\n\r\n... so do you *really* want to read it in?\r\n\r\n(This can mess up big-style if you load a programmer-script with nested statements etc)", dlg.SelectedFileName), "BehavEd", MessageDialogButtons.YesNo, MessageDialogIcon.Warning) == DialogResult.No)
{
return;
}
}
}
}
}
IcarusScriptObjectModel script = (ObjectModel as IcarusScriptObjectModel);
IcarusScriptObjectModel icarus = new IcarusScriptObjectModel();
DataFormats.Icarus.IcarusTextDataFormat ictxt = new DataFormats.Icarus.IcarusTextDataFormat();
Document.Load(icarus, ictxt, new Accessors.FileAccessor(dlg.SelectedFileName));
int start = script.Commands.Count;
script.Commands.Insert(start++, new IcarusCommandRem("============================="));
script.Commands.Insert(start++, new IcarusCommandRem(String.Format(" Appended File ({0}) follows... ", dlg.SelectedFileName)));
script.Commands.Insert(start++, new IcarusCommandRem("============================="));
for (int i = 0; i < icarus.Commands.Count; i++)
{
script.Commands.Insert(start, icarus.Commands[i]);
start++;
}
OnObjectModelChanged(EventArgs.Empty);
}
}
private System.Threading.Thread tDebugger = null;
private void mnuDebugStart_Click(object sender, EventArgs e)
{
@ -539,6 +655,12 @@ namespace UniversalEditor.Plugins.RavenSoftware.UserInterface.Editors.Icarus
StringBuilder sb = new StringBuilder();
if (command == null) return sb.ToString();
if (command.IsCommented)
{
sb.Append(new string('/', 13));
sb.Append(" ");
}
if (command is IcarusPredefinedCommand)
{
sb.Append((command as IcarusPredefinedCommand).Name);

View File

@ -0,0 +1,53 @@
//
// SingingStyleDefaultsOptionProvider.cs - provides a SettingsProvider for managing singing style defaults for SynthesizedAudioEditor
//
// Author:
// Michael Becker <alcexhim@gmail.com>
//
// Copyright (c) 2019-2020 Mike Becker's Software
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using MBS.Framework.UserInterface;
namespace UniversalEditor.Plugins.RavenSoftware.UserInterface.SettingsProviders
{
/// <summary>
/// Provides a <see cref="IcarusSettingsProvider" /> for managing Icarus settings.
/// </summary>
public class IcarusSettingsProvider : ApplicationSettingsProvider
{
public IcarusSettingsProvider()
{
SettingsGroups.Add("Editors:Raven Software:ICARUS Scripting:General", new Setting[]
{
new BooleanSetting("Re-open last file at startup"), // UE Platform Setting
new BooleanSetting("_Alphabetically-sort edit pulldowns"),
new BooleanSetting("Enable _SourceSafe functions"),
new BooleanSetting("_Warn before opening BehavEd-incompatible ICARUS script"),
});
SettingsGroups.Add("Editors:Raven Software:ICARUS Scripting:Directories", new Setting[]
{
new TextSetting("Script path"),
new TextSetting("SourceSafe script path"),
new TextSetting("SourceSafe configuration location"),
new TextSetting("Location of ICARUS compiler (IBIZE)"),
new TextSetting("Command description file (BehavEd.bhc)"),
new TextSetting("Source files path"),
});
}
}
}

View File

@ -37,11 +37,13 @@
<Compile Include="Editors\Icarus\IcarusScriptEditorEnumeration.cs" />
<Compile Include="Editors\Icarus\IcarusScriptEditorConfiguration.cs" />
<Compile Include="Editors\Icarus\IcarusScriptEditorCommand.cs" />
<Compile Include="SettingsProviders\IcarusSettingsProvider.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Controls\" />
<Folder Include="Dialogs\" />
<Folder Include="Editors\" />
<Folder Include="SettingsProviders\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\MBS.Framework\MBS.Framework\MBS.Framework.csproj">

View File

@ -76,7 +76,7 @@ namespace UniversalEditor.DataFormats.Icarus
line = line.Trim();
if (String.IsNullOrEmpty(line)) continue;
if (line.StartsWith("//") && !line.StartsWith("//$")) continue;
if (line.StartsWith("//") && !line.StartsWith("//$") && !line.StartsWith("//(BHVDREM)")) continue;
break;
}
@ -108,6 +108,13 @@ namespace UniversalEditor.DataFormats.Icarus
}
else
{
bool commented = false;
if (line.StartsWith("//(BHVDREM)"))
{
commented = true;
line = line.Substring(11);
}
int indexOfParen = FindToken(reader, ref line, '(');
string funcName = line.Substring(0, line.IndexOf('('));
@ -118,12 +125,14 @@ namespace UniversalEditor.DataFormats.Icarus
string parmList = line.Substring(start, indexOfParen - start);
parmList = parmList.Trim();
string[] parms = parmList.Split(new string[] { "," }, "\"");
string[] parms = parmList.Split(new string[] { "," }, "\"", "\"", StringSplitOptions.None, -1, false);
IcarusCommand cmd = IcarusCommand.CreateFromName(funcName);
// TODO: handle tabs within name
if (cmd == null) return null;
cmd.IsCommented = commented;
for (int i = 0; i < parms.Length; i++)
{
string parm = parms[i];
@ -135,14 +144,16 @@ namespace UniversalEditor.DataFormats.Icarus
comment = parm.Substring(comment_start + 2, comment_end - comment_start - 2);
parm = parm.Substring(0, comment_start) + parm.Substring(comment_end + 2);
}
parm = parm.Trim();
IcarusExpression expr = IcarusExpression.Parse(parm);
if (i < cmd.Parameters.Count)
{
cmd.Parameters[i].Value = new IcarusConstantExpression(parm);
cmd.Parameters[i].Value = expr;
}
else
{
cmd.Parameters.Add(new IcarusGenericParameter(null, new IcarusConstantExpression(parm)));
cmd.Parameters.Add(new IcarusGenericParameter(null, expr));
}
if (comment != null)
@ -164,14 +175,26 @@ namespace UniversalEditor.DataFormats.Icarus
private int FindToken(Reader reader, ref string line, char token)
{
int indexOfQuote = line.IndexOf('"');
int indexOfNextQuote = line.IndexOf('"', indexOfQuote + 1);
int index = line.IndexOf(token);
while (index == -1)
{
// try the next line
if (reader.EndOfStream) return -1;
line = line + reader.ReadLine();
index = line.IndexOf(')');
index = line.IndexOf(token);
}
while (index != -1 && (index > indexOfQuote && index < indexOfNextQuote))
{
// we are inside quotes, so ignore it and move to the next occurrence
index = line.IndexOf(token, index + 1);
indexOfQuote = line.IndexOf('"', index);
indexOfNextQuote = line.IndexOf('"', indexOfQuote + 1);
}
return index;
}
@ -183,6 +206,7 @@ namespace UniversalEditor.DataFormats.Icarus
Writer tw = base.Accessor.Writer;
tw.WriteLine("//Generated by BehavEd");
tw.WriteLine();
foreach (IcarusCommand command in script.Commands)
{
@ -193,46 +217,50 @@ namespace UniversalEditor.DataFormats.Icarus
private void WriteCommand(Writer tw, IcarusCommand command, int indentLength = 0)
{
string indent = new string(' ', indentLength * 4);
/*
if (command is IcarusCommandAffect)
{
IcarusCommandAffect cmd = (command as IcarusCommandAffect);
tw.Write(indent);
tw.WriteLine("affect ( \"" + cmd.Target + "\", " + cmd.AffectType.ToString() + " )");
tw.Write(indent);
tw.WriteLine("{");
foreach (IcarusCommand command2 in cmd.Commands)
{
WriteCommand(tw, command2, indentLength + 1);
}
if (command is IcarusPredefinedCommand)
{
IcarusPredefinedCommand cmd = (command as IcarusPredefinedCommand);
if (cmd.IsCommented)
{
tw.Write("//(BHVDREM) ");
}
tw.WriteLine();
tw.Write(indent);
tw.WriteLine("}");
if (cmd is IcarusCommandMacro)
{
IcarusCommandMacro macro = (cmd as IcarusCommandMacro);
tw.WriteLine(String.Format("//$\"{0}\"@{1}", macro.MacroName, macro.Commands.Count));
for (int i = 0; i < macro.Commands.Count; i++)
{
WriteCommand(tw, macro.Commands[i]);
}
}
else
{
tw.Write(cmd.Name);
tw.Write(" ( ");
}
else if (command is IcarusCommandSet)
{
IcarusCommandSet cmd = (command as IcarusCommandSet);
tw.Write(indent);
tw.WriteLine("set ( " + cmd.Property.ToString() + ", " + cmd.Value.ToString() + " );");
}
else if (command is IcarusCommandUse)
{
IcarusCommandUse cmd = (command as IcarusCommandUse);
tw.Write(indent);
tw.WriteLine("use ( " + cmd.Target.ToString() + " );");
}
else if (command is IcarusCommandWait)
{
IcarusCommandWait cmd = (command as IcarusCommandWait);
tw.Write(indent);
tw.WriteLine("wait ( " + cmd.Target.ToString() + " );");
}
*/
tw.Flush();
for (int i = 0; i < cmd.Parameters.Count; i++)
{
if (cmd.Parameters[i].ReadOnly)
{
tw.Write("/*!*/ ");
}
else if (cmd.Parameters[i].EnumerationName != null)
{
tw.Write(String.Format("/*@{0}*/ ", cmd.Parameters[i].EnumerationName));
}
tw.Write(cmd.Parameters[i].Value?.ToString());
if (i < cmd.Parameters.Count - 1)
{
tw.Write(", ");
}
}
tw.Write(" );");
}
tw.WriteLine();
}
}
}
}

View File

@ -41,8 +41,8 @@ namespace UniversalEditor.ObjectModels.Icarus.Commands
}));
}
public IcarusExpression Target { get { return Parameters["Target"].Value; } set { Parameters["Target"].Value = value; } }
public IcarusExpression AffectType { get { return Parameters["AffectType"].Value; } set { Parameters["AffectType"].Value = value; } }
public IcarusExpression Target { get { return Parameters[0].Value; } set { Parameters[0].Value = value; } }
public IcarusExpression AffectType { get { return Parameters[1].Value; } set { Parameters[1].Value = value; } }
public override object Clone()
{

View File

@ -44,9 +44,9 @@ namespace UniversalEditor.ObjectModels.Icarus.Commands
public override object Clone()
{
IcarusCommandIf clone = new IcarusCommandIf();
clone.Source = (Source.Clone() as IcarusExpression);
clone.Comparison = (Comparison.Clone() as IcarusExpression);
clone.Target = (Target.Clone() as IcarusExpression);
clone.Source = (Source?.Clone() as IcarusExpression);
clone.Comparison = (Comparison?.Clone() as IcarusExpression);
clone.Target = (Target?.Clone() as IcarusExpression);
return clone;
}
}

View File

@ -0,0 +1,48 @@
//
// IcarusCommandRem.cs
//
// Author:
// Michael Becker <alcexhim@gmail.com>
//
// Copyright (c) 2020 Mike Becker's Software
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using UniversalEditor.ObjectModels.Icarus.Expressions;
using UniversalEditor.ObjectModels.Icarus.Parameters;
namespace UniversalEditor.ObjectModels.Icarus.Commands
{
public class IcarusCommandRem : IcarusPredefinedCommand
{
public IcarusCommandRem() : this(String.Empty)
{
}
public IcarusCommandRem(string comment)
{
Parameters.Add(new IcarusGenericParameter("comment", null, new IcarusConstantExpression(comment)));
}
public IcarusExpression Comment { get { return Parameters[0].Value; } set { Parameters[0].Value = value; } }
public override string Name => "rem";
public override object Clone()
{
IcarusCommandRem clone = new IcarusCommandRem();
clone.Comment = (Comment?.Clone() as IcarusExpression);
return clone;
}
}
}

View File

@ -36,7 +36,14 @@ namespace UniversalEditor.ObjectModels.Icarus
public IcarusParameter.IcarusParameterCollection Parameters { get; } = new IcarusParameter.IcarusParameterCollection();
public abstract object Clone();
/// <summary>
/// Gets or sets a value indicating whether this <see cref="IcarusCommand" /> is commented by the graphical editor (e.g. UniversalEditor or
/// BehavEd).
/// </summary>
/// <value><c>true</c> if is commented; otherwise, <c>false</c>.</value>
public bool IsCommented { get; set; } = false;
public abstract object Clone();
private static Dictionary<string, Type> _cmdsByName = null;
public static IcarusCommand CreateFromName(string funcName)

View File

@ -20,6 +20,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using UniversalEditor.ObjectModels.Icarus.Expressions;
namespace UniversalEditor.ObjectModels.Icarus
{
@ -43,5 +44,36 @@ namespace UniversalEditor.ObjectModels.Icarus
if (ret) return (T)val;
return defaultValue;
}
public static IcarusExpression Parse(string parm)
{
if (parm.StartsWith("\"") && parm.EndsWith("\""))
{
return new IcarusConstantExpression(parm.Substring(1, parm.Length - 2));
}
else if (parm.StartsWith("$") && parm.EndsWith("$"))
{
return new IcarusConstantExpression(parm);
}
else
{
switch (parm)
{
case "FLOAT":
{
return new IcarusConstantExpression(IcarusVariableDataType.Float);
}
case "STRING":
{
return new IcarusConstantExpression(IcarusVariableDataType.String);
}
case "VECTOR":
{
return new IcarusConstantExpression(IcarusVariableDataType.Vector);
}
}
}
return null;
}
}
}

View File

@ -82,6 +82,7 @@
<Compile Include="ObjectModels\Icarus\IcarusTagType.cs" />
<Compile Include="ObjectModels\Icarus\Commands\IcarusCommandIf.cs" />
<Compile Include="ObjectModels\Icarus\Commands\IcarusCommandPlay.cs" />
<Compile Include="ObjectModels\Icarus\Commands\IcarusCommandRem.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />