summaryrefslogtreecommitdiff
path: root/cli/src/main/scala/com/rockymadden/stringmetric
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src/main/scala/com/rockymadden/stringmetric')
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/package.scala105
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/metaphonealgorithm.scala16
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/metaphonemetric.scala21
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/nysiisalgorithm.scala16
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/nysiismetric.scala21
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinednysiisalgorithm.scala16
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinednysiismetric.scala21
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinedsoundexalgorithm.scala16
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinedsoundexmetric.scala21
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/soundexalgorithm.scala16
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/soundexmetric.scala21
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/dicesorensenmetric.scala26
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/hammingmetric.scala22
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jaccardmetric.scala26
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jarometric.scala22
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jarowinklermetric.scala22
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/levenshteinmetric.scala23
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/ngrammetric.scala26
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/overlapmetric.scala26
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/ratcliffobershelpmetric.scala22
-rwxr-xr-xcli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/weightedlevenshteinmetric.scala33
21 files changed, 538 insertions, 0 deletions
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/package.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/package.scala
new file mode 100755
index 0000000..617f4a5
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/package.scala
@@ -0,0 +1,105 @@
+package com.rockymadden.stringmetric
+
+/**
+ * Provides core CLI functionality. Note that some things might look sloppy (e.g. access modifiers, broad imports,
+ * repetitive imports, etc), but are required because of the way scalascript is ultimately compiled.
+ */
+package object cli {
+ import scala.language.implicitConversions
+
+
+ implicit def optionStringToArray(os: OptionString): Array[String] =
+ if (os.get.length == 0) Array.empty[String]
+ else os.get.split(" ")
+ implicit def optionStringToBigDecimal(os: OptionString): BigDecimal = BigDecimal(os.get)
+ implicit def optionStringToBigInt(os: OptionString): BigInt = BigInt(os.get)
+ implicit def optionStringToDouble(os: OptionString): Double = os.get.toDouble
+ implicit def optionStringToFloat(os: OptionString): Float = os.get.toFloat
+ implicit def optionStringToInt(os: OptionString): Int = os.get.toInt
+ implicit def optionStringToLong(os: OptionString): Long = os.get.toLong
+ implicit def optionStringToShort(os: OptionString): Short = os.get.toShort
+ implicit def optionStringToString(os: OptionString): String = os.get
+ implicit def stringToOptionString(s: String): OptionString = OptionString(s)
+ implicit def arrayOfStringToOptionMap(stringArray: Array[String]): OptionMap = OptionMap(stringArray)
+
+
+ final val Ls = sys.props("line.separator")
+ final val Tab = " "
+
+
+ class OptionString(val get: String)
+
+ object OptionString {
+ def apply(s: String): OptionString = new OptionString(s)
+ }
+
+
+ type OptionMap = Map[Symbol, OptionString]
+
+ object OptionMap {
+ def apply(args: Array[String]): OptionMap = apply(args: _*)
+
+ def apply(varargs: String*): OptionMap = {
+ @annotation.tailrec
+ def next(om: OptionMap, a: List[String]): OptionMap = {
+ val double = """^(--[a-zA-Z0-9]+)(=[a-zA-Z0-9\.\-_]+)?""".r
+ val single = """^(-[a-zA-Z0-9]+)(=[a-zA-Z0-9\.\-_]+)?""".r
+ val less = """([a-zA-Z0-9/\-_\$\.]+)""".r
+
+ a match {
+ // Empty, return.
+ case Nil => om
+ // Double dash options without value.
+ case double(k, null) :: t => next(om + (Symbol(k.tail.tail) -> ""), t)
+ // Double dash options with value.
+ case double(k, v) :: t => next(om + (Symbol(k.tail.tail) -> v.tail), t)
+ // Single dash options without value.
+ case single(k, null) :: t => next(om + (Symbol(k.tail) -> ""), t)
+ // Single dash options with value. Value is discarded.
+ case single(k, v) :: t => next(om + (Symbol(k.tail) -> ""), t)
+ // Dashless options.
+ case less(v) :: t if v.head != '-' =>
+ if (om.contains('dashless))
+ next((om - 'dashless) + ('dashless -> (om('dashless).get + " " + v.trim)), t)
+ else next(om + ('dashless -> v.trim), t)
+ // Invalid option, ignore.
+ case _ :: t => next(om, t)
+ }
+ }
+
+ next(Map.empty[Symbol, OptionString], varargs.toList)
+ }
+ }
+
+
+ abstract class Command(
+ protected val help: (OptionMap => String),
+ protected val predicate: (OptionMap => Boolean),
+ protected val execute: (OptionMap => String)
+ ) {
+ final def main(args: Array[String]): Unit = {
+ val opts: OptionMap = args
+
+ try
+ if (opts.contains('h) || opts.contains('help)) {
+ println(help(opts))
+ exit(opts)
+ } else if (predicate(opts)) {
+ println(execute(opts))
+ exit(opts)
+ } else throw new IllegalArgumentException("Expected valid syntax. See --help.")
+ catch { case e: Throwable => error(e, opts) }
+ }
+
+ private def error(error: Throwable, opts: OptionMap): Unit =
+ if (!isUnitTest(opts)) {
+ println(error.getMessage)
+ sys.exit(1)
+ } else throw error
+
+ private def exit(opts: OptionMap): Unit = if (!isUnitTest(opts)) sys.exit(0)
+
+ private def isUnitTest(opts: OptionMap) =
+ opts.contains('ut) || (opts.contains('unitTest) && opts.get('unitTest) != "false")
+ }
+}
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/metaphonealgorithm.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/metaphonealgorithm.scala
new file mode 100755
index 0000000..95f14b6
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/metaphonealgorithm.scala
@@ -0,0 +1,16 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.MetaphoneAlgorithm
+
+case object metaphonealgorithm extends Command(
+ (opts) =>
+ "Returns the phonetic representation of the passed string, per the Metaphone algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "metaphonealgorithm [Options] string..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 1,
+ (opts) => MetaphoneAlgorithm.compute(opts('dashless)).getOrElse("not computable")
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/metaphonemetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/metaphonemetric.scala
new file mode 100755
index 0000000..1249723
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/metaphonemetric.scala
@@ -0,0 +1,21 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.MetaphoneMetric
+
+case object metaphonemetric extends Command(
+ (opts) =>
+ "Compares two strings to determine if they are phonetically similarly, per the Metaphone algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "metaphonemetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+ MetaphoneMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/nysiisalgorithm.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/nysiisalgorithm.scala
new file mode 100755
index 0000000..bef2bc5
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/nysiisalgorithm.scala
@@ -0,0 +1,16 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.NysiisAlgorithm
+
+case object nysiisalgorithm extends Command(
+ (opts) =>
+ "Returns the phonetic representation of the passed string, per the NYSIIS algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "nysiisalgorithm [Options] string..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and options.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 1,
+ (opts) => NysiisAlgorithm.compute(opts('dashless)).getOrElse("not computable")
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/nysiismetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/nysiismetric.scala
new file mode 100755
index 0000000..7857c21
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/nysiismetric.scala
@@ -0,0 +1,21 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.NysiisMetric
+
+case object nysiismetric extends Command(
+ (opts) =>
+ "Compares two strings to determine if they are phonetically similarly, per the NYSIIS algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "nysiismetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+ NysiisMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinednysiisalgorithm.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinednysiisalgorithm.scala
new file mode 100755
index 0000000..3fc9f25
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinednysiisalgorithm.scala
@@ -0,0 +1,16 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.RefinedNysiisAlgorithm
+
+case object refinednysiisalgorithm extends Command(
+ (opts) =>
+ "Returns the phonetic representation of the passed string, per the refined NYSIIS algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "refinednysiisalgorithm [Options] string..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 1,
+ (opts) => RefinedNysiisAlgorithm.compute(opts('dashless)).getOrElse("not computable")
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinednysiismetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinednysiismetric.scala
new file mode 100755
index 0000000..2566fa8
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinednysiismetric.scala
@@ -0,0 +1,21 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.RefinedNysiisMetric
+
+case object refinednysiismetric extends Command(
+ (opts) =>
+ "Compares two strings to determine if they are phonetically similarly, per the refined NYSIIS algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "refinednysiismetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and options.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+ RefinedNysiisMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinedsoundexalgorithm.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinedsoundexalgorithm.scala
new file mode 100755
index 0000000..12ac8e0
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinedsoundexalgorithm.scala
@@ -0,0 +1,16 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.RefinedSoundexAlgorithm
+
+case object refinedsoundexalgorithm extends Command(
+ (opts) =>
+ "Returns the phonetic representation of the passed string, per the refined Soundex algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "refinedsoundexalgorithm [Options] string..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 1,
+ (opts) => RefinedSoundexAlgorithm.compute(opts('dashless)).getOrElse("not computable")
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinedsoundexmetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinedsoundexmetric.scala
new file mode 100755
index 0000000..370bd71
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/refinedsoundexmetric.scala
@@ -0,0 +1,21 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.RefinedSoundexMetric
+
+case object refinedsoundexmetric extends Command(
+ (opts) =>
+ "Compares two strings to determine if they are phonetically similarly, per the refined Soundex algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "refinedsoundexmetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and options.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+ RefinedSoundexMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/soundexalgorithm.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/soundexalgorithm.scala
new file mode 100755
index 0000000..56cf068
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/soundexalgorithm.scala
@@ -0,0 +1,16 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.SoundexAlgorithm
+
+case object soundexalgorithm extends Command(
+ (opts) =>
+ "Returns the phonetic representation of the passed string, per the Soundex algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "soundexalgorithm [Options] string..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 1,
+ (opts) => SoundexAlgorithm.compute(opts('dashless)).getOrElse("not computable")
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/soundexmetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/soundexmetric.scala
new file mode 100755
index 0000000..c7ec0cd
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/phonetic/soundexmetric.scala
@@ -0,0 +1,21 @@
+package com.rockymadden.stringmetric.cli.phonetic
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.phonetic.SoundexMetric
+
+case object soundexmetric extends Command(
+ (opts) =>
+ "Compares two strings to determine if they are phonetically similarly, per the Soundex algorithm." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "soundexmetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and options.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+ SoundexMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/dicesorensenmetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/dicesorensenmetric.scala
new file mode 100755
index 0000000..bb7ac0b
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/dicesorensenmetric.scala
@@ -0,0 +1,26 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.DiceSorensenMetric
+
+case object dicesorensenmetric extends Command(
+ (opts) =>
+ "Compares the similarity of two strings using the Dice / Sorensen coefficient." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "dicesorensenmetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts." +
+ Tab + "--n" + Ls +
+ Tab + Tab + "The n-gram size, traditionally 2.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2 &&
+ opts.contains('n) && (opts('n): Int) >= 1,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+ val n: Int = opts('n)
+
+ DiceSorensenMetric(n).compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/hammingmetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/hammingmetric.scala
new file mode 100755
index 0000000..e3db059
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/hammingmetric.scala
@@ -0,0 +1,22 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.HammingMetric
+
+case object hammingmetric extends Command(
+ (opts) =>
+ "Compares the number of characters that two equal length strings are different from one another." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "hammingmetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and options.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+
+ HammingMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jaccardmetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jaccardmetric.scala
new file mode 100755
index 0000000..8301158
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jaccardmetric.scala
@@ -0,0 +1,26 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.JaccardMetric
+
+case object jaccardmetric extends Command(
+ (opts) =>
+ "Compares the similarity of two strings using the Jaccard coefficient." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "jaccardmetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts." +
+ Tab + "--n" + Ls +
+ Tab + Tab + "The n-gram size.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2
+ && opts.contains('n) && (opts('n): Int) >= 1,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+ val n: Int = opts('n)
+
+ JaccardMetric(n).compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jarometric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jarometric.scala
new file mode 100755
index 0000000..cb7e188
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jarometric.scala
@@ -0,0 +1,22 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.JaroMetric
+
+case object jarometric extends Command(
+ (opts) =>
+ "Compares two strings to calculate the Jaro distance." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "jarometric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and options.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+
+ JaroMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jarowinklermetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jarowinklermetric.scala
new file mode 100755
index 0000000..5cfcb1e
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/jarowinklermetric.scala
@@ -0,0 +1,22 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.JaroWinklerMetric
+
+case object jarowinklermetric extends Command(
+ (opts) =>
+ "Compares two strings to calculate the Jaro-Winkler distance." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "jarowinklermetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+
+ JaroWinklerMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/levenshteinmetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/levenshteinmetric.scala
new file mode 100755
index 0000000..9cfb021
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/levenshteinmetric.scala
@@ -0,0 +1,23 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.LevenshteinMetric
+
+case object levenshteinmetric extends Command(
+ (opts) =>
+ "Compares the number of characters that two strings are different from one another via insertion, deletion, " +
+ "and substitution." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "levenshteinmetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and options.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+
+ LevenshteinMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/ngrammetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/ngrammetric.scala
new file mode 100755
index 0000000..26914c8
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/ngrammetric.scala
@@ -0,0 +1,26 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.NGramMetric
+
+case object ngrammetric extends Command(
+ (opts) =>
+ "Compares the similarity of two strings using an N-Gram similarity index." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "ngrammetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and options." +
+ Tab + "--n" + Ls +
+ Tab + Tab + "The n.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2 &&
+ opts.contains('n) && (opts('n): Int) >= 1,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+ val n: Int = opts('n)
+
+ NGramMetric(n).compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/overlapmetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/overlapmetric.scala
new file mode 100755
index 0000000..a045b49
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/overlapmetric.scala
@@ -0,0 +1,26 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.OverlapMetric
+
+case object overlapmetric extends Command(
+ (opts) =>
+ "Compares the similarity of two strings using the overlap coefficient." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "overlapmetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts." +
+ Tab + "--n" + Ls +
+ Tab + Tab + "The n-gram size.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2 &&
+ opts.contains('n) && (opts('n): Int) >= 1,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+ val n: Int = opts('n)
+
+ OverlapMetric(n).compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/ratcliffobershelpmetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/ratcliffobershelpmetric.scala
new file mode 100755
index 0000000..08804b6
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/ratcliffobershelpmetric.scala
@@ -0,0 +1,22 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.RatcliffObershelpMetric
+
+case object ratcliffobershelpmetric extends Command(
+ (opts) =>
+ "Compares the similarity of two strings using the Ratcliff / Obershelp similarity index." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "ratcliffobershelpmetric [Options] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+
+ RatcliffObershelpMetric.compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)
diff --git a/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/weightedlevenshteinmetric.scala b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/weightedlevenshteinmetric.scala
new file mode 100755
index 0000000..c74f80a
--- /dev/null
+++ b/cli/src/main/scala/com/rockymadden/stringmetric/cli/similarity/weightedlevenshteinmetric.scala
@@ -0,0 +1,33 @@
+package com.rockymadden.stringmetric.cli.similarity
+
+import com.rockymadden.stringmetric.cli._
+import com.rockymadden.stringmetric.similarity.WeightedLevenshteinMetric
+
+case object weightedlevenshteinmetric extends Command(
+ (opts) =>
+ "Compares the number of characters that two strings are different from one another via insertion, deletion, " +
+ "and substitution. Allows the invoker to indicate the weight each operation takes." + Ls + Ls +
+ "Syntax:" + Ls +
+ Tab + "weightedlevenshteinmetric [Options] --deleteWeight=[double] --insertWeight=[double] --substituteWeight=[double] string1 string2..." + Ls + Ls +
+ "Options:" + Ls +
+ Tab + "--deleteWeight" + Ls +
+ Tab + Tab + "The weight given to delete operations." +
+ Tab + "-h, --help" + Ls +
+ Tab + Tab + "Outputs description, syntax, and opts." +
+ Tab + "--insertWeight" + Ls +
+ Tab + Tab + "The weight given to insert operations." +
+ Tab + "--substituteWeight" + Ls +
+ Tab + Tab + "The weight given to substitute operations.",
+ (opts) => opts.contains('dashless) && (opts('dashless): Array[String]).length == 2 &&
+ opts.contains('deleteWeight) && (opts('deleteWeight): Double) >= 0 &&
+ opts.contains('insertWeight) && (opts('insertWeight): Double) >= 0 &&
+ opts.contains('substituteWeight) && (opts('substituteWeight): Double) >= 0,
+ (opts) => {
+ val strings: Array[String] = opts('dashless)
+
+ WeightedLevenshteinMetric(opts('deleteWeight), opts('insertWeight), opts('substituteWeight))
+ .compare(strings(0), strings(1))
+ .map(_.toString)
+ .getOrElse("not comparable")
+ }
+)