Reading STDIN always buffered?

Hi there! I am trying to read data from stdin, and am havig some trouble when there is less than a line of data. Here’s some sample code:

m = IO::Memory.new
STDIN.read_buffering=false
m << STDIN.gets_to_end
pp! m.to_s

If I run it and type “1234<Ctrl+D>” this should print 1234, but doesn’t, it just keeps waiting for more input.

Unless I send Ctrl+D right after a newline, it always keeps waiting for data, so

1234\n<Ctrl+D> works
1234\n5678<Ctrl+D> doesn’t

Any ideas?

Update: This works, which is more confusing to me :smiley:

echo -n "hola" | crystal run stdin.cr
m.to_s # => "hola"

UPDATE
found some code in stack overflow that solves the whole thing (even shows how to do “echo * for passwords” if desired

# Fix for crystal bug
STDIN.blocking = true

# STDIN chars without buffering
STDIN.raw do
  # Dont echo out to the terminal
  STDIN.noecho do
    final_password = ""
    while char = STDIN.read_char
      # If we have a backspace
      if char == '\u{7f}'
        # Move the cursor back 1 char
        if final_password != ""
          STDOUT << "\b \b"
          STDOUT.flush
          final_password = final_password[0...-1]
        end
        next
      elsif char == '\u{3}'
        # Control + C was pressed. Get outta here
        Process.exit 0
      elsif char == '\u{4}'
        # Control + D was pressed. Finished
        break
      elsif char.ascii_control?
        # A Control + [] char was pressed. Not valid for a password
        next
      end

      STDOUT << "*"
      STDOUT.flush
      final_password += char
    end

    puts final_password
  end
end

On unix like sysems ctrl D or ^D triggers end of file as below:

  1. CTRL D is pressed on an empty line
  2. CTRL D is pressed twice on a non-empty line

So in your case, you need to press ^D twice for the shell to trigger end of file signal.

HIH

Indeed that works, but it’s not how other unix tools work like, for example cat ends immediately on the first Ctrl+d

I guess it may be because it’s not just reading stdin but using it as a tty or something.

Anyway, good enough, thanks!

On my machine, I have to hit it twice if it’s not at the beginning of a line.