Browse Source

Fixes #1318. Ensures that the OS clipboard is always sets.

BDisp 4 years ago
parent
commit
67d75725cc
2 changed files with 195 additions and 36 deletions
  1. 61 35
      Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
  2. 134 1
      UnitTests/ClipboardTests.cs

+ 61 - 35
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -1062,7 +1062,7 @@ namespace Terminal.Gui {
 			var tempFileName = System.IO.Path.GetTempFileName ();
 			try {
 				// BashRunner.Run ($"xsel -o --clipboard > {tempFileName}");
-				BashRunner.Run ($"xclip -o > {tempFileName}");
+				BashRunner.Run ($"xclip -selection clipboard -o > {tempFileName}");
 				return System.IO.File.ReadAllText (tempFileName);
 			} finally {
 				System.IO.File.Delete (tempFileName);
@@ -1071,52 +1071,78 @@ namespace Terminal.Gui {
 
 		public void SetClipboardData (string text)
 		{
-			var tempFileName = System.IO.Path.GetTempFileName ();
-			System.IO.File.WriteAllText (tempFileName, text);
+			// var tempFileName = System.IO.Path.GetTempFileName ();
+			// System.IO.File.WriteAllText (tempFileName, text);
+			// try {
+			// 	// BashRunner.Run ($"cat {tempFileName} | xsel -i --clipboard");
+			// 	BashRunner.Run ($"cat {tempFileName} | xclip -selection clipboard");
+			// } finally {
+			// 	System.IO.File.Delete (tempFileName);
+			// }
+
 			try {
-				// BashRunner.Run ($"cat {tempFileName} | xsel -i --clipboard");
-				BashRunner.Run ($"cat {tempFileName} | xclip -selection clipboard");
-			} finally {
-				System.IO.File.Delete (tempFileName);
+				BashRunner.Run ("xclip -selection clipboard -i", false, text);
+			} catch (Exception ex) {
+				throw new Exception (ex.Message);
 			}
 		}
 	}
 
 	static class BashRunner {
-		public static string Run (string commandLine)
+		public static string Run (string commandLine, bool output = true, string inputText = "")
 		{
-			var errorBuilder = new System.Text.StringBuilder ();
-			var outputBuilder = new System.Text.StringBuilder ();
 			var arguments = $"-c \"{commandLine}\"";
-			using (var process = new System.Diagnostics.Process {
-				StartInfo = new System.Diagnostics.ProcessStartInfo {
-					FileName = "bash",
-					Arguments = arguments,
-					RedirectStandardOutput = true,
-					RedirectStandardError = true,
-					UseShellExecute = false,
-					CreateNoWindow = false,
-				}
-			}) {
-				process.Start ();
-				process.OutputDataReceived += (sender, args) => { outputBuilder.AppendLine (args.Data); };
-				process.BeginOutputReadLine ();
-				process.ErrorDataReceived += (sender, args) => { errorBuilder.AppendLine (args.Data); };
-				process.BeginErrorReadLine ();
-				if (!process.DoubleWaitForExit ()) {
-					var timeoutError = $@"Process timed out. Command line: bash {arguments}.
+
+			if (output) {
+				var errorBuilder = new System.Text.StringBuilder ();
+				var outputBuilder = new System.Text.StringBuilder ();
+
+				using (var process = new System.Diagnostics.Process {
+					StartInfo = new System.Diagnostics.ProcessStartInfo {
+						FileName = "bash",
+						Arguments = arguments,
+						RedirectStandardOutput = true,
+						RedirectStandardError = true,
+						UseShellExecute = false,
+						CreateNoWindow = false,
+					}
+				}) {
+					process.Start ();
+					process.OutputDataReceived += (sender, args) => { outputBuilder.AppendLine (args.Data); };
+					process.BeginOutputReadLine ();
+					process.ErrorDataReceived += (sender, args) => { errorBuilder.AppendLine (args.Data); };
+					process.BeginErrorReadLine ();
+					if (!process.DoubleWaitForExit ()) {
+						var timeoutError = $@"Process timed out. Command line: bash {arguments}.
+							Output: {outputBuilder}
+							Error: {errorBuilder}";
+						throw new Exception (timeoutError);
+					}
+					if (process.ExitCode == 0) {
+						return outputBuilder.ToString ();
+					}
+
+					var error = $@"Could not execute process. Command line: bash {arguments}.
 						Output: {outputBuilder}
 						Error: {errorBuilder}";
-					throw new Exception (timeoutError);
+					throw new Exception (error);
 				}
-				if (process.ExitCode == 0) {
-					return outputBuilder.ToString ();
+			} else {
+				using (var process = new System.Diagnostics.Process {
+					StartInfo = new System.Diagnostics.ProcessStartInfo {
+						FileName = "bash",
+						Arguments = arguments,
+						RedirectStandardInput = true,
+						UseShellExecute = false,
+						CreateNoWindow = false
+					}
+				}) {
+					process.Start ();
+					process.StandardInput.Write (inputText);
+					process.StandardInput.Close ();
+					process.WaitForExit ();
+					return inputText;
 				}
-
-				var error = $@"Could not execute process. Command line: bash {arguments}.
-					Output: {outputBuilder}
-					Error: {errorBuilder}";
-				throw new Exception (error);
 			}
 		}
 

+ 134 - 1
UnitTests/ClipboardTests.cs

@@ -1,4 +1,6 @@
-using Xunit;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using Xunit;
 
 namespace Terminal.Gui.Core {
 	public class ClipboardTests {
@@ -13,5 +15,136 @@ namespace Terminal.Gui.Core {
 
 			Application.Shutdown ();
 		}
+
+		[Fact]
+		public void Contents_Gets_From_OS_Clipboard ()
+		{
+			Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
+
+			var clipText = "This is a clipboard unit test to get clipboard from OS.";
+
+			Application.Iteration += () => {
+				if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
+					// using (Process clipExe = new Process {
+					// 	StartInfo = new ProcessStartInfo {
+					// 		RedirectStandardInput = true,
+					// 		FileName = "clip"
+					// 	}
+					// }) {
+					// 	clipExe.Start ();
+					// 	clipExe.StandardInput.Write (clipText);
+					// 	clipExe.StandardInput.Close ();
+					// 	var result = clipExe.WaitForExit (500);
+					// 	if (result) {
+					// 		clipExe.WaitForExit ();
+					// 	}
+					// }
+
+					using (Process pwsh = new Process {
+						StartInfo = new ProcessStartInfo {
+							FileName = "powershell",
+							Arguments = $"-command \"Set-Clipboard -Value \\\"{clipText}\\\"\""
+						}
+					}) {
+						pwsh.Start ();
+						pwsh.WaitForExit ();
+					}
+				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) {
+					using (Process copy = new Process {
+						StartInfo = new ProcessStartInfo {
+							RedirectStandardInput = true,
+							FileName = "pbcopy"
+						}
+					}) {
+						copy.Start ();
+						copy.StandardInput.Write (clipText);
+						copy.StandardInput.Close ();
+						copy.WaitForExit ();
+					}
+				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
+					using (Process bash = new Process {
+						StartInfo = new ProcessStartInfo {
+							FileName = "bash",
+							Arguments = $"-c \"xclip -sel clip -i\"",
+							RedirectStandardInput = true,
+						}
+					}) {
+						bash.Start ();
+						bash.StandardInput.Write (clipText);
+						bash.StandardInput.Close ();
+						bash.WaitForExit ();
+					}
+				}
+
+				Application.RequestStop ();
+			};
+
+			Application.Run ();
+
+			Assert.Equal (clipText, Clipboard.Contents);
+
+			Application.Shutdown ();
+		}
+
+		[Fact]
+		public void Contents_Sets_The_OS_Clipboard ()
+		{
+			Application.Init (new FakeDriver (), new FakeMainLoop (() => FakeConsole.ReadKey (true)));
+
+			var clipText = "This is a clipboard unit test to set the OS clipboard.";
+			var clipReadText = "";
+
+			Application.Iteration += () => {
+				Clipboard.Contents = clipText;
+
+				if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
+					using (Process pwsh = new Process {
+						StartInfo = new ProcessStartInfo {
+							RedirectStandardOutput = true,
+							FileName = "powershell.exe",
+							Arguments = "-command \"Get-Clipboard\""
+						}
+					}) {
+						pwsh.Start ();
+						clipReadText = pwsh.StandardOutput.ReadToEnd ().TrimEnd ();
+						pwsh.StandardOutput.Close ();
+						pwsh.WaitForExit ();
+					}
+				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) {
+					using (Process paste = new Process {
+						StartInfo = new ProcessStartInfo {
+							RedirectStandardOutput = true,
+							FileName = "pbpaste"
+						}
+					}) {
+						paste.Start ();
+						clipReadText = paste.StandardOutput.ReadToEnd ();
+						paste.StandardOutput.Close ();
+						paste.WaitForExit ();
+					}
+				} else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) {
+					using (Process bash = new Process {
+						StartInfo = new ProcessStartInfo {
+							RedirectStandardOutput = true,
+							FileName = "bash",
+							Arguments = $"-c \"xclip -sel clip -o\""
+						}
+					}) {
+						bash.Start ();
+						clipReadText = bash.StandardOutput.ReadToEnd ();
+						bash.StandardOutput.Close ();
+						bash.WaitForExit ();
+					}
+				}
+
+				Application.RequestStop ();
+			};
+
+			Application.Run ();
+
+			Assert.Equal (clipText, clipReadText);
+
+			Application.Shutdown ();
+		}
 	}
 }