summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2023-05-28 05:54:32 +0200
committerGitHub <noreply@github.com>2023-05-28 05:54:32 +0200
commit2900987c2fc2109b636f5f92358fd4ac221fe565 (patch)
treeab69a3066f6dcf8ef1157ebb581f5f69f8bf3f4e
parentb96c501836a7434fd4e76ad24a3d87b01cdcb2e0 (diff)
downloadNim-2900987c2fc2109b636f5f92358fd4ac221fe565.tar.gz
Atlas: use colored output (#21939)
* Atlas: use colored output

* fixes merge conflict

* another tiny improvement
-rw-r--r--tools/atlas/atlas.nim86
1 files changed, 48 insertions, 38 deletions
diff --git a/tools/atlas/atlas.nim b/tools/atlas/atlas.nim
index 9361cf043..606578613 100644
--- a/tools/atlas/atlas.nim
+++ b/tools/atlas/atlas.nim
@@ -10,7 +10,7 @@
 ## a Nimble dependency and its dependencies recursively.
 
 import std / [parseopt, strutils, os, osproc, tables, sets, json, jsonutils,
-  parsecfg, streams]
+  parsecfg, streams, terminal]
 import parse_requires, osutils, packagesjson
 
 from unicode import nil
@@ -57,6 +57,7 @@ Options:
   --workspace=DIR       use DIR as workspace
   --genlock             generate a lock file (use with `clone` and `update`)
   --uselock             use the lock file for the build
+  --colors=on|off       turn on|off colored output
   --version             show the version
   --help                show this help
 """
@@ -113,6 +114,7 @@ type
       currentDir: string
       step: int
       mockupSuccess: bool
+    noColors: bool
 
 proc `==`(a, b: CfgPath): bool {.borrow.}
 
@@ -212,24 +214,30 @@ proc isCleanGit(c: var AtlasContext): string =
   elif status != 0:
     result = "'git diff' returned non-zero"
 
-proc message(c: var AtlasContext; category: string; p: PackageName; args: varargs[string]) =
-  var msg = category & "(" & p.string & ")"
-  for a in args:
-    msg.add ' '
-    msg.add a
+proc message(c: var AtlasContext; category: string; p: PackageName; arg: string) =
+  var msg = category & "(" & p.string & ") " & arg
   stdout.writeLine msg
 
-proc info(c: var AtlasContext; p: PackageName; args: varargs[string]) =
-  message(c, "[Info] ", p, args)
-
-proc warn(c: var AtlasContext; p: PackageName; args: varargs[string]) =
-  message(c, "[Warning] ", p, args)
+proc warn(c: var AtlasContext; p: PackageName; arg: string) =
+  if c.noColors:
+    message(c, "[Warning] ", p, arg)
+  else:
+    stdout.styledWriteLine(fgYellow, styleBright, "[Warning] ", resetStyle, fgCyan, "(", p.string, ")", fgDefault, " ", arg)
   inc c.errors
 
-proc error(c: var AtlasContext; p: PackageName; args: varargs[string]) =
-  message(c, "[Error] ", p, args)
+proc error(c: var AtlasContext; p: PackageName; arg: string) =
+  if c.noColors:
+    message(c, "[Error] ", p, arg)
+  else:
+    stdout.styledWriteLine(fgRed, styleBright, "[Error] ", resetStyle, fgCyan, "(", p.string, ")", fgDefault, " ", arg)
   inc c.errors
 
+proc info(c: var AtlasContext; p: PackageName; arg: string) =
+  if c.noColors:
+    message(c, "[Info] ", p, arg)
+  else:
+    stdout.styledWriteLine(fgGreen, styleBright, "[Info] ", resetStyle, fgCyan, "(", p.string, ")", fgDefault, " ", arg)
+
 proc sameVersionAs(tag, ver: string): bool =
   const VersionChars = {'0'..'9', '.'}
 
@@ -273,7 +281,7 @@ proc shortToCommit(c: var AtlasContext; short: string): string =
 proc checkoutGitCommit(c: var AtlasContext; p: PackageName; commit: string) =
   let (_, status) = exec(c, GitCheckout, [commit])
   if status != 0:
-    error(c, p, "could not checkout commit", commit)
+    error(c, p, "could not checkout commit " & commit)
 
 proc gitPull(c: var AtlasContext; p: PackageName) =
   let (_, status) = exec(c, GitPull, [])
@@ -431,7 +439,7 @@ proc checkoutCommit(c: var AtlasContext; w: Dependency) =
           if requiredCommit == "" and w.commit == InvalidCommit:
             warn c, w.name, "package has no tagged releases"
           else:
-            warn c, w.name, "cannot find specified version/commit", w.commit
+            warn c, w.name, "cannot find specified version/commit " & w.commit
         else:
           if currentCommit != requiredCommit:
             # checkout the later commit:
@@ -619,7 +627,7 @@ proc patchNimCfg(c: var AtlasContext; deps: seq[CfgPath]; cfgPath: string) =
         writeFile(cfg, cfgContent)
         info(c, projectFromCurrentDir(), "updated: " & cfg)
 
-proc error*(msg: string) =
+proc fatal*(msg: string) =
   when defined(debug):
     writeStackTrace()
   quit "[Error] " & msg
@@ -646,14 +654,14 @@ proc generateDepGraph(g: DepGraph) =
   else:
     discard execShellCmd("dot -Tpng -odeps.png deps.dot")
 
-proc installDependencies(c: var AtlasContext; nimbleFile: string) =
+proc installDependencies(c: var AtlasContext; nimbleFile: string; startIsDep: bool) =
   # 1. find .nimble file in CWD
   # 2. install deps from .nimble
   var g = DepGraph(nodes: @[])
   let (_, pkgname, _) = splitFile(nimbleFile)
   let dep = Dependency(name: toName(pkgname), url: "", commit: "")
   discard collectDeps(c, g, -1, dep, nimbleFile)
-  let paths = traverseLoop(c, g, startIsDep = true)
+  let paths = traverseLoop(c, g, startIsDep)
   patchNimCfg(c, paths, if c.cfgHere: getCurrentDir() else: findSrcDir(c))
 
 proc updateDir(c: var AtlasContext; dir, filter: string) =
@@ -673,7 +681,7 @@ proc updateDir(c: var AtlasContext; dir, filter: string) =
               if exitCode != 0:
                 error c, pkg, output
               else:
-                message(c, "[Hint] ", pkg, "successfully updated")
+                info(c, pkg, "successfully updated")
             else:
               error c, pkg, "could not fetch current branch name"
 
@@ -779,16 +787,15 @@ proc main =
   var args: seq[string] = @[]
   template singleArg() =
     if args.len != 1:
-      error action & " command takes a single package name"
+      fatal action & " command takes a single package name"
 
   template noArgs() =
     if args.len != 0:
-      error action & " command takes no arguments"
+      fatal action & " command takes no arguments"
 
   template projectCmd() =
     if getCurrentDir() == c.workspace or getCurrentDir() == c.depsDir:
-      error action & " command must be executed in a project, not in the workspace"
-      return
+      fatal action & " command must be executed in a project, not in the workspace"
 
   var c = AtlasContext(projectDir: getCurrentDir(), workspace: "")
 
@@ -830,11 +837,16 @@ proc main =
           c.lockOption = useLock
         else:
           writeHelp()
+      of "colors":
+        case val.normalize
+        of "off": c.noColors = true
+        of "on": c.noColors = false
+        else: writeHelp()
       else: writeHelp()
     of cmdEnd: assert false, "cannot happen"
 
   if c.workspace.len > 0:
-    if not dirExists(c.workspace): error "Workspace directory '" & c.workspace & "' not found."
+    if not dirExists(c.workspace): fatal "Workspace directory '" & c.workspace & "' not found."
   elif action != "init":
     when MockupRun:
       c.workspace = autoWorkspace()
@@ -842,17 +854,16 @@ proc main =
       c.workspace = detectWorkspace()
       if c.workspace.len > 0:
         readConfig c
-        echo "Using workspace ", c.workspace
+        info c, toName(c.workspace), "is the current workspace"
       elif action notin ["search", "list"]:
-        error "No workspace found. Run `atlas init` if you want this current directory to be your workspace."
-        return
+        fatal "No workspace found. Run `atlas init` if you want this current directory to be your workspace."
 
   when MockupRun:
     c.depsDir = c.workspace
 
   case action
   of "":
-    error "No action."
+    fatal "No action."
   of "init":
     c.workspace = getCurrentDir()
     createWorkspaceIn c.workspace, c.depsDir
@@ -862,20 +873,20 @@ proc main =
     patchNimCfg c, deps, if c.cfgHere: getCurrentDir() else: findSrcDir(c)
     when MockupRun:
       if not c.mockupSuccess:
-        error "There were problems."
+        fatal "There were problems."
     else:
       if c.errors > 0:
-        error "There were problems."
+        fatal "There were problems."
   of "use":
     projectCmd()
     singleArg()
     let nimbleFile = patchNimbleFile(c, args[0])
     if nimbleFile.len > 0:
-      installDependencies(c, nimbleFile)
+      installDependencies(c, nimbleFile, startIsDep = false)
   of "install":
     projectCmd()
     if args.len > 1:
-      error "install command takes a single argument"
+      fatal "install command takes a single argument"
     var nimbleFile = ""
     if args.len == 1:
       nimbleFile = args[0]
@@ -884,9 +895,9 @@ proc main =
         nimbleFile = x
         break
     if nimbleFile.len == 0:
-      error "could not find a .nimble file"
+      fatal "could not find a .nimble file"
     else:
-      installDependencies(c, nimbleFile)
+      installDependencies(c, nimbleFile, startIsDep = true)
   of "refresh":
     noArgs()
     updatePackages(c)
@@ -904,7 +915,7 @@ proc main =
     if fileExists(args[0]):
       echo toJson(extractRequiresInfo(args[0]))
     else:
-      error "File does not exist: " & args[0]
+      fatal "File does not exist: " & args[0]
   of "tag":
     projectCmd()
     if args.len == 0:
@@ -917,7 +928,7 @@ proc main =
     else:
       var field: SemVerField
       try: field = parseEnum[SemVerField](args[0])
-      except: error "tag command takes one of 'patch' 'minor' 'major', a SemVer tag, or a letter from 'a' to 'z'"
+      except: fatal "tag command takes one of 'patch' 'minor' 'major', a SemVer tag, or a letter from 'a' to 'z'"
       tag(c, ord(field))
   of "build", "test", "doc", "tasks":
     projectCmd()
@@ -926,8 +937,7 @@ proc main =
     projectCmd()
     nimbleExec("", args)
   else:
-    error "Invalid action: " & action
+    fatal "Invalid action: " & action
 
 when isMainModule:
   main()
-