diff --git a/hm-imports/nvim/config/lua/dark_notify.lua b/hm-imports/nvim/config/lua/dark_notify.lua new file mode 100644 index 00000000..380ca195 --- /dev/null +++ b/hm-imports/nvim/config/lua/dark_notify.lua @@ -0,0 +1,210 @@ +-- http://lua-users.org/wiki/StringTrim +function trim6(s) + return s:match '^()%s*$' and '' or s:match '^%s*(.*%S)' +end + +-- from norcalli/nvim_utils +function nvim_create_augroups(definitions) + for group_name, definition in pairs(definitions) do + vim.api.nvim_command('augroup ' .. group_name) + vim.api.nvim_command('autocmd!') + for _, def in ipairs(definition) do + -- if type(def) == 'table' and type(def[#def]) == 'function' then + -- def[#def] = lua_callback(def[#def]) + -- end + local command = table.concat(vim.tbl_flatten { 'autocmd', def }, ' ') + vim.api.nvim_command(command) + end + vim.api.nvim_command('augroup END') + end +end + +local state = { + initialized = false, + pid = -1, + stdin_handle = nil, + config = {}, +} + +local M = {} + +local function ensure_config() + if state.config == nil then + state.config = {} + end +end + +local function get_config() + ensure_config() + return state.config +end + +local function edit_config(fn) + ensure_config() + fn(state.config) +end + +local function apply_mode(mode) + local config = get_config() + local sel = config.schemes[mode] or {} + local colorscheme = sel.colorscheme or nil + local bg = sel.background or mode + local lualineTheme = sel.lualine or nil + + vim.api.nvim_command('set background=' .. bg) + if colorscheme ~= nil then + vim.api.nvim_command('colorscheme ' .. colorscheme) + end + + require('lualine').setup { options = { theme = lualineTheme } } + + if config.onchange ~= nil then + config.onchange(mode) + end + + state.current_mode = mode +end + +function M.update() + local mode = vim.fn.system('dark-notify --exit') + mode = trim6(mode) + apply_mode(mode) +end + +function M.set_mode(mode) + mode = trim6(mode) + if not (mode == "light" or mode == "dark") then + error("mode must be either \"light\" or \"dark\"" .. mode) + return + end + apply_mode(mode) +end + +function M.toggle() + local mode = state.current_mode + if mode == "light" then + mode = "dark" + elseif mode == "dark" then + mode = "light" + else + M.update() + return + end + apply_mode(mode) +end + +local function init_dark_notify() + -- Docs on this vim.loop stuff: https://github.com/luvit/luv + + local handle, pid + local stdout = vim.loop.new_pipe(false) + local stdin = vim.loop.new_pipe(false) + + local function onexit() + vim.loop.close(handle, vim.schedule_wrap(function() + vim.loop.shutdown(stdout) + vim.loop.shutdown(stdin) + state.initialized = false + state.pid = nil + state.stdin_handle = nil + end)) + end + + local function onread(err, chunk) + assert(not err, err) + if (chunk) then + local mode = trim6(chunk) + if not (mode == "light" or mode == "dark") then + error("dark-notify output not expected: " .. chunk) + return + end + apply_mode(mode) + end + end + + handle, pid = vim.loop.spawn( + "dark-notify", + { stdio = { stdin, stdout, nil } }, + vim.schedule_wrap(onexit) + ) + + vim.loop.read_start(stdout, vim.schedule_wrap(onread)) + + state.initialized = true + state.pid = pid + state.stdin_handle = stdin + + -- For whatever reason, nvim isn't killing child processes properly on exit + -- So if you don't do this, you get zombie dark-notify processes hanging about. + nvim_create_augroups({ + DarkNotifyKillChildProcess = { + { "VimLeave", "*", "lua require('dark_notify').stop()" }, + } + }) +end + +-- For whatever reason, killing the child process doesn't work, at all. So we +-- send it the line "quit\n", and it kills itself. +function M.stop() + if state.stdin_handle == nil then + return + end + vim.loop.write(state.stdin_handle, "quit\n") + -- process quits itself, calls onexit + -- config gets edited from there +end + +function M.configure(config) + if config == nil then + return + end + local lightline_loaders = config.lightline_loaders or {} + local schemes = config.schemes or {} + local onchange = config.onchange + + for _, mode in pairs({ "light", "dark" }) do + if type(schemes[mode]) == "string" then + schemes[mode] = { colorscheme = schemes[mode] } + end + end + + edit_config(function(conf) + conf.lightline_loaders = lightline_loaders + conf.schemes = schemes + conf.onchange = onchange + end) +end + +function M.run(config) + if config ~= nil or get_config().schemes == nil then + -- if it's nil, it's a first run, so configure with no options. + config = config or {} + M.configure(config) + end + + local config = get_config() + if not config.initialized then + -- first run on startup, also happens to apply current mode + init_dark_notify() + elseif state.current_mode ~= nil then + -- we have run it before, but we're updating the settings + -- so don't reset to system, but do apply changed config. + local mode = state.current_mode + apply_mode(mode) + end +end + +return M + +-- init.lua or init.vim in a lua < /dev/null && pwd ) + +$DN/theme_switcher.sh diff --git a/hm-imports/tmux/tmux-switch-colors/theme_setter.sh b/hm-imports/tmux/tmux-switch-colors/theme_setter.sh new file mode 100755 index 00000000..7ead9203 --- /dev/null +++ b/hm-imports/tmux/tmux-switch-colors/theme_setter.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +DN=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +if [[ $1 == "dark" ]]; then + tmux source-file $DN/dark.tmux +else + tmux source-file $DN/light.tmux +fi diff --git a/hm-imports/tmux/tmux-switch-colors/theme_switcher.sh b/hm-imports/tmux/tmux-switch-colors/theme_switcher.sh new file mode 100755 index 00000000..25aed8db --- /dev/null +++ b/hm-imports/tmux/tmux-switch-colors/theme_switcher.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -o errexit +set -o pipefail +[[ "${TRACE-0}" =~ ^1|t|y|true|yes$ ]] && set -o xtrace + + +[[ ! $(type -P "dark-notify") ]] && echo "dark-notify command not found. Exiting..." && exit 0 +DN=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +SCRIPT_NAME="$(basename $0)" + +THEME_SETTER="$DN/theme_setter.sh" + +if pgrep -qf "$SCRIPT_NAME"; then + echo "$SCRIPT_NAME is already running, nothing to do here." + exit 0 +fi + +while :; do + dark-notify -c "$THEME_SETTER" +done diff --git a/hosts/daedalus/default.nix b/hosts/daedalus/default.nix index 1efa1064..79ff5969 100644 --- a/hosts/daedalus/default.nix +++ b/hosts/daedalus/default.nix @@ -15,6 +15,7 @@ with lib.my; enable = true; brews = [ "pam-reattach" + "cormacrelf/tap/dark-notify" ]; casks = [ "heroic"