Skip to content

Instantly share code, notes, and snippets.

@Ertavf
Forked from RichardBronosky/README.MD
Created February 8, 2022 09:59
Show Gist options
  • Save Ertavf/e041560dcc859474e9d4b8a8cb3dd26b to your computer and use it in GitHub Desktop.
Save Ertavf/e041560dcc859474e9d4b8a8cb3dd26b to your computer and use it in GitHub Desktop.
cb - A leak-proof tee to the clipboard - Unify the copy and paste commands into one intelligent chainable command.

cb

A leak-proof tee to the clipboard

This script is modeled after tee (see man tee) and works on Linux, macOS, Cygwin, WSL/WSL2

It's like your normal copy and paste commands, but unified and able to sense when you want it to be chainable.

This project started as an answer to the StackOverflow question: How can I copy the output of a command directly into my clipboard?

Examples

Copy

$ echo -n $(date) | cb
# clipboard contains: Tue Jan 24 23:00:00 EST 2017
# but, because of `echo -n` there is no newline at the end

Paste

# clipboard retained from the previous block
$ cb
Tue Jan 24 23:00:00 EST 2017
# above there is a newline after the output for readability
# below there is no newline because cb recognized that it was outputing to a pipe and any alterations would "contaminate" the data
$ cb | cat
Tue Jan 24 23:00:00 EST 2017$ cb > foo
# look carefully at this   ^^ that's a new $ prompt at the end of the content exactly as copied
$ cat foo
Tue Jan 24 23:00:00 EST 2017

Chaining

$ date | cb | tee updates.log
Tue Jan 24 23:11:11 EST 2017
$ cat updates.log
Tue Jan 24 23:11:11 EST 2017
# clipboard contains: Tue Jan 24 23:11:11 EST 2017
#!/bin/bash
# from: https://gist.github.com/RichardBronosky/56d8f614fab2bacdd8b048fb58d0c0c7
LINUX_copy(){
cat | xclip -selection clipboard
}
LINUX_paste(){
xclip -selection clipboard -o
}
WSL_copy(){
cat | /mnt/c/Windows/System32/clip.exe
}
WSL_paste(){
/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe Get-Clipboard | sed 's/\r//'
}
CYGWIN_copy(){
cat > /dev/clipboard
}
CYGWIN_paste(){
cat /dev/clipboard
}
MAC_copy(){
cat | pbcopy
}
MAC_paste(){
pbpaste
}
stdin_is_a_pipe(){
[[ -p /dev/stdin ]]
}
stdin_is_a_tty(){
[[ -t 0 ]]
}
stdin_is_pipe_like(){
stdin_is_a_pipe || ! stdin_is_a_tty
}
stdout_is_pipe_like(){
! stdout_is_a_tty # meaning # it must be a pipe or redirection
}
stdout_is_a_tty(){
[[ -t 1 ]]
}
requested_open_ended(){
[[ "${args[0]:-}" == "-" ]]
}
requested_test_suite(){
[[ "${args[0]:-}" == "--test" ]]
}
enable_tee_like_chaining(){
# see `man tee`
if stdout_is_pipe_like; then
${os}_paste
elif requested_open_ended; then
${os}_paste
echo
fi
}
prevent_prompt_from_being_on_the_same_line(){
if stdout_is_a_tty; then # we don't have to be strict about not altering the output
echo
fi
}
detect_os(){
if [[ -f /proc/version ]] && grep -iq Microsoft /proc/version; then
printf WSL
else
case "$(uname -s)" in
Linux*) printf LINUX;;
Darwin*) printf MAC;;
CYGWIN*) printf CYGWIN;;
esac
fi
}
test_suite(){
# setup
printf '1234' | ${BASH_SOURCE[0]}
printf "\n1. output to TTY\n"
${BASH_SOURCE[0]}
printf "1234 should be above.\n"
printf "\n2. output to pipe\n"
${BASH_SOURCE[0]} | cat; echo
printf "1234 should be above.\n"
printf "\n3. input from pipe and output to pipe\n"
printf '1234' | ${BASH_SOURCE[0]} | cat; echo
printf "1234 should be above.\n"
}
function debug(){
stdin_is_a_pipe && echo "stdin_is_a_pipe: 1" >> /tmp/ono || echo "stdin_is_a_pipe: 0" >> /tmp/ono
stdin_is_a_tty && echo "stdin_is_a_tty: 1" >> /tmp/ono || echo "stdin_is_a_tty: 0" >> /tmp/ono
stdin_is_pipe_like && echo "stdin_is_pipe_like: 1" >> /tmp/ono || echo "stdin_is_pipe_like: 0" >> /tmp/ono
stdout_is_pipe_like && echo "stdout_is_pipe_like: 1" >> /tmp/ono || echo "stdout_is_pipe_like: 0" >> /tmp/ono
stdout_is_a_tty && echo "stdout_is_a_tty: 1" >> /tmp/ono || echo "stdout_is_a_tty: 0" >> /tmp/ono
echo >> /tmp/ono
}
main(){
os="$(detect_os)"
if stdin_is_pipe_like; then
${os}_copy
enable_tee_like_chaining
else # stdin is not pipe-like
${os}_paste
prevent_prompt_from_being_on_the_same_line
fi
}
args=("$@")
if requested_test_suite; then
export DEBUG=1
test_suite
else
[[ ${DEBUG:-} == 1 ]] && debug
main
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment