Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow setting default selections in TerminalMenus #30043

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions stdlib/REPL/src/TerminalMenus/AbstractMenu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ subtypes.

- `header(m::AbstractMenu)`
- `keypress(m::AbstractMenu, i::UInt32)`
- `cursorstart(m::AbstractMenu)`

"""
abstract type AbstractMenu end
Expand Down Expand Up @@ -108,6 +109,12 @@ If `true` is returned, `request()` will exit.
keypress(m::AbstractMenu, i::UInt32) = false


"""
cursorstart(m::AbstractMenu) -> Int

Compute the starting cursor position.
"""
cursorstart(m::AbstractMenu) = 1


"""
Expand All @@ -119,7 +126,7 @@ varies based on menu type.
request(m::AbstractMenu) = request(terminal, m)

function request(term::REPL.Terminals.TTYTerminal, m::AbstractMenu)
cursor = 1
cursor = cursorstart(m)

menu_header = header(m)
!CONFIG[:supress_output] && menu_header != "" && println(term.out_stream, menu_header)
Expand Down Expand Up @@ -234,7 +241,7 @@ function printMenu(out, m::AbstractMenu, cursor::Int; init::Bool=false)
lines = m.pagesize-1

if init
m.pageoffset = 0
m.pageoffset = min(max(cursor-m.pagesize+1, 0), length(options(m))-m.pagesize)
else
# Move the cursor to the beginning of where it should print
print(buf, "\x1b[999D\x1b[$(lines)A")
Expand Down
11 changes: 8 additions & 3 deletions stdlib/REPL/src/TerminalMenus/MultiSelectMenu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ end

"""

MultiSelectMenu(options::Array{String,1}; pagesize::Int=10)
MultiSelectMenu(options::Array{String,1}; pagesize::Int=10, default=Set{Int}())

Create a MultiSelectMenu object. Use `request(menu::MultiSelectMenu)` to get
user input. `request()` returns a `Set` containing the indices of options that
Expand All @@ -47,8 +47,9 @@ were selected by the user.

- `options::Array{String, 1}`: Options to be displayed
- `pagesize::Int=10`: The number of options to be displayed at one time, the menu will scroll if length(options) > pagesize
- `default=Set{Int}()`: The indices of options which are first selected, must be a collection of `Int`s
"""
function MultiSelectMenu(options::Array{String,1}; pagesize::Int=10)
function MultiSelectMenu(options::Array{String,1}; pagesize::Int=10, default=Int[])
length(options) < 2 && error("MultiSelectMenu must have at least two options")

# if pagesize is -1, use automatic paging
Expand All @@ -57,9 +58,13 @@ function MultiSelectMenu(options::Array{String,1}; pagesize::Int=10)
pagesize = min(length(options), pagesize)
# after other checks, pagesize must be greater than 2
pagesize < 2 && error("pagesize must be >= 2")
# defaults must be in the range of the options
if !all(d -> 0 < d <= length(options), default)
error("defaults must be > 0 and <= $(length(options))")
end

pageoffset = 0
selected = Set{Int}() # none
selected = Set{Int}(default)

MultiSelectMenu(options, pagesize, pageoffset, selected)
end
Expand Down
14 changes: 10 additions & 4 deletions stdlib/REPL/src/TerminalMenus/RadioMenu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ mutable struct RadioMenu <: AbstractMenu
pagesize::Int
pageoffset::Int
selected::Int
default::Int
end


"""

RadioMenu(options::Array{String,1}; pagesize::Int=10)
RadioMenu(options::Array{String,1}; pagesize::Int=10, default::Int=1)

Create a RadioMenu object. Use `request(menu::RadioMenu)` to get user input.
`request()` returns an `Int` which is the index of the option selected by the
Expand All @@ -39,8 +40,9 @@ user.

- `options::Array{String, 1}`: Options to be displayed
- `pagesize::Int=10`: The number of options to be displayed at one time, the menu will scroll if length(options) > pagesize
- `default::Int=1`: The index of the option which is first selected
"""
function RadioMenu(options::Array{String,1}; pagesize::Int=10)
function RadioMenu(options::Array{String,1}; pagesize::Int=10, default::Int=1)
length(options) < 2 && error("RadioMenu must have at least two options")

# if pagesize is -1, use automatic paging
Expand All @@ -49,11 +51,13 @@ function RadioMenu(options::Array{String,1}; pagesize::Int=10)
pagesize = min(length(options), pagesize)
# after other checks, pagesize must be greater than 2
pagesize < 2 && error("pagesize must be >= 2")
# default must be in the range of the options
0 < default <= length(options) || error("default must be > 0 and <= $(length(options))")

pageoffset = 0
selected = -1 # none

RadioMenu(options, pagesize, pageoffset, selected)
RadioMenu(options, pagesize, pageoffset, selected, default)
end


Expand All @@ -66,9 +70,11 @@ options(m::RadioMenu) = m.options

cancel(m::RadioMenu) = m.selected = -1

cursorstart(m::RadioMenu) = m.default

function pick(menu::RadioMenu, cursor::Int)
menu.selected = cursor
return true #break out of the menu
return true # break out of the menu
end

function writeLine(buf::IOBuffer, menu::RadioMenu, idx::Int, cursor::Bool)
Expand Down
5 changes: 4 additions & 1 deletion stdlib/REPL/test/TerminalMenus/multiselect_menu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
# Invalid Menu Params
@test_throws ErrorException MultiSelectMenu(["one"])
@test_throws ErrorException MultiSelectMenu(["one", "two", "three"], pagesize=1)
@test_throws ErrorException MultiSelectMenu(["one", "two", "three"], default=[0, 1, 2])
@test_throws ErrorException MultiSelectMenu(["one", "two", "three"], default=[2, 3, 4])

# Constructor
@test MultiSelectMenu(["one", "two", "three"]).pagesize == 3
@test MultiSelectMenu(string.(1:30), pagesize=-1).pagesize == 30
@test MultiSelectMenu(string.(1:4), pagesize=10).pagesize == 4
@test MultiSelectMenu(string.(1:100)).pagesize == 10

multi_menu = MultiSelectMenu(string.(1:20))
multi_menu = MultiSelectMenu(string.(1:20), default=[2, 4, 6])
@test multi_menu.selected == Set([2, 4, 6])
@test TerminalMenus.options(multi_menu) == string.(1:20)
@test TerminalMenus.header(multi_menu) == "[press: d=done, a=all, n=none]"

Expand Down
3 changes: 3 additions & 0 deletions stdlib/REPL/test/TerminalMenus/radio_menu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
# Invalid Menu Params
@test_throws ErrorException RadioMenu(["one"])
@test_throws ErrorException RadioMenu(["one", "two", "three"], pagesize=1)
@test_throws ErrorException RadioMenu(["one"], default=0)
@test_throws ErrorException RadioMenu(["one"], default=2)

# Constructor
@test RadioMenu(["one", "two", "three"]).pagesize == 3
@test RadioMenu(string.(1:30), pagesize=-1).pagesize == 30
@test RadioMenu(string.(1:4), pagesize=10).pagesize == 4
@test RadioMenu(string.(1:100)).pagesize == 10
@test RadioMenu(string.(1:20), default=10).default == 10

radio_menu = RadioMenu(string.(1:20))
@test TerminalMenus.options(radio_menu) == string.(1:20)
Expand Down