Add interactive Template constructor, but not interactive Plugins
This commit is contained in:
parent
004d84ecfa
commit
05b8d2245a
@ -1,8 +1,3 @@
|
||||
# const PLUGIN_TYPES = let
|
||||
# leaves(T::Type) = isconcretetype(T) ? [T] : vcat(map(leaves, subtypes(T))...)
|
||||
# leaves(Plugin)
|
||||
# end
|
||||
|
||||
function Base.show(io::IO, ::MIME"text/plain", p::T) where T <: Plugin
|
||||
indent = get(io, :indent, 0)
|
||||
print(io, repeat(' ', indent), T)
|
||||
@ -21,6 +16,15 @@ else
|
||||
show_field(x::AbstractString) = repr(contractuser(x))
|
||||
end
|
||||
|
||||
"""
|
||||
interactive(::Type{T<:Plugin}) -> T
|
||||
|
||||
Create a [`Plugin`](@ref) of type `T` interactively from user input.
|
||||
"""
|
||||
function interactive(::Type{T}) where T <: Plugin
|
||||
return T() # TODO
|
||||
end
|
||||
|
||||
function Base.show(io::IO, m::MIME"text/plain", t::Template)
|
||||
println(io, "Template:")
|
||||
foreach(fieldnames(Template)) do n
|
||||
@ -36,3 +40,112 @@ function Base.show(io::IO, m::MIME"text/plain", t::Template)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
leaves(T::Type) = isconcretetype(T) ? [T] : vcat(map(leaves, subtypes(T))...)
|
||||
|
||||
function plugin_types()
|
||||
Ts = leaves(Plugin)
|
||||
# Hack both Documenter types into the list.
|
||||
# Unfortunately there's no way to do this automatically,
|
||||
# but it's unlikely for more parametric plugin types to exist.
|
||||
push!(Ts, Documenter{TravisCI}, Documenter{GitLabCI})
|
||||
return Ts
|
||||
end
|
||||
|
||||
function Template(::Val{true}; kwargs...)
|
||||
opts = Dict{Symbol, Any}(kwargs)
|
||||
|
||||
if !haskey(opts, :user)
|
||||
opts[:user] = prompt(String, "Git hosting service username", defaultkw(:user))
|
||||
end
|
||||
|
||||
if !haskey(opts, :host)
|
||||
opts[:host] = prompt(String, "Git hosting service URL", defaultkw(:host))
|
||||
end
|
||||
|
||||
if !haskey(opts, :authors)
|
||||
opts[:authors] = prompt(String, "Package author(s)", defaultkw(:authors))
|
||||
end
|
||||
|
||||
if !haskey(opts, :dir)
|
||||
opts[:dir] = prompt(String, "Path to package parent directory", defaultkw(:dir))
|
||||
end
|
||||
|
||||
if !haskey(opts, :julia)
|
||||
opts[:julia] = prompt(VersionNumber, "Supported Julia version", defaultkw(:julia))
|
||||
end
|
||||
|
||||
if !haskey(opts, :disable_defaults)
|
||||
available = map(typeof, default_plugins())
|
||||
opts[:disable_defaults] = select("Select defaults to disable:", available, [])
|
||||
end
|
||||
|
||||
if !haskey(opts, :plugins)
|
||||
# Don't offer any disabled plugins as options.
|
||||
available = setdiff(sort(plugin_types(); by=string), opts[:disable_defaults])
|
||||
initial = setdiff(map(typeof, default_plugins()), opts[:disable_defaults])
|
||||
chosen = select("Select plugins", available, initial)
|
||||
opts[:plugins] = map(interactive, chosen)
|
||||
end
|
||||
|
||||
return Template(Val(false); opts...)
|
||||
end
|
||||
|
||||
function prompt(::Type{String}, s::AbstractString, default; required::Bool=false)
|
||||
default isa AbstractString && (default = contractuser(default))
|
||||
default_display = required ? "REQUIRED" : repr(default)
|
||||
print("$s [$default_display]: ")
|
||||
input = strip(readline())
|
||||
return if isempty(input) && required
|
||||
println("This option is required")
|
||||
prompt(String, s, default; required=required)
|
||||
elseif isempty(input)
|
||||
default
|
||||
else
|
||||
input
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function prompt(
|
||||
::Type{VersionNumber}, s::AbstractString, default::VersionNumber;
|
||||
required::Bool=false,
|
||||
)
|
||||
v = prompt(String, s, default; required=required)
|
||||
return if v isa VersionNumber
|
||||
v
|
||||
else
|
||||
startswith(v, "v") && (v = v[2:end])
|
||||
v = replace(v, "\"" => "")
|
||||
VersionNumber(v)
|
||||
end
|
||||
end
|
||||
|
||||
function prompt(::Type{Bool}, s::AbstractString, default::Bool; required::Bool=false)
|
||||
b = prompt(String, s, default; required=required)
|
||||
return uppercase(b) in ("Y", "YES", "T", "TRUE")
|
||||
end
|
||||
|
||||
function prompt(::Type{Vector{String}}, s::AbstractString, default::Vector{<:AbstractString})
|
||||
# TODO
|
||||
end
|
||||
|
||||
# TODO: These can be made simpler when this is merged:
|
||||
# https://github.com/JuliaLang/julia/pull/30043
|
||||
|
||||
select(s::AbstractString, xs::Vector, initial) = select(string, s, xs, initial)
|
||||
|
||||
# Select any number of elements from a collection.
|
||||
function select(f::Function, s::AbstractString, xs::Vector, initial::Vector)
|
||||
m = MultiSelectMenu(map(f, xs); pagesize=length(xs))
|
||||
foreach(x -> push!(m.selected, findfirst(==(x), xs)), initial)
|
||||
selection = request(s, m)
|
||||
return map(i -> xs[i], collect(selection))
|
||||
end
|
||||
|
||||
# Select one item frm oa collection.
|
||||
function select(f::Function, s::AbstractString, xs::Vector, _initial)
|
||||
# Can't use the initial value yet.
|
||||
selection = request(s, RadioMenu(map(f, xs)))
|
||||
return xs[selection]
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user