** Generates snippets of source code, often used to report errors. Example:** ** pre>** file:/C:/test/app/compilationErr.moustache : Line 11** - Unbalanced "{" in tag "{ alienHeadSvg } <span class="brand">{{ title"** ** 6: {{{ bedSheetCss }}}** 7: </style>** 8: </head>** 9: <body>** 10: <header>** ==> 11: {{{ alienHeadSvg }** 12: <span class="brand">{{ title }}</span>** 13: </header>** 14:** 15: <main>** 16: {{{ content }}}** <preconstclass SrcCodeSnippet {** An arbitrary uri of where the source code originated from. const Uri srcCodeLocation** A list of source code lines.const Str[] srcCode** Creates a SrcCodeSnippet. ** The srcCodeLocation URI may be anything as it is only used for reporting. new make(Uri srcCodeLocation, Str srcCode){this.srcCodeLocation= srcCodeLocationthis.srcCode = srcCode.splitLines}** Returns a snippet of source code, centred on 'lineNo' and padded on either side by an ** extra 'linesOfPadding'.** ** Note that 'lineNo' is ONE based, not zero. Str srcCodeSnippet(Int lineNo, Str? msg := null, Int linesOfPadding := 5){ buf := StrBuf() buf.add(" ${srcCodeLocation}").add(" : Line ${lineNo}\n")if(msg != null) buf.add(" - ${msg}\n") buf.add("\n") srcCodeSnippetMap(lineNo, linesOfPadding).each |src, line| { pointer := (line == lineNo) ? "==>" : " " buf.add("${pointer}${line.toStr.justr(3)}: ${src}\n".replace("\t", " "))}return buf.toStr}** Returns a map of line numbers to source code, centred on 'lineNo' and padded on either ** side by an extra 'linesOfPadding'.** ** Note that 'lineNo' is ONE based, not zero. Int:Str srcCodeSnippetMap(Int lineNo, Int linesOfPadding := 5){ min := (lineNo - 1 - linesOfPadding).max(0)// -1 so "Line 1" == src[0] max := (lineNo - 1 + linesOfPadding + 1).min(srcCode.size) lines := Int:Str[:]{it.ordered = true}(min..<max).each { lines[it+1] = srcCode[it]}// uniformly remove extra whitespace while(canTrim(lines)) trim(lines)return lines}private Bool canTrim(Int:Str lines){ lines.vals.all {it.size > 0 && it[0].isSpace }}private Void trim(Int:Str lines){ lines.each |val, key| { lines[key] = val[1..-1]}}override Str toStr(){"${srcCodeLocation} : ${srcCode.size} lines"}}