mirror of
https://github.com/harivansh-afk/nix.git
synced 2026-04-15 06:04:42 +00:00
Merge pull request #1 from harivansh-afk/theme-scripts
theme and scripts
This commit is contained in:
commit
905375ff1a
20 changed files with 880 additions and 333 deletions
24
config/nvim/lua/config/fzf_reload.lua
Normal file
24
config/nvim/lua/config/fzf_reload.lua
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
local M = {}
|
||||
M.opts = nil
|
||||
|
||||
function M.setup(opts) M.opts = vim.deepcopy(opts or {}) end
|
||||
|
||||
function M.reload()
|
||||
local path = vim.env.FZF_DEFAULT_OPTS_FILE or vim.fn.expand "~/.config/fzf/themes/theme"
|
||||
if vim.fn.filereadable(path) == 0 then return end
|
||||
|
||||
local lines = vim.fn.readfile(path)
|
||||
if not lines or #lines == 0 or not M.opts then return end
|
||||
|
||||
local colors = {}
|
||||
for color_spec in table.concat(lines, "\n"):gmatch "%-%-color=([^%s]+)" do
|
||||
for key, value in color_spec:gmatch "([^:,]+):([^,]+)" do
|
||||
colors[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
M.opts.fzf_colors = colors
|
||||
require("fzf-lua").setup(M.opts)
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,74 +1,76 @@
|
|||
---@param kind 'issue'|'pr'
|
||||
---@param state 'all'|'open'|'closed'
|
||||
local function gh_picker(kind, state)
|
||||
if vim.fn.executable('gh') ~= 1 then
|
||||
vim.notify('gh CLI not found', vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
local next_state = ({ all = 'open', open = 'closed', closed = 'all' })[state]
|
||||
local label = kind == 'pr' and 'PRs' or 'Issues'
|
||||
require('fzf-lua').fzf_exec(('gh %s list --limit 100 --state %s'):format(kind, state), {
|
||||
prompt = ('%s (%s)> '):format(label, state),
|
||||
header = ':: <c-o> to toggle all/open/closed',
|
||||
actions = {
|
||||
['default'] = function(selected)
|
||||
local num = selected[1]:match('^#?(%d+)')
|
||||
if num then
|
||||
vim.system({ 'gh', kind, 'view', num, '--web' })
|
||||
end
|
||||
end,
|
||||
['ctrl-o'] = function()
|
||||
gh_picker(kind, next_state)
|
||||
end,
|
||||
},
|
||||
})
|
||||
if vim.fn.executable "gh" ~= 1 then
|
||||
vim.notify("gh CLI not found", vim.log.levels.WARN)
|
||||
return
|
||||
end
|
||||
local next_state = ({ all = "open", open = "closed", closed = "all" })[state]
|
||||
local label = kind == "pr" and "PRs" or "Issues"
|
||||
require("fzf-lua").fzf_exec(("gh %s list --limit 100 --state %s"):format(kind, state), {
|
||||
prompt = ("%s (%s)> "):format(label, state),
|
||||
header = ":: <c-o> to toggle all/open/closed",
|
||||
actions = {
|
||||
["default"] = function(selected)
|
||||
local num = selected[1]:match "^#?(%d+)"
|
||||
if num then vim.system { "gh", kind, "view", num, "--web" } end
|
||||
end,
|
||||
["ctrl-o"] = function() gh_picker(kind, next_state) end,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
return {
|
||||
'ibhagwan/fzf-lua',
|
||||
dependencies = { 'nvim-tree/nvim-web-devicons' },
|
||||
config = function(_, opts)
|
||||
require('fzf-lua').setup(opts)
|
||||
"ibhagwan/fzf-lua",
|
||||
dependencies = { "nvim-tree/nvim-web-devicons" },
|
||||
config = function(_, opts)
|
||||
local fzf = require "fzf-lua"
|
||||
fzf.setup(opts)
|
||||
|
||||
map('n', '<C-f>', function()
|
||||
local fzf = require('fzf-lua')
|
||||
local git_dir = vim.fn.system('git rev-parse --git-dir 2>/dev/null'):gsub('\n', '')
|
||||
if vim.v.shell_error == 0 and git_dir ~= '' then
|
||||
fzf.git_files()
|
||||
else
|
||||
fzf.files()
|
||||
end
|
||||
end)
|
||||
map('n', '<leader>ff', '<cmd>FzfLua files<cr>')
|
||||
map('n', '<leader>fg', '<cmd>FzfLua live_grep<cr>')
|
||||
map('n', '<leader>fb', '<cmd>FzfLua buffers<cr>')
|
||||
map('n', '<leader>fh', '<cmd>FzfLua help_tags<cr>')
|
||||
map('n', '<leader>fr', '<cmd>FzfLua resume<cr>')
|
||||
map('n', '<leader>fo', '<cmd>FzfLua oldfiles<cr>')
|
||||
map('n', '<leader>fc', '<cmd>FzfLua commands<cr>')
|
||||
map('n', '<leader>fk', '<cmd>FzfLua keymaps<cr>')
|
||||
map('n', '<leader>f/', '<cmd>FzfLua search_history<cr>')
|
||||
map('n', '<leader>f:', '<cmd>FzfLua command_history<cr>')
|
||||
map('n', '<leader>fe', '<cmd>FzfLua files cwd=~/.config<cr>')
|
||||
map('n', 'gq', '<cmd>FzfLua quickfix<cr>')
|
||||
map('n', 'gl', '<cmd>FzfLua loclist<cr>')
|
||||
map('n', '<leader>GB', '<cmd>FzfLua git_branches<cr>')
|
||||
map('n', '<leader>Gc', '<cmd>FzfLua git_commits<cr>')
|
||||
map('n', '<leader>Gs', '<cmd>FzfLua git_status<cr>')
|
||||
map('n', '<leader>Gp', function() gh_picker('pr', 'open') end)
|
||||
map('n', '<leader>Gi', function() gh_picker('issue', 'open') end)
|
||||
end,
|
||||
opts = {
|
||||
'default-title',
|
||||
winopts = {
|
||||
border = 'single',
|
||||
preview = {
|
||||
layout = 'vertical',
|
||||
vertical = 'down:50%',
|
||||
},
|
||||
},
|
||||
fzf_opts = {
|
||||
['--layout'] = 'reverse',
|
||||
},
|
||||
local ok, fzf_reload = pcall(require, "config.fzf_reload")
|
||||
if ok then
|
||||
fzf_reload.setup(opts)
|
||||
fzf_reload.reload()
|
||||
end
|
||||
|
||||
map("n", "<C-f>", function()
|
||||
local git_dir = vim.fn.system("git rev-parse --git-dir 2>/dev/null"):gsub("\n", "")
|
||||
if vim.v.shell_error == 0 and git_dir ~= "" then
|
||||
fzf.git_files()
|
||||
else
|
||||
fzf.files()
|
||||
end
|
||||
end)
|
||||
map("n", "<leader>ff", "<cmd>FzfLua files<cr>")
|
||||
map("n", "<leader>fg", "<cmd>FzfLua live_grep<cr>")
|
||||
map("n", "<leader>fb", "<cmd>FzfLua buffers<cr>")
|
||||
map("n", "<leader>fh", "<cmd>FzfLua help_tags<cr>")
|
||||
map("n", "<leader>fr", "<cmd>FzfLua resume<cr>")
|
||||
map("n", "<leader>fo", "<cmd>FzfLua oldfiles<cr>")
|
||||
map("n", "<leader>fc", "<cmd>FzfLua commands<cr>")
|
||||
map("n", "<leader>fk", "<cmd>FzfLua keymaps<cr>")
|
||||
map("n", "<leader>f/", "<cmd>FzfLua search_history<cr>")
|
||||
map("n", "<leader>f:", "<cmd>FzfLua command_history<cr>")
|
||||
map("n", "<leader>fe", "<cmd>FzfLua files cwd=~/.config<cr>")
|
||||
map("n", "gq", "<cmd>FzfLua quickfix<cr>")
|
||||
map("n", "gl", "<cmd>FzfLua loclist<cr>")
|
||||
map("n", "<leader>GB", "<cmd>FzfLua git_branches<cr>")
|
||||
map("n", "<leader>Gc", "<cmd>FzfLua git_commits<cr>")
|
||||
map("n", "<leader>Gs", "<cmd>FzfLua git_status<cr>")
|
||||
map("n", "<leader>Gp", function() gh_picker("pr", "open") end)
|
||||
map("n", "<leader>Gi", function() gh_picker("issue", "open") end)
|
||||
end,
|
||||
opts = {
|
||||
"default-title",
|
||||
winopts = {
|
||||
border = "single",
|
||||
preview = {
|
||||
layout = "vertical",
|
||||
vertical = "down:50%",
|
||||
},
|
||||
},
|
||||
fzf_opts = {
|
||||
["--layout"] = "reverse",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,74 +1,50 @@
|
|||
return {
|
||||
{
|
||||
'harivansh-afk/cozybox.nvim',
|
||||
lazy = false,
|
||||
priority = 1000,
|
||||
config = function()
|
||||
local function apply_cozybox_overrides()
|
||||
local links = {
|
||||
{ 'DiffsAdd', 'DiffAdd' },
|
||||
{ 'DiffsDelete', 'DiffDelete' },
|
||||
{ 'DiffsChange', 'DiffChange' },
|
||||
{ 'DiffsText', 'DiffText' },
|
||||
{ 'DiffsClear', 'Normal' },
|
||||
}
|
||||
for _, pair in ipairs(links) do
|
||||
vim.api.nvim_set_hl(0, pair[1], { link = pair[2], default = false })
|
||||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_create_augroup('cozybox_fallback_highlights', { clear = true })
|
||||
vim.api.nvim_create_autocmd('ColorScheme', {
|
||||
group = 'cozybox_fallback_highlights',
|
||||
callback = function()
|
||||
if vim.g.colors_name == 'cozybox' then
|
||||
apply_cozybox_overrides()
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
vim.cmd.colorscheme('cozybox')
|
||||
apply_cozybox_overrides()
|
||||
end,
|
||||
},
|
||||
{
|
||||
'nvim-lualine/lualine.nvim',
|
||||
dependencies = { 'nvim-tree/nvim-web-devicons' },
|
||||
config = function()
|
||||
local theme = {
|
||||
normal = {
|
||||
a = { gui = 'bold' },
|
||||
},
|
||||
visual = {
|
||||
a = { gui = 'bold' },
|
||||
},
|
||||
replace = {
|
||||
a = { gui = 'bold' },
|
||||
},
|
||||
command = {
|
||||
a = { gui = 'bold' },
|
||||
},
|
||||
}
|
||||
require('lualine').setup({
|
||||
options = {
|
||||
icons_enabled = false,
|
||||
component_separators = '',
|
||||
section_separators = { left = '', right = '' },
|
||||
theme = theme,
|
||||
},
|
||||
sections = {
|
||||
lualine_a = { 'mode' },
|
||||
lualine_b = { 'FugitiveHead', 'diff' },
|
||||
lualine_c = { { 'filename', path = 0 } },
|
||||
lualine_x = { 'diagnostics' },
|
||||
lualine_y = { 'filetype' },
|
||||
lualine_z = { 'progress' },
|
||||
},
|
||||
})
|
||||
end,
|
||||
},
|
||||
{
|
||||
'barrettruth/nonicons.nvim',
|
||||
dependencies = { 'nvim-tree/nvim-web-devicons' },
|
||||
},
|
||||
{
|
||||
dir = vim.fn.expand "~/Documents/GitHub/cozybox.nvim",
|
||||
name = "cozybox.nvim",
|
||||
lazy = false,
|
||||
priority = 1000,
|
||||
config = function() require("theme").setup() end,
|
||||
},
|
||||
{
|
||||
"nvim-lualine/lualine.nvim",
|
||||
dependencies = { "nvim-tree/nvim-web-devicons" },
|
||||
config = function()
|
||||
local theme_status = function() return require("theme").statusline_label() end
|
||||
local theme = {
|
||||
normal = {
|
||||
a = { gui = "bold" },
|
||||
},
|
||||
visual = {
|
||||
a = { gui = "bold" },
|
||||
},
|
||||
replace = {
|
||||
a = { gui = "bold" },
|
||||
},
|
||||
command = {
|
||||
a = { gui = "bold" },
|
||||
},
|
||||
}
|
||||
require("lualine").setup {
|
||||
options = {
|
||||
icons_enabled = false,
|
||||
component_separators = "",
|
||||
section_separators = { left = "", right = "" },
|
||||
theme = theme,
|
||||
},
|
||||
sections = {
|
||||
lualine_a = { "mode" },
|
||||
lualine_b = { "FugitiveHead", "diff" },
|
||||
lualine_c = { { "filename", path = 0 } },
|
||||
lualine_x = { "diagnostics" },
|
||||
lualine_y = { "filetype" },
|
||||
lualine_z = { theme_status, "progress" },
|
||||
},
|
||||
}
|
||||
end,
|
||||
},
|
||||
{
|
||||
"barrettruth/nonicons.nvim",
|
||||
dependencies = { "nvim-tree/nvim-web-devicons" },
|
||||
},
|
||||
}
|
||||
|
|
|
|||
111
config/nvim/lua/theme.lua
Normal file
111
config/nvim/lua/theme.lua
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
local M = {}
|
||||
|
||||
local xdg_state_home = vim.env.XDG_STATE_HOME or (vim.env.HOME .. "/.local/state")
|
||||
local theme_state_file = xdg_state_home .. "/theme/current"
|
||||
local active_schemes = {
|
||||
cozybox = true,
|
||||
["cozybox-light"] = true,
|
||||
}
|
||||
|
||||
local function ensure_server_socket()
|
||||
local socket_path = ("/tmp/nvim-%d.sock"):format(vim.fn.getpid())
|
||||
local active_servers = vim.fn.serverlist()
|
||||
|
||||
for _, server in ipairs(active_servers) do
|
||||
if server == socket_path then return end
|
||||
end
|
||||
|
||||
local stat = vim.uv.fs_stat(socket_path)
|
||||
if stat and stat.type == "socket" then vim.fn.delete(socket_path) end
|
||||
|
||||
vim.fn.serverstart(socket_path)
|
||||
end
|
||||
|
||||
local function apply_cozybox_overrides()
|
||||
local links = {
|
||||
{ "DiffsAdd", "DiffAdd" },
|
||||
{ "DiffsDelete", "DiffDelete" },
|
||||
{ "DiffsChange", "DiffChange" },
|
||||
{ "DiffsText", "DiffText" },
|
||||
{ "DiffsClear", "Normal" },
|
||||
}
|
||||
|
||||
for _, pair in ipairs(links) do
|
||||
vim.api.nvim_set_hl(0, pair[1], { link = pair[2], default = false })
|
||||
end
|
||||
end
|
||||
|
||||
local function read_mode()
|
||||
local ok, lines = pcall(vim.fn.readfile, theme_state_file)
|
||||
if not ok or not lines or not lines[1] then return "dark" end
|
||||
|
||||
local mode = vim.trim(lines[1])
|
||||
if mode == "light" then return "light" end
|
||||
|
||||
return "dark"
|
||||
end
|
||||
|
||||
local function colorscheme_for_mode(mode)
|
||||
if mode == "light" then return "cozybox-light" end
|
||||
|
||||
return "cozybox"
|
||||
end
|
||||
|
||||
function M.statusline_label()
|
||||
local mode = vim.g.cozybox_theme_mode or read_mode()
|
||||
local scheme = vim.g.colors_name or colorscheme_for_mode(mode)
|
||||
local expected_scheme = colorscheme_for_mode(mode)
|
||||
|
||||
if scheme == expected_scheme then return "theme:" .. mode end
|
||||
|
||||
return ("theme:%s/%s"):format(mode, scheme)
|
||||
end
|
||||
|
||||
function M.apply(mode)
|
||||
local next_mode = mode or read_mode()
|
||||
local next_scheme = colorscheme_for_mode(next_mode)
|
||||
|
||||
if vim.o.background ~= next_mode then vim.o.background = next_mode end
|
||||
|
||||
if vim.g.cozybox_theme_mode ~= next_mode or vim.g.colors_name ~= next_scheme then vim.cmd.colorscheme(next_scheme) end
|
||||
|
||||
vim.g.cozybox_theme_mode = next_mode
|
||||
apply_cozybox_overrides()
|
||||
local ok_reload, fzf_reload = pcall(require, "config.fzf_reload")
|
||||
if ok_reload then pcall(fzf_reload.reload) end
|
||||
vim.schedule(function()
|
||||
local ok, lualine = pcall(require, "lualine")
|
||||
if ok then pcall(lualine.refresh, { place = { "statusline" } }) end
|
||||
pcall(vim.cmd, "redraw!")
|
||||
end)
|
||||
end
|
||||
|
||||
function M.setup()
|
||||
local group = vim.api.nvim_create_augroup("cozybox_theme_sync", { clear = true })
|
||||
|
||||
ensure_server_socket()
|
||||
|
||||
vim.api.nvim_create_autocmd("ColorScheme", {
|
||||
group = group,
|
||||
callback = function()
|
||||
if active_schemes[vim.g.colors_name] then apply_cozybox_overrides() end
|
||||
end,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd({ "VimEnter", "FocusGained" }, {
|
||||
group = group,
|
||||
callback = function() M.apply() end,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_user_command("ThemeSync", function(opts)
|
||||
local mode = opts.args ~= "" and opts.args or nil
|
||||
M.apply(mode)
|
||||
end, {
|
||||
nargs = "?",
|
||||
complete = function() return { "dark", "light" } end,
|
||||
})
|
||||
|
||||
M.apply()
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
./bat.nix
|
||||
./claude.nix
|
||||
./codex.nix
|
||||
./fzf.nix
|
||||
./gcloud.nix
|
||||
./gh.nix
|
||||
./ghostty.nix
|
||||
|
|
@ -13,6 +14,7 @@
|
|||
./migration.nix
|
||||
./nvim.nix
|
||||
./rectangle.nix
|
||||
./scripts.nix
|
||||
./tmux.nix
|
||||
./zsh.nix
|
||||
];
|
||||
|
|
|
|||
10
home/fzf.nix
Normal file
10
home/fzf.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{config, ...}: let
|
||||
theme = import ../lib/theme.nix {inherit config;};
|
||||
in {
|
||||
home.sessionVariables = {
|
||||
FZF_DEFAULT_OPTS_FILE = theme.paths.fzfCurrentFile;
|
||||
};
|
||||
|
||||
xdg.configFile."fzf/themes/cozybox-dark".text = theme.renderFzf "dark";
|
||||
xdg.configFile."fzf/themes/cozybox-light".text = theme.renderFzf "light";
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
{ pkgs, ... }:
|
||||
let
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
theme = import ../lib/theme.nix {inherit config;};
|
||||
ghosttyConfig = ''
|
||||
theme = "Gruvbox Material Dark"
|
||||
background = #181818
|
||||
cursor-color = #ddc7a1
|
||||
selection-background = #504945
|
||||
selection-foreground = #ebdbb2
|
||||
theme = "cozybox-current"
|
||||
font-family = Berkeley Mono
|
||||
font-codepoint-map = U+f101-U+f25c=nonicons
|
||||
background-opacity = 1
|
||||
|
|
@ -38,12 +38,6 @@ let
|
|||
keybind = vim/i=deactivate_key_table
|
||||
keybind = vim/catch_all=ignore
|
||||
mouse-hide-while-typing = true
|
||||
palette = 2=#8ec97c
|
||||
palette = 10=#8ec97c
|
||||
palette = 4=#4672d4
|
||||
palette = 12=#4672d4
|
||||
palette = 6=#8ec07c
|
||||
palette = 14=#8ec07c
|
||||
macos-titlebar-style = hidden
|
||||
macos-option-as-alt = true
|
||||
confirm-close-surface = true
|
||||
|
|
@ -67,6 +61,9 @@ in {
|
|||
force = true;
|
||||
};
|
||||
|
||||
xdg.configFile."ghostty/themes/cozybox-dark".text = theme.renderGhostty "dark";
|
||||
xdg.configFile."ghostty/themes/cozybox-light".text = theme.renderGhostty "light";
|
||||
|
||||
home.file."Library/Application Support/com.mitchellh.ghostty/config.ghostty" = {
|
||||
text = ghosttyConfig;
|
||||
force = true;
|
||||
|
|
|
|||
39
home/scripts.nix
Normal file
39
home/scripts.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
customScripts = import ../scripts {inherit config lib pkgs;};
|
||||
in {
|
||||
home.packages = builtins.attrValues customScripts.packages;
|
||||
|
||||
home.activation.initializeThemeState = lib.hm.dag.entryAfter ["writeBoundary"] ''
|
||||
mkdir -p "${customScripts.theme.paths.stateDir}" "${customScripts.theme.paths.fzfDir}" "${customScripts.theme.paths.ghosttyDir}" "${customScripts.theme.paths.tmuxDir}"
|
||||
|
||||
if [[ -f "${customScripts.theme.paths.stateFile}" ]]; then
|
||||
mode=$(tr -d '[:space:]' < "${customScripts.theme.paths.stateFile}")
|
||||
else
|
||||
mode="${customScripts.theme.defaultMode}"
|
||||
printf '%s\n' "$mode" > "${customScripts.theme.paths.stateFile}"
|
||||
fi
|
||||
|
||||
case "$mode" in
|
||||
light)
|
||||
fzf_target="${customScripts.theme.paths.fzfDir}/cozybox-light"
|
||||
ghostty_target="${customScripts.theme.paths.ghosttyDir}/cozybox-light"
|
||||
tmux_target="${customScripts.tmuxConfigs.light}"
|
||||
;;
|
||||
*)
|
||||
printf '%s\n' "${customScripts.theme.defaultMode}" > "${customScripts.theme.paths.stateFile}"
|
||||
fzf_target="${customScripts.theme.paths.fzfDir}/cozybox-dark"
|
||||
ghostty_target="${customScripts.theme.paths.ghosttyDir}/cozybox-dark"
|
||||
tmux_target="${customScripts.tmuxConfigs.dark}"
|
||||
;;
|
||||
esac
|
||||
|
||||
ln -sfn "$fzf_target" "${customScripts.theme.paths.fzfCurrentFile}"
|
||||
ln -sfn "$ghostty_target" "${customScripts.theme.paths.ghosttyCurrentFile}"
|
||||
ln -sfn "$tmux_target" "${customScripts.theme.paths.tmuxCurrentFile}"
|
||||
'';
|
||||
}
|
||||
|
|
@ -1,4 +1,11 @@
|
|||
{lib, pkgs, ...}: {
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
theme = import ../lib/theme.nix {inherit config;};
|
||||
in {
|
||||
programs.tmux = {
|
||||
enable = true;
|
||||
plugins = with pkgs.tmuxPlugins; [
|
||||
|
|
@ -75,54 +82,14 @@
|
|||
# Disable waiting time when pressing escape, for smoother Neovim usage.
|
||||
set-option -s escape-time 0
|
||||
|
||||
# Styling
|
||||
RED="#ea6962"
|
||||
GREEN="#8ec97c"
|
||||
YELLOW="#d8a657"
|
||||
BLUE="#4672d4"
|
||||
MAGENTA="#d3869b"
|
||||
CYAN="#89b482"
|
||||
BLACK="#1d2021"
|
||||
DARK_GRAY="#181818"
|
||||
LIGHT_GRAY="#4F4946"
|
||||
# Match Ghostty theme (cozybox-override palette + Gruvbox Material Dark base)
|
||||
BG="#181818"
|
||||
FG="#d4be98"
|
||||
|
||||
HALF_ROUND_OPEN="#(printf '\uE0B2')"
|
||||
HALF_ROUND_CLOSE="#(printf '\uE0B0')"
|
||||
TRIANGLE_OPEN="#(printf '\uE0B2')"
|
||||
TRIANGLE_CLOSE="#(printf '\uE0B0')"
|
||||
|
||||
set-option -g prompt-cursor-colour default
|
||||
set-option -g status-position bottom
|
||||
set-option -g status-style bg=''${BG},fg=''${FG}
|
||||
set-option -g status-justify left
|
||||
set-option -g status-left ""
|
||||
set-option -g status-right "#(~/.config/tmux/session-list.sh)"
|
||||
set-option -g status-left-length 100
|
||||
set-option -g status-right-length 100
|
||||
|
||||
set-option -g window-status-format "\
|
||||
\
|
||||
#I\
|
||||
#[fg=''${MAGENTA}]:\
|
||||
#[fg=default]#W\
|
||||
\
|
||||
"
|
||||
|
||||
set-option -g window-status-current-format "\
|
||||
\
|
||||
#[fg=''${MAGENTA}]*#[fg=default]#I\
|
||||
#[fg=''${MAGENTA}]:\
|
||||
#[fg=default]#W\
|
||||
\
|
||||
"
|
||||
|
||||
set-option -g window-status-separator ""
|
||||
|
||||
set-option -g pane-border-style fg=''${BG}
|
||||
set-option -g pane-active-border-style fg=''${BG}
|
||||
|
||||
source-file "${theme.paths.tmuxCurrentFile}"
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -131,9 +98,10 @@
|
|||
text = ''
|
||||
#!/bin/sh
|
||||
current=$(tmux display-message -p '#S')
|
||||
accent=$(tmux show -gv @cozybox-accent 2>/dev/null || printf '#d3869b')
|
||||
tmux list-sessions -F '#S' | while IFS= read -r s; do
|
||||
if [ "$s" = "$current" ]; then
|
||||
printf ' #[fg=#d3869b]*#[fg=default]%s ' "$s"
|
||||
printf ' #[fg=%s]*#[fg=default]%s ' "$accent" "$s"
|
||||
else
|
||||
printf ' %s ' "$s"
|
||||
fi
|
||||
|
|
|
|||
230
home/zsh.nix
230
home/zsh.nix
|
|
@ -41,11 +41,11 @@
|
|||
tailscale = "/Applications/Tailscale.app/Contents/MacOS/Tailscale";
|
||||
|
||||
# nix helpers
|
||||
nr = "nix profile remove"; # nr <index> - remove from profile
|
||||
ns = "nix search nixpkgs"; # ns <query> - search packages
|
||||
nls = "nix profile list"; # nls - list installed profile packages
|
||||
nrb = "sudo darwin-rebuild switch --flake ~/Documents/GitHub/nix"; # nrb - rebuild declarative config
|
||||
nup = "nix flake update ~/Documents/GitHub/nix && sudo darwin-rebuild switch --flake ~/Documents/GitHub/nix"; # nup - update flake + rebuild
|
||||
nr = "nix profile remove"; # nr <index> - remove from profile
|
||||
ns = "nix search nixpkgs"; # ns <query> - search packages
|
||||
nls = "nix profile list"; # nls - list installed profile packages
|
||||
nrb = "sudo darwin-rebuild switch --flake ~/Documents/GitHub/nix"; # nrb - rebuild declarative config
|
||||
nup = "nix flake update ~/Documents/GitHub/nix && sudo darwin-rebuild switch --flake ~/Documents/GitHub/nix"; # nup - update flake + rebuild
|
||||
};
|
||||
|
||||
envExtra = ''
|
||||
|
|
@ -108,16 +108,92 @@
|
|||
$path
|
||||
)
|
||||
|
||||
ni() { nix profile add "nixpkgs#$1"; }
|
||||
_codex_read_theme_mode() {
|
||||
local mode_file="$HOME/.local/state/theme/current"
|
||||
if [[ -f "$mode_file" ]]; then
|
||||
local mode
|
||||
mode=$(tr -d '[:space:]' < "$mode_file")
|
||||
if [[ "$mode" == light || "$mode" == dark ]]; then
|
||||
printf '%s' "$mode"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
printf 'dark'
|
||||
}
|
||||
|
||||
_codex_apply_highlight_styles() {
|
||||
local mode="$(_codex_read_theme_mode)"
|
||||
if [[ "$mode" == "''${_CODEX_LAST_HIGHLIGHT_THEME:-}" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
typeset -gA ZSH_HIGHLIGHT_STYLES
|
||||
|
||||
if [[ "$mode" == light ]]; then
|
||||
ZSH_HIGHLIGHT_STYLES[arg0]='fg=#427b58'
|
||||
ZSH_HIGHLIGHT_STYLES[autodirectory]='fg=#427b58,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[back-dollar-quoted-argument]='fg=#076678'
|
||||
ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument]='fg=#076678'
|
||||
ZSH_HIGHLIGHT_STYLES[back-quoted-argument-delimiter]='fg=#8f3f71'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-error]='fg=#ea6962,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-1]='fg=#076678,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-2]='fg=#427b58,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-3]='fg=#8f3f71,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-4]='fg=#b57614,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-5]='fg=#076678,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[comment]='fg=#928374'
|
||||
ZSH_HIGHLIGHT_STYLES[command-substitution-delimiter]='fg=#8f3f71'
|
||||
ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument]='fg=#076678'
|
||||
ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]='fg=#b57614'
|
||||
ZSH_HIGHLIGHT_STYLES[double-quoted-argument]='fg=#b57614'
|
||||
ZSH_HIGHLIGHT_STYLES[global-alias]='fg=#076678'
|
||||
ZSH_HIGHLIGHT_STYLES[globbing]='fg=#076678'
|
||||
ZSH_HIGHLIGHT_STYLES[history-expansion]='fg=#076678'
|
||||
ZSH_HIGHLIGHT_STYLES[path]='fg=#3c3836,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[precommand]='fg=#427b58,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[process-substitution-delimiter]='fg=#8f3f71'
|
||||
ZSH_HIGHLIGHT_STYLES[rc-quote]='fg=#076678'
|
||||
ZSH_HIGHLIGHT_STYLES[redirection]='fg=#b57614'
|
||||
ZSH_HIGHLIGHT_STYLES[reserved-word]='fg=#b57614'
|
||||
ZSH_HIGHLIGHT_STYLES[single-quoted-argument]='fg=#b57614'
|
||||
ZSH_HIGHLIGHT_STYLES[suffix-alias]='fg=#427b58,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[unknown-token]='fg=#ea6962,bold'
|
||||
else
|
||||
ZSH_HIGHLIGHT_STYLES[arg0]='fg=#8ec97c'
|
||||
ZSH_HIGHLIGHT_STYLES[autodirectory]='fg=#8ec97c,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[back-dollar-quoted-argument]='fg=#8ec07c'
|
||||
ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument]='fg=#8ec07c'
|
||||
ZSH_HIGHLIGHT_STYLES[back-quoted-argument-delimiter]='fg=#d3869b'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-error]='fg=#ea6962,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-1]='fg=#5b84de,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-2]='fg=#8ec97c,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-3]='fg=#d3869b,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-4]='fg=#d8a657,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[bracket-level-5]='fg=#8ec07c,bold'
|
||||
ZSH_HIGHLIGHT_STYLES[comment]='fg=#7c6f64'
|
||||
ZSH_HIGHLIGHT_STYLES[command-substitution-delimiter]='fg=#d3869b'
|
||||
ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument]='fg=#8ec07c'
|
||||
ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]='fg=#d8a657'
|
||||
ZSH_HIGHLIGHT_STYLES[double-quoted-argument]='fg=#d8a657'
|
||||
ZSH_HIGHLIGHT_STYLES[global-alias]='fg=#8ec07c'
|
||||
ZSH_HIGHLIGHT_STYLES[globbing]='fg=#5b84de'
|
||||
ZSH_HIGHLIGHT_STYLES[history-expansion]='fg=#5b84de'
|
||||
ZSH_HIGHLIGHT_STYLES[path]='fg=#d4be98,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[precommand]='fg=#8ec97c,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[process-substitution-delimiter]='fg=#d3869b'
|
||||
ZSH_HIGHLIGHT_STYLES[rc-quote]='fg=#8ec07c'
|
||||
ZSH_HIGHLIGHT_STYLES[redirection]='fg=#d8a657'
|
||||
ZSH_HIGHLIGHT_STYLES[reserved-word]='fg=#d8a657'
|
||||
ZSH_HIGHLIGHT_STYLES[single-quoted-argument]='fg=#d8a657'
|
||||
ZSH_HIGHLIGHT_STYLES[suffix-alias]='fg=#8ec97c,underline'
|
||||
ZSH_HIGHLIGHT_STYLES[unknown-token]='fg=#ea6962,bold'
|
||||
fi
|
||||
|
||||
typeset -g _CODEX_LAST_HIGHLIGHT_THEME="$mode"
|
||||
}
|
||||
|
||||
unalias ga 2>/dev/null
|
||||
ga() {
|
||||
if [[ $# -eq 0 ]]; then
|
||||
git add .
|
||||
else
|
||||
git add "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
git() {
|
||||
command git "$@"
|
||||
|
|
@ -162,6 +238,7 @@
|
|||
zle -N zle-line-finish
|
||||
|
||||
precmd() {
|
||||
_codex_apply_highlight_styles
|
||||
_codex_set_cursor beam
|
||||
}
|
||||
|
||||
|
|
@ -169,136 +246,11 @@
|
|||
_codex_set_cursor beam
|
||||
}
|
||||
|
||||
iosrun() {
|
||||
local project=$(find . -maxdepth 1 -name "*.xcodeproj" | head -1)
|
||||
local scheme=$(basename "$project" .xcodeproj)
|
||||
local derived=".derived-data"
|
||||
local sim_name="''${1:-iPhone 16e}"
|
||||
|
||||
if [[ -z "$project" ]]; then
|
||||
echo "No .xcodeproj found in current directory"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Building $scheme..."
|
||||
if ! xcodebuild -project "$project" -scheme "$scheme" \
|
||||
-destination "platform=iOS Simulator,name=$sim_name" \
|
||||
-derivedDataPath "$derived" build -quiet; then
|
||||
echo "Build failed"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Build succeeded. Launching simulator..."
|
||||
|
||||
xcrun simctl boot "$sim_name" 2>/dev/null
|
||||
open -a Simulator
|
||||
|
||||
local app_path="$derived/Build/Products/Debug-iphonesimulator/$scheme.app"
|
||||
local bundle_id=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$app_path/Info.plist")
|
||||
|
||||
echo "Installing $scheme..."
|
||||
while ! xcrun simctl install "$sim_name" "$app_path" 2>/dev/null; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
echo "Launching $bundle_id..."
|
||||
while ! xcrun simctl launch "$sim_name" "$bundle_id" 2>&1 | grep -q "$bundle_id"; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
echo "Launched $bundle_id - streaming logs (Ctrl+C to stop)"
|
||||
echo "----------------------------------------"
|
||||
|
||||
xcrun simctl spawn "$sim_name" log stream \
|
||||
--predicate "(subsystem CONTAINS '$bundle_id' OR process == '$scheme') AND NOT subsystem BEGINSWITH 'com.apple'" \
|
||||
--style compact \
|
||||
--color always 2>/dev/null | while read -r line; do
|
||||
if [[ "$line" == *"error"* ]] || [[ "$line" == *"Error"* ]]; then
|
||||
echo "\033[31m$line\033[0m"
|
||||
elif [[ "$line" == *"warning"* ]] || [[ "$line" == *"Warning"* ]]; then
|
||||
echo "\033[33m$line\033[0m"
|
||||
else
|
||||
echo "$line"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
mdview() {
|
||||
markserv "$1"
|
||||
}
|
||||
_codex_apply_highlight_styles
|
||||
|
||||
if command -v wt >/dev/null 2>&1; then
|
||||
eval "$(command wt config shell init zsh)"
|
||||
fi
|
||||
|
||||
wtc() { wt switch --create --base @ "$@"; }
|
||||
|
||||
unalias gpr 2>/dev/null
|
||||
gpr() {
|
||||
while true; do
|
||||
local pr=$(gh pr list --limit 50 \
|
||||
--json number,title,author,headRefName \
|
||||
--template '{{range .}}#{{.number}} {{.title}} ({{.author.login}}) [{{.headRefName}}]{{"\n"}}{{end}}' \
|
||||
| fzf --preview 'gh pr view {1} --comments' \
|
||||
--preview-window=right:60%:wrap \
|
||||
--header 'enter: view | ctrl-m: merge | ctrl-x: close | ctrl-o: checkout | ctrl-b: browser' \
|
||||
--bind 'ctrl-o:execute(gh pr checkout {1})' \
|
||||
--bind 'ctrl-b:execute(gh pr view {1} --web)' \
|
||||
--expect=ctrl-m,ctrl-x,enter)
|
||||
|
||||
[[ -z "$pr" ]] && return
|
||||
|
||||
local key=$(echo "$pr" | head -1)
|
||||
local selection=$(echo "$pr" | tail -1)
|
||||
local num=$(echo "$selection" | grep -o '#[0-9]*' | tr -d '#')
|
||||
|
||||
[[ -z "$num" ]] && return
|
||||
|
||||
case "$key" in
|
||||
ctrl-m)
|
||||
echo "Merge PR #$num? (y/n)"
|
||||
read -q && gh pr merge "$num" --merge
|
||||
echo
|
||||
;;
|
||||
ctrl-x)
|
||||
echo "Close PR #$num? (y/n)"
|
||||
read -q && gh pr close "$num"
|
||||
echo
|
||||
;;
|
||||
enter|"")
|
||||
gh pr view "$num"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
ghpr() {
|
||||
local base=$(git rev-parse --abbrev-ref HEAD)
|
||||
local upstream="''${1:-main}"
|
||||
local remote_ref="origin/$upstream"
|
||||
local unpushed=$(git log "$remote_ref"..HEAD --oneline 2>/dev/null)
|
||||
|
||||
if [[ -z "$unpushed" ]]; then
|
||||
if git diff --cached --quiet; then
|
||||
echo "No unpushed commits and no staged changes"
|
||||
return 1
|
||||
fi
|
||||
echo "No unpushed commits, but staged changes found. Opening commit dialog..."
|
||||
git commit || return 1
|
||||
fi
|
||||
|
||||
local msg=$(git log "$remote_ref"..HEAD --format='%s' --reverse | head -1)
|
||||
local branch=$(echo "$msg" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
|
||||
|
||||
git checkout -b "$branch"
|
||||
git checkout "$base"
|
||||
git reset --hard "$remote_ref"
|
||||
git checkout "$branch"
|
||||
|
||||
git push -u origin "$branch"
|
||||
gh pr create --base "$upstream" --fill --web 2>/dev/null || gh pr create --base "$upstream" --fill
|
||||
gh pr view "$branch" --json url -q '.url'
|
||||
}
|
||||
'')
|
||||
|
||||
(lib.mkAfter ''
|
||||
|
|
|
|||
135
lib/theme.nix
Normal file
135
lib/theme.nix
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
{config, ...}: let
|
||||
defaultMode = "dark";
|
||||
sharedPalette = {
|
||||
red = "#ea6962";
|
||||
green = "#8ec97c";
|
||||
yellow = "#d79921";
|
||||
yellowBright = "#fabd2f";
|
||||
blue = "#5b84de";
|
||||
purple = "#d3869b";
|
||||
purpleNeutral = "#b16286";
|
||||
aqua = "#8ec07c";
|
||||
aquaNeutral = "#689d6a";
|
||||
gray = "#928374";
|
||||
};
|
||||
paths = {
|
||||
stateDir = "${config.xdg.stateHome}/theme";
|
||||
stateFile = "${config.xdg.stateHome}/theme/current";
|
||||
fzfDir = "${config.xdg.configHome}/fzf/themes";
|
||||
fzfCurrentFile = "${config.xdg.configHome}/fzf/themes/theme";
|
||||
ghosttyDir = "${config.xdg.configHome}/ghostty/themes";
|
||||
ghosttyCurrentFile = "${config.xdg.configHome}/ghostty/themes/cozybox-current";
|
||||
tmuxDir = "${config.xdg.configHome}/tmux/theme";
|
||||
tmuxCurrentFile = "${config.xdg.configHome}/tmux/theme/current.conf";
|
||||
};
|
||||
|
||||
themes = {
|
||||
dark = {
|
||||
background = "#181818";
|
||||
surface = "#1e1e1e";
|
||||
selectionBackground = "#504945";
|
||||
selectionForeground = "#ebdbb2";
|
||||
cursorColor = "#ddc7a1";
|
||||
cursorText = "#181818";
|
||||
foreground = "#ebdbb2";
|
||||
text = "#d4be98";
|
||||
mutedText = "#7c6f64";
|
||||
blue = sharedPalette.blue;
|
||||
green = sharedPalette.green;
|
||||
purple = sharedPalette.purple;
|
||||
border = "#181818";
|
||||
palette = [
|
||||
"#1d2021"
|
||||
sharedPalette.red
|
||||
sharedPalette.green
|
||||
sharedPalette.yellow
|
||||
sharedPalette.blue
|
||||
sharedPalette.purpleNeutral
|
||||
sharedPalette.aquaNeutral
|
||||
"#a89984"
|
||||
sharedPalette.gray
|
||||
sharedPalette.red
|
||||
sharedPalette.green
|
||||
sharedPalette.yellowBright
|
||||
sharedPalette.blue
|
||||
sharedPalette.purple
|
||||
sharedPalette.aqua
|
||||
"#ebdbb2"
|
||||
];
|
||||
};
|
||||
|
||||
light = {
|
||||
background = "#e7e7e7";
|
||||
surface = "#e1e1e1";
|
||||
selectionBackground = "#c3c7c9";
|
||||
selectionForeground = "#3c3836";
|
||||
cursorColor = "#282828";
|
||||
cursorText = "#e7e7e7";
|
||||
foreground = "#3c3836";
|
||||
text = "#3c3836";
|
||||
mutedText = "#665c54";
|
||||
blue = sharedPalette.blue;
|
||||
green = sharedPalette.green;
|
||||
purple = sharedPalette.purple;
|
||||
border = "#e7e7e7";
|
||||
palette = [
|
||||
"#f9f5d7"
|
||||
"#923f3a"
|
||||
sharedPalette.green
|
||||
sharedPalette.yellow
|
||||
"#4261a5"
|
||||
sharedPalette.purpleNeutral
|
||||
sharedPalette.aquaNeutral
|
||||
"#7c6f64"
|
||||
sharedPalette.gray
|
||||
"#923f3a"
|
||||
sharedPalette.green
|
||||
sharedPalette.yellowBright
|
||||
"#4261a5"
|
||||
sharedPalette.purple
|
||||
sharedPalette.aqua
|
||||
"#3c3836"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
renderGhostty = mode: let
|
||||
theme = themes.${mode};
|
||||
paletteLines =
|
||||
builtins.concatStringsSep "\n"
|
||||
(builtins.genList
|
||||
(index: "palette = ${toString index}=${builtins.elemAt theme.palette index}")
|
||||
(builtins.length theme.palette));
|
||||
in ''
|
||||
background = ${theme.background}
|
||||
foreground = ${theme.foreground}
|
||||
cursor-color = ${theme.cursorColor}
|
||||
cursor-text = ${theme.cursorText}
|
||||
selection-background = ${theme.selectionBackground}
|
||||
selection-foreground = ${theme.selectionForeground}
|
||||
${paletteLines}
|
||||
'';
|
||||
|
||||
renderTmux = mode: let
|
||||
theme = themes.${mode};
|
||||
in ''
|
||||
set-option -g @cozybox-mode '${mode}'
|
||||
set-option -g @cozybox-accent '${theme.purple}'
|
||||
set-option -g status-style bg=${theme.background},fg=${theme.text}
|
||||
set-option -g window-status-format " #I#[fg=${theme.purple}]:#[fg=default]#W "
|
||||
set-option -g window-status-current-format " #[fg=${theme.purple}]*#[fg=default]#I#[fg=${theme.purple}]:#[fg=default]#W "
|
||||
set-option -g window-status-separator ""
|
||||
set-option -g pane-border-style fg=${theme.border}
|
||||
set-option -g pane-active-border-style fg=${theme.border}
|
||||
'';
|
||||
|
||||
renderFzf = mode: let
|
||||
theme = themes.${mode};
|
||||
in ''
|
||||
--color=fg:${theme.text},bg:${theme.background},hl:${theme.blue}
|
||||
--color=fg+:${theme.text},bg+:${theme.surface},hl+:${theme.blue}
|
||||
--color=info:${theme.green},prompt:${theme.blue},pointer:${theme.text},marker:${theme.green},spinner:${theme.text}
|
||||
'';
|
||||
in {
|
||||
inherit defaultMode paths renderFzf renderGhostty renderTmux themes;
|
||||
}
|
||||
95
scripts/default.nix
Normal file
95
scripts/default.nix
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
}: let
|
||||
theme = import ../lib/theme.nix {inherit config;};
|
||||
|
||||
tmuxConfigs = {
|
||||
dark = pkgs.writeText "tmux-theme-dark.conf" (theme.renderTmux "dark");
|
||||
light = pkgs.writeText "tmux-theme-light.conf" (theme.renderTmux "light");
|
||||
};
|
||||
|
||||
mkScript = {
|
||||
file,
|
||||
name,
|
||||
runtimeInputs ? [],
|
||||
replacements ? {},
|
||||
}:
|
||||
pkgs.writeShellApplication {
|
||||
inherit name runtimeInputs;
|
||||
text =
|
||||
lib.replaceStrings
|
||||
(builtins.attrNames replacements)
|
||||
(builtins.attrValues replacements)
|
||||
(builtins.readFile file);
|
||||
};
|
||||
|
||||
packages = {
|
||||
ga = mkScript {
|
||||
name = "ga";
|
||||
file = ./ga.sh;
|
||||
runtimeInputs = with pkgs; [git];
|
||||
};
|
||||
|
||||
ghpr = mkScript {
|
||||
name = "ghpr";
|
||||
file = ./ghpr.sh;
|
||||
runtimeInputs = with pkgs; [gh git gnugrep gnused coreutils];
|
||||
};
|
||||
|
||||
gpr = mkScript {
|
||||
name = "gpr";
|
||||
file = ./gpr.sh;
|
||||
runtimeInputs = with pkgs; [gh fzf gnugrep coreutils];
|
||||
};
|
||||
|
||||
iosrun = mkScript {
|
||||
name = "iosrun";
|
||||
file = ./iosrun.sh;
|
||||
runtimeInputs = with pkgs; [findutils gnugrep coreutils];
|
||||
};
|
||||
|
||||
mdview = mkScript {
|
||||
name = "mdview";
|
||||
file = ./mdview.sh;
|
||||
};
|
||||
|
||||
ni = mkScript {
|
||||
name = "ni";
|
||||
file = ./ni.sh;
|
||||
runtimeInputs = with pkgs; [nix];
|
||||
};
|
||||
|
||||
theme = mkScript {
|
||||
name = "theme";
|
||||
file = ./theme.sh;
|
||||
runtimeInputs = with pkgs; [coreutils findutils neovim tmux];
|
||||
replacements = {
|
||||
"@DEFAULT_MODE@" = theme.defaultMode;
|
||||
"@STATE_DIR@" = theme.paths.stateDir;
|
||||
"@STATE_FILE@" = theme.paths.stateFile;
|
||||
"@FZF_DIR@" = theme.paths.fzfDir;
|
||||
"@FZF_CURRENT_FILE@" = theme.paths.fzfCurrentFile;
|
||||
"@FZF_DARK_FILE@" = "${theme.paths.fzfDir}/cozybox-dark";
|
||||
"@FZF_LIGHT_FILE@" = "${theme.paths.fzfDir}/cozybox-light";
|
||||
"@GHOSTTY_DIR@" = theme.paths.ghosttyDir;
|
||||
"@GHOSTTY_CURRENT_FILE@" = theme.paths.ghosttyCurrentFile;
|
||||
"@GHOSTTY_DARK_FILE@" = "${theme.paths.ghosttyDir}/cozybox-dark";
|
||||
"@GHOSTTY_LIGHT_FILE@" = "${theme.paths.ghosttyDir}/cozybox-light";
|
||||
"@TMUX_DIR@" = theme.paths.tmuxDir;
|
||||
"@TMUX_CURRENT_FILE@" = theme.paths.tmuxCurrentFile;
|
||||
"@TMUX_DARK_FILE@" = "${tmuxConfigs.dark}";
|
||||
"@TMUX_LIGHT_FILE@" = "${tmuxConfigs.light}";
|
||||
"@TMUX_CONFIG@" = "${config.xdg.configHome}/tmux/tmux.conf";
|
||||
};
|
||||
};
|
||||
|
||||
wtc = mkScript {
|
||||
name = "wtc";
|
||||
file = ./wtc.sh;
|
||||
};
|
||||
};
|
||||
in {
|
||||
inherit packages theme tmuxConfigs;
|
||||
}
|
||||
9
scripts/ga.sh
Normal file
9
scripts/ga.sh
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
if [[ $# -eq 0 ]]; then
|
||||
git add .
|
||||
else
|
||||
git add "$@"
|
||||
fi
|
||||
|
||||
if command -v critic >/dev/null 2>&1; then
|
||||
( critic review 2>/dev/null & )
|
||||
fi
|
||||
26
scripts/ghpr.sh
Normal file
26
scripts/ghpr.sh
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
base=$(git rev-parse --abbrev-ref HEAD)
|
||||
upstream="${1:-main}"
|
||||
remote_ref="origin/$upstream"
|
||||
unpushed=$(git log "$remote_ref"..HEAD --oneline 2>/dev/null)
|
||||
|
||||
if [[ -z "$unpushed" ]]; then
|
||||
if git diff --cached --quiet; then
|
||||
echo "No unpushed commits and no staged changes"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "No unpushed commits, but staged changes found. Opening commit dialog..."
|
||||
git commit
|
||||
fi
|
||||
|
||||
msg=$(git log "$remote_ref"..HEAD --format='%s' --reverse | head -1)
|
||||
branch=$(echo "$msg" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
|
||||
|
||||
git checkout -b "$branch"
|
||||
git checkout "$base"
|
||||
git reset --hard "$remote_ref"
|
||||
git checkout "$branch"
|
||||
|
||||
git push -u origin "$branch"
|
||||
gh pr create --base "$upstream" --fill --web 2>/dev/null || gh pr create --base "$upstream" --fill
|
||||
gh pr view "$branch" --json url -q '.url'
|
||||
39
scripts/gpr.sh
Normal file
39
scripts/gpr.sh
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
while true; do
|
||||
pr=$(
|
||||
gh pr list --limit 50 \
|
||||
--json number,title,author,headRefName \
|
||||
--template '{{range .}}#{{.number}} {{.title}} ({{.author.login}}) [{{.headRefName}}]{{"\n"}}{{end}}' \
|
||||
| fzf --preview 'gh pr view {1} --comments' \
|
||||
--preview-window=right:60%:wrap \
|
||||
--header 'enter: view | ctrl-m: merge | ctrl-x: close | ctrl-o: checkout | ctrl-b: browser' \
|
||||
--bind 'ctrl-o:execute(gh pr checkout {1})' \
|
||||
--bind 'ctrl-b:execute(gh pr view {1} --web)' \
|
||||
--expect=ctrl-m,ctrl-x,enter
|
||||
)
|
||||
|
||||
[[ -z "$pr" ]] && exit 0
|
||||
|
||||
key=$(echo "$pr" | head -1)
|
||||
selection=$(echo "$pr" | tail -1)
|
||||
num=$(echo "$selection" | grep -o '#[0-9]*' | tr -d '#')
|
||||
|
||||
[[ -z "$num" ]] && exit 0
|
||||
|
||||
case "$key" in
|
||||
ctrl-m)
|
||||
read -r -p "Merge PR #$num? [y/N] " response
|
||||
if [[ "$response" =~ ^[Yy]$ ]]; then
|
||||
gh pr merge "$num" --merge
|
||||
fi
|
||||
;;
|
||||
ctrl-x)
|
||||
read -r -p "Close PR #$num? [y/N] " response
|
||||
if [[ "$response" =~ ^[Yy]$ ]]; then
|
||||
gh pr close "$num"
|
||||
fi
|
||||
;;
|
||||
enter|"")
|
||||
gh pr view "$num"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
51
scripts/iosrun.sh
Normal file
51
scripts/iosrun.sh
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
project=$(find . -maxdepth 1 -name "*.xcodeproj" | head -1)
|
||||
scheme=$(basename "$project" .xcodeproj)
|
||||
derived=".derived-data"
|
||||
sim_name="${1:-iPhone 16e}"
|
||||
|
||||
if [[ -z "$project" ]]; then
|
||||
echo "No .xcodeproj found in current directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Building $scheme..."
|
||||
if ! xcodebuild -project "$project" -scheme "$scheme" \
|
||||
-destination "platform=iOS Simulator,name=$sim_name" \
|
||||
-derivedDataPath "$derived" build -quiet; then
|
||||
echo "Build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Build succeeded. Launching simulator..."
|
||||
|
||||
xcrun simctl boot "$sim_name" 2>/dev/null || true
|
||||
open -a Simulator
|
||||
|
||||
app_path="$derived/Build/Products/Debug-iphonesimulator/$scheme.app"
|
||||
bundle_id=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$app_path/Info.plist")
|
||||
|
||||
echo "Installing $scheme..."
|
||||
while ! xcrun simctl install "$sim_name" "$app_path" 2>/dev/null; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
echo "Launching $bundle_id..."
|
||||
while ! xcrun simctl launch "$sim_name" "$bundle_id" 2>&1 | grep -q "$bundle_id"; do
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
echo "Launched $bundle_id - streaming logs (Ctrl+C to stop)"
|
||||
echo "----------------------------------------"
|
||||
|
||||
xcrun simctl spawn "$sim_name" log stream \
|
||||
--predicate "(subsystem CONTAINS '$bundle_id' OR process == '$scheme') AND NOT subsystem BEGINSWITH 'com.apple'" \
|
||||
--style compact \
|
||||
--color always 2>/dev/null | while read -r line; do
|
||||
if [[ "$line" == *"error"* ]] || [[ "$line" == *"Error"* ]]; then
|
||||
printf '\033[31m%s\033[0m\n' "$line"
|
||||
elif [[ "$line" == *"warning"* ]] || [[ "$line" == *"Warning"* ]]; then
|
||||
printf '\033[33m%s\033[0m\n' "$line"
|
||||
else
|
||||
echo "$line"
|
||||
fi
|
||||
done
|
||||
1
scripts/mdview.sh
Normal file
1
scripts/mdview.sh
Normal file
|
|
@ -0,0 +1 @@
|
|||
exec markserv "$@"
|
||||
6
scripts/ni.sh
Normal file
6
scripts/ni.sh
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
if [[ $# -ne 1 ]]; then
|
||||
echo "usage: ni <package>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec nix profile add "nixpkgs#$1"
|
||||
103
scripts/theme.sh
Normal file
103
scripts/theme.sh
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
usage() {
|
||||
echo "usage: theme <dark|light|toggle|current>"
|
||||
}
|
||||
|
||||
read_mode() {
|
||||
if [[ -f "@STATE_FILE@" ]]; then
|
||||
mode=$(tr -d '[:space:]' < "@STATE_FILE@")
|
||||
if [[ "$mode" == "dark" || "$mode" == "light" ]]; then
|
||||
echo "$mode"
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "@DEFAULT_MODE@"
|
||||
}
|
||||
|
||||
link_mode_assets() {
|
||||
local mode="$1"
|
||||
local fzf_target
|
||||
local ghostty_target
|
||||
local tmux_target
|
||||
local apple_dark_mode
|
||||
|
||||
case "$mode" in
|
||||
dark)
|
||||
fzf_target="@FZF_DARK_FILE@"
|
||||
ghostty_target="@GHOSTTY_DARK_FILE@"
|
||||
tmux_target="@TMUX_DARK_FILE@"
|
||||
apple_dark_mode=true
|
||||
;;
|
||||
light)
|
||||
fzf_target="@FZF_LIGHT_FILE@"
|
||||
ghostty_target="@GHOSTTY_LIGHT_FILE@"
|
||||
tmux_target="@TMUX_LIGHT_FILE@"
|
||||
apple_dark_mode=false
|
||||
;;
|
||||
*)
|
||||
echo "invalid mode: $mode" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p "@STATE_DIR@" "@FZF_DIR@" "@GHOSTTY_DIR@" "@TMUX_DIR@"
|
||||
printf '%s\n' "$mode" > "@STATE_FILE@"
|
||||
ln -sfn "$fzf_target" "@FZF_CURRENT_FILE@"
|
||||
ln -sfn "$ghostty_target" "@GHOSTTY_CURRENT_FILE@"
|
||||
ln -sfn "$tmux_target" "@TMUX_CURRENT_FILE@"
|
||||
|
||||
if command -v tmux >/dev/null 2>&1 && tmux start-server >/dev/null 2>&1; then
|
||||
tmux source-file "@TMUX_CONFIG@" >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
if [[ "$(uname -s)" == "Darwin" ]] && command -v osascript >/dev/null 2>&1; then
|
||||
osascript -e "tell application \"System Events\" to tell appearance preferences to set dark mode to ${apple_dark_mode}" >/dev/null 2>&1 || true
|
||||
|
||||
osascript <<'EOF' >/dev/null 2>&1 || true
|
||||
tell application "System Events"
|
||||
if not (exists process "Ghostty") then
|
||||
return
|
||||
end if
|
||||
|
||||
tell process "Ghostty"
|
||||
click menu item "Reload Configuration" of menu 1 of menu bar item "Ghostty" of menu bar 1
|
||||
end tell
|
||||
end tell
|
||||
EOF
|
||||
fi
|
||||
|
||||
while IFS= read -r socket; do
|
||||
[[ -S "$socket" ]] || continue
|
||||
nvim --server "$socket" --remote-expr "execute('ThemeSync $mode')" >/dev/null 2>&1 || true
|
||||
done < <(
|
||||
{
|
||||
find /tmp -maxdepth 1 -type s -name 'nvim-*.sock' 2>/dev/null
|
||||
find "${TMPDIR:-/tmp}" -type s -path "*/nvim.${USER}/*/nvim.*" 2>/dev/null
|
||||
} | sort -u
|
||||
)
|
||||
}
|
||||
|
||||
mode="${1:-current}"
|
||||
|
||||
case "$mode" in
|
||||
dark|light)
|
||||
;;
|
||||
toggle)
|
||||
if [[ "$(read_mode)" == "dark" ]]; then
|
||||
mode="light"
|
||||
else
|
||||
mode="dark"
|
||||
fi
|
||||
;;
|
||||
current)
|
||||
read_mode
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
link_mode_assets "$mode"
|
||||
printf 'applied %s theme\n' "$mode"
|
||||
1
scripts/wtc.sh
Normal file
1
scripts/wtc.sh
Normal file
|
|
@ -0,0 +1 @@
|
|||
exec wt switch --create --base @ "$@"
|
||||
Loading…
Add table
Add a link
Reference in a new issue