Skip to content

Commit

Permalink
Make TerminalMenus header dynamic. (JuliaLang#38489)
Browse files Browse the repository at this point in the history
  • Loading branch information
GunnarFarneback committed Nov 23, 2020
1 parent bb6a48e commit c701c32
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 6 deletions.
11 changes: 8 additions & 3 deletions stdlib/REPL/src/TerminalMenus/AbstractMenu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,6 @@ function request(term::REPL.Terminals.TTYTerminal, m::AbstractMenu; cursor::Unio
if cursor isa Int
cursor = Ref(cursor)
end
menu_header = header(m)
!suppress_output && !isempty(menu_header) && println(term.out_stream, menu_header)

state = nothing
if !suppress_output
Expand Down Expand Up @@ -327,6 +325,12 @@ function printmenu(out::IO, m::AbstractMenu, cursoridx::Int; oldstate=nothing, i
print(buf, "\x1b[999D\x1b[$(ncleared)A") # move left 999 spaces and up `ncleared` lines
end

nheaderlines = 0
for headerline in split(header(m), "\n", keepempty=false)
print(buf, "\x1b[2K", headerline, "\r\n")
nheaderlines += 1
end

firstline = m.pageoffset+1
lastline = min(m.pagesize+m.pageoffset, lastoption)

Expand All @@ -353,7 +357,8 @@ function printmenu(out::IO, m::AbstractMenu, cursoridx::Int; oldstate=nothing, i
(firstline == lastline || i != lastline) && print(buf, "\r\n")
end

newstate = lastline-firstline # final line doesn't have `\n`
newstate = nheaderlines + lastline - firstline # final line doesn't have `\n`

if newstate < ncleared && oldstate !== nothing
# we printed fewer lines than last time. Erase the leftovers.
for i = newstate+1:ncleared
Expand Down
4 changes: 2 additions & 2 deletions stdlib/REPL/test/TerminalMenus/multiselect_menu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ for kws in ((charset=:ascii,),
TerminalMenus.writeline(buf, multi_menu, 1, true)
@test String(take!(buf)) == "$uck 1"
TerminalMenus.printmenu(buf, multi_menu, 1; init=true)
@test startswith(String(take!(buf)), string("\e[2K $cur $uck 1"))
@test startswith(String(take!(buf)), string("\e[2K[press: d=done, a=all, n=none]\r\n\e[2K $cur $uck 1"))
push!(multi_menu.selected, 1)
TerminalMenus.printmenu(buf, multi_menu, 2; init=true)
@test startswith(String(take!(buf)), string("\e[2K $chk 1\r\n\e[2K $cur $uck 2"))
@test startswith(String(take!(buf)), string("\e[2K[press: d=done, a=all, n=none]\r\n\e[2K $chk 1\r\n\e[2K $cur $uck 2"))
end

# Preselection
Expand Down
8 changes: 7 additions & 1 deletion stdlib/REPL/test/TerminalMenus/multiselect_with_skip_menu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function MultiSelectWithSkipMenu(options::Array{String,1}; pagesize::Int=10,
TerminalMenus.MultiSelectConfig(; kwargs...))
end

TerminalMenus.header(m::MultiSelectWithSkipMenu) = "[press: d=done, a=all, c=none, npNP=move with skip]"
TerminalMenus.header(m::MultiSelectWithSkipMenu) = "[press: d=done, a=all, c=none, npNP=move with skip, $(length(m.selected)) items selected]"

TerminalMenus.options(m::MultiSelectWithSkipMenu) = m.options

Expand Down Expand Up @@ -118,7 +118,13 @@ end
# These tests are specifically designed to verify that a `RefValue`
# input to the AbstractMenu `request` function works as intended.
menu = MultiSelectWithSkipMenu(string.(1:5), selected=[2, 3])
buf = IOBuffer()
TerminalMenus.printmenu(buf, menu, 1; init=true)
@test occursin("2 items selected", String(take!(buf)))
@test simulate_input(Set([2, 3, 4]), menu, 'n', :enter, 'd')
buf = IOBuffer()
TerminalMenus.printmenu(buf, menu, 1; init=true)
@test occursin("3 items selected", String(take!(buf)))

menu = MultiSelectWithSkipMenu(string.(1:5), selected=[2, 3])
@test simulate_input(Set([2]), menu, 'P', :enter, 'd', cursor=5)

0 comments on commit c701c32

Please sign in to comment.