Daemon plain file and plain text format support#76
Daemon plain file and plain text format support#76nikolayKeniston wants to merge 1 commit intoblock:mainfrom
Conversation
11614e7 to
0fbf105
Compare
staktrace
left a comment
There was a problem hiding this comment.
Generally looks good. Have a question though
| val inputLines = mutableListOf<String>() | ||
| while (true) { | ||
| val line = reader.readLine() ?: break | ||
| if (line.trim() == "\u0004") break |
There was a problem hiding this comment.
Is this needed? Can we not just the end of stream as the break condition? I think it's possible for legitimate kotlin code files using a multiline string to have this character alone on a line, and then this would fail to format them correctly.
There was a problem hiding this comment.
I tried this initially and I was able to achieve the expected result only by programmatically closing the output part of the stream. However, such simple tools as nc, as far as I understand, do not provide such an opportunity, and I wanted to keep the ability to use commands entirely from the terminal. Maybe there is a solution to this problem, but I did not find it.
There was a problem hiding this comment.
It seems to work for me. What I did:
- comment out this one line (line 148, where you check for \u0004
- build the shadowjar (
../gradlew shadowJar) - start the daemon (
java -jar build/libs/kotlin-format-1.0.4-SNAPSHOT-all.jar --daemon) - in a separate terminal, get the port number from
cat ../.kotlinformatter/kf.lock - run
(echo "format -"; echo "fun main() { println() }") | nc localhost 64957 - as expected I get the output:
0
fun main() {
println()
}
This matches my understanding that when the input pipe to nc is closed, nc will close the stream, and that will manifest as a reader.readLine() returning null in the daemon.
Do you not get the same behaviour?
There was a problem hiding this comment.
I also get the expected behavior if I cat a file into it:
$ (echo "format -"; cat foo.kt) | nc localhost 65065
0
fun main() {
println()
}
There was a problem hiding this comment.
I changed the loop to:
while (true) {
val line = reader.readLine()
println(line)
if (line == null) break;
// if (line.trim() == "\u0004") break
inputLines.add(line)
}
Then I do (echo "format -"; echo "fun main() { println() }") | nc localhost 45753. This results in the message fun main() { println() } in the console, and nothing happens until I close nc forcibly with ctrl+c. After closing, I see null (for line) and an exception:
Error handling client connection: Broken pipe
java.net.SocketException: Broken pipe
at java.base/sun.nio.ch.SocketDispatcher.write0(Native Method)
at java.base/sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:62)
at java.base/sun.nio.ch.NioSocketImpl.tryWrite(NioSocketImpl.java:394)
at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:410)
at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440)
at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:819)
at java.base/java.net.Socket$SocketOutputStream.implWrite(Socket.java:1231)
at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1218)
at java.base/java.io.OutputStream.write(OutputStream.java:124)
at xyz.block.kotlinformatter.Daemon.write(Daemon.kt:275)
at xyz.block.kotlinformatter.Daemon.start(Daemon.kt:162)
at xyz.block.kotlinformatter.Cli.run(Cli.kt:42)
at com.github.ajalt.clikt.core.CoreCliktCommandKt.parse(CoreCliktCommand.kt:107)
at com.github.ajalt.clikt.core.CoreCliktCommandKt.main(CoreCliktCommand.kt:78)
at com.github.ajalt.clikt.core.CoreCliktCommandKt.main(CoreCliktCommand.kt:90)
at xyz.block.kotlinformatter.CliKt.main(Cli.kt:117)
It seems that nc closes both read and write streams when you press ctrl+c, and does nothing before this. I'm not sure why this behavior might be happening. Maybe there's some difference in the environments?
There was a problem hiding this comment.
weird. what shell/OS are you using? and what version of nc?
There was a problem hiding this comment.
bash, arch linux, netcat (The GNU Netcat) 0.7.1
There was a problem hiding this comment.
I was able to reproduce your issue using an arch linux docker image. I also reproduced it on an ubuntu docker image. Some searching online led me to https://stackoverflow.com/questions/53634911/why-does-sending-d-with-netcat-not-trigger-an-eof-when-reading-from-a-unix-sock
I was able to confirm that when using openbsd-netcat on arch linux or Ubuntu with the -N flag it works as intended. On ubuntu with netcat-traditional you have to use -q 1. On arch linux with gnu netcat I couldn't get it working since the -c option closes the connection right away instead of waiting for the response. I did however manage to get it working with socat instead of nc:
$ (echo "format -"; echo "fun main() { print() }") | socat STDIO TCP4:localhost:34169
0
fun main() {
print()
}
Given the inconsistency of different netcat versions, perhaps you can get by with using socat instead?
Added format command to daemon, which allows formatting either the specified files, or the specified code if the file list is "-" (similar to CLI), starting from a newline and ending with an ASCII EOT character (04); can be used as (echo "format -"; echo <CODE>; echo -ne '\04\n') | nc localhost <PORT>, or replace "echo <CODE>" with "cat" for standard input. Tests included.