diff --git a/src/libutil/error.cc b/src/libutil/error.cc new file mode 100644 index 000000000..4af4691d4 --- /dev/null +++ b/src/libutil/error.cc @@ -0,0 +1,137 @@ +#include "error.hh" + +#include + +namespace nix { + +using std::cout; +using std::endl; + +// return basic_format? +string showErrLine(ErrLine &errLine) +{ + if (errLine.columnRange.has_value()) + { + return (format("(%1%:%2%)") % errLine.lineNumber % errLine.columnRange->start).str(); + } + else + { + return (format("(%1%)") % errLine.lineNumber).str(); + }; +} + +void print_code_lines(string &prefix, NixCode &nix_code) +{ + if (nix_code.errLine.has_value()) + { + // previous line of code. + if (nix_code.errLine->prevLineOfCode.has_value()) { + cout << format("%1% %2$+5d%| %3%") % prefix % (nix_code.errLine->lineNumber - 1) % *nix_code.errLine->prevLineOfCode; + } + + // line of code containing the error. + cout << format("%1% %2$+5d%| %3%") % prefix % (nix_code.errLine->lineNumber) % nix_code.errLine->errLineOfCode; + + // error arrows for the column range. + if (nix_code.errLine->columnRange.has_value()) + { + int start = nix_code.errLine->columnRange->start; + std::string spaces; + for (int i = 0; i < start; ++i) + { + spaces.append(" "); + } + + int len = nix_code.errLine->columnRange->len; + std::string arrows; + for (int i = 0; i < len; ++i) + { + arrows.append("^"); + } + + cout << format("%1% |%2%%3%") % prefix % spaces % arrows; + } + + + // next line of code. + if (nix_code.errLine->nextLineOfCode.has_value()) { + cout << format("%1% %2$+5d%| %3%") % prefix % (nix_code.errLine->lineNumber + 1) % *nix_code.errLine->nextLineOfCode; + } + + } + else + { + } + +} + +void print_error(ErrorInfo &einfo) +{ + int errwidth = 80; + string prefix = " "; + + string level_string; + switch (einfo.level) + { + case ErrLevel::elError: + { + level_string = "error:"; // TODO make red. + break; + } + case ErrLevel::elWarning: + { + level_string = "warning:"; // TODO make yellow. + break; + } + } + + int ndl = level_string.length() + 3 + einfo.errName.length() + einfo.toolName.length(); + int dashwidth = errwidth - 3 ? 3 : 80 - ndl; + + string dashes; + for (int i = 0; i < dashwidth; ++i) + dashes.append("-"); + + // divider. + cout << format("%1%%2% %3% %4% %5% %6%") + % prefix + % level_string + % "---" + % einfo.errName + % dashes + % einfo.toolName; + + // filename. + if (einfo.nixCode.has_value()) + { + if (einfo.nixCode->nixFile.has_value()) + { + string eline = einfo.nixCode->errLine.has_value() + ? string(" ") + showErrLine(*einfo.nixCode->errLine) + : ""; + + cout << format("%1%in file: %2%%3%") % prefix % *einfo.nixCode->nixFile % eline; + cout << prefix << endl; + } + else + { + cout << format("%1%from command line argument") % prefix << endl; + cout << prefix << endl; + } + } + + // description + cout << prefix << einfo.description << endl; + cout << prefix << endl; + + // lines of code. + if (einfo.nixCode.has_value()) + print_code_lines(prefix, *einfo.nixCode); + + // hint + cout << prefix << einfo.hint << endl; + cout << prefix << endl; + +} + +} diff --git a/src/libutil/error.hh b/src/libutil/error.hh new file mode 100644 index 000000000..0bc1f4e24 --- /dev/null +++ b/src/libutil/error.hh @@ -0,0 +1,57 @@ +#pragma once + +#include "types.hh" +#include +#include +// #include + +using std::string; +using std::optional; +// using boost::format; + +namespace nix { + +enum ErrLevel + { elWarning + , elError + }; + +class ColumnRange { + public: + unsigned int start; + unsigned int len; +}; + +class ErrLine { + public: + int lineNumber; + optional columnRange; + optional prevLineOfCode; + string errLineOfCode; + optional nextLineOfCode; +}; + +class NixCode { + public: + optional nixFile; + optional errLine; +}; + + +class ErrorInfo { + public: + ErrLevel level; + string errName; + string description; + string toolName; + optional nixCode; + string hint; +}; + +string showErrLine(ErrLine &errLine); + +void print_code_lines(string &prefix, NixCode &nix_code); + +void print_error(ErrorInfo &einfo); +} +