diff --git a/src/nativeMain/kotlin/com/norsedreki/dogcat/app/Keymap.kt b/src/nativeMain/kotlin/com/norsedreki/dogcat/app/Keymap.kt index 97ae6e1..249d87c 100644 --- a/src/nativeMain/kotlin/com/norsedreki/dogcat/app/Keymap.kt +++ b/src/nativeMain/kotlin/com/norsedreki/dogcat/app/Keymap.kt @@ -30,15 +30,14 @@ import ncurses.KEY_NPAGE import ncurses.KEY_PPAGE import ncurses.KEY_UP +@OptIn(ExperimentalForeignApi::class) object Keymap { - @OptIn(ExperimentalForeignApi::class) + fun printedShortcut(keyCode: Int) = keyNames[keyCode] ?: keyCode.toChar().toString() + val bindings = mapOf( - '?'.code to HELP, - 'r'.code to AUTOSCROLL, - 'q'.code to QUIT, - 'f'.code to INPUT_FILTER_BY_SUBSTRING, + // Navigation actions 'e'.code to HOME, KEY_HOME to HOME, 'd'.code to END, @@ -49,36 +48,63 @@ object Keymap { KEY_NPAGE to PAGE_DOWN, 'w'.code to PAGE_UP, KEY_PPAGE to PAGE_UP, - 'c'.code to CLEAR_LOGS, + + // Filter actions + 'f'.code to INPUT_FILTER_BY_SUBSTRING, 't'.code to TOGGLE_FILTER_BY_PACKAGE, // '7'.code to RESET_FILTER_BY_SUBSTRING, // '8'.code to RESET_FILTER_BY_MIN_LOG_LEVEL, + + // Log level actions '1'.code to MIN_LOG_LEVEL_V, '2'.code to MIN_LOG_LEVEL_D, '3'.code to MIN_LOG_LEVEL_I, '4'.code to MIN_LOG_LEVEL_W, '5'.code to MIN_LOG_LEVEL_E, + + // Other actions + '?'.code to HELP, + 'r'.code to AUTOSCROLL, + 'c'.code to CLEAR_LOGS, + 'q'.code to QUIT, ) - enum class Actions { - HELP, - AUTOSCROLL, - CLEAR_LOGS, - INPUT_FILTER_BY_SUBSTRING, - HOME, - END, - PAGE_UP, - PAGE_DOWN, - LINE_UP, - LINE_DOWN, - TOGGLE_FILTER_BY_PACKAGE, - RESET_FILTER_BY_SUBSTRING, - RESET_FILTER_BY_MIN_LOG_LEVEL, - MIN_LOG_LEVEL_V, - MIN_LOG_LEVEL_D, - MIN_LOG_LEVEL_I, - MIN_LOG_LEVEL_W, - MIN_LOG_LEVEL_E, - QUIT + enum class Actions(val description: String) { + // Navigation actions + HOME("Move to the beginning of log lines (Home)"), + END("Move to the end of log lines (End)"), + PAGE_UP("Move one screen up (Page Up)"), + PAGE_DOWN("Move one screen down (Page Down)"), + LINE_UP("Move one line up"), + LINE_DOWN("Move one line down"), + + // Filter actions + INPUT_FILTER_BY_SUBSTRING("Filter log lines by inputted string"), + TOGGLE_FILTER_BY_PACKAGE("Toggle filtering log lines by app package"), + RESET_FILTER_BY_SUBSTRING("Reset the filter for log lines by substring"), + RESET_FILTER_BY_MIN_LOG_LEVEL("Reset the filter for log lines by minimum log level"), + + // Log level actions + MIN_LOG_LEVEL_V("Set the minimum log level to V"), + MIN_LOG_LEVEL_D("Set the minimum log level to D"), + MIN_LOG_LEVEL_I("Set the minimum log level to I"), + MIN_LOG_LEVEL_W("Set the minimum log level to W"), + MIN_LOG_LEVEL_E("Set the minimum log level to E"), + + // Other actions + HELP("Display this window on screen or hide it"), + AUTOSCROLL("Toggle automatic scrolling of log lines on screen"), + CLEAR_LOGS("Clear log source and empty log lines on screen"), + QUIT("Quit this application") } + + private val keyNames = + mapOf( + KEY_HOME to "Home", + KEY_END to "End", + KEY_UP to "Up", + KEY_DOWN to "Down", + KEY_NPAGE to "Page Down", + KEY_PPAGE to "Page Up", + ) } diff --git a/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/Strings.kt b/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/Strings.kt index 3324176..3458465 100644 --- a/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/Strings.kt +++ b/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/Strings.kt @@ -18,4 +18,6 @@ object Strings { const val SEPARATOR = " | " const val ALL_APPS = "All apps" + + const val HELP_WINDOW_TITLE = "Help: Shortcuts" } diff --git a/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/help/HelpPresenter.kt b/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/help/HelpPresenter.kt index cac481e..fcde227 100644 --- a/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/help/HelpPresenter.kt +++ b/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/help/HelpPresenter.kt @@ -27,18 +27,26 @@ class HelpPresenter( } override suspend fun stop() { - // No op since views come and go along with hotkey for help. + // No op since views come and go along with shortcut for help. } private suspend fun collectKeypresses() { lateinit var view: HelpView - var showing = false input.keypresses.collect { key -> when (Keymap.bindings[key]) { HELP -> { - val h = Keymap.bindings.entries.map { "${it.value.name} -- '${Char(it.key)}'" } + val maxDescriptionLength = + Keymap.bindings.values.maxOf { it.description.length } + 3 + + val lines = + Keymap.bindings.entries.map { + val dotsCount = + maxOf(3, maxDescriptionLength - it.value.description.length + 1) + + "${it.value.description}${".".repeat(dotsCount)}${Keymap.printedShortcut(it.key)}" + } if (!showing) { appState.holdUi(true) @@ -47,7 +55,7 @@ class HelpPresenter( view.start() yield() - view.state = HelpView.State(h) + view.state = HelpView.State(lines) showing = true } else { diff --git a/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/help/HelpView.kt b/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/help/HelpView.kt index 5d36ac8..e63a461 100644 --- a/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/help/HelpView.kt +++ b/src/nativeMain/kotlin/com/norsedreki/dogcat/app/ui/help/HelpView.kt @@ -6,6 +6,7 @@ package com.norsedreki.dogcat.app.ui.help import com.norsedreki.dogcat.app.ui.HasLifecycle +import com.norsedreki.dogcat.app.ui.Strings.HELP_WINDOW_TITLE import kotlin.properties.Delegates import kotlinx.cinterop.CPointer import kotlinx.cinterop.ExperimentalForeignApi @@ -36,8 +37,8 @@ class HelpView : HasLifecycle { val sx = getmaxx(stdscr) / 2 window = newwin(1, 1, sy, sx)!! - werase(window) // clear the window - wrefresh(window) // refresh the window to apply the clearing + werase(window) + wrefresh(window) } override suspend fun stop() { @@ -45,11 +46,11 @@ class HelpView : HasLifecycle { } private fun updateView(state: State) { - val horizontalPadding = 4 // adjust this value as needed - val verticalPadding = 2 // adjust this value as needed + val horizontalPadding = 4 + val verticalPadding = 2 val maxWidth = - maxOf(state.text.maxOf { it.length }, "Help: hotkeys".length) + horizontalPadding * 2 + maxOf(state.text.maxOf { it.length }, HELP_WINDOW_TITLE.length) + horizontalPadding * 2 val height = state.text.size + @@ -64,21 +65,18 @@ class HelpView : HasLifecycle { wresize(window, height, maxWidth) mvwin(window, startY, startX) - box(window, 0U, 0U) // draw a box around the window + box(window, 0U, 0U) - // Add title - val title = "Help: hotkeys" - val titleStartX = (maxWidth - title.length) / 2 - mvwaddstr(window, verticalPadding, titleStartX, title) + val titleStartX = (maxWidth - HELP_WINDOW_TITLE.length) / 2 + mvwaddstr(window, verticalPadding, titleStartX, HELP_WINDOW_TITLE) - // Add text state.text.forEachIndexed { index, line -> mvwaddstr( window, index + verticalPadding + 2, horizontalPadding, line, - ) // start from the third line + ) } wrefresh(window)