Jelajahi Sumber

mucking with xclip

Charlie Kindel 2 tahun lalu
induk
melakukan
5d7a4e3dd5

+ 38 - 37
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -955,11 +955,12 @@ namespace Terminal.Gui {
 
 		public static bool Is_WSL_Platform ()
 		{
-			if (new CursesClipboard ().IsSupported) {
-				// If xclip is installed on Linux under WSL, this will return true.
-				return false;
-			}
-			var (exitCode, result) = ClipboardProcessRunner.Bash ("uname -a");
+			// xclip does not work on WSL, so we need to use the Windows clipboard vis Powershell
+			//if (new CursesClipboard ().IsSupported) {
+			//	// If xclip is installed on Linux under WSL, this will return true.
+			//	return false;
+			//}
+			var (exitCode, result) = ClipboardProcessRunner.Bash ("uname -a", waitForOutput: true);
 			if (exitCode == 0 && result.Contains ("microsoft") && result.Contains ("WSL")) {
 				return true;
 			}
@@ -1280,7 +1281,7 @@ namespace Terminal.Gui {
 		bool CheckSupport ()
 		{
 			try {
-				var (exitCode, result) = ClipboardProcessRunner.Bash ("which xclip");
+				var (exitCode, result) = ClipboardProcessRunner.Bash ("which xclip", waitForOutput: true);
 				if (exitCode == 0 && result.FileExists ()) {
 					xclipPath = result;
 					return true;
@@ -1295,9 +1296,9 @@ namespace Terminal.Gui {
 		{
 			var tempFileName = System.IO.Path.GetTempFileName ();
 			var xclipargs = "-selection clipboard -o";
-
+			
 			try {
-				var (exitCode, result) = ClipboardProcessRunner.Bash ($"{xclipPath} {xclipargs} > {tempFileName}");
+				var (exitCode, result) = ClipboardProcessRunner.Bash ($"{xclipPath} {xclipargs} > {tempFileName}", waitForOutput: false);
 				if (exitCode == 0) {
 					return System.IO.File.ReadAllText (tempFileName);
 				}
@@ -1313,7 +1314,7 @@ namespace Terminal.Gui {
 		{
 			var xclipargs = "-selection clipboard -i";
 			try {
-				ClipboardProcessRunner.Bash ($"{xclipPath} {xclipargs}", text);
+				ClipboardProcessRunner.Bash ($"{xclipPath} {xclipargs}", text, waitForOutput: false);
 			} catch (Exception e) {
 				throw new NotSupportedException ($"\"{xclipPath} {xclipargs} < {text}\" failed", e);
 			}
@@ -1321,10 +1322,10 @@ namespace Terminal.Gui {
 	}
 
 	internal static class ClipboardProcessRunner {
-		public static (int exitCode, string result) Bash (string commandLine, string inputText = "")
+		public static (int exitCode, string result) Bash (string commandLine, string inputText = "", bool waitForOutput = false)
 		{
 			var arguments = $"-c \"{commandLine}\"";
-			var (exitCode, result) = Process ("bash", arguments, inputText);
+			var (exitCode, result) = Process ("bash", arguments, inputText, waitForOutput);
 
 			if (exitCode == 0) {
 				if (Application.Driver is CursesDriver) {
@@ -1335,11 +1336,8 @@ namespace Terminal.Gui {
 			return (exitCode, result.TrimEnd ());
 		}
 
-		public static (int exitCode, string result) Process (string cmd, string arguments, string input = null)
+		public static (int exitCode, string result) Process (string cmd, string arguments, string input = null, bool waitForOutput = true)
 		{
-			var errorBuilder = new System.Text.StringBuilder ();
-			var outputBuilder = new System.Text.StringBuilder ();
-
 			var output = string.Empty;
 
 			using (Process process = new Process {
@@ -1360,25 +1358,20 @@ namespace Terminal.Gui {
 					process.StandardInput.Close ();
 				}
 
-				//process.OutputDataReceived += (sender, args) => { outputBuilder.AppendLine (args.Data); };
-				//process.BeginOutputReadLine ();
-				//process.ErrorDataReceived += (sender, args) => { errorBuilder.AppendLine (args.Data); };
-				//process.BeginErrorReadLine ();
-
 				if (!process.WaitForExit (5000)) {
-					var timeoutError = $@"Process timed out. Command line: {process.StartInfo.FileName} {process.StartInfo.Arguments}.
-							Output: {outputBuilder}
-							Error: {errorBuilder}";
+					var timeoutError = $@"Process timed out. Command line: {process.StartInfo.FileName} {process.StartInfo.Arguments}.";
 					throw new TimeoutException (timeoutError);
 				}
 
-				if (process.ExitCode > 0) {
-					output = $@"Process failed to run. Command line: {cmd} {arguments}.
-										Output: {process.StandardOutput.ReadToEnd()}
-										Error: {process.StandardOutput.ReadToEnd ()}";
-				} else {
+				if (waitForOutput && process.StandardOutput.Peek () != -1) {
 					output = process.StandardOutput.ReadToEnd ().TrimEnd ();
 				}
+
+				if (process.ExitCode > 0) {
+					output = $@"Process failed to run. Command line: {cmd} {arguments}.
+										Output: {output}
+										Error: {process.StandardError.ReadToEnd ()}";
+				} 
 				return (process.ExitCode, output);
 			}
 		}
@@ -1431,11 +1424,11 @@ namespace Terminal.Gui {
 
 		bool CheckSupport ()
 		{
-			var (exitCode, result) = ClipboardProcessRunner.Bash ("which pbcopy");
+			var (exitCode, result) = ClipboardProcessRunner.Bash ("which pbcopy", waitForOutput: true);
 			if (exitCode != 0 || !result.FileExists ()) {
 				return false;
 			}
-			(exitCode, result) = ClipboardProcessRunner.Bash ("which pbpaste");
+			(exitCode, result) = ClipboardProcessRunner.Bash ("which pbpaste", waitForOutput: true);
 			return exitCode == 0 && result.FileExists ();
 		}
 
@@ -1492,21 +1485,21 @@ namespace Terminal.Gui {
 			isSupported = CheckSupport ();
 		}
 
-		public override bool IsSupported { 
-			get { 
-				return isSupported = CheckSupport ();  
+		public override bool IsSupported {
+			get {
+				return isSupported = CheckSupport ();
 			}
 		}
 
-		private string powershellPath = string.Empty;
+		private static string powershellPath = string.Empty;
 
 		bool CheckSupport ()
 		{
 			if (string.IsNullOrEmpty (powershellPath)) {
 				// Specify pwsh.exe (not pwsh) to ensure we get the Windows version (invoked via WSL)
-				var (exitCode, result) = ClipboardProcessRunner.Bash ("which pwsh.exe");
+				var (exitCode, result) = ClipboardProcessRunner.Bash ("which pwsh.exe", waitForOutput: true);
 				if (exitCode > 0) {
-					(exitCode, result) = ClipboardProcessRunner.Bash ("which powershell.exe");
+					(exitCode, result) = ClipboardProcessRunner.Bash ("which powershell.exe", waitForOutput: true);
 				}
 
 				if (exitCode == 0) {
@@ -1518,8 +1511,12 @@ namespace Terminal.Gui {
 
 		protected override string GetClipboardDataImpl ()
 		{
+			if (!IsSupported) {
+				return string.Empty;
+			}
+			
 			var (exitCode, output) = ClipboardProcessRunner.Process (powershellPath, "-noprofile -command \"Get-Clipboard\"");
-			if (exitCode == 0) { 
+			if (exitCode == 0) {
 				if (Application.Driver is CursesDriver) {
 					Curses.raw ();
 					Curses.noecho ();
@@ -1535,6 +1532,10 @@ namespace Terminal.Gui {
 
 		protected override void SetClipboardDataImpl (string text)
 		{
+			if (!IsSupported) {
+				return;
+			}
+
 			var (exitCode, output) = ClipboardProcessRunner.Process (powershellPath, $"-noprofile -command \"Set-Clipboard -Value \\\"{text}\\\"\"");
 			if (exitCode == 0) {
 				if (Application.Driver is CursesDriver) {

+ 7 - 5
UnitTests/ClipboardTests.cs

@@ -91,16 +91,16 @@ namespace Terminal.Gui.ConsoleDrivers {
 
 
 		[Fact, AutoInitShutdown (useFakeClipboard: false)]
-		public void Contents_Gets_From_OS_Clipboard ()
+		public void Contents_Copies_From_OS_Clipboard ()
 		{
-			var clipText = "This is a clipboard unit test to get clipboard from OS.";
+			var clipText = "The Contents_Copies_From_OS_Clipboard unit test pasted this to the OS clipboard.";
 			var failed = false;
 			var getClipText = "";
 
 			Application.Iteration += () => {
 				int exitCode = 0;
 				string result = "";
-				output.WriteLine ($"Setting OS clipboard to: {clipText}...");
+				output.WriteLine ($"Pasting to OS clipboard: {clipText}...");
 
 				if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
 					(exitCode, result) = ClipboardProcessRunner.Process ("pwsh", $"-command \"Set-Clipboard -Value \\\"{clipText}\\\"\"");
@@ -121,7 +121,9 @@ namespace Terminal.Gui.ConsoleDrivers {
 						} catch {
 							failed = true;
 						}
+
 						if (!failed) {
+							// If we set the OS clipboard via Powershell, then getting Contents should return the same text.
 							getClipText = Clipboard.Contents.ToString ();
 							output.WriteLine ($"  WSL: Clipboard.Contents: {getClipText}");
 						}
@@ -157,9 +159,9 @@ namespace Terminal.Gui.ConsoleDrivers {
 		}
 
 		[Fact, AutoInitShutdown (useFakeClipboard: false)]
-		public void Contents_Sets_The_OS_Clipboard ()
+		public void Contents_Pastes_To_OS_Clipboard ()
 		{
-			var clipText = "This is a clipboard unit test to set the OS clipboard.";
+			var clipText = "The Contents_Pastes_To_OS_Clipboard unit test pasted this via Clipboard.Contents.";
 			var clipReadText = "";
 			var failed = false;