Skip to content

Commit

Permalink
added more functionality + improved README
Browse files Browse the repository at this point in the history
  • Loading branch information
anthony-cros committed Oct 6, 2021
1 parent d968714 commit d1524e5
Show file tree
Hide file tree
Showing 12 changed files with 616 additions and 133 deletions.
494 changes: 417 additions & 77 deletions README.md

Large diffs are not rendered by default.

Binary file modified dependencies.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
65 changes: 39 additions & 26 deletions src/main/scala/aptus/AptusPackage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ package object aptus
extends AptusAnnotations
with AptusAliases
with AptusCommonAliases {
// TODO: t211006141756 - should most of them have @inline? is there a downside?

/* for extends AnyVals, see https://stackoverflow.com/questions/14929422/should-implicit-classes-always-extend-anyval */

def illegalState (x: Any*): Nothing = { throw new IllegalStateException (x.toString) }
def illegalArgument(x: Any*): Nothing = { throw new IllegalArgumentException(x.toString) }
def illegalState (x: Any*): Nothing = { throw new IllegalStateException (x.mkString(", ")) }
def illegalArgument(x: Any*): Nothing = { throw new IllegalArgumentException(x.mkString(", ")) }

// ---------------------------------------------------------------------------
def seqOrdering[T : Ordering]: Ordering[Seq [T]] = SeqUtils. seqOrdering[T]
def listOrdering[T : Ordering]: Ordering[List[T]] = SeqUtils.listOrdering[T]

// ---------------------------------------------------------------------------
def zip[T1, T2, T3] (a: Iterable[T1], b: Iterable[T2], c: Iterable[T3]) : Iterable[(T1, T2, T3)] = a.zip(b).zip(c) .map { case ((a, b), c) => (a, b, c) }
def zip[T1, T2, T3, T4] (a: Iterable[T1], b: Iterable[T2], c: Iterable[T3], d: Iterable[T4]) : Iterable[(T1, T2, T3, T4)] = a.zip(b).zip(c).zip(d) .map { case (((a, b), c), d) => (a, b, c, d) }
Expand All @@ -29,7 +33,7 @@ package object aptus

// ===========================================================================
implicit class Unit_(val u: Unit) extends AnyVal { // TODO: t201213095810 anyway to add that to Predef? implicit class doesn't seem to work
def environment = aptmisc.Environment
def system = aptmisc.AptusSystem
def fs = aptmisc.Fs
def hardware = aptmisc.Hardware
def random = aptmisc.Random
Expand All @@ -44,8 +48,11 @@ package object aptus

// ===========================================================================
implicit class Anything_[A](private val a: A) extends AnyVal {
def str = a.toString

def str: String = a.toString
def prt: A = { System.out.println(a); a }

def inspect(f: A => Any): A = { f(a).prt; a }

// ---------------------------------------------------------------------------
//@inline def pipe [B ] (f: A => B) : B = f(a)
def pipeIf (test: Boolean) (f: A => A) : A = if (test) f(a) else a
Expand All @@ -71,15 +78,17 @@ package object aptus
def sideEffectIf (pred: A => Boolean)(f: A => Unit) : A = { if (pred(a)) { f(a) } ; a }

// ---------------------------------------------------------------------------
@fordevonly def __exit: A = { ReflectionUtils.formatExitTrace(().reflect.stackTrace(), "intentionally stopping").p; System.exit(0); a }
@fordevonly def __exit: A = { ReflectionUtils.formatExitTrace(().reflect.stackTrace(), "intentionally stopping").p; System.exit(0); a }

@fordevonly def p : A = { System.out.println(a) ; a }
@fordevonly def p__ : A = { System.out.println(a) ; __exit }
@fordevonly def p : A = prt
@fordevonly def p__ : A = { prt; __exit }
@fordevonly def pp : A = { System.out.println(s"a\n"); a }

// "i" for "inspect"
@fordevonly def i(f: A => Any ): A = { System.out.println( f(a) ); a }
@fordevonly def i(f: A => Any, prefix: String): A = { System.out.println(s"${prefix}\t${f(a)}"); a }
@fordevonly def i (f: A => Any ): A = inspect(f)
@fordevonly def i (f: A => Any, prefix: String): A = { System.out.println(s"${prefix}\t${f(a)}"); a }
@fordevonly def i__(f: A => Any ): A = { System.out.println( f(a) ); __exit }
@fordevonly def i__(f: A => Any, prefix: String): A = { System.out.println(s"${prefix}\t${f(a)}"); __exit }

// ---------------------------------------------------------------------------
def assert(p: A => Boolean): A = assert(p, identity)
Expand All @@ -89,9 +98,7 @@ package object aptus
def require(p: A => Boolean, f: A => Any): A = { Predef.require(p(a), f(a)); a }

// ---------------------------------------------------------------------------
// TODO: t210116165559 - rename to "in"?
@deprecated def as: aptus.aptmisc.As[A] = new aptus.aptmisc.As[A](a)
def in: aptus.aptmisc.As[A] = new aptus.aptmisc.As[A](a)
def in: aptus.aptmisc.As[A] = new aptus.aptmisc.As[A](a)

// most common ones
def inNoneIf(p: A => Boolean): Option[A] = in.noneIf(p)
Expand Down Expand Up @@ -119,7 +126,7 @@ package object aptus
// ---------------------------------------------------------------------------
def systemCallLines(): Seq[String] = systemCall().splitBy("\n")

import scala.language.postfixOps; def systemCall(): String = sys.process.Process(str) !!
import scala.language.postfixOps; def systemCall(): String = (sys.process.Process(str) !!).replaceAll("\n$", "")

// ===========================================================================
def path = new aptmisc.AptusPath(str)
Expand Down Expand Up @@ -182,10 +189,10 @@ package object aptus
def indentAll(n: Int, indenter: String): String = StringUtils.indentAll(n , indenter )(str)

// ---------------------------------------------------------------------------
def sectionAllOff : String = StringUtils.sectionAllOff(n = 1, indenter = "\t")(str)
def sectionAllOff(n: Int) : String = StringUtils.sectionAllOff(n , indenter = "\t")(str)
def sectionAllOff : String = StringUtils.sectionAllOff(n = 1, indenter = "\t")(str)
def sectionAllOff(n: Int) : String = StringUtils.sectionAllOff(n , indenter = "\t")(str)

def sectionAllOff(prefix: String): String = s"${prefix}\n" + StringUtils.sectionAllOff(n = 1, indenter = "\t")(str)
def sectionAllOff(prefix: String): String = s"${prefix}" + StringUtils.sectionAllOff(n = 1, indenter = "\t")(str)

// ===========================================================================
def isTrimmed : Boolean = str == str.trim
Expand Down Expand Up @@ -317,8 +324,8 @@ package object aptus
case seq => seq.slidingList(2).map(_.force.tuple2) }

// ---------------------------------------------------------------------------
def splitHead: (A, Seq[A]) = coll.splitAt( 1).mapFirst (_.force.one)
def splitLast: (Seq[A], A) = coll.splitAt(coll.size - 1).mapSecond(_.force.one)
def splitAtHead: (A, Seq[A]) = coll.splitAt( 1).mapFirst (_.force.one)
def splitAtLast: (Seq[A], A) = coll.splitAt(coll.size - 1).mapSecond(_.force.one)

// ---------------------------------------------------------------------------
def distinctByAdjacency: Seq[A] = IterableUtils.distinctByAdjacency(coll).toList // TODO: test for 1
Expand Down Expand Up @@ -351,7 +358,7 @@ package object aptus
def countBySelf: List[(A, Int)] = coll.groupBy(identity).view.map { x => x._1 -> x._2.size }.toList.sortBy(-_._2) // TODO: t211004120452 - more efficient version

// ===========================================================================
def toOption[B](implicit ev: A <:< Option[B]): Option[Seq[B]] = if (coll.contains(None)) None else Some(coll.map(_.get))
def toOptionalSeq[B](implicit ev: A <:< Option[B]): Option[Seq[B]] = if (coll.contains(None)) None else Some(coll.map(_.get))
}

// ===========================================================================
Expand Down Expand Up @@ -409,6 +416,10 @@ package object aptus
// ---------------------------------------------------------------------------
implicit class Tuple3_[A, B, C](val tup: Tuple3[A, B, C]) extends AnyVal {
def toSeq[Z](implicit ev1: A <:< Z, ev2: B <:< Z, ev3: C <:< Z) = Seq[Z](tup._1, tup._2, tup._3)

def mapFirst [A2](fa: A => A2) = (fa(tup._1), tup._2, tup._3 )
def mapSecond[B2](fb: B => B2) = ( tup._1, fb(tup._2), tup._3 )
def mapThird [C2](fc: C => C2) = ( tup._1, tup._2 , fc(tup._3))
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -457,8 +468,10 @@ package object aptus
def divideBy (n: Number): Double = combine(n)(_ / _)
def multiplyBy(n: Number): Double = combine(n)(_ * _)

def log2(n: Number): Double = math.log10(n.doubleValue) / math.log10(2.0)

// ---------------------------------------------------------------------------
def exp : Double = math.exp (nmbr.doubleValue)
def log2: Double = math.log10(nmbr.doubleValue) / math.log10(2.0)

// ---------------------------------------------------------------------------
def formatUsLocale : FormattedNumber = NumberUtils.NumberFormatter.format(nmbr)
def formatExplicit : FormattedNumber = f"${nmbr}%.16f".stripTrailingZeros
Expand All @@ -472,8 +485,8 @@ package object aptus

// ===========================================================================
implicit class Throwable_(val throwable: Throwable) extends AnyVal {
def stackTrace: Seq[StackTraceElement] = throwable.getStackTrace.toList
def formatStackTrace: String = ThrowableUtils.stackTraceString(throwable)
def stackTrace: Seq[StackTraceElement] = throwable.getStackTrace.toList
def formatStackTrace: String = ThrowableUtils.stackTraceString(throwable)
}

// ---------------------------------------------------------------------------
Expand All @@ -488,7 +501,7 @@ package object aptus

// ---------------------------------------------------------------------------
implicit class InputStream_(is: java.io.InputStream) {
def closeabledBufferedReader : aptus.Closeabled[java.io.BufferedReader] = InputStreamUtils.closeabledBufferedReader(is, UTF_8)
def closeabledBufferedReader : aptus.Closeabled[java.io.BufferedReader] = InputStreamUtils.closeabledBufferedReader(is, aptus.UTF_8)
def closeabledBufferedReader(charset: Charset): aptus.Closeabled[java.io.BufferedReader] = InputStreamUtils.closeabledBufferedReader(is, charset)
}

Expand Down
14 changes: 7 additions & 7 deletions src/main/scala/aptus/aptmisc/Closeabled.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ package aptmisc
import scala.util.chaining._

// ===========================================================================
private[aptus] final class Closeabled[A](val u: A, val cls: Closeable) extends Closeable { // TODO: look into geny for Iterator version?
private[aptus] final class Closeabled[T](val underlying: T, val cls: Closeable) extends Closeable { // TODO: look into geny for Iterator version?
override def close() = { cls.close() }

// ---------------------------------------------------------------------------
def consume[B](f: A => B ): B = { val result = f(u); close(); result }
def map[B](f: A => B ): Closeabled[B] = Closeabled.fromPair(f(u), cls)
def flatMap[B](f: A => Closeabled[B]): Closeabled[B] = f(u).pipe { x => Closeabled.from(x.u, Seq(x.cls, this.cls)) }
def consume[U](f: T => U ): U = { val result = f(underlying); close(); result }
def map[U](f: T => U ): Closeabled[U] = Closeabled.fromPair(f(underlying), cls)
def flatMap[U](f: T => Closeabled[U]): Closeabled[U] = f(underlying).pipe { x => Closeabled.from(x.underlying, Seq(x.cls, this.cls)) }
}

// ===========================================================================
private[aptus] object Closeabled {

def from [A <: Closeable](a: A) : Closeabled[A] = new Closeabled(a, a)
def from [A] (a: A, values: Seq[Closeable]): Closeabled[A] = new Closeabled(a, closeable(values))
def fromPair[A] (pair: (A, Closeable)) : Closeabled[A] = new Closeabled(pair._1, closeable(pair._2))
def from [T <: Closeable](underlying: T) : Closeabled[T] = new Closeabled(underlying, underlying)
def from [T] (underlying: T, values: Seq[Closeable]): Closeabled[T] = new Closeabled(underlying, closeable(values))
def fromPair[T] (pair: (T, Closeable)) : Closeabled[T] = new Closeabled(pair._1, closeable(pair._2))

// ---------------------------------------------------------------------------
@ordermatters private def closeable[A](values: Seq[Closeable] ): Closeable = new java.io.Closeable { def close() = { values.foreach(_.close()) } }
Expand Down
13 changes: 8 additions & 5 deletions src/main/scala/aptus/aptmisc/Misc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package aptmisc
import scala.util.chaining._

// ===========================================================================
object Environment {
object AptusSystem {
def userName (): String = System.getProperty("user.name")
def hostName (): HostName = java.net.InetAddress.getLocalHost().getHostName() // TODO: https://stackoverflow.com/questions/7348711/recommended-way-to-get-hostname-in-java

Expand All @@ -13,10 +13,13 @@ object Environment {
def osName(): String = System.getProperty("os.name")

// ---------------------------------------------------------------------------
def isLinux (): Boolean = osName().toLowerCase.startsWith("linux")
def isMac (): Boolean = osName().toLowerCase.startsWith("mac")
def isWindows(): Boolean = osName().toLowerCase.startsWith("windows")
// TODO: FreeBSD and SunOS?
def isUnix(): Boolean = org.apache.commons.lang3.SystemUtils.IS_OS_UNIX

def isLinux (): Boolean = org.apache.commons.lang3.SystemUtils.IS_OS_LINUX
def isMac (): Boolean = org.apache.commons.lang3.SystemUtils.IS_OS_MAC
def isWindows(): Boolean = org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS
def isFreeBSD(): Boolean = org.apache.commons.lang3.SystemUtils.IS_OS_FREE_BSD
def isSunOS (): Boolean = org.apache.commons.lang3.SystemUtils.IS_OS_SUN_OS
}

// ===========================================================================
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/aptus/aptmisc/Zip.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ object Zip {
.pipe(aptus.Closeabled.fromPair(_, zipFile)),
StandardCharsets.UTF_8)

pair.u -> pair }
pair.underlying -> pair }

// ---------------------------------------------------------------------------
def content(in: FilePath) : Content = content(in, _ => true)
Expand Down
45 changes: 31 additions & 14 deletions src/main/scala/aptus/aptutils/SeqUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,39 @@ object SeqUtils {
coll
}

// ===========================================================================
private[aptus] def listOrdering[T : Ordering]: Ordering[List[T]] = new Ordering[List[T]] { // 210827123947
override def compare(x: List[T], y: List[T]): Int = {
val sizeComparison = x.size.compare(y.size)

if (sizeComparison != 0) sizeComparison
else {
val ordering = implicitly[Ordering[T]]

x .zip(y)
.map { case (l, r) => ordering.compare(l, r) }
.find(_ != 0)
.getOrElse(0)
// ===========================================================================
private[aptus] def seqOrdering[T : Ordering]: Ordering[Seq[T]] = new Ordering[Seq[T]] { // 210827123947
override def compare(x: Seq[T], y: Seq[T]): Int = {
val sizeComparison = x.size.compare(y.size)

if (sizeComparison != 0) sizeComparison
else {
val ordering = implicitly[Ordering[T]]

x .zip(y)
.map { case (l, r) => ordering.compare(l, r) }
.find(_ != 0)
.getOrElse(0)
}
}
}

// ---------------------------------------------------------------------------
private[aptus] def listOrdering[T : Ordering]: Ordering[List[T]] = new Ordering[List[T]] { // 210827123947
override def compare(x: List[T], y: List[T]): Int = {
val sizeComparison = x.size.compare(y.size)

if (sizeComparison != 0) sizeComparison
else {
val ordering = implicitly[Ordering[T]]

x .zip(y)
.map { case (l, r) => ordering.compare(l, r) }
.find(_ != 0)
.getOrElse(0)
}
}
}
}

}

Expand Down
8 changes: 7 additions & 1 deletion src/test/scala/aptustesting/AnythingTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ object AnythingTests extends TestSuite {

test(noop ("hello".require(_.nonEmpty)))
test(fail[java.lang.IllegalArgumentException]("hello".require(_. isEmpty)))
test(fail[java.lang.IllegalArgumentException]("hello".require(_. isEmpty, x => s"input: ${x}"), msg = "requirement failed: input: hello"))
test(fail[java.lang.IllegalArgumentException]("hello".require(_. isEmpty, x => s"input: ${x}"), msg = "requirement failed: input: hello"))

// ---------------------------------------------------------------------------
// in.{none,some}If

test("foo".in.someIf(_.size < 3), Some("foo"))
test("foo".in.noneIf(_.size < 3), None)
}
}

Expand Down
8 changes: 6 additions & 2 deletions src/test/scala/aptustesting/AptusTestingPackage.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// ===========================================================================
package object aptustesting {
import aptus._
import scala.reflect._
import scala.util._

// ===========================================================================
def noop [A](actual: A) = compare(actual, actual)
def compare[A](actual: A, expected: A) = { assert(actual == expected, message = actual -> expected) }
def noop [A](actual: A) : Unit = compare(actual, actual)
def compare[A](actual: A, expected: A): Unit = { assert(actual == expected, message = actual -> expected) }

def compare [A](enabled: Boolean)(actual: => A, expected: A): Unit = { if (enabled) compare(actual, expected) else () }
def compareIfUnix[A] (actual: => A, expected: A): Unit = compare(().system.isUnix())(actual, expected)

// ---------------------------------------------------------------------------
def fail[$Throwable <: Throwable : ClassTag](f: => Any) = { _fail[$Throwable](f, msgOpt = None) }
Expand Down
Loading

0 comments on commit d1524e5

Please sign in to comment.