|
1 | 1 | # 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 | +} |
2 | 7 |
|
3 | 8 | 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 |
9 | 13 | } |
10 | 14 |
|
11 | 15 | 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" |
17 | 20 | } |
18 | 21 |
|
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 |
21 | 60 | } |
22 | 61 |
|
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 |
25 | 85 | } |
26 | 86 |
|
| 87 | +# Determine the appropriate protocol and print the image |
27 | 88 | 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 |
32 | 93 | ] { |
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 | + } |
51 | 99 | } |
52 | 100 |
|
53 | 101 | def error [] { |
54 | | - print "Error: ($env.LAST_EXIT_CODE)" |
| 102 | + print "Error: ($env.LAST_EXIT_CODE)" |
55 | 103 | } |
56 | 104 |
|
57 | 105 | 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" |
60 | 108 | } |
61 | 109 |
|
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 | +} |
72 | 116 |
|
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 | +} |
78 | 121 |
|
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 | + } |
85 | 134 |
|
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 |
90 | 139 | } |
| 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 | + } |
91 | 148 | } |
0 commit comments