2022-08-25 19:56:57 +00:00
{ lib
, stdenv
, fetchFromGitHub
, fetchzip
, writeShellScript
, installShellFiles
, testers
, yabai
, xxd
, xcodebuild
, Carbon
, Cocoa
, ScriptingBridge
# This needs to be from SDK 10.13 or higher, SLS APIs introduced in that version get used
, SkyLight
} :
2020-04-30 16:55:35 +00:00
2022-08-25 19:56:57 +00:00
let
2020-04-30 16:55:35 +00:00
pname = " y a b a i " ;
2022-08-25 19:56:57 +00:00
version = " 4 . 0 . 2 " ;
2020-04-30 16:55:35 +00:00
2022-08-25 19:56:57 +00:00
test-version = testers . testVersion {
package = yabai ;
version = " y a b a i - v ${ version } " ;
2020-04-30 16:55:35 +00:00
} ;
2022-08-25 19:56:57 +00:00
_meta = with lib ; {
description = " A t i l i n g w i n d o w m a n a g e r f o r m a c O S b a s e d o n b i n a r y s p a c e p a r t i t i o n i n g " ;
longDescription = ''
yabai is a window management utility that is designed to work as an extension to the built-in
window manager of macOS . yabai allows you to control your windows , spaces and displays freely
using an intuitive command line interface and optionally set user-defined keyboard shortcuts
using skhd and other third-party software .
2020-04-30 16:55:35 +00:00
'' ;
2020-05-02 08:36:09 +00:00
homepage = " h t t p s : / / g i t h u b . c o m / k o e k e i s h i y a / y a b a i " ;
2022-08-25 19:56:57 +00:00
changelog = " h t t p s : / / g i t h u b . c o m / k o e k e i s h i y a / y a b a i / b l o b / v ${ version } / C H A N G E L O G . m d " ;
2020-04-30 16:55:35 +00:00
license = licenses . mit ;
2022-08-25 19:56:57 +00:00
platforms = platforms . darwin ;
maintainers = with maintainers ; [
cmacrae
shardy
ivar
] ;
} ;
in
{
# Unfortunately compiling yabai from source on aarch64-darwin is a bit complicated. We use the precompiled binary instead for now.
# See the comments on https://github.com/NixOS/nixpkgs/pull/188322 for more information.
aarch64-darwin = stdenv . mkDerivation {
inherit pname version ;
src = fetchzip {
url = " h t t p s : / / g i t h u b . c o m / k o e k e i s h i y a / y a b a i / r e l e a s e s / d o w n l o a d / v ${ version } / y a b a i - v ${ version } . t a r . g z " ;
sha256 = " s h a 2 5 6 - R w A R z K 3 e 0 e 2 N 3 n d F N i k f o 8 s r D j e o 6 j s W N 2 x Q 1 8 b X t / I = " ;
} ;
nativeBuildInputs = [
installShellFiles
] ;
dontConfigure = true ;
dontBuild = true ;
installPhase = ''
runHook preInstall
mkdir - p $ out
cp - r ./bin $ out
installManPage ./doc/yabai.1
runHook postInstall
'' ;
passthru . tests . version = test-version ;
meta = _meta // {
sourceProvenance = with lib . sourceTypes ; [
binaryNativeCode
] ;
} ;
} ;
x86_64-darwin = stdenv . mkDerivation rec {
inherit pname version ;
src = fetchFromGitHub {
owner = " k o e k e i s h i y a " ;
repo = " y a b a i " ;
rev = " v ${ version } " ;
sha256 = " s h a 2 5 6 - D X D d j I 4 k k L c R U N t M o S u 7 f J 0 f 3 f U t y 8 8 o 5 Z S 6 l J z 0 c G U = " ;
} ;
nativeBuildInputs = [
installShellFiles
xcodebuild
xxd
] ;
buildInputs = [
Carbon
Cocoa
ScriptingBridge
SkyLight
] ;
dontConfigure = true ;
enableParallelBuilding = true ;
postPatch = ''
# aarch64 code is compiled on all targets, which causes our Apple SDK headers to error out.
# Since multilib doesnt work on darwin i dont know of a better way of handling this.
substituteInPlace makefile \
- - replace " - a r c h a r m 6 4 e " " " \
- - replace " - a r c h a r m 6 4 " " " \
- - replace " c l a n g " " ${ stdenv . cc . targetPrefix } c l a n g "
# `NSScreen::safeAreaInsets` is only available on macOS 12.0 and above, which frameworks arent packaged.
# When a lower OS version is detected upstream just returns 0, so we can hardcode that at compiletime.
# https://github.com/koekeishiya/yabai/blob/v4.0.2/src/workspace.m#L109
substituteInPlace src/workspace.m \
- - replace ' return screen . safeAreaInsets . top ; ' ' return 0 ; '
'' ;
installPhase = ''
runHook preInstall
mkdir - p $ out / { bin , share/icons/hicolor/scalable/apps }
cp ./bin/yabai $ out/bin/yabai
ln - s $ { loadScriptingAddition } $ out/bin/yabai-load-sa
cp ./assets/icon/icon.svg $ out/share/icons/hicolor/scalable/apps/yabai.svg
installManPage ./doc/yabai.1
runHook postInstall
'' ;
# Defining this here exposes it as a passthru attribute, which is useful because it allows us to run `builtins.hashFile` on it in pure-eval mode.
# With that we can programatically generate an `/etc/sudoers.d` entry which disables the password requirement, so that a user-agent can run it at login.
loadScriptingAddition = writeShellScript " y a b a i - l o a d - s a " ''
# For whatever reason the regular commands to load the scripting addition do not work, yabai will throw an error.
# The installation command mutably installs binaries to '/System', but then fails to start them. Manually running
# the bins as root does start the scripting addition, so this serves as a more user-friendly way to do that.
set - euo pipefail
if [ [ " $ E U I D " != 0 ] ] ; then
echo " e r r o r : t h e s c r i p t i n g - a d d i t i o n l o a d e r m u s t r a n a s r o o t . t r y ' s u d o $ 0 ' "
exit 1
fi
loaderPath = " / L i b r a r y / S c r i p t i n g A d d i t i o n s / y a b a i . o s a x / C o n t e n t s / M a c O S / m a c h _ l o a d e r " ;
if ! test - x " $ l o a d e r P a t h " ; then
echo " c o u l d n o t l o c a t e t h e s c r i p t i n g - a d d i t i o n l o a d e r a t ' $ l o a d e r P a t h ' , i n s t a l l i n g i t . . . "
echo " n o t e : t h i s m a y d i s p l a y a n e r r o r "
eval " $ ( d i r n a m e " '' ${ BASH_SOURCE [ 0 ] } " ) / y a b a i - - i n s t a l l - s a " | | t r u e
sleep 1
fi
echo " e x e c u t i n g l o a d e r . . . "
eval " $ l o a d e r P a t h "
echo " s c r i p t i n g - a d d i t i o n s t a r t e d "
'' ;
passthru . tests . version = test-version ;
meta = _meta // {
longDescription = _meta . longDescription + ''
Note that due to a nix-only bug the scripting addition cannot be launched using the regular
procedure . Instead , you can use the provided ` yabai-load-sa ` script .
'' ;
sourceProvenance = with lib . sourceTypes ; [
fromSource
] ;
} ;
2020-04-30 16:55:35 +00:00
} ;
2022-08-25 19:56:57 +00:00
} . ${ stdenv . hostPlatform . system } or ( throw " U n s u p p o r t e d p l a t f o r m ${ stdenv . hostPlatform . system } " )