Fixed terminal module so that it doesn't raise an EOS exception when stdout is redirected.
This commit is contained in:
parent
317675d5e5
commit
9540a93d95
2 changed files with 334 additions and 334 deletions
|
|
@ -1,312 +1,310 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2012 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
## This module contains a few procedures to control the *terminal*
|
## This module contains a few procedures to control the *terminal*
|
||||||
## (also called *console*). On UNIX, the implementation simply uses ANSI escape
|
## (also called *console*). On UNIX, the implementation simply uses ANSI escape
|
||||||
## sequences and does not depend on any other module, on Windows it uses the
|
## sequences and does not depend on any other module, on Windows it uses the
|
||||||
## Windows API.
|
## Windows API.
|
||||||
## Changing the style is permanent even after program termination! Use the
|
## Changing the style is permanent even after program termination! Use the
|
||||||
## code ``system.addQuitProc(resetAttributes)`` to restore the defaults.
|
## code ``system.addQuitProc(resetAttributes)`` to restore the defaults.
|
||||||
|
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
import windows, os
|
import windows, os
|
||||||
|
|
||||||
var
|
var
|
||||||
conHandle: THandle
|
conHandle: THandle
|
||||||
# = createFile("CONOUT$", GENERIC_WRITE, 0, nil, OPEN_ALWAYS, 0, 0)
|
# = createFile("CONOUT$", GENERIC_WRITE, 0, nil, OPEN_ALWAYS, 0, 0)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var hTemp = GetStdHandle(STD_OUTPUT_HANDLE)
|
var hTemp = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||||
if DuplicateHandle(GetCurrentProcess(), hTemp, GetCurrentProcess(),
|
if DuplicateHandle(GetCurrentProcess(), hTemp, GetCurrentProcess(),
|
||||||
addr(conHandle), 0, 1, DUPLICATE_SAME_ACCESS) == 0:
|
addr(conHandle), 0, 1, DUPLICATE_SAME_ACCESS) == 0:
|
||||||
OSError()
|
OSError()
|
||||||
|
|
||||||
proc getCursorPos(): tuple [x,y: int] =
|
proc getCursorPos(): tuple [x,y: int] =
|
||||||
var c: TCONSOLE_SCREEN_BUFFER_INFO
|
var c: TCONSOLE_SCREEN_BUFFER_INFO
|
||||||
if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: OSError()
|
if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: OSError()
|
||||||
return (int(c.dwCursorPosition.x), int(c.dwCursorPosition.y))
|
return (int(c.dwCursorPosition.x), int(c.dwCursorPosition.y))
|
||||||
|
|
||||||
proc getAttributes(): int16 =
|
proc getAttributes(): int16 =
|
||||||
var c: TCONSOLE_SCREEN_BUFFER_INFO
|
var c: TCONSOLE_SCREEN_BUFFER_INFO
|
||||||
# workaround Windows bugs: try several times
|
# workaround Windows bugs: try several times
|
||||||
if GetConsoleScreenBufferInfo(conHandle, addr(c)) != 0:
|
if GetConsoleScreenBufferInfo(conHandle, addr(c)) != 0:
|
||||||
return c.wAttributes
|
return c.wAttributes
|
||||||
else:
|
return 0x70'i16 # ERROR: return white background, black text
|
||||||
OSError()
|
|
||||||
return 0x70'i16 # ERROR: return white background, black text
|
var
|
||||||
|
oldAttr = getAttributes()
|
||||||
var
|
|
||||||
oldAttr = getAttributes()
|
proc setCursorPos*(x, y: int) =
|
||||||
|
## sets the terminal's cursor to the (x,y) position. (0,0) is the
|
||||||
proc setCursorPos*(x, y: int) =
|
## upper left of the screen.
|
||||||
## sets the terminal's cursor to the (x,y) position. (0,0) is the
|
when defined(windows):
|
||||||
## upper left of the screen.
|
var c: TCoord
|
||||||
when defined(windows):
|
c.x = int16(x)
|
||||||
var c: TCoord
|
c.y = int16(y)
|
||||||
c.x = int16(x)
|
if SetConsoleCursorPosition(conHandle, c) == 0: OSError()
|
||||||
c.y = int16(y)
|
else:
|
||||||
if SetConsoleCursorPosition(conHandle, c) == 0: OSError()
|
stdout.write("\e[" & $y & ';' & $x & 'f')
|
||||||
else:
|
|
||||||
stdout.write("\e[" & $y & ';' & $x & 'f')
|
proc setCursorXPos*(x: int) =
|
||||||
|
## sets the terminal's cursor to the x position. The y position is
|
||||||
proc setCursorXPos*(x: int) =
|
## not changed.
|
||||||
## sets the terminal's cursor to the x position. The y position is
|
when defined(windows):
|
||||||
## not changed.
|
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||||
when defined(windows):
|
var hStdout = conHandle
|
||||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
||||||
var hStdout = conHandle
|
var origin = scrbuf.dwCursorPosition
|
||||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
origin.x = int16(x)
|
||||||
var origin = scrbuf.dwCursorPosition
|
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError()
|
||||||
origin.x = int16(x)
|
else:
|
||||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError()
|
stdout.write("\e[" & $x & 'G')
|
||||||
else:
|
|
||||||
stdout.write("\e[" & $x & 'G')
|
when defined(windows):
|
||||||
|
proc setCursorYPos*(y: int) =
|
||||||
when defined(windows):
|
## sets the terminal's cursor to the y position. The x position is
|
||||||
proc setCursorYPos*(y: int) =
|
## not changed. **Warning**: This is not supported on UNIX!
|
||||||
## sets the terminal's cursor to the y position. The x position is
|
when defined(windows):
|
||||||
## not changed. **Warning**: This is not supported on UNIX!
|
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||||
when defined(windows):
|
var hStdout = conHandle
|
||||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
||||||
var hStdout = conHandle
|
var origin = scrbuf.dwCursorPosition
|
||||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
origin.y = int16(y)
|
||||||
var origin = scrbuf.dwCursorPosition
|
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError()
|
||||||
origin.y = int16(y)
|
else:
|
||||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError()
|
nil
|
||||||
else:
|
|
||||||
nil
|
proc CursorUp*(count=1) =
|
||||||
|
## Moves the cursor up by `count` rows.
|
||||||
proc CursorUp*(count=1) =
|
when defined(windows):
|
||||||
## Moves the cursor up by `count` rows.
|
var p = getCursorPos()
|
||||||
when defined(windows):
|
dec(p.y, count)
|
||||||
var p = getCursorPos()
|
setCursorPos(p.x, p.y)
|
||||||
dec(p.y, count)
|
else:
|
||||||
setCursorPos(p.x, p.y)
|
stdout.write("\e[" & $count & 'A')
|
||||||
else:
|
|
||||||
stdout.write("\e[" & $count & 'A')
|
proc CursorDown*(count=1) =
|
||||||
|
## Moves the cursor down by `count` rows.
|
||||||
proc CursorDown*(count=1) =
|
when defined(windows):
|
||||||
## Moves the cursor down by `count` rows.
|
var p = getCursorPos()
|
||||||
when defined(windows):
|
inc(p.y, count)
|
||||||
var p = getCursorPos()
|
setCursorPos(p.x, p.y)
|
||||||
inc(p.y, count)
|
else:
|
||||||
setCursorPos(p.x, p.y)
|
stdout.write("\e[" & $count & 'B')
|
||||||
else:
|
|
||||||
stdout.write("\e[" & $count & 'B')
|
proc CursorForward*(count=1) =
|
||||||
|
## Moves the cursor forward by `count` columns.
|
||||||
proc CursorForward*(count=1) =
|
when defined(windows):
|
||||||
## Moves the cursor forward by `count` columns.
|
var p = getCursorPos()
|
||||||
when defined(windows):
|
inc(p.x, count)
|
||||||
var p = getCursorPos()
|
setCursorPos(p.x, p.y)
|
||||||
inc(p.x, count)
|
else:
|
||||||
setCursorPos(p.x, p.y)
|
stdout.write("\e[" & $count & 'C')
|
||||||
else:
|
|
||||||
stdout.write("\e[" & $count & 'C')
|
proc CursorBackward*(count=1) =
|
||||||
|
## Moves the cursor backward by `count` columns.
|
||||||
proc CursorBackward*(count=1) =
|
when defined(windows):
|
||||||
## Moves the cursor backward by `count` columns.
|
var p = getCursorPos()
|
||||||
when defined(windows):
|
dec(p.x, count)
|
||||||
var p = getCursorPos()
|
setCursorPos(p.x, p.y)
|
||||||
dec(p.x, count)
|
else:
|
||||||
setCursorPos(p.x, p.y)
|
stdout.write("\e[" & $count & 'D')
|
||||||
else:
|
|
||||||
stdout.write("\e[" & $count & 'D')
|
when true:
|
||||||
|
nil
|
||||||
when true:
|
else:
|
||||||
nil
|
proc EraseLineEnd* =
|
||||||
else:
|
## Erases from the current cursor position to the end of the current line.
|
||||||
proc EraseLineEnd* =
|
when defined(windows):
|
||||||
## Erases from the current cursor position to the end of the current line.
|
nil
|
||||||
when defined(windows):
|
else:
|
||||||
nil
|
stdout.write("\e[K")
|
||||||
else:
|
|
||||||
stdout.write("\e[K")
|
proc EraseLineStart* =
|
||||||
|
## Erases from the current cursor position to the start of the current line.
|
||||||
proc EraseLineStart* =
|
when defined(windows):
|
||||||
## Erases from the current cursor position to the start of the current line.
|
nil
|
||||||
when defined(windows):
|
else:
|
||||||
nil
|
stdout.write("\e[1K")
|
||||||
else:
|
|
||||||
stdout.write("\e[1K")
|
proc EraseDown* =
|
||||||
|
## Erases the screen from the current line down to the bottom of the screen.
|
||||||
proc EraseDown* =
|
when defined(windows):
|
||||||
## Erases the screen from the current line down to the bottom of the screen.
|
nil
|
||||||
when defined(windows):
|
else:
|
||||||
nil
|
stdout.write("\e[J")
|
||||||
else:
|
|
||||||
stdout.write("\e[J")
|
proc EraseUp* =
|
||||||
|
## Erases the screen from the current line up to the top of the screen.
|
||||||
proc EraseUp* =
|
when defined(windows):
|
||||||
## Erases the screen from the current line up to the top of the screen.
|
nil
|
||||||
when defined(windows):
|
else:
|
||||||
nil
|
stdout.write("\e[1J")
|
||||||
else:
|
|
||||||
stdout.write("\e[1J")
|
proc EraseLine* =
|
||||||
|
## Erases the entire current line.
|
||||||
proc EraseLine* =
|
when defined(windows):
|
||||||
## Erases the entire current line.
|
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||||
when defined(windows):
|
var numwrote: DWORD
|
||||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
var hStdout = conHandle
|
||||||
var numwrote: DWORD
|
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
||||||
var hStdout = conHandle
|
var origin = scrbuf.dwCursorPosition
|
||||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
origin.x = 0'i16
|
||||||
var origin = scrbuf.dwCursorPosition
|
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError()
|
||||||
origin.x = 0'i16
|
var ht = scrbuf.dwSize.Y - origin.Y
|
||||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError()
|
var wt = scrbuf.dwSize.X - origin.X
|
||||||
var ht = scrbuf.dwSize.Y - origin.Y
|
if FillConsoleOutputCharacter(hStdout,' ', ht*wt,
|
||||||
var wt = scrbuf.dwSize.X - origin.X
|
origin, addr(numwrote)) == 0:
|
||||||
if FillConsoleOutputCharacter(hStdout,' ', ht*wt,
|
OSError()
|
||||||
origin, addr(numwrote)) == 0:
|
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, ht * wt,
|
||||||
OSError()
|
scrbuf.dwCursorPosition, addr(numwrote)) == 0:
|
||||||
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, ht * wt,
|
OSError()
|
||||||
scrbuf.dwCursorPosition, addr(numwrote)) == 0:
|
else:
|
||||||
OSError()
|
stdout.write("\e[2K")
|
||||||
else:
|
setCursorXPos(0)
|
||||||
stdout.write("\e[2K")
|
|
||||||
setCursorXPos(0)
|
proc EraseScreen* =
|
||||||
|
## Erases the screen with the background colour and moves the cursor to home.
|
||||||
proc EraseScreen* =
|
when defined(windows):
|
||||||
## Erases the screen with the background colour and moves the cursor to home.
|
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||||
when defined(windows):
|
var numwrote: DWORD
|
||||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
var origin: TCoord # is inititalized to 0, 0
|
||||||
var numwrote: DWORD
|
var hStdout = conHandle
|
||||||
var origin: TCoord # is inititalized to 0, 0
|
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
||||||
var hStdout = conHandle
|
if FillConsoleOutputCharacter(hStdout, ' ', scrbuf.dwSize.X*scrbuf.dwSize.Y,
|
||||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
origin, addr(numwrote)) == 0:
|
||||||
if FillConsoleOutputCharacter(hStdout, ' ', scrbuf.dwSize.X*scrbuf.dwSize.Y,
|
OSError()
|
||||||
origin, addr(numwrote)) == 0:
|
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes,
|
||||||
OSError()
|
scrbuf.dwSize.X * scrbuf.dwSize.Y,
|
||||||
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes,
|
origin, addr(numwrote)) == 0:
|
||||||
scrbuf.dwSize.X * scrbuf.dwSize.Y,
|
OSError()
|
||||||
origin, addr(numwrote)) == 0:
|
setCursorXPos(0)
|
||||||
OSError()
|
else:
|
||||||
setCursorXPos(0)
|
stdout.write("\e[2J")
|
||||||
else:
|
|
||||||
stdout.write("\e[2J")
|
proc ResetAttributes* {.noconv.} =
|
||||||
|
## resets all attributes; it is advisable to register this as a quit proc
|
||||||
proc ResetAttributes* {.noconv.} =
|
## with ``system.addQuitProc(resetAttributes)``.
|
||||||
## resets all attributes; it is advisable to register this as a quit proc
|
when defined(windows):
|
||||||
## with ``system.addQuitProc(resetAttributes)``.
|
discard SetConsoleTextAttribute(conHandle, oldAttr)
|
||||||
when defined(windows):
|
else:
|
||||||
discard SetConsoleTextAttribute(conHandle, oldAttr)
|
stdout.write("\e[0m")
|
||||||
else:
|
|
||||||
stdout.write("\e[0m")
|
type
|
||||||
|
TStyle* = enum ## different styles for text output
|
||||||
type
|
styleBright = 1, ## bright text
|
||||||
TStyle* = enum ## different styles for text output
|
styleDim, ## dim text
|
||||||
styleBright = 1, ## bright text
|
styleUnknown, ## unknown
|
||||||
styleDim, ## dim text
|
styleUnderscore = 4, ## underscored text
|
||||||
styleUnknown, ## unknown
|
styleBlink, ## blinking/bold text
|
||||||
styleUnderscore = 4, ## underscored text
|
styleReverse = 7, ## unknown
|
||||||
styleBlink, ## blinking/bold text
|
styleHidden ## hidden text
|
||||||
styleReverse = 7, ## unknown
|
|
||||||
styleHidden ## hidden text
|
when not defined(windows):
|
||||||
|
var
|
||||||
when not defined(windows):
|
# XXX: These better be thread-local
|
||||||
var
|
gFG = 0
|
||||||
# XXX: These better be thread-local
|
gBG = 0
|
||||||
gFG = 0
|
|
||||||
gBG = 0
|
proc setStyle*(style: set[TStyle]) =
|
||||||
|
## sets the terminal style
|
||||||
proc setStyle*(style: set[TStyle]) =
|
when defined(windows):
|
||||||
## sets the terminal style
|
var a = 0'i16
|
||||||
when defined(windows):
|
if styleBright in style: a = a or int16(FOREGROUND_INTENSITY)
|
||||||
var a = 0'i16
|
if styleBlink in style: a = a or int16(BACKGROUND_INTENSITY)
|
||||||
if styleBright in style: a = a or int16(FOREGROUND_INTENSITY)
|
if styleReverse in style: a = a or 0x4000'i16 # COMMON_LVB_REVERSE_VIDEO
|
||||||
if styleBlink in style: a = a or int16(BACKGROUND_INTENSITY)
|
if styleUnderscore in style: a = a or 0x8000'i16 # COMMON_LVB_UNDERSCORE
|
||||||
if styleReverse in style: a = a or 0x4000'i16 # COMMON_LVB_REVERSE_VIDEO
|
discard SetConsoleTextAttribute(conHandle, a)
|
||||||
if styleUnderscore in style: a = a or 0x8000'i16 # COMMON_LVB_UNDERSCORE
|
else:
|
||||||
discard SetConsoleTextAttribute(conHandle, a)
|
for s in items(style):
|
||||||
else:
|
stdout.write("\e[" & $ord(s) & 'm')
|
||||||
for s in items(style):
|
|
||||||
stdout.write("\e[" & $ord(s) & 'm')
|
proc WriteStyled*(txt: string, style: set[TStyle] = {styleBright}) =
|
||||||
|
## writes the text `txt` in a given `style`.
|
||||||
proc WriteStyled*(txt: string, style: set[TStyle] = {styleBright}) =
|
when defined(windows):
|
||||||
## writes the text `txt` in a given `style`.
|
var old = getAttributes()
|
||||||
when defined(windows):
|
setStyle(style)
|
||||||
var old = getAttributes()
|
stdout.write(txt)
|
||||||
setStyle(style)
|
discard SetConsoleTextAttribute(conHandle, old)
|
||||||
stdout.write(txt)
|
else:
|
||||||
discard SetConsoleTextAttribute(conHandle, old)
|
setStyle(style)
|
||||||
else:
|
stdout.write(txt)
|
||||||
setStyle(style)
|
resetAttributes()
|
||||||
stdout.write(txt)
|
if gFG != 0:
|
||||||
resetAttributes()
|
stdout.write("\e[" & $ord(gFG) & 'm')
|
||||||
if gFG != 0:
|
if gBG != 0:
|
||||||
stdout.write("\e[" & $ord(gFG) & 'm')
|
stdout.write("\e[" & $ord(gBG) & 'm')
|
||||||
if gBG != 0:
|
|
||||||
stdout.write("\e[" & $ord(gBG) & 'm')
|
type
|
||||||
|
TForegroundColor* = enum ## terminal's foreground colors
|
||||||
type
|
fgBlack = 30, ## black
|
||||||
TForegroundColor* = enum ## terminal's foreground colors
|
fgRed, ## red
|
||||||
fgBlack = 30, ## black
|
fgGreen, ## green
|
||||||
fgRed, ## red
|
fgYellow, ## yellow
|
||||||
fgGreen, ## green
|
fgBlue, ## blue
|
||||||
fgYellow, ## yellow
|
fgMagenta, ## magenta
|
||||||
fgBlue, ## blue
|
fgCyan, ## cyan
|
||||||
fgMagenta, ## magenta
|
fgWhite ## white
|
||||||
fgCyan, ## cyan
|
|
||||||
fgWhite ## white
|
TBackgroundColor* = enum ## terminal's background colors
|
||||||
|
bgBlack = 40, ## black
|
||||||
TBackgroundColor* = enum ## terminal's background colors
|
bgRed, ## red
|
||||||
bgBlack = 40, ## black
|
bgGreen, ## green
|
||||||
bgRed, ## red
|
bgYellow, ## yellow
|
||||||
bgGreen, ## green
|
bgBlue, ## blue
|
||||||
bgYellow, ## yellow
|
bgMagenta, ## magenta
|
||||||
bgBlue, ## blue
|
bgCyan, ## cyan
|
||||||
bgMagenta, ## magenta
|
bgWhite ## white
|
||||||
bgCyan, ## cyan
|
|
||||||
bgWhite ## white
|
proc setForegroundColor*(fg: TForegroundColor, bright=false) =
|
||||||
|
## sets the terminal's foreground color
|
||||||
proc setForegroundColor*(fg: TForegroundColor, bright=false) =
|
when defined(windows):
|
||||||
## sets the terminal's foreground color
|
var old = getAttributes() and not 0x0007
|
||||||
when defined(windows):
|
if bright:
|
||||||
var old = getAttributes() and not 0x0007
|
old = old or FOREGROUND_INTENSITY
|
||||||
if bright:
|
const lookup: array [TForegroundColor, int] = [
|
||||||
old = old or FOREGROUND_INTENSITY
|
0,
|
||||||
const lookup: array [TForegroundColor, int] = [
|
(FOREGROUND_RED),
|
||||||
0,
|
(FOREGROUND_GREEN),
|
||||||
(FOREGROUND_RED),
|
(FOREGROUND_RED or FOREGROUND_GREEN),
|
||||||
(FOREGROUND_GREEN),
|
(FOREGROUND_BLUE),
|
||||||
(FOREGROUND_RED or FOREGROUND_GREEN),
|
(FOREGROUND_RED or FOREGROUND_BLUE),
|
||||||
(FOREGROUND_BLUE),
|
(FOREGROUND_BLUE or FOREGROUND_GREEN),
|
||||||
(FOREGROUND_RED or FOREGROUND_BLUE),
|
(FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED)]
|
||||||
(FOREGROUND_BLUE or FOREGROUND_GREEN),
|
discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[fg]))
|
||||||
(FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED)]
|
else:
|
||||||
discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[fg]))
|
gFG = ord(fg)
|
||||||
else:
|
if bright: inc(gFG, 60)
|
||||||
gFG = ord(fg)
|
stdout.write("\e[" & $gFG & 'm')
|
||||||
if bright: inc(gFG, 60)
|
|
||||||
stdout.write("\e[" & $gFG & 'm')
|
proc setBackgroundColor*(bg: TBackgroundColor, bright=false) =
|
||||||
|
## sets the terminal's background color
|
||||||
proc setBackgroundColor*(bg: TBackgroundColor, bright=false) =
|
when defined(windows):
|
||||||
## sets the terminal's background color
|
var old = getAttributes() and not 0x0070
|
||||||
when defined(windows):
|
if bright:
|
||||||
var old = getAttributes() and not 0x0070
|
old = old or BACKGROUND_INTENSITY
|
||||||
if bright:
|
const lookup: array [TBackgroundColor, int] = [
|
||||||
old = old or BACKGROUND_INTENSITY
|
0,
|
||||||
const lookup: array [TBackgroundColor, int] = [
|
(BACKGROUND_RED),
|
||||||
0,
|
(BACKGROUND_GREEN),
|
||||||
(BACKGROUND_RED),
|
(BACKGROUND_RED or BACKGROUND_GREEN),
|
||||||
(BACKGROUND_GREEN),
|
(BACKGROUND_BLUE),
|
||||||
(BACKGROUND_RED or BACKGROUND_GREEN),
|
(BACKGROUND_RED or BACKGROUND_BLUE),
|
||||||
(BACKGROUND_BLUE),
|
(BACKGROUND_BLUE or BACKGROUND_GREEN),
|
||||||
(BACKGROUND_RED or BACKGROUND_BLUE),
|
(BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED)]
|
||||||
(BACKGROUND_BLUE or BACKGROUND_GREEN),
|
discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[bg]))
|
||||||
(BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED)]
|
else:
|
||||||
discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[bg]))
|
gBG = ord(bg)
|
||||||
else:
|
if bright: inc(gBG, 60)
|
||||||
gBG = ord(bg)
|
stdout.write("\e[" & $gBG & 'm')
|
||||||
if bright: inc(gBG, 60)
|
|
||||||
stdout.write("\e[" & $gBG & 'm')
|
|
||||||
|
|
||||||
proc isatty*(f: TFile): bool =
|
proc isatty*(f: TFile): bool =
|
||||||
## returns true if `f` is associated with a terminal device.
|
## returns true if `f` is associated with a terminal device.
|
||||||
|
|
@ -318,33 +316,33 @@ proc isatty*(f: TFile): bool =
|
||||||
importc: "_isatty", header: "<io.h>".}
|
importc: "_isatty", header: "<io.h>".}
|
||||||
|
|
||||||
result = isatty(fileHandle(f)) != 0'i32
|
result = isatty(fileHandle(f)) != 0'i32
|
||||||
|
|
||||||
proc styledEchoProcessArg(s: string) = write stdout, s
|
proc styledEchoProcessArg(s: string) = write stdout, s
|
||||||
proc styledEchoProcessArg(style: TStyle) = setStyle({style})
|
proc styledEchoProcessArg(style: TStyle) = setStyle({style})
|
||||||
proc styledEchoProcessArg(style: set[TStyle]) = setStyle style
|
proc styledEchoProcessArg(style: set[TStyle]) = setStyle style
|
||||||
proc styledEchoProcessArg(color: TForegroundColor) = setForeGroundColor color
|
proc styledEchoProcessArg(color: TForegroundColor) = setForeGroundColor color
|
||||||
proc styledEchoProcessArg(color: TBackgroundColor) = setBackGroundColor color
|
proc styledEchoProcessArg(color: TBackgroundColor) = setBackGroundColor color
|
||||||
|
|
||||||
macro styledEcho*(m: varargs[expr]): stmt =
|
macro styledEcho*(m: varargs[expr]): stmt =
|
||||||
## to be documented.
|
## to be documented.
|
||||||
let m = callsite()
|
let m = callsite()
|
||||||
result = newNimNode(nnkStmtList)
|
result = newNimNode(nnkStmtList)
|
||||||
|
|
||||||
for i in countup(1, m.len - 1):
|
for i in countup(1, m.len - 1):
|
||||||
result.add(newCall(bindSym"styledEchoProcessArg", m[i]))
|
result.add(newCall(bindSym"styledEchoProcessArg", m[i]))
|
||||||
|
|
||||||
result.add(newCall(bindSym"write", bindSym"stdout", newStrLitNode("\n")))
|
result.add(newCall(bindSym"write", bindSym"stdout", newStrLitNode("\n")))
|
||||||
result.add(newCall(bindSym"resetAttributes"))
|
result.add(newCall(bindSym"resetAttributes"))
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
system.addQuitProc(resetAttributes)
|
system.addQuitProc(resetAttributes)
|
||||||
write(stdout, "never mind")
|
write(stdout, "never mind")
|
||||||
eraseLine()
|
eraseLine()
|
||||||
#setCursorPos(2, 2)
|
#setCursorPos(2, 2)
|
||||||
writeStyled("styled text ", {styleBright, styleBlink, styleUnderscore})
|
writeStyled("styled text ", {styleBright, styleBlink, styleUnderscore})
|
||||||
setBackGroundColor(bgCyan, true)
|
setBackGroundColor(bgCyan, true)
|
||||||
setForeGroundColor(fgBlue)
|
setForeGroundColor(fgBlue)
|
||||||
writeln(stdout, "ordinary text")
|
writeln(stdout, "ordinary text")
|
||||||
|
|
||||||
styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore})
|
styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore})
|
||||||
|
|
||||||
|
|
@ -32,6 +32,7 @@ Options:
|
||||||
--ignoreCase, -i be case insensitive
|
--ignoreCase, -i be case insensitive
|
||||||
--ignoreStyle, -y be style insensitive
|
--ignoreStyle, -y be style insensitive
|
||||||
--ext:EX1|EX2|... only search the files with the given extension(s)
|
--ext:EX1|EX2|... only search the files with the given extension(s)
|
||||||
|
--nocolor output will be given without any colours.
|
||||||
--verbose be verbose: list every processed file
|
--verbose be verbose: list every processed file
|
||||||
--help, -h shows this help
|
--help, -h shows this help
|
||||||
--version, -v shows the version
|
--version, -v shows the version
|
||||||
|
|
@ -291,6 +292,7 @@ for kind, key, val in getopt():
|
||||||
of "ignorecase", "i": incl(options, optIgnoreCase)
|
of "ignorecase", "i": incl(options, optIgnoreCase)
|
||||||
of "ignorestyle", "y": incl(options, optIgnoreStyle)
|
of "ignorestyle", "y": incl(options, optIgnoreStyle)
|
||||||
of "ext": extensions = val.split('|')
|
of "ext": extensions = val.split('|')
|
||||||
|
of "nocolor": useWriteStyled = false
|
||||||
of "verbose": incl(options, optVerbose)
|
of "verbose": incl(options, optVerbose)
|
||||||
of "help", "h": writeHelp()
|
of "help", "h": writeHelp()
|
||||||
of "version", "v": writeVersion()
|
of "version", "v": writeVersion()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue