Repository: ajalt/mordant
Pull request #16 (2021-05-10 16:41:13)

Add macOS target


Patch:
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index fa546cd3..6f806fc6 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -8,8 +8,14 @@ on:
       - master
 
 jobs:
-  linux-tests:
-    runs-on: ubuntu-latest
+  test:
+    strategy:
+      matrix:
+        os:
+          - macOS-latest
+          - windows-latest
+          - ubuntu-latest
+    runs-on: ${{matrix.os}}
     steps:
       - uses: actions/checkout@v2
       - uses: eskatos/gradle-command-action@v1
@@ -25,26 +31,9 @@ jobs:
         with:
           name: error-report
           path: build-reports.zip
-  windows-tests:
-    runs-on: windows-latest
-    steps:
-      - uses: actions/checkout@v2
-      - uses: eskatos/gradle-command-action@v1
-        with:
-          dependencies-cache-enabled: true
-          arguments: mingwX64Test --stacktrace
-      - name: Bundle the build report
-        if: failure()
-        run: find . -type d -name 'reports' | zip -@ -r build-reports.zip
-      - name: Upload the build report
-        if: failure()
-        uses: actions/upload-artifact@master
-        with:
-          name: error-report
-          path: build-reports.zip
-  deploy-linux:
-    needs: [ linux-tests, windows-tests ]
-    runs-on: ubuntu-latest
+  deploy-mac-and-linux:
+    needs: test
+    runs-on: macos-latest
     steps:
       - uses: actions/checkout@v2
       - name: Fetch git tags
@@ -55,7 +44,7 @@ jobs:
           dependencies-cache-enabled: true
           arguments: :mordant:publish -PinferVersion=true
   deploy-windows:
-    needs: [ linux-tests, windows-tests ]
+    needs: test
     runs-on: windows-latest
     steps:
       - uses: actions/checkout@v2
@@ -68,7 +57,7 @@ jobs:
           arguments: :mordant:publishMingwX64PublicationToMavenRepository -PinferVersion=true
 
 env:
-  GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=true -Dkotlin.incremental=false -Dorg.gradle.project.kotlin.incremental.multiplatform=false -Dorg.gradle.project.kotlin.native.disableCompilerDaemon=true -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
+  GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=true -Dkotlin.incremental=false -Dorg.gradle.project.kotlin.incremental.multiplatform=false -Dorg.gradle.project.kotlin.native.disableCompilerDaemon=true -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
   ORG_GRADLE_PROJECT_SONATYPE_USERNAME: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_USERNAME }}
   ORG_GRADLE_PROJECT_SONATYPE_PASSWORD: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPE_PASSWORD }}
   ORG_GRADLE_PROJECT_signingKey: ${{ secrets.ORG_GRADLE_PROJECT_signingKey }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d267ce37..aee794d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,13 @@
 
 ## Unreleased
 
+### Added
+- Published artifacts for macOS
+
+### Changed
+- Update Kotlin to 1.5.0
+- All text instances and print functions now default to preformatted whitespace, meaning that spaces and newlines will be preserved. You can explicitly pass `Whitespace.NORMAL` to restore the previous behavior.
+
 ## 2.0.0-beta1
 _2021-03-26_
 
diff --git a/build.gradle.kts b/build.gradle.kts
index 04700547..f370e9d4 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,7 +1,7 @@
 import java.io.ByteArrayOutputStream
 
 plugins {
-    kotlin("jvm") version "1.4.31"
+    kotlin("jvm") version "1.5.10"
     id("org.jetbrains.dokka") version "0.10.1"
 }
 
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index f371643e..0f80bbf5 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/mordant/build.gradle.kts b/mordant/build.gradle.kts
index b2fa5a28..e20b34a8 100644
--- a/mordant/build.gradle.kts
+++ b/mordant/build.gradle.kts
@@ -9,21 +9,20 @@ plugins {
 
 kotlin {
     jvm()
-    js(LEGACY) { // TODO: enable js(BOTH) once jb:markdown does
+    js(LEGACY) {
         nodejs()
         browser()
     }
 
-    // TODO: enable other native targets once jb:markdown publishes them
-    // macosX64()
+    macosX64()
     linuxX64()
     mingwX64()
 
     sourceSets {
         all {
             with(languageSettings) {
-                languageVersion = "1.4"
-                apiVersion = "1.4"
+                languageVersion = "1.5"
+                apiVersion = "1.5"
                 useExperimentalAnnotation("kotlin.RequiresOptIn")
             }
         }
@@ -31,34 +30,23 @@ kotlin {
         val commonMain by getting {
             dependsOn(gen)
             dependencies {
-                api("com.github.ajalt.colormath:colormath:2.0.0")
-                implementation("org.jetbrains:markdown:0.2.1")
+                api("com.github.ajalt.colormath:colormath:2.1.0")
+                implementation("org.jetbrains:markdown:0.2.4")
             }
         }
         val commonTest by getting {
             dependencies {
-                implementation(kotlin("test-common"))
-                implementation(kotlin("test-annotations-common"))
-                implementation("io.kotest:kotest-assertions-core:4.4.3")
-            }
-        }
-        val jvmTest by getting {
-            dependencies {
-                implementation(kotlin("test-junit"))
-            }
-        }
-        val jsTest by getting {
-            dependencies {
-                api(kotlin("test-js"))
+                implementation(kotlin("test"))
+                implementation("io.kotest:kotest-assertions-core:4.6.0")
             }
         }
 
         val nativeMain by creating {
             dependsOn(commonMain)
         }
-//        val macosX64Main by getting {
-//            dependsOn(nativeMain)
-//        }
+        val macosX64Main by getting {
+            dependsOn(nativeMain)
+        }
         val linuxX64Main by getting {
             dependsOn(nativeMain)
         }
@@ -69,9 +57,9 @@ kotlin {
         val nativeTest by creating {
             dependsOn(commonTest)
         }
-//        val macosX64Test by getting {
-//            dependsOn(nativeTest)
-//        }
+        val macosX64Test by getting {
+            dependsOn(nativeTest)
+        }
         val linuxX64Test by getting {
             dependsOn(nativeTest)
         }
@@ -114,7 +102,7 @@ publishing {
             licenses {
                 license {
                     name.set("The Apache Software License, Version 2.0")
-                    url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
+                    url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
                     distribution.set("repo")
                 }
             }
diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/internal/Constants.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/internal/Constants.kt
index c9e6b6a3..4c4cac8f 100644
--- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/internal/Constants.kt
+++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/internal/Constants.kt
@@ -24,5 +24,6 @@ internal val SINGLE_SPACE = Span.space(1)
 @SharedImmutable
 internal val DEFAULT_PADDING = Padding.none()
 
+@Suppress("RegExpRedundantEscape") // JS requires escaping the lone `]` at the beginning of the pattern, so we can't use $OSC
 @SharedImmutable
-internal val ANSI_RE = Regex("""$OSC[^$ESC]*$ESC\\|$ESC(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])""")
+internal val ANSI_RE = Regex("""$ESC\][^$ESC]*$ESC\\|$ESC(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])""")
diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt
index a4c72ba4..c608bfbd 100644
--- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt
+++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/markdown/MarkdownRenderer.kt
@@ -56,6 +56,7 @@ private inline fun <T> List<T>.foldLines(transform: (T) -> Lines): Lines {
     }
 }
 
+@Suppress("PrivatePropertyName")
 internal class MarkdownRenderer(
     input: String,
     private val theme: Theme,
@@ -67,7 +68,7 @@ internal class MarkdownRenderer(
     private val TABLE_DELIMITER_REGEX = Regex(""":?-+:?""")
 
     @Suppress("RegExpRedundantEscape") // extra escape required on js
-    private val CHECK_BOX_REGEX = Regex("""\[[^\]]]""")
+    private val CHECK_BOX_REGEX = Regex("""\[[^\]]\]""")
 
     // Hack to work around the fact that the markdown parser doesn't parse CRLF correctly
     private val input = input.replace("\r", "")
diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/TerminalDetection.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/TerminalDetection.kt
index 169470e1..9cf9a59f 100644
--- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/TerminalDetection.kt
+++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/terminal/TerminalDetection.kt
@@ -102,10 +102,10 @@ internal object TerminalDetection {
         }
     }
 
-    private fun getTerm() = getEnv("TERM")?.toLowerCase()
+    private fun getTerm() = getEnv("TERM")?.lowercase()
 
     // https://github.com/termstandard/colors/
-    private fun getColorTerm() = getEnv("COLORTERM")?.toLowerCase()
+    private fun getColorTerm() = getEnv("COLORTERM")?.lowercase()
 
     private fun forcedColor(): AnsiLevel? {
         return when {
@@ -114,7 +114,7 @@ internal object TerminalDetection {
             getEnv("NO_COLOR") != null -> NONE
             // A lot of npm packages support the FORCE_COLOR envvar, although they all look for
             // different values. We try to support them all.
-            else -> when (getEnv("FORCE_COLOR")?.toLowerCase()) {
+            else -> when (getEnv("FORCE_COLOR")?.lowercase()) {
                 "0", "false", "none" -> NONE
                 "1", "", "true", "16color" -> ANSI16
                 "2", "256color" -> ANSI256
@@ -124,7 +124,7 @@ internal object TerminalDetection {
         }
     }
 
-    private fun getTermProgram() = getEnv("TERM_PROGRAM")?.toLowerCase()
+    private fun getTermProgram() = getEnv("TERM_PROGRAM")?.lowercase()
 
     // https://github.com/Microsoft/vscode/pull/30346
     private fun isVsCodeTerminal() = getTermProgram() == "vscode"
diff --git a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/widgets/ProgressCell.kt b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/widgets/ProgressCell.kt
index e05e8e9c..813f2dac 100644
--- a/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/widgets/ProgressCell.kt
+++ b/mordant/src/commonMain/kotlin/com/github/ajalt/mordant/widgets/ProgressCell.kt
@@ -74,7 +74,7 @@ internal class CompletedProgressCell(
             includeTotal && total == null -> "/---.-"
             else -> ""
         } + suffix
-        return Text(t, whitespace = Whitespace.PRE)
+        return Text(style(t), whitespace = Whitespace.PRE)
     }
 }
 
@@ -90,7 +90,7 @@ internal class SpeedProgressCell(
             indeterminate || completedPerSecond <= 0 -> "---.-"
             else -> completedPerSecond.formatWithSiSuffix(1)
         }
-        return Text(t + suffix, whitespace = Whitespace.PRE)
+        return Text(style(t + suffix), whitespace = Whitespace.PRE)
     }
 }
 
@@ -115,7 +115,7 @@ internal class EtaProgressCell(
         return text("$prefix$h:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}")
     }
 
-    private fun text(s: String) = Text(s, whitespace = Whitespace.PRE)
+    private fun text(s: String) = Text(style(s), whitespace = Whitespace.PRE)
 }
 
 internal class BarProgressCell(
diff --git a/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppImpl.kt b/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppImpl.kt
index f38a8c3c..f6a19d3b 100644
--- a/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppImpl.kt
+++ b/mordant/src/jvmMain/kotlin/com/github/ajalt/mordant/internal/MppImpl.kt
@@ -56,7 +56,7 @@ private fun parseSttySize(output: String): Pair<Int, Int>? {
     return dimens[1] to dimens[0]
 }
 
-internal actual fun isWindows(): Boolean = "win" in System.getProperty("os.name").toLowerCase()
+internal actual fun isWindows(): Boolean = "win" in System.getProperty("os.name").lowercase()
 
 internal actual fun getEnv(key: String): String? = System.getenv(key)
 


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 847979bc..ec0f4992 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -6,8 +6,14 @@ on:
       - '*.md'
 
 jobs:
-  linux-tests:
-    runs-on: ubuntu-latest
+  test:
+    strategy:
+      matrix:
+        os:
+          - macOS-latest
+          - windows-latest
+          - ubuntu-latest
+    runs-on: ${{matrix.os}}
     steps:
       - uses: actions/checkout@v2
       - uses: eskatos/gradle-command-action@v1
@@ -23,41 +29,6 @@ jobs:
         with:
           name: error-report
           path: build-reports.zip
-# TODO: enable once macOS target is supported
-#  macos-tests:
-#    runs-on: macos-latest
-#    steps:
-#      - uses: actions/checkout@v2
-#      - uses: eskatos/gradle-command-action@v1
-#        with:
-#          dependencies-cache-enabled: true
-#          arguments: macosX64Test --stacktrace
-#      - name: Bundle the build report
-#        if: failure()
-#        run: find . -type d -name 'reports' | zip -@ -r build-reports.zip
-#      - name: Upload the build report
-#        if: failure()
-#        uses: actions/upload-artifact@master
-#        with:
-#          name: error-report
-#          path: build-reports.zip
-  windows-tests:
-    runs-on: windows-latest
-    steps:
-      - uses: actions/checkout@v2
-      - uses: eskatos/gradle-command-action@v1
-        with:
-          dependencies-cache-enabled: true
-          arguments: mingwX64Test --stacktrace
-      - name: Bundle the build report
-        if: failure()
-        run: find . -type d -name 'reports' | zip -@ -r build-reports.zip
-      - name: Upload the build report
-        if: failure()
-        uses: actions/upload-artifact@master
-        with:
-          name: error-report
-          path: build-reports.zip
 
 env:
-  GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=true -Dkotlin.incremental=false -Dorg.gradle.project.kotlin.incremental.multiplatform=false -Dorg.gradle.project.kotlin.native.disableCompilerDaemon=true -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"
+  GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dorg.gradle.parallel=true -Dkotlin.incremental=false -Dorg.gradle.project.kotlin.incremental.multiplatform=false -Dorg.gradle.project.kotlin.native.disableCompilerDaemon=true -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8"