├── .devcontainer └── devcontainer.json ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE.txt ├── OSSMETADATA ├── README.md ├── demo.gif ├── main.tmux └── scripts ├── devcontainer_postCreateCommand.sh ├── tmux-dark-notify-runner.sh └── tmux-theme-mode.sh /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "features": { 3 | "ghcr.io/devcontainers-extra/features/apt-get-packages:1": { 4 | "packages": ["tmux"] // There's no macOS host image, so can't install dark-notify. 5 | } 6 | }, 7 | "postCreateCommand": "bash scripts/devcontainer_postCreateCommand.sh", 8 | "customizations": { 9 | "vscode": { 10 | "extensions": [ 11 | "timonwong.shellcheck" 12 | ] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "TMUXCONF" 4 | ] 5 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | ### Added 9 | - GitHub Codespaces devcontainer config setting up all dependencies and installs tmux-dark-notify in the container. See [devcontainer.json](.devcontainer/devcontainer.json) and [devcontainer_postCreateCommand.sh](scripts/devcontainer_postCreateCommand.sh). 10 | 11 | ## [0.1.1] - 2024-06-12 12 | ### Fixed 13 | - Corrected README instructions. 14 | 15 | ## [0.1.0] - 2023-03-26 16 | ### Added 17 | - Initial release! 18 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Erik Westrup 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /OSSMETADATA: -------------------------------------------------------------------------------- 1 | osslifecycle=active 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tmux-dark-notify - Make tmux's theme follow macOS dark/light mode 2 | [![Top programming languages used](https://img.shields.io/github/languages/top/erikw/tmux-dark-notify)](#) 3 | [![SLOC](https://sloc.xyz/github/erikw/tmux-dark-notify?lower=true)](#) 4 | [![License](https://img.shields.io/github/license/erikw/tmux-dark-notify?color=informational)](LICENSE.txt) 5 | [![OSS Lifecycle](https://img.shields.io/osslifecycle/erikw/tmux-dark-notify)](https://github.com/Netflix/osstracker) 6 | [![Latest tag](https://img.shields.io/github/v/tag/erikw/tmux-dark-notify)](https://github.com/erikw/tmux-powerline/tags) 7 | 8 |

9 | 10 | Open in GitHub Codespaces 11 |

12 | 13 | This tmux [tpm](https://github.com/tmux-plugins/tpm) plugin will change the tmux theme automatically when the system changes the light/dark mode. Configure a light and a dark theme and the plugin will take care of the rest! 14 | 15 | ![Demo of changing system theme](demo.gif) 16 | 17 | 18 | For example I use a Solarized in all my programs that support it. For tmux I use [seebi/tmux-colors-solarized](https://github.com/seebi/tmux-colors-solarized) which is locally cloned (in my dotfiles as a submodule). This tmux theme repo provides a light theme `tmuxcolors-light.conf` and a dark theme `tmuxcolors-dark.conf`. With this tmux plugin, I have configured so that when the system appearance mode changes, the corresponding tmux theme will be used. 19 | 20 | Hats off to [dark-notify](https://github.com/cormacrelf/dark-notify) which this plugin is built up on! 21 | 22 | # Setup 23 | ## Requirements 24 | * macOS - dark-notify is only for mac 25 | * Bash 26 | * Homebrew 27 | * [dark-notify](https://github.com/cormacrelf/dark-notify) - `$ brew install cormacrelf/tap/dark-notify` 28 | * tmux 29 | * [tpm](https://github.com/tmux-plugins/tpm) - Tmux Plugin Manager 30 | 31 | ## Setup steps 32 | 1. Make sure all requirements above are installed and working already. 33 | 2. Configure tmux-dark-notify in `tmux.conf` 34 | * To install the plugin, add a line 35 | ```conf 36 | set -g @plugin 'erikw/tmux-dark-notify' 37 | ``` 38 | * Now you must configure the paths for the light/dark themes you want to use. I personally have [seebi/tmux-colors-solarized](https://github.com/seebi/tmux-colors-solarized) installed as a TPM plugin. NOTE that in the tmux.conf any themes must be set up before tmux-dark-notify, otherwise they might override the theme set by this plugin. . Change the paths below to your themes. 39 | ```conf 40 | set -g @dark-notify-theme-path-light '$HOME/.config/tmux/plugins/tmux-colors-solarized/tmuxcolors-light.conf' 41 | set -g @dark-notify-theme-path-dark '$HOME/.config/tmux/plugins/tmux-colors-solarized/tmuxcolors-dark.conf' 42 | ``` 43 | * To cover some corner cases e.g. if you use the plugin [tmux-reset](https://github.com/hallazzang/tmux-reset) or another TPM plugin sets the theme itself, I recommend adding this explicit source of the theme as well as a fallback in case this plugin is not run in all scenarios. The `if-shell` condition is there because the symlink won't be there the very first time until tmux-dark-notify has run. It should be placed after TPM is initialized, because the ordering of plugin initialization is not guaranteed. **Remove any other** `source-file` for theme you have of course! 44 | ```conf 45 | run-shell '~/.config/tmux/plugins/tpm/tpm' # Or however you source tpm. 46 | 47 | if-shell "test -e ~/.local/state/tmux/tmux-dark-notify-theme.conf" \ 48 | "source-file ~/.local/state/tmux/tmux-dark-notify-theme.conf" 49 | ``` 50 | * Thus in summary, the relevant section of you `tmux.conf` could look like this (including the theme I use) 51 | ```conf 52 | [...] 53 | 54 | set -g @plugin 'seebi/tmux-colors-solarized' 55 | set -g @plugin 'erikw/tmux-dark-notify' 56 | 57 | set -g @dark-notify-theme-path-light '$HOME/.config/tmux/plugins/tmux-colors-solarized/tmuxcolors-light.conf' 58 | set -g @dark-notify-theme-path-dark '$HOME/.config/tmux/plugins/tmux-colors-solarized/tmuxcolors-dark.conf' 59 | 60 | [...] 61 | run-shell '~/.config/tmux/plugins/tpm/tpm' # Or however you source tpm. 62 | 63 | if-shell "test -e ~/.local/state/tmux/tmux-dark-notify-theme.conf" \ 64 | "source-file ~/.local/state/tmux/tmux-dark-notify-theme.conf" 65 | ``` 66 | 3. Install the plugin with `I`, unless you changed [tpm's keybindings](https://github.com/tmux-plugins/tpm#key-bindings). 67 | 4. Try toggle the system's appearance mode from System Settings and see that the tmux theme is changing 68 | * To verify, you can `ls -l ~/.local/state/tmux/tmux-dark-notify-theme.conf` to see that it is linked to the light or dark theme you configured. 69 | 70 | 71 | 72 | # Tips on more light/dark mode configuration 73 | * NeoVim: set up [dark-notify](https://github.com/cormacrelf/dark-notify) to change our nvim theme as well! 74 | * [iTerm2](https://iterm2.com/downloads.html): Use version >=3.5 (currently in beta) as it has support for automatically changing the whole terminal theme between light/dark when the system appearance mode changes. This is what I have in the demo GIF at the top of this file. 75 | * Go to iTerm2 Preferences > Profiles > your profile > Colors (tab): 76 | * Check the "Use different colors for light and dark mode" 77 | * Under "Editing:", chose your light and dark colors (tip: usee the color presets button). 78 | * Global keyboard shortcut: Create a global keyboard shortcut to toggle mode in macOS. 79 | * Open Automator.app 80 | * Create a new `Quick Action`. 81 | * Drag from the list to the left the "Change System Appearace" to the areaon the rnage, and set "Change Appearance" to "Toggle Light/Dark". 82 | * Save it e.g. as `apperance_toggle`. 83 | * Open System Settings > Keyboard > Keyboard shortcuts (button) > Services 84 | * Find the `apperance_toggle` service we just created under the General category 85 | * Bind it to a shortcut e.g. CTRL+OPT+CMD+t (this shortcut was used when feature first appeared in a beta version of macOS). 86 | 87 | # Development 88 | ## Codespaces Devcontainer 89 | You can fork this project and then start coding right away with GitHub Codespaces as this project is set up to install all development dependencies and install tmux-dark-notify on the devcontainer. See [devcontainer.json](.devcontainer/devcontainer.json) and [devcontainer_postCreateCommand.sh](scripts/devcontainer_postCreateCommand.sh). After starting the devcontainer, just type `tmux` in the terminal and you should see a working tmux-dark-notify already to start playing with. 90 | 91 | Note: if you have set up your own dotfiles to be installed with GitHub Codespaces, and there was some tmux config files installed from your dotfiles to the devcontainer, then you might have to run this script to wipe your config in favour of the setup provided by this repo's initialization: 92 | 93 | ```shell 94 | ./scripts/devcontainer_postCreateCommand.sh 95 | ``` 96 | 97 | Note: there is no macOS host image for devcontainers, so we can't actually use dark-notify. However you can manually simulate the change of mode e.g. light->dark by calling the CLI script yourself.: 98 | 99 | ```shell 100 | tmux # jump in to tmux 101 | ./scripts/tmux-theme-mode.sh dark 102 | ./scripts/tmux-theme-mode.sh light 103 | ``` 104 | and you will see how the tmux statusbar theme changes! 105 | 106 | # More tmux plugins 107 | I have another tmux plugin that might interest you: 108 | * [tmux-powerline](https://github.com/erikw/tmux-powerline) - A tmux plugin giving you a hackable status bar consisting of dynamic & beautiful looking powerline segments, written purely in bash. 109 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikw/tmux-dark-notify/59a6789f0a4f0d86e5b69629750f35905a7f1a88/demo.gif -------------------------------------------------------------------------------- /main.tmux: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Entry point for this plugin. This is loaded possibly multiple times on tmux start or session restore. Outsource handling of multiple running instances to the runner. This script just starts the runner in the background. 3 | 4 | set -o errexit 5 | set -o pipefail 6 | 7 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | RUNNER="${CURRENT_DIR}/scripts/tmux-dark-notify-runner.sh" 9 | 10 | $RUNNER & 11 | -------------------------------------------------------------------------------- /scripts/devcontainer_postCreateCommand.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Devcontainer postCreateCommand. 3 | # Install dependencies for running this project in GitHub Codespaces. 4 | 5 | set -eux 6 | 7 | # Defensive (aggressive?) sysop: in case user's dotfiles installed tmux configs already. 8 | # NOTE unfortunately there is not devcontainer command that runs after the setup of dotfiles. So these rm's might not have the intended effect... Just run this script manually once if you happen to have any own tmux confs installed via dotfiles in your Codespaces. Ref: https://containers.dev/implementors/json_reference/#lifecycle-scripts 9 | ## Tmux 10 | rm -rf "${XDG_CONFIG_HOME:-$HOME/.config}"/tmux 11 | rm -rf "$HOME"/.tmux 12 | 13 | 14 | # Set up TPM. Ref: https://github.com/tmux-plugins/tpm?#installation 15 | git clone https://github.com/tmux-plugins/tpm "$HOME"/.tmux/plugins/tpm 16 | 17 | cat << TMUXCONF > "$HOME"/.tmux.conf 18 | # List of plugins 19 | set -g @plugin 'tmux-plugins/tpm' 20 | set -g @plugin 'seebi/tmux-colors-solarized' 21 | # Install tmux-dark-notify as a "local plugin". Ref: https://github.com/tmux-plugins/tpm/issues/220#issuecomment-1082686994 22 | run '/workspaces/tmux-dark-notify/main.tmux' 23 | 24 | # Plugin options 25 | set -g @dark-notify-theme-path-light '$HOME/.tmux/plugins/tmux-colors-solarized/tmuxcolors-light.conf' 26 | set -g @dark-notify-theme-path-dark '$HOME/.tmux/plugins/tmux-colors-solarized/tmuxcolors-dark.conf' 27 | 28 | # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) 29 | run '~/.tmux/plugins/tpm/tpm' 30 | TMUXCONF 31 | 32 | # Install TPM plugins 33 | "$HOME"/.tmux/plugins/tpm/bin/install_plugins -------------------------------------------------------------------------------- /scripts/tmux-dark-notify-runner.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script will run dark-notify(1) in a while loop (in case it would exit). 3 | 4 | set -o errexit 5 | set -o pipefail 6 | [[ "${TRACE-0}" =~ ^1|t|y|true|yes$ ]] && set -o xtrace 7 | 8 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 9 | SCRIPT_NAME="$(basename $0)" 10 | TMUX_THEME_SETTER="${CURRENT_DIR}/tmux-theme-mode.sh" 11 | 12 | program_is_in_path() { 13 | local program="$1" 14 | type "$1" >/dev/null 2>&1 15 | } 16 | 17 | if pgrep -qf "$SCRIPT_NAME"; then 18 | echo "$SCRIPT_NAME is already running, nothing to do here." 19 | exit 0 20 | fi 21 | 22 | # Load Homebrew PATHs 23 | if ! program_is_in_path brew; then 24 | echo "Could not find brew(1) in \$PATH" >&2 25 | exit 1 26 | fi 27 | eval "$(brew shellenv)" 28 | 29 | if ! program_is_in_path dark-notify; then 30 | echo "Could not find dark-notify(1) in \$PATH" >&2 31 | exit 1 32 | fi 33 | 34 | while :; do 35 | dark-notify -c "$TMUX_THEME_SETTER" 36 | done 37 | -------------------------------------------------------------------------------- /scripts/tmux-theme-mode.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This script will set the tmux theme in use by rewriting a symlink and then sourcing the theme. 3 | # The dark/light theme paths should be configured in tmux user options (@-prefixed). 4 | # 5 | # Why write symlink and not just source? Because if tmux.conf uses the tmux-clear plugin and tmux.conf is resourced, then this plugin might not load. Then it's convenient to also have a "tmux source-file path/to/the/symlink-theme.conf" so that the right theme is still loaded. 6 | 7 | set -o errexit 8 | set -o pipefail 9 | [[ "${TRACE-0}" =~ ^1|t|y|true|yes$ ]] && set -o xtrace 10 | 11 | SCRIPT_NAME=${0##*/} 12 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 13 | cd "$SCRIPT_DIR" 14 | 15 | OPTION_THEME_LIGHT="@dark-notify-theme-path-light" 16 | OPTION_THEME_DARK="@dark-notify-theme-path-dark" 17 | 18 | IFS= read -rd '' USAGE <&2 34 | exit 1 35 | fi 36 | echo $opt_val 37 | } 38 | 39 | tmux_set_theme_mode() { 40 | local mode="$1" 41 | 42 | if [ "$mode" = dark ]; then 43 | theme_path=$(tmux_get_option $OPTION_THEME_DARK) 44 | else 45 | theme_path=$(tmux_get_option $OPTION_THEME_LIGHT) 46 | fi 47 | # Expand e.g. $HOME 48 | theme_path=$(eval echo "$theme_path") 49 | if [ ! -r "$theme_path" ]; then 50 | echo "The configured theme is not readable: $theme_path" >&2 51 | exit 2 52 | fi 53 | tmux source-file "$theme_path" 54 | ln -sf "$theme_path" $TMUX_THEME_LINK 55 | } 56 | 57 | mode= 58 | while getopts ":c:h?" opt; do 59 | case "$opt" in 60 | :) echo "Option -$OPTARG requires an argument." >&2; exit 1;; 61 | h|?|*) echo -e "$USAGE"; exit 0;; 62 | esac 63 | done 64 | shift $(($OPTIND - 1)) 65 | 66 | mode="$1" 67 | if [[ -z "$mode" ]]; then 68 | echo "Missing required argument 'mode'." >&2 69 | exit 1 70 | elif [[ "$mode" != light ]] && [[ "$1" != dark ]]; then 71 | echo "Mode must be 'light' or 'dark'." >&2 72 | exit 2 73 | fi 74 | 75 | tmux_set_theme_mode "$mode" 76 | --------------------------------------------------------------------------------