Initial implementation.
This commit is contained in:
		
							
								
								
									
										80
									
								
								src/slfmt.nim
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/slfmt.nim
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
import std/[json, sequtils, streams, strutils, terminal, times]
 | 
			
		||||
import timeutils
 | 
			
		||||
#import docopt
 | 
			
		||||
 | 
			
		||||
const VERSION = "0.1.0"
 | 
			
		||||
 | 
			
		||||
# const USAGE = """Usage:
 | 
			
		||||
#   slfmt
 | 
			
		||||
#
 | 
			
		||||
# Options:
 | 
			
		||||
#
 | 
			
		||||
#   -h, --help            Print this usage and help information
 | 
			
		||||
 | 
			
		||||
const fieldDisplayOrder = @[
 | 
			
		||||
  "scope", "level", "ts", "code", "sid", "sub", "msg", "err", "stack", "method", "args"]
 | 
			
		||||
 | 
			
		||||
func decorate(
 | 
			
		||||
    s: string,
 | 
			
		||||
    fg = fgDefault,
 | 
			
		||||
    style: set[Style] = {}): string =
 | 
			
		||||
 | 
			
		||||
  result = ""
 | 
			
		||||
 | 
			
		||||
  if style != {}:
 | 
			
		||||
    result &= toSeq(items(style)).mapIt(ansiStyleCode(it)).join("")
 | 
			
		||||
 | 
			
		||||
  if fg != fgDefault: result &= ansiForegroundColorCode(fg)
 | 
			
		||||
 | 
			
		||||
  result &= s & ansiResetCode
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
proc formatField(name: string, value: JsonNode): string =
 | 
			
		||||
  result = decorate(name, fgCyan) & ":" & " ".repeat(max(1, 10 - name.len))
 | 
			
		||||
 | 
			
		||||
  var strVal: string = ""
 | 
			
		||||
  case name:
 | 
			
		||||
    of "ts":
 | 
			
		||||
      let dt = parseIso8601(value.getStr)
 | 
			
		||||
      strVal = decorate(dt.local.formatIso8601 & " (local)  ", fgBlue, {styleBright}) &
 | 
			
		||||
        dt.utc.formatIso8601 & " (UTC)"
 | 
			
		||||
    of "sid", "sub": strVal = decorate(value.getStr, fgGreen)
 | 
			
		||||
    of "err": strVal = decorate(value.getStr, fgRed)
 | 
			
		||||
    of "msg": strVal = decorate(value.getStr, fgYellow)
 | 
			
		||||
    of "stack": strVal = decorate(value.getStr, fgBlack, {styleBright})
 | 
			
		||||
    else: strVal = pretty(value)
 | 
			
		||||
 | 
			
		||||
  let valLines = splitLines(strVal)
 | 
			
		||||
  if name.len > 10 or strVal.len + 16 > terminalWidth() or valLines.len > 1:
 | 
			
		||||
    result &= "\n" & valLines.mapIt("  " & it).join("\n") & "\n"
 | 
			
		||||
  else: result &= strVal & "\n"
 | 
			
		||||
 | 
			
		||||
proc prettyPrintFormat(logLine: string): string =
 | 
			
		||||
  try:
 | 
			
		||||
    var logJson = parseJson(logLine)
 | 
			
		||||
 | 
			
		||||
    result = '-'.repeat(terminalWidth())
 | 
			
		||||
 | 
			
		||||
    # Print the known fields in order first
 | 
			
		||||
    for f in fieldDisplayOrder:
 | 
			
		||||
      if logJson.hasKey(f):
 | 
			
		||||
        result &= formatField(f, logJson[f])
 | 
			
		||||
        logJson.delete(f)
 | 
			
		||||
 | 
			
		||||
    # Print the rest of the fields
 | 
			
		||||
    for (key, val) in pairs(logJson): result &= formatField(key, val)
 | 
			
		||||
 | 
			
		||||
    result &= "\n"
 | 
			
		||||
 | 
			
		||||
  except ValueError, JsonParsingError:
 | 
			
		||||
    result = logLine
 | 
			
		||||
 | 
			
		||||
when isMainModule:
 | 
			
		||||
  try:
 | 
			
		||||
    var line: string = ""
 | 
			
		||||
    let sin = newFileStream(stdin)
 | 
			
		||||
    while(sin.readLine(line)): stdout.writeLine(prettyPrintFormat(line))
 | 
			
		||||
  except:
 | 
			
		||||
    stderr.writeLine("slfmt - FATAL: " & getCurrentExceptionMsg())
 | 
			
		||||
    stderr.writeLine(getCurrentException().getStackTrace())
 | 
			
		||||
    quit(QuitFailure)
 | 
			
		||||
		Reference in New Issue
	
	Block a user