Skip to content

Commit

Permalink
Add update mechanism for Terminfo, and common user-alias data (#53285)
Browse files Browse the repository at this point in the history
Now that we take care of terminfo parsing ourselves, having a clear
origin and processing method for arriving at our reference terminfo data
seems somewhat important.

The original form was acquired by re-purposing some pre-processed
terminfo data from NCurses (I forget the exact source). I considered
adding a separate ingestion/processing script, but it occurred to me
that it would make sense to have the method for updating the data file
be _in_ the data file, by turning it into a quine.

This seems to work rather well, and so long as the NCurses source file
format stays the same, updating the terminfo data is now dead simple.

While working on the terminfo files, some minor refactors popped up as
"probably nice to have". One of which makes the reported number of
flags/numbers/strings actually accurate.

Lastly, to support the ergonomic use of capability variable names
instead of the short (read: uninformative) capname, we now also import
the NCurses-recognised extended capabilities, and generate/specify some
nice aliases for them.

-----

If we separate out the terminfo parser/data into a small stdlib, the
state here will be the initial state of the repo.

(cherry picked from commit 923fe2d)
  • Loading branch information
fingolfin authored and KristofferC committed Feb 26, 2024
1 parent 7a95a0c commit 91cf14a
Show file tree
Hide file tree
Showing 3 changed files with 818 additions and 533 deletions.
37 changes: 23 additions & 14 deletions base/terminfo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ struct TermInfo
numbers::Dict{Symbol, Int}
strings::Dict{Symbol, String}
extensions::Union{Nothing, Set{Symbol}}
aliases::Dict{Symbol, Symbol}
end

TermInfo() = TermInfo([], Dict(), Dict(), Dict(), nothing)
TermInfo() = TermInfo([], Dict(), Dict(), Dict(), nothing, Dict())

function read(data::IO, ::Type{TermInfoRaw})
# Parse according to `term(5)`
Expand Down Expand Up @@ -175,24 +176,28 @@ function TermInfo(raw::TermInfoRaw)
flags = Dict{Symbol, Bool}()
numbers = Dict{Symbol, Int}()
strings = Dict{Symbol, String}()
aliases = Dict{Symbol, Symbol}()
extensions = nothing
for (flag, value) in zip(TERM_FLAGS, raw.flags)
flags[flag.short] = value
flags[flag.long] = value
flags[flag.name] = value
aliases[flag.capname] = flag.name
end
for (num, value) in zip(TERM_NUMBERS, raw.numbers)
numbers[num.short] = Int(value)
numbers[num.long] = Int(value)
numbers[num.name] = Int(value)
aliases[num.capname] = num.name
end
for (str, value) in zip(TERM_STRINGS, raw.strings)
if !isnothing(value)
strings[str.short] = value
strings[str.long] = value
strings[str.name] = value
aliases[str.capname] = str.name
end
end
if !isnothing(raw.extended)
extensions = Set{Symbol}()
for (key, value) in raw.extended
longalias(key, value) = first(get(TERM_USER, (typeof(value), key), (nothing, "")))
for (short, value) in raw.extended
long = longalias(short, value)
key = something(long, short)
push!(extensions, key)
if value isa Bool
flags[key] = value
Expand All @@ -201,26 +206,30 @@ function TermInfo(raw::TermInfoRaw)
elseif value isa String
strings[key] = value
end
if !isnothing(long)
aliases[short] = long
end
end
end
TermInfo(raw.names, flags, numbers, strings, extensions)
TermInfo(raw.names, flags, numbers, strings, extensions, aliases)
end

get(ti::TermInfo, key::Symbol, default::Bool) = get(ti.flags, key, default)
get(ti::TermInfo, key::Symbol, default::Int) = get(ti.numbers, key, default)
get(ti::TermInfo, key::Symbol, default::String) = get(ti.strings, key, default)
get(ti::TermInfo, key::Symbol, default::Bool) = get(ti.flags, get(ti.aliases, key, key), default)
get(ti::TermInfo, key::Symbol, default::Int) = get(ti.numbers, get(ti.aliases, key, key), default)
get(ti::TermInfo, key::Symbol, default::String) = get(ti.strings, get(ti.aliases, key, key), default)

haskey(ti::TermInfo, key::Symbol) =
haskey(ti.flags, key) || haskey(ti.numbers, key) || haskey(ti.strings, key)
haskey(ti.flags, key) || haskey(ti.numbers, key) || haskey(ti.strings, key) || haskey(ti.aliases, key)

function getindex(ti::TermInfo, key::Symbol)
haskey(ti.flags, key) && return ti.flags[key]
haskey(ti.numbers, key) && return ti.numbers[key]
haskey(ti.strings, key) && return ti.strings[key]
haskey(ti.aliases, key) && return getindex(ti, ti.aliases[key])
throw(KeyError(key))
end

keys(ti::TermInfo) = keys(ti.flags) keys(ti.numbers) keys(ti.strings)
keys(ti::TermInfo) = keys(ti.flags) keys(ti.numbers) keys(ti.strings) keys(ti.aliases)

function show(io::IO, ::MIME"text/plain", ti::TermInfo)
print(io, "TermInfo(", ti.names, "; ", length(ti.flags), " flags, ",
Expand Down
Loading

0 comments on commit 91cf14a

Please sign in to comment.