Skip to content

Commit

Permalink
chore: 🧹 update imgcat and add support for kitty
Browse files Browse the repository at this point in the history
  • Loading branch information
melMass authored Jan 16, 2025
1 parent 14e3ecb commit 6e7b738
Showing 1 changed file with 121 additions and 64 deletions.
185 changes: 121 additions & 64 deletions sourced/imaging/imgcat.nu
Original file line number Diff line number Diff line change
@@ -1,91 +1,148 @@
# https://iterm2.com/documentation-images.html
# https://sw.kovidgoyal.net/kitty/graphics-protocol/

def is-screen-term [] {
$env.TERM =~ ^screen
}

def print_osc [] {
if $env.TERM == screen* {
"\ePtmux;\e\e]"
} else {
"\e]"
}
if (is-screen-term) {
return "\ePtmux;\e\e]"
}
ansi escape_right
}

def print_st [] {
if $env.TERM == screen* {
"\a\e\\"
} else {
"\a"
}
if (is-screen-term) {
return "\a\e\\"
}
"\a"
}

def --env b64_encode [fn] {
open $fn | encode base64
def b64_encode [fn] {
open -r $fn | encode base64
}

# Print an image using the iTerm protocol
def print_iterm_image [
filename: path
base64contents: string
--inline
--print_filename
] {
let b64_enc_data = (b64_encode $filename)
let b64_dec_data = ($base64contents | decode base64)
let query = (
[(print_osc)]
| append "1337;File="
| append (
if ($filename | str length) > 0 {
$"name=($b64_enc_data);"
}
)
| append $"size=($b64_dec_data | bytes length)"
| append (
if $inline {
$";inline=1"
}
)
| append ":"
| append $base64contents
| append (print_st)
| append "\n"
)

if $print_filename {
print -n $filename
}

$query | str join
}

def --env b64_decode [fn] {
$fn | decode base64
# Print an image using the Kitty protocol
def print_kitty_image [
filename: path
base64contents: string
--print_filename
] {

let b64_dec_data = ($base64contents | decode base64)
let size = ($b64_dec_data | bytes length)

let result = (
["\e"]
| append "_G"
| append $"a=T,f=100,t=d,s=($size);"
| append $base64contents
| append (ansi st)
)

if $print_filename {
print -n $filename
}

$result | str join
}

# Determine the appropriate protocol and print the image
def print_image [
filename # Filename to convey to client
inline # 0 or 1
base64contents # Base64-encoded contents
print_filename # If non-empty, print the filename before outputting the image
filename: path
base64contents: string
--inline # Only for iTerm; ignored for Kitty
--print_filename
] {
let a = (print_osc)
let b = "1337;File="
let c = (if ($filename | length) > 0 {
let b64_enc_data = (b64_encode $filename)
$"name=($b64_enc_data);"
})
let b64_dec_data = (b64_decode $base64contents)
let d = $"size=($b64_dec_data | bytes length)"
let e = $";inline=($inline)"
let f = ":"
let g = $base64contents
let h = print_st
let i = "\n"
let j = (if ($print_filename | length) > 0 {
print -n $filename
})

[ $a $b $c $d $e $f $g $h $i $j ] | str join
if (detect_kitty_support) {
print_kitty_image $filename $base64contents --print_filename=$print_filename
} else {
print_iterm_image $filename $base64contents --inline=$inline --print_filename=$print_filename
}
}

def error [] {
print "Error: ($env.LAST_EXIT_CODE)"
print "Error: ($env.LAST_EXIT_CODE)"
}

def show_help [] {
print "Usage: imgcat [-p] filename ..."
print " or: cat filename | imgcat"
print "Usage: imgcat [-p] filename ..."
print " or: cat filename | imgcat"
}

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

let print_filename = (
if $print {
1
}
)
export def detected [] {
print $"Kitty support: (detect_kitty_support)"
print $"Is Screen term: (is-screen-term)"
}

let url_img = (
if $url {
let encoded_image = (b64_encode (http get $url))
print_image $url 1 $encoded_image $print_filename
}
)
# imgcat.nu shows images in your terminal if your terminal supports it
# it uses either the Iterm or the Kitty protocol
export def main [
--help (-h) # Help/Usage message
--print (-p) # Print filename
--url (-u) # Use a URL
--inline (-i) # Inline image (only for iTerm; ignored for Kitty)
filename # The filename to show
] {
if $help {
show_help
}

if ($filename | path exists) {
print_image $filename 1 (b64_encode $filename) $print_filename
} else {
print $"imgcat: ($filename): No such file or directory"
let url_img = (
if $url {
let encoded_image = (b64_encode (http get $url))
print_image $url $encoded_image --inline=$inline --print_filename=$print
}
)

if ($filename | path exists) {
let filename = ($filename | path expand)
print_image $filename (b64_encode $filename) --inline=$inline --print_filename=$print
} else {
print $"imgcat: ($filename): No such file or directory"
}
}

0 comments on commit 6e7b738

Please sign in to comment.