Current state of main at 0240060 feat(hp-laptop): install TeleportFling from its flake. History intentionally collapsed to a single commit; this repo mirrors only the latest state.
393 lines
6.4 KiB
Python
393 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
||
"""qs-launch — wofi-based launcher modes: emoji pick, calculator, DuckDuckGo search.
|
||
|
||
Subcommands:
|
||
emoji feed a curated emoji list into wofi --dmenu, copy the picked emoji
|
||
calc type an expression in wofi, evaluate with qalc, copy + toast result
|
||
search type a query in wofi, open DuckDuckGo in the default browser
|
||
|
||
All binary paths are injected via $QS_* env vars by the .local/bin/qs-launch
|
||
wrapper so execution works regardless of PATH (same pattern as qs-bt's
|
||
$BLUECTL). When no DISPLAY/WAYLAND_DISPLAY is present, wofi can't open, so each
|
||
mode exits silently with code 1.
|
||
"""
|
||
|
||
import os
|
||
import subprocess
|
||
import sys
|
||
import urllib.parse
|
||
|
||
# Curated emoji list: "<char> <shortcode>". Searchable by name, output splits
|
||
# on the first whitespace so only the emoji character gets copied.
|
||
EMOJI = """😀 grin
|
||
😃 smiley
|
||
😁 beam
|
||
😂 joy
|
||
🤣 rofl
|
||
😊 blush
|
||
🙂 slight smile
|
||
😉 wink
|
||
😍 heart eyes
|
||
😘 kiss
|
||
🤩 star struck
|
||
🥳 party
|
||
😎 cool
|
||
🤓 nerd
|
||
😇 halo
|
||
😏 smirk
|
||
😜 winky tongue
|
||
🥺 plead
|
||
😬 grimace
|
||
🤔 think
|
||
🤯 mind blown
|
||
😴 sleepy
|
||
😭 cry
|
||
😢 sad
|
||
😞 disappointed
|
||
😠 angry
|
||
😤 triumph
|
||
🤬 swear
|
||
🙄 roll eyes
|
||
😐 neutral
|
||
😑 expressionless
|
||
🙂🙃 upside down
|
||
😱 scream
|
||
🤒 sick
|
||
🤕 hurt
|
||
💀 skull
|
||
👻 ghost
|
||
👽 alien
|
||
🤖 robot
|
||
🎃 pumpkin
|
||
💩 poo
|
||
🙌 yes
|
||
👏 clap
|
||
🙏 pray
|
||
🤝 handshake
|
||
👍 thumbs up
|
||
👎 thumbs down
|
||
👊 fist
|
||
✊ raised fist
|
||
🤞 crossed fingers
|
||
✌️ peace
|
||
👋 hello wave
|
||
🖐️ hand
|
||
✍️ writing
|
||
💪 muscle
|
||
🫶 heart hands
|
||
🦾 bionic arm
|
||
🧠 brain
|
||
👀 eyes
|
||
👁️ eye
|
||
👄 lips
|
||
👅 taste tongue
|
||
🧛 vampire
|
||
🧟 zombie
|
||
❤️ heart
|
||
🧡 orange heart
|
||
💛 yellow heart
|
||
💚 green heart
|
||
💙 blue heart
|
||
💜 purple heart
|
||
🖤 black heart
|
||
🤍 white heart
|
||
🤎 brown heart
|
||
💔 broken heart
|
||
❤️🔥 heart fire
|
||
💯 hundred
|
||
💥 boom
|
||
💫 dizzy
|
||
✨ sparkles
|
||
🔥 fire
|
||
🌟 star
|
||
⭐ star white
|
||
☀️ sun
|
||
🌙 moon
|
||
🌑 new moon
|
||
🌈 rainbow
|
||
☁️ cloud
|
||
⛈️ storm
|
||
❄️ snow
|
||
🌊 ocean wave
|
||
🌍 earth
|
||
🌺 hibiscus
|
||
🌸 cherry blossom
|
||
🌹 rose
|
||
🌷 tulip
|
||
🌵 cactus
|
||
🌴 palm
|
||
🍀 clover
|
||
🍄 mushroom
|
||
🐶 dog
|
||
🐱 cat
|
||
🦊 fox
|
||
🐻 bear
|
||
🐼 panda
|
||
🐨 koala
|
||
🦁 lion
|
||
🐯 tiger
|
||
🐸 frog
|
||
🐵 monkey
|
||
🐧 penguin
|
||
🦄 unicorn
|
||
🐝 bee
|
||
🦋 butterfly
|
||
🐢 turtle
|
||
🐙 octopus
|
||
🦈 shark
|
||
🐬 dolphin
|
||
🍍 pineapple
|
||
🥭 mango
|
||
🍒 cherries
|
||
🍓 strawberry
|
||
🍑 peach
|
||
🥑 avocado
|
||
🍕 pizza
|
||
🍔 burger
|
||
🍟 fries
|
||
🌭 hotdog
|
||
🍿 popcorn
|
||
🌮 taco
|
||
🍰 cake
|
||
🍩 donut
|
||
🥐 croissant
|
||
☕ coffee
|
||
🍵 tea
|
||
🍺 beer
|
||
🍻 cheers
|
||
⚽ football
|
||
🏀 basketball
|
||
🎾 tennis
|
||
⚾ baseball
|
||
🏈 american football
|
||
🎮 game
|
||
🎲 dice
|
||
🎯 target
|
||
🎵 music
|
||
🎶 notes
|
||
🎤 mic
|
||
🎧 headphones
|
||
📻 radio
|
||
🎬 movie
|
||
📺 tv
|
||
💻 laptop
|
||
📱 phone
|
||
🖥️ computer
|
||
🖱️ mouse
|
||
💾 floppy
|
||
💿 disc
|
||
🔋 battery
|
||
🔌 plug
|
||
💡 bulb
|
||
🔦 flashlight
|
||
🗑️ trash
|
||
🔒 lock
|
||
🔓 unlocked
|
||
🔑 key
|
||
✂️ scissors
|
||
📎 paperclip
|
||
📌 pin
|
||
📍 location
|
||
🧲 magnet
|
||
🛠️ tools
|
||
⚙️ gear
|
||
🔧 wrench
|
||
✏️ pencil
|
||
🖊️ pen
|
||
📖 book
|
||
📚 books
|
||
📄 doc
|
||
📁 folder
|
||
📦 package
|
||
✉️ mail
|
||
📝 memo
|
||
📊 chart
|
||
💰 money
|
||
💳 card
|
||
🧾 receipt
|
||
🏆 trophy
|
||
🥇 gold
|
||
🥈 silver
|
||
🎁 gift
|
||
🎈 balloon
|
||
🎉 party popper
|
||
🥂 toast
|
||
🎊 confetti
|
||
🧹 clean
|
||
🧽 sponge
|
||
⏰ alarm
|
||
⏱️ stopwatch
|
||
🕰️ clock
|
||
📅 calendar
|
||
📆 date
|
||
🔔 bell
|
||
🔕 bell off
|
||
❌ cross
|
||
✅ check
|
||
⚠️ warning
|
||
🚫 no entry
|
||
➕ plus
|
||
➖ minus
|
||
➗ divide
|
||
✖️ multiply
|
||
🔄 refresh
|
||
⬆️ up
|
||
⬇️ down
|
||
⬅️ left
|
||
➡️ right
|
||
↩️ return
|
||
🔙 back
|
||
🔜 soon
|
||
🌐 globe
|
||
🚀 rocket
|
||
🛸 saucer
|
||
✈️ plane
|
||
🚗 car
|
||
🚕 taxi
|
||
🚌 bus
|
||
🚂 train
|
||
🚲 bike
|
||
🏍️ motorcycle
|
||
👻 spooky
|
||
☠️ skull crossbones
|
||
💣 bomb
|
||
🚁 chopper
|
||
🚢 ship
|
||
🚄 bullet train
|
||
🚦 traffic light
|
||
⛽ fuel
|
||
🅿️ parking
|
||
🚧 roadwork
|
||
🌉 bridge
|
||
🏰 castle
|
||
⛺ camp
|
||
🌋 volcano
|
||
🗼 tower
|
||
🏯 pagoda
|
||
🌆 city dusk
|
||
🌃 city night
|
||
🏙️ skyline
|
||
🖼️ frame
|
||
🎨 palette
|
||
🖌️ brush
|
||
🧶 yarn
|
||
🧵 thread
|
||
💍 ring
|
||
👟 sneaker
|
||
👠 heel
|
||
🧢 cap
|
||
🎓 graduate
|
||
👒 hat
|
||
🧣 scarf
|
||
🧤 gloves
|
||
🧥 coat
|
||
👔 tie
|
||
👕 shirt
|
||
👖 jeans
|
||
💭 thought
|
||
💬 speech
|
||
🗯️ anger
|
||
⌨️ keyboard
|
||
🖨️ printer
|
||
🧮 abacus
|
||
🕹️ joystick
|
||
🎳 bowling
|
||
🏓 ping pong
|
||
🏸 badminton
|
||
🥊 boxing
|
||
🥋 martial arts
|
||
🎽 running shirt
|
||
🚴 cyclist
|
||
🧗 climber
|
||
🏊 swimmer
|
||
🎪 circus
|
||
🎠 carousel
|
||
🗿 moai
|
||
🏛️ classical
|
||
🏟️ stadium
|
||
🏫 school
|
||
🏥 hospital
|
||
🏦 bank
|
||
🏪 store
|
||
🏭 factory
|
||
🏝️ island
|
||
🏖️ beach
|
||
⛱️ umbrella
|
||
🧭 compass"""
|
||
|
||
|
||
def run(command, **kwargs):
|
||
return subprocess.run(command, capture_output=True, text=True, **kwargs)
|
||
|
||
|
||
def wofi(entries, prompt, exec_search=False):
|
||
cmd = [os.environ.get("QS_WOFI", "wofi"), "--dmenu", "--prompt", prompt]
|
||
if exec_search:
|
||
cmd.append("--exec-search")
|
||
result = run(cmd, input=entries)
|
||
if result.returncode != 0:
|
||
return None
|
||
return result.stdout.rstrip("\n")
|
||
|
||
|
||
def cmd_mode():
|
||
if "WAYLAND_DISPLAY" not in os.environ and "DISPLAY" not in os.environ:
|
||
return 1
|
||
sub = sys.argv[1] if len(sys.argv) > 1 else ""
|
||
if sub == "emoji":
|
||
return emoji_mode()
|
||
if sub == "calc":
|
||
return calc_mode()
|
||
if sub == "search":
|
||
return search_mode()
|
||
print(__doc__, file=sys.stderr)
|
||
return 2
|
||
|
||
|
||
def emoji_mode():
|
||
picked = wofi(EMOJI, "\U0001f600 Emoji")
|
||
if not picked:
|
||
return 0
|
||
char = picked.split(" ", 1)[0]
|
||
if not char:
|
||
return 0
|
||
wl_copy = os.environ.get("QS_WLCOPY", "wl-copy")
|
||
run([wl_copy, char])
|
||
return 0
|
||
|
||
|
||
def calc_mode():
|
||
expr = wofi("", "=? \u2014 1+2 then Enter", exec_search=True)
|
||
if not expr:
|
||
return 0
|
||
qalc = os.environ.get("QS_QALC", "qalc")
|
||
result = run([qalc, "-t", expr])
|
||
if result.returncode != 0:
|
||
return 0
|
||
answer = result.stdout.strip()
|
||
wl_copy = os.environ.get("QS_WLCOPY", "wl-copy")
|
||
run([wl_copy, answer])
|
||
notify(os.environ.get("QS_NOTIFY", "notify-send"),
|
||
"\U0001f4d0 " + expr, "= " + answer + " (copied)")
|
||
return 0
|
||
|
||
|
||
def search_mode():
|
||
query = wofi("", "Search the web", exec_search=True)
|
||
if not query:
|
||
return 0
|
||
url = "https://duckduckgo.com/?q=" + urllib.parse.quote_plus(query)
|
||
xdg_open = os.environ.get("QS_XDGO", "xdg-open")
|
||
subprocess.Popen([xdg_open, url])
|
||
return 0
|
||
|
||
|
||
def notify(sender, title, body):
|
||
try:
|
||
run([sender, "-a", "qs-launch", title, body])
|
||
except OSError:
|
||
pass
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(cmd_mode()) |