You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm not intricately familiar with the codebase or Java stdin handling, but I wouldn't expect one method call to break the other even though they use the same NonBlockingReader instance. I get this impression because the calls shouldn't be even remotely overlapping.
Actual behavior
The first call to LineReader's readLine(String) method using a Terminal instance's NonBlockingReader breaks arrow key navigation for a BindingReader's readBinding(Map, Map, boolean) that uses the same NonBlockingReader, until the application is restarted.
Description of issue
I'm developing an app which I built somewhat based on the builtin Nano.
In the main loop, there's a call to BindingReader.readBinding(Map, Map, boolean) that looks like this:
// ...Opinput;
while (isRunAllowed()) {
input = bindingReader.readBinding(keyMap, keyMap, true);
if (input != null) {
switch (input) {
// ...
This main loop is within a Runnable class' run() function, which gets called like this:
publicvoiddoStart() {
ThreadFactoryfactory = r -> {
StringthreadName = "\"The\" thread";
Threadresult = newThread(r, threadName);
// the JVM instaquits if only daemon (user) threads are running, so set this to falseresult.setDaemon(false);
returnresult;
};
this.executor = Executors.newSingleThreadExecutor(factory);
executor.execute(this);
}
I'm using it with a Terminal-s NonBlockingReader:
//... input class constructorthis.bindingReader = newBindingReader(terminal.reader());
//...
when a certain Op is matched by the BindingReader, I handle it by prompting the user for input:
// ... in handler method called from switch case for the user promptStringnInput;
nInput = selectionReader.readLine(prompt);
// ...
As soon as selectionReader.readLine(prompt) is called, arrow keys presses aren't recognized by the BindingReader anymore, and instead get recognized as collections of the characters ],[,O,A,B,C,D, like what one sees when pressing arrow keys in a terminal program that doesn't consume the input.
Before this happens, the readBinding call in my main loop correctly distinguishes and receives ENTER_CHAR and arrow key presses. Afterwards, a single arrow key gets read as one or multiple ENTER_CHAR bindings.
The arrow key bindings are bound like this, analogous to jline3 examples:
It would seem that the readLine call is capturing some subsequences of the bytes that would be otherwise received by readBinding.
When I looked a bit deeper, for example in KeyMap.getBound(Charsequence, int[]) I found that even at this level, the received bytes were incorrect for the mapping. The codes almost always started with the byte 27, which is the correct place for the arrow key mappings, but subsequent bytes wouldn't point to the four mappings below that.
Interestingly enough, this isn't breaking in all terminals:
OS
Shell/Terminal
Works without issue
Windows 10
cmd.exe in Windows Terminal
✅
Windows 10
powershell.exe in Windows Terminal
❌
Windows 10/WSL2/Ubuntu 18.04
zsh in Windows Terminal
❌
OSX
zsh in Terminal
❌
OSX
zsh in iTerm
❌
I tried some dumb things to begin with, but couldn't resolve the issue. Because the two read operations rely on a shared NonBlockingReader I expect that there is a workaround and I'm just using the resources incorrectly.
Thanks for the help in advance!
The text was updated successfully, but these errors were encountered:
PMarci
changed the title
LineReader.readline(String) seems to interfere with BindingReader.readBinding(Map, Map, boolean)
LineReader.readline(String) interferes with BindingReader.readBinding(Map, Map, boolean)
Oct 21, 2021
Thx for the detailed explanation. That does not ring any bell though. Would it be possible to create a small reproductible project so that I can investigate ?
It will take some time, but I'm invested in getting this resolved. I could try and rip out the relevant parts in the coming days.
If it's not an issue to you, you could take the entire project to test in the meantime. Let me know if you gave it a shot.
Installation
git clone git@github.com:PMarci/ejigma.git
cd ./ejigma
mvn clean package
# optional for running jar in a command-like way instead of a parameter to java
./build
# optional
install ./ejigma /usr/local/bin
Reproduction
run the jar any way you prefer, but without arguments (no params to the command-like or -Dexec.args to maven)
This should launch the app in interactive mode. Press any key if the title screen doesn't go away.
the screen should clear
press some keys, encrypted characters should appear
verify that moving the cursor by arrow keys works
press Ctrl + I or Ctrl + E or Ctrl + F to bring up the prompt by LineReader.readLine(String)
Press Ctrl + C to cancel the prompt. The next arrow key press should produce no input or movement. This is where the truncated byte sequences start.
pressing the arrow keys at this point produces letters.
Expected behavior
I'm not intricately familiar with the codebase or Java
stdin
handling, but I wouldn't expect one method call to break the other even though they use the sameNonBlockingReader
instance. I get this impression because the calls shouldn't be even remotely overlapping.Actual behavior
The first call to
LineReader
'sreadLine(String)
method using aTerminal
instance'sNonBlockingReader
breaks arrow key navigation for aBindingReader
'sreadBinding(Map, Map, boolean)
that uses the sameNonBlockingReader
, until the application is restarted.Description of issue
I'm developing an app which I built somewhat based on the builtin
Nano
.In the main loop, there's a call to
BindingReader.readBinding(Map, Map, boolean)
that looks like this:This main loop is within a
Runnable
class'run()
function, which gets called like this:I'm using it with a
Terminal
-sNonBlockingReader
:when a certain
Op
is matched by theBindingReader
, I handle it by prompting the user for input:As soon as
selectionReader.readLine(prompt)
is called, arrow keys presses aren't recognized by theBindingReader
anymore, and instead get recognized as collections of the characters],[,O,A,B,C,D
, like what one sees when pressing arrow keys in a terminal program that doesn't consume the input.Before this happens, the
readBinding
call in my main loop correctly distinguishes and receivesENTER_CHAR
and arrow key presses. Afterwards, a single arrow key gets read as one or multipleENTER_CHAR
bindings.The arrow key bindings are bound like this, analogous to
jline3
examples:It would seem that the
readLine
call is capturing some subsequences of the bytes that would be otherwise received byreadBinding
.When I looked a bit deeper, for example in KeyMap.getBound(Charsequence, int[]) I found that even at this level, the received bytes were incorrect for the mapping. The codes almost always started with the byte
27
, which is the correct place for the arrow key mappings, but subsequent bytes wouldn't point to the four mappings below that.Interestingly enough, this isn't breaking in all terminals:
I tried some dumb things to begin with, but couldn't resolve the issue. Because the two read operations rely on a shared
NonBlockingReader
I expect that there is a workaround and I'm just using the resources incorrectly.Thanks for the help in advance!
The text was updated successfully, but these errors were encountered: