diff options
author | Araq <rumpf_a@web.de> | 2016-09-02 01:22:59 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2016-09-02 01:22:59 +0200 |
commit | 7332266c7ee53bf19cf3ac65285dad4cff5daec0 (patch) | |
tree | a1bae1b4534e22c3df8e7372a7748f59c645b4f6 | |
parent | 11f7eb2d9b2ff22053aa6e3d442f43922842d5e6 (diff) | |
parent | e4ddcd836ce723859b71d2d52be85e8eaed7e119 (diff) | |
download | Nim-7332266c7ee53bf19cf3ac65285dad4cff5daec0.tar.gz |
Merge branch 'devel' of https://github.com/c-blake/Nim into c-blake-devel
-rw-r--r-- | lib/posix/termios.nim | 10 | ||||
-rw-r--r-- | lib/pure/terminal.nim | 44 |
2 files changed, 53 insertions, 1 deletions
diff --git a/lib/posix/termios.nim b/lib/posix/termios.nim index c3934c6a9..1fbccba9c 100644 --- a/lib/posix/termios.nim +++ b/lib/posix/termios.nim @@ -259,3 +259,13 @@ proc tcFlow*(fd: cint; action: cint): cint {.importc: "tcflow", # Get process group ID for session leader for controlling terminal FD. proc tcGetSid*(fd: cint): Pid {.importc: "tcgetsid", header: "<termios.h>".} + +# Window size ioctl. Should work on on any Unix that xterm has been ported to. +var TIOCGWINSZ*{.importc, header: "<sys/ioctl.h>".}: culong + +type IOctl_WinSize* {.importc: "struct winsize", header: "<sys/ioctl.h>", + final, pure.} = object + ws_row*, ws_col*, ws_xpixel*, ws_ypixel*: cushort + +proc ioctl*(fd: cint, request: culong, reply: ptr IOctl_WinSize): int {. + importc: "ioctl", header: "<stdio.h>", varargs.} diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 1f34ec07e..d4734c3e3 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -60,6 +60,21 @@ when defined(windows): lpConsoleScreenBufferInfo: ptr CONSOLE_SCREEN_BUFFER_INFO): WINBOOL{.stdcall, dynlib: "kernel32", importc: "GetConsoleScreenBufferInfo".} + proc terminalWidthIoctl*(handles: openArray[Handle]): int = + var csbi: CONSOLE_SCREEN_BUFFER_INFO + for h in handles: + if getConsoleScreenBufferInfo(h, addr csbi) != 0: + return int(csbi.srWindow.Right - csbi.srWindow.Left + 1) + return 0 + + proc terminalWidth*(): int = + var w: int = 0 + w = terminalWidthIoctl([ getStdHandle(STD_INPUT_HANDLE), + getStdHandle(STD_OUTPUT_HANDLE), + getStdHandle(STD_ERROR_HANDLE) ] ) + if w > 0: return w + return 80 + proc setConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD): WINBOOL{. stdcall, dynlib: "kernel32", importc: "SetConsoleCursorPosition".} @@ -123,7 +138,7 @@ when defined(windows): if f == stderr: hStderr else: hStdout else: - import termios + import termios, posix, os, parseutils proc setRaw(fd: FileHandle, time: cint = TCSAFLUSH) = var mode: Termios @@ -137,6 +152,33 @@ else: mode.c_cc[VTIME] = 0.cuchar discard fd.tcsetattr(time, addr mode) + proc terminalWidthIoctl*(fds: openArray[int]): int = + ## Returns terminal width from first fd that supports the ioctl. + + var win: IOctl_WinSize + for fd in fds: + if ioctl(cint(fd), TIOCGWINSZ, addr win) != -1: + return int(win.ws_col) + return 0 + + var L_ctermid{.importc, header: "<stdio.h>".}: cint + proc terminalWidth*(): int = + ## Returns some reasonable terminal width from either standard file + ## descriptors, controlling terminal, environment variables or tradition. + + var w = terminalWidthIoctl([0, 1, 2]) #Try standard file descriptors + if w > 0: return w + var cterm = newString(L_ctermid) #Try controlling tty + var fd = open(ctermid(cstring(cterm)), O_RDONLY) + if fd != -1: + w = terminalWidthIoctl([ int(fd) ]) + discard close(fd) + if w > 0: return w + var s = getEnv("COLUMNS") #Try standard env var + if len(s) > 0 and parseInt(string(s), w) > 0 and w > 0: + return w + return 80 #Finally default to venerable value + proc setCursorPos*(f: File, x, y: int) = ## Sets the terminal's cursor to the (x,y) position. ## (0,0) is the upper left of the screen. |