Skip to content

Commit

Permalink
Add validation for input arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
NorseDreki committed Feb 27, 2024
1 parent 6951cff commit f425da0
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 15 deletions.
12 changes: 9 additions & 3 deletions src/nativeMain/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import logger.Logger
import logger.context
import platform.posix.exit
import userInput.Arguments
import userInput.Keymap
import userInput.Keymap.Actions

@OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class)
fun main(args: Array<String>) {
Arguments.validate(args)
val appModule = AppModule()

try {
appModule.arguments.validate(args)
} catch (e: Arguments.ValidationException) {
println(e.message)
exit(1)
}

val ui = newSingleThreadContext("UI")

Expand All @@ -24,8 +32,6 @@ fun main(args: Array<String>) {
//he key takeaway is that if you call launch on a custom CoroutineScope, any CoroutineExceptionHandler provided
// directly to the CoroutineScope constructor or to launch will be executed when an exception is thrown within the launched coroutine.
val appJob = CoroutineScope(ui).launch(handler) {
val appModule = AppModule()

with(appModule) {
Logger.set(fileLogger)

Expand Down
8 changes: 7 additions & 1 deletion src/nativeMain/kotlin/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import BuildConfig
import FileLogger
import InternalAppState
import di.DogcatModule.dogcatModule
import kotlinx.coroutines.CloseableCoroutineDispatcher
import kotlinx.cli.ArgParser
import logger.CanLog
import logger.NoOpLogger
import org.kodein.di.DI
Expand All @@ -14,6 +14,7 @@ import org.kodein.di.instance
import ui.AppPresenter
import ui.logLines.LogLinesPresenter
import ui.status.StatusPresenter
import userInput.Arguments
import userInput.DefaultInput
import userInput.Input

Expand All @@ -27,6 +28,7 @@ class AppModule {
NoOpLogger()
}
}
bindSingleton<Arguments> { Arguments(ArgParser("dogcat")) }
bindSingleton<AppState> { InternalAppState() }
bindSingleton<Input> { DefaultInput(instance()) }
bindSingleton<AppPresenter> {
Expand All @@ -35,6 +37,7 @@ class AppModule {
instance(),
instance(),
instance(),
instance(),
instance()
)
}
Expand All @@ -47,6 +50,7 @@ class AppModule {
}
bindSingleton<LogLinesPresenter> {
LogLinesPresenter(
instance(),
instance(),
instance(),
instance()
Expand All @@ -61,6 +65,8 @@ class AppModule {

val fileLogger: CanLog by serviceLocator.instance()

val arguments: Arguments by serviceLocator.instance()

val input: Input by serviceLocator.instance()

val appPresenter: AppPresenter by serviceLocator.instance()
Expand Down
11 changes: 7 additions & 4 deletions src/nativeMain/kotlin/ui/AppPresenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import dogcat.state.PublicState
import dogcat.state.PublicState.Active
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.launch
import logger.Logger
import logger.context
import ui.Strings.INPUT_FILTER_PREFIX
import ui.logLines.LogLinesPresenter
import ui.status.StatusPresenter
import userInput.Arguments
Expand All @@ -25,6 +27,7 @@ import kotlin.coroutines.coroutineContext

class AppPresenter(
private val dogcat: Dogcat,
private val arguments: Arguments,
private val appState: AppState,
private val input: Input,
private val logLinesPresenter: LogLinesPresenter,
Expand All @@ -35,8 +38,8 @@ class AppPresenter(

override suspend fun start() {
when {
Arguments.packageName != null -> dogcat(PickAppPackage(Arguments.packageName!!))
Arguments.current == true -> dogcat(PickForegroundApp)
arguments.packageName != null -> dogcat(PickAppPackage(arguments.packageName!!))
arguments.current == true -> dogcat(PickForegroundApp)
else -> dogcat(PickAllApps)
}

Expand Down
3 changes: 2 additions & 1 deletion src/nativeMain/kotlin/ui/logLines/LogLinesPresenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import kotlin.coroutines.coroutineContext

class LogLinesPresenter(
private val dogcat: Dogcat,
private val arguments: Arguments,
private val appState: AppState,
private val input: Input,
) : HasLifecycle {
Expand Down Expand Up @@ -55,7 +56,7 @@ class LogLinesPresenter(
.collect {
view.state = view.state.copy(
autoscroll = it.autoscroll,
showLineNumbers = Arguments.lineNumbers ?: false,
showLineNumbers = arguments.lineNumbers ?: false,
isCursorHeld = it.isCursorHeld,
cursorReturnLocation = it.inputFilterLocation
)
Expand Down
28 changes: 22 additions & 6 deletions src/nativeMain/kotlin/userInput/Arguments.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,34 @@ import kotlinx.cli.ArgParser
import kotlinx.cli.ArgType
import kotlinx.cli.optional

object Arguments {
class Arguments(private val parser: ArgParser) {

private val parser = ArgParser("dogcat")
class ValidationException(override val message: String) : RuntimeException(message)

val packageName by parser.argument(ArgType.String, "package name", "description for p n").optional()
val current by parser.option(ArgType.Boolean, shortName = "c", description = "Filter by currently running program")
val lineNumbers by parser.option(ArgType.Boolean, shortName = "ln", description = "Show line numbers")
val packageName by parser.argument(
ArgType.String,
"package name",
"Show logs for a particular application specified by this package name. " +
"Example: 'com.google.android.apps.messaging'."
).optional()

val current by parser.option(
ArgType.Boolean,
shortName = "c",
description = "Show logs for an application currently running in foreground"
)

val lineNumbers by parser.option(
ArgType.Boolean,
shortName = "ln",
description = "Show line numbers for log lines, embedded into message body"
)

fun validate(args: Array<String>) {
parser.parse(args)
if (packageName != null && current != null) {
//can't have both at the same time
throw ValidationException("'Package name' and '--current' arguments are mutually exclusive and " +
"can't be used at the same time.")
}
}
}

0 comments on commit f425da0

Please sign in to comment.