* Reuse -y to mean accept defaults for init command * Change cli.promptCustom to accept a ForcePrompt value and delegate prompting responsiblity to it * Add prompt for different license selection * Remove extra spaces in category in promptCustom and promptList * Fix bug that always returned MIT * Add LGPL3 to array of licenses * Change to not prompt at all for package name * Change to not prompt for author if acquired from vcs and moved before prompting for version * Reduce excess indenting * Create tools.writeContents to contain file writting functionality and use it to write the nimble file * Create package src directory and add it to the nimble file * Write an initial source file * Create directory and files needed for testing * Add package created message and change priority of nimble file creation * Rearrange args for promptCustom and add another promptCustom function that doesn't accept ForcePrompt * Add package type prompt, remove writeContents proc, rename initial test file, provide alternate initial file contents based on type, and other minor improvements
This commit is contained in:
parent
f852198724
commit
4cc1d44bdd
4 changed files with 185 additions and 52 deletions
167
src/nimble.nim
167
src/nimble.nim
|
|
@ -693,73 +693,168 @@ proc dump(options: Options) =
|
||||||
proc init(options: Options) =
|
proc init(options: Options) =
|
||||||
var nimbleFile: string = ""
|
var nimbleFile: string = ""
|
||||||
|
|
||||||
display("Info:",
|
if options.forcePrompts != forcePromptYes:
|
||||||
"In order to initialise a new Nimble package, I will need to ask you\n" &
|
display("Info:",
|
||||||
"some questions. Default values are shown in square brackets, press\n" &
|
"In order to initialise a new Nimble package, I will need to ask you\n" &
|
||||||
"enter to use them.", priority = HighPriority)
|
"some questions. Default values are shown in square brackets, press\n" &
|
||||||
|
"enter to use them.", priority = HighPriority)
|
||||||
|
|
||||||
# Ask for package name.
|
# Ask for package name.
|
||||||
if options.action.projName != "":
|
let pkgName =
|
||||||
let pkgName = options.action.projName
|
if options.action.projName != "":
|
||||||
nimbleFile = pkgName.changeFileExt("nimble")
|
options.action.projName
|
||||||
else:
|
else:
|
||||||
var pkgName = os.getCurrentDir().splitPath.tail.toValidPackageName()
|
os.getCurrentDir().splitPath.tail.toValidPackageName()
|
||||||
pkgName = promptCustom("Package name?", pkgName)
|
|
||||||
nimbleFile = pkgName.changeFileExt("nimble")
|
|
||||||
|
|
||||||
|
nimbleFile = pkgName.changeFileExt("nimble")
|
||||||
validatePackageName(nimbleFile.changeFileExt(""))
|
validatePackageName(nimbleFile.changeFileExt(""))
|
||||||
|
|
||||||
if existsFile(os.getCurrentDir() / nimbleFile):
|
if existsFile(os.getCurrentDir() / nimbleFile):
|
||||||
raise newException(NimbleError, "Nimble file already exists.")
|
raise newException(NimbleError, "Nimble file already exists.")
|
||||||
|
|
||||||
# Ask for package version.
|
display("Using", "$# for new package name" % [pkgName.escape()],
|
||||||
let pkgVersion = promptCustom("Initial version of package?", "0.1.0")
|
priority = HighPriority)
|
||||||
validateVersion(pkgVersion)
|
|
||||||
|
|
||||||
# Ask for package author
|
# Ask for package author
|
||||||
var defaultAuthor = "Anonymous"
|
proc getAuthor(): string =
|
||||||
if findExe("git") != "":
|
if findExe("git") != "":
|
||||||
let (name, exitCode) = doCmdEx("git config --global user.name")
|
let (name, exitCode) = doCmdEx("git config --global user.name")
|
||||||
if exitCode == QuitSuccess and name.len > 0:
|
if exitCode == QuitSuccess and name.len > 0:
|
||||||
defaultAuthor = name.strip()
|
result = name.strip()
|
||||||
elif defaultAuthor == "Anonymous" and findExe("hg") != "":
|
display("Using", "$# for new package author" % [result.escape()],
|
||||||
let (name, exitCode) = doCmdEx("hg config ui.username")
|
priority = HighPriority)
|
||||||
if exitCode == QuitSuccess and name.len > 0:
|
elif findExe("hg") != "":
|
||||||
defaultAuthor = name.strip()
|
let (name, exitCode) = doCmdEx("hg config ui.username")
|
||||||
let pkgAuthor = promptCustom("Your name?", defaultAuthor)
|
if exitCode == QuitSuccess and name.len > 0:
|
||||||
|
result = name.strip()
|
||||||
|
display("Using", "$# for new package author" % [result.escape()],
|
||||||
|
priority = HighPriority)
|
||||||
|
else:
|
||||||
|
result = promptCustom(options, "Your name?", "Anonymous")
|
||||||
|
let pkgAuthor = getAuthor()
|
||||||
|
|
||||||
|
# Declare the src/ directory
|
||||||
|
let pkgSrcDir = "src"
|
||||||
|
display("Using", "$# for new package source directory" % [pkgSrcDir.escape()],
|
||||||
|
priority = HighPriority)
|
||||||
|
|
||||||
|
# Determine the type of package
|
||||||
|
let pkgType = promptList(options, "Package type?", [
|
||||||
|
"lib",
|
||||||
|
"bin",
|
||||||
|
])
|
||||||
|
|
||||||
|
# Ask for package version.
|
||||||
|
let pkgVersion = promptCustom(options, "Initial version of package?", "0.1.0")
|
||||||
|
validateVersion(pkgVersion)
|
||||||
|
|
||||||
# Ask for description
|
# Ask for description
|
||||||
let pkgDesc = promptCustom("Package description?", "")
|
let pkgDesc = promptCustom(options, "Package description?",
|
||||||
|
"A new awesome nimble package")
|
||||||
|
|
||||||
# Ask for license
|
# Ask for license
|
||||||
# TODO: Provide selection of licenses, or select random default license.
|
let pkgLicense = options.promptList("Package License?", [
|
||||||
let pkgLicense = promptCustom("Package license?", "MIT")
|
"MIT",
|
||||||
|
"BSD2",
|
||||||
|
"GPLv3",
|
||||||
|
"LGPLv3",
|
||||||
|
"Apache2",
|
||||||
|
])
|
||||||
|
|
||||||
# Ask for Nim dependency
|
# Ask for Nim dependency
|
||||||
let nimDepDef = getNimrodVersion()
|
let nimDepDef = getNimrodVersion()
|
||||||
let pkgNimDep = promptCustom("Lowest supported Nim version?", $nimDepDef)
|
let pkgNimDep = promptCustom(options, "Lowest supported Nim version?",
|
||||||
|
$nimDepDef)
|
||||||
validateVersion(pkgNimDep)
|
validateVersion(pkgNimDep)
|
||||||
|
|
||||||
var outFile: File
|
let pkgTestDir = "tests"
|
||||||
if open(f = outFile, filename = nimbleFile, mode = fmWrite):
|
|
||||||
outFile.writeLine """# Package
|
# Create source directory
|
||||||
|
os.createDir(pkgSrcDir)
|
||||||
|
|
||||||
|
display("Success:", "Source directory created successfully", Success,
|
||||||
|
MediumPriority)
|
||||||
|
|
||||||
|
# Create initial source file
|
||||||
|
cd pkgSrcDir:
|
||||||
|
let pkgFile = pkgName.changeFileExt("nim")
|
||||||
|
try:
|
||||||
|
if pkgType == "bin":
|
||||||
|
pkgFile.writeFile "# Hello Nim!\necho \"Hello, World!\"\n"
|
||||||
|
else:
|
||||||
|
pkgFile.writeFile """# $#
|
||||||
|
# Copyright $#
|
||||||
|
# $#
|
||||||
|
""" % [pkgName, pkgAuthor, pkgDesc]
|
||||||
|
display("Success:", "Created initial source file successfully", Success,
|
||||||
|
MediumPriority)
|
||||||
|
except:
|
||||||
|
raise newException(NimbleError, "Unable to open file " & pkgFile &
|
||||||
|
" for writing: " & osErrorMsg(osLastError()))
|
||||||
|
|
||||||
|
# Create test directory
|
||||||
|
os.createDir(pkgTestDir)
|
||||||
|
|
||||||
|
display("Success:", "Test directory created successfully", Success,
|
||||||
|
MediumPriority)
|
||||||
|
|
||||||
|
cd pkgTestDir:
|
||||||
|
try:
|
||||||
|
"test1.nims".writeFile("""switch("path", "$$projectDir/../$#")""" %
|
||||||
|
[pkgSrcDir])
|
||||||
|
display("Success:", "Test config file created successfully", Success,
|
||||||
|
MediumPriority)
|
||||||
|
except:
|
||||||
|
raise newException(NimbleError, "Unable to open file " & "test1.nims" &
|
||||||
|
" for writing: " & osErrorMsg(osLastError()))
|
||||||
|
try:
|
||||||
|
"test1.nim".writeFile("doAssert(1 + 1 == 2)\n")
|
||||||
|
display("Success:", "Test file created successfully", Success,
|
||||||
|
MediumPriority)
|
||||||
|
except:
|
||||||
|
raise newException(NimbleError, "Unable to open file " & "test1.nim" &
|
||||||
|
" for writing: " & osErrorMsg(osLastError()))
|
||||||
|
|
||||||
|
# Write the nimble file
|
||||||
|
try:
|
||||||
|
if pkgType == "lib":
|
||||||
|
nimbleFile.writeFile """# Package
|
||||||
|
|
||||||
version = $#
|
version = $#
|
||||||
author = $#
|
author = $#
|
||||||
description = $#
|
description = $#
|
||||||
license = $#
|
license = $#
|
||||||
|
srcDir = $#
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
requires "nim >= $#"
|
requires "nim >= $#"
|
||||||
""" % [pkgVersion.escape(), pkgAuthor.escape(), pkgDesc.escape(),
|
""" % [pkgVersion.escape(), pkgAuthor.escape(), pkgDesc.escape(),
|
||||||
pkgLicense.escape(), pkgNimDep]
|
pkgLicense.escape(), pkgSrcDir.escape(), pkgNimDep]
|
||||||
close(outFile)
|
else:
|
||||||
else:
|
nimbleFile.writeFile """# Package
|
||||||
raise newException(NimbleError, "Unable to open file " & nimbleFile &
|
|
||||||
|
version = $#
|
||||||
|
author = $#
|
||||||
|
description = $#
|
||||||
|
license = $#
|
||||||
|
srcDir = $#
|
||||||
|
bin = @[$#]
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= $#"
|
||||||
|
""" % [pkgVersion.escape(), pkgAuthor.escape(), pkgDesc.escape(),
|
||||||
|
pkgLicense.escape(), pkgSrcDir.escape(), pkgName.escape(), pkgNimDep]
|
||||||
|
except:
|
||||||
|
raise newException(NimbleError, "Unable to open file " & "test1.nim" &
|
||||||
" for writing: " & osErrorMsg(osLastError()))
|
" for writing: " & osErrorMsg(osLastError()))
|
||||||
|
|
||||||
display("Success:", "Nimble file created successfully", Success, HighPriority)
|
display("Success:", "Nimble file created successfully", Success,
|
||||||
|
MediumPriority)
|
||||||
|
|
||||||
|
display("Success:", "Package $# created successfully" % [pkgName], Success,
|
||||||
|
HighPriority)
|
||||||
|
|
||||||
proc uninstall(options: Options) =
|
proc uninstall(options: Options) =
|
||||||
if options.action.packages.len == 0:
|
if options.action.packages.len == 0:
|
||||||
|
|
|
||||||
|
|
@ -146,19 +146,43 @@ proc prompt*(forcePrompts: ForcePrompt, question: string): bool =
|
||||||
else:
|
else:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc promptCustom*(question, default: string): string =
|
proc promptCustom*(forcePrompts: ForcePrompt, question, default: string): string =
|
||||||
if default == "":
|
case forcePrompts:
|
||||||
display("Prompt:", question, Warning, HighPriority)
|
of forcePromptYes:
|
||||||
displayCategory("Answer:", Warning, HighPriority)
|
display("Prompt:", question & " -> [forced " & default & "]", Warning,
|
||||||
let user = stdin.readLine()
|
HighPriority)
|
||||||
if user.len == 0: return promptCustom(question, default)
|
return default
|
||||||
else: return user
|
|
||||||
else:
|
else:
|
||||||
display("Prompt:", question & " [" & default & "]", Warning, HighPriority)
|
if default == "":
|
||||||
|
display("Prompt:", question, Warning, HighPriority)
|
||||||
|
displayCategory("Answer:", Warning, HighPriority)
|
||||||
|
let user = stdin.readLine()
|
||||||
|
if user.len == 0: return promptCustom(forcePrompts, question, default)
|
||||||
|
else: return user
|
||||||
|
else:
|
||||||
|
display("Prompt:", question & " [" & default & "]", Warning, HighPriority)
|
||||||
|
displayCategory("Answer:", Warning, HighPriority)
|
||||||
|
let user = stdin.readLine()
|
||||||
|
if user == "": return default
|
||||||
|
else: return user
|
||||||
|
|
||||||
|
proc promptCustom*(question, default: string): string =
|
||||||
|
return promptCustom(dontForcePrompt, question, default)
|
||||||
|
|
||||||
|
proc promptList*(forcePrompts: ForcePrompt, question: string, args: openarray[string]): string =
|
||||||
|
case forcePrompts:
|
||||||
|
of forcePromptYes:
|
||||||
|
result = args[0]
|
||||||
|
display("Prompt:", question & " -> [forced " & result & "]", Warning,
|
||||||
|
HighPriority)
|
||||||
|
else:
|
||||||
|
display("Prompt:", question & " [" & join(args, "/") & "]", Warning, HighPriority)
|
||||||
displayCategory("Answer:", Warning, HighPriority)
|
displayCategory("Answer:", Warning, HighPriority)
|
||||||
let user = stdin.readLine()
|
result = stdin.readLine()
|
||||||
if user == "": return default
|
for arg in args:
|
||||||
else: return user
|
if arg.cmpIgnoreCase(result) == 0:
|
||||||
|
return arg
|
||||||
|
return promptList(forcePrompts, question, args)
|
||||||
|
|
||||||
proc setVerbosity*(level: Priority) =
|
proc setVerbosity*(level: Priority) =
|
||||||
globalCLI.level = level
|
globalCLI.level = level
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,20 @@ proc prompt*(options: Options, question: string): bool =
|
||||||
## forcePrompts has a value different than dontForcePrompt.
|
## forcePrompts has a value different than dontForcePrompt.
|
||||||
return prompt(options.forcePrompts, question)
|
return prompt(options.forcePrompts, question)
|
||||||
|
|
||||||
|
proc promptCustom*(options: Options, question, default: string): string =
|
||||||
|
## Asks an interactive question and returns the result.
|
||||||
|
##
|
||||||
|
## The proc will return "default" without asking the user if the global
|
||||||
|
## forcePrompts is forcePromptYes.
|
||||||
|
return promptCustom(options.forcePrompts, question, default)
|
||||||
|
|
||||||
|
proc promptList*(options: Options, question: string, args: openarray[string]): string =
|
||||||
|
## Asks an interactive question and returns the result.
|
||||||
|
##
|
||||||
|
## The proc will return one of the provided args. If not prompting the first
|
||||||
|
## options is selected.
|
||||||
|
return promptList(options.forcePrompts, question, args)
|
||||||
|
|
||||||
proc renameBabelToNimble(options: Options) {.deprecated.} =
|
proc renameBabelToNimble(options: Options) {.deprecated.} =
|
||||||
let babelDir = getHomeDir() / ".babel"
|
let babelDir = getHomeDir() / ".babel"
|
||||||
let nimbleDir = getHomeDir() / ".nimble"
|
let nimbleDir = getHomeDir() / ".nimble"
|
||||||
|
|
@ -384,4 +398,4 @@ proc briefClone*(options: Options): Options =
|
||||||
newOptions.config = options.config
|
newOptions.config = options.config
|
||||||
newOptions.nimbleData = options.nimbleData
|
newOptions.nimbleData = options.nimbleData
|
||||||
newOptions.pkgInfoCache = options.pkgInfoCache
|
newOptions.pkgInfoCache = options.pkgInfoCache
|
||||||
return newOptions
|
return newOptions
|
||||||
|
|
|
||||||
|
|
@ -80,10 +80,10 @@ proc changeRoot*(origRoot, newRoot, path: string): string =
|
||||||
## path: /home/dom/bar/blah/2/foo.txt
|
## path: /home/dom/bar/blah/2/foo.txt
|
||||||
## Return value -> /home/test/bar/blah/2/foo.txt
|
## Return value -> /home/test/bar/blah/2/foo.txt
|
||||||
|
|
||||||
## The additional check of `path.samePaths(origRoot)` is necessary to prevent
|
## The additional check of `path.samePaths(origRoot)` is necessary to prevent
|
||||||
## a regression, where by ending the `srcDir` defintion in a nimble file in a
|
## a regression, where by ending the `srcDir` defintion in a nimble file in a
|
||||||
## trailing separator would cause the `path.startsWith(origRoot)` evaluation to
|
## trailing separator would cause the `path.startsWith(origRoot)` evaluation to
|
||||||
## fail because of the value of `origRoot` would be longer than `path` due to
|
## fail because of the value of `origRoot` would be longer than `path` due to
|
||||||
## the trailing separator. This would cause this method to throw during package
|
## the trailing separator. This would cause this method to throw during package
|
||||||
## installation.
|
## installation.
|
||||||
if path.startsWith(origRoot) or path.samePaths(origRoot):
|
if path.startsWith(origRoot) or path.samePaths(origRoot):
|
||||||
|
|
@ -157,4 +157,4 @@ proc getNimbleTempDir*(): string =
|
||||||
importc: "GetCurrentProcessId".}
|
importc: "GetCurrentProcessId".}
|
||||||
result.add($GetCurrentProcessId())
|
result.add($GetCurrentProcessId())
|
||||||
else:
|
else:
|
||||||
result.add($getpid())
|
result.add($getpid())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue