A Linux/Wayland equivalent of the classic AutoHotkey trick for cleaning up copied text from PDF viewers. Removes mid-sentence line breaks introduced by PDF column layout, replacing them with spaces — while preserving true paragraph breaks.
Tested on: CachyOS Linux · KDE Plasma 6.6.3 · Wayland
On Windows, AutoHotkey can intercept Ctrl+C globally and post-process the clipboard.
#Requires AutoHotkey v2.0
#SingleInstance Force
; Create window group
GroupAdd("GroupName", "ahk_class SUMATRA_PDF_FRAME")
GroupAdd("GroupName", "ahk_class PXE:{C5309AD3-73E4-4707-B1E1-2940D8AF3B9D}")
GroupAdd("GroupName", "ahk_class classFoxitPhantom")
GroupAdd("GroupName", "ahk_class classFoxitReader")
#HotIf WinActive("ahk_group GroupName")
^c:: {
old := ClipboardAll()
A_Clipboard := ""
Send("^c")
if !ClipWait(0.8) {
A_Clipboard := old
} else {
tmp := RegExReplace(A_Clipboard, "(\S.*?)\R(.*?\S)", "$1 $2")
; Replace double spaces with single spaces until no more remain
while InStr(tmp, " ")
tmp := StrReplace(tmp, " ", " ")
A_Clipboard := tmp
}
old := ""
tmp := ""
}
#HotIfWayland intentionally disallows this for security reasons. The workaround is a separate shortcut (Ctrl+Alt+C) that:
- Sends a real Ctrl+C to the focused window (via
ydotool) - Polls until the clipboard actually changes (like AHK's
ClipWait) - Applies a regex to join mid-sentence line breaks
- Writes the cleaned text back to the clipboard
Because Ctrl+Alt+C is a conscious action, no window class filtering is needed — you simply use it only when you're in a PDF viewer.
sudo pacman -S ydotool wl-clipboard pythonydotool— injects keystrokes via/dev/uinput, bypassing the compositor entirely. Works on any Wayland compositor.wl-clipboard— provideswl-pasteandwl-copyfor Wayland clipboard access.python— for the regex cleaning step.
ydotool needs access to /dev/uinput. The package ships a udev rule that
grants the input group this access.
sudo usermod -aG input $USERThen reboot — a simple logout/login may not be sufficient because systemd can preserve the old user session without the new group.
After rebooting, verify:
groups | grep inputinput should appear in the output.
ydotool is a client that talks to ydotoold (the daemon). The package
ships a systemd user service:
systemctl --user enable --now ydotool.service
systemctl --user status ydotool.serviceThe service should show Active: active (running). If it fails, check that
the reboot in Step 2 was completed and the input group is active.
Save the following as ~/.local/bin/pdf-clean-copy.sh:
#!/bin/bash
sleep 0.8
# Save current clipboard to detect change
old=$(wl-paste --no-newline 2>/dev/null)
# Inject Ctrl+C into the focused window (evdev keycodes: 29=Ctrl, 46=C)
# --key-delay 50: 50ms between events prevents stuck modifier keys
ydotool key --key-delay 50 29:1 46:1 46:0 29:0
text="$new"
[ -z "$text" ] && exit 0
# Clean the text using Python regex
# Faithfully ports the original AHK regex: (\S.*?)\R(.*?\S) → $1 $2
# [^\r\n] is used intentionally — re.S/re.DOTALL must NOT be used here,
# as it would allow .* to span multiple lines and cause incorrect merges
cleaned=$(printf '%s' "$text" | python3 -c "
import sys, re
text = sys.stdin.read()
result = re.sub(r'(\S[^\r\n]*?)\r?\n([^\r\n]*?\S)', r'\1 \2', text)
result = re.sub(r' {2,}', ' ', result)
sys.stdout.write(result)
")
# Write back only if text actually changed
[ "$cleaned" != "$text" ] && printf '%s' "$cleaned" | wl-copyMake it executable:
chmod +x ~/.local/bin/pdf-clean-copy.sh- Open System Settings → Keyboard → Shortcuts
- Scroll to the bottom → Custom Shortcuts
- Click Edit → New → Global Shortcut → Command/URL
- Set:
- Name: PDF Clean Copy
- Trigger:
Ctrl+Alt+C - Action:
/home/yourusername/.local/bin/pdf-clean-copy.sh
KDE applies the shortcut immediately — no restart needed.
- Open any PDF in your viewer (Okular, PDF-XChange via Wine, Evince, etc.)
- Select text that has broken line endings
- Press Ctrl+Alt+C instead of Ctrl+C
- Paste anywhere — line breaks within sentences are replaced with spaces, paragraph breaks are preserved
ydotool.service fails to start
- Confirm
inputgroup is active:groups | grep input - If missing, reboot (logout alone may not be enough)
- Check udev rule:
cat /usr/lib/udev/rules.d/80-uinput.rules— should grantGROUP="input"onuinput
Line breaks not being removed
- The PDF viewer may be slow to populate the clipboard
- increase sleep timer
- Why not Ctrl+C directly? Wayland's security model prevents any application from intercepting or suppressing another app's keyboard shortcuts globally. A separate shortcut is the correct solution, not a workaround.
- Why not
wl-paste --watch? Passive clipboard watching applies to all copies everywhere. A deliberate shortcut is cleaner and more predictable. - Why not
wtype? KDE Plasma does not expose thezwp_virtual_keyboard_v1protocol by default.ydotoolbypasses the compositor via the kerneluinputinterface instead.