How does nested tab completion work in the REPL?
I notice I can get this to work with nested NamedTuple
but I am struggling to get it to work with a custom type.
How does nested tab completion work in the REPL?
I notice I can get this to work with nested NamedTuple
but I am struggling to get it to work with a custom type.
The short answer is that itβs very ad-hoc. 1.10 makes it a bunch better, but we still have some hard-coded hacks for things like AbstractDict.
Aside from special cases, generically it uses propertynames
to find the tab completions after a .
. So, if you have a custom getproperty
then you will need to overload Base.propertynames
to provide completions. But this doesnβt nest.
Setup:
begin
using HDF5, Downloads
url = "https://github.com/evetion/SpaceLiDAR-artifacts/releases/download/v0.3.0/ATL08_20201121151145_08920913_006_01.h5";
fn = Downloads.download(url, basename(url))
h5f = h5open(fn)
end
begin
h5_to_tuple(h5o::Union{HDF5.File,HDF5.Group}) =
NamedTuple(Symbol.(keys(h5o)) .=> h5_to_tuple.(getindex.((h5o,), keys(h5o))))
h5_to_tuple(h5o) = h5o
nt = h5_to_tuple(h5f)
end
This works in the REPL:
julia> nt.[TAB]
METADATA ancillary_data ds_geosegments ds_metrics ds_surf_type gt1l gt1r
gt2l gt2r gt3l gt3r orbit_info quality_assessment
julia> nt.gt2l.[TAB]
land_segments signal_photons
julia> nt.gt2l.land_segments.[TAB]
asr atlas_pa beam_azimuth beam_coelev brightness_flag canopy cloud_flag_atm
cloud_fold_flag delta_time delta_time_beg delta_time_end dem_flag dem_h dem_removal_flag
h_dif_ref last_seg_extend latitude latitude_20m layer_flag longitude longitude_20m
msw_flag n_seg_ph night_flag ph_ndx_beg ph_removal_flag psf_flag rgt
sat_flag segment_id_beg segment_id_end segment_landcover segment_snowcover segment_watermask sigma_across
sigma_along sigma_atlas_land sigma_h sigma_topo snr solar_azimuth solar_elevation
surf_type terrain terrain_flg urban_flag
julia> nt.gt2l.land_segments.sat_flag.[TAB]
file id xfer
julia> nt.gt2l.land_segments.sat_flag
π’ HDF5.Dataset: /gt2l/land_segments/sat_flag (file: ATL08_20201121151145_08920913_006_01.h5 xfer_mode: 0)
ββ π·οΈ DIMENSION_LIST
ββ π·οΈ _FillValue
ββ π·οΈ contentType
ββ π·οΈ coordinates
ββ π·οΈ description
ββ π·οΈ flag_meanings
ββ π·οΈ flag_values
ββ π·οΈ long_name
ββ π·οΈ source
ββ π·οΈ units
ββ π·οΈ valid_max
ββ π·οΈ valid_min
As in this issue:
This however does not work:
begin
struct H5Indexer{O <: Union{HDF5.File,HDF5.Group}, C <: NamedTuple}
parent::O
children::C
function H5Indexer(p)
pairs = Pair{Symbol,Any}[
Symbol(k) => index(getindex(p,k))
for k in keys(p)
]
#a = NamedTuple(Symbol(k) => v for (k,v) in attrs(p))
#push!(pairs, :attrs => a)
c = NamedTuple(pairs)
new{typeof(p),typeof(c)}(p,c)
end
end
index(h5o::Union{HDF5.File,HDF5.Group}) =
H5Indexer(h5o)
index(x) = x
Base.parent(h5idx::H5Indexer) = getfield(h5idx, :parent)
Base.getproperty(h5idx::H5Indexer, s::Symbol) =
(@inline; getfield(getfield(h5idx, :children), s))
Base.propertynames(h5idx::H5Indexer) =
propertynames(getfield(h5idx, :children))
Base.fieldnames(H5IDX::Type{H5Indexer{<: Any, C}}) where C =
(@inline; fieldnames(C))
Base.show(io::IO, m::MIME"text/plain", h5idx::H5Indexer) =
show(io, m, getfield(h5idx, :parent))
end
I get the following behavior:
julia> h5idx.[TAB]
METADATA ancillary_data ds_geosegments ds_metrics ds_surf_type gt1l gt1r gt2l gt2r gt3l gt3r orbit_info quality_assessment
julia> h5idx.gt1r.[TAB]
# no suggestions
What is special about a NamedTuple
?
As of 1.10, this works.
h5idx.gt1r.land_segments.[TAB]
asr atlas_pa beam_azimuth beam_coelev brightness_flag canopy
cloud_flag_atm cloud_fold_flag delta_time delta_time_beg delta_time_end dem_flag
dem_h dem_removal_flag h_dif_ref last_seg_extend latitude latitude_20m
layer_flag longitude longitude_20m msw_flag n_seg_ph night_flag
ph_ndx_beg ph_removal_flag psf_flag rgt sat_flag segment_id_beg
segment_id_end segment_landcover segment_snowcover segment_watermask sigma_across sigma_along
sigma_atlas_land sigma_h sigma_topo snr solar_azimuth solar_elevation
Awesome. I just need to download the beta now.