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.
read query
goldendict -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:
wl-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:
STATEFILE="/path/to/statefile"
# If state file doesn't yet exist, create it.
if [ ! -f $STATEFILE ]; then
touch $STATEFILE
fi
# Fetch the content of the state file
STATUS=$(<$STATEFILE)
# If the content matches our conditions, then send the query
if [ "$STATUS" == "1" ]; then
goldendict -s "$query"
fi
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:
#!/usr/bin/env ruby
STATE_FILE_PATH = "/tmp/kiku-status"
print_status = false
new_status = ""
# Create state file if not yet exists
unless File.exist? STATE_FILE_PATH
File.new(STATE_FILE_PATH, "wx").close
end
# Load the initial status
status = File.read(STATE_FILE_PATH)
# Loop through each command line arguments and evaluate them
ARGV.each do |arg|
case arg
when "-0"
# Disable
new_status = "0"
when "-1"
# Enable
new_status = "1"
when "-t"
# Toggle
if status == "1"
new_status = "0"
else
new_status = "1"
end
when "-s"
print_status = true
end
end
# If the user wants to assign new states, open up the
# file and do so.
unless new_status.empty?
state_file = File.open(STATE_FILE_PATH, "w+")
state_file.write(new_status)
state_file.flush
state_file.close
end
# Read the new status
status = File.read(STATE_FILE_PATH)
if print_status
# Write your own conditions here
puts "" if status == "1"
puts "" unless status == "1"
else
if status == "1"
input = gets
unless input == nil # In case clipboard is empty
IO.popen("goldendict -s #{input}")
end
end
end
Some explanation for the arguments here:
-0: Set state to0(disable)-1: Set state to1(enable)-t: Switch state between0and1-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:
...
"modules-right": [
...
"custom/goldendict",
"tray",
...
],
...
"custom/goldendict": {
"format": "{}",
"exec": "ruby /path/to/script -s",
"on-click": "ruby /path/to/script -t",
"interval": "once",
},
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:
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:
swayidle -w \
timeout 600 'gtklock -d' \
timeout 900 'if [ "$(cat /tmp/mimis-status)" -eq "1" ]; then loginctl suspend; fi' \
before-sleep "playerctl pause; gtklock -d" &
The script for Waybar:
#!/usr/bin/env ruby
STATE_FILE_PATH = "/tmp/mimis-status"
print_status = false
new_status = ""
# Create state file if not yet exists
unless File.exist? STATE_FILE_PATH
File.new(STATE_FILE_PATH, "wx").close
new_status = "1"
end
# Load the initial status
status = File.read(STATE_FILE_PATH)
# Loop through each command line arguments and evaluate them
ARGV.each do |arg|
case arg
when "-0"
# Disable
new_status = "0"
when "-1"
# Enable
new_status = "1"
when "-t"
# Toggle
if status == "1"
new_status = "0"
else
new_status = "1"
end
when "-s"
print_status = true
end
end
# If the user wants to assign new states, open up the
# file and do so.
unless new_status.empty?
state_file = File.open(STATE_FILE_PATH, "w+")
state_file.write(new_status)
state_file.flush
state_file.close
end
# Read the new status
status = File.read(STATE_FILE_PATH)
if print_status
# Write your own conditions here
puts "" if status == "1"
puts "" unless status == "1"
end