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)
|
priority = HighPriority)
|
||||||
|
|
||||||
# Determine the type of package
|
# 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",
|
"lib",
|
||||||
"bin",
|
"bin",
|
||||||
])
|
])
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,10 @@
|
||||||
# - Bright for HighPriority.
|
# - Bright for HighPriority.
|
||||||
# - Normal for MediumPriority.
|
# - Normal for MediumPriority.
|
||||||
|
|
||||||
import logging, terminal, sets, strutils
|
import logging, terminal, sets, strutils, os
|
||||||
|
|
||||||
|
when defined(windows):
|
||||||
|
import winlean
|
||||||
|
|
||||||
type
|
type
|
||||||
CLI* = ref object
|
CLI* = ref object
|
||||||
|
|
@ -169,6 +172,74 @@ proc promptCustom*(forcePrompts: ForcePrompt, question, default: string): string
|
||||||
proc promptCustom*(question, default: string): string =
|
proc promptCustom*(question, default: string): string =
|
||||||
return promptCustom(dontForcePrompt, question, default)
|
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 =
|
proc promptList*(forcePrompts: ForcePrompt, question: string, args: openarray[string]): string =
|
||||||
case forcePrompts:
|
case forcePrompts:
|
||||||
of forcePromptYes:
|
of forcePromptYes:
|
||||||
|
|
@ -176,13 +247,10 @@ proc promptList*(forcePrompts: ForcePrompt, question: string, args: openarray[st
|
||||||
display("Prompt:", question & " -> [forced " & result & "]", Warning,
|
display("Prompt:", question & " -> [forced " & result & "]", Warning,
|
||||||
HighPriority)
|
HighPriority)
|
||||||
else:
|
else:
|
||||||
display("Prompt:", question & " [" & join(args, "/") & "]", Warning, HighPriority)
|
if isatty(stdout):
|
||||||
displayCategory("Answer:", Warning, HighPriority)
|
return promptListInteractive(question, args)
|
||||||
result = stdin.readLine()
|
else:
|
||||||
for arg in args:
|
return promptListFallback(question, args)
|
||||||
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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue