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:
parent
01211ced1d
commit
ed0cb7b85d
7 changed files with 152 additions and 114 deletions
85
compiler/cmdlinehelper.nim
Normal file
85
compiler/cmdlinehelper.nim
Normal 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
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,69 +57,43 @@ 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"
|
if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
|
||||||
conf.projectFull = "stdinfile"
|
#echo(GC_getStatistics())
|
||||||
conf.projectPath = canonicalizePath(conf, getCurrentDir())
|
if conf.errorCounter != 0: return
|
||||||
conf.projectIsStdin = true
|
when hasTinyCBackend:
|
||||||
elif conf.projectName != "":
|
if conf.cmd == cmdRun:
|
||||||
try:
|
tccgen.run(conf.arguments)
|
||||||
conf.projectFull = canonicalizePath(conf, conf.projectName)
|
if optRun in conf.globalOptions:
|
||||||
except OSError:
|
if conf.cmd == cmdCompileToJS:
|
||||||
conf.projectFull = conf.projectName
|
var ex: string
|
||||||
let p = splitFile(conf.projectFull)
|
if conf.outFile.len > 0:
|
||||||
let dir = if p.dir.len > 0: p.dir else: getCurrentDir()
|
ex = conf.outFile.prependCurDir.quoteShell
|
||||||
conf.projectPath = canonicalizePath(conf, dir)
|
else:
|
||||||
conf.projectName = p.name
|
ex = quoteShell(
|
||||||
|
completeCFilePath(conf, changeFileExt(conf.projectFull, "js").prependCurDir))
|
||||||
|
execExternalProgram(conf, findNodeJs() & " " & ex & ' ' & conf.arguments)
|
||||||
else:
|
else:
|
||||||
conf.projectPath = canonicalizePath(conf, getCurrentDir())
|
var binPath: string
|
||||||
loadConfigs(DefaultConfig, cache, conf) # load all config files
|
if conf.outFile.len > 0:
|
||||||
let scriptFile = conf.projectFull.changeFileExt("nims")
|
# If the user specified an outFile path, use that directly.
|
||||||
if fileExists(scriptFile):
|
binPath = conf.outFile.prependCurDir
|
||||||
runNimScript(cache, scriptFile, freshDefines=false, conf)
|
else:
|
||||||
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
|
# Figure out ourselves a valid binary name.
|
||||||
if scriptFile == conf.projectFull: return
|
binPath = changeFileExt(conf.projectFull, ExeExt).prependCurDir
|
||||||
elif fileExists(conf.projectPath / "config.nims"):
|
var ex = quoteShell(binPath)
|
||||||
# directory wide NimScript file
|
execExternalProgram(conf, ex & ' ' & conf.arguments)
|
||||||
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)
|
|
||||||
|
|
||||||
when declared(GC_setMaxPause):
|
when declared(GC_setMaxPause):
|
||||||
GC_setMaxPause 2_000
|
GC_setMaxPause 2_000
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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!
|
||||||
|
|
|
||||||
|
|
@ -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,55 +582,32 @@ 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)
|
|
||||||
if gMode != mstdin:
|
|
||||||
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.
|
self.processCmdLineAndProjectPath(conf)
|
||||||
let binaryPath = findExe("nim")
|
|
||||||
if binaryPath == "":
|
|
||||||
raise newException(IOError,
|
|
||||||
"Cannot find Nim standard library: Nim compiler not in PATH")
|
|
||||||
conf.prefixDir = binaryPath.splitPath().head.parentDir()
|
|
||||||
if not dirExists(conf.prefixDir / "lib"): conf.prefixDir = ""
|
|
||||||
|
|
||||||
#msgs.writelnHook = proc (line: string) = log(line)
|
if gMode != mstdin:
|
||||||
myLog("START " & conf.projectFull)
|
conf.writelnHook = proc (msg: string) = discard
|
||||||
|
# Find Nim's prefix dir.
|
||||||
|
let binaryPath = findExe("nim")
|
||||||
|
if binaryPath == "":
|
||||||
|
raise newException(IOError,
|
||||||
|
"Cannot find Nim standard library: Nim compiler not in PATH")
|
||||||
|
conf.prefixDir = binaryPath.splitPath().head.parentDir()
|
||||||
|
if not dirExists(conf.prefixDir / "lib"): conf.prefixDir = ""
|
||||||
|
|
||||||
loadConfigs(DefaultConfig, cache, conf) # load all config files
|
#msgs.writelnHook = proc (line: string) = log(line)
|
||||||
# now process command line arguments again, because some options in the
|
myLog("START " & conf.projectFull)
|
||||||
# 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)
|
discard self.loadConfigsAndRunMainCommand(cache, conf)
|
||||||
processCmdLine(passCmd2, "", conf)
|
|
||||||
|
|
||||||
let graph = newModuleGraph(cache, conf)
|
|
||||||
graph.suggestMode = true
|
|
||||||
mainCommand(graph)
|
|
||||||
|
|
||||||
handleCmdline(newIdentCache(), newConfigRef())
|
handleCmdline(newIdentCache(), newConfigRef())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue