Skip to content

Commit

Permalink
Drop wgetnstr in favor of wgetch, since it does not support editing
Browse files Browse the repository at this point in the history
  • Loading branch information
NorseDreki committed Feb 18, 2024
1 parent bd0d306 commit 37c270a
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 21 deletions.
3 changes: 3 additions & 0 deletions src/nativeInterop/cinterop/ncurses.def
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ compilerOpts.linux = -I/usr/include -I/usr/include/ncurses -I/usr/include/x86_64
linkerOpts.linux = -L/usr/local/lib/ -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -lncurses --allow-shlib-undefined
#libraryPaths = /usr/local/lib/ /usr/lib64 /usr/lib/x86_64-linux-gnu
#staticLibraries = libform.a libmenu.a libpanel.a libutil.a libtinfo.a libdl.a libncurses.a


#./dogcat.kexe: /lib64/libncurses.so.6: version `NCURSES6_5.0.19991023' not found (required by ./dogcat.kexe)
9 changes: 1 addition & 8 deletions src/nativeMain/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import di.AppModule
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import logger.Logger
import logger.context
Expand All @@ -25,7 +24,7 @@ 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()
val appModule = AppModule(ui)

with(appModule) {
Logger.set(fileLogger)
Expand Down Expand Up @@ -53,10 +52,4 @@ fun main(args: Array<String>) {

Logger.d("Exit!")
Logger.close()

/*signal(SIGINT, staticCFunction<Int, Unit> { signal ->
// This code will be executed when Ctrl+C is pressed
println("SIGINT received")
exitProcess(0)
})*/
}
5 changes: 5 additions & 0 deletions src/nativeMain/kotlin/ui/AppView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class AppView {
//melpomene

nodelay(stdscr, true) //The nodelay option causes getch to be a non-blocking call. If no input is ready, getch returns ERR. If disabled (bf is FALSE), getch waits until a key is pressed

//cbreak or raw, to make wgetch read unbuffered data, i.e., not waiting for '\n'.
//nodelay or timeout, to control the amount of time wgetch spends waiting for input.

//??? enable
//cbreak() //making getch() work without a buffer I.E. raw characters

if (!has_colors()) {
Expand Down
12 changes: 6 additions & 6 deletions src/nativeMain/kotlin/ui/status/StatusPresenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,18 @@ class StatusPresenter(
.filter { it }
.distinctUntilChanged()
.flatMapLatest {
input.keypresses
}
.filter {
Keymap.bindings[it] == InputFilterBySubstring
input.strings
}
.onEach {
val filterString = view.inputFilter()
view.inputFilter1()

dogcat(FilterBy(Substring(filterString)))
dogcat(FilterBy(Substring(it)))
}
.launchIn(scope)




appStateFlow
.state
.onEach {
Expand Down
14 changes: 12 additions & 2 deletions src/nativeMain/kotlin/ui/status/StatusView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ class StatusView {

private var filterLength = "Filter: ".length

fun inputFilter1() {
val prompt = ""//""Filter: "
mvwprintw(window, 1, 0, prompt)
wmove(window, 1, prompt.length)
}

suspend fun inputFilter(): String = memScoped {
val sx = getmaxx(stdscr)

Expand All @@ -60,15 +66,19 @@ class StatusView {
val j = CoroutineScope(coroutineContext).launch {
while (isActive) {
delay(10)
wmove(stdscr, 49 , 0)
wmove(stdscr, 49 , 2)
wrefresh(stdscr)
//Logger.d("moved (${getcurx(window)}, ${getcury(window)})")
}
}

withContext(Dispatchers.IO) {
//wgetch(window)
//keypad(window, false)

wgetnstr(window, bytePtr, 200)

//keypad(window, true)
//readLine() ?: "zzzz"
}

Expand Down Expand Up @@ -122,7 +132,7 @@ class StatusView {
filters.forEach {
when (it.key) {
Substring::class -> {
val fs = "Filter: ${(it.value as Substring).substring}"
val fs = "${(it.value as Substring).substring}"
filterLength = fs.length

wattroff(window, COLOR_PAIR(12))
Expand Down
95 changes: 90 additions & 5 deletions src/nativeMain/kotlin/userInput/Input.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,111 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import logger.Logger
import logger.context
import ncurses.ERR
import ncurses.stdscr
import ncurses.wgetch
import ncurses.*
import ui.HasLifecycle
import kotlin.coroutines.coroutineContext

interface Input : HasLifecycle {
val keypresses: Flow<Int>

val strings: Flow<String>
}

class DefaultInput(
private val ioDispatcher: CoroutineDispatcher
) : Input {

private val keypressesSubject = MutableSharedFlow<Int>()
override val keypresses = keypressesSubject//.debounceRepetitiveKeys(150.milliseconds)
override val keypresses = keypressesSubject //.debounceRepetitiveKeys(150.milliseconds)

private val stringsSubject = MutableSharedFlow<String>()
override val strings = stringsSubject

private var inputMode = false
//private val inputModeMutex = Mutex()

private val fl = 0//"Filter: ".length

private var inputBuffer = StringBuilder()
private var cursorPosition = fl

@OptIn(ExperimentalForeignApi::class)
override suspend fun start() {
CoroutineScope(coroutineContext)
.launch(ioDispatcher) {
while (isActive) {
val key = wgetch(stdscr)

if (key == ERR) {

if (inputMode) {
curs_set(1)
wmove(stdscr, 49 , cursorPosition)
wrefresh(stdscr)
}

delay(INPUT_KEY_DELAY_MILLIS)


continue
}

if (Keymap.bindings[key] == Keymap.Actions.InputFilterBySubstring) {
inputMode = true
//echo()

continue
}

if (inputMode) {
when (key) {
KEY_LEFT -> if (cursorPosition > 0) cursorPosition--
KEY_RIGHT -> if (cursorPosition < inputBuffer.length) cursorPosition++
KEY_BACKSPACE, 127/*, KEY_DELETE*/ -> {
Logger.d("${context()} Delete char")

if (cursorPosition > 0) {
inputBuffer.deleteAt(cursorPosition - fl - 1)
cursorPosition--
// Delete the character on the screen
mvdelch(49, cursorPosition)
}
}

'\n'.code -> {
// Handle the completed input
val input = inputBuffer.toString()
inputBuffer.clear()
cursorPosition = fl
//noecho()
inputMode = false
// Emit the input string
stringsSubject.emit(input)
}

//filter out control characters
else -> {
val char = key.toChar()
if (char in ' '..'~') {
inputBuffer.insert(cursorPosition, char)
mvaddch(49, cursorPosition, key.toUInt())
cursorPosition++
// Add the character to the screen
}
}
}
// Move the cursor to the correct position
wmove(stdscr, 49, cursorPosition)

} else {
Logger.d("${context()} Process key $key")
keypressesSubject.emit(key)
}
}
}


/*CoroutineScope(coroutineContext)
.launch(ioDispatcher) {
while (isActive) {
val key = wgetch(stdscr)
Expand All @@ -40,7 +125,7 @@ class DefaultInput(
keypressesSubject.emit(key)
}
}
}*/
}

override suspend fun stop() {
Expand Down

0 comments on commit 37c270a

Please sign in to comment.