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
This commit is contained in:
Timothee Cour 2018-08-30 04:52:32 -07:00 • committed by Andreas Rumpf
commit ed0cb7b85d
7 changed files with 152 additions and 114 deletions

View file

@ -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

View file

@ -651,7 +651,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
else: localError(conf, info, "invalid option for --symbolFiles: " & arg) else: localError(conf, info, "invalid option for --symbolFiles: " & arg)
of "skipcfg": of "skipcfg":
expectNoArg(conf, switch, arg, pass, info) expectNoArg(conf, switch, arg, pass, info)
incl(conf.globalOptions, optSkipConfigFile) incl(conf.globalOptions, optSkipSystemConfigFile)
of "skipprojcfg": of "skipprojcfg":
expectNoArg(conf, switch, arg, pass, info) expectNoArg(conf, switch, arg, pass, info)
incl(conf.globalOptions, optSkipProjConfigFile) incl(conf.globalOptions, optSkipProjConfigFile)

View file

@ -21,7 +21,7 @@ when defined(i386) and defined(windows) and defined(vcc):
import import
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes, commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
extccomp, strutils, os, osproc, platform, main, parseopt, extccomp, strutils, os, osproc, platform, main, parseopt,
nodejs, scriptconfig, idents, modulegraphs, lineinfos nodejs, scriptconfig, idents, modulegraphs, lineinfos, cmdlinehelper
when hasTinyCBackend: when hasTinyCBackend:
import tccgen import tccgen
@ -57,47 +57,21 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
rawMessage(config, errGenerated, errArgsNeedRunOption) rawMessage(config, errGenerated, errArgsNeedRunOption)
proc handleCmdLine(cache: IdentCache; conf: ConfigRef) = 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: if paramCount() == 0:
writeCommandLineUsage(conf, conf.helpWritten) writeCommandLineUsage(conf, conf.helpWritten)
else: return
# Process command line arguments:
processCmdLine(passCmd1, "", conf) self.processCmdLineAndProjectPath(conf)
if conf.projectName == "-": if not self.loadConfigsAndRunMainCommand(cache, conf): return
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())
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()) if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
#echo(GC_getStatistics()) #echo(GC_getStatistics())
if conf.errorCounter == 0: if conf.errorCounter != 0: return
when hasTinyCBackend: when hasTinyCBackend:
if conf.cmd == cmdRun: if conf.cmd == cmdRun:
tccgen.run(conf.arguments) tccgen.run(conf.arguments)

View file

@ -219,10 +219,10 @@ proc readConfigFile(
closeLexer(L) closeLexer(L)
return true return true
proc getUserConfigPath(filename: string): string = proc getUserConfigPath*(filename: string): string =
result = joinPath([getConfigDir(), "nim", filename]) 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 # try standard configuration file (installation did not distribute files
# the UNIX way) # the UNIX way)
let p = getPrefixDir(conf) let p = getPrefixDir(conf)
@ -241,7 +241,7 @@ proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef) =
if readConfigFile(configPath, cache, conf): if readConfigFile(configPath, cache, conf):
add(configFiles, configPath) add(configFiles, configPath)
if optSkipConfigFile notin conf.globalOptions: if optSkipSystemConfigFile notin conf.globalOptions:
readConfigFile(getSystemConfigPath(conf, cfg)) readConfigFile(getSystemConfigPath(conf, cfg))
if optSkipUserConfigFile notin conf.globalOptions: if optSkipUserConfigFile notin conf.globalOptions:
@ -263,4 +263,5 @@ proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef) =
readConfigFile(projectConfig) readConfigFile(projectConfig)
for filename in configFiles: for filename in configFiles:
# delayed to here so that `hintConf` is honored
rawMessage(conf, hintConf, filename) rawMessage(conf, hintConf, filename)

View file

@ -54,10 +54,10 @@ type # please make sure we have under 32 options
optGenMapping, # generate a mapping file optGenMapping, # generate a mapping file
optRun, # run the compiled project optRun, # run the compiled project
optCheckNep1, # check that the names adhere to NEP-1 optCheckNep1, # check that the names adhere to NEP-1
optSkipConfigFile, # skip the general config file optSkipSystemConfigFile, # skip the system's cfg/nims config file
optSkipProjConfigFile, # skip the project's config file optSkipProjConfigFile, # skip the project's cfg/nims config file
optSkipUserConfigFile, # skip the users's config file optSkipUserConfigFile, # skip the users's cfg/nims config file
optSkipParentConfigFiles, # skip parent dir's config files optSkipParentConfigFiles, # skip parent dir's cfg/nims config files
optNoMain, # do not generate a "main" proc optNoMain, # do not generate a "main" proc
optUseColors, # use colors for hints, warnings, and errors optUseColors, # use colors for hints, warnings, and errors
optThreads, # support for multi-threading optThreads, # support for multi-threading
@ -391,6 +391,7 @@ const
TexExt* = "tex" TexExt* = "tex"
IniExt* = "ini" IniExt* = "ini"
DefaultConfig* = "nim.cfg" DefaultConfig* = "nim.cfg"
DefaultConfigNims* = "config.nims"
DocConfig* = "nimdoc.cfg" DocConfig* = "nimdoc.cfg"
DocTexConfig* = "nimdoc.tex.cfg" DocTexConfig* = "nimdoc.tex.cfg"

View file

@ -171,7 +171,7 @@ proc runNimScript*(cache: IdentCache; scriptName: string;
incl(m.flags, sfMainModule) incl(m.flags, sfMainModule)
graph.vm = setupVM(m, cache, scriptName, graph) 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)) discard graph.processModule(m, llStreamOpen(scriptName, fmRead))
# ensure we load 'system.nim' again for the real non-config stuff! # ensure we load 'system.nim' again for the real non-config stuff!

View file

@ -20,7 +20,7 @@ import compiler / [options, commands, modules, sem,
passes, passaux, msgs, nimconf, passes, passaux, msgs, nimconf,
extccomp, condsyms, extccomp, condsyms,
sigmatch, ast, scriptconfig, sigmatch, ast, scriptconfig,
idents, modulegraphs, vm, prefixmatches, lineinfos] idents, modulegraphs, vm, prefixmatches, lineinfos, cmdlinehelper]
when defined(windows): when defined(windows):
import winlean import winlean
@ -582,26 +582,21 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) =
# if processArgument(pass, p, argsCount): break # if processArgument(pass, p, argsCount): break
proc handleCmdLine(cache: IdentCache; conf: ConfigRef) = proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
condsyms.initDefines(conf.symbols) let self = NimProg(
defineSymbol conf.symbols, "nimsuggest" suggestMode: true,
processCmdLine: processCmdLine,
mainCommand: mainCommand
)
self.initDefinesProg(conf, "nimsuggest")
if paramCount() == 0: if paramCount() == 0:
stdout.writeline(Usage) stdout.writeline(Usage)
else: return
processCmdLine(passCmd1, "", conf)
self.processCmdLineAndProjectPath(conf)
if gMode != mstdin: if gMode != mstdin:
conf.writelnHook = proc (msg: string) = discard conf.writelnHook = proc (msg: string) = discard
if conf.projectName != "":
try:
conf.projectFull = canonicalizePath(conf, conf.projectName)
except OSError:
conf.projectFull = conf.projectName
var p = splitFile(conf.projectFull)
conf.projectPath = canonicalizePath(conf, p.dir)
conf.projectName = p.name
else:
conf.projectPath = canonicalizePath(conf, getCurrentDir())
# Find Nim's prefix dir. # Find Nim's prefix dir.
let binaryPath = findExe("nim") let binaryPath = findExe("nim")
if binaryPath == "": if binaryPath == "":
@ -613,24 +608,6 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
#msgs.writelnHook = proc (line: string) = log(line) #msgs.writelnHook = proc (line: string) = log(line)
myLog("START " & conf.projectFull) myLog("START " & conf.projectFull)
loadConfigs(DefaultConfig, cache, conf) # load all config files discard self.loadConfigsAndRunMainCommand(cache, conf)
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
conf.command = "nimsuggest"
let scriptFile = conf.projectFull.changeFileExt("nims")
if fileExists(scriptFile):
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file:
if scriptFile != conf.projectFull:
runNimScript(cache, scriptFile, freshDefines=false, conf)
elif fileExists(conf.projectPath / "config.nims"):
# directory wide NimScript file
runNimScript(cache, conf.projectPath / "config.nims", freshDefines=false, conf)
extccomp.initVars(conf)
processCmdLine(passCmd2, "", conf)
let graph = newModuleGraph(cache, conf)
graph.suggestMode = true
mainCommand(graph)
handleCmdline(newIdentCache(), newConfigRef()) handleCmdline(newIdentCache(), newConfigRef())