Let's summarize things: * **UTF-16** works for input in Windows console, **UTF-8** does not. * We must use a **" W"** function in order to get correct input from the Windows console. This function uses **UTF-16** and does not actually depend on **SetConsoleCP**. * **SetConsoleCP(65001)** actually breaks input for **" A"** functions. In the following link it is described very well why using **SetConsoleCP(65001)** is a bad idea:
[https://stackoverflow.com/questions/14109024/how-to-make-unicode-charset-in-cmd-exe-by-default](https://stackoverflow.com/questions/14109024/how-to-make-unicode-charset-in-cmd-exe-by-default) * On the other hand **SetConsoleOutputCP(65001)** is necessary for correct output of **UTF-8** strings. * **System** module uses binary mode for **stdin** on Windows. This is not necessary; in fact it is bad, but it is easily overridden. Bellow I present a piece of code similar to yours, but which does not utilize the Windows API. I hope you will find it interesting: #console.nim when defined(windows): import system/widestrs proc setMode(fd: int, mode: int): int {.importc: "_setmode", header: "io.h".} proc fgetws(str: WideCString, numChars: int, stream: File): bool {.importc, header: "stdio.h".} discard setMode(getFileHandle(stdin), 0x00020000) #_O_U16TEXT proc consoleReadLine(line: var string): bool = let buffer = newWideCString("", 256) result = fgetws(buffer, 256, stdin) if buffer[buffer.len - 1].int16 == 10: #discard '\n' buffer[buffer.len - 1] = Utf16Char(0) line = $buffer proc consoleReadLine(): string = discard consoleReadLine(result) else: proc consoleReadLine(line: var string): bool = result = stdin.readLine(line) proc consoleReadLine(): string = result = stdin.readLine() Run **setMode(getFileHandle(stdin), 0x00020000)** does the overriding necessary for **fgetws** to work. Now the test code: import console let s = consoleReadLine() echo s.len, ' ', s Run
