80 lines
2.7 KiB
Plaintext
Executable File
80 lines
2.7 KiB
Plaintext
Executable File
#!/usr/bin/nu
|
|
|
|
let launcher_apps = open $"($env.HOME)/.config/switchrun/apps.nuon"
|
|
|
|
def lookup_window_id [running_apps, app_id] {
|
|
let matches = $running_apps | where app_id == $app_id
|
|
if ($matches | is-empty) {
|
|
"none"
|
|
} else {
|
|
$matches | get id | first | into string
|
|
}
|
|
}
|
|
|
|
def switch_to [target_window_id: string] {
|
|
let focus_cmd = {Action: { FocusWindow: { id: ($target_window_id | into int ) } } }
|
|
$focus_cmd | to json -r | socat STDIO $env.NIRI_SOCKET
|
|
}
|
|
|
|
def launch [target_app_id: string] {
|
|
let app = (
|
|
$launcher_apps |
|
|
where app_id == $target_app_id |
|
|
first
|
|
)
|
|
print $app.exec
|
|
print ...$app.args
|
|
if $app != null { run-external $app.exec ...$app.args} else { print "no exec found" }
|
|
}
|
|
|
|
def main [target_app_id: string] {
|
|
let running_apps = niri msg --json windows | from json
|
|
let matches = $running_apps | where app_id == $target_app_id
|
|
print $matches
|
|
if ($matches | is-empty) {
|
|
launch $target_app_id
|
|
} else {
|
|
let focused_matches = $matches | enumerate | where item.is_focused == true | get index
|
|
if ($focused_matches | is-empty) {
|
|
switch_to (($matches | first | get id) | into string)
|
|
} else {
|
|
# In the event of multiple matches, switch to the one after the focused one - wrapping around
|
|
# That way we will cycle through them
|
|
let target_index = ($focused_matches | first) - 1
|
|
print $target_index
|
|
print ($matches | length)
|
|
let target_window = if ($target_index < 0) { $matches | last } else { ($matches | get $target_index) }
|
|
switch_to ($target_window.id | into string)
|
|
}
|
|
}
|
|
}
|
|
|
|
def "main list" [tag?: string] {
|
|
let running_apps = niri msg --json windows | from json
|
|
|
|
# Optionally narrow to apps carrying the requested tag.
|
|
let filtered = (if ($tag | is-empty) {
|
|
$launcher_apps
|
|
} else {
|
|
$launcher_apps | where { |app| ($tag in ($app.tags? | default [])) }
|
|
})
|
|
|
|
if ($filtered | is-empty) {
|
|
print $"No applications match tag '($tag)'"
|
|
return
|
|
}
|
|
|
|
let apps = $filtered | each { |app| $app | insert window_id { lookup_window_id $running_apps $app.app_id } }
|
|
# if the selected app_id is running then
|
|
# focus it by its window id (first window id for that app id is fine)
|
|
# if it's not running then launch it using the app's desktop entry
|
|
#
|
|
let app_lines = $apps | each { $"($in.name) - [($in.app_id), ($in.window_id)]" }
|
|
|
|
let prompt = if ($tag | is-empty) { "Launch/Switch" } else { $"Launch/Switch [($tag)]" }
|
|
let selection = $app_lines | each { echo $in } | str join "|" | rofi -dmenu -i -p $prompt -sep "|"
|
|
let parsed = $selection | parse "{name} - [{app_id}, {window_id}]" | first
|
|
let match = $apps | where app_id == $parsed.app_id | first
|
|
if $parsed.window_id == "none" { launch $match.app_id } else { switch_to $match.window_id }
|
|
}
|