Processing clipboard text through a script in between copy and paste

I want to intercept the paste event and run any text through my script. The use case is like this (assume I have a script somewhere which accepts text on stdin and turns 'world' into 'potato', writing on stdout).

  1. Highlight some text 'hello world!' with the cursor
  2. Middle-mouse click to paste from the selection buffer, and 'hello potato!' appears

There should be no manual step between 1 and 2, i.e. I want a hook on the paste event (or perhaps on the copy event) so that the text is processed automatically. I don't have anything malicious in mind; it's just about auto-formatting some source code when copying/pasting from/to the web.

My question concerns the selection buffer (middle-mouse clipboard), but I guess the question applies to other clipboard text in general too.


Solution 1:

You can use clipnotify to get notified of clipboard changes without polling. From the project page:

while clipnotify; do
    [an event happened, do something with the selection]
done

The tool is only a few lines of C code that uses the XFIXES functionality.

Solution 2:

You can use the following Bash function. Copy it to your ~/.bashrc and source it as . ~/.bashrc from a terminal.

cngstr(){
    echo `xclip -o` | sed -e "s#$1#$2#g" | xclip
}

Usage

  • Highlight any text by selecting it with mouse. As usual the selected text can be pasted using the mouse middle click.
  • Run in terminal:

    $ cngstr "string" "replacement"
    
  • Next when you paste using mouse middle click, the word(s) "string" in your selection will be replaced with "replacement".

Example

Say your selection is "hello world!". Next you run in terminal,

cngstr world potato

Use "" for a string consisting of more than one word. Next when you paste using the mouse middle clip, "hello potato!" will appear. See the screenshots.

Enter image description here

How it works

  1. xclip -o prints the selection to standard output which is being piped to sed here.
  2. Next sed is replacing the strings taking input from the user.
  3. Finally the modified contents are being passed to xclip which put it in the primary selection and becomes available for pasting by a mouse middle click.

I think xclip comes with the default Ubuntu distribution. Otherwise install it through apt-get:

sudo apt-get install xclip

Extra Information

Make the modified contents available to clipboard also

If you want the modified contents also be available to the clipboard so that Ctrl+V also works as well, add the following line in the above script.

echo `xclip -o` | xclip -selection c

The above line will pass the contents of the primary selection to the clipboard. The modified function will look like:

cngstr(){
    echo `xclip -o` | sed -e "s#$1#$2#g" | xclip
    echo `xclip -o` | xclip -selection c
}

A Bash function that can modify contents of the clipboard (i.e., copied using Ctrl+C or from the right click menu) and make the modified string available to the primary selection as well as to the clipboard.

cngstr1(){
    echo `xclip -o -selection c` | sed -e "s#$1#$2#g" | xclip
    echo `xclip -o` | xclip -selection c
}

xclip -o prints the contents of the primary selection by default. Use -selection c to print the contents of the clipboard. See man xclip for more.


You can combine these two functions in a script using a switch case,

#!/bin/sh
string="$2"
replacement="$3"

cngstr(){
    echo `xclip -o` | sed -e "s#$1#$2#g" | xclip
    echo `xclip -o` | xclip -selection c
}

cngstr1(){
    echo `xclip -o -selection c` | sed -e "s#$1#$2#g" | xclip
    echo `xclip -o` | xclip -selection c
}

if [ $# -lt 2 ]
then
    echo "Usage : $0 [c|p] \"string\" \"replacement\" "
    exit
fi

case "$1" in

    c)  cngstr1 "$string" "$replacement"
        ;;
    p)  cngstr "$string" "$replacement"
        ;;
    *) echo "Usage : $0 [c|p] \"string\" \"replacement\" "
        ;;
esac

Usage

./script.sh [c|p] "string" "replacement"
  • Use option c for altering contents copied using the clipboard i.e., contents copied using Ctrl+C or from the right click menu.

  • Use option p for altering the contents copied using the primary selection.