Standard library or original for TerminalMenus

I want to use TerminalMenus in some minimal GUI app I’m developing. I can either use the original author’s version, or the one included in Julia’s standard libraries (documented here).
I think they’re both really similar, it seems like the original one is slightly outdated (found an issue and PRed a fix for it), but I just don’t know what the best practice is in this case.

If the standard library version should be used instead then we should add some depreciation-indication to the original one.

Bumping this, maybe someone has some input.

And since I have your attention, any opinions on default values (see this issue)? Currently I’m just pushfirsting a default value to the list accepted by RadioMenu (I then account for that in the results). But it would be cool to have something built-in.

All points here are IMHO

  • stdlib parts must be licensed as julia
  • stdlib parts must be supported
  • stdlib parts must be authoritative
    • stdlib part starts as a copy
    • if other package is not maintained. case is closed. stdlib wins.
    • if other package continue to grow, it will rather become an extension of stdlib.
      in fact stdlib will dominate when present for its implementation, interface and distribution.
      great if external project owner can lead the transition!

And that’s the case for all packages prior to stdlib in the transitive closure
of dependencies in the julia packages world.

Same problem exist with TOML that is included in Pkg in a ext directory
Pkg is on the same layer of authority in the graph dependencies than Julia.
Any bug in Pkg, then TOML will break the stdlib and Julia.
Not acceptable from an outer pkg. And for the community.

[Replying to self]

Actually parsing of toml is done like this :

https://github.com/JuliaLang/julia/blob/v1.2.0/base/loading.jl#L352-L363

A bit hacky, isn’t it?
A good thing if some committer can grasp the problem.

I don’t really understand, what is the problem?

Regarding parsing of TOML inside Julia, see Code loading might be better just fully parsing TOML files · Issue #27414 · JuliaLang/julia · GitHub.

I see minor problems now, and majors ones upcoming later.

Is TOML supported ? Used but not supported ? Shall we use it as a config file for our package ?
Rust cargo, go dep use it. Julia pkgs need one. Pkg use toml. It seems quirky to not follow it.

The there’s more than one way to do things, accompanied with code duplication also lead to lost feature as you point : loss of caching, error reporting … I have pointed loss in code gen, init workflow at Pkg too.

If many options come from Julia itself, i see unsync and non-quality creeping at each update.
Each time there are src/test/docs on linux/win/macos, x86/arm to support. Even with managed code.
Subpackages will become splitted, obsoleted, at the second, third level of deps.
Code could be moved and pasted upon duplicated one. Typing will be skirted.

As an illustration, I am today concerned by the (sad) state of linters in Julia.


So i have a done a lot of research about the allowed head in Expr. Not an easy game at all. I have reviewed Julia runtime in 3 langs. 8 externals package @ JuliaDebug & co, dismiss 3 at least, and am still not sure to have a robust review. Single source of truth is a good pattern.

Wishing the same fate will not pop here and there @ toml config (section), io with terminals menu, graph algos, even every curated pkg in julia pro.

I would assume that development to nick-paul/TerminalMenus.jl is basically done now that it’s in the stdlib. It has the unfortunate side effect that it can’t really be changed much anymore, though.
I commented on the issue you mentioned, since I have an old PR up that adds your desired behaviour to the stdlib version.

Thank you.
I ended up hacking this, it’s simple and works well:

mutable struct Dialog
    selected::String
end
Dialog() = Dialog("")
function TerminalMenus.RadioMenu(options::Vector{String}, default::Int)
    m = RadioMenu(options)
    m.selected = default
    m
end
function TerminalMenus.MultiSelectMenu(options::Vector{String}, default::Set{Int})
    m = MultiSelectMenu(options)
    m.selected = default
    m
end
function simulateInput(n)
    for _ in 1:n-1
        write(stdin.buffer, "\e[B")
    end
end
function requestᵐ(msg::AbstractString, m::RadioMenu)
    simulateInput(m.selected)
    request(msg, m)
end
function requestᵐ(msg::AbstractString, m::MultiSelectMenu)
    # if !isempty(m.selected)
        simulateInput(reduce(min, m.selected))
    # end
    request(msg, m)
end
function TerminalMenus.request(msg::String, m::Dialog)
    println(msg)
    println("[there is no default]")
    strip(readline())
end
function requestᵐ(msg::String, m::Dialog)
    println(msg)
    println("[Enter for default, or type new value]")
    println("default> ", m.selected)
    ans = strip(readline())
    if !isempty(ans)
        m.selected = ans
    end
    return m.selected
end

Hah, I’ve done similar things, but I forgot about the write(stdin.buffer, ...) trick. Thanks for that :slightly_smiling_face: