ajalt / clikt

Multiplatform command line interface parsing for Kotlin
https://ajalt.github.io/clikt/
Apache License 2.0
2.54k stars 121 forks source link

Pasting multiple lines to a prompt is broken #471

Closed PaulWoitaschek closed 11 months ago

PaulWoitaschek commented 11 months ago

I'd like to use a terminal.prompt to let users paste text. If it has line breaks, clikt will only take the first linebreak and the terminal will try to execute the following:

To reproduce, run this:

#!/usr/bin/env kotlin
@file:DependsOn("com.github.ajalt.clikt:clikt-jvm:4.2.1")

import com.github.ajalt.clikt.core.CliktCommand
import com.github.ajalt.clikt.core.terminal

class App : CliktCommand() {

  override fun run() {
    val pasted = terminal.prompt("Paste")
    echo("User added\n###\n$pasted\n###")
  }
}

App().main(args)

And paste the following text:

One
Two
Three

It will output:

➜  AdventOfCode git:(main) ✗ kotlin prompt_example.main.kts
Paste: One
Two
ThreeUser added
###
One
###
➜  AdventOfCode git:(main) ✗ Two
zsh: command not found: Two
➜  AdventOfCode git:(main) ✗ Three
PaulWoitaschek commented 11 months ago

Thinking of this, imagine what happens if you paste code into a promt 🙈

# rm -rf *
# rm -rf /
ajalt commented 11 months ago

Mordant uses kotlin's readln function to get a line of input. I can see why it might be surprising, but this isn't a bug in mordant; that's just how shells work.

Pasting something in adds it to stdin, and if you didn't stop reading after encountering a line break, you wouldn't be able to know if there's any more input or not.

You could consider reading the clipboard directly from code, which would avoid that limitation.