Auto-type the contents of your clipboard
Why auto-type the clipboard?
Thereβs infrequent occasions I canβt paste something but really need to. Usually itβs when iβm using Spice to perform a new OS install or iβm looking at a TTY. Thereβs also times I have to use specific remote viewers for work that donβt have clipboard support.
Why isnβt this an xdotool one-liner script?
Auto-typing the contents of the clipboard is deceptively difficult. It can be done in a one-liner but the outcome is best summarized as spray and pray.
- Most auto-typers including
xdotool
will turn accidental presses of ctrl, shift and alt into shortcut commands (see: fireworks). This is especially problematic if youβre launching the one-liner with a shortcut combo as itβll react to these keys the moment it starts. - Itβs a freight train that wonβt stop till itβs done, hope you pasted to the right place.
- Unless that one-liner is very long, thereβs no removal of artifacts or trailing newlines. If text is selected from a document to the last letter of a line, itβll always include a newline which will auto-run commands if pasted to a terminal and produce un-intuitive auto-type results.
All thatβs fixed, introducingβ¦
cliptokeys
( pronounced like an ancient Roman name )
- Auto-types the contents of the keyboard at a user defined rate.
- Stops typing the moment the current window loses focus so it can be ended with a mouse click.
- Freezes keyboard input until typing finishes which maintains typing integrity.
- Removes the trailing newline associated with selecting text to the end of the line.
- When encountering a newline, the Enter key is pressed.
#!/bin/env sh
# To do: <FOSS License here>
# Examples of usage:
# cliptokeys
# cliptokeys 0.5 # 0.5 seconds between keystrokes
# Dependencies:
# xdotool, xinput and (xsel or xclip)
# Installation:
# mkdir -p ~/.local/bin/
# mv ./cliptokeys ~/.local/bin/
# chmod u+x ~/.local/bin/cliptokeys
TypeWaitSec=$1;
[ -z "$TypeWaitSec" ] && TypeWaitSec='0.05'
# Check for missing package(s)
if ! which xinput 2> /dev/null; then
echo "Missing package: xinput"
exit
elif ! which xdotool 2> /dev/null; then
echo "Missing package: xdotool"
exit
fi
FocusedWindowId=$(xdotool getwindowfocus)
# Get clipboard contents
if which xsel 2> /dev/null; then
ClipOut=$(xsel -ob)
elif which xclip 2> /dev/null; then
ClipOut=$(xclip -o -sel c)
else
echo "Missing package: xsel OR xclip"
exit
fi
# Handle keyboard locking
KeyboardIds=$(xinput list | grep keyboard | cut -d '=' -f 2 | cut -f 1)
KeyboardStates() {
for Id in $KeyboardIds; do xinput --$1 $Id; done
}
trap 'KeyboardStates enable' EXIT
KeyboardStates disable
# Read the output of the clipboard one character at a time into xdotool to type
CharCount=0
ClipOutLen=$(wc -c <<< $ClipOut) # Note: Using `expr` doesn't count last newline
while read -rN1 Char; do
(( CharCount++ ))
# If the current window loses focus, exit
[ "$FocusedWindowId" != "$(xdotool getwindowfocus)" ] && exit
if [ "$Char" = $'\n' ]; then
# If the newline isn't the last character type the Enter key. Otherwise ignore.
[ "$CharCount" -ne "$ClipOutLen" ] && xdotool key Return
else
xdotool type "$Char"
fi
sleep $TypeWaitSec
done <<< $ClipOut
Working with remote viewers
Remote viewers often capture keystrokes so local keyboard shorcuts donβt work. You can get around this by clicking on the titlebar of the viewer, hit your chosen shortcut to start the script and it should βtypeβ the text into the focused window inside the viewer. In my case it this works with spice
viewer launched from virt-manager
.