Skip to content

Commit 1f6ee6c

Browse files
authored
chore: 🧹 update imgcat and add support for kitty (#1017)
This could be done better by exposing more options from the protocol, but it should be a good start!
1 parent 14e3ecb commit 1f6ee6c

File tree

1 file changed

+121
-64
lines changed

1 file changed

+121
-64
lines changed

‎sourced/imaging/imgcat.nu‎

Lines changed: 121 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,148 @@
11
# https://iterm2.com/documentation-images.html
2+
# https://sw.kovidgoyal.net/kitty/graphics-protocol/
3+
4+
def is-screen-term [] {
5+
$env.TERM =~ ^screen
6+
}
27

38
def print_osc [] {
4-
if $env.TERM == screen* {
5-
"\ePtmux;\e\e]"
6-
} else {
7-
"\e]"
8-
}
9+
if (is-screen-term) {
10+
return "\ePtmux;\e\e]"
11+
}
12+
ansi escape_right
913
}
1014

1115
def print_st [] {
12-
if $env.TERM == screen* {
13-
"\a\e\\"
14-
} else {
15-
"\a"
16-
}
16+
if (is-screen-term) {
17+
return "\a\e\\"
18+
}
19+
"\a"
1720
}
1821

19-
def --env b64_encode [fn] {
20-
open $fn | encode base64
22+
def b64_encode [fn] {
23+
open -r $fn | encode base64
24+
}
25+
26+
# Print an image using the iTerm protocol
27+
def print_iterm_image [
28+
filename: path
29+
base64contents: string
30+
--inline
31+
--print_filename
32+
] {
33+
let b64_enc_data = (b64_encode $filename)
34+
let b64_dec_data = ($base64contents | decode base64)
35+
let query = (
36+
[(print_osc)]
37+
| append "1337;File="
38+
| append (
39+
if ($filename | str length) > 0 {
40+
$"name=($b64_enc_data);"
41+
}
42+
)
43+
| append $"size=($b64_dec_data | bytes length)"
44+
| append (
45+
if $inline {
46+
$";inline=1"
47+
}
48+
)
49+
| append ":"
50+
| append $base64contents
51+
| append (print_st)
52+
| append "\n"
53+
)
54+
55+
if $print_filename {
56+
print -n $filename
57+
}
58+
59+
$query | str join
2160
}
2261

23-
def --env b64_decode [fn] {
24-
$fn | decode base64
62+
# Print an image using the Kitty protocol
63+
def print_kitty_image [
64+
filename: path
65+
base64contents: string
66+
--print_filename
67+
] {
68+
69+
let b64_dec_data = ($base64contents | decode base64)
70+
let size = ($b64_dec_data | bytes length)
71+
72+
let result = (
73+
["\e"]
74+
| append "_G"
75+
| append $"a=T,f=100,t=d,s=($size);"
76+
| append $base64contents
77+
| append (ansi st)
78+
)
79+
80+
if $print_filename {
81+
print -n $filename
82+
}
83+
84+
$result | str join
2585
}
2686

87+
# Determine the appropriate protocol and print the image
2788
def print_image [
28-
filename # Filename to convey to client
29-
inline # 0 or 1
30-
base64contents # Base64-encoded contents
31-
print_filename # If non-empty, print the filename before outputting the image
89+
filename: path
90+
base64contents: string
91+
--inline # Only for iTerm; ignored for Kitty
92+
--print_filename
3293
] {
33-
let a = (print_osc)
34-
let b = "1337;File="
35-
let c = (if ($filename | length) > 0 {
36-
let b64_enc_data = (b64_encode $filename)
37-
$"name=($b64_enc_data);"
38-
})
39-
let b64_dec_data = (b64_decode $base64contents)
40-
let d = $"size=($b64_dec_data | bytes length)"
41-
let e = $";inline=($inline)"
42-
let f = ":"
43-
let g = $base64contents
44-
let h = print_st
45-
let i = "\n"
46-
let j = (if ($print_filename | length) > 0 {
47-
print -n $filename
48-
})
49-
50-
[ $a $b $c $d $e $f $g $h $i $j ] | str join
94+
if (detect_kitty_support) {
95+
print_kitty_image $filename $base64contents --print_filename=$print_filename
96+
} else {
97+
print_iterm_image $filename $base64contents --inline=$inline --print_filename=$print_filename
98+
}
5199
}
52100

53101
def error [] {
54-
print "Error: ($env.LAST_EXIT_CODE)"
102+
print "Error: ($env.LAST_EXIT_CODE)"
55103
}
56104

57105
def show_help [] {
58-
print "Usage: imgcat [-p] filename ..."
59-
print " or: cat filename | imgcat"
106+
print "Usage: imgcat [-p] filename ..."
107+
print " or: cat filename | imgcat"
60108
}
61109

62-
# imgcat.nu shows images in your terminal if your terminal supports it
63-
def imgcat [
64-
--help(-h) # Help/Usage message
65-
--print(-p) # Print filename
66-
--url(-u) # Use a URL
67-
filename # The filename to show
68-
] {
69-
if $help {
70-
show_help
71-
}
110+
# Detect Kitty support by querying the terminal
111+
# https://sw.kovidgoyal.net/kitty/graphics-protocol/#querying-support-and-available-transmission-mediums
112+
def detect_kitty_support [] {
113+
let is_kitty_supported = $"(ansi esc)_Gi=1234,s=1,v=1,a=q,t=d,f=24;AAAA(ansi st)"
114+
return (term query $is_kitty_supported --terminator (ansi st) | "OK" in ($in | decode))
115+
}
72116

73-
let print_filename = (
74-
if $print {
75-
1
76-
}
77-
)
117+
export def detected [] {
118+
print $"Kitty support: (detect_kitty_support)"
119+
print $"Is Screen term: (is-screen-term)"
120+
}
78121

79-
let url_img = (
80-
if $url {
81-
let encoded_image = (b64_encode (http get $url))
82-
print_image $url 1 $encoded_image $print_filename
83-
}
84-
)
122+
# imgcat.nu shows images in your terminal if your terminal supports it
123+
# it uses either the Iterm or the Kitty protocol
124+
export def main [
125+
--help (-h) # Help/Usage message
126+
--print (-p) # Print filename
127+
--url (-u) # Use a URL
128+
--inline (-i) # Inline image (only for iTerm; ignored for Kitty)
129+
filename # The filename to show
130+
] {
131+
if $help {
132+
show_help
133+
}
85134

86-
if ($filename | path exists) {
87-
print_image $filename 1 (b64_encode $filename) $print_filename
88-
} else {
89-
print $"imgcat: ($filename): No such file or directory"
135+
let url_img = (
136+
if $url {
137+
let encoded_image = (b64_encode (http get $url))
138+
print_image $url $encoded_image --inline=$inline --print_filename=$print
90139
}
140+
)
141+
142+
if ($filename | path exists) {
143+
let filename = ($filename | path expand)
144+
print_image $filename (b64_encode $filename) --inline=$inline --print_filename=$print
145+
} else {
146+
print $"imgcat: ($filename): No such file or directory"
147+
}
91148
}

0 commit comments

Comments
 (0)