diff --git a/docs/changelog.rst b/docs/changelog.rst index ff4d4008c..f76333ef6 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -46,6 +46,8 @@ Detailed list of changes 0.33.0 [future] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- Graphics protocol: Add a new delete mode for deleting images whose ids fall within a range. Useful for bulk deletion (:iss:`7080`) + - Keyboard protocol: Fix the :kbd:`Enter`, :kbd:`Tab` and :kbd:`Backspace` keys generating spurious release events even when report all keys as escape codes is not set (:iss:`7136`) diff --git a/docs/graphics-protocol.rst b/docs/graphics-protocol.rst index 7ccef7413..85ab69fa4 100644 --- a/docs/graphics-protocol.rst +++ b/docs/graphics-protocol.rst @@ -637,7 +637,7 @@ terminal may apply other heuristics (but it doesn't have to). It is important to distinguish between virtual image placements and real images displayed on top of Unicode placeholders. Virtual placements are invisible and only play the role of prototypes for real images. Virtual placements can be deleted by a -deletion command only when the `d` key is equal to ``i``, ``I``, ``n`` or ``N``. +deletion command only when the `d` key is equal to ``i``, ``I``, ``r``, ``R``, ``n`` or ``N``. The key values ``a``, ``c``, ``p``, ``q``, ``x``, ``y``, ``z`` and their capital variants never affect virtual placements because they do not have a physical location on the screen. @@ -729,13 +729,14 @@ scrollback buffer. The values of the ``x`` and ``y`` keys are the same as cursor Value of ``d`` Meaning ================= ============ ``a`` or ``A`` Delete all placements visible on screen -``i`` or ``I`` Delete all images with the specified id, specified using the ``i`` key. If you specify a ``p`` key for the placement id as well, then only the placement with the specified image id and placement id will be deleted. +``i`` or ``I`` Delete all images with the specified id, specified using the ``i`` key. If you specify a ``p`` key for the placement id as well, then only the placement with the specified image id and placement id will be deleted. ``n`` or ``N`` Delete newest image with the specified number, specified using the ``I`` key. If you specify a ``p`` key for the placement id as well, then only the placement with the specified number and placement id will be deleted. ``c`` or ``C`` Delete all placements that intersect with the current cursor position. ``f`` or ``F`` Delete animation frames. ``p`` or ``P`` Delete all placements that intersect a specific cell, the cell is specified using the ``x`` and ``y`` keys ``q`` or ``Q`` Delete all placements that intersect a specific cell having a specific z-index. The cell and z-index is specified using the ``x``, ``y`` and ``z`` keys. +``r`` or ``R`` Delete all images whose id is greater than or equal to the value of the ``x`` key and less than or equal to the value of the ``y`` (added in kitty version 0.33.0). ``x`` or ``X`` Delete all placements that intersect the specified column, specified using the ``x`` key. ``y`` or ``Y`` Delete all placements that intersect the specified row, specified using the ``y`` key. ``z`` or ``Z`` Delete all placements that have the specified z-index, specified using the ``z`` key. @@ -1083,9 +1084,11 @@ Key Value Default Description **Keys for deleting images** ----------------------------------------------------------- ``d`` Single character. ``a`` What to delete. - ``(a, A, c, C, n, N, - i, I, p, P, q, Q, x, - X, y, Y, z, Z)``. + ``( + a, A, c, C, n, N, + i, I, p, P, q, Q, r, + R, x, X, y, Y, z, Z + )``. ======= ==================== ========= ================= diff --git a/gen/apc_parsers.py b/gen/apc_parsers.py index 87f306317..7a73ae113 100755 --- a/gen/apc_parsers.py +++ b/gen/apc_parsers.py @@ -260,7 +260,7 @@ def graphics_parser() -> None: flag = frozenset keymap: KeymapType = { 'a': ('action', flag('tTqpdfac')), - 'd': ('delete_action', flag('aAiIcCfFnNpPqQxXyYzZ')), + 'd': ('delete_action', flag('aAiIcCfFnNpPqQrRxXyYzZ')), 't': ('transmission_type', flag('dfts')), 'o': ('compressed', flag('z')), 'f': ('format', 'uint'), diff --git a/kitty/graphics.c b/kitty/graphics.c index 2a01a230a..1e7823e58 100644 --- a/kitty/graphics.c +++ b/kitty/graphics.c @@ -2005,6 +2005,13 @@ id_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixelSize return false; } +static bool +id_range_filter_func(const ImageRef *ref UNUSED, Image *img, const void *data, CellPixelSize cell UNUSED) { + const GraphicsCommand *g = data; + return img->client_id && g->x_offset <= img->client_id && img->client_id <= g->y_offset; +} + + static bool number_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixelSize cell UNUSED) { const GraphicsCommand *g = data; @@ -2059,6 +2066,7 @@ handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c case 0: D('a', 'A', NULL, clear_filter_func_noncell); G('i', 'I', id_filter_func); + G('r', 'R', id_range_filter_func); G('p', 'P', point_filter_func); G('q', 'Q', point3d_filter_func); G('x', 'X', x_filter_func); diff --git a/kitty/parse-graphics-command.h b/kitty/parse-graphics-command.h index d67464f6a..9feca8510 100644 --- a/kitty/parse-graphics-command.h +++ b/kitty/parse-graphics-command.h @@ -183,12 +183,13 @@ static inline void parse_graphics_code(PS *self, uint8_t *parser_buf, if (g.delete_action != 'A' && g.delete_action != 'C' && g.delete_action != 'F' && g.delete_action != 'I' && g.delete_action != 'N' && g.delete_action != 'P' && - g.delete_action != 'Q' && g.delete_action != 'X' && - g.delete_action != 'Y' && g.delete_action != 'Z' && - g.delete_action != 'a' && g.delete_action != 'c' && - g.delete_action != 'f' && g.delete_action != 'i' && - g.delete_action != 'n' && g.delete_action != 'p' && - g.delete_action != 'q' && g.delete_action != 'x' && + g.delete_action != 'Q' && g.delete_action != 'R' && + g.delete_action != 'X' && g.delete_action != 'Y' && + g.delete_action != 'Z' && g.delete_action != 'a' && + g.delete_action != 'c' && g.delete_action != 'f' && + g.delete_action != 'i' && g.delete_action != 'n' && + g.delete_action != 'p' && g.delete_action != 'q' && + g.delete_action != 'r' && g.delete_action != 'x' && g.delete_action != 'y' && g.delete_action != 'z') { REPORT_ERROR("Malformed GraphicsCommand control block, unknown flag " "value for delete_action: 0x%x", diff --git a/kitty_tests/graphics.py b/kitty_tests/graphics.py index 9d8204a23..8a0351e6c 100644 --- a/kitty_tests/graphics.py +++ b/kitty_tests/graphics.py @@ -1016,6 +1016,13 @@ class TestGraphics(BaseTest): put_image(s, cw, ch, z=9) delete('Z', z=9) self.ae(s.grman.image_count, 0) + put_image(s, cw, ch, id=1) + put_image(s, cw, ch, id=2) + put_image(s, cw, ch, id=3) + delete('R', y=2) + self.ae(s.grman.image_count, 1) + delete('R', x=3, y=3) + self.ae(s.grman.image_count, 0) self.assertEqual(s.grman.disk_cache.total_size, 0) # test put + delete + put diff --git a/tools/tui/graphics/command.go b/tools/tui/graphics/command.go index 71fff5efb..a5da2a877 100644 --- a/tools/tui/graphics/command.go +++ b/tools/tui/graphics/command.go @@ -116,6 +116,9 @@ const ( GRT_delete_by_cell_zindex // q GRT_free_by_cell_zindex // Q + GRT_delete_by_range // r + GRT_free_by_range // R + GRT_delete_by_column // x GRT_free_by_column // X