diff --git a/.aerospace.toml b/.aerospace.toml new file mode 100644 index 0000000..ab2a132 --- /dev/null +++ b/.aerospace.toml @@ -0,0 +1,164 @@ + +# After that, you can edit ~/.aerospace.toml to your liking + +# Feel free to omit keys that you don't use in your config. +# If the key is absent in your config the default value is taken from this config + +# You can use it to add commands that run after login to macOS user session. +# 'start-at-login' needs to be 'true' for 'after-login-command' to work +# Available commands: https://nikitabobko.github.io/AeroSpace/commands +after-login-command = [] + +# You can use it to add commands that run after AeroSpace startup. +# 'after-startup-command' is run after 'after-login-command' +# Available commands : https://nikitabobko.github.io/AeroSpace/commands +after-startup-command = [ + 'exec-and-forget /bin/bash -c "sleep 3 && /Users/robray/.config/sketchybar/plugins/aerospace_update_all.sh"' +] + +exec-on-workspace-change = ['/bin/bash', '-c', + '/Users/robray/.config/sketchybar/plugins/aerospace_update_all.sh $AEROSPACE_FOCUSED_WORKSPACE' +] + +# Start AeroSpace at login +start-at-login = true + +# Normalizations. See: https://nikitabobko.github.io/AeroSpace/guide#normalization +enable-normalization-flatten-containers = true +enable-normalization-opposite-orientation-for-nested-containers = true + +# See: https://nikitabobko.github.io/AeroSpace/guide#layouts +# The 'accordion-padding' specifies the size of accordion padding +# You can set 0 to disable the padding feature +accordion-padding = 30 + +# Possible values: tiles|accordion +default-root-container-layout = 'tiles' + +# Possible values: horizontal|vertical|auto +# 'auto' means: wide monitor (anything wider than high) gets horizontal orientation, +# tall monitor (anything higher than wide) gets vertical orientation +default-root-container-orientation = 'auto' + +# Possible values: (qwerty|dvorak) +# See https://nikitabobko.github.io/AeroSpace/guide#key-mapping +key-mapping.preset = 'qwerty' + +# Gaps between windows (inner-*) and between monitor edges (outer-*). +# Possible values: +# - Constant: gaps.outer.top = 8 +# - Per monitor: gaps.outer.top = [{ monitor.main = 16 }, { monitor."some-pattern" = 32 }, 24] +# In this example, 24 is a default value when there is no match. +# Monitor pattern is the same as for 'workspace-to-monitor-force-assignment'. +# See: https://nikitabobko.github.io/AeroSpace/guide#assign-workspaces-to-monitors +# [gaps] +# inner.horizontal = 10 +# inner.vertical = 10 +# outer.left = 10 +# outer.bottom = 10 +# outer.top = 10 +# outer.right = 10 +[gaps] +inner.horizontal = 20 +inner.vertical = 20 +outer.left = 20 +outer.bottom = 20 +outer.top = 40 +outer.right = 20 + +[workspace-to-monitor-force-assignment] +7 = 'secondary' + +# See https://nikitabobko.github.io/AeroSpace/guide#exec-env-vars +[exec] +inherit-env-vars = true +[exec.env-vars] +PATH = '/opt/homebrew/bin:/opt/homebrew/sbin:${PATH}' + +# 'main' binding mode declaration +# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes +# 'main' binding mode must be always presented +[mode.main.binding] + +# All possible keys: +# - Letters. a, b, c, ..., z +# - Numbers. 0, 1, 2, ..., 9 +# - Keypad numbers. keypad0, keypad1, keypad2, ..., keypad9 +# - F-keys. f1, f2, ..., f20 +# - Special keys. minus, equal, period, comma, slash, backslash, quote, semicolon, backtick, +# leftSquareBracket, rightSquareBracket, space, enter, esc, backspace, tab +# - Keypad special. keypadClear, keypadDecimalMark, keypadDivide, keypadEnter, keypadEqual, +# keypadMinus, keypadMultiply, keypadPlus +# - Arrows. left, down, up, right + +# All possible modifiers: cmd, alt, ctrl, shift + +# All possible commands: https://nikitabobko.github.io/AeroSpace/commands + +# You can uncomment this line to open up terminal with alt + enter shortcut +# See: https://nikitabobko.github.io/AeroSpace/commands#exec-and-forget +# alt-enter = 'exec-and-forget open -n /System/Applications/Utilities/Terminal.app' + +# See: https://nikitabobko.github.io/AeroSpace/commands#layout +alt-slash = 'layout tiles horizontal vertical' +alt-comma = 'layout accordion horizontal vertical' + +# See: https://nikitabobko.github.io/AeroSpace/commands#focus +alt-left = 'focus left' +alt-down = 'focus down' +alt-up = 'focus up' +alt-right = 'focus right' + +# See: https://nikitabobko.github.io/AeroSpace/commands#move +alt-shift-left = 'move left' +alt-shift-down = 'move down' +alt-shift-up = 'move up' +alt-shift-right = 'move right' + +# See: https://nikitabobko.github.io/AeroSpace/commands#resize +alt-shift-minus = 'resize smart -50' +alt-shift-equal = 'resize smart +50' + +# See: https://nikitabobko.github.io/AeroSpace/commands#workspace +alt-ctrl-1 = 'workspace 1' +alt-ctrl-2 = 'workspace 2' +alt-ctrl-3 = 'workspace 3' +alt-ctrl-4 = 'workspace 4' +alt-ctrl-5 = 'workspace 5' +alt-ctrl-6 = 'workspace 6' +alt-ctrl-7 = 'workspace 7' +alt-shift-1 = 'move-node-to-workspace 1' +alt-shift-2 = 'move-node-to-workspace 2' +alt-shift-3 = 'move-node-to-workspace 3' +alt-shift-4 = 'move-node-to-workspace 4' +alt-shift-5 = 'move-node-to-workspace 5' +alt-shift-6 = 'move-node-to-workspace 6' +alt-shift-7 = 'move-node-to-workspace 7' +# See: https://nikitabobko.github.io/AeroSpace/commands#workspace-back-and-forth +alt-tab = 'workspace-back-and-forth' +# See: https://nikitabobko.github.io/AeroSpace/commands#move-workspace-to-monitor +alt-shift-tab = 'move-workspace-to-monitor --wrap-around next' + +# See: https://nikitabobko.github.io/AeroSpace/commands#mode +alt-shift-semicolon = 'mode service' + +# 'service' binding mode declaration. +# See: https://nikitabobko.github.io/AeroSpace/guide#binding-modes +[mode.service.binding] +shift-esc = ['reload-config', 'mode main'] +# shift-ctrl-r = ['flatten-workspace-tree', 'mode main'] # reset layout +#s = ['layout sticky tiling', 'mode main'] # sticky is not yet supported https://github.com/nikitabobko/AeroSpace/issues/2 +# shift-ctrl-f = ['layout floating tiling', 'mode main'] # Toggle between floating and tiling layout +# shift-backspace = ['close-all-windows-but-current', 'mode main'] + +alt-shift-h = ['join-with left', 'mode main'] +alt-shift-j = ['join-with down', 'mode main'] +alt-shift-k = ['join-with up', 'mode main'] +alt-shift-l = ['join-with right', 'mode main'] + +[[on-window-detected]] +if.app-id="com.mitchellh.ghostty" +run= [ + "layout floating", +] + diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..db7963b --- /dev/null +++ b/.gitconfig @@ -0,0 +1,2 @@ +[core] + editor = hx diff --git a/.gitignore b/.gitignore index a85146b..8a0bc92 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .secrets.fish .DS_Store +.backup/ # Claude directory ignores .claude/ diff --git a/.wezterm.lua b/.wezterm.lua new file mode 100644 index 0000000..15bb676 --- /dev/null +++ b/.wezterm.lua @@ -0,0 +1,88 @@ +local wezterm = require 'wezterm' +local config = wezterm.config_builder() + +-- General +config.default_prog = { '/run/current-system/sw/bin/fish', '-l' } +config.font_size = 19 +config.line_height = 1.1 +config.font = wezterm.font "BlexMono Nerd Font Mono" +config.color_scheme = 'tokyonight_night' +config.window_close_confirmation = 'NeverPrompt' -- For quitting WezTerm + +-- Performance Hack +config.max_fps = 120 +config.animation_fps = 120 + +-- Cursor +config.colors = { + cursor_bg = '#7aa2f7', + cursor_border = '#7aa2f7', +} + +config.inactive_pane_hsb = { + saturation = 0.5, + brightness = 0.3, +} + +-- Appearance +config.window_decorations = "RESIZE" +config.enable_tab_bar = false +-- config.tab_bar_at_bottom = true +config.window_padding = { + bottom = 0 +} + +-- Key bindings +config.keys = { + { + key = 'w', + mods = 'CMD', + action = wezterm.action.CloseCurrentPane { confirm = false }, + }, + { + key = 'd', + mods = 'CMD', + action = wezterm.action.SplitHorizontal { domain = 'CurrentPaneDomain' }, + }, + { + key = 'd', + mods = 'CMD|SHIFT', + action = wezterm.action.SplitVertical { domain = 'CurrentPaneDomain' }, + }, + { + key = 'k', + mods = 'CMD', + action = wezterm.action.SendString 'clear\n' + }, + { + key = '+', + mods = 'CTRL', + action = wezterm.action.Multiple { + wezterm.action.IncreaseFontSize, + wezterm.action.EmitEvent('show-zoom'), + }, + }, + { + key = '-', + mods = 'CTRL', + action = wezterm.action.Multiple { + wezterm.action.DecreaseFontSize, + wezterm.action.EmitEvent('show-zoom'), + }, + }, + { + key = '0', + mods = 'CTRL', + action = wezterm.action.Multiple { + wezterm.action.ResetFontSize, + wezterm.action.EmitEvent('show-zoom'), + }, + }, +} + + +-- Ensure Option key sends composed characters (e.g., #) +config.send_composed_key_when_left_alt_is_pressed = true + +return config + diff --git a/.zshrc b/.zshrc new file mode 100644 index 0000000..0b5744a --- /dev/null +++ b/.zshrc @@ -0,0 +1,3 @@ + +# bun completions +[ -s "/Users/robray/.bun/_bun" ] && source "/Users/robray/.bun/_bun" diff --git a/config/fish/conf.d/fish_frozen_key_bindings.fish b/config/fish/conf.d/fish_frozen_key_bindings.fish new file mode 100644 index 0000000..dfed4d6 --- /dev/null +++ b/config/fish/conf.d/fish_frozen_key_bindings.fish @@ -0,0 +1,14 @@ +# This file was created by fish when upgrading to version 4.3, to migrate +# the 'fish_key_bindings' variable from its old default scope (universal) +# to its new default scope (global). We recommend you delete this file +# and configure key bindings in ~/.config/fish/config.fish if needed. + +set --global fish_key_bindings fish_vi_key_bindings + +# Prior to version 4.3, fish shipped an event handler that runs +# `set --universal fish_key_bindings fish_default_key_bindings` +# whenever the fish_key_bindings variable is erased. +# This means that as long as any fish < 4.3 is still running on this system, +# we cannot complete the migration. +# As a workaround, erase the universal variable at every shell startup. +set --erase --universal fish_key_bindings diff --git a/config/fish/conf.d/fish_frozen_theme.fish b/config/fish/conf.d/fish_frozen_theme.fish new file mode 100644 index 0000000..5c7cef9 --- /dev/null +++ b/config/fish/conf.d/fish_frozen_theme.fish @@ -0,0 +1,37 @@ +# This file was created by fish when upgrading to version 4.3, to migrate +# theme variables from universal to global scope. +# Don't edit this file, as it will be written by the web-config tool (`fish_config`). +# To customize your theme, delete this file and see +# help interactive#syntax-highlighting +# or +# man fish-interactive | less +/^SYNTAX.HIGHLIGHTING +# for appropriate commands to add to ~/.config/fish/config.fish instead. +# See also the release notes for fish 4.3.0 (run `help relnotes`). + +set --global fish_color_autosuggestion brblack +set --global fish_color_cancel -r +set --global fish_color_command normal +set --global fish_color_comment red +set --global fish_color_cwd green +set --global fish_color_cwd_root red +set --global fish_color_end green +set --global fish_color_error brred +set --global fish_color_escape brcyan +set --global fish_color_history_current --bold +set --global fish_color_host normal +set --global fish_color_host_remote yellow +set --global fish_color_normal normal +set --global fish_color_operator brcyan +set --global fish_color_param cyan +set --global fish_color_quote yellow +set --global fish_color_redirection cyan --bold +set --global fish_color_search_match white --background=brblack +set --global fish_color_selection white --bold --background=brblack +set --global fish_color_status red +set --global fish_color_user brgreen +set --global fish_color_valid_path --underline +set --global fish_pager_color_completion normal +set --global fish_pager_color_description yellow -i +set --global fish_pager_color_prefix normal --bold --underline +set --global fish_pager_color_progress brwhite --background=cyan +set --global fish_pager_color_selected_background -r diff --git a/config/fish/config.fish b/config/fish/config.fish index a749ee2..51093e0 100644 --- a/config/fish/config.fish +++ b/config/fish/config.fish @@ -19,9 +19,7 @@ eval "$(/opt/homebrew/bin/brew shellenv)" zoxide init fish | source mise activate fish | source -# Add Bun global bin directory to PATH for Gemini CLI -fish_add_path "/Users/richardoliverbray/.bun/bin" - +fish_add_path ~/.opencode/bin # Add WezTerm to PATH fish_add_path -a "/Applications/WezTerm.app/Contents/MacOS" @@ -81,3 +79,5 @@ set -gx PATH /run/current-system/sw/bin $PATH set -gx NIX_PATH darwin=$HOME/.nix-defexpr/channels/nixpkgs-darwin:darwin-config=$HOME/.nixpkgs/darwin-configuration.nix $NIX_PATH set -gx NIX_PATH darwin=$HOME/.config/nix:$NIX_PATH set -x EZA_CONFIG_DIR /Users/richardoliverbray/.config/eza +functions -e spf +set -gx PATH $HOME/.local/bin $PATH diff --git a/config/fish/fish_variables b/config/fish/fish_variables index 47f1d66..ac789b7 100644 --- a/config/fish/fish_variables +++ b/config/fish/fish_variables @@ -1,33 +1,5 @@ # This file contains fish universal variable definitions. # VERSION: 3.0 -SETUVAR __fish_initialized:3800 +SETUVAR __fish_initialized:4300 SETUVAR _fisher_upgraded_to_4_4:\x1d -SETUVAR fish_color_autosuggestion:brblack -SETUVAR fish_color_cancel:\x2dr -SETUVAR fish_color_command:normal -SETUVAR fish_color_comment:red -SETUVAR fish_color_cwd:green -SETUVAR fish_color_cwd_root:red -SETUVAR fish_color_end:green -SETUVAR fish_color_error:brred -SETUVAR fish_color_escape:brcyan -SETUVAR fish_color_history_current:\x2d\x2dbold -SETUVAR fish_color_host:normal -SETUVAR fish_color_host_remote:yellow -SETUVAR fish_color_normal:normal -SETUVAR fish_color_operator:brcyan -SETUVAR fish_color_param:cyan -SETUVAR fish_color_quote:yellow -SETUVAR fish_color_redirection:cyan\x1e\x2d\x2dbold -SETUVAR fish_color_search_match:white\x1e\x2d\x2dbackground\x3dbrblack -SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack -SETUVAR fish_color_status:red -SETUVAR fish_color_user:brgreen -SETUVAR fish_color_valid_path:\x2d\x2dunderline -SETUVAR fish_key_bindings:fish_vi_key_bindings -SETUVAR fish_pager_color_completion:normal -SETUVAR fish_pager_color_description:yellow\x1e\x2di -SETUVAR fish_pager_color_prefix:normal\x1e\x2d\x2dbold\x1e\x2d\x2dunderline -SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan -SETUVAR fish_pager_color_selected_background:\x2dr -SETUVAR fish_user_paths:/run/current\x2dsystem/sw/bin\x1e/Users/richardoliverbray/\x2ebun/bin\x1e/Applications/WezTerm\x2eapp/Contents/MacOS +SETUVAR fish_user_paths:/Users/robray/\x2eopencode/bin\x1e/run/current\x2dsystem/sw/bin\x1e/Users/richardoliverbray/\x2ebun/bin\x1e/Applications/WezTerm\x2eapp/Contents/MacOS diff --git a/config/fish/functions/clean_dl.fish b/config/fish/functions/clean_dl.fish new file mode 100644 index 0000000..3428f36 --- /dev/null +++ b/config/fish/functions/clean_dl.fish @@ -0,0 +1,26 @@ +# clean-dl # Clean files older than 30 days +# clean-dl --days 7 # Clean files older than 7 days +# clean-dl --days 90 # Clean files older than 90 days + +function clean_dl + set downloads_dir "$HOME/Downloads" + set days 30 + + # Parse arguments + argparse 'd/days=' -- $argv + + if set -q _flag_days + set days $_flag_days + end + + # Clean files and folders older than N days (top-level only to avoid app bundle issues) + set -l files (find "$downloads_dir" -mindepth 1 -maxdepth 1 -not -path "$downloads_dir/keep" -mtime "+$days") + set -l count (count $files) + + if test $count -gt 0 + trash $files + echo "Cleaned Downloads folder - moved $count file(s) older than $days days to Trash" + else + echo "No files older than $days days found in Downloads folder" + end +end diff --git a/config/fish/functions/copyf.fish b/config/fish/functions/copyf.fish new file mode 100644 index 0000000..4c617a8 --- /dev/null +++ b/config/fish/functions/copyf.fish @@ -0,0 +1,14 @@ +function copyf + if test (count $argv) -eq 0 + echo "Usage: copyf " + return 1 + end + + if not test -f $argv[1] + echo "Error: '$argv[1]' is not a valid file" + return 1 + end + + pbcopy < $argv[1] + echo "File contents copied to clipboard: $argv[1]" +end diff --git a/config/fish/functions/keys.fish b/config/fish/functions/keys.fish index b8cacfd..147b21b 100644 --- a/config/fish/functions/keys.fish +++ b/config/fish/functions/keys.fish @@ -2,6 +2,35 @@ function keys -d "Auto-detect and monitor keyboard changes" set config_dir /Users/robray/dotfiles/config/kanata set current_config "" + function __keys_stop_kanata + # Kill any existing kanata (including ones started via sudo) + sudo -n /usr/bin/killall kanata 2>/dev/null + /usr/bin/killall kanata 2>/dev/null + sleep 1 + end + + function __keys_stop_karabiner_grabbers + # Keep Karabiner's VirtualHIDDevice daemon; stop only the parts that can + # seize/grab physical keyboards and block IOHIDDeviceOpen. + set -l labels \ + org.pqrs.service.agent.Karabiner-Core-Service \ + org.pqrs.service.agent.Karabiner-Menu \ + org.pqrs.service.agent.Karabiner-NotificationWindow \ + org.pqrs.service.agent.karabiner_console_user_server \ + org.pqrs.service.agent.karabiner_session_monitor + + for lbl in $labels + launchctl stop $lbl 2>/dev/null + end + + pkill -f '[K]arabiner-Core-Service' 2>/dev/null + pkill -f '[K]arabiner-Menu' 2>/dev/null + pkill -f '[K]arabiner-NotificationWindow' 2>/dev/null + pkill -f '[k]arabiner_console_user_server' 2>/dev/null + pkill -f '[k]arabiner_session_monitor' 2>/dev/null + sleep 1 + end + echo "Starting kanata with keyboard monitoring (Ctrl+C to stop)" while true @@ -13,9 +42,8 @@ function keys -d "Auto-detect and monitor keyboard changes" # Restart kanata if config changed if test "$new_config" != "$current_config" - # Kill existing kanata process - pkill -f "kanata.*port 7070" 2>/dev/null - sleep 1 + __keys_stop_kanata + __keys_stop_karabiner_grabbers set current_config $new_config set config_path "$config_dir/$current_config.kbd" @@ -26,7 +54,6 @@ function keys -d "Auto-detect and monitor keyboard changes" else echo (date "+%H:%M:%S") "🖥️ No Durgod keyboard found! Switching to default config 📝" end - sudo -v 2>/dev/null || true sudo kanata --cfg "$config_path" --port 7070 & sleep 3 sketchybar --reload diff --git a/config/fish/functions/pastef.fish b/config/fish/functions/pastef.fish new file mode 100644 index 0000000..cf4ef89 --- /dev/null +++ b/config/fish/functions/pastef.fish @@ -0,0 +1,9 @@ +function pastef + if test (count $argv) -eq 0 + echo "Usage: pastef " + return 1 + end + + pbpaste > $argv[1] + echo "Clipboard contents pasted to: $argv[1]" +end diff --git a/config/fish/functions/speed_video.fish b/config/fish/functions/speed_video.fish index 6d0a8f9..8ef0726 100644 --- a/config/fish/functions/speed_video.fish +++ b/config/fish/functions/speed_video.fish @@ -4,40 +4,40 @@ function speed_video --description "Speed up video and process with whisper" if test "$arg" = "--help" -o "$arg" = "-h" echo "speed_video - Speed up video with quality control" echo "" - echo "Usage: speed_video [--speed SPEED] [--near-lossless] [--help]" + echo "Usage: speed_video [--speed SPEED] [--lossless] [--help]" echo "" echo "Arguments:" echo " input_filename Video file in ~/Downloads (without path or extension)" echo "" echo "Options:" echo " --speed SPEED Playback speed multiplier (default: 1.2, meaning 20% faster)" - echo " --near-lossless Use CRF 18 + 320k audio (smaller files, excellent quality)" + echo " --lossless Use CRF 0 + uncompressed PCM audio (largest files, perfect quality)" echo " --help, -h Show this help message" echo "" echo "Examples:" - echo " speed_video myvideo # Lossless, 1.2x speed" - echo " speed_video myvideo --speed 1.5 # Lossless, 1.5x speed" - echo " speed_video myvideo --speed 1.2 --near-lossless # Near-lossless, 1.2x speed" + echo " speed_video myvideo # Near-lossless, 1.2x speed" + echo " speed_video myvideo --speed 1.5 # Near-lossless, 1.5x speed" + echo " speed_video myvideo --speed 1.2 --lossless # Lossless, 1.2x speed" echo "" echo "Quality Settings:" - echo " Lossless (default): crf 0 + uncompressed PCM audio (largest files)" - echo " Near-lossless: crf 18 + 320k bitrate audio (smaller files)" + echo " Near-lossless (default): crf 18 + 320k bitrate audio (smaller files)" + echo " Lossless: crf 0 + uncompressed PCM audio (largest files)" return 0 end end # Check if argument is provided if test (count $argv) -lt 1 - echo "Usage: speed_video [--speed SPEED] [--near-lossless] [--help]" + echo "Usage: speed_video [--speed SPEED] [--lossless] [--help]" echo "Use --help for detailed information" return 1 end set input_name $argv[1] set speed 1.2 - # Default to lossless: CRF 0 means mathematically lossless, PCM audio is uncompressed - set video_args -crf 0 - set audio_args -c:a pcm_s16le + # Default to near-lossless: CRF 18 is visually lossless, 320k audio is high quality + set video_args -crf 18 -preset medium + set audio_args -b:a 320k # Parse flags: check for --speed and --near-lossless set i 1 @@ -49,10 +49,10 @@ function speed_video --description "Speed up video and process with whisper" if test $i -le (count $argv) set speed $argv[$i] end - else if test "$arg" = "--near-lossless" - # Check for near-lossless flag: CRF 18 is visually lossless, 320k audio is high quality - set video_args -crf 18 -preset medium - set audio_args -b:a 320k + else if test "$arg" = "--lossless" + # Check for lossless flag: CRF 0 means mathematically lossless, PCM audio is uncompressed + set video_args -crf 0 + set audio_args -c:a pcm_s16le end set i (math $i + 1) diff --git a/config/fish/functions/toggle_aerospace_padding.fish b/config/fish/functions/toggle_aerospace_padding.fish index 8953251..5338e54 100644 --- a/config/fish/functions/toggle_aerospace_padding.fish +++ b/config/fish/functions/toggle_aerospace_padding.fish @@ -1,12 +1,12 @@ function toggle_aerospace_padding --description "Toggle AeroSpace outer.top padding between 20 and 40" - set config_file ~/dotfiles/aerospace.toml - + set config_file ~/.aerospace.toml + # Get current padding value more precisely set current_padding (grep "^outer\.top" $config_file | grep -o "[0-9]\+") - + echo "Current outer.top padding: $current_padding" - - if test "$current_padding" = "20" + + if test "$current_padding" = 20 # Change to 40 sed -i '' 's/^outer\.top.*$/outer.top = 40/' $config_file echo "Switched outer.top padding to 40" @@ -15,7 +15,7 @@ function toggle_aerospace_padding --description "Toggle AeroSpace outer.top padd sed -i '' 's/^outer\.top.*$/outer.top = 20/' $config_file echo "Switched outer.top padding to 20" end - + # Reload AeroSpace config to apply changes aerospace reload-config echo "AeroSpace config reloaded" diff --git a/config/helix/config.toml b/config/helix/config.toml index 6539f51..e25790d 100644 --- a/config/helix/config.toml +++ b/config/helix/config.toml @@ -19,3 +19,4 @@ enable = true [keys.normal] esc = ["collapse_selection", "keep_primary_selection"] + diff --git a/config/helix/languages.toml b/config/helix/languages.toml new file mode 100644 index 0000000..c2c5a84 --- /dev/null +++ b/config/helix/languages.toml @@ -0,0 +1,26 @@ +[[language]] +name = "markdown" +language-servers = ["typos-lsp"] + +[language-server.typos-lsp] +command = "/opt/homebrew/bin/typos-lsp" + +[[language]] +name = "typescript" +language-servers = ["typescript-language-server"] + +[[language]] +name = "tsx" +language-servers = ["typescript-language-server"] + +[[language]] +name = "javascript" +language-servers = ["typescript-language-server"] + +[[language]] +name = "jsx" +language-servers = ["typescript-language-server"] + +[language-server.typescript-language-server] +command = "node" +args = ["/Users/robray/.local/share/mise/installs/npm-typescript-language-server/5.1.3/lib/node_modules/typescript-language-server/lib/cli.mjs", "--stdio"] diff --git a/config/mise/config.toml b/config/mise/config.toml index 4e59422..20f97c6 100644 --- a/config/mise/config.toml +++ b/config/mise/config.toml @@ -3,14 +3,18 @@ idiomatic_version_file_enable_tools = ["python"] experimental = true [tools] -claude-code = "latest" +bun = "latest" doctl = "latest" +go = "latest" "go:github.com/schollz/croc/v10" = "latest" hcloud = "latest" -helm = "latest" -k9s = "latest" -kubectx = "latest" +node = "latest" "npm:@beads/bd" = "latest" -"npm:@google/gemini-cli" = "latest" -ruby = "latest" +"npm:agent-browser" = "latest" +"npm:okiro" = "latest" +"npm:prettier" = "latest" +"npm:typescript" = "latest" +"npm:typescript-language-server" = "latest" +uv = "latest" +wrangler = "latest" diff --git a/config/nvim/init.lua b/config/nvim/init.lua index ed4142c..beaa39d 100644 --- a/config/nvim/init.lua +++ b/config/nvim/init.lua @@ -4,10 +4,10 @@ vim.g.mapleader = " " -- bootstrap lazy and all plugins local lazypath = vim.fn.stdpath "data" .. "/lazy/lazy.nvim" --- if not vim.uv.fs_stat(lazypath) then --- local repo = "https://github.com/folke/lazy.nvim.git" --- vim.fn.system { "git", "clone", "--filter=blob:none", repo, "--branch=stable", lazypath } --- end +if not vim.uv.fs_stat(lazypath) then + local repo = "https://github.com/folke/lazy.nvim.git" + vim.fn.system { "git", "clone", "--filter=blob:none", repo, "--branch=stable", lazypath } +end vim.opt.rtp:prepend(lazypath) vim.wo.relativenumber = true diff --git a/config/nvim/lazy-lock.json b/config/nvim/lazy-lock.json index 8d225c3..df8b445 100644 --- a/config/nvim/lazy-lock.json +++ b/config/nvim/lazy-lock.json @@ -1,43 +1,38 @@ { "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, - "LuaSnip": { "branch": "master", "commit": "eda5be8f0ce9816278671f0b578cdbb8b762c701" }, - "NvChad": { "branch": "v2.5", "commit": "f95da3325c2b0dca9468f52440225e351b074a3a" }, - "avante.nvim": { "branch": "main", "commit": "5b2a0e6118902c9a4494b9a13e73f412d3e75dff" }, - "base46": { "branch": "v2.5", "commit": "fde7a2cd54599e148d376f82980407c2d24b0fa2" }, - "cmp-async-path": { "branch": "main", "commit": "0ed1492f59e730c366d261a5ad822fa37e44c325" }, + "LuaSnip": { "branch": "master", "commit": "dae4f5aaa3574bd0c2b9dd20fb9542a02c10471c" }, + "NvChad": { "branch": "v2.5", "commit": "c57b82473b821274f6017eb03582ba1d13be9d8c" }, + "base46": { "branch": "v3.0", "commit": "884b990dcdbe07520a0892da6ba3e8d202b46337" }, + "cmp-async-path": { "branch": "main", "commit": "9c2374deb32c2bec8b27e928c6f57090e9a875d2" }, "cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" }, - "cmp-nvim-lsp": { "branch": "main", "commit": "a8912b88ce488f411177fc8aed358b04dc246d7b" }, - "cmp-nvim-lua": { "branch": "main", "commit": "f12408bdb54c39c23e67cab726264c10db33ada8" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" }, + "cmp-nvim-lua": { "branch": "main", "commit": "e3a22cb071eb9d6508a156306b102c45cd2d573d" }, "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, - "conform.nvim": { "branch": "master", "commit": "8132ec733eed3bf415b97b76797ca41b59f51d7d" }, - "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, - "gitsigns.nvim": { "branch": "main", "commit": "1b0350ab707713b2bc6c236151f1a324175347b1" }, + "conform.nvim": { "branch": "master", "commit": "c2526f1cde528a66e086ab1668e996d162c75f4f" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "gitsigns.nvim": { "branch": "main", "commit": "abf82a65f185bd54adc0679f74b7d6e1ada690c9" }, "indent-blankline.nvim": { "branch": "master", "commit": "005b56001b2cb30bfa61b7986bc50657816ba4ba" }, - "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "c4c84f4521d62de595c0d0f718a9a40c1890c8ce" }, - "mason.nvim": { "branch": "main", "commit": "8024d64e1330b86044fed4c8494ef3dcd483a67c" }, - "mcphub.nvim": { "branch": "main", "commit": "424e8c988e2e958da6f2182e40d52ee54bb18b8c" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "fb179adb7161b53ec998b1139002473434586c3f" }, + "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, + "mcphub.nvim": { "branch": "main", "commit": "7cd5db330f41b7bae02b2d6202218a061c3ebc1f" }, "menu": { "branch": "main", "commit": "7a0a4a2896b715c066cfbe320bdc048091874cc6" }, "minty": { "branch": "main", "commit": "aafc9e8e0afe6bf57580858a2849578d8d8db9e0" }, - "neoscroll.nvim": { "branch": "master", "commit": "f957373912e88579e26fdaea4735450ff2ef5c9c" }, - "noice.nvim": { "branch": "main", "commit": "0427460c2d7f673ad60eb02b35f5e9926cf67c59" }, - "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, - "nvim-autopairs": { "branch": "master", "commit": "2647cce4cb64fb35c212146663384e05ae126bdf" }, - "nvim-cmp": { "branch": "main", "commit": "b5311ab3ed9c846b585c0c15b7559be131ec4be9" }, + "nvim-autopairs": { "branch": "master", "commit": "c2a0dd0d931d0fb07665e1fedb1ea688da3b80b4" }, + "nvim-cmp": { "branch": "main", "commit": "da88697d7f45d16852c6b2769dc52387d1ddc45f" }, "nvim-fFHighlight": { "branch": "main", "commit": "791a07a59751bda3809d458761ff9eccd54fb542" }, - "nvim-lspconfig": { "branch": "master", "commit": "6bba673aa8993eceec233be17b42ddfb9540794b" }, - "nvim-notify": { "branch": "master", "commit": "a22f5d7ac511c2df2fd3290a9f04c48d5a822e2e" }, - "nvim-redraft": { "branch": "main", "commit": "04386ae795df8c79f64fbc9ac7a1d5665003a7b9" }, - "nvim-tree.lua": { "branch": "master", "commit": "b0b49552c9462900a882fe772993b01d780445fe" }, - "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, - "nvim-web-devicons": { "branch": "master", "commit": "19d6211c78169e78bab372b585b6fb17ad974e82" }, - "opencode.nvim": { "branch": "main", "commit": "abde303aa43517d32a84dbeeb14037ef146a106a" }, - "plenary.nvim": { "branch": "master", "commit": "857c5ac632080dba10aae49dba902ce3abf91b35" }, - "snacks.nvim": { "branch": "main", "commit": "dae80fb393f712bd7352a20f9185f5e16b69f20f" }, + "nvim-lspconfig": { "branch": "master", "commit": "54baa4beeeabed24be24379d5b3ce402fe7b5208" }, + "nvim-redraft": { "branch": "main", "commit": "d77ef5164cc60daed72744e824a0ece1e97527c3" }, + "nvim-tree.lua": { "branch": "master", "commit": "c07ce43527e5f0242121f4eb1feb7ac0ecea8275" }, + "nvim-treesitter": { "branch": "main", "commit": "f8bbc3177d929dc86e272c41cc15219f0a7aa1ac" }, + "nvim-web-devicons": { "branch": "master", "commit": "803353450c374192393f5387b6a0176d0972b848" }, + "opencode.nvim": { "branch": "main", "commit": "0f85a4446720263b172521caa9cfaaf782a4f4ad" }, + "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, + "snacks.nvim": { "branch": "main", "commit": "fe7cfe9800a182274d0f868a74b7263b8c0c020b" }, "supermaven-nvim": { "branch": "main", "commit": "07d20fce48a5629686aefb0a7cd4b25e33947d50" }, - "telescope.nvim": { "branch": "master", "commit": "b4da76be54691e854d3e0e02c36b0245f945c2c7" }, - "tokyonight.nvim": { "branch": "main", "commit": "057ef5d260c1931f1dffd0f052c685dcd14100a3" }, - "ui": { "branch": "v3.0", "commit": "d3fb80f458bb91a170fb4aa8c0ce40867c71fcb9" }, - "volt": { "branch": "main", "commit": "7b8c5e790120d9f08c8487dcb80692db6d2087a1" }, - "which-key.nvim": { "branch": "main", "commit": "370ec46f710e058c9c1646273e6b225acf47cbed" } + "telescope.nvim": { "branch": "master", "commit": "ad7d9580338354ccc136e5b8f0aa4f880434dcdc" }, + "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }, + "ui": { "branch": "v3.0", "commit": "cb75908a86720172594b30de147272c1b3a7f452" }, + "volt": { "branch": "main", "commit": "620de1321f275ec9d80028c68d1b88b409c0c8b1" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } } diff --git a/config/nvim/lua/configs/lspconfig.lua b/config/nvim/lua/configs/lspconfig.lua index 508ebf6..e9d11df 100644 --- a/config/nvim/lua/configs/lspconfig.lua +++ b/config/nvim/lua/configs/lspconfig.lua @@ -1,33 +1,73 @@ --- load defaults i.e lua_lsp require("nvchad.configs.lspconfig").defaults() -local lspconfig = require "lspconfig" - --- EXAMPLE -local servers = { "html", "cssls", "ts_ls", "svelte" } local nvlsp = require "nvchad.configs.lspconfig" +local capabilities = require("cmp_nvim_lsp").default_capabilities() --- lsps with default config -for _, lsp in ipairs(servers) do - lspconfig[lsp].setup { - on_attach = nvlsp.on_attach, - on_init = nvlsp.on_init, - capabilities = nvlsp.capabilities, - } -end +vim.diagnostic.config({ + virtual_text = true, + float = true, + signs = true, + underline = true, + update_in_insert = false, + severity_sort = true, +}) + +require("mason-lspconfig").setup({ + ensure_installed = { "gopls", "ts_ls" }, +}) --- configuring single server, example: typescript -lspconfig.ts_ls.setup { +vim.keymap.set("n", "gD", vim.lsp.buf.declaration, { desc = "Go to declaration" }) +vim.keymap.set("n", "gd", vim.lsp.buf.definition, { desc = "Go to definition" }) +vim.keymap.set("n", "K", vim.lsp.buf.hover, { desc = "Hover Documentation" }) +vim.keymap.set("n", "gi", vim.lsp.buf.implementation, { desc = "Go to implementation" }) +vim.keymap.set("n", "ca", vim.lsp.buf.code_action, { desc = "Code actions" }) +vim.keymap.set("n", "rn", vim.lsp.buf.rename, { desc = "Rename" }) + +vim.lsp.config("ruff", { + capabilities = capabilities, + on_attach = nvlsp.on_attach, + on_init = nvlsp.on_init, +}) + +vim.lsp.config("gopls", { + capabilities = capabilities, + on_attach = nvlsp.on_attach, + on_init = nvlsp.on_init, + settings = { + gopls = { + analyses = { + unusedparams = true, + }, + staticcheck = true, + gofumpt = true, + }, + }, +}) + +vim.lsp.config("ts_ls", { + capabilities = capabilities, on_attach = nvlsp.on_attach, on_init = nvlsp.on_init, - capabilities = nvlsp.capabilities, filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact" }, -} +}) --- configuring svelte server -lspconfig.svelte.setup { +vim.lsp.config("svelte", { + capabilities = capabilities, on_attach = nvlsp.on_attach, on_init = nvlsp.on_init, - capabilities = nvlsp.capabilities, filetypes = { "svelte" }, -} +}) + +local servers = { "html", "cssls" } + +for _, lsp in ipairs(servers) do + vim.lsp.config(lsp, { + capabilities = capabilities, + on_attach = nvlsp.on_attach, + on_init = nvlsp.on_init, + }) +end + +for _, lsp in ipairs({ "html", "cssls", "ts_ls", "svelte", "gopls", "ruff" }) do + vim.lsp.enable(lsp) +end diff --git a/config/nvim/lua/configs/telescope.lua b/config/nvim/lua/configs/telescope.lua new file mode 100644 index 0000000..9faff4a --- /dev/null +++ b/config/nvim/lua/configs/telescope.lua @@ -0,0 +1,14 @@ +local actions = require "telescope.actions" + +require("telescope").setup { + pickers = { + buffers = { + mappings = { + i = { + [""] = actions.delete_buffer + actions.move_to_top, + [""] = actions.delete_buffer, + } + } + } + } +} diff --git a/config/nvim/lua/mappings.lua b/config/nvim/lua/mappings.lua index 6210bb1..b74348d 100644 --- a/config/nvim/lua/mappings.lua +++ b/config/nvim/lua/mappings.lua @@ -1,5 +1,8 @@ require "nvchad.mappings" +-- Remove NvChad's default nvim-tree keybinding since nvim-tree is removed +vim.keymap.del("n", "e") + -- add yours here local map = vim.keymap.set @@ -13,8 +16,7 @@ map("i", "jk", "") map("v", "K", ":m '<-2gv=gv", { desc = "Move selected text up" }) map("v", "J", ":m '>+1gv=gv", { desc = "Move selected text down" }) --- Buffer navigation with Shift-h and Shift-l -map("n", "x", "bd", { desc = "Close buffer" }) + -- Buffer navigation with Alt-arrows map("n", "", "bprevious", { desc = "Previous buffer" }) @@ -36,8 +38,11 @@ map("n", "fg", builtin.live_grep, { desc = "Telescope live grep" }) map("n", "fb", builtin.buffers, { desc = "Telescope buffers" }) map("n", "fh", builtin.help_tags, { desc = "Telescope help tags" }) -map("n", "gl", vim.diagnostic.open_float, { desc = "Show diagnostic message" }) -map("n", "nd", "NoiceDismiss", { desc = "Dismiss noice message" }) +-- Helix-style keymaps +map("n", "x", "V", { desc = "Visual line mode" }) +map("n", "gl", "$", { desc = "Go to end of line" }) +map("n", "gs", "^", { desc = "Go to start of line" }) +map("n", "ge", "G", { desc = "Go to end of file" }) -- Remap delete operations to use blackhole register map("n", "d", '"_d', { desc = "Delete to blackhole register" }) diff --git a/config/nvim/lua/plugins/init.lua b/config/nvim/lua/plugins/init.lua index 44eafe8..bbf9544 100644 --- a/config/nvim/lua/plugins/init.lua +++ b/config/nvim/lua/plugins/init.lua @@ -1,20 +1,4 @@ return { - { - "nvim-tree/nvim-tree.lua", - dependencies = { - "nvim-tree/nvim-web-devicons", - }, - config = function() - require("nvim-tree").setup { - view = { - width = 30, - side = "right", - relativenumber = true, - number = true, - }, - } - end, - }, { "stevearc/conform.nvim", -- event = 'BufWritePre', -- uncomment for format on save @@ -30,20 +14,28 @@ return { }, { - "nvim-treesitter/nvim-treesitter", - config = function() - require('nvim-treesitter.configs').setup { - ensure_installed = { - "markdown", "markdown_inline", - "vim", "lua", "vimdoc", - "html", "css", "hcl", "toml", "hurl", - "javascript", "typescript", "tsx", "svelte" - }, - highlight = { - enable = true - } - } - end, + "nvim-treesitter/nvim-treesitter", + event = { "BufReadPost", "BufNewFile" }, + build = ":TSUpdate", + opts = { + ensure_installed = { + "javascript", + "typescript", + "tsx", + "lua", + "vim", + "vimdoc", + "html", + "css", + "markdown", + }, + highlight = { + enable = true, + }, + indent = { + enable = true, + }, + }, }, { diff --git a/config/nvim/lua/plugins/lspconfig.lua b/config/nvim/lua/plugins/lspconfig.lua index d499fcd..d4e0de0 100644 --- a/config/nvim/lua/plugins/lspconfig.lua +++ b/config/nvim/lua/plugins/lspconfig.lua @@ -1,75 +1,38 @@ -return { - { - "williamboman/mason.nvim", - cmd = "Mason", - keys = { { "cm", "Mason", desc = "Mason" } }, - opts = { - ensure_installed = { - "gopls", - }, - }, - config = function(_, opts) - require("mason").setup(opts) - local mr = require("mason-registry") - for _, tool in ipairs(opts.ensure_installed) do - local p = mr.get_package(tool) - if not p:is_installed() then - p:install() - end - end - end, - }, - { - "neovim/nvim-lspconfig", - event = { "BufReadPre", "BufNewFile" }, - dependencies = { - "williamboman/mason.nvim", - "williamboman/mason-lspconfig.nvim", - }, - config = function() - vim.diagnostic.config({ - virtual_text = true, - float = true, - signs = true, - underline = true, - update_in_insert = false, - severity_sort = true, - }) - local lspconfig = require("lspconfig") - local capabilities = require("cmp_nvim_lsp").default_capabilities() - - require("mason-lspconfig").setup({ - ensure_installed = { "gopls" }, - }) - require('lspconfig').ruff.setup({ - init_options = { - settings = { - -- Ruff language server settings go here - } - } - }) - -- Go configuration - lspconfig.gopls.setup({ - capabilities = capabilities, - settings = { - gopls = { - analyses = { - unusedparams = true, - }, - staticcheck = true, - gofumpt = true, - }, - }, - }) - - -- Global LSP mappings - vim.keymap.set("n", "gD", vim.lsp.buf.declaration, { desc = "Go to declaration" }) - vim.keymap.set("n", "gd", vim.lsp.buf.definition, { desc = "Go to definition" }) - vim.keymap.set("n", "K", vim.lsp.buf.hover, { desc = "Hover Documentation" }) - vim.keymap.set("n", "gi", vim.lsp.buf.implementation, { desc = "Go to implementation" }) - vim.keymap.set("n", "ca", vim.lsp.buf.code_action, { desc = "Code actions" }) - vim.keymap.set("n", "rn", vim.lsp.buf.rename, { desc = "Rename" }) - end, - }, -} +return { + { + "williamboman/mason.nvim", + cmd = "Mason", + keys = { { "cm", "Mason", desc = "Mason" } }, + opts = { + ensure_installed = { + "gopls", + "typescript-language-server", + }, + }, + config = function(_, opts) + require("mason").setup(opts) + local mr = require("mason-registry") + for _, tool in ipairs(opts.ensure_installed) do + local ok, p = pcall(mr.get_package, tool) + if ok then + if not p:is_installed() then + p:install() + end + else + vim.notify(("mason.nvim: unknown package '%s'"):format(tool), vim.log.levels.WARN) + end + end + end, + }, + { + "neovim/nvim-lspconfig", + dependencies = { + "williamboman/mason.nvim", + "williamboman/mason-lspconfig.nvim", + }, + config = function() + require "configs.lspconfig" + end, + }, +} diff --git a/config/nvim/lua/plugins/neoscroll.lua b/config/nvim/lua/plugins/neoscroll.lua deleted file mode 100644 index be86504..0000000 --- a/config/nvim/lua/plugins/neoscroll.lua +++ /dev/null @@ -1,18 +0,0 @@ -return { - "karb94/neoscroll.nvim", - event = "VeryLazy", - config = function() - require('neoscroll').setup({ - mappings = {'', '', '', '', - '', '', 'zt', 'zz', 'zb'}, - hide_cursor = true, - stop_eof = true, - respect_scrolloff = false, - cursor_scrolls_alone = true, - easing_function = "cubic", - pre_hook = nil, - post_hook = nil, - performance_mode = false, - }) - end -} diff --git a/config/nvim/lua/plugins/noice.lua b/config/nvim/lua/plugins/noice.lua deleted file mode 100644 index fe2347f..0000000 --- a/config/nvim/lua/plugins/noice.lua +++ /dev/null @@ -1,16 +0,0 @@ --- lazy.nvim -return { - "folke/noice.nvim", - event = "VeryLazy", - opts = { - -- add any options here - }, - dependencies = { - -- if you lazy-load any plugin below, make sure to add proper `module="..."` entries - "MunifTanjim/nui.nvim", - -- OPTIONAL: - -- `nvim-notify` is only needed, if you want to use the notification view. - -- If not available, we use `mini` as the fallback - "rcarriga/nvim-notify", - } -} diff --git a/config/nvim/spell/en.utf-8.add b/config/nvim/spell/en.utf-8.add index fce89ac..2073149 100644 --- a/config/nvim/spell/en.utf-8.add +++ b/config/nvim/spell/en.utf-8.add @@ -28,3 +28,4 @@ deflayer darwin eza nvim +gitrhub diff --git a/config/sketchybar/plugins/aerospace_update_all.sh b/config/sketchybar/plugins/aerospace_update_all.sh index be65c61..12a0e53 100755 --- a/config/sketchybar/plugins/aerospace_update_all.sh +++ b/config/sketchybar/plugins/aerospace_update_all.sh @@ -7,8 +7,8 @@ SKETCHYBAR_CMD="sketchybar" # Source colors -CONFIG_DIR="$(dirname "$0")/.." -source "$CONFIG_DIR/colors.sh" +CONFIG_DIR="$(dirname "$0")" +source "$CONFIG_DIR/../colors.sh" # Get the current focused workspace CURRENT_WORKSPACE="$1" @@ -18,6 +18,8 @@ if [ -z "$CURRENT_WORKSPACE" ]; then CURRENT_WORKSPACE=$(aerospace list-workspaces --focused) fi + + # Update all workspace indicators for workspace in 7 1 2 3 4 5 6; do if [ "$workspace" = "$CURRENT_WORKSPACE" ]; then diff --git a/config/sketchybar/plugins/network.sh b/config/sketchybar/plugins/network.sh index 2032f68..e3b8624 100755 --- a/config/sketchybar/plugins/network.sh +++ b/config/sketchybar/plugins/network.sh @@ -47,7 +47,7 @@ fi # Get connection speed/info if [ "$INTERFACE" = "en0" ]; then # Check if it's WiFi first using system_profiler - WIFI_NAME=$(system_profiler SPAirPortDataType | awk '/Current Network Information:/,/PHY Mode:/ {if ($0 ~ /:$/ && $0 !~ /Current Network Information:/ && $0 !~ /PHY Mode:/) print $1}' | sed 's/:$//' | head -1) + WIFI_NAME=$(airport -I | awk -F' SSID: ' '/ SSID: / {print $2}') if [ -z "$WIFI_NAME" ]; then # Not WiFi, check if en0 is active for other connection types diff --git a/config/sketchybar/sketchybarrc b/config/sketchybar/sketchybarrc index 404c5b0..baa1a98 100755 --- a/config/sketchybar/sketchybarrc +++ b/config/sketchybar/sketchybarrc @@ -1,7 +1,7 @@ # Modern SketchyBar Configuration # A clean, developer-friendly setup with commonly used widgets -CONFIG_DIR="$(dirname "$0")" +CONFIG_DIR="/Users/robray/.config/sketchybar" source "$CONFIG_DIR/colors.sh" PLUGIN_DIR="$CONFIG_DIR/plugins" diff --git a/docs/SYNC_README.md b/docs/SYNC_README.md new file mode 100644 index 0000000..465a3ac --- /dev/null +++ b/docs/SYNC_README.md @@ -0,0 +1,97 @@ +# Dotfiles Sync Script + +## Description +`sync.sh` automatically syncs your home configuration files to your dotfiles repository and replaces them with symlinks. + +## Usage + +```bash +./sync.sh [OPTIONS] +``` + +### Options +- `-d, --dry-run`: Show what would be done without making changes +- `-v, --verbose`: Show detailed output for each operation +- `-y, --yes`: Skip confirmation prompts +- `-f, --force`: Force overwrite even if dotfile is newer +- `-b, --backup-dir`: Custom backup directory (default: ~/dotfiles/.backup/) +- `-h, --help`: Show help message + +### Examples + +```bash +# Preview changes +./sync.sh --dry-run --verbose + +# Sync with confirmation prompts +./sync.sh + +# Force sync all files without confirmation +./sync.sh --yes --force + +# Sync with custom backup location +./sync.sh --backup-dir ~/backups/dotfiles +``` + +## What Gets Synced + +### Root-level files +- `.zshrc` +- `.gitconfig` +- `.aerospace.toml` +- `.wezterm.lua` + +### Config directories +- `~/.config/fish/` +- `~/.config/nvim/` +- `~/.config/sketchybar/` +- `~/.config/mise/` +- `~/.config/nix/` +- `~/.config/helix/` +- `~/.config/kanata/` +- `~/.config/opencode/` + +## What Gets Ignored + +### Files +- `.zsh_history` +- `.zcompdump` +- `.bash_history` +- `.python_history` +- `.viminfo` +- `.DS_Store` +- `.CFUserTextEncoding` + +### Directories +- `node_modules/` +- `.git/` +- `__pycache__/` +- `target/` +- `dist/` +- `build/` +- `.venv/` +- `venv/` + +## How It Works + +1. **Detects changes**: Compares home config files against dotfiles repository using `diff` +2. **Backs up originals**: Creates timestamped backups in `~/dotfiles/.backup/` +3. **Copies changes**: Copies modified files from home to dotfiles repository +4. **Creates symlinks**: Replaces home files with symlinks to dotfiles versions + +## Safety Features + +- **Dry-run mode**: Preview changes before applying +- **Backup directory**: All original files are backed up before symlinking +- **Confirmation prompts**: Requires confirmation before making destructive changes (use `-y` to skip) +- **Ignore patterns**: Automatically skips transient files and build artifacts +- **Idempotent**: Safe to run multiple times + +## Recovery + +If something goes wrong, you can restore files from the backup directory: + +```bash +ls ~/dotfiles/.backup/ +cp ~/dotfiles/.backup/. ~/ +``` diff --git a/sync.sh b/sync.sh new file mode 100755 index 0000000..9532d35 --- /dev/null +++ b/sync.sh @@ -0,0 +1,391 @@ +#!/usr/bin/env bash + +set -uo pipefail + +# ===== CONFIGURATION ===== +DOTFILES_DIR="$HOME/dotfiles" +BACKUP_DIR="$DOTFILES_DIR/.backup" +IGNORE_FILES=(.zsh_history .zcompdump .bash_history .python_history .viminfo .DS_Store .CFUserTextEncoding) +IGNORE_DIRS=(node_modules .git __pycache__ target dist build .venv venv .backup) + +ROOT_FILES=(.zshrc .gitconfig .aerospace.toml .wezterm.lua) +CONFIG_DIRS=(fish nvim sketchybar mise nix helix kanata opencode) +HOME_DIRS=(.claude) + +# ===== OPTIONS ===== +DRY_RUN=false +VERBOSE=false +FORCE=false +SKIP_CONFIRM=false + +# ===== UTILITY FUNCTIONS ===== + +log() { + echo -e "\e[1;34m[INFO]\e[0m $1" +} + +warn() { + echo -e "\e[1;33m[WARN]\e[0m $1" >&2 +} + +error() { + echo -e "\e[1;31m[ERROR]\e[0m $1" >&2 +} + +verbose() { + if $VERBOSE; then + echo -e "\e[1;36m[DEBUG]\e[0m $1" + fi +} + +dry_run() { + local cmd="$1" + if $DRY_RUN; then + echo -e "\e[1;32m[DRY-RUN]\e[0m $cmd" + else + verbose "Executing: $cmd" + eval "$cmd" + fi +} + +# ===== HELPER FUNCTIONS ===== + +show_help() { + cat << EOF +sync.sh - Sync home configuration files to dotfiles and create symlinks + +USAGE: + ./sync.sh [OPTIONS] + +OPTIONS: + -d, --dry-run Show what would be done without making changes + -v, --verbose Show detailed output for each operation + -y, --yes Skip confirmation prompts + -f, --force Force overwrite even if dotfile is newer + -b, --backup-dir Custom backup directory (default: ~/dotfiles/.backup/) + -h, --help Show this help message + +EXAMPLES: + ./sync.sh --dry-run --verbose # Preview changes + ./sync.sh # Sync with confirmation + ./sync.sh --yes --force # Force sync all files +EOF +} + +parse_args() { + while [[ $# -gt 0 ]]; do + case $1 in + -d|--dry-run) + DRY_RUN=true + shift + ;; + -v|--verbose) + VERBOSE=true + shift + ;; + -y|--yes) + SKIP_CONFIRM=true + shift + ;; + -f|--force) + FORCE=true + shift + ;; + -b|--backup-dir) + BACKUP_DIR="$2" + shift 2 + ;; + -h|--help) + show_help + exit 0 + ;; + *) + error "Unknown option: $1" + echo "Use --help for usage information" + exit 1 + ;; + esac + done +} + +should_ignore() { + local filepath="$1" + local filename + filename=$(basename "$filepath") + + for ignore in "${IGNORE_FILES[@]}"; do + if [[ "$filename" == "$ignore" ]]; then + verbose "Ignoring: $filename" + return 0 + fi + done + + for ignore in "${IGNORE_DIRS[@]}"; do + if [[ "$filepath" == *"/$ignore/"* ]]; then + verbose "Ignoring directory: $ignore" + return 0 + fi + done + + return 1 +} + +is_symlinked() { + local home_file="$1" + local dotfile="$2" + + if [[ -L "$home_file" ]]; then + local target + target=$(readlink "$home_file" 2>/dev/null || true) + if [[ "$target" == "$dotfile" ]]; then + verbose "Already symlinked: $home_file -> $dotfile" + return 0 + fi + fi + return 1 +} + +files_differ() { + local file1="$1" + local file2="$2" + + if ! diff -q "$file1" "$file2" >/dev/null 2>&1; then + return 0 + fi + return 1 +} + +backup_file() { + local file="$1" + local timestamp + timestamp=$(date +%Y%m%d_%H%M%S) + local filename + filename=$(basename "$file") + local backup_path="$BACKUP_DIR/${filename}.${timestamp}" + + if [[ -e "$file" ]]; then + dry_run "cp -a '$file' '$backup_path'" + log "Backed up to: $backup_path" + fi +} + +copy_to_dotfiles() { + local home_file="$1" + local dotfile="$2" + + dry_run "mkdir -p '$(dirname "$dotfile")' && cp -a '$home_file' '$dotfile'" + log "Copied to dotfiles: $dotfile" +} + +create_symlink() { + local home_file="$1" + local dotfile="$2" + + if [[ -e "$home_file" && ! -L "$home_file" ]]; then + dry_run "rm '$home_file'" + fi + + dry_run "ln -s '$dotfile' '$home_file'" + log "Created symlink: $home_file -> $dotfile" +} + +confirm() { + local prompt="$1" + + if $SKIP_CONFIRM; then + return 0 + fi + + read -p "$prompt [y/N] " -n 1 -r + echo + [[ $REPLY =~ ^[Yy]$ ]] +} + +sync_file() { + local home_file="$1" + local dotfile="$2" + + if [[ ! -e "$home_file" ]]; then + verbose "File does not exist: $home_file" + return 2 + fi + + if should_ignore "$home_file"; then + return 2 + fi + + if is_symlinked "$home_file" "$dotfile"; then + return 2 + fi + + local needs_copy=false + local needs_backup=false + + if [[ ! -e "$dotfile" ]]; then + verbose "Creating new dotfile: $dotfile" + needs_copy=true + elif files_differ "$home_file" "$dotfile"; then + log "Changes detected: $home_file" + needs_copy=true + needs_backup=true + else + verbose "Files are identical, just creating symlink" + fi + + if $needs_backup && ! $DRY_RUN && ! confirm "Sync $home_file?"; then + return 2 + fi + + if $needs_backup; then + backup_file "$home_file" + fi + + if $needs_copy; then + copy_to_dotfiles "$home_file" "$dotfile" + fi + + create_symlink "$home_file" "$dotfile" + return 0 +} + +sync_root_files() { + log "Syncing root configuration files..." + + local synced=0 + local skipped=0 + + for file in "${ROOT_FILES[@]}"; do + verbose "Processing root file: $file" + local home_file="$HOME/$file" + local dotfile="$DOTFILES_DIR/$file" + + sync_file "$home_file" "$dotfile" || true + verbose "Synced: $file" + synced=$((synced + 1)) + done + + echo "Root files: $synced synced, $skipped skipped" +} + +sync_config_files() { + log "Syncing config directory files..." + + local synced=0 + local skipped=0 + + for dir in "${CONFIG_DIRS[@]}"; do + local config_dir="$HOME/.config/$dir" + + if [[ ! -d "$config_dir" ]]; then + verbose "Config directory does not exist: $config_dir" + continue + fi + + verbose "Processing directory: $dir" + local count=0 + for file in $(find "$config_dir" -type f 2>/dev/null); do + verbose "Processing file: $file" + count=$((count + 1)) + local rel_path="${file#$HOME/.config/}" + local home_file="$HOME/.config/$rel_path" + local dotfile="$DOTFILES_DIR/config/$rel_path" + + sync_file "$home_file" "$dotfile" + local result=$? + + if [[ $result -eq 0 ]]; then + synced=$((synced + 1)) + else + skipped=$((skipped + 1)) + fi + done + verbose "Completed directory: $dir ($count files)" + done + + echo "Config files: $synced synced, $skipped skipped" +} + +sync_home_dirs() { + log "Syncing home dot-directories..." + + local synced=0 + local skipped=0 + + for dir in "${HOME_DIRS[@]}"; do + local home_dir="$HOME/$dir" + + if [[ ! -d "$home_dir" ]]; then + verbose "Home directory does not exist: $home_dir" + continue + fi + + verbose "Processing directory: $dir" + local count=0 + for file in $(find "$home_dir" -type f 2>/dev/null); do + verbose "Processing file: $file" + count=$((count + 1)) + local rel_path="${file#$HOME/}" + local home_file="$HOME/$rel_path" + local dotfile="$DOTFILES_DIR/$rel_path" + + sync_file "$home_file" "$dotfile" + local result=$? + + if [[ $result -eq 0 ]]; then + synced=$((synced + 1)) + else + skipped=$((skipped + 1)) + fi + done + verbose "Completed directory: $dir ($count files)" + done + + echo "Home dirs: $synced synced, $skipped skipped" +} + +sync_all() { + local total_synced=0 + local total_skipped=0 + local start_time + + start_time=$(date +%s) + + if $DRY_RUN; then + log "Running in dry-run mode, no changes will be made" + fi + + sync_root_files + + sync_config_files + + sync_home_dirs + + local end_time + end_time=$(date +%s) + local duration=$((end_time - start_time)) + + echo "" + log "Sync completed in ${duration}s" + echo "Backup directory: $BACKUP_DIR" + + if $DRY_RUN; then + log "This was a dry-run. Run without --dry-run to apply changes." + fi +} + +# ===== MAIN ===== + +main() { + parse_args "$@" + + if [[ ! -d "$DOTFILES_DIR" ]]; then + error "Dotfiles directory not found: $DOTFILES_DIR" + exit 1 + fi + + mkdir -p "$BACKUP_DIR" + + sync_all +} + +main "$@"