summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2018-08-30 04:52:32 -0700
committerAndreas Rumpf <rumpf_a@web.de>2018-08-30 13:52:32 +0200
commited0cb7b85d8d48bcebb63a5e90a45a4e29bcb673 (patch)
treea89177259a1fb42477adbafa09c1790c5fe50535 /compiler
parent01211ced1d5c3252c88e61bbbb6bb78dcc5575f0 (diff)
downloadNim-ed0cb7b85d8d48bcebb63a5e90a45a4e29bcb673.tar.gz
make config.nims behave like nim.cfg in terms of where these scripts are searched / run (#8682)
* run project config.nims if exists, then inputfile.nims if exists
* ~/.config/nim/config.nims can now be used
* also check in getSystemConfigPath for config.nims
* refactor handleCmdLine for nim and nimsuggest
Diffstat (limited to 'compiler')
-rw-r--r--compiler/cmdlinehelper.nim85
-rw-r--r--compiler/commands.nim2
-rw-r--r--compiler/nim.nim96
-rw-r--r--compiler/nimconf.nim7
-rw-r--r--compiler/options.nim9
-rw-r--r--compiler/scriptconfig.nim2
6 files changed, 131 insertions, 70 deletions
diff --git a/compiler/cmdlinehelper.nim b/compiler/cmdlinehelper.nim
new file mode 100644
index 000000000..9d2334af5
--- /dev/null
+++ b/compiler/cmdlinehelper.nim
@@ -0,0 +1,85 @@
+## Helpers for binaries that use compiler passes, eg: nim, nimsuggest, nimfix
+
+# TODO: nimfix should use this; currently out of sync
+
+import
+  compiler/[options, idents, nimconf, scriptconfig, extccomp, commands, msgs, lineinfos, modulegraphs, condsyms],
+  std/os
+
+type
+  NimProg* = ref object
+    suggestMode*: bool
+    supportsStdinFile*: bool
+    processCmdLine*: proc(pass: TCmdLinePass, cmd: string; config: ConfigRef)
+    mainCommand*: proc(graph: ModuleGraph)
+
+proc initDefinesProg*(self: NimProg, conf: ConfigRef, name: string) =
+  condsyms.initDefines(conf.symbols)
+  defineSymbol conf.symbols, name
+
+proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
+  self.processCmdLine(passCmd1, "", conf)
+  if self.supportsStdinFile and conf.projectName == "-":
+    conf.projectName = "stdinfile"
+    conf.projectFull = "stdinfile"
+    conf.projectPath = canonicalizePath(conf, getCurrentDir())
+    conf.projectIsStdin = true
+  elif conf.projectName != "":
+    try:
+      conf.projectFull = canonicalizePath(conf, conf.projectName)
+    except OSError:
+      conf.projectFull = conf.projectName
+    let p = splitFile(conf.projectFull)
+    let dir = if p.dir.len > 0: p.dir else: getCurrentDir()
+    conf.projectPath = canonicalizePath(conf, dir)
+    conf.projectName = p.name
+  else:
+    conf.projectPath = canonicalizePath(conf, getCurrentDir())
+
+proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: ConfigRef): bool =
+  loadConfigs(DefaultConfig, cache, conf) # load all config files
+  if self.suggestMode:
+    conf.command = "nimsuggest"
+
+  proc runNimScriptIfExists(path: string)=
+    if fileExists(path):
+      runNimScript(cache, path, freshDefines = false, conf)
+
+  # Caution: make sure this stays in sync with `loadConfigs`
+  if optSkipSystemConfigFile notin conf.globalOptions:
+    runNimScriptIfExists(getSystemConfigPath(conf, DefaultConfigNims))
+
+  if optSkipUserConfigFile notin conf.globalOptions:
+    runNimScriptIfExists(getUserConfigPath(DefaultConfigNims))
+
+  if optSkipParentConfigFiles notin conf.globalOptions:
+    for dir in parentDirs(conf.projectPath, fromRoot = true, inclusive = false):
+      runNimScriptIfExists(dir / DefaultConfigNims)
+
+  if optSkipProjConfigFile notin conf.globalOptions:
+    runNimScriptIfExists(conf.projectPath / DefaultConfigNims)
+  block:
+    let scriptFile = conf.projectFull.changeFileExt("nims")
+    if not self.suggestMode:
+      runNimScriptIfExists(scriptFile)
+      # 'nim foo.nims' means to just run the NimScript file and do nothing more:
+      if fileExists(scriptFile) and scriptFile.cmpPaths(conf.projectFull) == 0:
+        return false
+    else:
+      if scriptFile.cmpPaths(conf.projectFull) != 0:
+        runNimScriptIfExists(scriptFile)
+      else:
+        # 'nimsuggest foo.nims' means to just auto-complete the NimScript file
+        discard
+
+  # now process command line arguments again, because some options in the
+  # command line can overwite the config file's settings
+  extccomp.initVars(conf)
+  self.processCmdLine(passCmd2, "", conf)
+  if conf.command == "":
+    rawMessage(conf, errGenerated, "command missing")
+
+  let graph = newModuleGraph(cache, conf)
+  graph.suggestMode = self.suggestMode
+  self.mainCommand(graph)
+  return true
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 8165fa5d4..b47ccf610 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -651,7 +651,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     else: localError(conf, info, "invalid option for --symbolFiles: " & arg)
   of "skipcfg":
     expectNoArg(conf, switch, arg, pass, info)
-    incl(conf.globalOptions, optSkipConfigFile)
+    incl(conf.globalOptions, optSkipSystemConfigFile)
   of "skipprojcfg":
     expectNoArg(conf, switch, arg, pass, info)
     incl(conf.globalOptions, optSkipProjConfigFile)
diff --git a/compiler/nim.nim b/compiler/nim.nim
index 90049bdfb..0fed72dc7 100644
--- a/compiler/nim.nim
+++ b/compiler/nim.nim
@@ -21,7 +21,7 @@ when defined(i386) and defined(windows) and defined(vcc):
 import
   commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
   extccomp, strutils, os, osproc, platform, main, parseopt,
-  nodejs, scriptconfig, idents, modulegraphs, lineinfos
+  nodejs, scriptconfig, idents, modulegraphs, lineinfos, cmdlinehelper
 
 when hasTinyCBackend:
   import tccgen
@@ -57,69 +57,43 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
       rawMessage(config, errGenerated, errArgsNeedRunOption)
 
 proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
-  condsyms.initDefines(conf.symbols)
+  let self = NimProg(
+    supportsStdinFile: true,
+    processCmdLine: processCmdLine,
+    mainCommand: mainCommand
+  )
+  self.initDefinesProg(conf, "nim_compiler")
   if paramCount() == 0:
     writeCommandLineUsage(conf, conf.helpWritten)
-  else:
-    # Process command line arguments:
-    processCmdLine(passCmd1, "", conf)
-    if conf.projectName == "-":
-      conf.projectName = "stdinfile"
-      conf.projectFull = "stdinfile"
-      conf.projectPath = canonicalizePath(conf, getCurrentDir())
-      conf.projectIsStdin = true
-    elif conf.projectName != "":
-      try:
-        conf.projectFull = canonicalizePath(conf, conf.projectName)
-      except OSError:
-        conf.projectFull = conf.projectName
-      let p = splitFile(conf.projectFull)
-      let dir = if p.dir.len > 0: p.dir else: getCurrentDir()
-      conf.projectPath = canonicalizePath(conf, dir)
-      conf.projectName = p.name
+    return
+
+  self.processCmdLineAndProjectPath(conf)
+  if not self.loadConfigsAndRunMainCommand(cache, conf): return
+  if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
+  #echo(GC_getStatistics())
+  if conf.errorCounter != 0: return
+  when hasTinyCBackend:
+    if conf.cmd == cmdRun:
+      tccgen.run(conf.arguments)
+  if optRun in conf.globalOptions:
+    if conf.cmd == cmdCompileToJS:
+      var ex: string
+      if conf.outFile.len > 0:
+        ex = conf.outFile.prependCurDir.quoteShell
+      else:
+        ex = quoteShell(
+          completeCFilePath(conf, changeFileExt(conf.projectFull, "js").prependCurDir))
+      execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments)
     else:
-      conf.projectPath = canonicalizePath(conf, getCurrentDir())
-    loadConfigs(DefaultConfig, cache, conf) # load all config files
-    let scriptFile = conf.projectFull.changeFileExt("nims")
-    if fileExists(scriptFile):
-      runNimScript(cache, scriptFile, freshDefines=false, conf)
-      # 'nim foo.nims' means to just run the NimScript file and do nothing more:
-      if scriptFile == conf.projectFull: return
-    elif fileExists(conf.projectPath / "config.nims"):
-      # directory wide NimScript file
-      runNimScript(cache, conf.projectPath / "config.nims", freshDefines=false, conf)
-    # now process command line arguments again, because some options in the
-    # command line can overwite the config file's settings
-    extccomp.initVars(conf)
-    processCmdLine(passCmd2, "", conf)
-    if conf.command == "":
-      rawMessage(conf, errGenerated, "command missing")
-    mainCommand(newModuleGraph(cache, conf))
-    if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
-    #echo(GC_getStatistics())
-    if conf.errorCounter == 0:
-      when hasTinyCBackend:
-        if conf.cmd == cmdRun:
-          tccgen.run(conf.arguments)
-      if optRun in conf.globalOptions:
-        if conf.cmd == cmdCompileToJS:
-          var ex: string
-          if conf.outFile.len > 0:
-            ex = conf.outFile.prependCurDir.quoteShell
-          else:
-            ex = quoteShell(
-              completeCFilePath(conf, changeFileExt(conf.projectFull, "js").prependCurDir))
-          execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments)
-        else:
-          var binPath: string
-          if conf.outFile.len > 0:
-            # If the user specified an outFile path, use that directly.
-            binPath = conf.outFile.prependCurDir
-          else:
-            # Figure out ourselves a valid binary name.
-            binPath = changeFileExt(conf.projectFull, ExeExt).prependCurDir
-          var ex = quoteShell(binPath)
-          execExternalProgram(conf, ex & ' ' & conf.arguments)
+      var binPath: string
+      if conf.outFile.len > 0:
+        # If the user specified an outFile path, use that directly.
+        binPath = conf.outFile.prependCurDir
+      else:
+        # Figure out ourselves a valid binary name.
+        binPath = changeFileExt(conf.projectFull, ExeExt).prependCurDir
+      var ex = quoteShell(binPath)
+      execExternalProgram(conf, ex & ' ' & conf.arguments)
 
 when declared(GC_setMaxPause):
   GC_setMaxPause 2_000
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim
index 96b9a3841..5f6889a6f 100644
--- a/compiler/nimconf.nim
+++ b/compiler/nimconf.nim
@@ -219,10 +219,10 @@ proc readConfigFile(
     closeLexer(L)
     return true
 
-proc getUserConfigPath(filename: string): string =
+proc getUserConfigPath*(filename: string): string =
   result = joinPath([getConfigDir(), "nim", filename])
 
-proc getSystemConfigPath(conf: ConfigRef; filename: string): string =
+proc getSystemConfigPath*(conf: ConfigRef; filename: string): string =
   # try standard configuration file (installation did not distribute files
   # the UNIX way)
   let p = getPrefixDir(conf)
@@ -241,7 +241,7 @@ proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef) =
     if readConfigFile(configPath, cache, conf):
       add(configFiles, configPath)
 
-  if optSkipConfigFile notin conf.globalOptions:
+  if optSkipSystemConfigFile notin conf.globalOptions:
     readConfigFile(getSystemConfigPath(conf, cfg))
 
   if optSkipUserConfigFile notin conf.globalOptions:
@@ -263,4 +263,5 @@ proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef) =
       readConfigFile(projectConfig)
 
   for filename in configFiles:
+    # delayed to here so that `hintConf` is honored
     rawMessage(conf, hintConf, filename)
diff --git a/compiler/options.nim b/compiler/options.nim
index 04b14c65f..2a10aa9f8 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -54,10 +54,10 @@ type                          # please make sure we have under 32 options
     optGenMapping,            # generate a mapping file
     optRun,                   # run the compiled project
     optCheckNep1,             # check that the names adhere to NEP-1
-    optSkipConfigFile,        # skip the general config file
-    optSkipProjConfigFile,    # skip the project's config file
-    optSkipUserConfigFile,    # skip the users's config file
-    optSkipParentConfigFiles, # skip parent dir's config files
+    optSkipSystemConfigFile,  # skip the system's cfg/nims config file
+    optSkipProjConfigFile,    # skip the project's cfg/nims config file
+    optSkipUserConfigFile,    # skip the users's cfg/nims config file
+    optSkipParentConfigFiles, # skip parent dir's cfg/nims config files
     optNoMain,                # do not generate a "main" proc
     optUseColors,             # use colors for hints, warnings, and errors
     optThreads,               # support for multi-threading
@@ -391,6 +391,7 @@ const
   TexExt* = "tex"
   IniExt* = "ini"
   DefaultConfig* = "nim.cfg"
+  DefaultConfigNims* = "config.nims"
   DocConfig* = "nimdoc.cfg"
   DocTexConfig* = "nimdoc.tex.cfg"
 
diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim
index 659206a40..184b60733 100644
--- a/compiler/scriptconfig.nim
+++ b/compiler/scriptconfig.nim
@@ -171,7 +171,7 @@ proc runNimScript*(cache: IdentCache; scriptName: string;
   incl(m.flags, sfMainModule)
   graph.vm = setupVM(m, cache, scriptName, graph)
 
-  graph.compileSystemModule()
+  graph.compileSystemModule() # TODO: see why this unsets hintConf in conf.notes
   discard graph.processModule(m, llStreamOpen(scriptName, fmRead))
 
   # ensure we load 'system.nim' again for the real non-config stuff!