Skip to content

Instantly share code, notes, and snippets.

@towry
Last active February 26, 2023 06:04
Show Gist options
  • Save towry/155c5e9577107d8e27b55754bab3dca5 to your computer and use it in GitHub Desktop.
Save towry/155c5e9577107d8e27b55754bab3dca5 to your computer and use it in GitHub Desktop.
macos auto dark mode with kitty+tmux+neovim. read order: install_dark_mode_notify.sh -> ke.bou.dark-mode-notify.plist -> dark_mode_changed.sh -> color_mode.py | YOU NEED TO CHANGE SOME PATH&VARIABLE to make this work.
#!/usr/bin/env python3
import os
import sys
import subprocess
# author: https://github.com/olimorris/dotfiles/blob/main/commands/color_mode.py
kitty_path = "~/.config/kitty"
# starship_path = "~/.config/starship"
tmux_path = "~"
nvim_path = "~/.config/nvim"
# If we toggle dark mode via Alfred, we end up in a infinite loop. The dark-mode
# binary changes the MacOS mode which in turn causes color-mode-notify to run
# this script. This script then calls dark-mode (via the app_macos method)
# which kick starts this loop all over again. We use this boolean var
# to detect when we've run the command via the cmdline or alfred.
ran_from_cmd_line = False
# The order in which apps are changed
apps = [
"kitty",
#"starship",
"neovim",
# tmux must come after neovim.
"tmux",
#"fish",
]
def app_macos(mode):
"""
Change the macOS environment
"""
path_to_file = "~/.color_mode"
# Open the color_mode file
with open(os.path.expanduser(path_to_file), "r") as config_file:
contents = config_file.read()
# Change the mode to ensure on a fresh startup, the color is remembered
if mode == "dark":
contents = contents.replace("light", "dark")
if ran_from_cmd_line:
subprocess.run(["dark-mode", "on"])
if mode == "light":
contents = contents.replace("dark", "light")
if ran_from_cmd_line:
subprocess.run(["dark-mode", "off"])
with open(os.path.expanduser(path_to_file), "w") as config_file:
config_file.write(contents)
def app_kitty(mode):
"""
Change the Kitty terminal
"""
kitty_file = kitty_path + "/theme_env.conf"
# Begin changing the modes
if mode == "dark":
contents = "include ./Gruvbox Material Dark Soft.conf"
if mode == "light":
contents = "include ./gruvbox/gruvbox_light_soft.conf"
with open(os.path.expanduser(kitty_file), "w") as config_file:
config_file.write(contents)
# Reload the Kitty config
# Note: For Kitty 0.23.1, this breaks it
try:
pids = subprocess.run(["pgrep", "kitty"], stdout=subprocess.PIPE)
pids = pids.stdout.splitlines()
for pid in pids:
try:
subprocess.run(["kill", "-SIGUSR1", pid])
except:
continue
except IndexError:
pass
def app_starship(mode):
"""
Change the prompt in the terminal
"""
if mode == "dark":
return subprocess.run(
[
"cp",
os.path.expanduser(starship_path + "/starship_dark.toml"),
os.path.expanduser(starship_path + "/starship.toml"),
]
)
if mode == "light":
return subprocess.run(
[
"cp",
os.path.expanduser(starship_path + "/starship_light.toml"),
os.path.expanduser(starship_path + "/starship.toml"),
]
)
def app_tmux(mode):
subprocess.run(
[
"/usr/local/bin/tmux",
"source-file",
os.path.expanduser(tmux_path + "/.tmux.conf"),
]
)
# return os.system("exec zsh")
def app_neovim(mode):
"""
Change the Neovim color scheme
"""
print("start process")
from pynvim import attach
import signal
# sucks https://github.com/neovim/pynvim/issues/231
def handler(signum, frame):
raise Exception("end of time")
signal.signal(signal.SIGALRM, handler)
nvim_config = nvim_path + "/lua/towry/settings_env.lua"
# in your neovim config, require the settings_env.lua file by pcall.
# you can add settings_env.lua to gitignore.
if not os.path.isfile(os.path.expanduser(nvim_config)):
with open(os.path.expanduser(nvim_config), 'w') as fp:
pass
nvim_contents = 'vim.opt.background = "{mode}"'.format(mode=mode)
nvim_contents = nvim_contents.strip()
with open(os.path.expanduser(nvim_config), "w") as config_file:
config_file.write(nvim_contents)
# Now begin changing our open Neovim instances
# Get the neovim servers using neovim-remote
print("start nvr call")
servers = subprocess.run(["nvr", "--serverlist"], stdout=subprocess.PIPE)
servers = servers.stdout.splitlines()
# must exit after 2s
signal.alarm(2)
# Loop through them and change the theme by calling our custom Lua code
for server in servers:
try:
print("attaching to nvim")
nvim = attach("socket", path=server)
print("calling command")
nvim.command("call v:lua.tw.ToggleTheme('" + mode + "')")
print("finish call")
except Exception as e:
print(e)
continue
return
def app_fish(mode):
return subprocess.run(["/opt/homebrew/bin/fish"])
def run_apps(mode=None):
"""
Based on the apps in our list, sequentially run and trigger them
"""
if mode == None:
mode = get_mode()
for app in apps:
getattr(sys.modules[__name__], "app_%s" % app)(mode)
return
def get_mode():
"""
Determine what mode macOS is currently in
"""
mode = os.environ.get("DARKMODE", 1)
if mode == 1 or mode == "1":
return "dark"
else:
return "light"
if __name__ == "__main__":
# If we've passed a specific mode then activate it
try:
print("start py1")
if sys.argv[1]:
ran_from_cmd_line = True
run_apps(sys.argv[1])
except IndexError:
print("start py2")
try:
run_apps()
except Exception as e:
print(e)
#!/usr/bin/env bash
# called by the dark-mode-notify daemon.
set -e
export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
pyenv shell 3.11.1
if ! [ $? -eq 0 ]; then
echo "missing python 3.11.1"
exit 0
fi
echo "mode is: $DARKMODE"
python3 $HOME/.dotfiles/conf/commands/color_mode.py
#!/usr/bin/env bash
Repo_Dark_Mode_Notify="https://ghproxy.com/https://github.com/pze/dark-mode-notify"
function build_dark_mode_bin() {
if [ -f "/usr/local/bin/dark-mode-notify" ]; then
echo "~> Bin exists"
return
fi
echo "~> Installing dark mode notify daemon"
cd /tmp
echo "~> Clone source repo into /tmp/dark-mode-notify"
git clone --depth 1 $Repo_Dark_Mode_Notify dark-mode-notify
cd dark-mode-notify
echo "~> Builing from source"
make build
echo "~> Install to /usr/local/bin/dark-mode-notify"
make install
}
function install_dark_mode_notify() {
pwd=`pwd`
build_dark_mode_bin
echo "~> Copy daemon file"
cp ~/.dotfiles/conf/tasks/ke.bou.dark-mode-notify.plist ~/Library/LaunchAgents/
cp ~/.dotfiles/conf/commands/dark_mode_changed.sh /usr/local/bin/
echo "~> Install other deps"
# make sure the python deps is installed by correct pip3(not system).
# make sure we use one specific python version.
export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
pyenv shell 3.11.1
if ! [ $? -eq 0 ]; then
echo "missing python 3.11.1"
exit 0
fi
pyenv exec pip install pynvim neovim-remote
echo "~> Launch the daemon"
# may have errors at first install, but just ignore it.
launchctl unload ~/Library/LaunchAgents/ke.bou.dark-mode-notify.plist
launchctl load -w ~/Library/LaunchAgents/ke.bou.dark-mode-notify.plist
cd $pwd
echo "~> 👌 Done"
}
install_dark_mode_notify
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>ke.bou.dark-mode-notify</string>
<key>KeepAlive</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/dark-mode-notify-stderr.log</string>
<key>StandardOutPath</key>
<string>/tmp/dark-mode-notify-stdout.log</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/dark-mode-notify</string>
<string>/usr/local/bin/dark_mode_changed.sh</string>
</array>
</dict>
</plist>
@towry
Copy link
Author

towry commented Jan 4, 2023

In your tmux conf, after the settings of appearance:

change code as you need. tmux depends on the neovim setting file.

is_light="cat ~/.config/nvim/lua/towry/settings_env.lua 2>/dev/null | grep -q 'light'"
if-shell "$is_light" {
  %hidden color_dark="#ebdbb2"
  %hidden color_status_text="#3c3836"
  set -g status-style fg="$color_status_text",bg="$color_dark"
  setw -g window-status-current-style "fg=$color_dark,bold,bg=$color_secondary"
  setw -g window-status-current-format "#[fg=$color_dark,bg=$color_secondary]$separator_powerline_right#[default] #I:#W #[fg=$color_secondary,bg=$color_dark]$separator_powerline_right#[default]"
}
# end apperance

@towry
Copy link
Author

towry commented Feb 16, 2023

Warn1

Make sure you have correct python3 && pip3 installed, otherwise the script will hang up.

So, set the PATH in dark_mode_changed.sh correctly.

Like this:

#!/usr/bin/env bash

echo "mode is: $DARKMODE"

export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH:/usr/local/bin:/usr/bin"
eval "$(pyenv init -)"
pyenv shell 3.8.2
if ! [ $? -eq 0 ]; then
  echo "missing python 3.8.2"
  exit 0
fi

python --version

if ! [ -x "$(command -v nvr)" ]; then
  echo "nvr command not exists"
fi

echo "running color_mode.py"
python3 $HOME/.dotfiles/conf/commands/color_mode.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment