Browse Source

better error handling

Charlie Kindel 2 years ago
parent
commit
9d7f985c8a

+ 22 - 14
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -1260,6 +1260,13 @@ namespace Terminal.Gui {
 		}
 		}
 	}
 	}
 
 
+	/// <summary>
+	///  A clipboard implementation for Linux.
+	///  This implementation uses the xclip command to access the clipboard.
+	/// </summary>	
+	/// <remarks>
+	/// If xclip is not installed, this implementation will not work.
+	/// </remarks>
 	class CursesClipboard : ClipboardBase {
 	class CursesClipboard : ClipboardBase {
 		public CursesClipboard ()
 		public CursesClipboard ()
 		{
 		{
@@ -1373,6 +1380,12 @@ namespace Terminal.Gui {
 		}
 		}
 	}
 	}
 
 
+	/// <summary>
+	///  A clipboard implementation for MacOSX. 
+	///  This implementation uses the Mac clipboard API (via P/Invoke) to copy/paste.
+	///  The existance of the Mac pbcopy and pbpaste commands 
+	///  is used to determine if copy/paste is supported.
+	/// </summary>	
 	class MacOSXClipboard : ClipboardBase {
 	class MacOSXClipboard : ClipboardBase {
 		IntPtr nsString = objc_getClass ("NSString");
 		IntPtr nsString = objc_getClass ("NSString");
 		IntPtr nsPasteboard = objc_getClass ("NSPasteboard");
 		IntPtr nsPasteboard = objc_getClass ("NSPasteboard");
@@ -1447,6 +1460,12 @@ namespace Terminal.Gui {
 		static extern IntPtr sel_registerName (string selectorName);
 		static extern IntPtr sel_registerName (string selectorName);
 	}
 	}
 
 
+	/// <summary>
+	///  A clipboard implementation for Linux, when running under WSL. 
+	///  This implementation uses the Windows clipboard to store the data, and uses Windows'
+	///  powershell.exe (launched via WSL interop services) to set/get the Windows
+	///  clipboard. 
+	/// </summary>
 	class WSLClipboard : ClipboardBase {
 	class WSLClipboard : ClipboardBase {
 		public WSLClipboard ()
 		public WSLClipboard ()
 		{
 		{
@@ -1460,9 +1479,10 @@ namespace Terminal.Gui {
 		bool CheckSupport ()
 		bool CheckSupport ()
 		{
 		{
 			if (string.IsNullOrEmpty (powershellCommand)) {
 			if (string.IsNullOrEmpty (powershellCommand)) {
-				var (exitCode, result) = BashRunner.Run ("which pwsh");
+				// Specify pwsh.exe (not pwsh) to ensure we get the Windows version (invoked via WSL)
+				var (exitCode, result) = BashRunner.Run ("which pwsh.exe");
 				if (exitCode > 0) {
 				if (exitCode > 0) {
-					(exitCode, result) = BashRunner.Run ("which powershell");
+					(exitCode, result) = BashRunner.Run ("which powershell.exe");
 				}
 				}
 
 
 				if (exitCode == 0) {
 				if (exitCode == 0) {
@@ -1536,18 +1556,6 @@ namespace Terminal.Gui {
 					Curses.noecho ();
 					Curses.noecho ();
 				}
 				}
 			}
 			}
-
-			//using (var clipExe = new System.Diagnostics.Process {
-			//	StartInfo = new System.Diagnostics.ProcessStartInfo {
-			//		FileName = "clip.exe",
-			//		RedirectStandardInput = true
-			//	}
-			//}) {
-			//	clipExe.Start ();
-			//	clipExe.StandardInput.Write (text);
-			//	clipExe.StandardInput.Close ();
-			//	clipExe.WaitForExit ();
-			//}
 		}
 		}
 	}
 	}
 }
 }

+ 37 - 10
Terminal.Gui/Core/Clipboard/Clipboard.cs

@@ -3,8 +3,27 @@ using System;
 
 
 namespace Terminal.Gui {
 namespace Terminal.Gui {
 	/// <summary>
 	/// <summary>
-	/// Provides cut, copy, and paste support for the clipboard with OS interaction.
+	/// Provides cut, copy, and paste support for the OS clipboard.
 	/// </summary>
 	/// </summary>
+	/// <remarks>
+	/// <para>
+	/// On Windows, the <see cref="Clipboard"/> class uses the Windows Clipboard APIs via P/Invoke.
+	/// </para>
+	/// <para>
+	/// On Linux, when not running under Windows Subsystem for Linux (WSL),
+	/// the <see cref="Clipboard"/> class uses the xclip command line tool. If xclip is not installed,
+	/// the clipboard will not work.
+	/// </para>
+	/// <para>
+	/// On Linux, when running under Windows Subsystem for Linux (WSL),
+	/// the <see cref="Clipboard"/> class launches Windows' powershell.exe via WSL interop and uses the
+	/// "Set-Clipboard" and "Get-Clipboard" Powershell CmdLets. 
+	/// </para>
+	/// <para>
+	/// On the Mac, the <see cref="Clipboard"/> class uses the MacO OS X pbcopy and pbpaste command line tools
+	/// and the Mac clipboard APIs vai P/Invoke.
+	/// </para>
+	/// </remarks>
 	public static class Clipboard {
 	public static class Clipboard {
 		static ustring contents;
 		static ustring contents;
 
 
@@ -25,7 +44,10 @@ namespace Terminal.Gui {
 			}
 			}
 			set {
 			set {
 				try {
 				try {
-					if (IsSupported && value != null) {
+					if (IsSupported) {
+						if (value == null) {
+							value = string.Empty;
+						}
 						Application.Driver.Clipboard.SetClipboardData (value.ToString ());
 						Application.Driver.Clipboard.SetClipboardData (value.ToString ());
 					}
 					}
 					contents = value;
 					contents = value;
@@ -40,32 +62,37 @@ namespace Terminal.Gui {
 		/// <summary>
 		/// <summary>
 		/// Returns true if the environmental dependencies are in place to interact with the OS clipboard.
 		/// Returns true if the environmental dependencies are in place to interact with the OS clipboard.
 		/// </summary>
 		/// </summary>
+		/// <remarks>
+		/// The first time IsSupported is called, it will spawn a process (e.g. "bash xclip" or "powershell.exe"
+		/// to determine if the clipboard is supported byt the OS platform. This is a one-time cost.
+		/// </remarks>
 		public static bool IsSupported { get => Application.Driver.Clipboard.IsSupported; }
 		public static bool IsSupported { get => Application.Driver.Clipboard.IsSupported; }
 
 
 		/// <summary>
 		/// <summary>
-		/// Gets the operation system clipboard if possible.
+		/// Copies the contents of the OS clipboard to <paramref name="result"/> if possible.
 		/// </summary>
 		/// </summary>
-		/// <param name="result">Clipboard contents read</param>
-		/// <returns>true if it was possible to read the OS clipboard.</returns>
+		/// <param name="result">The contents of the OS clipboard if successful, <see cref="string.Empty"/> if not.</param>
+		/// <returns><see langword="true"/> the OS clipboard was retrieved, <see langword="false"/> otherwise.</returns>
 		public static bool TryGetClipboardData (out string result)
 		public static bool TryGetClipboardData (out string result)
 		{
 		{
-			if (Application.Driver.Clipboard.TryGetClipboardData (out result)) {
+			if (IsSupported && Application.Driver.Clipboard.TryGetClipboardData (out result)) {
 				if (contents != result) {
 				if (contents != result) {
 					contents = result;
 					contents = result;
 				}
 				}
 				return true;
 				return true;
 			}
 			}
+			result = string.Empty;
 			return false;
 			return false;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
-		/// Sets the operation system clipboard if possible.
+		/// Pastes the <paramref name="text"/> to the OS clipboard if possible.
 		/// </summary>
 		/// </summary>
-		/// <param name="text"></param>
-		/// <returns>True if the clipboard content was set successfully.</returns>
+		/// <param name="text">The text to paste to the OS clipboard.</param>
+		/// <returns><see langword="true"/> the OS clipboard was set, <see langword="false"/> otherwise.</returns>
 		public static bool TrySetClipboardData (string text)
 		public static bool TrySetClipboardData (string text)
 		{
 		{
-			if (Application.Driver.Clipboard.TrySetClipboardData (text)) {
+			if (IsSupported && Application.Driver.Clipboard.TrySetClipboardData (text)) {
 				contents = text;
 				contents = text;
 				return true;
 				return true;
 			}
 			}

+ 2 - 1
UnitTests/ClipboardTests.cs

@@ -120,7 +120,8 @@ namespace Terminal.Gui.ConsoleDrivers {
 				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
 				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
 					if (Is_WSL_Platform ()) {
 					if (Is_WSL_Platform ()) {
 						try {
 						try {
-							RunClipboardProcess ("pwsh", $"-noprofile -command \"Set-Clipboard -Value \\\"{clipText}\\\"\"");
+							// This runs the WINDOWS version of powershell.exe via WSL.
+							RunClipboardProcess ("powershell.exe", $"-noprofile -command \"Set-Clipboard -Value \\\"{clipText}\\\"\"");
 						} catch {
 						} catch {
 							failed = true;
 							failed = true;
 						}
 						}