Page image
A method to control scripts on window managers using files
Making a toggleable clipboard watcher for automatic dictionary lookup
Published: Aug 16, 2025
Updated: Dec 27, 2025

The wl-paste command from wl-clipboard has a --watch flag that allows you to run a command with the copied text passed in as input. This is an awesome feature if you wanted to integrate your clipboard to a script or program, for example, looking up words on dictionaries automatically by just copying the text.

The only problem is that you don’t always want every copy to be looked up. Like when you are reading a novel in a foreign language, for example, sometimes you may take a break and go to some other apps, if in case you needed to copy something there, a dictionary pop-up would show up! You will have to kill the script and run it again for this to not happen, which would be a hassle to manage, so I came up with an idea: just use file to manage the state of these scripts.

GoldenDict pop-up

Let’s write a script that monitors your clipboard and send all copies to a dictionary. I’ll be using GoldenDict-ng as my dictionary.

1read query
2goldendict -s "$query"

The above script simply reads the standard input (which will be our copied text) and send it to GoldenDict. Now to start clipboard monitoring, you just run:

1wl-paste --watch sh /path/to/script.sh

It is should be working as expected now. But like I said in the beginning, we want a way to easily control this script’s behavior: to send or not to send. One idea is to save a value into a file, with a value representing a state, and make our script look up the value from this file and decide what to do.

Here is a modified script in Bash that does so:

 1STATEFILE="/path/to/statefile"
 2
 3# If state file doesn't yet exist, create it.
 4if [ ! -f $STATEFILE ]; then
 5	touch $STATEFILE
 6fi
 7
 8# Fetch the content of the state file
 9STATUS=$(<$STATEFILE)
10
11# If the content matches our conditions, then send the query
12if [ "$STATUS" == "1" ]; then
13	goldendict -s "$query"
14fi

I’m gonna be honest here, but I kinda suck at Bash and I don’t really want to bother myself crawling on Stack Overflow so I rewrote the script to Ruby instead:

 1#!/usr/bin/env ruby
 2
 3STATE_FILE_PATH = "/tmp/kiku-status"
 4
 5print_status = false
 6new_status = ""
 7
 8# Create state file if not yet exists
 9unless File.exist? STATE_FILE_PATH
10  File.new(STATE_FILE_PATH, "wx").close
11end
12
13# Load the initial status
14status = File.read(STATE_FILE_PATH)
15
16# Loop through each command line arguments and evaluate them
17ARGV.each do |arg|
18  case arg
19  when "-0"
20    # Disable
21    new_status = "0"
22  when "-1"
23    # Enable
24    new_status = "1"
25  when "-t"
26    # Toggle
27    if status == "1"
28      new_status = "0"
29    else
30      new_status = "1"
31    end
32  when "-s"
33    print_status = true
34  end
35end
36
37# If the user wants to assign new states, open up the
38# file and do so.
39unless new_status.empty?
40  state_file = File.open(STATE_FILE_PATH, "w+")
41  state_file.write(new_status)
42  state_file.flush
43  state_file.close
44end
45
46# Read the new status
47status = File.read(STATE_FILE_PATH)
48
49if print_status
50  # Write your own conditions here
51  puts "󰺂" if status == "1"
52  puts "󰪗" unless status == "1"
53else
54  if status == "1"
55    input = gets
56    unless input == nil  # In case clipboard is empty
57      IO.popen("goldendict -s #{input}")
58    end
59  end
60end

Some explanation for the arguments here:

  • -0: Set state to 0 (disable)
  • -1: Set state to 1 (enable)
  • -t: Switch state between 0 and 1
  • -s: Prints an icon that indicates the state
  • nothing: Asks for input and send it to GoldenDict if state is 1

Our only problem left is to somehow find a way to edit that value. My idea is to use a panel, since it usually always stay on your screen, perhaps adding a toggle button like a tray icon is a good idea. I will be using Waybar as my panel. Let’s create our custom Waybar module and assign it to somewhere on your panel. I put it to the left of my system tray:

 1...
 2
 3"modules-right": [
 4  ...
 5  "custom/goldendict",
 6  "tray",
 7  ...
 8],
 9
10...
11
12"custom/goldendict": {
13  "format": "{}",
14  "exec": "ruby /path/to/script -s",
15  "on-click": "ruby /path/to/script -t",
16  "interval": "once",
17},

Don’t forget the main part of the story: run wl-paste -w ruby /path/to/script to trigger the script on every clipboard changes (you should run this on boot). And your panel should now look something like this after a restart. Also try clicking the icon to switch the state and copy some text:

A book icon sitting next to the system tray

A popup for 現在

Allow sleep script

In addition to the clipboard watcher, I also have a script that allows my system to sleep after 15 minutes of idling. I will put it here as well so maybe you could have more ideas on what you could do.

In my LabWC autostart script:

1swayidle -w \
2         timeout 600 'gtklock -d' \
3         timeout 900 'if [ "$(cat /tmp/mimis-status)" -eq "1" ]; then loginctl suspend; fi' \
4         before-sleep "playerctl pause; gtklock -d" &

The script for Waybar:

 1#!/usr/bin/env ruby
 2
 3STATE_FILE_PATH = "/tmp/mimis-status"
 4
 5print_status = false
 6new_status = ""
 7
 8# Create state file if not yet exists
 9unless File.exist? STATE_FILE_PATH
10  File.new(STATE_FILE_PATH, "wx").close
11  new_status = "1"
12end
13
14# Load the initial status
15status = File.read(STATE_FILE_PATH)
16
17# Loop through each command line arguments and evaluate them
18ARGV.each do |arg|
19  case arg
20  when "-0"
21    # Disable
22    new_status = "0"
23  when "-1"
24    # Enable
25    new_status = "1"
26  when "-t"
27    # Toggle
28    if status == "1"
29      new_status = "0"
30    else
31      new_status = "1"
32    end
33  when "-s"
34    print_status = true
35  end
36end
37
38# If the user wants to assign new states, open up the
39# file and do so.
40unless new_status.empty?
41  state_file = File.open(STATE_FILE_PATH, "w+")
42  state_file.write(new_status)
43  state_file.flush
44  state_file.close
45end
46
47# Read the new status
48status = File.read(STATE_FILE_PATH)
49
50if print_status
51  # Write your own conditions here
52  puts "󰒲" if status == "1"
53  puts "󰒳" unless status == "1"
54end

← Go to parent
Category:  Scripting Tips
Tags:  Ruby Waybar LabWC GoldenDict