amber-lang / amber

💎 Amber the programming language compiled to Bash
https://amber-lang.com
GNU General Public License v3.0
3.86k stars 83 forks source link

feat: add input_hidden function #492

Closed karpfediem closed 5 days ago

karpfediem commented 1 week ago

Adds input_hidden function to std/env

Prompts for input, but hides the user input (useful for password prompts)

karpfediem commented 1 week ago

I copied the existing test of the input function.

I found a weird issue when running the test. It prints the following messages into stderr when calling stty


[carp@aquarium:~/code/clones/amber/src/tests/stdlib]$ ./input_hidden.sh 
stty: 'standard input': Inappropriate ioctl for device
Please enter your name:stty: 'standard input': Inappropriate ioctl for device

Hello, Amber

[carp@aquarium:~/code/clones/amber/src/tests/stdlib]$ ./input_hidden.sh 2>err.txt
Please enter your name:
Hello, Amber

[carp@aquarium:~/code/clones/amber/src/tests/stdlib]$ cat err.txt 
stty: 'standard input': Inappropriate ioctl for device
stty: 'standard input': Inappropriate ioctl for device

However it works fine even in that case.

I need some help to figure out if thats okay, or should be surpressed somehow or anything.

Mte90 commented 1 week ago

Let's see what happens in the CI

karpfediem commented 1 week ago

If i run the test now

main {
    unsafe $echo "Amber" >> /tmp/test_input$
    unsafe $exec 0< /tmp/test_input$
    let name = input_hidden("Please enter your name:")
    echo "Hello, " + name
    unsafe $rm /tmp/test_input$
}

outputs just Hello, Amber

Running this

 main {
     let name = input_hidden("Please enter your name:")
     echo "Hello, " + name
 }

turns it interactive again and outputs Please enter your name:Hello, Amber

Which is missing the linebreak. I'll look into this again in a bit.

karpfediem commented 1 week ago

So the issue with read -p is that the prompt gets redirected to fd 2 and that it omits the newline.

I'm not sure if

I would like to

EDIT: maybe i've just got the wrong idea and we don't want to send a newline at all, just leave it up for the end user...

hdwalters commented 1 week ago

So the issue with read -p is that the prompt gets redirected to fd 2 and that it omits the newline...

Assuming you're planning to modify input as well, I copied the functions to this test script:

$ cat prompt.ab
#!/usr/bin/env amber

pub fun input(prompt: Text): Text {
    unsafe $read -p "\${nameof prompt}"$
    return "\$REPLY"
}

pub fun input_hidden(prompt: Text): Text {
    unsafe $read -s -p "\${nameof prompt}"$
    return "\$REPLY"
}

echo "[before input]"
let password = input("Password: ")
echo "[after input]"
echo password

echo "[before input_hidden]"
let password = input_hidden("Password: ")
echo "[after input_hidden]"
echo password

The input function seems to work fine, but input_hidden does not:

$ ./prompt.ab
[before input]
Password: SHOWN
[after input]
SHOWN
[before input_hidden]
Password: [after input_hidden]
HIDDEN

Why can't you just add an artificial newline?

pub fun input_hidden(prompt: Text): Text {
    unsafe $read -s -p "\${nameof prompt}"$
    echo ""
    return "\$REPLY"
}

Seems to fix the problem:

$ ./prompt.ab
[before input]
Password: SHOWN
[after input]
SHOWN
[before input_hidden]
Password: 
[after input_hidden]
HIDDEN
karpfediem commented 1 week ago

Thanks :)

I'm fine with that solution, as long as both input functions are handled equally. I wouldn't want to decide on my own if we should put a forced newline or not though.

So waiting for other opinions on that

b1ek commented 5 days ago

@Ph0enixKM can we merge this?