# TerminalUserInterfaces.jl question

**URL:** <https://discourse.julialang.org/t/terminaluserinterfaces-jl-question/112043>\
**Category:** General Usage\
**Tags:** question, package, ui\
**Created:** [March 24, 2024, 4:06pm UTC](https://discourse.julialang.org/t/terminaluserinterfaces-jl-question/112043 "2024-03-24T16:06:13Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [March 24, 2024, 4:06pm UTC](https://discourse.julialang.org/t/terminaluserinterfaces-jl-question/112043/1 "2024-03-24T16:06:13Z")

</div>

I try to use [TerminalUserInterfaces.jl](https://github.com/kdheepak/TerminalUserInterfaces.jl) and the list example: [TerminalUserInterfaces.jl/examples/list.jl at main · kdheepak/TerminalUserInterfaces.jl · GitHub](https://github.com/kdheepak/TerminalUserInterfaces.jl/blob/main/examples/list.jl) to create a list of options.  
This part is fine and works.

Now, how can I expand this example to be able to multi select list entries?  
I want to select more than 1 entries from the list and visible highlight the selected entries.

Another question is: when I am in the menu and switch to another window, the menu errors out with

```julia
ERROR: ArgumentError: invalid JSON at byte position 1 while parsing type JSON3.Object: ExpectedOpeningObjectChar
"FocusLost"

```

which is quite annoying.  
How can this solved?

---

<div class="post-metadata">

**Author:** ![mnemnion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mnemnion/32/206596_2.png) [@mnemnion](https://discourse.julialang.org/u/mnemnion)\
**Post date:** [March 24, 2024, 4:46pm UTC](https://discourse.julialang.org/t/terminaluserinterfaces-jl-question/112043/2 "2024-03-24T16:46:23Z")

</div>

> [@oheil](#):
>
> Another question is: when I am in the menu and switch to another window, the menu errors out with

Is there also a stack trace? That probably contains the critical information about where the error is arising.

Also, you may have better luck with that part of your question if you work out a minimal reproduction and file an issue for the package.

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [March 24, 2024, 5:17pm UTC](https://discourse.julialang.org/t/terminaluserinterfaces-jl-question/112043/3 "2024-03-24T17:17:24Z")

</div>

The MWE is just the linked example above, again: [TerminalUserInterfaces.jl/examples/list.jl at main · kdheepak/TerminalUserInterfaces.jl · GitHub](https://github.com/kdheepak/TerminalUserInterfaces.jl/blob/main/examples/list.jl)

> ****
>
> ```julia
> using TerminalUserInterfaces
> const TUI = TerminalUserInterfaces
> using Random
> using Logging
> 
> @kwdef mutable struct Model <: TUI.Model
> words = [
> "Option A"
> "Option B"
> "Option C"
> "Option D"
> "Option E"
> "Option F"
> "Option G"
> "Option H"
> "Option I"
> ]
> selection = 1
> scroll = 1
> quit = false
> end
> 
> function TUI.update!(m::Model, evt::TUI.KeyEvent)
> !isnothing(evt) && @info "Received event" evt
> if TUI.keypress(evt) == "j"
> m.selection += 1
> elseif TUI.keypress(evt) == "k"
> m.selection -= 1
> elseif TUI.keypress(evt) == "q"
> m.quit = true
> elseif TUI.keypress(evt) == "Enter"
> m.quit = true
> end
> if m.selection < 1
> m.selection = 1
> end
> if m.selection > length(m.words)
> m.selection = length(m.words)
> end
> end
> 
> function TUI.view(m::Model)
> words = [TUI.Word(word, TUI.Crayon()) for word in m.words]
> block = TUI.Block(; title = "Option Picker")
> TUI.SelectableList(block, words, m.scroll, m.selection)
> end
> 
> function main()
> m = Model()
> TUI.app(m)
> println(m.words[m.selection])
> end
> 
> main()
> 
> ```

How can I enhance this code for multiple selections?

This is the stacktrace which can also easily reproduced by using above example code and switching to another window (Windows11 here):

> ****
>
> ```julia
> julia> main()
> ERROR: ArgumentError: invalid JSON at byte position 1 while parsing type JSON3.Object: ExpectedOpeningObjectChar
> "FocusLost"
> 
> Stacktrace:
> [1] invalid(error::JSON3.Error, buf::Base.CodeUnits{UInt8, String}, pos::Int64, T::Type)
> @ JSON3 C:\Users\Oli\.julia\packages\JSON3\jSAdy\src\JSON3.jl:30
> [2] #read#43
> @ C:\Users\Oli\.julia\packages\JSON3\jSAdy\src\structs.jl:429 [inlined]
> [3] read
> @ C:\Users\Oli\.julia\packages\JSON3\jSAdy\src\structs.jl:353 [inlined]
> [4] read
> @ C:\Users\Oli\.julia\packages\JSON3\jSAdy\src\structs.jl:350 [inlined]
> [5] read(str::String, ::Type{Dict}; jsonlines::Bool, kw::@Kwargs{})
> @ JSON3 C:\Users\Oli\.julia\packages\JSON3\jSAdy\src\structs.jl:41
> [6] read
> @ C:\Users\Oli\.julia\packages\JSON3\jSAdy\src\structs.jl:33 [inlined]
> [7] read()
> @ Crossterm C:\Users\Oli\.julia\packages\Crossterm\IcBlh\src\Crossterm.jl:384
> [8] #try_get_event#19
> @ C:\Users\Oli\.julia\packages\TerminalUserInterfaces\eHCFe\src\terminal.jl:48 [inlined]
> [9] try_get_event
> @ C:\Users\Oli\.julia\packages\TerminalUserInterfaces\eHCFe\src\terminal.jl:46 [inlined]
> [10] (::TerminalUserInterfaces.var"#54#55"{Float64, Model})()
> @ TerminalUserInterfaces C:\Users\Oli\.julia\packages\TerminalUserInterfaces\eHCFe\src\app.jl:37
> [11] tui(f::TerminalUserInterfaces.var"#54#55"{Float64, Model}; flags::@Kwargs{})
> @ TerminalUserInterfaces C:\Users\Oli\.julia\packages\TerminalUserInterfaces\eHCFe\src\terminal.jl:262
> [12] tui
> @ C:\Users\Oli\.julia\packages\TerminalUserInterfaces\eHCFe\src\terminal.jl:258 [inlined]
> [13] #app#53
> @ C:\Users\Oli\.julia\packages\TerminalUserInterfaces\eHCFe\src\app.jl:31 [inlined]
> [14] app
> @ C:\Users\Oli\.julia\packages\TerminalUserInterfaces\eHCFe\src\app.jl:30 [inlined]
> [15] main()
> @ Main .\REPL[8]:3
> [16] top-level scope
> @ REPL[9]:1
> 
> ```

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [March 24, 2024, 10:09pm UTC](https://discourse.julialang.org/t/terminaluserinterfaces-jl-question/112043/4 "2024-03-24T22:09:20Z")

</div>

Alternative question:

Is there another TextUI usable in the REPL?

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [March 25, 2024, 1:09pm UTC](https://discourse.julialang.org/t/terminaluserinterfaces-jl-question/112043/5 "2024-03-25T13:09:40Z")

</div>

@kdheepak ?

---

<div class="post-metadata">

**Author:** ![kdheepak](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kdheepak/32/10881_2.png) [@kdheepak](https://discourse.julialang.org/u/kdheepak)\
**Post date:** [March 25, 2024, 1:28pm UTC](https://discourse.julialang.org/t/terminaluserinterfaces-jl-question/112043/6 "2024-03-25T13:28:17Z")

</div>

Thanks for pinging! I don’t check discourse actively.

If you can open an issue with a Minimal Working Example reproducing the error, I can take a look at what is going on. My guess is that Crossterm is sending a `FocusLost` and that isn’t being parsed correctly somewhere along the way. I tested the `FocusLost` locally on iTerm2 and wasn’t able to reproduce it.

Are you interested in building a TUI? If you just want to enable multiple selections for yourself or your users, you probably want to check out `QuickMenus.jl`:

> **[Expanding Man / QuickMenus.jl · GitLab](https://gitlab.com/ExpandingMan/QuickMenus.jl)**
>
> easily bring up REPL menus for rapid interaction in Julia

There’s also built-in functionality in the Julia REPL in `TerminalMenus` that can get you a long ways:

[https://docs.julialang.org/en/v1/stdlib/REPL/#MultiSelectMenu](https://docs.julialang.org/en/v1/stdlib/REPL/#MultiSelectMenu)

---

<div class="post-metadata">

**Author:** ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)\
**Post date:** [March 25, 2024, 1:51pm UTC](https://discourse.julialang.org/t/terminaluserinterfaces-jl-question/112043/7 "2024-03-25T13:51:21Z")

</div>

Thanks for the reply, the FocusLost issue is created.  
I will check the alternatives you mentioned, thanks again.
