61 lines
1.7 KiB
Nim
61 lines
1.7 KiB
Nim
import std/[
|
|
strutils,
|
|
math,
|
|
]
|
|
import fusion/matching
|
|
|
|
{.experimental: "caseStmtMacros".}
|
|
|
|
func prettyExpectedSet*(x: set[char]): string =
|
|
## Pretty print value for a set `x` of characters
|
|
case x:
|
|
of AllChars:
|
|
"AllChars {'\x00'..'\xFF'}"
|
|
of Digits:
|
|
"Digits {'0'..'9'}"
|
|
of HexDigits:
|
|
"HexDigits {'0'..'9', 'A'..'F', 'a'..'f'}"
|
|
of Letters:
|
|
"Letters {'A'..'Z', 'a'..'z'}"
|
|
of Newlines:
|
|
"Newlines {'\r', '\n'}"
|
|
of Whitespace:
|
|
"Whitespace {' ', '\t', '\v', '\r', '\n', '\f'}"
|
|
else:
|
|
$x
|
|
|
|
func indentAfterNewline*(str: string, count: int): string =
|
|
## Indent lines following the first line of `str` by `count`.
|
|
## Useful for indenting nested keys of stringify functions.
|
|
var strDup = str.indent(count)
|
|
strDup.delete(0..count - 1)
|
|
strDup
|
|
|
|
proc safeDelete*(str: string, slice: Slice[int]): string =
|
|
## Deletes the items `str[slice]`, ignoring elements out of range.
|
|
if slice.a > str.len - 1:
|
|
str
|
|
else:
|
|
let fromIndex = clamp(slice.a, 0..str.len)
|
|
let toIndex = clamp(slice.b, 0..str.len - 1)
|
|
|
|
var strDup = str
|
|
strDup.delete(fromIndex..toIndex)
|
|
strDup
|
|
|
|
func findAndDelete*(str: string, chars: set[char], start = 0, last = str.len - 1): string =
|
|
## Find the next instance of `chars` from `start`.
|
|
## When found delete characters until `last`.
|
|
# Prevent passing negative numbers (e.g.: initial parser)
|
|
if start >= 0 and last >= 0:
|
|
let startChar = str.find(chars, start, last)
|
|
if startChar == -1:
|
|
str
|
|
else:
|
|
str.safeDelete(startChar..last)
|
|
else: str
|
|
|
|
func deleteAfterNewline*(str: string, start = 0): string =
|
|
## Delete string after next Newline from `start`.
|
|
findAndDelete(str, Newlines, start)
|