Prompt for multiple selections interactively when possible (#441)
* Add interactive selection ability and preserve old behavior if not available * Add description of library and binary packages * Add function origin to doc * Fix typos and windows compilation test * Change select message type and fix style * Change to use TAB to cycle through options
This commit is contained in:
parent
57f73ea268
commit
a3a60eca51
2 changed files with 79 additions and 9 deletions
|
|
@ -757,7 +757,9 @@ proc init(options: Options) =
|
|||
priority = HighPriority)
|
||||
|
||||
# Determine the type of package
|
||||
let pkgType = promptList(options, "Package type?", [
|
||||
let pkgType = promptList(options, """Package type?
|
||||
Library packages provide functionality for other packages.
|
||||
Binary packages produce executables.""", [
|
||||
"lib",
|
||||
"bin",
|
||||
])
|
||||
|
|
|
|||
|
|
@ -12,7 +12,10 @@
|
|||
# - Bright for HighPriority.
|
||||
# - Normal for MediumPriority.
|
||||
|
||||
import logging, terminal, sets, strutils
|
||||
import logging, terminal, sets, strutils, os
|
||||
|
||||
when defined(windows):
|
||||
import winlean
|
||||
|
||||
type
|
||||
CLI* = ref object
|
||||
|
|
@ -169,6 +172,74 @@ proc promptCustom*(forcePrompts: ForcePrompt, question, default: string): string
|
|||
proc promptCustom*(question, default: string): string =
|
||||
return promptCustom(dontForcePrompt, question, default)
|
||||
|
||||
proc promptListInteractive(question: string, args: openarray[string]): string =
|
||||
display("Prompt:", question, Warning, HighPriority)
|
||||
display("Select", "Cycle with 'Tab', 'Enter' when done", Message,
|
||||
HighPriority)
|
||||
displayCategory("Choices:", Warning, HighPriority)
|
||||
var
|
||||
current = 0
|
||||
selected = false
|
||||
# Incase the cursor is at the bottom of the terminal
|
||||
for arg in args:
|
||||
stdout.write "\n"
|
||||
# Reset the cursor to the start of the selection prompt
|
||||
cursorUp(stdout, args.len)
|
||||
cursorForward(stdout, longestCategory)
|
||||
hideCursor(stdout)
|
||||
|
||||
# The selection loop
|
||||
while not selected:
|
||||
# Loop through the options
|
||||
for i, arg in args:
|
||||
# Check if the option is the current
|
||||
if i == current:
|
||||
setForegroundColor(fgWhite)
|
||||
writeStyled(" " & arg, {styleBright})
|
||||
else:
|
||||
setForegroundColor(fgWhite)
|
||||
writeStyled(" " & arg, {styleDim})
|
||||
# Move the cursor back to the start
|
||||
for s in 0..<(arg.len + 1):
|
||||
cursorBackward(stdout)
|
||||
# Move down for the next item
|
||||
cursorDown(stdout)
|
||||
# Move the cursor back up to the start of the selection prompt
|
||||
for i in 0..<(args.len()):
|
||||
cursorUp(stdout)
|
||||
resetAttributes(stdout)
|
||||
|
||||
# Begin key input
|
||||
while true:
|
||||
case getch():
|
||||
of '\t':
|
||||
current = (current + 1) mod args.len
|
||||
break
|
||||
of '\r':
|
||||
selected = true
|
||||
break
|
||||
else: discard
|
||||
|
||||
# Erase all lines of the selection
|
||||
for i in 0..<args.len:
|
||||
eraseLine(stdout)
|
||||
cursorDown(stdout)
|
||||
# Move the cursor back up to the initial selection line
|
||||
for i in 0..<args.len():
|
||||
cursorUp(stdout)
|
||||
showCursor(stdout)
|
||||
display("Answer:", args[current], Warning,HighPriority)
|
||||
return args[current]
|
||||
|
||||
proc promptListFallback(question: string, args: openarray[string]): string =
|
||||
display("Prompt:", question & " [" & join(args, "/") & "]", Warning,
|
||||
HighPriority)
|
||||
displayCategory("Answer:", Warning, HighPriority)
|
||||
result = stdin.readLine()
|
||||
for arg in args:
|
||||
if arg.cmpIgnoreCase(result) == 0:
|
||||
return arg
|
||||
|
||||
proc promptList*(forcePrompts: ForcePrompt, question: string, args: openarray[string]): string =
|
||||
case forcePrompts:
|
||||
of forcePromptYes:
|
||||
|
|
@ -176,13 +247,10 @@ proc promptList*(forcePrompts: ForcePrompt, question: string, args: openarray[st
|
|||
display("Prompt:", question & " -> [forced " & result & "]", Warning,
|
||||
HighPriority)
|
||||
else:
|
||||
display("Prompt:", question & " [" & join(args, "/") & "]", Warning, HighPriority)
|
||||
displayCategory("Answer:", Warning, HighPriority)
|
||||
result = stdin.readLine()
|
||||
for arg in args:
|
||||
if arg.cmpIgnoreCase(result) == 0:
|
||||
return arg
|
||||
return promptList(forcePrompts, question, args)
|
||||
if isatty(stdout):
|
||||
return promptListInteractive(question, args)
|
||||
else:
|
||||
return promptListFallback(question, args)
|
||||
|
||||
proc setVerbosity*(level: Priority) =
|
||||
globalCLI.level = level
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue