aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/repl/ammonite/Filter.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/repl/ammonite/Filter.scala')
-rw-r--r--src/dotty/tools/dotc/repl/ammonite/Filter.scala61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/repl/ammonite/Filter.scala b/src/dotty/tools/dotc/repl/ammonite/Filter.scala
new file mode 100644
index 000000000..9d34bb0f2
--- /dev/null
+++ b/src/dotty/tools/dotc/repl/ammonite/Filter.scala
@@ -0,0 +1,61 @@
+package dotty.tools
+package dotc
+package repl
+package ammonite.terminal
+
+object Filter {
+ def apply(id: String)(f: PartialFunction[TermInfo, TermAction]): Filter =
+ new Filter {
+ val op = f.lift
+ def identifier = id
+ }
+
+ def wrap(id: String)(f: TermInfo => Option[TermAction]): Filter =
+ new Filter {
+ val op = f
+ def identifier = id
+ }
+
+ /** Merges multiple [[Filter]]s into one. */
+ def merge(pfs: Filter*) = new Filter {
+ val op = (v1: TermInfo) => pfs.iterator.map(_.op(v1)).find(_.isDefined).flatten
+ def identifier = pfs.iterator.map(_.identifier).mkString(":")
+ }
+
+ val empty = Filter.merge()
+}
+
+/**
+ * The way you configure your terminal behavior; a trivial wrapper around a
+ * function, though you should provide a good `.toString` method to make
+ * debugging easier. The [[TermInfo]] and [[TermAction]] types are its
+ * interface to the terminal.
+ *
+ * [[Filter]]s are composed sequentially: if a filter returns `None` the next
+ * filter is tried, while if a filter returns `Some` that ends the cascade.
+ * While your `op` function interacts with the terminal purely through
+ * immutable case classes, the Filter itself is free to maintain its own state
+ * and mutate it whenever, even when returning `None` to continue the cascade.
+ */
+trait Filter {
+ val op: TermInfo => Option[TermAction]
+
+ /**
+ * the `.toString` of this object, except by making it separate we force
+ * the implementer to provide something and stop them from accidentally
+ * leaving it as the meaningless default.
+ */
+ def identifier: String
+ override def toString = identifier
+}
+
+/**
+ * A filter as an abstract class, letting you provide a [[filter]] instead of
+ * an `op`, automatically providing a good `.toString` for debugging, and
+ * providing a reasonable "place" inside the inheriting class/object to put
+ * state or helpers or other logic associated with the filter.
+ */
+abstract class DelegateFilter() extends Filter {
+ def filter: Filter
+ val op = filter.op
+}