mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-01 10:52:14 +00:00
don't use conio.h on windows (#2137)
This commit is contained in:
@@ -8,16 +8,16 @@
|
||||
#
|
||||
|
||||
## This module contains code for reading from `stdin`:idx:. On UNIX the GNU
|
||||
## readline library is wrapped and set up to provide default key bindings
|
||||
## readline library is wrapped and set up to provide default key bindings
|
||||
## (e.g. you can navigate with the arrow keys). On Windows ``system.readLine``
|
||||
## is used. This suffices because Windows' console already provides the
|
||||
## is used. This suffices because Windows' console already provides the
|
||||
## wanted functionality.
|
||||
|
||||
{.deadCodeElim: on.}
|
||||
|
||||
when defined(Windows):
|
||||
proc readLineFromStdin*(prompt: string): TaintedString {.
|
||||
tags: [ReadIOEffect, WriteIOEffect].} =
|
||||
tags: [ReadIOEffect, WriteIOEffect].} =
|
||||
## Reads a line from stdin.
|
||||
stdout.write(prompt)
|
||||
result = readLine(stdin)
|
||||
@@ -33,27 +33,71 @@ when defined(Windows):
|
||||
stdout.write(prompt)
|
||||
result = readLine(stdin, line)
|
||||
|
||||
import winlean
|
||||
|
||||
const
|
||||
VK_SHIFT* = 16
|
||||
VK_CONTROL* = 17
|
||||
VK_MENU* = 18
|
||||
KEY_EVENT* = 1
|
||||
|
||||
type
|
||||
KEY_EVENT_RECORD = object
|
||||
bKeyDown: WinBool
|
||||
wRepeatCount: uint16
|
||||
wVirtualKeyCode: uint16
|
||||
wVirtualScanCode: uint16
|
||||
unicodeChar: uint16
|
||||
dwControlKeyState: uint32
|
||||
INPUT_RECORD = object
|
||||
eventType*: int16
|
||||
reserved*: int16
|
||||
event*: KEY_EVENT_RECORD
|
||||
safetyBuffer: array[0..5, DWORD]
|
||||
|
||||
proc readConsoleInputW*(hConsoleInput: THANDLE, lpBuffer: var INPUTRECORD,
|
||||
nLength: uint32,
|
||||
lpNumberOfEventsRead: var uint32): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
|
||||
|
||||
proc getch(): uint16 =
|
||||
let hStdin = getStdHandle(STD_INPUT_HANDLE)
|
||||
var
|
||||
irInputRecord: INPUT_RECORD
|
||||
dwEventsRead: uint32
|
||||
|
||||
while readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead) != 0:
|
||||
if irInputRecord.eventType == KEY_EVENT and
|
||||
irInputRecord.event.wVirtualKeyCode notin {VK_SHIFT, VK_MENU, VK_CONTROL}:
|
||||
result = irInputRecord.event.unicodeChar
|
||||
discard readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead)
|
||||
return result
|
||||
|
||||
from unicode import toUTF8, Rune, runeLenAt
|
||||
|
||||
proc readPasswordFromStdin*(prompt: string, password: var TaintedString):
|
||||
bool {.tags: [ReadIOEffect, WriteIOEffect].} =
|
||||
## Reads a `password` from stdin without printing it. `password` must not
|
||||
## be ``nil``! Returns ``false`` if the end of the file has been reached,
|
||||
## ``true`` otherwise.
|
||||
proc getch(): cint {.header: "<conio.h>", importc: "_getch".}
|
||||
|
||||
password.setLen(0)
|
||||
var c: char
|
||||
stdout.write(prompt)
|
||||
while true:
|
||||
c = getch().char
|
||||
case c
|
||||
let c = getch()
|
||||
case c.char
|
||||
of '\r', chr(0xA):
|
||||
break
|
||||
of '\b':
|
||||
password.setLen(password.len - 1)
|
||||
# ensure we delete the whole UTF-8 character:
|
||||
var i = 0
|
||||
var x = 1
|
||||
while i < password.len:
|
||||
x = runeLenAt(password, i)
|
||||
inc i, x
|
||||
password.setLen(password.len - x)
|
||||
else:
|
||||
password.add(c)
|
||||
password.add(toUTF8(c.Rune))
|
||||
stdout.write "\n"
|
||||
# TODO: How to detect EOF on Windows?
|
||||
|
||||
else:
|
||||
import readline, history, termios, unsigned
|
||||
|
||||
@@ -45,7 +45,6 @@ when defined(windows):
|
||||
var
|
||||
oldAttr = getAttributes()
|
||||
|
||||
proc winGetch(): cint {.header: "<conio.h>", importc: "_getch".}
|
||||
else:
|
||||
import termios, unsigned
|
||||
|
||||
@@ -344,7 +343,7 @@ proc isatty*(f: File): bool =
|
||||
else:
|
||||
proc isatty(fildes: FileHandle): cint {.
|
||||
importc: "_isatty", header: "<io.h>".}
|
||||
|
||||
|
||||
result = isatty(getFileHandle(f)) != 0'i32
|
||||
|
||||
proc styledEchoProcessArg(s: string) = write stdout, s
|
||||
@@ -364,12 +363,11 @@ macro styledEcho*(m: varargs[expr]): stmt =
|
||||
result.add(newCall(bindSym"write", bindSym"stdout", newStrLitNode("\n")))
|
||||
result.add(newCall(bindSym"resetAttributes"))
|
||||
|
||||
proc getch*(): char =
|
||||
## Read a single character from the terminal, blocking until it is entered.
|
||||
## The character is not printed to the terminal.
|
||||
when defined(windows):
|
||||
result = winGetch().char
|
||||
else:
|
||||
when not defined(windows):
|
||||
proc getch*(): char =
|
||||
## Read a single character from the terminal, blocking until it is entered.
|
||||
## The character is not printed to the terminal. This is not available for
|
||||
## Windows.
|
||||
let fd = getFileHandle(stdin)
|
||||
var oldMode: Termios
|
||||
discard fd.tcgetattr(addr oldMode)
|
||||
@@ -387,5 +385,5 @@ when isMainModule:
|
||||
setForeGroundColor(fgBlue)
|
||||
writeln(stdout, "ordinary text")
|
||||
|
||||
styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore})
|
||||
|
||||
styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user