Skip to content

Instantly share code, notes, and snippets.

@sshaw
Last active July 28, 2016 20:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sshaw/3687e4acdc2e1e9080d3dff04474e4e5 to your computer and use it in GitHub Desktop.
Save sshaw/3687e4acdc2e1e9080d3dff04474e4e5 to your computer and use it in GitHub Desktop.
Ruby class & program to take an image and output it using an iTerm2 escape sequence. Supports all of the iTerm2 image protocol.
require "base64"
#
# Take an image and output it using an iTerm2 escape sequence.
# Supports all of the iTerm2 image protocol: https://iterm2.com/documentation-images.html
#
# https://gist.github.com/sshaw/3687e4acdc2e1e9080d3dff04474e4e5
module ITerm2
class Image
def initialize(image, options = {})
@options = options.dup
@options[:inline] = true unless @options.include?(:inline)
@screen = @options.delete(:screen)
@image = Base64.encode64(File.read(image))
end
def print
# Respect screen escapes being explicitly turned off
if !screen_tty? || @screen == false
puts to_s
return
end
begin
old = @screen
@screen = true
puts to_s
ensure
@screen = old
end
end
def to_s
encode_image
end
private
def screen_tty?
$stdout.tty? && ENV.include?("TERM") && ENV["TERM"].start_with?("screen")
end
def encode_image
sprintf("%s1337;File=%s:%s%s", start_esc, format_options, @image, end_esc)
end
# From imgls: https://raw.githubusercontent.com/gnachman/iTerm2/master/tests/imgls
def start_esc
@screen == true ? "\033Ptmux;\033\033]" : "\033]"
end
def end_esc
@screen == true ? "\a\033\\" : "\a"
end
# --
def bool_option(value)
value == false ? 0 : 1
end
def format_options
@options.map do |name, value|
case name
when :preserve_aspect_ratio
name = "preserveAspectRatio"
value = bool_option(value)
when :inline
value = bool_option(value)
when :name
value = Base64.encode64(value)
end
sprintf "%s=%s", name, value
end.join(";")
end
end
end
def iTerm2
ITerm2
end
if $0 == __FILE__
require "optparse"
options = {}
OptionParser.new do |opts|
opts.banner = "usage: #{File.basename($0)} [options] file1..."
opts.on "-d", "--dimension [WIDTHxHEIGHT]" do |d|
# TODO: Use OptionParser regex support
if d =~ /(\d+(?:px|%)?)x(\d+(?:px|%)?)/i
options[:width] = $1
options[:height] = $2
end
end
opts.on "-i", "--[no-]inline", TrueClass, "Display inline" do |inline|
options[:inline] = inline
end
opts.on "-n", "--name [FILENAME]", "Filename" do |name|
options[:name] = name
end
opts.on "-p", "--[no-]preserve-aspect-ratio", TrueClass do |ar|
options[:preserve_aspect_ratio] = ar
end
opts.on "-w", "--width [WIDTH]", Integer do |w|
options[:width] = w
end
opts.on "-h", "--height [HEIGHT]", Integer do |h|
options[:height] = h
end
end.parse!
abort "images required" unless ARGV.any?
ARGV.each { |path| iTerm2::Image.new(path, options).print }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment