Module: Imaginator

Extended by:
Imaginator
Included in:
Imaginator
Defined in:
lib/imsg-grep/images/imaginator.rb

Defined Under Namespace

Classes: Image

Instance Method Summary collapse

Instance Method Details

#cell_sizeObject

cell width px, cell height px

(Floats)



86
87
88
89
90
91
92
93
94
# File 'lib/imsg-grep/images/imaginator.rb', line 86

def cell_size # [cell width px, cell height px] (Floats)
  @cell_size ||= case
  when iterm = term_seq("\e]1337;ReportCellSize\e\\", ?\a)[/ReportCellSize=(.*)\e/, 1]
    iterm.split(?;).map{ Float it }.then{ |h, w, s| s ||= 1; [w*s, h*s] } # multiply by retina scale factor
  when csi16t = term_seq("\e[16t", ?t)[/\e\[6;(\d+;\d+)t/, 1] # ghostty
    csi16t.split(?;).map{ Float it }.reverse
  # else calc from TIOCGWINSZ or CSI14/18t, but this is enough for iterm, ghostty
  end
end

#image_tooling?Boolean

Returns:

  • (Boolean)


106
# File 'lib/imsg-grep/images/imaginator.rb', line 106

def image_tooling? = !!(EXTENSION_AVAILABLE && term_image_protocol && cell_size)

#iterm_images?Boolean

Returns:

  • (Boolean)


83
# File 'lib/imsg-grep/images/imaginator.rb', line 83

def iterm_images? = @iterm_images  ||= term_features&.include?(?F)

#iterm_print_image(data:, r: nil, c: nil, io: $stdout) ⇒ Object



108
109
110
111
112
113
114
115
116
117
# File 'lib/imsg-grep/images/imaginator.rb', line 108

def iterm_print_image data:, r:nil, c:nil, io:$stdout
  head = "\e]1337;"
  io << head << "MultipartFile=inline=1;preserveAspectRatio=1"
  io << ";width="  << c if c
  io << ";height=" << r if r
  io << ?\a
  data = [data].pack("m0")
  (0...data.size).step(200).each{ io << head << "FilePart=" << data[it, 200] << ?\a }
  io << head << "FileEnd" << ?\a
end

#kitty_images?Boolean

Returns:

  • (Boolean)


84
# File 'lib/imsg-grep/images/imaginator.rb', line 84

def kitty_images? = @kitty_images  ||= term_seq("\e_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\e\\", "\e\\") == "\e_Gi=31;OK\e\\"

#kitty_print_image(data:, r: nil, c: nil, io: $stdout) ⇒ Object



119
120
121
122
123
124
# File 'lib/imsg-grep/images/imaginator.rb', line 119

def kitty_print_image data:, r:nil, c:nil, io:$stdout
  io << "\e_Gf=100,a=T,t=d"
  io << ",c=" << c if c
  io << ",r=" << r if r
  io << ?; << [data].pack("m0") << "\e\\"
end


126
127
128
129
130
131
132
# File 'lib/imsg-grep/images/imaginator.rb', line 126

def print_image(...)
  return unless image_tooling?
  case term_image_protocol
  when :iterm then iterm_print_image(...)
  when :kitty then kitty_print_image(...)
  end
end

#term_featuresObject



82
# File 'lib/imsg-grep/images/imaginator.rb', line 82

def term_features = @term_features ||= (term_seq("\e]1337;Capabilities\e\\", ?\a) =~ /Capabilities=([A-Za-z0-9]*)/ and $1.scan(/[A-Z][a-z]?\d*/))

#term_image_protocolObject



96
97
98
99
100
101
102
103
104
# File 'lib/imsg-grep/images/imaginator.rb', line 96

def term_image_protocol
  return @term_image_protocol unless @term_image_protocol.nil?
  @term_image_protocol = case
  when ENV["TERM_PROGRAM"] == "Apple_Terminal" then false # it echoes back the kitty query and I don't wanna figure out how not to
  when iterm_images? then :iterm # has to go before kitty as iterm responds ok to kitty query but can't render them
  when kitty_images? then :kitty # you're a kitty! yes you are! and you're sitting there! hi, kitty!
  else false
  end
end

#term_seq(seq, end_marker) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/imsg-grep/images/imaginator.rb', line 64

def term_seq(seq, end_marker)
  t = ->{ Process.clock_gettime Process::CLOCK_MONOTONIC }
  buf = ""
  IO.console.raw do |tty|
    tty << seq
    tty.flush
    timeout = t.() + 0.1
    loop do
      buf << tty.read_nonblock(1)
      break if buf.end_with? end_marker
    rescue IO::WaitReadable
      break if t.() > timeout
      IO.select([tty], nil, nil, 0.01)
    end
  end
  buf
end