diff --git a/.bashrc b/.bashrc deleted file mode 100644 index e5db98e..0000000 --- a/.bashrc +++ /dev/null @@ -1,664 +0,0 @@ -#!/usr/bin/env bash -iatest=$(expr index "$-" i) -cat /home/nicholai/.cache/wal/sequences - -# Source global definitions -if [ -f /etc/bashrc ]; then - . /etc/bashrc -fi - -if [ -f /usr/share/bash-completion/bash_completion ]; then - . /usr/share/bash-completion/bash_completion -elif [ -f /etc/bash_completion ]; then - . /etc/bash_completion -fi - -####################################################### -# EXPORTS -####################################################### - -# Disable the bell -if [[ $iatest -gt 0 ]]; then bind "set bell-style visible"; fi - -# Expand the history size -export HISTFILESIZE=10000 -export HISTSIZE=500 -export HISTTIMEFORMAT="%F %T" # add timestamp to history - -# Don't put duplicate lines in the history and do not add lines that start with a space -export HISTCONTROL=erasedups:ignoredups:ignorespace - -# Check the window size after each command and, if necessary, update the values of LINES and COLUMNS -shopt -s checkwinsize - -# Causes bash to append to history instead of overwriting it so if you start a new terminal, you have old session history -shopt -s histappend -PROMPT_COMMAND='history -a' - -# set up XDG folders -export XDG_DATA_HOME="$HOME/.local/share" -export XDG_CONFIG_HOME="$HOME/.config" -export XDG_STATE_HOME="$HOME/.local/state" -export XDG_CACHE_HOME="$HOME/.cache" - -# Seeing as other scripts will use it might as well export it -export LINUXTOOLBOXDIR="$HOME/linuxtoolbox" - -# Allow ctrl-S for history navigation (with ctrl-R) -# [[ $- == *i* ]] && stty -ixon - -# Ignore case on auto-completion -# Note: bind used instead of sticking these in .inputrc -if [[ $iatest -gt 0 ]]; then bind "set completion-ignore-case on"; fi - -# Show auto-completion list automatically, without double tab -if [[ $iatest -gt 0 ]]; then bind "set show-all-if-ambiguous On"; fi - -# Set the default editor -export EDITOR=nvim -export VISUAL=nvim -alias spico='sudo pico' -alias snano='sudo nano' -alias vim='nvim' - -# To have colors for ls and all grep commands such as grep, egrep and zgrep -export CLICOLOR=1 -export LS_COLORS='no=00:fi=00:di=00;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.ogg=01;35:*.mp3=01;35:*.wav=01;35:*.xml=00;31:' -#export GREP_OPTIONS='--color=auto' #deprecated - -# Color for manpages in less makes manpages a little easier to read -export LESS_TERMCAP_mb=$'\E[01;31m' -export LESS_TERMCAP_md=$'\E[01;31m' -export LESS_TERMCAP_me=$'\E[0m' -export LESS_TERMCAP_se=$'\E[0m' -export LESS_TERMCAP_so=$'\E[01;44;33m' -export LESS_TERMCAP_ue=$'\E[0m' -export LESS_TERMCAP_us=$'\E[01;32m' - - export QT_QPA_PLATFORMTHEME=qt5ct - -####################################################### -# MACHINE SPECIFIC ALIAS'S -####################################################### - -# Alias's for SSH -alias united-tattoo='ssh root@77.37.63.91' - -# Alias's to change the directory -alias web='cd /var/www/html' - -# Alias's to mount ISO files -# mount -o loop /home/NAMEOFISO.iso /home/ISOMOUNTDIR/ -# umount /home/NAMEOFISO.iso -# (Both commands done as root only.) - -####################################################### -# GENERAL ALIAS'S -####################################################### -# To temporarily bypass an alias, we precede the command with a \ -# EG: the ls command is aliased, but to use the normal ls command you would type \ls - -# Add an "alert" alias for long running commands. Use like so: -# sleep 10; alert -alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' - -# Edit this .bashrc file -alias ebrc='edit ~/.bashrc' - -# Show help for this .bashrc file -alias hlp='less ~/.bashrc_help' - -# alias to show the date -alias da='date "+%Y-%m-%d %A %T %Z"' - -# Alias's to modified commands -alias cp='cp -i' -alias mv='mv -i' -alias mkdir='mkdir -p' -alias ps='ps auxf' -alias ping='ping -c 10' -alias less='less -R' -alias cls='clear' -alias apt-get='sudo apt-get' -alias multitail='multitail --no-repeat -c' -alias freshclam='sudo freshclam' -alias vi='nvim' -alias svi='sudo vi' -alias vis='nvim "+set si"' -alias yayf="yay -Slq | fzf --multi --preview 'yay -Sii {1}' --preview-window=down:75% | xargs -ro yay -S" - -# Change directory aliases -alias home='cd ~' -alias cd..='cd ..' -alias ..='cd ..' -alias ...='cd ../..' -alias ....='cd ../../..' -alias .....='cd ../../../..' - -# cd into the old directory -alias bd='cd "$OLDPWD"' - -# Remove a directory and all files -alias rmd='/bin/rm --recursive --force --verbose ' - -# Alias's for multiple directory listing commands -alias la='ls -Alh' # show hidden files -alias ls='ls -aFh --color=always' # add colors and file type extensions -alias lx='ls -lXBh' # sort by extension -alias lk='ls -lSrh' # sort by size -alias lc='ls -ltcrh' # sort by change time -alias lu='ls -lturh' # sort by access time -alias lr='ls -lRh' # recursive ls -alias lt='ls -ltrh' # sort by date -alias lm='ls -alh |more' # pipe through 'more' -alias lw='ls -xAh' # wide listing format -alias ll='ls -Fls' # long listing format -alias labc='ls -lap' # alphabetical sort -alias lf="ls -l | egrep -v '^d'" # files only -alias ldir="ls -l | egrep '^d'" # directories only -alias lla='ls -Al' # List and Hidden Files -alias las='ls -A' # Hidden Files -alias lls='ls -l' # List - -# alias chmod commands -alias mx='chmod a+x' -alias 000='chmod -R 000' -alias 644='chmod -R 644' -alias 666='chmod -R 666' -alias 755='chmod -R 755' -alias 777='chmod -R 777' - -# Search command line history -alias h="history | grep " - -# Search running processes -alias p="ps aux | grep " -alias topcpu="/bin/ps -eo pcpu,pid,user,args | sort -k 1 -r | head -10" - -# Search files in the current folder -alias f="find . | grep " - -# Count all files (recursively) in the current folder -alias countfiles="for t in files links directories; do echo \`find . -type \${t:0:1} | wc -l\` \$t; done 2> /dev/null" - -# To see if a command is aliased, a file, or a built-in command -alias checkcommand="type -t" - -# Show open ports -alias openports='netstat -nape --inet' - -# Alias's for safe and forced reboots -alias rebootsafe='sudo shutdown -r now' -alias rebootforce='sudo shutdown -r -n now' - -# Alias's to show disk space and space used in a folder -alias diskspace="du -S | sort -n -r |more" -alias folders='du -h --max-depth=1' -alias folderssort='find . -maxdepth 1 -type d -print0 | xargs -0 du -sk | sort -rn' -alias tree='tree -CAhF --dirsfirst' -alias treed='tree -CAFd' -alias mountedinfo='df -hT' - -# Alias's for archives -alias mktar='tar -cvf' -alias mkbz2='tar -cvjf' -alias mkgz='tar -cvzf' -alias untar='tar -xvf' -alias unbz2='tar -xvjf' -alias ungz='tar -xvzf' - -# Show all logs in /var/log -alias logs="sudo find /var/log -type f -exec file {} \; | grep 'text' | cut -d' ' -f1 | sed -e's/:$//g' | grep -v '[0-9]$' | xargs tail -f" - -# SHA1 -alias sha1='openssl sha1' - -alias clickpaste='sleep 3; xdotool type "$(xclip -o -selection clipboard)"' - -# KITTY - alias to be able to use kitty features when connecting to remote servers(e.g use tmux on remote server) - -alias kssh="kitty +kitten ssh" - -# alias to cleanup unused docker containers, images, networks, and volumes - -alias docker-clean=' \ - docker container prune -f ; \ - docker image prune -f ; \ - docker network prune -f ; \ - docker volume prune -f ' - -####################################################### -# SPECIAL FUNCTIONS -####################################################### -# Extracts any archive(s) (if unp isn't installed) -extract() { - for archive in "$@"; do - if [ -f "$archive" ]; then - case $archive in - *.tar.bz2) tar xvjf $archive ;; - *.tar.gz) tar xvzf $archive ;; - *.bz2) bunzip2 $archive ;; - *.rar) rar x $archive ;; - *.gz) gunzip $archive ;; - *.tar) tar xvf $archive ;; - *.tbz2) tar xvjf $archive ;; - *.tgz) tar xvzf $archive ;; - *.zip) unzip $archive ;; - *.Z) uncompress $archive ;; - *.7z) 7z x $archive ;; - *) echo "don't know how to extract '$archive'..." ;; - esac - else - echo "'$archive' is not a valid file!" - fi - done -} - -# Searches for text in all files in the current folder -ftext() { - # -i case-insensitive - # -I ignore binary files - # -H causes filename to be printed - # -r recursive search - # -n causes line number to be printed - # optional: -F treat search term as a literal, not a regular expression - # optional: -l only print filenames and not the matching lines ex. grep -irl "$1" * - grep -iIHrn --color=always "$1" . | less -r -} - -# Copy file with a progress bar -cpp() { - set -e - strace -q -ewrite cp -- "${1}" "${2}" 2>&1 | - awk '{ - count += $NF - if (count % 10 == 0) { - percent = count / total_size * 100 - printf "%3d%% [", percent - for (i=0;i<=percent;i++) - printf "=" - printf ">" - for (i=percent;i<100;i++) - printf " " - printf "]\r" - } - } - END { print "" }' total_size="$(stat -c '%s' "${1}")" count=0 -} - -# Copy and go to the directory -cpg() { - if [ -d "$2" ]; then - cp "$1" "$2" && cd "$2" - else - cp "$1" "$2" - fi -} - -# Move and go to the directory -mvg() { - if [ -d "$2" ]; then - mv "$1" "$2" && cd "$2" - else - mv "$1" "$2" - fi -} - -# Create and go to the directory -mkdirg() { - mkdir -p "$1" - cd "$1" -} - -# Goes up a specified number of directories (i.e. up 4) -up() { - local d="" - limit=$1 - for ((i = 1; i <= limit; i++)); do - d=$d/.. - done - d=$(echo $d | sed 's/^\///') - if [ -z "$d" ]; then - d=.. - fi - cd $d -} - -# Automatically do an ls after each cd, z, or zoxide -cd () -{ - if [ -n "$1" ]; then - builtin cd "$@" && ls - else - builtin cd ~ && ls - fi -} - -# Returns the last 2 fields of the working directory -pwdtail() { - pwd | awk -F/ '{nlast = NF -1;print $nlast"/"$NF}' -} - -# Show the current distribution -distribution () { - local dtype="unknown" # Default to unknown - - # Use /etc/os-release for modern distro identification - if [ -r /etc/os-release ]; then - source /etc/os-release - case $ID in - fedora|rhel|centos) - dtype="redhat" - ;; - sles|opensuse*) - dtype="suse" - ;; - ubuntu|debian) - dtype="debian" - ;; - gentoo) - dtype="gentoo" - ;; - arch|manjaro) - dtype="arch" - ;; - slackware) - dtype="slackware" - ;; - *) - # Check ID_LIKE only if dtype is still unknown - if [ -n "$ID_LIKE" ]; then - case $ID_LIKE in - *fedora*|*rhel*|*centos*) - dtype="redhat" - ;; - *sles*|*opensuse*) - dtype="suse" - ;; - *ubuntu*|*debian*) - dtype="debian" - ;; - *gentoo*) - dtype="gentoo" - ;; - *arch*) - dtype="arch" - ;; - *slackware*) - dtype="slackware" - ;; - esac - fi - - # If ID or ID_LIKE is not recognized, keep dtype as unknown - ;; - esac - fi - - echo $dtype -} - - -DISTRIBUTION=$(distribution) -if [ "$DISTRIBUTION" = "redhat" ] || [ "$DISTRIBUTION" = "arch" ]; then - alias cat='bat' -else - alias cat='batcat' -fi - -# Show the current version of the operating system -ver() { - local dtype - dtype=$(distribution) - - case $dtype in - "redhat") - if [ -s /etc/redhat-release ]; then - cat /etc/redhat-release - else - cat /etc/issue - fi - uname -a - ;; - "suse") - cat /etc/SuSE-release - ;; - "debian") - lsb_release -a - ;; - "gentoo") - cat /etc/gentoo-release - ;; - "arch") - cat /etc/os-release - ;; - "slackware") - cat /etc/slackware-version - ;; - *) - if [ -s /etc/issue ]; then - cat /etc/issue - else - echo "Error: Unknown distribution" - exit 1 - fi - ;; - esac -} - -# Automatically install the needed support files for this .bashrc file -install_bashrc_support() { - local dtype - dtype=$(distribution) - - case $dtype in - "redhat") - sudo yum install multitail tree zoxide trash-cli fzf bash-completion fastfetch - ;; - "suse") - sudo zypper install multitail tree zoxide trash-cli fzf bash-completion fastfetch - ;; - "debian") - sudo apt-get install multitail tree zoxide trash-cli fzf bash-completion - # Fetch the latest fastfetch release URL for linux-amd64 deb file - FASTFETCH_URL=$(curl -s https://api.github.com/repos/fastfetch-cli/fastfetch/releases/latest | grep "browser_download_url.*linux-amd64.deb" | cut -d '"' -f 4) - - # Download the latest fastfetch deb file - curl -sL $FASTFETCH_URL -o /tmp/fastfetch_latest_amd64.deb - - # Install the downloaded deb file using apt-get - sudo apt-get install /tmp/fastfetch_latest_amd64.deb - ;; - "arch") - sudo paru multitail tree zoxide trash-cli fzf bash-completion fastfetch - ;; - "slackware") - echo "No install support for Slackware" - ;; - *) - echo "Unknown distribution" - ;; - esac -} - -# IP address lookup -alias whatismyip="whatsmyip" -function whatsmyip () { - # Internal IP Lookup. - if command -v ip &> /dev/null; then - echo -n "Internal IP: " - ip addr show wlan0 | grep "inet " | awk '{print $2}' | cut -d/ -f1 - else - echo -n "Internal IP: " - ifconfig wlan0 | grep "inet " | awk '{print $2}' - fi - - # External IP Lookup - echo -n "External IP: " - curl -4 ifconfig.me -} - -# View Apache logs -apachelog() { - if [ -f /etc/httpd/conf/httpd.conf ]; then - cd /var/log/httpd && ls -xAh && multitail --no-repeat -c -s 2 /var/log/httpd/*_log - else - cd /var/log/apache2 && ls -xAh && multitail --no-repeat -c -s 2 /var/log/apache2/*.log - fi -} - -# Edit the Apache configuration -apacheconfig() { - if [ -f /etc/httpd/conf/httpd.conf ]; then - sedit /etc/httpd/conf/httpd.conf - elif [ -f /etc/apache2/apache2.conf ]; then - sedit /etc/apache2/apache2.conf - else - echo "Error: Apache config file could not be found." - echo "Searching for possible locations:" - sudo updatedb && locate httpd.conf && locate apache2.conf - fi -} - -# Edit the PHP configuration file -phpconfig() { - if [ -f /etc/php.ini ]; then - sedit /etc/php.ini - elif [ -f /etc/php/php.ini ]; then - sedit /etc/php/php.ini - elif [ -f /etc/php5/php.ini ]; then - sedit /etc/php5/php.ini - elif [ -f /usr/bin/php5/bin/php.ini ]; then - sedit /usr/bin/php5/bin/php.ini - elif [ -f /etc/php5/apache2/php.ini ]; then - sedit /etc/php5/apache2/php.ini - else - echo "Error: php.ini file could not be found." - echo "Searching for possible locations:" - sudo updatedb && locate php.ini - fi -} - -# Edit the MySQL configuration file -mysqlconfig() { - if [ -f /etc/my.cnf ]; then - sedit /etc/my.cnf - elif [ -f /etc/mysql/my.cnf ]; then - sedit /etc/mysql/my.cnf - elif [ -f /usr/local/etc/my.cnf ]; then - sedit /usr/local/etc/my.cnf - elif [ -f /usr/bin/mysql/my.cnf ]; then - sedit /usr/bin/mysql/my.cnf - elif [ -f ~/my.cnf ]; then - sedit ~/my.cnf - elif [ -f ~/.my.cnf ]; then - sedit ~/.my.cnf - else - echo "Error: my.cnf file could not be found." - echo "Searching for possible locations:" - sudo updatedb && locate my.cnf - fi -} - - -# Trim leading and trailing spaces (for scripts) -trim() { - local var=$* - var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters - var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters - echo -n "$var" -} -# GitHub Titus Additions - -gcom() { - git add . - git commit -m "$1" -} -lazyg() { - git add . - git commit -m "$1" - git push -} - -function hb { - if [ $# -eq 0 ]; then - echo "No file path specified." - return - elif [ ! -f "$1" ]; then - echo "File path does not exist." - return - fi - - uri="http://bin.christitus.com/documents" - response=$(curl -s -X POST -d @"$1" "$uri") - if [ $? -eq 0 ]; then - hasteKey=$(echo $response | jq -r '.key') - echo "http://bin.christitus.com/$hasteKey" - else - echo "Failed to upload the document." - fi -} - -####################################################### -# Set the ultimate amazing command prompt -####################################################### - -alias hug="systemctl --user restart hugo" -alias lanm="systemctl --user restart lan-mouse" - -# Check if the shell is interactive -if [[ $- == *i* ]]; then - # Bind Ctrl+f to insert 'zi' followed by a newline - bind '"\C-f":"zi\n"' -fi - -export PATH=$PATH:"$HOME/.local/bin:$HOME/.cargo/bin:/var/lib/flatpak/exports/bin:/.local/share/flatpak/exports/bin" - -eval "$(starship init bash)" -eval "$(zoxide init bash)" - -if [[ -z $DISPLAY ]] && [[ $(tty) = /dev/tty1 ]]; then - -exec startx - -fi - - - - -eval "$(starship init bash)" - -# . "$HOME/.local/share/../bin/env" # Commented out - file doesn't exist - -# Added by LM Studio CLI (lms) -export PATH="$PATH:/home/nicholai/.lmstudio/bin" -# End of LM Studio CLI section - - -# Git shortcuts -alias gs='git status' -alias ga='git add' -alias gc='git commit -m' -alias gp='git push' -alias gl='git log --oneline' - -# Colorize man pages -export LESS_TERMCAP_mb=$'\e[1;32m' -export LESS_TERMCAP_md=$'\e[1;32m' -export LESS_TERMCAP_me=$'\e[0m' -export LESS_TERMCAP_se=$'\e[0m' -export LESS_TERMCAP_so=$'\e[01;33m' -export LESS_TERMCAP_ue=$'\e[0m' -export LESS_TERMCAP_us=$'\e[1;4;31m' - -alias ff='fastfetch' -alias nuke='sudo bash /home/nicholai/Documents/obsidian-vault/02_Areas/Nuke-monitoring/scripts/nuke_isolated.sh' -alias note='cd /mnt/work/dev/personal-projects/nicholai-work-2026 && pnpm notepad' -alias comfy='cd /home/nicholai/ComfyUI && source .venv/bin/activate && python main.py' -alias scripts='nvim .nuke/' - -# opencode -export PATH=/home/nicholai/.opencode/bin:$PATH - -# OpenRouter API Key for oh-my-opencode -export OPENROUTER_API_KEY="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" diff --git a/.gitignore b/.gitignore index ee8f337..6dd907d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -CLAUDE.md lazy-lock.json +tmp/ diff --git a/README.md b/README.md index cd3e411..7df5cdf 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,45 @@ -# Neovim Configuration +Neovim Configuration +=== -Modular Neovim setup for TypeScript/JavaScript development. +Modular Neovim setup. -## Installation +Installation +--- ```bash # Clone to config directory git clone ~/.config/nvim - -# Symlink dotfiles (optional) +# Run setup script (installs opencode, symlinks dotfiles, adds shell aliases) ./setup.sh - # Launch Neovim - plugins install automatically nvim ``` -## Features +New Features +--- -- LSP with TypeScript/JavaScript support -- Autocompletion and snippets -- Telescope fuzzy finder -- Treesitter syntax highlighting -- Format-on-save with Prettier +- AI-powered code generation via ThePrimeagen's agent plugin + - `fill_in_function`: generates function bodies from context + - visual mode: modify selected code with AI + - `stop_all_requests`: cancel pending AI operations + - supports SKILL.md and AGENT.md for custom rules -Leader key: `` +Features +--- + +This configuration provides LSP integration for TypeScript and +JavaScript with intelligent code navigation, autocompletion powered by +nvim-cmp with snippet expansion, and Telescope for fast fuzzy finding +across files, buffers, and content. Syntax highlighting uses Treesitter +for semantic understanding, and Prettier handles auto-formatting on +save. + +AI-powered development is available through ThePrimeagen's agent plugin. +Use `fill_in_function` to generate function implementations from +context, or select code in visual mode and transform it with natural +language prompts. Cancel pending operations with `stop_all_requests`. +Custom behavior can be defined via SKILL.md and AGENT.md files. + +Navigation uses `` as the leader key for all custom keybindings. +Fugitive handles git operations, Lualine provides status information, +and Neo-tree offers visual file management. diff --git a/docs/neovim-cheatsheet.md b/docs/neovim-cheatsheet.md index 7e115a6..a059bf3 100644 --- a/docs/neovim-cheatsheet.md +++ b/docs/neovim-cheatsheet.md @@ -117,6 +117,40 @@ - `Tab` - Next completion item - `Shift+Tab` - Previous completion item +### Commenting (Comment.nvim) +- `gcc` - Toggle comment on line +- `gc{motion}` - Toggle comment with motion (e.g., `gc3j` comments 3 lines down) +- `gbc` - Toggle block comment +- Visual mode: `gc` - Comment selection + +### Surround (nvim-surround) +- `ys{motion}{char}` - Add surround (e.g., `ysiw"` surrounds word with quotes) +- `ds{char}` - Delete surround (e.g., `ds"` removes quotes) +- `cs{old}{new}` - Change surround (e.g., `cs"'` changes `"` to `'`) +- Visual mode: `S{char}` - Surround selection + +### Harpoon (quick file switching) +- `Space+ha` - Add current file to harpoon +- `Space+hh` - Open harpoon menu +- `Space+1/2/3/4` - Jump to harpoon file 1-4 + +### Flash (supercharged motions) +- `s` - Flash jump (type chars to jump to) +- `S` - Flash treesitter select + +### Diagnostics (Trouble) +- `Space+xx` - Toggle diagnostics panel +- `Space+xX` - Buffer diagnostics only +- `Space+xl` - Location list +- `Space+xq` - Quickfix list + +### Theme Switcher +- `Space+th` - Open theme picker (pywal, kanagawa variants, or pick new wallpaper) + +### Utilities +- `Space+u` - Toggle undo tree +- `Space+ft` - Find TODOs in project + ## Useful Tips - **Repeat actions**: Number before command (e.g., `5dd` deletes 5 lines) - **Combine motions**: `d3w` deletes 3 words, `y2j` yanks 2 lines down @@ -150,4 +184,4 @@ - System clipboard integration: Just yank normally with `y` - it copies to system clipboard! (You have `clipboard=unnamedplus` set) --- -*Last updated: November 2025* +*Last updated: February 2026* diff --git a/.tmux.conf b/dotfiles/.tmux.conf similarity index 53% rename from .tmux.conf rename to dotfiles/.tmux.conf index 033012b..9fc105e 100644 --- a/.tmux.conf +++ b/dotfiles/.tmux.conf @@ -1,34 +1,40 @@ + +# Terminal settings set -g default-terminal "tmux-256color" set-option -g status-position top -#keybinds -unbind r + +# Keybinds +unbind r bind r source-file ~/.tmux.conf \; display "reloaded-config" unbind C-b set -g prefix C-w -#preferences + +# Preferences set -g mouse on -set-option -g status-position top -set -g base-index 1 +set -g base-index 1 set -g pane-base-index 1 set -g repeat-time 1000 -set -g history-limit 10000 -#window status +set -g history-limit 10000 + +# Window status set -g window-status-format " #I " -set -g window-status-current-format " #I " +set -g window-status-current-format " #I " set -g window-status-bell-style "bg=red,nobold" -set -g window-status-current-style \ - "#{?window_zoomed_flag,bg=yellow,bg=magenta,nobold}" -#pane separators +set -g window-status-current-style "#{?window_zoomed_flag,bg=yellow,bg=magenta,nobold}" + +# Pane separators set -g pane-border-lines simple -# vim keybinds for navigation -bind-key h select-pane -L -bind-key j select-pane -D -bind-key k select-pane -U -bind-key l select-pane -R -#plugins + +# Vim keybinds for navigation +bind-key h select-pane -L +bind-key j select-pane -D +bind-key k select-pane -U +bind-key l select-pane -R + +# Plugins set -g @plugin 'tmux-plugins/tpm' set -g @plugin 'tmux-plugins/tmux-sensible' -#catpuccin theme + +# Catppuccin theme run ~/.config/tmux/plugins/catppuccin/tmux/catppuccin.tmux run '~/.tmux/plugins/tpm/tpm' - diff --git a/starship.toml b/dotfiles/starship.toml similarity index 89% rename from starship.toml rename to dotfiles/starship.toml index 77efcf4..9968e85 100644 --- a/starship.toml +++ b/dotfiles/starship.toml @@ -1,7 +1,7 @@ # Catppuccin Mocha theme to match nvim format = """ -[┌─](bold blue)$directory$git_branch$git_status -[└─](bold blue)$character""" +[╭─](bold blue)$directory$git_branch$git_status +[╰─](bold blue)$character""" [character] success_symbol = "[➜](bold green)" diff --git a/lazy-lock.json b/lazy-lock.json index 9b8e931..a30a67b 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -1,27 +1,38 @@ { - "LuaSnip": { "branch": "master", "commit": "ccf25a5452b8697a823de3e5ecda63ed3d723b79" }, + "99": { "branch": "master", "commit": "0fb3b8b2d032289ea7088a37161e1c50bdfccfa9" }, + "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, + "LuaSnip": { "branch": "master", "commit": "dae4f5aaa3574bd0c2b9dd20fb9542a02c10471c" }, "alpha-nvim": { "branch": "main", "commit": "3979b01cb05734331c7873049001d3f2bb8477f4" }, "cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" }, - "cmp-nvim-lsp": { "branch": "main", "commit": "bd5a7d6db125d4654b50eeae9f5217f24bb22fd3" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" }, "cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" }, "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, - "conform.nvim": { "branch": "master", "commit": "235dd79731c1dc51ec04abb4045cbc54727a172a" }, + "conform.nvim": { "branch": "master", "commit": "c2526f1cde528a66e086ab1668e996d162c75f4f" }, "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, - "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, - "gitsigns.nvim": { "branch": "main", "commit": "42d6aed4e94e0f0bbced16bbdcc42f57673bd75e" }, + "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, + "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, + "gitsigns.nvim": { "branch": "main", "commit": "1ce96a464fdbc24208e24c117e2021794259005d" }, + "harpoon": { "branch": "harpoon2", "commit": "87b1a3506211538f460786c23f98ec63ad9af4e5" }, + "indent-blankline.nvim": { "branch": "master", "commit": "005b56001b2cb30bfa61b7986bc50657816ba4ba" }, "kanagawa": { "branch": "master", "commit": "aef7f5cec0a40dbe7f3304214850c472e2264b10" }, - "lazy.nvim": { "branch": "main", "commit": "1ea3c4085785f460fb0e46d2fe1ee895f5f9e7c1" }, - "lualine.nvim": { "branch": "master", "commit": "3946f0122255bc377d14a59b27b609fb3ab25768" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "2304ff65ecc8cb2afc2484de3e2ed9a407edf0b9" }, - "mason.nvim": { "branch": "main", "commit": "ad7146aa61dcaeb54fa900144d768f040090bff0" }, - "nvim-cmp": { "branch": "main", "commit": "a7bcf1d88069fc67c9ace8a62ba480b8fe879025" }, - "nvim-colorizer.lua": { "branch": "master", "commit": "51cf7c995ed1eb6642aecf19067ee634fa1b6ba2" }, - "nvim-lspconfig": { "branch": "master", "commit": "e5c61b02f33b5c6538be25b2696b33b4cc91e667" }, - "nvim-tree.lua": { "branch": "master", "commit": "64e2192f5250796aa4a7f33c6ad888515af50640" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "ae609525ddf01c153c39305730b1791800ffe4fe" }, + "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, + "nvim-autopairs": { "branch": "master", "commit": "59bce2eef357189c3305e25bc6dd2d138c1683f5" }, + "nvim-cmp": { "branch": "main", "commit": "da88697d7f45d16852c6b2769dc52387d1ddc45f" }, + "nvim-colorizer.lua": { "branch": "master", "commit": "338409dd8a6ed74767bad3eb5269f1b903ffb3cf" }, + "nvim-lspconfig": { "branch": "master", "commit": "0480b120318ec8bab27b530ffab6ee76a8c4d806" }, + "nvim-surround": { "branch": "main", "commit": "1098d7b3c34adcfa7feb3289ee434529abd4afd1" }, + "nvim-tree.lua": { "branch": "master", "commit": "037d89e60fb01a6c11a48a19540253b8c72a3c32" }, "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, - "nvim-web-devicons": { "branch": "master", "commit": "b8221e42cf7287c4dcde81f232f58d7b947c210d" }, + "nvim-web-devicons": { "branch": "master", "commit": "746ffbb17975ebd6c40142362eee1b0249969c5c" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, - "telescope.nvim": { "branch": "master", "commit": "b4da76be54691e854d3e0e02c36b0245f945c2c7" }, - "typescript-tools.nvim": { "branch": "master", "commit": "bf11d98ad5736e1cbc1082ca9a03196d45c701f1" }, + "pywal": { "branch": "main", "commit": "d11b673c0e3d6eb8cbee7ea8cf4a8911f6ee24b9" }, + "telescope.nvim": { "branch": "master", "commit": "ad7d9580338354ccc136e5b8f0aa4f880434dcdc" }, + "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, + "typescript-tools.nvim": { "branch": "master", "commit": "c2f5910074103705661e9651aa841e0d7eea9932" }, + "undotree": { "branch": "master", "commit": "fc28931fbfba66ab75d9af23fe46ffbbb9de6e8c" }, "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } } diff --git a/lua/plugins/ai.lua b/lua/plugins/ai.lua new file mode 100644 index 0000000..a8f68ba --- /dev/null +++ b/lua/plugins/ai.lua @@ -0,0 +1,95 @@ +return { + -- AI agent (99) + { + "ThePrimeagen/99", + config = function() + local _99 = require("99") + local Providers = require("99.providers") + local cwd = vim.uv.cwd() + local basename = vim.fs.basename(cwd) + + -- custom provider with --attach flag for tool use + local CustomOpenCodeProvider = setmetatable({}, { + __index = Providers.OpenCodeProvider + }) + + function CustomOpenCodeProvider._build_command(_, query, request) + return { + "opencode", "run", + "--attach", "http://localhost:4096", + "-m", request.context.model, + query + } + end + + _99.setup({ + -- Auto-detect provider: OpenCode with server if available, else Claude Code + provider = (function() + -- Check if opencode is installed + local opencode_installed = vim.fn.executable("opencode") == 1 + if not opencode_installed then + return Providers.ClaudeCodeProvider + end + + -- Check if opencode serve is running on port 4096 + local handle = io.popen("curl -s -o /dev/null -w '%{http_code}' http://localhost:4096/health 2>/dev/null || echo '000'") + local result = handle:read("*a") + handle:close() + + -- If server is responding (any 2xx or 404), use CustomOpenCodeProvider + if result:match("^[24]%d%d") then + return Providers.CustomOpenCodeProvider + end + + -- Fallback to Claude Code + return Providers.ClaudeCodeProvider + end)(), + model = (function() + -- Use appropriate model format based on provider + local opencode_installed = vim.fn.executable("opencode") == 1 + if opencode_installed then + local handle = io.popen("curl -s -o /dev/null -w '%{http_code}' http://localhost:4096/health 2>/dev/null || echo '000'") + local result = handle:read("*a") + handle:close() + if result:match("^[24]%d%d") then + return "anthropic/claude-sonnet-4-5" + end + end + return "claude-sonnet-4-5" + end)(), + + logger = { + level = _99.DEBUG, + path = "/tmp/" .. basename .. ".99.debug", + print_on_error = true, + }, + + completion = { + -- custom_rules = { "~/.config/nvim/rules/" }, + source = "cmp", + }, + + md_files = { + "AGENT.md", + "CLAUDE.md", + }, + }) + + vim.keymap.set("n", "9f", function() + _99.fill_in_function() + end, { desc = "99: Fill function" }) + + vim.keymap.set("v", "9v", function() + _99.visual() + end, { desc = "99: Visual AI" }) + + vim.keymap.set("v", "9p", function() + _99.visual_prompt() + end, { desc = "99: Visual with prompt" }) + + vim.keymap.set("v", "9s", function() + _99.stop_all_requests() + end, { desc = "99: Stop requests" }) + end, + }, +} diff --git a/lua/plugins/colorscheme.lua b/lua/plugins/colorscheme.lua new file mode 100644 index 0000000..00e15dd --- /dev/null +++ b/lua/plugins/colorscheme.lua @@ -0,0 +1,123 @@ +return { + -- Kanagawa colorscheme + { + "rebelot/kanagawa.nvim", + name = "kanagawa", + lazy = false, + priority = 1000, + config = function() + require('kanagawa').setup({ + compile = true, + undercurl = true, + commentStyle = { italic = true }, + functionStyle = {}, + keywordStyle = { italic = true }, + statementStyle = { bold = true }, + typeStyle = {}, + transparent = false, + dimInactive = false, + terminalColors = true, + colors = { + palette = {}, + theme = { wave = {}, lotus = {}, dragon = {}, all = {} }, + }, + overrides = function(colors) + return {} + end, + theme = "wave", + background = { + dark = "wave", + light = "lotus" + }, + }) + -- only set kanagawa if pywal colors don't exist + if vim.fn.filereadable(vim.fn.expand("~/.cache/wal/colors")) == 0 then + vim.cmd("colorscheme kanagawa") + end + end, + }, + + -- Pywal colorscheme (syncs with terminal) + { + "AlphaTechnolog/pywal.nvim", + name = "pywal", + lazy = false, + priority = 1000, + config = function() + -- auto-load pywal if colors exist + if vim.fn.filereadable(vim.fn.expand("~/.cache/wal/colors")) == 1 then + vim.cmd("colorscheme pywal") + end + end, + }, + + -- Theme switcher + { + "nvim-telescope/telescope.nvim", + keys = { + { + "th", + function() + local pickers = require("telescope.pickers") + local finders = require("telescope.finders") + local conf = require("telescope.config").values + local actions = require("telescope.actions") + local action_state = require("telescope.actions.state") + + local themes = { + { name = "pywal (from wallpaper)", value = "pywal" }, + { name = "Pick new wallpaper...", value = "_wallpaper_picker" }, + { name = "kanagawa", value = "kanagawa" }, + { name = "kanagawa-wave", value = "kanagawa-wave" }, + { name = "kanagawa-dragon", value = "kanagawa-dragon" }, + { name = "kanagawa-lotus", value = "kanagawa-lotus" }, + } + + pickers.new({}, { + prompt_title = "Theme Switcher", + finder = finders.new_table({ + results = themes, + entry_maker = function(entry) + return { + value = entry.value, + display = entry.name, + ordinal = entry.name, + } + end, + }), + sorter = conf.generic_sorter({}), + attach_mappings = function(prompt_bufnr, map) + actions.select_default:replace(function() + actions.close(prompt_bufnr) + local selection = action_state.get_selected_entry() + if selection.value == "_wallpaper_picker" then + -- launch wallpaper picker, then reload pywal + vim.fn.jobstart( + { "bash", "-c", "~/scripts/pywal/wallpapermenu.sh && sleep 1" }, + { + on_exit = function() + vim.schedule(function() + vim.cmd("colorscheme pywal") + require("lualine").setup({ options = { theme = "pywal" } }) + vim.notify("Pywal theme applied", vim.log.levels.INFO) + end) + end, + } + ) + else + vim.cmd("colorscheme " .. selection.value) + -- update lualine theme + local lualine_theme = selection.value:match("^kanagawa") and "kanagawa" or selection.value + require("lualine").setup({ options = { theme = lualine_theme } }) + vim.notify("Theme: " .. selection.value, vim.log.levels.INFO) + end + end) + return true + end, + }):find() + end, + desc = "Theme switcher", + }, + }, + }, +} diff --git a/lua/plugins/completion.lua b/lua/plugins/completion.lua new file mode 100644 index 0000000..952591a --- /dev/null +++ b/lua/plugins/completion.lua @@ -0,0 +1,35 @@ +return { + -- Autocompletion + { + "hrsh7th/nvim-cmp", + dependencies = { + "hrsh7th/cmp-buffer", + "hrsh7th/cmp-path", + "hrsh7th/cmp-nvim-lsp", + "L3MON4D3/LuaSnip", + "saadparwaiz1/cmp_luasnip", + "rafamadriz/friendly-snippets", + }, + config = function() + local cmp = require("cmp") + local luasnip = require("luasnip") + require("luasnip.loaders.from_vscode").lazy_load() + + cmp.setup({ + snippet = { expand = function(args) luasnip.lsp_expand(args.body) end }, + mapping = cmp.mapping.preset.insert({ + [""] = cmp.mapping.complete(), + [""] = cmp.mapping.confirm({ select = true }), + [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping.select_prev_item(), + }), + sources = { + { name = "nvim_lsp" }, + { name = "path" }, + { name = "buffer" }, + { name = "luasnip" }, + }, + }) + end, + }, +} diff --git a/lua/plugins/editor.lua b/lua/plugins/editor.lua new file mode 100644 index 0000000..b438057 --- /dev/null +++ b/lua/plugins/editor.lua @@ -0,0 +1,48 @@ +return { + -- Commenting + { + "numToStr/Comment.nvim", + event = { "BufReadPre", "BufNewFile" }, + opts = {}, + }, + + -- Surround text objects + { + "kylechui/nvim-surround", + version = "*", + event = "VeryLazy", + opts = {}, + }, + + -- Flash motions + { + "folke/flash.nvim", + event = "VeryLazy", + opts = {}, + keys = { + { "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" }, + { "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" }, + }, + }, + + -- Auto-pairs + { + "windwp/nvim-autopairs", + event = "InsertEnter", + opts = { + check_ts = true, + ts_config = { + lua = { "string", "source" }, + javascript = { "string", "template_string" }, + typescript = { "string", "template_string" }, + }, + disable_filetype = { "TelescopePrompt", "spectre_panel" }, + }, + config = function(_, opts) + require("nvim-autopairs").setup(opts) + local cmp_autopairs = require("nvim-autopairs.completion.cmp") + local cmp = require("cmp") + cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done()) + end, + }, +} diff --git a/lua/plugins/git.lua b/lua/plugins/git.lua new file mode 100644 index 0000000..44b15d2 --- /dev/null +++ b/lua/plugins/git.lua @@ -0,0 +1,42 @@ +return { + -- Git signs + { + "lewis6991/gitsigns.nvim", + event = { "BufReadPre", "BufNewFile" }, + config = function() + require("gitsigns").setup({ + on_attach = function(bufnr) + local gs = package.loaded.gitsigns + local map = function(mode, l, r, opts) + opts = opts or {} + opts.buffer = bufnr + vim.keymap.set(mode, l, r, opts) + end + -- Navigation + map("n", "]c", function() gs.next_hunk() end, { desc = "Next hunk" }) + map("n", "[c", function() gs.prev_hunk() end, { desc = "Previous hunk" }) + -- Actions + map("n", "gs", gs.stage_hunk, { desc = "Stage hunk" }) + map("n", "gr", gs.reset_hunk, { desc = "Reset hunk" }) + map("n", "gS", gs.stage_buffer, { desc = "Stage buffer" }) + map("n", "gu", gs.undo_stage_hunk, { desc = "Undo stage" }) + map("n", "gp", gs.preview_hunk, { desc = "Preview hunk" }) + map("n", "gb", function() gs.blame_line({ full = true }) end, { desc = "Blame line" }) + map("n", "gd", gs.diffthis, { desc = "Diff this" }) + end, + }) + end, + }, + + -- Diff view + { + "sindrets/diffview.nvim", + cmd = { "DiffviewOpen", "DiffviewFileHistory" }, + keys = { + { "gv", "DiffviewOpen", desc = "Diff view" }, + { "gh", "DiffviewFileHistory %", desc = "File history" }, + { "gx", "DiffviewClose", desc = "Close diff" }, + }, + config = true, + }, +} diff --git a/lua/plugins/lsp.lua b/lua/plugins/lsp.lua new file mode 100644 index 0000000..df99cdd --- /dev/null +++ b/lua/plugins/lsp.lua @@ -0,0 +1,45 @@ +return { + -- Mason (LSP installer) + { + "williamboman/mason.nvim", + build = ":MasonUpdate", + config = true, + }, + + -- Mason LSP config bridge + { + "williamboman/mason-lspconfig.nvim", + dependencies = { "williamboman/mason.nvim" }, + config = function() + require("mason-lspconfig").setup({ + ensure_installed = { "ts_ls", "eslint", "jsonls", "html", "cssls", "tailwindcss" }, + }) + end, + }, + + -- LSP config + { + "neovim/nvim-lspconfig", + dependencies = { + "williamboman/mason.nvim", + "williamboman/mason-lspconfig.nvim", + "hrsh7th/cmp-nvim-lsp", + }, + }, + + -- TypeScript tools + { + "pmizio/typescript-tools.nvim", + dependencies = { "nvim-lua/plenary.nvim", "neovim/nvim-lspconfig" }, + config = function() + require("typescript-tools").setup({ + settings = { + tsserver_file_preferences = { + includeInlayParameterNameHints = "all", + includeCompletionsForModuleExports = true + }, + }, + }) + end, + }, +} diff --git a/lua/plugins/navigation.lua b/lua/plugins/navigation.lua new file mode 100644 index 0000000..05d34f1 --- /dev/null +++ b/lua/plugins/navigation.lua @@ -0,0 +1,28 @@ +return { + -- Quick file navigation + { + "ThePrimeagen/harpoon", + branch = "harpoon2", + dependencies = { "nvim-lua/plenary.nvim" }, + config = function() + local harpoon = require("harpoon") + harpoon:setup() + + vim.keymap.set("n", "ha", function() harpoon:list():add() end, { desc = "Harpoon add" }) + vim.keymap.set("n", "hh", function() harpoon.ui:toggle_quick_menu(harpoon:list()) end, { desc = "Harpoon menu" }) + vim.keymap.set("n", "1", function() harpoon:list():select(1) end, { desc = "Harpoon 1" }) + vim.keymap.set("n", "2", function() harpoon:list():select(2) end, { desc = "Harpoon 2" }) + vim.keymap.set("n", "3", function() harpoon:list():select(3) end, { desc = "Harpoon 3" }) + vim.keymap.set("n", "4", function() harpoon:list():select(4) end, { desc = "Harpoon 4" }) + end, + }, + + -- File explorer + { + "nvim-tree/nvim-tree.lua", + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = function() + require("nvim-tree").setup() + end, + }, +} diff --git a/lua/plugins/plugin.lua b/lua/plugins/plugin.lua deleted file mode 100644 index 4c2eb8f..0000000 --- a/lua/plugins/plugin.lua +++ /dev/null @@ -1,275 +0,0 @@ -return { - -- Color scheme - { - "rebelot/kanagawa.nvim", - name = "kanagawa", - priority = 1000, - config = function() - require('kanagawa').setup({ - compile = true, -- enable compiling the colorscheme - undercurl = true, -- enable undercurls - commentStyle = { italic = true }, - functionStyle = {}, - keywordStyle = { italic = true }, - statementStyle = { bold = true }, - typeStyle = {}, - transparent = false, -- do not set background color - dimInactive = false, -- dim inactive window `:h hl-NormalNC` - terminalColors = true, -- define vim.g.terminal_color_{0,17} - colors = { -- add/modify theme and palette colors - palette = {}, - theme = { wave = {}, lotus = {}, dragon = {}, all = {} }, - }, - overrides = function(colors) -- add/modify highlights - return {} - end, - theme = "wave", -- Load "wave" theme - background = { -- map the value of 'background' option to a theme - dark = "wave", -- try "dragon" ! - light = "lotus" - }, - }) - vim.cmd("colorscheme kanagawa") - end, - }, - - -- File explorer - { - "nvim-tree/nvim-tree.lua", - dependencies = { "nvim-tree/nvim-web-devicons" }, - config = function() - require("nvim-tree").setup() - end, - }, - - -- Git signs - { - "lewis6991/gitsigns.nvim", - event = { "BufReadPre", "BufNewFile" }, - config = function() - require("gitsigns").setup({ - on_attach = function(bufnr) - local gs = package.loaded.gitsigns - local map = function(mode, l, r, opts) - opts = opts or {} - opts.buffer = bufnr - vim.keymap.set(mode, l, r, opts) - end - -- Navigation - map("n", "]c", function() gs.next_hunk() end, { desc = "Next hunk" }) - map("n", "[c", function() gs.prev_hunk() end, { desc = "Previous hunk" }) - -- Actions - map("n", "gs", gs.stage_hunk, { desc = "Stage hunk" }) - map("n", "gr", gs.reset_hunk, { desc = "Reset hunk" }) - map("n", "gS", gs.stage_buffer, { desc = "Stage buffer" }) - map("n", "gu", gs.undo_stage_hunk, { desc = "Undo stage" }) - map("n", "gp", gs.preview_hunk, { desc = "Preview hunk" }) - map("n", "gb", function() gs.blame_line({ full = true }) end, { desc = "Blame line" }) - map("n", "gd", gs.diffthis, { desc = "Diff this" }) - end, - }) - end, - }, - - -- Diff view - { - "sindrets/diffview.nvim", - cmd = { "DiffviewOpen", "DiffviewFileHistory" }, - keys = { - { "gv", "DiffviewOpen", desc = "Diff view" }, - { "gh", "DiffviewFileHistory %", desc = "File history" }, - { "gx", "DiffviewClose", desc = "Close diff" }, - }, - config = true, - }, - - -- Fuzzy finder - { - "nvim-telescope/telescope.nvim", - dependencies = { "nvim-lua/plenary.nvim" }, - config = function() - require("telescope").setup() - end, - }, - - -- Formatter - { - "stevearc/conform.nvim", - opts = { - format_on_save = { timeout_ms = 1000, lsp_fallback = true }, - formatters_by_ft = { - javascript = { "prettierd", "prettier" }, - javascriptreact = { "prettierd", "prettier" }, - typescript = { "prettierd", "prettier" }, - typescriptreact = { "prettierd", "prettier" }, - json = { "prettierd", "prettier" }, - css = { "prettierd", "prettier" }, - html = { "prettierd", "prettier" }, - markdown = { "prettierd", "prettier" }, - }, - }, - }, - - -- Syntax highlighting - { - "nvim-treesitter/nvim-treesitter", - build = ":TSUpdate", - config = function() - require("nvim-treesitter.configs").setup({ - ensure_installed = { - "lua", "vim", "bash", "javascript", "typescript", "tsx", "json", "yaml", "html", "css", "prisma", - "graphql" - }, - highlight = { enable = true }, - indent = { enable = true }, - }) - end, - }, - - -- Autocompletion - { - "hrsh7th/nvim-cmp", - dependencies = { - "hrsh7th/cmp-buffer", - "hrsh7th/cmp-path", - "hrsh7th/cmp-nvim-lsp", - "L3MON4D3/LuaSnip", - "saadparwaiz1/cmp_luasnip", - "rafamadriz/friendly-snippets", - }, - config = function() - local cmp = require("cmp") - local luasnip = require("luasnip") - require("luasnip.loaders.from_vscode").lazy_load() - - cmp.setup({ - snippet = { expand = function(args) luasnip.lsp_expand(args.body) end }, - mapping = cmp.mapping.preset.insert({ - [""] = cmp.mapping.complete(), - [""] = cmp.mapping.confirm({ select = true }), - [""] = cmp.mapping.select_next_item(), - [""] = cmp.mapping.select_prev_item(), - }), - sources = { - { name = "nvim_lsp" }, - { name = "path" }, - { name = "buffer" }, - { name = "luasnip" }, - }, - }) - end, - }, - - -- LSP - { - "williamboman/mason.nvim", - build = ":MasonUpdate", - config = true, - }, - { - "williamboman/mason-lspconfig.nvim", - dependencies = { "williamboman/mason.nvim" }, - config = function() - require("mason-lspconfig").setup({ - ensure_installed = { "ts_ls", "eslint", "jsonls", "html", "cssls", "tailwindcss" }, - }) - end, - }, - { - "neovim/nvim-lspconfig", - dependencies = { - "williamboman/mason.nvim", - "williamboman/mason-lspconfig.nvim", - "hrsh7th/cmp-nvim-lsp", - }, - }, - { - "pmizio/typescript-tools.nvim", - dependencies = { "nvim-lua/plenary.nvim", "neovim/nvim-lspconfig" }, - config = function() - require("typescript-tools").setup({ - settings = { - tsserver_file_preferences = { - includeInlayParameterNameHints = "all", - includeCompletionsForModuleExports = true - }, - }, - }) - end, - }, - - -- Colorizer - { - "NvChad/nvim-colorizer.lua", - opts = { user_default_options = { names = false } } - }, - - -- Status line - { - "nvim-lualine/lualine.nvim", - dependencies = { "nvim-tree/nvim-web-devicons" }, - config = function() - require("lualine").setup({ - options = { theme = "kanagawa" }, - }) - end, - }, - - -- Which-key - { - "folke/which-key.nvim", - event = "VeryLazy", - config = function() - local wk = require("which-key") - wk.setup({ - preset = "modern", - }) - - wk.add({ - { "e", desc = "Toggle file explorer" }, - { "f", group = "Find" }, - { "ff", desc = "Find files" }, - { "fg", desc = "Live grep" }, - { "fb", desc = "Find buffers" }, - { "g", group = "Git" }, - { "w", desc = "Save" }, - { "q", desc = "Quit" }, - }) - end, - }, - - -- Alpha (dashboard) - { - "goolord/alpha-nvim", - config = function() - local alpha = require('alpha') - local dashboard = require("alpha.themes.dashboard") - dashboard.section.header.val = { - [[ ^ ^ ^ ^☆ ★ ☆ ___I_☆ ★ ☆ ^ ^ ^ ^ ^ ^ ^ ]], - [[ /|\/|\/|\ /|\ ★☆ /\-_--\ ☆ ★/|\/|\ /|\/|\/|\ /|\/|\ ]], - [[ /|\/|\/|\ /|\ ★ / \_-__\☆ ★/|\/|\ /|\/|\/|\ /|\/|\ ]], - [[ /|\/|\/|\ /|\ 󰻀 |[]| [] | 󰻀 /|\/|\ /|\/|\/|\ /|\/|\ ]], - } - - dashboard.section.buttons.val = { - dashboard.button("e", " New file", ":ene startinsert "), - dashboard.button("f", "󰍉 Find file", ":lua require('fzf-lua').files() "), - dashboard.button("t", " Browse cwd", ":NvimTreeOpen"), - dashboard.button("r", " Browse src", ":e ~/.local/src/"), - dashboard.button("s", "󰯂 Browse scripts", ":e ~/scripts/"), - dashboard.button("c", " Config", ":e ~/.config/nvim/"), - dashboard.button("m", " Mappings", ":e ~/.config/nvim/lua/core/keymaps.lua"), - dashboard.button("p", " Plugins", ":PlugInstall"), - dashboard.button("q", "󰅙 Quit", ":q!"), - } - - dashboard.section.footer.val = function() - return vim.g.startup_time_ms or "[[ ]]" - end - - dashboard.section.buttons.opts.hl = "Keyword" - dashboard.opts.opts.noautocmd = true - alpha.setup(dashboard.opts) - end, - }, -} diff --git a/lua/plugins/telescope.lua b/lua/plugins/telescope.lua new file mode 100644 index 0000000..bccc7eb --- /dev/null +++ b/lua/plugins/telescope.lua @@ -0,0 +1,10 @@ +return { + -- Fuzzy finder + { + "nvim-telescope/telescope.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + config = function() + require("telescope").setup() + end, + }, +} diff --git a/lua/plugins/tools.lua b/lua/plugins/tools.lua new file mode 100644 index 0000000..81ad801 --- /dev/null +++ b/lua/plugins/tools.lua @@ -0,0 +1,53 @@ +return { + -- Diagnostics list + { + "folke/trouble.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + cmd = "Trouble", + keys = { + { "xx", "Trouble diagnostics toggle", desc = "Diagnostics" }, + { "xX", "Trouble diagnostics toggle filter.buf=0", desc = "Buffer diagnostics" }, + { "xl", "Trouble loclist toggle", desc = "Location list" }, + { "xq", "Trouble qflist toggle", desc = "Quickfix list" }, + }, + opts = {}, + }, + + -- TODO comments + { + "folke/todo-comments.nvim", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { "nvim-lua/plenary.nvim" }, + opts = {}, + keys = { + { "ft", "TodoTelescope", desc = "Find TODOs" }, + }, + }, + + -- Undo tree + { + "mbbill/undotree", + cmd = "UndotreeToggle", + keys = { + { "u", "UndotreeToggle", desc = "Toggle undotree" }, + }, + }, + + -- Formatter + { + "stevearc/conform.nvim", + opts = { + format_on_save = { timeout_ms = 1000, lsp_fallback = true }, + formatters_by_ft = { + javascript = { "prettierd", "prettier" }, + javascriptreact = { "prettierd", "prettier" }, + typescript = { "prettierd", "prettier" }, + typescriptreact = { "prettierd", "prettier" }, + json = { "prettierd", "prettier" }, + css = { "prettierd", "prettier" }, + html = { "prettierd", "prettier" }, + markdown = { "prettierd", "prettier" }, + }, + }, + }, +} diff --git a/lua/plugins/treesitter.lua b/lua/plugins/treesitter.lua new file mode 100644 index 0000000..7ac2272 --- /dev/null +++ b/lua/plugins/treesitter.lua @@ -0,0 +1,17 @@ +return { + -- Syntax highlighting + { + "nvim-treesitter/nvim-treesitter", + build = ":TSUpdate", + config = function() + require("nvim-treesitter.configs").setup({ + ensure_installed = { + "lua", "vim", "bash", "javascript", "typescript", "tsx", "json", "yaml", "html", "css", "prisma", + "graphql" + }, + highlight = { enable = true }, + indent = { enable = true }, + }) + end, + }, +} diff --git a/lua/plugins/ui.lua b/lua/plugins/ui.lua new file mode 100644 index 0000000..9110bee --- /dev/null +++ b/lua/plugins/ui.lua @@ -0,0 +1,101 @@ +return { + -- Status line + { + "nvim-lualine/lualine.nvim", + dependencies = { + "nvim-tree/nvim-web-devicons", + "rebelot/kanagawa.nvim", + }, + config = function() + require("lualine").setup({ + options = { theme = "kanagawa" }, + }) + end, + }, + + -- Alpha (dashboard) + { + "goolord/alpha-nvim", + config = function() + local alpha = require('alpha') + local dashboard = require("alpha.themes.dashboard") + dashboard.section.header.val = { + [[ ██╗ ██╗███████╗ ██████╗ ███████╗███████╗██╗ ██████╗ ███╗ ██╗ ]], + [[ ██║ ██║╚════██║ ██╔══██╗██╔════╝██╔════╝██║██╔════╝ ████╗ ██║ ]], + [[ ██║ ██║ ██╔╝ ██║ ██║█████╗ ███████╗██║██║ ███╗██╔██╗ ██║ ]], + [[ ╚██╗ ██╔╝ ██╔╝ ██║ ██║██╔══╝ ╚════██║██║██║ ██║██║╚██╗██║ ]], + [[ ╚████╔╝ ██║ ██████╔╝███████╗███████║██║╚██████╔╝██║ ╚████║ ]], + [[ ╚═══╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ]], + } + dashboard.section.buttons.val = { + dashboard.button("e", " New file", ":ene startinsert "), + dashboard.button("f", "󰍉 Find file", ":lua require('fzf-lua').files() "), + dashboard.button("t", " Browse cwd", ":NvimTreeOpen"), + dashboard.button("r", " Browse src", ":e ~/.local/src/"), + dashboard.button("s", "󰯂 Browse scripts", ":e ~/scripts/"), + dashboard.button("c", " Config", ":e ~/.config/nvim/"), + dashboard.button("m", " Mappings", ":e ~/.config/nvim/lua/core/keymaps.lua"), + dashboard.button("p", " Plugins", ":PlugInstall"), + dashboard.button("q", "󰅙 Quit", ":q!"), + } + + dashboard.section.footer.val = function() + return vim.g.startup_time_ms or "[[ ]]" + end + + dashboard.section.buttons.opts.hl = "Keyword" + dashboard.opts.opts.noautocmd = true + alpha.setup(dashboard.opts) + end, + }, + + -- Which-key + { + "folke/which-key.nvim", + event = "VeryLazy", + config = function() + local wk = require("which-key") + wk.setup({ + preset = "modern", + }) + + wk.add({ + { "e", desc = "Toggle file explorer" }, + { "f", group = "Find" }, + { "ff", desc = "Find files" }, + { "fg", desc = "Live grep" }, + { "fb", desc = "Find buffers" }, + { "ft", desc = "Find TODOs" }, + { "g", group = "Git" }, + { "h", group = "Harpoon" }, + { "t", group = "Theme" }, + { "th", desc = "Theme switcher" }, + { "x", group = "Trouble" }, + { "w", desc = "Save" }, + { "q", desc = "Quit" }, + { "u", desc = "Undo tree" }, + { "9", group = "AI (99)" }, + { "9f", desc = "Fill Function" }, + { "9v", desc = "Visual AI" }, + { "9s", desc = "Stop requests" }, + }) + end, + }, + + -- Colorizer + { + "NvChad/nvim-colorizer.lua", + opts = { user_default_options = { names = false } } + }, + + -- Indent guides + { + "lukas-reineke/indent-blankline.nvim", + main = "ibl", + event = { "BufReadPre", "BufNewFile" }, + opts = { + indent = { char = "│" }, + scope = { enabled = true }, + }, + }, +} diff --git a/setup.sh b/setup.sh index 48f973a..e94c169 100755 --- a/setup.sh +++ b/setup.sh @@ -1,4 +1,158 @@ #!/bin/bash -# setup.sh -ln -sf ~/.config/nvim/.tmux.conf ~/.tmux.conf -ln -sf ~/.config/nvim/starship.toml ~/.config/starship.toml + +# This script sets up dotfiles and installs opencode: +# - Backs up and symlinks .tmux.conf from dotfiles/ to ~/ +# - Backs up and symlinks starship.toml from dotfiles/ to ~/.config/ +# - Installs opencode CLI if not already present + +# Check and backup/symlink .tmux.conf +if [ -f ~/.tmux.conf ] || [ -L ~/.tmux.conf ]; then + cp ~/.tmux.conf ~/.tmux.conf.backup + ln -sf ~/.config/nvim/dotfiles/.tmux.conf ~/.tmux.conf +elif [ -f ~/.config/nvim/.tmux.conf ]; then + cp ~/.config/nvim/dotfiles/.tmux.conf ~/.tmux.conf +fi + +# Check and backup/symlink starship.toml +if [ -f ~/.config/starship.toml ] || [ -L ~/.config/starship.toml ]; then + cp ~/.config/starship.toml ~/.config/starship.toml.backup + ln -sf ~/.config/nvim/dotfiles/starship.toml ~/.config/starship.toml +elif [ -f ~/.config/nvim/starship.toml ]; then + mkdir -p ~/.config + cp ~/.config/nvim/dotfiles/starship.toml ~/.config/starship.toml +fi + +# Check if opencode is installed, if not, install opencode +if ! command -v opencode &> /dev/null; then + curl -fsSL https://opencode.ai/install | bash +fi + +# Detect shell config file +SHELL_RC="" +if [ -f ~/.zshrc ]; then + SHELL_RC=~/.zshrc +elif [ -f ~/.bashrc ]; then + SHELL_RC=~/.bashrc +fi + +# Only proceed if we found a shell config +if [ -n "$SHELL_RC" ]; then + # Create a temporary file with all our aliases and functions + TEMP_ALIASES=$(mktemp) + + cat > "$TEMP_ALIASES" << 'EOF' + +# Git shortcuts +alias gs='git status' +alias ga='git add' +alias gc='git commit -m' +alias gp='git push' +alias gl='git log --oneline' + +# fastfetch +alias ff='fastfetch' + +# Claude Aliases +alias cldy='claude --dangerously-skip-permissions' +alias cldyh='claude --dangerously-skip-permissions --model haiku' +alias cldys='claude --dangerously-skip-permissions --model sonnet' +alias cldyo='claude --dangerously-skip-permissions --model opus' + +# IP address lookup +alias whatismyip="whatsmyip" +function whatsmyip () { + # Internal IP Lookup. + if command -v ip &> /dev/null; then + echo -n "Internal IP: " + ip addr show wlan0 | grep "inet " | awk '{print $2}' | cut -d/ -f1 + else + echo -n "Internal IP: " + ifconfig wlan0 | grep "inet " | awk '{print $2}' + fi + + # External IP Lookup + echo -n "External IP: " + curl -4 ifconfig.me +} + +# Automatically do an ls after each cd +cd () +{ + if [ -n "$1" ]; then + builtin cd "$@" && ls + else + builtin cd ~ && ls + fi +} + +# Create and go to the directory +mkdirg() { + mkdir -p "$1" + cd "$1" +} + +# Move and go to the directory +mvg() { + if [ -d "$2" ]; then + mv "$1" "$2" && cd "$2" + else + mv "$1" "$2" + fi +} + +# Copy file with a progress bar +cpp() { + set -e + strace -q -ewrite cp -- "${1}" "${2}" 2>&1 | + awk '{ + count += $NF + if (count % 10 == 0) { + percent = count / total_size * 100 + printf "%3d%% [", percent + for (i=0;i<=percent;i++) + printf "=" + printf ">" + for (i=percent;i<100;i++) + printf " " + printf "]\r" + } + } + END { print "" }' total_size="$(stat -c '%s' "${1}")" count=0 +} + +# Change directory aliases +alias home='cd ~' +alias cd..='cd ..' +alias ..='cd ..' +alias ...='cd ../..' +alias ....='cd ../../..' +alias .....='cd ../../../..' + +# Check the window size after each command +shopt -s checkwinsize + +# Set the default editor +export EDITOR=nvim +export VISUAL=nvim +alias spico='sudo pico' +alias snano='sudo nano' +alias vim='nvim' +EOF + + # Check if these aliases/functions already exist in the shell config + # Look for a marker comment or key aliases + if ! grep -q "# Git shortcuts" "$SHELL_RC" && ! grep -q "alias gs='git status'" "$SHELL_RC"; then + # Append to shell config + echo "" >> "$SHELL_RC" + echo "# Added by nvim dotfiles setup" >> "$SHELL_RC" + cat "$TEMP_ALIASES" >> "$SHELL_RC" + echo "Shell aliases and functions added to $SHELL_RC" + else + echo "Shell aliases already exist in $SHELL_RC, skipping..." + fi + + # Clean up + rm "$TEMP_ALIASES" +else + echo "No .bashrc or .zshrc found, skipping shell config setup" +fi