Add Run Script menu item

This commit is contained in:
Neil Brommer 2023-07-19 15:09:25 -07:00
parent 2a9911d973
commit 719d72c8b6
8 changed files with 126 additions and 345 deletions

View file

@ -1,5 +1,4 @@
using System;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
namespace Papercut.Core;
@ -20,22 +19,9 @@ public class RoslynHost
ScriptOptions options = ScriptOptions.Default
.AddImports(imports);
try
{
var result = await CSharpScript.RunAsync(code, options, globals,
await CSharpScript.RunAsync(code, options, globals,
cancellationToken: cancellationToken);
}
catch (CompilationErrorException ex)
{
Console.WriteLine(code);
Console.WriteLine(ex);
}
catch (Exception ex)
{
Console.WriteLine(code);
Console.WriteLine(ex);
}
}
}
public class RoslynHostGlobals

View file

@ -1,10 +1,10 @@
using AppKit;
using AppKit;
using Foundation;
namespace Papercut.Macos;
[Register("AppDelegate")]
public class AppDelegate : NSApplicationDelegate
public partial class AppDelegate : NSApplicationDelegate
{
public AppDelegate()
{
@ -19,4 +19,17 @@ public class AppDelegate : NSApplicationDelegate
{
// Insert code here to tear down your application
}
partial void RunScriptMenuItemClicked(AppKit.NSMenuItem sender)
{
ScriptRunner.RunScript(
NSApplication.SharedApplication.KeyWindow.WindowController
as MainWindow);
}
[Action("validateMenuItem:")]
public bool ValidateMenuItem(AppKit.NSMenuItem sender)
{
return true;
}
}

View file

@ -9,18 +9,13 @@ using System.CodeDom.Compiler;
namespace Papercut.Macos
{
[Register ("ScriptViewController")]
partial class ScriptViewController
partial class AppDelegate
{
[Outlet]
AppKit.NSTextView ScriptTextBox { get; set; }
[Action ("RunScriptMenuItemClicked:")]
partial void RunScriptMenuItemClicked (AppKit.NSMenuItem sender);
void ReleaseDesignerOutlets ()
{
if (ScriptTextBox != null) {
ScriptTextBox.Dispose ();
ScriptTextBox = null;
}
}
}
}

View file

@ -6,17 +6,17 @@
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Application-->
<!--Papercut Application-->
<scene sceneID="JPo-4y-FX3">
<objects>
<application id="hnw-xV-0zn" sceneMemberID="viewController">
<application id="hnw-xV-0zn" customClass="PapercutApplication" sceneMemberID="viewController">
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="Papercut" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Papercut" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About TestStoryboard" id="5kV-Vb-QxS">
<menuItem title="About Papercut" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
@ -106,7 +106,12 @@
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
<menuItem title="Run Script" keyEquivalent="r" id="JLu-BT-CR7" userLabel="Run Script"/>
<menuItem title="Run Script" keyEquivalent="r" id="JLu-BT-CR7" userLabel="Run Script">
<attributedString key="attributedTitle"/>
<connections>
<action selector="RunScriptMenuItemClicked:" target="Voe-Tx-rLC" id="HF3-L2-yVY"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
@ -140,12 +145,6 @@
<action selector="paste:" target="Ady-hI-5gd" id="UvS-8e-Qdg"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="Ady-hI-5gd" id="cEh-KX-wJQ"/>
</connections>
</menuItem>
<menuItem title="Delete" id="pa3-QI-u2k">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
@ -329,268 +328,6 @@
</items>
</menu>
</menuItem>
<menuItem title="Format" id="jxT-CU-nIS">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
<items>
<menuItem title="Font" id="Gi5-1S-RQB">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
<connections>
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
</connections>
</menuItem>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
</connections>
</menuItem>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
</connections>
</menuItem>
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
<connections>
<action selector="underline:" target="Ady-hI-5gd" id="FYS-2b-JAY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
</connections>
</menuItem>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
<menuItem title="Kern" id="jBQ-r6-VK2">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
<items>
<menuItem title="Use Default" id="GUa-eO-cwY">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardKerning:" target="Ady-hI-5gd" id="6dk-9l-Ckg"/>
</connections>
</menuItem>
<menuItem title="Use None" id="cDB-IK-hbR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffKerning:" target="Ady-hI-5gd" id="U8a-gz-Maa"/>
</connections>
</menuItem>
<menuItem title="Tighten" id="46P-cB-AYj">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="tightenKerning:" target="Ady-hI-5gd" id="hr7-Nz-8ro"/>
</connections>
</menuItem>
<menuItem title="Loosen" id="ogc-rX-tC1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="loosenKerning:" target="Ady-hI-5gd" id="8i4-f9-FKE"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligatures" id="o6e-r0-MWq">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
<items>
<menuItem title="Use Default" id="agt-UL-0e3">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardLigatures:" target="Ady-hI-5gd" id="7uR-wd-Dx6"/>
</connections>
</menuItem>
<menuItem title="Use None" id="J7y-lM-qPV">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffLigatures:" target="Ady-hI-5gd" id="iX2-gA-Ilz"/>
</connections>
</menuItem>
<menuItem title="Use All" id="xQD-1f-W4t">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAllLigatures:" target="Ady-hI-5gd" id="KcB-kA-TuK"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="OaQ-X3-Vso">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
<items>
<menuItem title="Use Default" id="3Om-Ey-2VK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unscript:" target="Ady-hI-5gd" id="0vZ-95-Ywn"/>
</connections>
</menuItem>
<menuItem title="Superscript" id="Rqc-34-cIF">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="superscript:" target="Ady-hI-5gd" id="3qV-fo-wpU"/>
</connections>
</menuItem>
<menuItem title="Subscript" id="I0S-gh-46l">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="subscript:" target="Ady-hI-5gd" id="Q6W-4W-IGz"/>
</connections>
</menuItem>
<menuItem title="Raise" id="2h7-ER-AoG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="raiseBaseline:" target="Ady-hI-5gd" id="4sk-31-7Q9"/>
</connections>
</menuItem>
<menuItem title="Lower" id="1tx-W0-xDw">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowerBaseline:" target="Ady-hI-5gd" id="OF1-bc-KW4"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
<connections>
<action selector="orderFrontColorPanel:" target="Ady-hI-5gd" id="mSX-Xz-DV3"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="copyFont:" target="Ady-hI-5gd" id="GJO-xA-L4q"/>
</connections>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteFont:" target="Ady-hI-5gd" id="JfD-CL-leO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="Fal-I4-PZk">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="d9c-me-L2H">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
<connections>
<action selector="alignLeft:" target="Ady-hI-5gd" id="zUv-R1-uAa"/>
</connections>
</menuItem>
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
<connections>
<action selector="alignCenter:" target="Ady-hI-5gd" id="spX-mk-kcS"/>
</connections>
</menuItem>
<menuItem title="Justify" id="J5U-5w-g23">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="alignJustified:" target="Ady-hI-5gd" id="ljL-7U-jND"/>
</connections>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
<connections>
<action selector="alignRight:" target="Ady-hI-5gd" id="r48-bG-YeY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
<menuItem title="Writing Direction" id="H1b-Si-o9J">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
<items>
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="YGs-j5-SAR">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionNatural:" target="Ady-hI-5gd" id="qtV-5e-UBP"/>
</connections>
</menuItem>
<menuItem id="Lbh-J2-qVU">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="S0X-9S-QSf"/>
</connections>
</menuItem>
<menuItem id="jFq-tB-4Kx">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="5fk-qB-AqJ"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem id="Nop-cj-93Q">
<string key="title"> Default</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionNatural:" target="Ady-hI-5gd" id="lPI-Se-ZHp"/>
</connections>
</menuItem>
<menuItem id="BgM-ve-c93">
<string key="title"> Left to Right</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="caW-Bv-w94"/>
</connections>
</menuItem>
<menuItem id="RB4-Sm-HuC">
<string key="title"> Right to Left</string>
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="EXD-6r-ZUu"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
<menuItem title="Show Ruler" id="vLm-3I-IUL">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleRuler:" target="Ady-hI-5gd" id="FOx-HJ-KwY"/>
</connections>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="copyRuler:" target="Ady-hI-5gd" id="71i-fW-3W2"/>
</connections>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="pasteRuler:" target="Ady-hI-5gd" id="cSh-wd-qM2"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
@ -686,7 +423,7 @@
<rect key="frame" x="0.0" y="0.0" width="620" height="406"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<toolbar key="toolbar" implicitIdentifier="09D11707-F4A3-4FD5-970E-AC5832E91C2B" displayMode="iconOnly" sizeMode="regular" id="c7l-9K-zGH">
<toolbar key="toolbar" implicitIdentifier="09D11707-F4A3-4FD5-970E-AC5832E91C2B" showsBaselineSeparator="NO" displayMode="iconOnly" sizeMode="regular" id="c7l-9K-zGH">
<allowedToolbarItems>
<toolbarItem implicitItemIdentifier="CC6DE1A4-9FD5-4729-8CD5-0960D99018C8" explicitItemIdentifier="toggleSidebar" label="Show Sidebar" paletteLabel="Show Sidebar" tag="-1" image="sidebar.leading" catalog="system" bordered="YES" sizingBehavior="auto" autovalidates="NO" id="a3w-Fk-xXU">
<connections>
@ -746,7 +483,7 @@
<splitViewItem id="W8R-VT-x8O"/>
<splitViewItem id="ysW-gC-LWo"/>
</splitViewItems>
<splitView key="splitView" dividerStyle="thin" id="LII-Lb-vwD">
<splitView key="splitView" id="LII-Lb-vwD">
<rect key="frame" x="0.0" y="0.0" width="450" height="300"/>
<autoresizingMask key="autoresizingMask"/>
<connections>
@ -781,6 +518,16 @@
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<size key="minSize" width="700" height="300"/>
<size key="maxSize" width="700" height="10000000"/>
<attributedString key="textStorage">
<fragment content="Papercut.Dump(&quot;From Script&quot;);">
<attributes>
<color key="NSColor" name="textColor" catalog="System" colorSpace="catalog"/>
<font key="NSFont" size="14" name="Menlo-Regular"/>
<font key="NSOriginalFont" size="14" name="Menlo-Regular"/>
<paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
</attributes>
</fragment>
</attributedString>
<color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
</textView>
</subviews>

View file

@ -1,12 +1,13 @@
using System;
using System.Threading.Tasks;
using System.Threading;
using AppKit;
using Papercut.Core;
namespace Papercut.Macos;
public partial class MainWindow : NSWindowController
{
#region Window components
private NSSplitViewController MainContentController
{
get => (this.ContentViewController as NSSplitViewController)
@ -26,15 +27,25 @@ public partial class MainWindow : NSWindowController
.ContentView.DocumentView as NSTextView;
}
private NSTextView ScriptOutputTextBox
public NSTextView ScriptOutputTextBox
{
get => (this.MainContentController
.SplitViewItems[1].ViewController.View as NSScrollView)
.ContentView.DocumentView as NSTextView;
}
public string ScriptText { get => this.ScriptEditorTextBox.Value; }
public MainWindow (IntPtr handle) : base (handle) { }
#endregion
#region Shared properties
public CancellationTokenSource ScriptCancellationTokenSource { get; set; }
#endregion
public MainWindow (ObjCRuntime.NativeHandle handle) : base (handle) { }
public override void AwakeFromNib()
{
@ -54,28 +65,24 @@ public partial class MainWindow : NSWindowController
}
public void RunScript(object sender, EventArgs e)
{
ScriptRunner.RunScript(this);
}
public void CancelScript(object sender, EventArgs e)
{
this.ScriptCancellationTokenSource?.Cancel();
}
public void SetScriptRunState(bool scriptIsRunning)
{
if (scriptIsRunning)
{
this.RunScriptToolbarButton.Enabled = false;
this.ScriptOutputTextBox.Value = "";
TaskScheduler uiThread = TaskScheduler.FromCurrentSynchronizationContext();
PapercutWriter writer = new(obj =>
}
else
{
if (obj is string str)
{
this.BeginInvokeOnMainThread(() =>
this.ScriptOutputTextBox.Value += str + "\n");
}
return Task.CompletedTask;
});
string script = this.ScriptEditorTextBox.Value;
Task<bool> _ = Task
.Run(() => RoslynHost.RunScript(script, Array.Empty<string>(),
new RoslynHostGlobals(writer)))
.ContinueWith((t) => this.RunScriptToolbarButton.Enabled = true,
uiThread);
this.RunScriptToolbarButton.Enabled = true;
}
}
}

View file

@ -36,8 +36,8 @@
<Compile Update="MainWindow.designer.cs">
<DependentUpon>MainWindow.cs</DependentUpon>
</Compile>
<Compile Update="ScriptViewController.designer.cs">
<DependentUpon>ScriptViewController.cs</DependentUpon>
<Compile Update="AppDelegate.designer.cs">
<DependentUpon>AppDelegate.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>

View file

@ -0,0 +1,51 @@
using System;
using Papercut.Core;
using System.Threading;
using System.Threading.Tasks;
using AppKit;
namespace Papercut.Macos;
public static class ScriptRunner
{
public static void RunScript(MainWindow window)
{
window.SetScriptRunState(true);
window.ScriptOutputTextBox.Value = "";
TaskScheduler uiThread = TaskScheduler.FromCurrentSynchronizationContext();
PapercutWriter writer = new(obj =>
{
if (obj is string str)
{
window.BeginInvokeOnMainThread(() =>
window.ScriptOutputTextBox.Value += str + "\n");
}
return Task.CompletedTask;
});
window.ScriptCancellationTokenSource = new CancellationTokenSource();
string script = window.ScriptText;
Task task = Task
.Run(async () =>
{
try
{
await RoslynHost.RunScript(script, Array.Empty<string>(),
new RoslynHostGlobals(writer),
window.ScriptCancellationTokenSource.Token);
}
catch (Exception ex)
{
window.BeginInvokeOnMainThread(() =>
window.ScriptOutputTextBox.Value += ex.ToString());
}
}, window.ScriptCancellationTokenSource.Token)
.ContinueWith((t) => window.SetScriptRunState(false),
uiThread);
}
}

View file

@ -1,18 +0,0 @@
// This file has been autogenerated from a class added in the UI designer.
using System;
using Foundation;
using AppKit;
using System.Diagnostics;
namespace Papercut.Macos
{
public partial class ScriptViewController : NSViewController
{
public ScriptViewController (IntPtr handle) : base (handle)
{
}
}
}