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:
antizealot1337 2018-09-01 08:09:37 -04:00 committed by Dominik Picheta
commit a3a60eca51
2 changed files with 79 additions and 9 deletions

View file

@ -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",
])

View file

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