-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiterm_wez.go
157 lines (117 loc) · 3.25 KB
/
iterm_wez.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package igo
import (
"bytes"
"encoding/base64"
"fmt"
"image"
"image/jpeg"
"image/png"
"io"
"strconv"
"strings"
)
const (
ITERM_IMG_HDR = "\x1b]1337;File="
ITERM_IMG_FTR = "\a"
)
type ItermImgOpts struct {
// Filename. Defaults to "Unnamed file".
Name string
// Width to render. See notes below.
Width string
// Height to render. See notes below.
Height string
// The width and height are given as a number followed by a unit, or the word "auto".
//
// - N: N character cells.
// - Npx: N pixels.
// - N%: N percent of the session's width or height.
// - auto: The image's inherent size will be used to determine an appropriate dimension.
// File size in bytes. Optional; this is only used by the progress indicator.
Size int64
// If set, the file will be displayed inline. Otherwise, it will be downloaded
// with no visual representation in the terminal session.
DisplayInline bool
// If set, the image's inherent aspect ratio will not be respected.
IgnoreAspectRatio bool
}
func (o ItermImgOpts) ToHeader() string {
var opts []string
if o.Name != "" {
opts = append(opts, "name="+base64.StdEncoding.EncodeToString([]byte(o.Name)))
}
if o.Width != "" {
opts = append(opts, "width="+o.Width)
}
if o.Height != "" {
opts = append(opts, "height="+o.Height)
}
if o.Size > 0 {
opts = append(opts, "size="+strconv.FormatInt(o.Size, 10))
}
// default: inline=0
if o.DisplayInline {
opts = append(opts, "inline=1")
}
// default: preserveAspectRatio=1
if o.IgnoreAspectRatio {
opts = append(opts, "preserveAspectRatio=0")
}
return ITERM_IMG_HDR + strings.Join(opts, ";") + ":"
}
// NOTE: uses $TERM_PROGRAM, which isn't passed through tmux or ssh
// checks if iterm inline image protocol is supported
func IsItermCapable() bool {
V := GetEnvIdentifiers()
if V["TERM"] == "mintty" {
return true
}
if V["LC_TERMINAL"] == "iterm2" {
return true
}
if V["TERM_PROGRAM"] == "wezterm" {
return true
}
return false
}
/*
Encode image using the iTerm2/WezTerm terminal image protocol:
https://iterm2.com/documentation-images.html
*/
func ItermWriteImageWithOptions(out io.Writer, iImg image.Image, opts ItermImgOpts) error {
pBuf := new(bytes.Buffer)
var E error
// NOTE: doing this under suspicion that wezterm PNG handling is slow
if _, bOK := iImg.(*image.Paletted); bOK {
// PNG IF PALETTED
E = png.Encode(pBuf, iImg)
} else {
// JPG IF NOT
E = jpeg.Encode(pBuf, iImg, &jpeg.Options{Quality: 93})
}
if E != nil {
return E
}
opts.Size = int64(pBuf.Len())
return ItermCopyFileInlineWithOptions(out, pBuf, opts)
}
func ItermCopyFileInlineWithOptions(out io.Writer, in io.Reader, opts ItermImgOpts) (E error) {
if _, E = fmt.Fprint(out, opts.ToHeader()); E != nil {
return
}
enc64 := base64.NewEncoder(base64.StdEncoding, out)
if _, E = io.Copy(enc64, in); E != nil {
return
}
if E = enc64.Close(); E != nil {
return
}
_, E = out.Write([]byte(ITERM_IMG_FTR))
return
}
func ItermWriteImage(out io.Writer, iImg image.Image) error {
return ItermWriteImageWithOptions(out, iImg, ItermImgOpts{DisplayInline: true})
}
func ItermCopyFileInline(out io.Writer, in io.Reader, nLen int64) (E error) {
return ItermCopyFileInlineWithOptions(out, in, ItermImgOpts{DisplayInline: true, Size: nLen})
}