diff --git a/src/wrappers.jl b/src/wrappers.jl index 5683486..7aaa862 100644 --- a/src/wrappers.jl +++ b/src/wrappers.jl @@ -172,11 +172,10 @@ for (geomtype, trait, childtype, child_trait, length_check, nesting) in ( # But not if geom is already a WrapperGeometry convert(::Type{$geomtype}, ::$trait, geom::$geomtype) = geom - function Base.show(io::IO, ::MIME"text/plain", geom::$geomtype{Z, M, T, E, C}; show_mz::Bool = true) where {Z, M, T, E <: Union{Nothing,Extents.Extent}, C} + function Base.show(io::IO, ::MIME"text/plain", geom::$geomtype{Z, M, T, E, C}; show_mz::Bool = true, screen_ncols::Int = displaysize(io)[2]) where {Z, M, T, E <: Union{Nothing,Extents.Extent}, C} compact = get(io, :compact, false) spacing = compact ? "" : " " show_mz &= !compact - screen_nrows, screen_ncols = displaysize(io) extent_str = "" crs_str = "" @@ -195,35 +194,47 @@ for (geomtype, trait, childtype, child_trait, length_check, nesting) in ( end str *= "(" this_geom = getgeom(trait(geom), geom) + # keep track of how much space we've used + make sure we give this info to any child geoms so they don't go over the limit + currently_used_space = textwidth(str) + textwidth(extent_str) + textwidth(crs_str) if this_geom isa AbstractVector # check here if we have enough room to display the whole object or if we need to condense the string str *= "[" - currently_used_space = textwidth(str) + textwidth(extent_str) + textwidth(crs_str) + 2 # +2 for brackets - length_of_one_object_in_chars = textwidth(_nice_geom_str(this_geom[1], false, compact)) - num_objects_to_show = min(length(this_geom), floor(Int, (screen_ncols - currently_used_space - 1 #=triple dot character =#) / length_of_one_object_in_chars)) + currently_used_space += 2 # +2 for brackets + available_space = screen_ncols - currently_used_space + + space_per_object = floor(Int, available_space / length(this_geom)) + + length_of_one_object_in_chars = textwidth(_nice_geom_str(this_geom[1], false, compact, space_per_object)) + + # this makes sure that if we have 1 or 2 geometries here, we show both, but any more and we skip them + num_objects_to_show = min(length(this_geom), max(2, floor(Int, (available_space - 1 #=triple dot character =#) / length_of_one_object_in_chars))) + + # separately track how many objects to show to the left and right of the ...()... + num_objects_left = num_objects_to_show == 1 ? 0 : ceil(Int, num_objects_to_show/2) + num_objects_right = max(1, floor(Int, num_objects_to_show/2)) - num_shown_each_side = ceil(Int, num_objects_to_show/2) - num_missing = length(this_geom) - num_objects_to_show + # how many objects are we skipping? + num_missing = length(this_geom) - (num_objects_left + num_objects_right) - for i ∈ 1:num_shown_each_side - str *= "$(_nice_geom_str(this_geom[i], false, compact)),$(spacing)" + for i ∈ 1:num_objects_left + str *= "$(_nice_geom_str(this_geom[i], false, compact, space_per_object)),$(spacing)" end if num_missing > 0 # report how many geometries aren't shown here - str *= " … ($(num_missing)) … " + str *= "…$(spacing)($(num_missing))$(spacing)…$(spacing),$(spacing)" end - for i ∈ 1:num_shown_each_side - str *= _nice_geom_str(this_geom[end - num_shown_each_side + i], false, compact) - if i != num_shown_each_side + for i ∈ 1:num_objects_right + str *= _nice_geom_str(this_geom[end - num_objects_right + i], false, compact, space_per_object) + if i != num_objects_right str *= ",$(spacing)" end end str *= "]" else - str *= _nice_geom_str(g, false, compact) + str *= _nice_geom_str(g, false, compact, screen_ncols - currently_used_space) end str *= extent_str @@ -290,21 +301,22 @@ for (geomtype, trait, childtype, child_trait, length_check, nesting) in ( end end -function _nice_geom_str(geom, ::Bool, ::Bool) +function _nice_geom_str(geom, ::Bool, ::Bool, ::Int) io = IOBuffer() show(io, MIME("text/plain"), geom) return String(take!(io)) end # need a work around to pass the show_mz variable through - put string to a temp IOBuffer then read it -function _nice_geom_str(geom::WrapperGeometry, show_mz::Bool, ::Bool) - io = IOBuffer() - show(io, MIME("text/plain"), geom; show_mz = show_mz) - return String(take!(io)) +function _nice_geom_str(geom::WrapperGeometry, show_mz::Bool, compact::Bool, screen_ncols::Int) + buf = IOBuffer() + io = IOContext(IOContext(buf, :compact => compact)) + show(io, MIME("text/plain"), geom; show_mz = show_mz, screen_ncols = screen_ncols) + return String(take!(buf)) end # handle tuples/vectors explicitly -function _nice_geom_str(geom::AbstractVector, ::Bool, compact::Bool) +function _nice_geom_str(geom::AbstractVector, ::Bool, compact::Bool, ::Int) spacing = compact ? "" : " " str = "[" str *= _add_elements_with_spacing(geom, spacing) @@ -312,7 +324,7 @@ function _nice_geom_str(geom::AbstractVector, ::Bool, compact::Bool) return str end -function _nice_geom_str(geom::Tuple, ::Bool, compact::Bool) +function _nice_geom_str(geom::Tuple, ::Bool, compact::Bool, ::Int) spacing = compact ? "" : " " str = "(" str *= _add_elements_with_spacing(geom, spacing) diff --git a/test/test_wrappers.jl b/test/test_wrappers.jl index 6c37498..e7764b6 100644 --- a/test/test_wrappers.jl +++ b/test/test_wrappers.jl @@ -195,12 +195,12 @@ polygon = GI.Polygon([linearring, linearring]) @test @inferred(GI.extent(polygon)) == Extent(X=(1, 5), Y=(2, 6)) @test GI.convert(GI, MyPolygon()) isa GI.Polygon @test GI.convert(GI, polygon) === polygon -test_display(polygon, "Polygon{false, false}([LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])])", +test_display(polygon, "Polygon{false, false}([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])", "Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])") polygon_crs = GI.Polygon(polygon; crs=EPSG(4326)) @test parent(polygon_crs) === parent(polygon) @test GI.crs(polygon_crs) === EPSG(4326) -test_display(polygon_crs, "Polygon{false, false}([LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])], crs = EPSG{1}((4326,)))", +test_display(polygon_crs, "Polygon{false, false}([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])], crs = EPSG{1}((4326,)))", "Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])") # Make sure `linestring` is also ok in polygons polygon = GI.Polygon([linestring, linestring]) @@ -229,7 +229,7 @@ test_display(multipoint, "MultiPoint{false, false}([(1, 2), (3, 4), (3, 2), (1, multipoint_crs = GI.MultiPoint(multipoint; crs=EPSG(4326)) @test parent(multipoint_crs) == parent(multipoint) @test GI.crs(multipoint_crs) === EPSG(4326) -test_display(multipoint_crs, "MultiPoint{false, false}([(1, 2), (3, 4), (3, 2), (1, 4), (7, 8), (9, 10)], crs = EPSG{1}((4326,)))", "MultiPoint([(1,2),(3,4),(3,2),(1,4),(7,8),(9,10)])") +test_display(multipoint_crs, "MultiPoint{false, false}([(1, 2), (3, 4), … (2) … , (7, 8), (9, 10)], crs = EPSG{1}((4326,)))", "MultiPoint([(1,2),(3,4),(3,2),(1,4),(7,8),(9,10)])") # GeometryCollection geoms = [line, linestring, linearring, multipoint, (1, 2)] @@ -240,13 +240,13 @@ collection = GI.GeometryCollection(geoms) @test !GI.is3d(collection) @test GI.ncoord(collection) == 2 @test GI.extent(collection) == reduce(Extents.union, map(GI.extent, geoms)) -test_display(collection, "GeometryCollection{false, false}([Line([(1, 2), (3, 4)]), LineString([(1, 2), (3, 4)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), MultiPoint([(1, 2), (3, 4), (3, 2), (1, 4), (7, 8), (9, 10)]), (1, 2)])", - "GeometryCollection([Line([(1,2),(3,4)]),LineString([(1,2),(3,4)]),LinearRing([(1,2),(3,4),(5,6),(1,2)]),MultiPoint([(1,2),(3,4),(3,2),(1,4),(7,8),(9,10)]),(1,2)])") +test_display(collection, "GeometryCollection{false, false}([Line([(1, 2), (3, 4)]), … (3) … , (1, 2)])", + "GeometryCollection([Line([(1,2),(3,4)]),LineString([(1,2),(3,4)]),…(2)…,(1,2)])") collection_crs = GI.GeometryCollection(collection; crs=EPSG(4326)) @test parent(collection_crs) == parent(collection) @test GI.crs(collection_crs) === EPSG(4326) -test_display(collection_crs, "GeometryCollection{false, false}([Line([(1, 2), (3, 4)]), LineString([(1, 2), (3, 4)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), MultiPoint([(1, 2), (3, 4), (3, 2), (1, 4), (7, 8), (9, 10)]), (1, 2)], crs = EPSG{1}((4326,)))", - "GeometryCollection([Line([(1,2),(3,4)]),LineString([(1,2),(3,4)]),LinearRing([(1,2),(3,4),(5,6),(1,2)]),MultiPoint([(1,2),(3,4),(3,2),(1,4),(7,8),(9,10)]),(1,2)])") +test_display(collection_crs, "GeometryCollection{false, false}([Line([(1, 2), (3, 4)]), … (3) … , (1, 2)], crs = EPSG{1}((4326,)))", + "GeometryCollection([Line([(1,2),(3,4)]),LineString([(1,2),(3,4)]),…(2)…,(1,2)])") # MultiCurve multicurve = GI.MultiCurve([linestring, linearring]) @@ -258,13 +258,13 @@ multicurve = GI.MultiCurve([linestring, linearring]) @test GI.extent(multicurve) == Extent(X=(1, 5), Y=(2, 6)) @test_throws ArgumentError GI.MultiCurve([pointz, polygon]) @test GI.testgeometry(multicurve) -test_display(multicurve, "MultiCurve{false, false}([LineString([(1, 2), (3, 4)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])])", - "MultiCurve([LineString([(1,2),(3,4)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])") +test_display(multicurve, "MultiCurve{false, false}([LineString([(1, 2), (3, 4)]), LinearRing([(1, 2), … (2) … , (1, 2)])])", + "MultiCurve([LineString([(1,2),(3,4)]),LinearRing([(1,2),(3,4),…(1)…,(1,2)])])") multicurve_crs = GI.MultiCurve(multicurve; crs=EPSG(4326)) @test parent(multicurve_crs) == parent(multicurve) @test GI.crs(multicurve_crs) === EPSG(4326) -test_display(multicurve_crs, "MultiCurve{false, false}([LineString([(1, 2), (3, 4)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])], crs = EPSG{1}((4326,)))", - "MultiCurve([LineString([(1,2),(3,4)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])") +test_display(multicurve_crs, "MultiCurve{false, false}([LineString([(1, 2), (3, 4)]), LinearRing([(1, 2), … (2) … , (1, 2)])], crs = EPSG{1}((4326,)))", + "MultiCurve([LineString([(1,2),(3,4)]),LinearRing([(1,2),(3,4),…(1)…,(1,2)])])") # MultiPolygon polygon = GI.Polygon([linearring, linearring]) @@ -273,8 +273,8 @@ multipolygon = GI.MultiPolygon([polygon]) @test GI.getgeom(multipolygon, 1) === polygon @test !GI.is3d(multipolygon) @test GI.ncoord(multipolygon) == 2 -test_display(multipolygon, "MultiPolygon{false, false}([Polygon([LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])])])", - "MultiPolygon([Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])])") +test_display(multipolygon, "MultiPolygon{false, false}([Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])])", + "MultiPolygon([Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])])])") # MultiPolygon extent does not infer, maybe due to nesting @test GI.extent(multipolygon) == Extent(X=(1, 5), Y=(2, 6)) @test collect(GI.getpoint(multipolygon)) == collect(GI.getpoint(polygon)) @@ -283,8 +283,8 @@ test_display(multipolygon, "MultiPolygon{false, false}([Polygon([LinearRing([(1, multipolygon_crs = GI.MultiPolygon(multipolygon; crs=EPSG(4326)) @test parent(multipolygon_crs) == parent(multipolygon) @test GI.crs(multipolygon_crs) === EPSG(4326) -test_display(multipolygon_crs, "MultiPolygon{false, false}([Polygon([LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])])], crs = EPSG{1}((4326,)))", - "MultiPolygon([Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])])") +test_display(multipolygon_crs, "MultiPolygon{false, false}([Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])], crs = EPSG{1}((4326,)))", + "MultiPolygon([Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])])])") # PolyhedralSurface polyhedralsurface = GI.PolyhedralSurface([polygon, polygon]) @@ -297,13 +297,13 @@ polyhedralsurface = GI.PolyhedralSurface([polygon, polygon]) @test GI.getgeom(polyhedralsurface, 1) == polygon @test collect(GI.getpoint(polyhedralsurface)) == vcat(collect(GI.getpoint(polygon)), collect(GI.getpoint(polygon))) @test GI.testgeometry(polyhedralsurface) -test_display(polyhedralsurface, "PolyhedralSurface{false, false}([Polygon([LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])]), Polygon([LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])])])", - "PolyhedralSurface([Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])]),Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])])") +test_display(polyhedralsurface, "PolyhedralSurface{false, false}([Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])]), Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])])", + "PolyhedralSurface([Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])]),Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])])])") polyhedralsurface_crs = GI.PolyhedralSurface(polyhedralsurface; crs=EPSG(4326)) @test parent(polyhedralsurface_crs) == parent(polyhedralsurface) @test GI.crs(polyhedralsurface_crs) === EPSG(4326) -test_display(polyhedralsurface_crs, "PolyhedralSurface{false, false}([Polygon([LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])]), Polygon([LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)]), LinearRing([(1, 2), (3, 4), (5, 6), (1, 2)])])], crs = EPSG{1}((4326,)))", - "PolyhedralSurface([Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])]),Polygon([LinearRing([(1,2),(3,4),(5,6),(1,2)]),LinearRing([(1,2),(3,4),(5,6),(1,2)])])])") +test_display(polyhedralsurface_crs, "PolyhedralSurface{false, false}([Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])]), Polygon([LinearRing([(1, 2), … (2) … , (1, 2)]), LinearRing([(1, 2), … (2) … , (1, 2)])])], crs = EPSG{1}((4326,)))", + "PolyhedralSurface([Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])]),Polygon([LinearRing([(1,2),…(2)…,(1,2)]),LinearRing([(1,2),…(2)…,(1,2)])])])") # Round-trip coordinates multipolygon_coords = [[[[1, 2], [3, 4], [3, 2], [1, 4]]]]