rdstdin.nim 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module contains code for reading from `stdin`:idx:. On UNIX the
  10. ## linenoise library is wrapped and set up to provide default key bindings
  11. ## (e.g. you can navigate with the arrow keys). On Windows ``system.readLine``
  12. ## is used. This suffices because Windows' console already provides the
  13. ## wanted functionality.
  14. {.deadCodeElim: on.} # dce option deprecated
  15. when defined(Windows):
  16. proc readLineFromStdin*(prompt: string): TaintedString {.
  17. tags: [ReadIOEffect, WriteIOEffect].} =
  18. ## Reads a line from stdin.
  19. stdout.write(prompt)
  20. result = readLine(stdin)
  21. proc readLineFromStdin*(prompt: string, line: var TaintedString): bool {.
  22. tags: [ReadIOEffect, WriteIOEffect].} =
  23. ## Reads a `line` from stdin. `line` must not be
  24. ## ``nil``! May throw an IO exception.
  25. ## A line of text may be delimited by ``CR``, ``LF`` or
  26. ## ``CRLF``. The newline character(s) are not part of the returned string.
  27. ## Returns ``false`` if the end of the file has been reached, ``true``
  28. ## otherwise. If ``false`` is returned `line` contains no new data.
  29. stdout.write(prompt)
  30. result = readLine(stdin, line)
  31. import winlean
  32. const
  33. VK_SHIFT* = 16
  34. VK_CONTROL* = 17
  35. VK_MENU* = 18
  36. KEY_EVENT* = 1
  37. type
  38. KEY_EVENT_RECORD = object
  39. bKeyDown: WinBool
  40. wRepeatCount: uint16
  41. wVirtualKeyCode: uint16
  42. wVirtualScanCode: uint16
  43. unicodeChar: uint16
  44. dwControlKeyState: uint32
  45. INPUT_RECORD = object
  46. eventType*: int16
  47. reserved*: int16
  48. event*: KEY_EVENT_RECORD
  49. safetyBuffer: array[0..5, DWORD]
  50. proc readConsoleInputW*(hConsoleInput: HANDLE, lpBuffer: var INPUTRECORD,
  51. nLength: uint32,
  52. lpNumberOfEventsRead: var uint32): WINBOOL{.
  53. stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
  54. proc getch(): uint16 =
  55. let hStdin = getStdHandle(STD_INPUT_HANDLE)
  56. var
  57. irInputRecord: INPUT_RECORD
  58. dwEventsRead: uint32
  59. while readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead) != 0:
  60. if irInputRecord.eventType == KEY_EVENT and
  61. irInputRecord.event.wVirtualKeyCode notin {VK_SHIFT, VK_MENU, VK_CONTROL}:
  62. result = irInputRecord.event.unicodeChar
  63. discard readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead)
  64. return result
  65. else:
  66. import linenoise, termios
  67. proc readLineFromStdin*(prompt: string): TaintedString {.
  68. tags: [ReadIOEffect, WriteIOEffect].} =
  69. var buffer = linenoise.readLine(prompt)
  70. if isNil(buffer):
  71. raise newException(IOError, "Linenoise returned nil")
  72. result = TaintedString($buffer)
  73. if result.string.len > 0:
  74. historyAdd(buffer)
  75. linenoise.free(buffer)
  76. proc readLineFromStdin*(prompt: string, line: var TaintedString): bool {.
  77. tags: [ReadIOEffect, WriteIOEffect].} =
  78. var buffer = linenoise.readLine(prompt)
  79. if isNil(buffer):
  80. line.string.setLen(0)
  81. return false
  82. line = TaintedString($buffer)
  83. if line.string.len > 0:
  84. historyAdd(buffer)
  85. linenoise.free(buffer)
  86. result = true