From 55ccebc8f54b258fb8a14a8c7967be45e3c495bb Mon Sep 17 00:00:00 2001 From: pfcoperez Date: Sat, 4 May 2019 16:39:25 +0200 Subject: [PATCH] Clipboard operations: xclip or pbcopy/pbpaste style operations. --- .../main/scala/ammonite/repl/ApiImpls.scala | 27 +++++++++++- .../main/scala/ammonite/repl/ReplAPI.scala | 18 +++++++- .../scala/ammonite/unit/ClipboardTests.scala | 44 +++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 amm/repl/src/test/scala/ammonite/unit/ClipboardTests.scala diff --git a/amm/repl/src/main/scala/ammonite/repl/ApiImpls.scala b/amm/repl/src/main/scala/ammonite/repl/ApiImpls.scala index d413c42b4..16704b97b 100644 --- a/amm/repl/src/main/scala/ammonite/repl/ApiImpls.scala +++ b/amm/repl/src/main/scala/ammonite/repl/ApiImpls.scala @@ -1,10 +1,13 @@ package ammonite.repl - +import ammonite.ops.Internals import ammonite.runtime._ import ammonite.util.Util._ import ammonite.util._ +import java.awt.Toolkit +import java.awt.datatransfer.{DataFlavor, StringSelection} + import scala.collection.mutable class SessionApiImpl(frames0: => StableRef[List[Frame]]) extends Session{ @@ -108,4 +111,26 @@ trait ReplApiImpl extends FullReplAPI{ def sess: SessionApiImpl + override def clipboard: Clipboard = ClipboardImpl +} +object ClipboardImpl extends Clipboard { + + private lazy val systemClipboard = + Toolkit.getDefaultToolkit.getSystemClipboard + + override def read: String = + Option(systemClipboard.getContents(null)) collect { + case data if data.isDataFlavorSupported(DataFlavor.stringFlavor) => + data.getTransferData(DataFlavor.stringFlavor) + } match { + case Some(str: String) => str + case _ => "" + } + + override def write(data: Internals.Writable): Unit = { + val newContents = new StringSelection( + data.writeableData.map(new String(_)).mkString + ) + systemClipboard.setContents(newContents, newContents) + } } diff --git a/amm/repl/src/main/scala/ammonite/repl/ReplAPI.scala b/amm/repl/src/main/scala/ammonite/repl/ReplAPI.scala index 6dd48c9d9..9561bf90e 100644 --- a/amm/repl/src/main/scala/ammonite/repl/ReplAPI.scala +++ b/amm/repl/src/main/scala/ammonite/repl/ReplAPI.scala @@ -1,5 +1,6 @@ package ammonite.repl +import ammonite.ops.Internals import ammonite.util._ import scala.reflect.runtime.universe._ @@ -160,6 +161,8 @@ trait ReplAPI { def sess: Session def load: ReplLoad + + def clipboard: Clipboard } trait ReplLoad{ /** @@ -206,4 +209,17 @@ trait Session{ */ def delete(name: String): Unit } - +trait Clipboard{ + /** + * Reads contents from the system clipboard. + * @return System clipboard contents if they are readable as `String`, + * empty string otherwise. + */ + def read: String + /** + * Sets the contents of the system clipboard. + * + * @param data New contents for the clipboard. + */ + def write(data: Internals.Writable): Unit +} diff --git a/amm/repl/src/test/scala/ammonite/unit/ClipboardTests.scala b/amm/repl/src/test/scala/ammonite/unit/ClipboardTests.scala new file mode 100644 index 000000000..7b4805a14 --- /dev/null +++ b/amm/repl/src/test/scala/ammonite/unit/ClipboardTests.scala @@ -0,0 +1,44 @@ +package ammonite.unit + +import ammonite.repl.{Clipboard, ClipboardImpl} + +import java.awt.Toolkit +import java.awt.datatransfer.DataFlavor + +import utest._ + +import scala.util.Try + +object ClipboardTests extends TestSuite{ + + val clipboard: Clipboard = ClipboardImpl + + /** + * This test suite requires an environment with access to a window + * service (either under, Windows, MacOs, X11, ...) CI environment + * doesn't satisfy that condition and that is detected in the following + * check in order to skip [[Clipboard]] test when running on CI. + */ + val canTest = Try( + Toolkit.getDefaultToolkit.getSystemClipboard.isDataFlavorAvailable( + DataFlavor.stringFlavor + ) + ).getOrElse(false) + + override def tests = Tests { + println("ClipboardTests") + 'clipboard { + val newClipboardContents = "hello Ammonite" + 'copyandpaste - { + if (canTest) { + clipboard.write(newClipboardContents) + assert(clipboard.read == newClipboardContents) + } else { + println( + "The environment doesn't allow testing clipboard - skipping" + ) + } + } + } + } +}