#!/bin/sh # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. # 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: die() { echo "ERROR: $*" exit 1 } # Send a DCS sequence through tmux. # Usage: tmux_dcs() { printf '\033Ptmux;\033%s\033\\' "$1" } # Send a DCS sequence through screen. # Usage: 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: 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}" ;; *) echo "${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 < 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 "$@"