diff options
-rw-r--r-- | compiler/msgs.nim | 143 |
1 files changed, 90 insertions, 53 deletions
diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 2d7094e63..2edb869d8 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -8,7 +8,7 @@ # import - options, strutils, os, tables, ropes, platform, terminal + options, strutils, os, tables, ropes, platform, terminal, macros type TMsgKind* = enum @@ -605,13 +605,15 @@ proc suggestQuit*() = # this format is understood by many text editors: it is the same that # Borland and Freepascal use const - PosErrorFormat* = "$1($2, $3) Error: " - PosWarningFormat* = "$1($2, $3) Warning: " - PosHintFormat* = "$1($2, $3) Hint: " - PosContextFormat = "$1($2, $3) Info: " - RawError* = "Error: " - RawWarning* = "Warning: " - RawHint* = "Hint: " + PosFormat = "$1($2, $3) " + ErrorTitle = "Error: " + ErrorColor = fgRed + WarningTitle = "Warning: " + WarningColor = fgYellow + HintTitle = "Hint: " + HintColor = fgGreen + InfoTitle = "Info: " + InfoColor = fgCyan proc getInfoContextLen*(): int = return msgContext.len proc setInfoContextLen*(L: int) = setLen(msgContext, L) @@ -686,27 +688,58 @@ proc outWriteln*(s: string) = ## Writes to stdout. Always. if eStdOut in errorOutputs: writeln(stdout, s) -proc msgWriteln*(s: string, color: ForegroundColor = fgWhite, coloredText: string = "") = - ## Writes to stdout. If --stderr option is given, writes to stderr instead. +proc msgWriteln*(s: string) = + ## Writes to stdout. If --stdout option is given, writes to stderr instead. #if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return - var hasColor = optUseColors in gGlobalOptions if not isNil(writelnHook): - writelnHook(coloredText & s) + writelnHook(s) + elif optStdout in gGlobalOptions: + if eStdErr in errorOutputs: writeln(stderr, s) else: - if optStdout in gGlobalOptions: - if eStdErr in errorOutputs: - if hasColor: setForegroundColor(color) - write(stderr, coloredText) - if hasColor: resetAttributes() - writeln(stderr, s) - else: - if eStdOut in errorOutputs: - if hasColor: setForegroundColor(color) - write(stdout, coloredText) - if hasColor: resetAttributes() - writeln(stdout, s) + if eStdOut in errorOutputs: writeln(stdout, s) + +macro callIgnoringStyle(theProc: typed, first: typed, + args: varargs[expr]): stmt = + let typForegroundColor = bindSym"ForegroundColor".getType + let typBackgroundColor = bindSym"BackgroundColor".getType + let typStyle = bindSym"Style".getType + let typTerminalCmd = bindSym"TerminalCmd".getType + result = newCall(theProc) + if first.kind != nnkNilLit: result.add(first) + for arg in children(args[0][1]): + if arg.kind == nnkNilLit: continue + let typ = arg.getType + if typ.kind != nnkEnumTy or + typ != typForegroundColor and + typ != typBackgroundColor and + typ != typStyle and + typ != typTerminalCmd: + result.add(arg) + +macro callStyledEcho(args: varargs[expr]): stmt = + result = newCall(bindSym"styledEcho") + for arg in children(args[0][1]): + result.add(arg) + +template callWritelnHook(args: varargs[string, `$`]) = + var s = "" + for arg in args: + s.add arg + writelnHook s + +template styledMsgWriteln*(args: varargs[expr]) = + if not isNil(writelnHook): + callIgnoringStyle(callWritelnHook, nil, args) + elif optStdout in gGlobalOptions: + if eStdErr in errorOutputs: callIgnoringStyle(writeln, stderr, args) + else: + if eStdOut in errorOutputs: + if optUseColors in gGlobalOptions: + callStyledEcho(args) + else: + callIgnoringStyle(writeln, stdout, args) proc coordToStr(coord: int): string = if coord == -1: result = "???" @@ -728,7 +761,7 @@ proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) = if stackTraceAvailable() and isNil(writelnHook): writeStackTrace() else: - msgWriteln("", fgRed, "No stack traceback available\nTo create a stacktrace, rerun compilation with ./koch temp " & options.command & " <file>") + styledMsgWriteln(fgRed, "No stack traceback available\nTo create a stacktrace, rerun compilation with ./koch temp " & options.command & " <file>") quit 1 if msg >= fatalMin and msg <= fatalMax: @@ -750,10 +783,12 @@ proc writeContext(lastinfo: TLineInfo) = var info = lastinfo for i in countup(0, len(msgContext) - 1): if msgContext[i] != lastinfo and msgContext[i] != info: - msgWriteln(PosContextFormat % [toMsgFilename(msgContext[i]), - coordToStr(msgContext[i].line), - coordToStr(msgContext[i].col+1), - getMessageStr(errInstantiationFrom, "")]) + styledMsgWriteln(styleBright, + PosFormat % [toMsgFilename(msgContext[i]), + coordToStr(msgContext[i].line), + coordToStr(msgContext[i].col+1)], + styleDim, + getMessageStr(errInstantiationFrom, "")) info = msgContext[i] proc ignoreMsgBecauseOfIdeTools(msg: TMsgKind): bool = @@ -761,29 +796,29 @@ proc ignoreMsgBecauseOfIdeTools(msg: TMsgKind): bool = proc rawMessage*(msg: TMsgKind, args: openArray[string]) = var - frmt: string + title: string color: ForegroundColor case msg of errMin..errMax: writeContext(unknownLineInfo()) - frmt = RawError - color = fgRed + title = ErrorTitle + color = ErrorColor of warnMin..warnMax: if optWarns notin gOptions: return if msg notin gNotes: return writeContext(unknownLineInfo()) - frmt = RawWarning + title = WarningTitle + color = WarningColor inc(gWarnCounter) - color = fgYellow of hintMin..hintMax: if optHints notin gOptions: return if msg notin gNotes: return - frmt = RawHint + title = HintTitle + color = HintColor inc(gHintCounter) - color = fgGreen let s = `%`(msgKindToString(msg), args) if not ignoreMsgBecauseOfIdeTools(msg): - msgWriteln(s, color, frmt) + styledMsgWriteln(color, title, resetStyle, s) handleError(msg, doAbort, s) proc rawMessage*(msg: TMsgKind, arg: string) = @@ -795,47 +830,49 @@ proc writeSurroundingSrc(info: TLineInfo) = msgWriteln(indent & spaces(info.col) & '^') proc formatMsg*(info: TLineInfo, msg: TMsgKind, arg: string): string = - let frmt = case msg - of warnMin..warnMax: PosWarningFormat - of hintMin..hintMax: PosHintFormat - else: PosErrorFormat - result = frmt % [toMsgFilename(info), coordToStr(info.line), - coordToStr(info.col+1), getMessageStr(msg, arg)] + let title = case msg + of warnMin..warnMax: WarningTitle + of hintMin..hintMax: HintTitle + else: ErrorTitle + result = PosFormat % [toMsgFilename(info), coordToStr(info.line), + coordToStr(info.col+1)] & + title & + getMessageStr(msg, arg) proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, eh: TErrorHandling) = var - frmt: string + title: string ignoreMsg = false color: ForegroundColor case msg of errMin..errMax: writeContext(info) - frmt = PosErrorFormat + title = ErrorTitle + color = ErrorColor # we try to filter error messages so that not two error message # in the same file and line are produced: #ignoreMsg = lastError == info and eh != doAbort lastError = info - color = fgRed of warnMin..warnMax: ignoreMsg = optWarns notin gOptions or msg notin gNotes if not ignoreMsg: writeContext(info) - frmt = PosWarningFormat + title = WarningTitle + color = WarningColor inc(gWarnCounter) - color = fgYellow of hintMin..hintMax: ignoreMsg = optHints notin gOptions or msg notin gNotes - frmt = PosHintFormat + title = HintTitle + color = HintColor inc(gHintCounter) - color = fgGreen # NOTE: currently line info line numbers start with 1, # but column numbers start with 0, however most editors expect # first column to be 1, so we need to +1 here - let x = frmt % [toMsgFilename(info), coordToStr(info.line), - coordToStr(info.col+1)] + let x = PosFormat % [toMsgFilename(info), coordToStr(info.line), + coordToStr(info.col+1)] let s = getMessageStr(msg, arg) if not ignoreMsg and not ignoreMsgBecauseOfIdeTools(msg): - msgWriteln(s, color, x) + styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s) if optPrintSurroundingSrc and msg in errMin..errMax: info.writeSurroundingSrc handleError(msg, eh, s) |