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
|
function Base.show(io::IO, ::MIME"text/plain", p::T) where T <: Plugin
|
||||||
indent = get(io, :indent, 0)
|
indent = get(io, :indent, 0)
|
||||||
print(io, repeat(' ', indent), T)
|
print(io, repeat(' ', indent), T)
|
||||||
@ -21,6 +16,15 @@ else
|
|||||||
show_field(x::AbstractString) = repr(contractuser(x))
|
show_field(x::AbstractString) = repr(contractuser(x))
|
||||||
end
|
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)
|
function Base.show(io::IO, m::MIME"text/plain", t::Template)
|
||||||
println(io, "Template:")
|
println(io, "Template:")
|
||||||
foreach(fieldnames(Template)) do n
|
foreach(fieldnames(Template)) do n
|
||||||
@ -36,3 +40,112 @@ function Base.show(io::IO, m::MIME"text/plain", t::Template)
|
|||||||
end
|
end
|
||||||
end
|
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