Start work on porting icat to Go
This commit is contained in:
parent
aab81c2d32
commit
7a1140cd03
@ -76,13 +76,14 @@ Remove all images currently displayed on the screen.
|
|||||||
|
|
||||||
--transfer-mode
|
--transfer-mode
|
||||||
type=choices
|
type=choices
|
||||||
choices=detect,file,stream
|
choices=detect,file,stream,memory
|
||||||
default=detect
|
default=detect
|
||||||
Which mechanism to use to transfer images to the terminal. The default is to
|
Which mechanism to use to transfer images to the terminal. The default is to
|
||||||
auto-detect. :italic:`file` means to use a temporary file and :italic:`stream`
|
auto-detect. :italic:`file` means to use a temporary file, :italic:`memory` means
|
||||||
means to send the data via terminal escape codes. Note that if you use the
|
to use shared memory, :italic:`stream` means to send the data via terminal
|
||||||
:italic:`file` transfer mode and you are connecting over a remote session then
|
escape codes. Note that if you use the :italic:`file` or :italic:`memory` transfer
|
||||||
image display will not work.
|
modes and you are connecting over a remote session then image display will not
|
||||||
|
work.
|
||||||
|
|
||||||
|
|
||||||
--detect-support
|
--detect-support
|
||||||
@ -622,4 +623,5 @@ elif __name__ == '__doc__':
|
|||||||
cd['usage'] = usage
|
cd['usage'] = usage
|
||||||
cd['options'] = options_spec
|
cd['options'] = options_spec
|
||||||
cd['help_text'] = help_text
|
cd['help_text'] = help_text
|
||||||
|
cd['short_desc'] = 'Display images in the terminal'
|
||||||
cd['args_completion'] = CompletionSpec.from_string('type:file mime:image/* group:Images')
|
cd['args_completion'] = CompletionSpec.from_string('type:file mime:image/* group:Images')
|
||||||
|
|||||||
@ -24,7 +24,7 @@ exec_kitty() {
|
|||||||
|
|
||||||
|
|
||||||
is_wrapped_kitten() {
|
is_wrapped_kitten() {
|
||||||
wrapped_kittens="clipboard"
|
wrapped_kittens="clipboard icat"
|
||||||
[ -n "$1" ] && {
|
[ -n "$1" ] && {
|
||||||
case " $wrapped_kittens " in
|
case " $wrapped_kittens " in
|
||||||
*" $1 "*) printf "%s" "$1" ;;
|
*" $1 "*) printf "%s" "$1" ;;
|
||||||
|
|||||||
113
tools/cmd/icat/main.go
Normal file
113
tools/cmd/icat/main.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
package icat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"kitty/tools/cli"
|
||||||
|
"kitty/tools/tty"
|
||||||
|
"kitty/tools/tui/graphics"
|
||||||
|
"kitty/tools/tui/loop"
|
||||||
|
"kitty/tools/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = fmt.Print
|
||||||
|
|
||||||
|
var opts *Options
|
||||||
|
var lp *loop.Loop
|
||||||
|
|
||||||
|
type transfer_mode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
unknown transfer_mode = iota
|
||||||
|
unsupported
|
||||||
|
supported
|
||||||
|
)
|
||||||
|
|
||||||
|
var transfer_by_file, transfer_by_memory, transfer_by_stream transfer_mode
|
||||||
|
|
||||||
|
var temp_files_to_delete []string
|
||||||
|
var direct_query_id, file_query_id, memory_query_id uint32
|
||||||
|
var stderr_is_tty bool
|
||||||
|
|
||||||
|
func print_error(format string, args ...any) {
|
||||||
|
if lp == nil || !stderr_is_tty {
|
||||||
|
fmt.Fprintf(os.Stderr, format, args...)
|
||||||
|
fmt.Fprintln(os.Stderr)
|
||||||
|
} else {
|
||||||
|
lp.QueueWriteString(fmt.Sprintf(format, args...))
|
||||||
|
lp.QueueWriteString("\r\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func on_initialize() (string, error) {
|
||||||
|
var iid uint32
|
||||||
|
g := func(t graphics.GRT_t, payload string) uint32 {
|
||||||
|
iid += 1
|
||||||
|
g1 := &graphics.GraphicsCommand{}
|
||||||
|
g1.SetTransmission(t).SetAction(graphics.GRT_action_query).SetImageId(iid).SetDataWidth(1).SetDataHeight(1).SetFormat(graphics.GRT_format_rgb)
|
||||||
|
g1.WriteWithPayloadToLoop(lp, utils.UnsafeStringToBytes(payload))
|
||||||
|
return iid
|
||||||
|
}
|
||||||
|
sz, err := lp.ScreenSize()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Failed to query terminal for screen size with error: %w", err)
|
||||||
|
}
|
||||||
|
if sz.WidthPx == 0 || sz.HeightPx == 0 {
|
||||||
|
return "", fmt.Errorf("Terminal does not support reporting screen sizes via the TIOCGWINSZ ioctl")
|
||||||
|
}
|
||||||
|
direct_query_id = g(graphics.GRT_transmission_direct, "123")
|
||||||
|
tf, err := graphics.MakeTemp()
|
||||||
|
if err == nil {
|
||||||
|
file_query_id = g(graphics.GRT_transmission_tempfile, tf.Name())
|
||||||
|
temp_files_to_delete = append(temp_files_to_delete, tf.Name())
|
||||||
|
tf.Write([]byte{1, 2, 3})
|
||||||
|
tf.Close()
|
||||||
|
} else {
|
||||||
|
transfer_by_file = unsupported
|
||||||
|
print_error("Failed to create temporary file for data transfer, file based transfer is disabled. Error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func on_finalize() string {
|
||||||
|
if len(temp_files_to_delete) > 0 {
|
||||||
|
for _, name := range temp_files_to_delete {
|
||||||
|
os.Remove(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) {
|
||||||
|
opts = o
|
||||||
|
stderr_is_tty = tty.IsTerminal(os.Stderr.Fd())
|
||||||
|
if opts.PrintWindowSize {
|
||||||
|
t, err := tty.OpenControllingTerm()
|
||||||
|
if err != nil {
|
||||||
|
return 1, fmt.Errorf("Failed to open controlling terminal with error: %w", err)
|
||||||
|
}
|
||||||
|
sz, err := t.GetSize()
|
||||||
|
if err != nil {
|
||||||
|
return 1, fmt.Errorf("Failed to query terminal using TIOCGWINSZ with error: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%dx%d", sz.Xpixel, sz.Ypixel)
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
temp_files_to_delete = make([]string, 0, 8)
|
||||||
|
lp, err = loop.New(loop.NoAlternateScreen, loop.NoRestoreColors, loop.NoMouseTracking)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lp.OnInitialize = on_initialize
|
||||||
|
lp.OnFinalize = on_finalize
|
||||||
|
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EntryPoint(parent *cli.Command) {
|
||||||
|
create_cmd(parent, main)
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"kitty/tools/cmd/at"
|
"kitty/tools/cmd/at"
|
||||||
"kitty/tools/cmd/clipboard"
|
"kitty/tools/cmd/clipboard"
|
||||||
"kitty/tools/cmd/edit_in_kitty"
|
"kitty/tools/cmd/edit_in_kitty"
|
||||||
|
"kitty/tools/cmd/icat"
|
||||||
"kitty/tools/cmd/update_self"
|
"kitty/tools/cmd/update_self"
|
||||||
"kitty/tools/tui"
|
"kitty/tools/tui"
|
||||||
)
|
)
|
||||||
@ -26,6 +27,8 @@ func KittyToolEntryPoints(root *cli.Command) {
|
|||||||
edit_in_kitty.EntryPoint(root)
|
edit_in_kitty.EntryPoint(root)
|
||||||
// clipboard
|
// clipboard
|
||||||
clipboard.EntryPoint(root)
|
clipboard.EntryPoint(root)
|
||||||
|
// icat
|
||||||
|
icat.EntryPoint(root)
|
||||||
// __hold_till_enter__
|
// __hold_till_enter__
|
||||||
root.AddSubCommand(&cli.Command{
|
root.AddSubCommand(&cli.Command{
|
||||||
Name: "__hold_till_enter__",
|
Name: "__hold_till_enter__",
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -17,6 +18,10 @@ import (
|
|||||||
|
|
||||||
var _ = fmt.Print
|
var _ = fmt.Print
|
||||||
|
|
||||||
|
func MakeTemp() (*os.File, error) {
|
||||||
|
return os.CreateTemp("", "tty-graphics-protocol-*")
|
||||||
|
}
|
||||||
|
|
||||||
// Enums {{{
|
// Enums {{{
|
||||||
type GRT_a int
|
type GRT_a int
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user