From be0dd00606f1a1c536ac44c144495b40be18aeb7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 24 Jan 2026 14:16:54 +0530 Subject: [PATCH] icat kitten: When catting multiple images display the images in input order Fixes #9413 --- docs/changelog.rst | 2 ++ kittens/icat/main.go | 30 +++++++++++++++++++++++++++--- kittens/icat/process_images.go | 4 +++- kitty_tests/mouse.py | 7 +++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index f49a9106f..de56314f5 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -200,6 +200,8 @@ Detailed list of changes - Linux: Fix a regression in 0.40 that caused horizontal alignment for emoji to be incorrect in some cases (:iss:`9395`) +- icat kitten: When catting multiple images display the images in input order (:iss:`9413`) + 0.45.0 [2025-12-24] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kittens/icat/main.go b/kittens/icat/main.go index f348570b0..e148d2847 100644 --- a/kittens/icat/main.go +++ b/kittens/icat/main.go @@ -7,6 +7,7 @@ import ( "math" "os" "runtime" + "slices" "strconv" "strings" "sync/atomic" @@ -256,7 +257,8 @@ func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) { return 1, fmt.Errorf("The --place option can only be used with a single image, not %d", len(items)) } files_channel = make(chan input_arg, len(items)) - for _, ia := range items { + for i, ia := range items { + ia.index = i files_channel <- ia } num_of_items = len(items) @@ -320,8 +322,10 @@ func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) { use_unicode_placeholder = true } base_id := uint32(opts.ImageId) - for num_of_items > 0 { - imgd := <-output_channel + expecting_input_sequence_number := 0 + pending := make([]*image_data, 0, num_of_items) + + do_one := func(imgd *image_data) { if base_id != 0 { imgd.image_id = base_id base_id++ @@ -341,6 +345,26 @@ func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) { } } } + + for num_of_items > 0 { + imgd := <-output_channel + if imgd.input_sequence_number == expecting_input_sequence_number { + do_one(imgd) + expecting_input_sequence_number++ + } else { + pending = append(pending, imgd) + index, _ := slices.BinarySearchFunc(pending, imgd.input_sequence_number, func(x *image_data, n int) int { + return x.input_sequence_number - n + }) + pending = slices.Insert(pending, index, imgd) + } + for len(pending) > 0 && pending[0].input_sequence_number == expecting_input_sequence_number { + do_one(pending[0]) + pending = pending[1:] + } + } + if len(pending) > 0 { + } keep_going.Store(false) if opts.Hold { fmt.Print("\r") diff --git a/kittens/icat/process_images.go b/kittens/icat/process_images.go index 3a3f0dc5b..b7f06fa4a 100644 --- a/kittens/icat/process_images.go +++ b/kittens/icat/process_images.go @@ -28,6 +28,7 @@ type input_arg struct { arg string value string is_http_url bool + index int } func is_http_url(arg string) bool { @@ -113,6 +114,7 @@ type image_data struct { width_cells, height_cells int use_unicode_placeholder bool passthrough_mode passthrough_type + input_sequence_number int // for error reporting err error @@ -293,7 +295,7 @@ func process_arg(arg input_arg) { case "magick": dopts = append(dopts, imaging.Backends(imaging.MAGICK_IMAGE)) } - imgd := image_data{source_name: arg.value} + imgd := image_data{source_name: arg.value, input_sequence_number: arg.index} dopts = append(dopts, imaging.ResizeCallback(func(w, h int) (int, int) { imgd.canvas_width, imgd.canvas_height = w, h set_basic_metadata(&imgd) diff --git a/kitty_tests/mouse.py b/kitty_tests/mouse.py index a2a9e6d33..31b3002b7 100644 --- a/kitty_tests/mouse.py +++ b/kitty_tests/mouse.py @@ -261,6 +261,13 @@ class TestMouse(BaseTest): scroll(x=2.6, up=False) self.ae(sel(), '3') release() + # fractional scrolling + init() + s.fractional_scroll(-0.5) + press() + move(x=3.6, q='1234') + release(x=3.6) + self.ae(sel(), '1234') # extending selections init()