Method gets with crystal

Hi guys, I have a specific request. How when I query the user input with gets, instead of echoing the input, print asterisk ? I would like basically to mask the user input, but print something instead.

It wouldn’t print asterisks, but would be pretty familiar to a Linux user to just use #noecho.

So I saw this already, but first it’s not exactly the result I would like, I really would like to have the possibility to print asterisk instead.

And the second issue I have is, if the user type straight away something, the echo take a bit to be disabled, is it normal too ?

Here’s my simple attempt:

print "Enter password: "
password = String.build do |str|
  loop do
    char = STDIN.raw &.read_char
    if char == '\r' || char == '\n'
      puts
      break
    end

    str << char
    print "*"
    # STDOUT.flush
  end
end
puts "Password is set as #{password}"

Additionally, I found a shard prompt that covers this use case. :smiling_face_with_sunglasses:

1 Like

Thanks a lot !

Is it normal when I press CTRL+C, I can’t still escape ?
And if I press backspace, I it still print asterisk :x

The following code adds a check to verify if the input characters are printable and handles backspaces.

print "Enter password: "
password = ""

loop do
  char = STDIN.raw &.read_char

  case char
  when '\u0003'
    abort "\nInput terminated with Ctrl+C"
  when '\r', '\n', '\u0004' # handle Ctrl+D as EOF
    puts
    break
  when '\u007F' # handle Backspace
    unless password.empty?
      password = password.rchop
      print "\b \b"
    end
  when .try &.printable?
    password += char.not_nil!
    print "*"
  else
    # next
    print "\r#{" " * (26 + password.size)}\r"
    print "Invalid input! Try again: "
    STDIN.rewind
    password = ""
  end
end

puts "Password is set as #{password}"

It should interrupt when detects Ctrl+C and treats as EOF when detects Ctrl+D from STDIN.

1 Like

Thank you so much Sunrise