koekeishiya / skhd

Simple hotkey daemon for macOS
MIT License
6.29k stars 209 forks source link

Cannot use custom script to move focus #139

Open d-miketa opened 4 years ago

d-miketa commented 4 years ago

I wrote a script to control yabai that either moves focus west or, if there's no window available on that display, selects the closest window on the closest adjacent display. It works well when run from the shell (as $SHELL -c '"${HOME}"/.config/skhd/yabai-locator window focus west') but the keybind doesn't do anything.

Can anyone see what's going wrong? I don't know how to debug what's happening but would be happy to with some direction.

Thanks!

in skhdrc:

cmd - h : "${HOME}"/.config/skhd/yabai-locator window focus west

yabai-locator: gist

Edit: I tried inserting echo [cmd] >> temp_file at various points and the problem is in calling functions internal to the script, eg $(exists_window_to_left_of_focus) on line 114. They don't return anything.

d-miketa commented 4 years ago

It's the same behaviour as in this issue: skhd works correctly when run from shell but not when started with brew services start skhd. I'm running 0.3.5.

dominiklohmann commented 4 years ago

So first, if you want to debug a shell script, run set -ex somewhere early on. -e causes the script to exit early on errors, and -x prints every line before running it. That way you can look at the log file of skhd and see what went wrong.

Second, I think the issue is even before your script runs. It is likely that the launch agent that brew services or its underlying launchctl load use don't know about the variable HOME.

d-miketa commented 4 years ago

So first, if you want to debug a shell script, run set -ex somewhere early on. -e causes the script to exit early on errors, and -x prints every line before running it. That way you can look at the log file of skhd and see what went wrong.

Thanks! Is there an obvious place to look for the logs?

Second, I think the issue is even before your script runs. It is likely that the launch agent that brew services or its underlying launchctl load use don't know about the variable HOME.

I was able to diagnose the issue using less sophisticated means. It turns out that if I define a function in the script and call it, using $() to capture its stdout (because I wanted a return value kind of functionality), the functions return an empty value. So it's probably something to do with how stdout behaves while running the script?

aSapien commented 3 years ago

After upgrading to Big Sur, brew services start skhd seems to have no effect. When running skhd from the terminal it works like a charm. The same "silence" happens when using launchctl load -w .../skhd directly.

Having tried to debug, I couldn't figure out the root cause here.

My workaround was to start skhd in the background from within .yabairc, as follows:

# Load Script Additions for BigSur, as per instructions:
# https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release)/c16d7804fc1093129516acedd507b5f838d34192#macos-big-sur---automatically-load-scripting-addition-on-startup
sudo yabai --load-sa
yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"

# Start SKHD in the background. Work around issues:
# https://github.com/koekeishiya/skhd/issues/103
# https://github.com/koekeishiya/skhd/issues/139
skhd & 

I don't like this solution much because it might leave the skhd process alive after yabai terminates, but it's something.

gronk-droid commented 2 years ago

thanks to @aSapien for this hacky solution, but if you are still having problems loading your configs from your dotfiles, try putting this in your ~/.config/yabai/yabairc/.yabairc:

# Start SKHD in the background. Work around issues:
# https://github.com/koekeishiya/skhd/issues/103
# https://github.com/koekeishiya/skhd/issues/139
# thanks to @aSapien!!!
skhd -c $HOME/.config/skhd/skhdrc

this should specify the config and load properly on loading yabai, but still has the same issues mentioned by aSapien. i personally have this at the end of my yabairc so that it runs after the config is loaded.

bpmckee commented 2 years ago

I've been struggling with this issue and I believe I've found the root cause and a workaround.

TL;DR

When skhd is launched by Homebrew the PATH is preset and does not include /usr/local/bin. When skhd is launched in the terminal, it has the full path.

The fix:

> # Make a copy of the default service.
$  cp ~/Library/LaunchAgents/homebrew.mxcl.skhd.plist ~/.config/skhd/

> # Add /usr/local/bin: to the service file.
> # Note: This probably only works if you have a M1 chip b/c homebrew installs to /opt/homebrew for M1 only (i think).
> # Either way, it's probably easier to just edit this file by hand vs using my sed command.
$  sed -i '' 's/\/opt\/homebrew\/bin:/\/usr\/local\/bin:&/' ~/.config/skhd/homebrew.mxcl.skhd.plist

> # Start skhd using the new service file.
$ brew services stop skhd
$ brew services start skhd --file=~/.config/skhd/homebrew.mxcl.skhd.plist

Longer version

I've been struggling with this for a few hours. Tricks like symlinking ~/.config/yabai/yabairc to ~/.yabairc didn't work for me.

Stopping skhd (brew services stop skhd) and running skhd & from a terminal worked for me. However, moving skhd & or skhd -c $HOME/.config/skhd/skhdrc to the bottom of my yabairc broke it again.

I checked yabai's error logs - tail -f /opt/homebrew/var/log/yabai/yabai.err.log Whenever I tried a skhd binding it said my script from my /usr/local/bin was not found. That was weird because which <my-command> worked and I verified that /usr/local/bin was in my path correctly.

For whatever reason the environment homebrew was running things in was different from my path. I tried a bunch of things like creating a ~/.bash_profile and adding a path, uninstalling & reinstalling everything, etc. No luck.

I ran brew services list and saw "files" listed next to the services. I checked these files out and saw that they were basically configs for how to launch these commands. What I saw was that they had a PATH that was super limited. It didn't include my /usr/local/bin.

I edited the file to add the /usr/local/bin, restarted and restarted yabai. Nothing. I opened the file again and my edits were gone.

More exploring and I where this file was getting created.

> # Turn on developer mode
$ brew developer on

> # Edit the skhd "homebrew formula"
$ brew edit skhd

I could see where it's redefining this file, overriding my path changes. I could edit this but that would be helpful for dotfiles or anything. I found out that homebrew lets you specify which plist file to use when starting services. Using a local copy of the file did the trick & plays nicer with dotfiles.

Long term fix

Could whatever is populating this brew edit skhd file be updated to include /usr/local/bin in the path?

JustSaX commented 1 year ago

https://github.com/koekeishiya/yabai/issues/526#issuecomment-639899511 solves window move focus across screens without script.

In case anybody ends up here from google like me ;-).