kakoune: [BUG] JSON UI only shows stdin when connecting to an existing session
Version of Kakoune
v2021.11.08
Reproducer
Create a script that will print text without exiting:
# make_commands.sh
while :
do
echo '{"jsonrpc":"2.0","method":"keys","params":["e"]}'
sleep 1
done
Then, create a named kak session
kak -ui "json" -s "test"
Then, try to connect with a second client that has a non-tty stdin:
sh ./make_commands.sh | kak -ui "json" -c "test"
Outcome
the second client shows a FIFO buffer where the contents of stdin are displayed as text rather than interpreted as commands.
Expectations
If you pipe input into a normal kak instance, it will display the text from stdin in a fifo buffer.
sh ./make_commands.sh | kak
(The status line shows *stdin* 1:1 [scratch][fifo] 1 sel - client0@[1608978]
.)
If you pipe text to stdin of a kak instance created with -ui json
, it will know to treat the input as JSON RPC commands and open the normal scratch buffer.
sh ./make_commands.sh | kak -ui "json"
{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "*scratch* 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "[scratch]" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[1610796]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }
But, if you pipe into the stdin of a JSON UI client that is connecting to an existing session, it goes back to the original behaviour where the input is interpreted as text, not commands, and is displayed (the status line is [fifo]
).
sh ./make_commands.sh | kak -ui "json" -c "test"
{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "*stdin-1* 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "[scratch][fifo]" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client1@[test]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }
This makes multiple clients useless for JSON UI because you cannot interact with them by sending commands. Instead, it should interpret stdin as RPC commands and not display them to the user
Additional information
I am using Ubuntu 20.04.2 LTS.
I first encountered this error running kak from a Rust program with
Command::new("kak")
.args(&["-ui", "json"])
.args(&["-c", "test"])
.stdout(Stdio::piped())
.stdin(Stdio::piped())
.spawn()
.unwrap()
but I was able to reproduce it in the terminal (Alacritty) as well.
This error seems to be a regression. A very old version of kak (probably from a couple years ago – I don’t remember the version number) did not have this issue but a late 2020 or early 2021 version introduced it.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 16 (10 by maintainers)
Commits related to this issue
- JSON UI only shows stdin when connecting to an existing session #4432 json-ui is not intended to be a user interactive session so don't worry about making the tty your stdin if fd 0 is not a tty. Th... — committed to sidkshatriya/kakoune by sidkshatriya 3 years ago
- Fixes #4432: JSON UI only shows stdin when connecting to an existing session Only ui type Terminal is intended to be a user interactive session. If your ui type is not Terminal, don't worry about mak... — committed to sidkshatriya/kakoune by sidkshatriya 3 years ago
- Fixes #4432: JSON UI only shows stdin when connecting to an existing session Only ui type Terminal is intended to be a user interactive session. If your ui type is not Terminal, don't worry about mak... — committed to sidkshatriya/kakoune by sidkshatriya 3 years ago
- Fixes #4432: JSON UI only shows stdin when connecting to an existing session Only ui type Terminal is intended to be a user interactive session. If your ui type is not Terminal, don't worry about mak... — committed to sidkshatriya/kakoune by sidkshatriya 3 years ago
- Fixes #4432: JSON UI only shows stdin when connecting to an existing session Only ui type Terminal is intended to be a user interactive session. If your ui type is not Terminal, don't worry about mak... — committed to TeddyDD/kakoune by sidkshatriya 3 years ago
…yes, but nobody wants to type JSON blobs manually, you want to generate them in some other program and pipe them to the JSON UI client, which is when you hit this bug.
Looking into the code, it seems that when started normally,
main()
callsrun_server()
which callscreate_local_ui()
which does the right thing - it handles reading stdin into a buffer for the terminal UI, but does nothing special for the JSON or dummy UIs.Meanwhile, when started with
-c
,main()
callsrun_client()
which callsmake_ui()
(no special treatment for any kind of UI) and thenRemoteClient()
which passes the stdin file descriptor to the server to read it, regardless of what UI type is being used.This is definitely a problem, but it’s not obvious to me how to solve it.
Yes, it looks like commenting out that if block fixes the issue! As a medium-term solution just having a cli flag to skip that check would solve my problem. But ideally that behaviour should be fixed. For now I can just comment it out. Thanks!
@sidkshatriya That is exactly what I am doing. Like you said, I override the
new
command to call back to my Rust app (via a custom fifo queue for now, although it would be nice if there was support for arbitrary UI commands in the JSON API). In my Rust app, I start a process withkak -ui json -c <session name>
and pipe JSON RPC commands to it. The bug seems to be that instances started withkak -ui json -c
don’t correctly handle JSON input.I get valid JSON UI output back that I can display, but when I send JSON commands via the stdin of the
kak -ui json -c
they are not interpreted correctly.