-
Notifications
You must be signed in to change notification settings - Fork 33
/
osc52.sh
executable file
·149 lines (129 loc) · 3.04 KB
/
osc52.sh
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
#!/bin/sh
# Copyright 2012 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Max length of the OSC 52 sequence. Sequences longer than this will not be
# sent to the terminal.
OSC_52_MAX_SEQUENCE="100000"
# Write an error message and exit.
# Usage: <message>
die() {
echo "ERROR: $*"
exit 1
}
# Send a DCS sequence through tmux.
# Usage: <sequence>
tmux_dcs() {
printf '\033Ptmux;\033%s\033\\' "$1"
}
# Send a DCS sequence through screen.
# Usage: <sequence>
screen_dcs() {
# Screen limits the length of string sequences, so we have to break it up.
# Going by the screen history:
# (v4.2.1) Apr 2014 - today: 768 bytes
# Aug 2008 - Apr 2014 (v4.2.0): 512 bytes
# ??? - Aug 2008 (v4.0.3): 256 bytes
# Since v4.2.0 is only ~4 years old, we'll use the 256 limit.
# We can probably switch to the 768 limit in 2022.
local limit=256
# We go 4 bytes under the limit because we're going to insert two bytes
# before (\eP) and 2 bytes after (\e\) each string.
echo "$1" | \
sed -E "s:.{$(( limit - 4 ))}:&\n:g" | \
sed -E -e 's:^:\x1bP:' -e 's:$:\x1b\\:' | \
tr -d '\n'
}
# Send an escape sequence to hterm.
# Usage: <sequence>
print_seq() {
local seq="$1"
case ${TERM-} in
screen*)
# Since tmux defaults to setting TERM=screen (ugh), we need to detect
# it here specially.
if [ -n "${TMUX-}" ]; then
tmux_dcs "${seq}"
else
screen_dcs "${seq}"
fi
;;
tmux*)
tmux_dcs "${seq}"
;;
*)
printf '%s' "${seq}"
;;
esac
}
# Base64 encode stdin.
b64enc() {
base64 | tr -d '\n'
}
# Send the OSC 52 sequence to copy the content.
# Usage: [string]
copy() {
local str
if [ $# -eq 0 ]; then
str="$(b64enc)"
else
str="$(echo "$@" | b64enc)"
fi
if [ ${OSC_52_MAX_SEQUENCE} -gt 0 ]; then
local len=${#str}
if [ ${len} -gt ${OSC_52_MAX_SEQUENCE} ]; then
die "selection too long to send to terminal:" \
"${OSC_52_MAX_SEQUENCE} limit, ${len} attempted"
fi
fi
print_seq "$(printf '\033]52;c;%s\a' "${str}")"
}
# Write tool usage and exit.
# Usage: [error message]
usage() {
if [ $# -gt 0 ]; then
exec 1>&2
fi
cat <<EOF
Usage: osc52 [options] [string]
Send an arbitrary string to the terminal clipboard using the OSC 52 escape
sequence as specified in xterm:
https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
Section "Operating System Commands", Ps => 52.
The data can either be read from stdin:
$ echo "hello world" | osc52.sh
Or specified on the command line:
$ osc52.sh "hello world"
Options:
-h, --help This screen.
-f, --force Ignore max byte limit (${OSC_52_MAX_SEQUENCE})
EOF
if [ $# -gt 0 ]; then
echo
die "$@"
else
exit 0
fi
}
main() {
set -e
while [ $# -gt 0 ]; do
case $1 in
-h|--help)
usage
;;
-f|--force)
OSC_52_MAX_SEQUENCE=0
;;
-*)
usage "Unknown option: $1"
;;
*)
break
;;
esac
shift
done
copy "$@"
}
main "$@"