Controlling the clipboard via Zenity and Xclip

Gnome, Unity, and KDE all have their own clipboard managing applications; they provide extensive features and are well integrated into the desktop. However, they are not necessarily easily integrated into other window managers. Those who do not use a top of the line desktop might be left without a clipboard manager. Another problem is that these programs usually create a history of the clipboard in which the older entries are continuously pushed back and eventually disappear from the list.

The Right Tools

Typically, to adapt an application as quickly as possible, all you need are the right tools, some creativity, and a little bit of imagination. This also holds true for the implementation of a tailor-made clipboard management app. I'll show how you can set up sleek dialogs for the script of the clipboard using Xclip [1] with Zenity [2].

Both Zenity and Xclip can be installed quickly using your package manager of choice. Both pieces of software can be installed via Apt or Yum using the command sudo apt-get install zenity xclip on DEB-based systems (e.g., Ubuntu) or yum install zenity xclip on a RPM-based computer.

The clipboard presented here comprises 10 memory slots. The content in these memory locations can be allocated, recalled, deleted, or manually revised retroactively with an editor.

A Few Lines of Script

Listing 1 begins by setting a fixed editor that allows you to manually and retroactively revise individual actions of the clipboard. This also defines a directory for the contents of the clipboard. The command test in line 4 checks whether the directory already exists. If the check determines that there is no directory in existence, then it creates one.

Listing 1

Personal Clipboard

01 #!/bin/bash
02 EDITOR=gedit
03 STORAGEPATH=~/.clipboard
04 test ! -d $STORAGEPATH && mkdir $STORAGEPATH
05
06 for x in $(seq 1 10); do
07   test ! -f ${STORAGEPATH}/slot${x} && > ${STORAGEPATH}/slot${x}
08 done
09
10 action=$1
11 length=80
12
13 sp=$(zenity --list --title="Select slot" \
14      --text "Slot ${1}!\nCurrently in the clipboard: \
15             $(xclip -o | cut -c 1-${length})" \
16      --column "Slots" \
17      "Slot 1: $(cat ${STORAGEPATH}/slot1 | cut -c 1-${length})" \
18      "Slot 2: $(cat ${STORAGEPATH}/slot2 | cut -c 1-${length})" \
19      "Slot 3: $(cat ${STORAGEPATH}/slot3 | cut -c 1-${length})" \
20      "Slot 4: $(cat ${STORAGEPATH}/slot4 | cut -c 1-${length})" \
21      "Slot 5: $(cat ${STORAGEPATH}/slot5 | cut -c 1-${length})" \
22      "Slot 6: $(cat ${STORAGEPATH}/slot6 | cut -c 1-${length})" \
23      "Slot 7: $(cat ${STORAGEPATH}/slot7 | cut -c 1-${length})" \
24      "Slot 8: $(cat ${STORAGEPATH}/slot8 | cut -c 1-${length})" \
25      "Slot 9: $(cat ${STORAGEPATH}/slot9 | cut -c 1-${length})" \
26      "Slot 10: $(cat ${STORAGEPATH}/slot10 | cut -c 1-${length})" \
27      | sed "1 s/Slot /slot/1" | grep -Eo "slot[0-9]{1,2}")
28
29 if [ $action = "save" ] && [ $(echo -n $sp | wc -m) -gt 0 ] 2>/dev/null; then
30   xclip -o > ${STORAGEPATH}/${sp}
31 elif [ $action = "retrieve" ] && [ $(echo -n $sp | wc -m) -gt 0 ] 2>/dev/null; then
32   cat ${STORAGEPATH}/${sp} | xclip -i -selection primary
33   cat ${STORAGEPATH}/${sp} | xclip -i -selection secondary
34   cat ${STORAGEPATH}/${sp} | xclip -i -selection clipboard
35 elif [ $action = "delete" ] && [ $(echo -n $sp | wc -m) -gt 0 ] 2>/dev/null; then
36   > ${STORAGEPATH}/${sp}
37 elif [ $action = "edit" ] && [ $(echo -n $sp | wc -m) -gt 0 ] 2>/dev/null; then
38   $EDITOR ${STORAGEPATH}/${sp}
39 fi

The code block at lines 6 through 8 creates the individual memory slots for the clipboard. A for loop operates from a list created by the command seq 1 10 . Within the block, between do and done , each digit appears instead of the line ${x} . Line 7 first tests whether the files slot1 to slot10 are in the directory. If this is true, then the redirection operator > gets executed at the end of line 7, creating the slot.

In line 10, the script grabs the first parameter passed on to the script and stores it in the variable action . Line 11 defines the maximum length of the character string, which should be displayed in the Zenity dialog. This prevents trying to store an excessively long string in one of the memory locations of the corresponding dialog. The first 80 characters should be plenty to indicate which text is saved to each slot.

In the Dialog

The lines 13 to 27 generate the actual Zenity dialog [3]. The dialog is enclosed in brackets preceded by a dollar sign. This is how the script stores the result in a variable, which allows you to change it later. The variable sp will store the output from the dialog.

Zenity generates a selection dialog for --title and --text by using the parameter --list . Zenith also generates a set of meaningful displays for both items.

The command cut 1-${length} restricts the output text to a maximum of 80 characters; note, however, that the content that is actually stored on the clipboard can be much longer. Eighty is just the number of characters shown.

Line 16 sets the column header, which is followed by the entries, each of which is enclosed within quotation marks. The content begins with Slot<lfdNr> and is followed by the output of the content of the corresponding text file using cat command. The cut command then shears the output down to the maximum length of 80 characters.

Because a relatively long character string would now be in the variable sp , it is necessary to remove unnecessary content and to modify partitions. At the beginning of each selection is the word "Slot" followed by a space and the number of the memory location.

The sed command at the beginning of line 27 alters the slot name taken from the "Slot" string. In the process, I want to explicitly show only the first line of the address, because the clipboard slot may well contain multiple lines. Because the word "Slot" is followed by a space, I can also get rid of that.

The number one (1 ) at the end of sed's s (substitution) command causes the program to only make changes in the first occurrence of the expression.

The grep command in the second half of line 27 extracts the content from the content of the clipboard itself, which places it into the sp variable. The values will be from slot1 to slot10 .

Wild Activism

Next, the block of commands from line 29 to 39 checks the contents of the variable action in order to undertake one of four possible actions with the clipboard content.

The first if statement is used if you make the first parameter of the script a save command. This command saves the value in the clipboard into the slot determined by sp . The script uses the shortened form of the test command (i.e., square brackets to enclose the test to be evaluated).

At this point, the script returns the contents of variable sp and uses the echo -n command (-n disables the line break \n ) to count the number of words in the string via wc -m in the next step of the pipe. The length is 0 for unused variables. This lets you test whether the user has made a selection on the previous screen and whether you can proceed with the script. This step then assigns the current content of the clipboard to the selected slot.

The second condition, the elif on line 31, implements the retrieve action after having made a selection in the dialog. In this case, the script will activate the Xclip command and fill the clipboard with the contents of a selected slot. Xclip comes with three areas (primary (Standard), secondary or simply clipboard ) that can contain data.

To tell Xclip which part of the clipboard you want to fill, Xclip provides the -selection option. You can enter primary (standard), secondary , or simply clipboard . Because not all window managers and applications use the clipboard assign (or retrieve) in the same way, the script fills all three areas of the clipboard with the same data (lines 32 to 34), so that the selected text is available for all programs.

Line 35 checks whether the delete action delete has been passed to the script and if you have actually selected an entry. If you have done so, it erases the contents of the corresponding memory location.

Last but not least, line 37 takes care of the edit action, edit . Line 38 delivers the content of the selected memory slot to the text editor set in line 2.

Shortcuts

You can easily set up helpful keyboard shortcuts to use your clipboard, and then you won't have to remember the parameters or input them by hand.

To do this in Unity, you can look for System Settings under the gear menu (in the upper right-hand corner of your screen), select Keyboard and open the Shortcuts tab.

In Gnome, the process is virtually the same: Go to System settings | Keyboard | Keyboard shortcuts . Do the same in KDE. When using other window managers, you can typically find the appropriate settings under the keyboard entry in the desktop configuration app.

You will then have to enter the path to the script together with one of the following parameters: retrieve , save , delete , or edit . The commands used to create four shortcuts (Figure 1) are shown in Listing 2. After defining the commands, you can fill in the key combination that will trigger the shortcut.

Figure 1: How to set keyboard shortcuts for the script with four different parameters.

Listing 2

Create Keyboard Shortcuts

/home/MyDirectory/clipboard.sh save
/home/MyDirectory/clipboard.sh retrieve
/home/MyDirectory/clipboard.sh delete
/home/MyDirectory/clipboard.sh edit

Conclusion

Now, you have a clipboard (Figure 2) that you can extend and customize as you wish. For example, you could add additional memory locations and have the current date, contact information, or other frequently used content ready to copy and paste wherever you need it. Zenity and Xclip lets you get up and running easily, and the clipboard can be used in most window managers. You only need to create the corresponding keyboard shortcuts.

Figure 2: The clipboard in action: a space filled with the current value of the clipboard.

Infos

  1. Xclip: http://xclip.sourceforge.net
  2. Zenity: http://live.gnome.org/Zenity
  3. "Automating tasks with SSH, Zenity, Yad, KDialog, PuTTY, WinSCP, and Rex Secure Agent" by Tim Schürmann, Linux Magazine , 146: http://www.linux-magazine.com/Issues/2013/146/Script-Dialogs/%28language%29/eng-US