Skip to content
34 changes: 33 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ tasks.dokkaHtml.configure {
outputDirectory.set(file("$buildDir/javadoc"))
}

sourceSets {
noop {
java.srcDir 'src/noop/kotlin'
}
}

dependencies {
implementation platform('org.jetbrains.kotlin:kotlin-bom')
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
Expand All @@ -22,6 +28,10 @@ dependencies {
testImplementation 'org.slf4j:slf4j-simple:1.7.36'

testImplementation 'org.jetbrains.kotlin:kotlin-test'
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5'

noopImplementation 'org.slf4j:slf4j-nop:1.7.32'
noopImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
}

task dokkaJar(type: Jar) {
Expand All @@ -37,16 +47,37 @@ task sourcesJar(type: Jar) {
from(sourceSets.getByName("main").allSource)
}

task noopSources(type: Jar) {
archiveClassifier.set("sources")
from(sourceSets.noop.allSource)
}

task noopBinary(type: Jar) {
archiveClassifier.set("")
from(sourceSets.noop.output)
}

publishing {
publications {
noop(MavenPublication) {
artifact noopSources
artifact noopBinary

pom {
name = "ktee-noop"
artifactId = "ktee-noop"
}
}

mavenJava(MavenPublication) {
from components.java
artifact sourcesJar
artifact dokkaJar

pom {
name = "ktee"
description = "KTee is Tee for Kotlin code pipelines. If you love the unix command line tee, you know what we mean."
description = "KTee is Tee for Kotlin code pipelines. " +
"If you love the unix command line tee, you know what we mean."
url.set("https://github.com/medly/ktee")
licenses {
license {
Expand Down Expand Up @@ -99,4 +130,5 @@ signing {
def signingPassword = System.getenv("OSSRH_SIGNING_PASSPHRASE")
useInMemoryPgpKeys(signingKey, signingPassword)
sign publishing.publications.mavenJava
sign publishing.publications.noop
}
47 changes: 14 additions & 33 deletions src/main/kotlin/ktee/KTee.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package ktee

import org.slf4j.Logger


/**
* Prints the value to the stdout and returns the same value. Useful when chaining
* methods. For example:
Expand All @@ -12,71 +11,53 @@ import org.slf4j.Logger
* myList.map(fn).tee(">>> ").reduce(fn)
*
*/
fun <T> T.tee(marker: String = ""): T {
println(marker + this)
return this
}
fun <T> T.tee(marker: String = "") = apply { println(marker + this) }

/**
*
* executes the lambda with the value of the chain and writes the
*
*/
inline fun <T> T.tee(fn: (T) -> String): T {
println(fn(this))
return this
}
inline fun <T> T.tee(fn: (T) -> String) = apply { println(fn(this)) }

/**
* logs the value to the given logger at info level. Message can be customized using message parameter
*/
fun <T> T.teeToInfo(logger: Logger, message: String = "{}"): T {
logger.info(message, this)
return this
}
fun <T> T.teeToInfo(logger: Logger, message: String = "{}")
= apply { logger.info(message, this) }

/**
* Evaluates the lambda and logs the result (of evaluation) to the given logger at info level
*
*/
inline fun <T> T.teeToInfo(logger: Logger, fn: (T) -> String): T {
logger.info(fn(this), this)
return this
}
inline fun <T> T.teeToInfo(logger: Logger, fn: (T) -> String)
= apply { logger.info(fn(this), this) }

/**
* logs the value to the given logger at info level. Message can be customized using message parameter
*/
fun <T> T.teeToDebug(logger: Logger, message: String = "{}"): T {
logger.debug(message, this)
return this
}
fun <T> T.teeToDebug(logger: Logger, message: String = "{}")
= apply { logger.debug(message, this) }

/**
* Evaluates the lambda and logs the result (of evaluation) to the given logger at debug level
*
*/
inline fun <T> T.teeToDebug(logger: Logger, fn: (T) -> String): T {
logger.debug(fn(this), this)
return this
}
inline fun <T> T.teeToDebug(logger: Logger, fn: (T) -> String)
= apply { logger.debug(fn(this), this) }

/**
* logs the value to the given logger at trace level. Message can be customized using message parameter
*/
fun <T> T.teeToTrace(logger: Logger, message: String = "{}"): T {
logger.trace(message, this)
return this
}
fun <T> T.teeToTrace(logger: Logger, message: String = "{}")
= apply { logger.trace(message, this) }

/**
* Evaluates the lambda and logs the result (of evaluation) to the given logger at trace level
*
*/
inline fun <T> T.teeToTrace(logger: Logger, fn: (T) -> String): T {
logger.trace(fn(this), this)
return this
}
inline fun <T> T.teeToTrace(logger: Logger, fn: (T) -> String)
= apply { logger.trace(fn(this), this) }



Expand Down
16 changes: 16 additions & 0 deletions src/noop/kotlin/ktee/KTee.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ktee

import org.slf4j.Logger

inline fun <T> T.tee(fn: (T) -> String) = this
inline fun <T> T.tee(marker: String = "") = this
inline fun <T> T.teeToInfo(logger: Logger, fn: (T) -> String) = this
inline fun <T> T.teeToDebug(logger: Logger, fn: (T) -> String) = this
inline fun <T> T.teeToTrace(logger: Logger, fn: (T) -> String) = this
inline fun <T> T.teeToInfo(logger: Logger, message: String = "{}") = this
inline fun <T> T.teeToDebug(logger: Logger, message: String = "{}") = this
inline fun <T> T.teeToTrace(logger: Logger, message: String = "{}") = this




14 changes: 7 additions & 7 deletions src/test/kotlin/ktee/KTeeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ class KTeeTest {

@Test
fun `should write to stdout`() {
assertEquals("myval\n", trapOut { "myval".tee() })
assertEquals("myval" + System.lineSeparator(), trapOut { "myval".tee() })
}

@Test
fun `should evaluate lambda and write to stdout`() {
assertEquals("value is myval\n", trapOut { "myval".tee { v -> "value is $v" } })
assertEquals("value is myval" + System.lineSeparator(), trapOut { "myval".tee { v -> "value is $v" } })
}

@Test
fun `should write to logger`() {
assertTrue(trapErr { "myval".teeToInfo(logger) }.endsWith("myval\n"))
assertTrue(trapErr { "myval".teeToInfo(logger) }.endsWith("myval" + System.lineSeparator()))
}

@Test
Expand All @@ -39,18 +39,18 @@ class KTeeTest {
trapErr { "myval".teeToInfo(logger) { "hello {}" } }
)
outputs.forEach { assertTrue { it.contains("INFO") } }
outputs.forEach { assertTrue { it.endsWith("hello myval\n") } }
outputs.forEach { assertTrue { it.endsWith("hello myval" + System.lineSeparator()) } }
}

@Test
fun `should log with trace() level`() {
fun `should log with trace level`() {
val outputs = listOf(
trapErr { "myval".teeToTrace(logger, "hello {}") },
trapErr { "myval".teeToTrace(logger) { "hello $it" } },
trapErr { "myval".teeToTrace(logger) { "hello {}" } }
)
outputs.forEach { assertTrue { it.contains("TRACE") } }
outputs.forEach { assertTrue { it.endsWith("hello myval\n") } }
outputs.forEach { assertTrue { it.endsWith("hello myval" + System.lineSeparator()) } }
}

@Test
Expand All @@ -61,7 +61,7 @@ class KTeeTest {
trapErr { "myval".teeToDebug(logger) { "hello {}" } }
)
outputs.forEach { assertTrue { it.contains("DEBUG") } }
outputs.forEach { assertTrue { it.endsWith("hello myval\n") } }
outputs.forEach { assertTrue { it.endsWith("hello myval" + System.lineSeparator()) } }
}

}