elvish
elvish copied to clipboard
Reading user input without echo
I'm looking if elvish support the bash equivalent read -s password
.
Currently I have the following but it echos what is typed to the console
var password = (read-line)
If an equivalent doesn't exist maybe something like read-password
or read-line &echo=$false
?
For what it's worth, here is what I use:
fn prompt {|prompt &tty=/dev/tty| print $prompt >$tty; read-line <$tty }
fn with-stty {|@args cmd~ &tty=/dev/tty|
var orig = (stty -g <$tty)
try { stty $@args <$tty; cmd } finally { stty $orig <$tty }
}
Then I can run, say,
with-stty -echo { prompt 'Enter password: ' } | var pw = (one)
I have absolutely no idea if this will work on windows, though. (And to be honest, I have never used the &tty
option in either of the two functions above.)
I was going to post a solution similar to @hanche's but he beat me to it. Whether this functionality should be builtin depends on how practical it is to implement it in a cross-platform manner.
@hanche's solution has another problem. If you ctrl+c out while in the prompt, the tty is never restored and echo remains off.
@hanche's solution has another problem. If you ctrl+c out while in the prompt, the tty is never restored and echo remains off.
I can't reproduce that on macOS. on macOS the try...finally...
does restore the stty mode. However, after pressing Ctrl-C I still have to press Enter -- which is probably also a bug as you would expect the Ctrl-C to terminate the read-line
command.
I am also on macos. I was incorrect. Ctrl-C does indeed not work.
This is kinda awkward and I didn't realize it until you pointed it out. After Ctrl-C didn't work, I immediately did a Ctrl-D out of reflex... every time I tried this. If you do Ctrl-C followed by Ctrl-D you get an exception where the echo is never restored:
$ ./tmp.elv
Password: Exception: interrupted
Traceback:
/Users/stephenmw/tmp.elv:7:44:
try { stty $@args <$tty; cmd } finally { stty $orig <$tty }
/Users/stephenmw/tmp.elv:10:17:
var password = (with-stty -echo { prompt 'Password: ' })
Code:
#!/usr/bin/env elvish
fn prompt {|prompt &tty=/dev/tty| print $prompt >$tty; read-line <$tty }
fn with-stty {|@args cmd~ &tty=/dev/tty|
var orig = (stty -g <$tty)
try { stty $@args <$tty; cmd } finally { stty $orig <$tty }
}
var password = (with-stty -echo { prompt 'Password: ' })
echo
echo Your password is $password
I am also on macos. I was incorrect. Ctrl-C does indeed not work.
I can't parse that. Your original problem statement was that Ctrl-C does not work so I don't understand the "I was incorrect" statement. Whether I put that code in an Elvish script I run from an interactive prompt, or directly in my interactive Elvish shell, a Ctrl-C does result in the stty mode being restored. However, as I stated previously, the Ctrl-C does not immediately terminate the read-line
command in either case. I have to press Enter or Ctrl-D. Which is a bug (arguably) but not the bug in your first comment that "echo remains off."
I'll also point out that the whole try...finally...
to restore the tty modes doesn't do anything useful since the finally
block isn't run when Ctrl-C is handled. See https://github.com/elves/elvish/issues/954. The reason the tty modes are restored is due to how Elvish currently handles tty modes. See https://github.com/elves/elvish/issues/732. The tty modes are always "restored" before the next prompt is emitted regardless of any changes done by an stty
command.