Search code examples
swiftshellunicodeprintingzsh

swift Cannot print in the terminal


In my terminal(zsh), this code don't print anything

import Foundation

while (true){
    print(".", terminator: "")
    sleep(1)
    print(String(Character(Unicode.Scalar(8))), terminator: "")
}

Solution

  • print does buffering (see this and this), so the things you asked it to print doesn't get printed (stays in the buffer) until the buffer is flushed. (Related) And the buffer gets flushed when, for example, a new line character gets printed, or when your program ends. In your code though, neither of those things happen, and the buffer never gets flushed, so nothing gets printed.

    The C function fflush flushes a given file handle, and you can use that to flush stdout:

    while (true){
        print(".", terminator: "")
        fflush(stdout)
        sleep(1)
        print(String(Character(Unicode.Scalar(8))), terminator: "")
        fflush(stdout)
    }
    

    (FileHandle.standardOutput.synchronize() is supposedly the more Swift way of doing this, but it doesn't seem to work for me)

    Now you should see a dot that is not flashing. This is because you are only waiting 1 second between printing the dot and printing the backspace, but not waiting at all between printing the backspace and printing the dot. You should actually wait twice in one iteration.

    There is also the issue that just printing a backspace is not enough to remove the dot. Printing the backspace just moves the cursor back. You would have to print another whitespace character there to replace the dot, but now the cursor would have moved one space to the right, so when printing the next dot, you would also need to print a backspace.

    while (true){
        sleep(1)
        print(".", terminator: "")
        fflush(stdout)
        sleep(1)
        print("\u{0008} \u{0008}", terminator: "")
        fflush(stdout)
    }
    

    Another way of erasing the dot would be to use VT100 escape codes:

    print("\u{001B}[2K\u{001B}[1D", terminator: "")