diff --git a/Makefile b/Makefile index 2930843a2a1..d3ff7d4bd30 100644 --- a/Makefile +++ b/Makefile @@ -1,178 +1,90 @@ -# Dotfiles Automation and Maintenance - -.DEFAULT_GOAL := help - -# Main script -AUTOSCRIPT := ./bin/autoupdate.zsh - -# Required tools for doctor check -REQUIRED := chezmoi zinit nvim npm pip3 tldr vale revolver - -## ---------------------------- -## Tasks -## ---------------------------- - -help: ## Show available commands - @echo "Available commands:" - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ - awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' - -update: ## Run the full autoupdate workflow - @$(AUTOSCRIPT) - -dotfiles-pull: ## Force chezmoi pull - chezmoi update --force -v - -brew-sync: ## Sync Homebrew packages - @./bin/sync_brews.sh - -npm-update: ## Update global npm packages - npm update && npm upgrade && npm audit fix --force && npm prune --production --force - -pip-update: ## Update Python packages - pip3 install --upgrade pip setuptools wheel - pip3 freeze --local | grep -v '^-e' | cut -d = -f 1 | xargs -n1 pip3 install --upgrade - -zinit-update: ## Update zinit plugins - source $$HOME/.local/share/zinit/zinit.git/zinit.zsh && \ - zinit self-update && \ - zinit update --quiet --parallel 8 && \ - zinit cclear - -nvim-update: ## Update Neovim plugins and Treesitter - nvim +PlugUpgrade +PlugClean! +PlugUpdate +PlugInstall +CocUpdateSync +TSUpdateSync +qall - -vale-sync: ## Sync Vale styles - cd styles && vale sync - -tldr-update: ## Update TLDR cache - tldr --update - -neopilot-sync: ## Sync NeoPilot repo - @./bin/sync_neopilotai.sh - -fluxninja-sync: ## Sync FluxNinja repo - @./bin/sync_fluxninja.sh - -doctor: ## Check required tools - @echo "🔍 Checking environment..." - @missing=0; \ - for tool in $(REQUIRED); do \ - if ! command -v $$tool >/dev/null 2>&1; then \ - echo "❌ Missing: $$tool"; \ - missing=1; \ - else \ - echo "✅ Found: $$tool"; \ - fi; \ - done; \ - if [ $$missing -eq 1 ]; then \ - echo "⚠️ One or more required tools are missing."; exit 1; \ - else \ - echo "✅ All required tools are installed."; \ - fi - -install: ## Install all dotfiles by creating symlinks - @echo "🔗 Installing dotfiles..." - @$(MAKE) install-zsh - @$(MAKE) install-git - @$(MAKE) install-nvim - @$(MAKE) install-tmux - @$(MAKE) install-prettier - @$(MAKE) install-golangci - @$(MAKE) install-urlview - @$(MAKE) install-bin - @$(MAKE) install-config - @echo "✅ Dotfiles installed." - -install-zsh: ## Install Zsh dotfiles - @echo "🔗 Installing Zsh dotfiles..." - ln -sf $(CURDIR)/dot_zshrc $(HOME)/.zshrc - ln -sf $(CURDIR)/dot_zprofile $(HOME)/.zprofile - ln -sf $(CURDIR)/dot_aliases $(HOME)/.aliases - ln -sf $(CURDIR)/dot_completions $(HOME)/.completions - @echo "✅ Zsh dotfiles installed." - -install-git: ## Install Git dotfiles - @echo "🔗 Installing Git dotfiles..." - ln -sf $(CURDIR)/dot_gitconfig $(HOME)/.gitconfig - ln -sf $(CURDIR)/dot_gitconfig_themes $(HOME)/.gitconfig_themes - @echo "✅ Git dotfiles installed." - -install-nvim: ## Install Neovim dotfiles - @echo "🔗 Installing Neovim dotfiles..." - mkdir -p $(HOME)/.config - ln -sf $(CURDIR)/dot_config/nvim $(HOME)/.config/nvim - ln -sf $(CURDIR)/dot_vim $(HOME)/.vim - @echo "✅ Neovim dotfiles installed." - -install-tmux: ## Install Tmux dotfiles - @echo "🔗 Installing Tmux dotfiles..." - ln -sf $(CURDIR)/dot_tmux.conf $(HOME)/.tmux.conf - ln -sf $(CURDIR)/dot_tmux.conf.settings $(HOME)/.tmux.conf.settings - @echo "✅ Tmux dotfiles installed." - -install-prettier: ## Install Prettier dotfiles - @echo "🔗 Installing Prettier dotfiles..." - ln -sf $(CURDIR)/dot_prettierrc $(HOME)/.prettierrc - @echo "✅ Prettier dotfiles installed." - -install-golangci: ## Install GolangCI-Lint dotfiles - @echo "🔗 Installing GolangCI-Lint dotfiles..." - ln -sf $(CURDIR)/dot_golangci.yml $(HOME)/.golangci.yml - @echo "✅ GolangCI-Lint dotfiles installed." - -install-urlview: ## Install URLView dotfiles - @echo "🔗 Installing URLView dotfiles..." - ln -sf $(CURDIR)/dot_urlview $(HOME)/.urlview - @echo "✅ URLView dotfiles installed." - -install-bin: ## Install bin scripts - @echo "🔗 Installing bin scripts..." - ln -sf $(CURDIR)/bin $(HOME)/bin - @echo "✅ Bin scripts installed." - -install-config: ## Install XDG config directories - @echo "🔗 Installing XDG config directories..." - mkdir -p $(HOME)/.config - ln -sf $(CURDIR)/dot_config/broot $(HOME)/.config/broot - ln -sf $(CURDIR)/dot_config/fsh $(HOME)/.config/fsh - ln -sf $(CURDIR)/dot_config/ghostty $(HOME)/.config/ghostty - ln -sf $(CURDIR)/dot_config/pip $(HOME)/.config/pip - ln -sf $(CURDIR)/dot_config/smug $(HOME)/.config/smug - @echo "✅ XDG config directories installed." - -clean: ## Remove all installed dotfile symlinks - @echo "🗑️ Cleaning up dotfile symlinks..." - rm -f $(HOME)/.zshrc - rm -f $(HOME)/.zprofile - rm -f $(HOME)/.aliases - rm -f $(HOME)/.gitconfig - rm -f $(HOME)/.gitconfig_themes - rm -f $(HOME)/.tmux.conf - rm -f $(HOME)/.tmux.conf.settings - rm -f $(HOME)/.prettierrc - rm -f $(HOME)/.golangci.yml - rm -f $(HOME)/.urlview - rm -rf $(HOME)/.completions - rm -rf $(HOME)/.config/nvim - rm -rf $(HOME)/.vim - rm -rf $(HOME)/bin - rm -rf $(HOME)/.config/broot - rm -rf $(HOME)/.config/fsh - rm -rf $(HOME)/.config/ghostty - rm -rf $(HOME)/.config/pip - rm -rf $(HOME)/.config/smug - @echo "✅ Cleanup complete." - -force-install: clean install ## Clean and then install all dotfiles - @echo "🔄 Forcing reinstallation of dotfiles..." - -## ---------------------------- -## Phony Targets -## ---------------------------- - -.PHONY: help update dotfiles-pull brew-sync npm-update pip-update zinit-update \ - nvim-update vale-sync tldr-update neopilot-sync fluxninja-sync doctor \ - install install-zsh install-git install-nvim install-tmux install-prettier \ - install-golangci install-urlview install-bin install-config clean force-install - +.PHONY: help install update diff apply clean lint validate test + +# Default target +help: ## Show this help message + @echo 'Usage: make [target]' + @echo '' + @echo 'Targets:' + @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-15s %s\n", $$1, $$2}' $(MAKEFILE_LIST) + +# Chezmoi operations +install: ## Initialize and apply dotfiles using chezmoi + chezmoi init https://github.com/neopilotai/dotfiles.git + chezmoi apply + +update: ## Update dotfiles from repository + chezmoi update + +diff: ## Show diff of changes + chezmoi diff + +apply: ## Apply changes without confirmation + chezmoi apply --force + +# Development and testing +lint: ## Lint configuration files + @echo "Running comprehensive linting..." + @./scripts/bin/executable_lint.zsh + +validate: ## Validate dotfiles configuration + @echo "Validating dotfiles configuration..." + @chezmoi doctor || echo "Some files may differ from target state" + @echo "Checking for required tools..." + @command -v chezmoi >/dev/null 2>&1 || { echo "chezmoi is required but not installed"; exit 1; } + @command -v shellcheck >/dev/null 2>&1 || echo "shellcheck not found (optional)" + @command -v yamllint >/dev/null 2>&1 || echo "yamllint not found (optional)" + @echo "Running security validation..." + @./scripts/bin/executable_validate_security.zsh + +security: ## Run security validation only + @echo "Running security validation..." + @./scripts/bin/executable_validate_security.zsh + +test: ## Test dotfiles setup (dry run) + @echo "Testing chezmoi configuration..." + @chezmoi diff | head -20 + +# Cleanup +clean: ## Clean up temporary files and caches + @echo "Cleaning up..." + @find . -name "*.tmp" -delete || true + @find . -name "*.bak" -delete || true + @find . -name ".DS_Store" -delete || true + +# Documentation +docs: ## Generate documentation + @echo "README.md is the main documentation" + @echo "Consider updating docs if structure changes" + +# Status and info +status: ## Show current dotfiles status + @chezmoi status + @echo "" + @echo "Repository status:" + @git status --short + +info: ## Show information about dotfiles setup + @echo "Dotfiles Repository: $(shell basename $(CURDIR))" + @echo "Chezmoi status:" + @chezmoi status || true + @echo "" + @echo "Git remotes:" + @git remote -v + @echo "" + @echo "Required tools:" + @which chezmoi || echo "chezmoi: NOT FOUND" + @which shellcheck || echo "shellcheck: NOT FOUND (optional)" + @which yamllint || echo "yamllint: NOT FOUND (optional)" + +# Development helpers +edit: ## Edit dotfiles with chezmoi + chezmoi edit + +add: ## Add a new dotfile (usage: make add FILE=path/to/file) + @if [ -z "$(FILE)" ]; then echo "Usage: make add FILE=path/to/file"; exit 1; fi + chezmoi add $(FILE) + +# Backup existing dotfiles before installation +backup: ## Backup existing dotfiles + @echo "Backing up existing dotfiles..." + @chezmoi backup --target ~/.config/chezmoi/backup/ diff --git a/README.md b/README.md index 236f16c0c99..39e662b942e 100644 --- a/README.md +++ b/README.md @@ -1,212 +1,334 @@ # NeoPilot Dotfiles -Welcome to NeoPilot optimized development environment that is well integrated -with our stack. +![NeoPilot Neovim](./scripts/assets/vim.png) -## Setup +## Table of Contents -We use [chezmoi](https://www.chezmoi.io) to manage NeoPilot dotfiles in your -home directory. +- [Introduction](#introduction) +- [Quick Start](#quick-start) +- [Features](#features) + - [Terminal (Zsh)](#terminal-zsh) + - [Tmux](#tmux) + - [Neovim](#neovim) + - [Git](#git) +- [Configuration](#configuration) + - [Local Overrides](#local-overrides) + - [Colors and Themes](#colors-and-themes) +- [Development](#development) +- [Security](#security) +- [Troubleshooting](#troubleshooting) -### Automatic Setup +## Introduction -``` -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/neopilotai/dotfiles/master/assets/executable_install.sh)" -``` +Welcome to NeoPilot optimized development environment that is well integrated with our stack. + +This dotfiles repository provides a comprehensive development setup including: + +- **Zsh** with modern plugins and fuzzy completion +- **Tmux** with session management and productivity features +- **Neovim** with AI-powered completion and modern tooling +- **Git** with enhanced workflows and theming + +## Quick Start -### Manual Setup +### Prerequisites +- [chezmoi](https://www.chezmoi.io) - Dotfile manager +- [Homebrew](https://brew.sh) - Package manager (macOS/Linux) + +### Installation + +#### Automatic Setup (Recommended) + +```bash +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/neopilotai/dotfiles/master/scripts/assets/executable_install.sh)" ``` + +#### Manual Setup + +```bash cd $HOME chezmoi init git@github.com:neopilotai/dotfiles.git -# show diff of changes that will be made +# Show diff of changes that will be made chezmoi diff -# If you are happy with the changes, apply away! +# Apply changes chezmoi apply -v ``` -Please close and reopen the terminal to trigger first time install/updates. +After installation, close and reopen your terminal to trigger first-time setup. + +### Post-Installation + +1. **GitHub Authentication**: Run `gh auth login` or add SSH key to your GitHub account +2. **Nerd Fonts**: Enable a nerd font (e.g., `Hack Nerd Font`) in your terminal +3. **iTerm2 Integration**: On macOS, the setup will offer to install the bundled iTerm2 profile + +## Features + +### Terminal (Zsh) + +![Zsh](./scripts/assets/zsh.png) + +#### Core Features +- **Fuzzy Menus**: Press `TAB` for command completion, `^R` for history search +- **Vi Mode**: Press `ESC` to enter Vi NORMAL mode +- **Smart Prompt**: Shows Git status, exit codes, and contextual information +- **Auto-complete**: Enhanced completion with previews and descriptions + +#### Quality of Life +- **Insults/Cheers**: Fun feedback for command success/failure (configurable) +- **Weather Display**: Shows current weather on startup +- **GitHub Status**: Displays GitHub service status +- **Auto-updates**: Automatic dotfile updates every 7 days + +#### Key Bindings +- `` - Command completion menu +- `^R` - History fuzzy search +- `ESC` - Enter Vi mode +- `vv` (in Vi mode) - Open file in Neovim with Copilot + +### Tmux + +![Tmux Menu](./scripts/assets/tmux-menu.png) +![Tmux Fuzzy Menu](./scripts/assets/tmux-fzf.png) + +#### Core Features +- **Session Management**: Automatic session restoration and fuzzy session switching +- **Fuzzy Menu**: Press `` for quick tmux management +- **Tmux Menu**: Press `F12` for session/window/pane management +- **Nested Sessions**: Press `F1` to suspend/unsuspend local tmux + +#### Key Bindings +- `` or `` - Prefix key +- `` - Fuzzy menu +- `F12` - Tmux management menu +- `F1` - Toggle nested sessions +- `` - Fuzzy search in terminal buffer +- `` - PathPicker integration + +### Neovim + +This environment provides a modern Neovim setup optimized for development. + +![Fuzzy Menu](./scripts/assets/fuzzymenu.png) +![IDE](./scripts/assets/vim_ide.png) + +#### AI Integration +- **GitHub Copilot**: Type `:Copilot setup` to configure +- **CodeGPT**: Highlight code and press `` for AI options +- **LanguageTool**: Premium integration for grammar checking + +#### Key Features +- **Fuzzy Menu**: Press `` or `Shift+LeftMouse` for contextual actions +- **Color Schemes**: Multiple themes with Gruvbox as default +- **Landing Page**: Helpful links and discoverability aids + +#### Configuration +You can provide additional settings in: +- `$HOME/.vimrc_local` - Additional Vim configuration +- `$HOME/.vimrc_plugins` - Additional plugins +- `$HOME/.config/nvim/init.vim` - Neovim-specific settings + +### Git + +#### Enhanced Configuration +- **Delta Integration**: Modern diff viewer with syntax highlighting +- **Git Extras**: Additional Git commands and utilities +- **Smart Defaults**: Optimized merge and push behavior + +#### Theme Integration +See `.gitconfig_themes` for available themes. Override in your local `.gitconfig_local`. + +## Configuration + +### Local Overrides + +All tools support local override files that won't be overwritten by updates: + +| Tool | Override File | Purpose | +|------|---------------|---------| +| Zsh | `.zshrc_local` | Additional shell configuration | +| Vim | `.vimrc_local` | Additional Vim settings | +| Tmux | `.tmux.conf_local` | Additional tmux settings | +| Git | `.gitconfig_local` | Personal Git configuration | +| Homebrew | `.brew_local` | Private package list | +| Fsh | `.config/fsh_local` | Fast syntax highlighting theme | + +### Colors and Themes + +The setup uses **Gruvbox Dark** as the default theme across all tools. + +#### Terminal Colors +- **macOS**: iTerm2 profile installation offered during setup +- **Linux**: Colors set via escape codes (disable with `SET_TERMINAL_COLORS=false`) +- **Alternative**: Use terminal's built-in color profiles + +#### Available Themes +- **bat**: `BAT_THEME` environment variable +- **FZF**: Base16 color schemes from [base16-fzf](https://github.com/fnune/base16-fzf) +- **LS_COLORS**: [vivid](https://github.com/sharkdp/vivid) integration +- **Git**: Multiple themes in `.gitconfig_themes` + +## Development + +### Repository Structure + +``` +├── dot_* # Chezmoi dotfiles (prefixed with dot_) +├── scripts/ # Scripts and assets +│ ├── assets/ # Configuration assets, scripts, images +│ └── bin/ # Executable scripts +├── .github/workflows/ # GitHub Actions +├── .chezmoidot.toml # Chezmoi configuration +├── .chezmoiignore # Chezmoi ignore patterns +├── Makefile # Development tasks +└── README.md # This file +``` + +### Development Commands + +```bash +# Show available commands +make help -Recommend using `GitHub CLI` for authenticating with GitHub. Run -`gh auth login`. Alternatively, add -[SSH key to your GitHub account](https://docs.github.com/en/authentication/connecting-to-github-with-ssh). +# Lint configuration files +make lint -## Git setup +# Validate setup and run security checks +make validate -### Username and local settings +# Run security validation only +make security -Provide username and email address by creating `.gitconfig_local` e.g. +# Update dotfiles +make update +# Show current status +make status ``` -[user] - name = Harjot Gill - email = harjot@neopilot.ai -[github] - user = - token = + +### Adding New Dotfiles + +```bash +# Add a new file to be managed +make add FILE=path/to/your/file + +# Edit existing dotfile with chezmoi +make edit ``` -You can generate -[personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) -for GitHub to use HTTP API. Also, it's useful to add this token to your -`$HOME/.netrc` file. Run - -`echo 'machine api.github.com login password ' >> $HOME/.netrc` +## Troubleshooting -### GitHub org cloning script +### Common Issues -To clone NeoPilot, run: `gh_clone_all.sh neopilotai $HOME/work`. This step -is performed automatically on installation. +#### Terminal Colors Not Working +```bash +# Disable automatic color setting +echo 'export SET_TERMINAL_COLORS=false' >> ~/.zshrc_local +``` -### Git pull all repos script +#### Missing Dependencies +```bash +# Install Homebrew (required) +make install +# or manually: +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +``` -To update all repos in a directory, run: `pull_all.sh $HOME/work/neopilotai`. -This step is performed automatically on auto-updates. +#### Chezmoi Issues +```bash +# Check chezmoi status +chezmoi doctor -## Preparing your terminal +# Force update +chezmoi update --force -- **Nerd fonts**: Please enable a nerd font such as `Hack Nerd Font` in your - terminal profile to see icons properly when using `nvim` in terminal mode. -- **Terminal colors**: See the section about [colors](#colors). +# Show what would change +chezmoi diff +``` + +#### Permission Issues +```bash +# Fix chezmoi permissions +chezmoi state reset +chezmoi apply +``` + +### Getting Help + +1. **Check Status**: Run `make status` to see current state +2. **Validate Setup**: Run `make validate` to check for issues +3. **View Diff**: Run `chezmoi diff` to see pending changes +4. **Documentation**: Check tool-specific documentation in comments + +### Manual Recovery + +If something breaks, you can: + +1. **Backup current setup**: `chezmoi backup` +2. **Reset to known state**: `chezmoi apply --force` +3. **Check logs**: Look for error messages in terminal output + +## Security + +### Security Features + +This dotfiles repository includes several security measures: + +- **No Hardcoded Secrets**: All sensitive data uses environment variables or secure vaults +- **Safe Installation**: Verified downloads and proper input validation +- **Secure Defaults**: Conservative permissions and safe shell practices +- **Regular Validation**: Automated security checks and linting + +### Security Validation + +Run security checks before making changes: + +```bash +# Run full validation +make validate + +# Run security validation only +make security + +# Lint all configuration files +make lint +``` -## Homebrew +### Best Practices -Homebrew is the default package manager for this environment. You can provide -private packages by adding them to: `$HOME/.brew_local` +#### For Users +- Store API keys and tokens in environment variables, not config files +- Use `*_local` files for personal settings (they're automatically ignored) +- Regularly update your system and packages +- Use SSH keys instead of passwords when possible -## Autoupdates +#### For Contributors +- Never commit secrets or personal information +- Use `make security` before submitting changes +- Follow shell scripting best practices +- Validate all user input in scripts -This environment is set to autoupdate every 7 days by default. You can trigger -autoupdates manually by calling `autoupdate.zsh --force` You can provide custom -autoupdate commands by adding them to: `$HOME/.autoupdate_local.zsh` +### Security Considerations -## zshrc +#### Installation Security +- Homebrew installation uses official sources +- No automatic privilege escalation +- User confirmation for system changes -You can provide additional zshrc settings by adding them to: -`$HOME/.zshrc_local` +#### Update Security +- Package updates use safe practices +- npm audit runs before applying fixes +- pip updates respect requirements files when available -![zsh](./assets/zsh.png) +#### Configuration Security +- Local override files are never committed +- Sensitive paths are properly ignored +- No world-writable files by default -### Features +## Contributing -- Fuzzy menus: Fuzzy menus are available for command completion (press `TAB`) - menus and command history (press `^r`). -- Vi mode: Press `ESC` to enter Vi `NORMAL` mode. Cool tip - while in normal - mode, press `vv` to switch to visual mode (it will open `nvim` editor) and in - that mode you can use GitHub Copilot to build sophisticated commands using AI! -- Prompt flags: Type `yazpt_explain_git` to understand the meaning of various - flags in the prompt. -- Forgit: You can use `forgit` as an interactive frontend for various git - commands. E.g. try `git forgit log`. -- iTerm2 integration: On macOS, please install iTerm2 shell - [integration](https://iterm2.com/documentation-shell-integration.html) to use - nice features such as navigating marks in prompt. - -## tmux - -`tmux` sessions are automatically started as part of `.zshrc` execution. You -will be shown an option to join an existing detached session if they exist, -otherwise a new session will be created and attached to. - -### Features - -- Prefix: `C-a` or `C-b` -- Fuzzy menu: Press `C-a C-Space` to access fuzzy menu for quick tmux management - and shortcuts to various commands. -- tmux menu: Press `F12` to access tmux session/window/pane management menu. -- Nested tmux sessions (e.g. remote ssh): Press `F1` to suspend/unsuspend local - tmux. -- [Smug](https://github.com/ivaaaan/smug): Define and orchestrate tmux sessions - with smug. e.g. use smug to start/stop local dev Kubernetes cluster and so on. -- Fuzzy search tmux terminal buffer: Press `C-a C-/` -- Vi bindings are enabled in tmux copy mode -- Facebook PathPicker: Press `C-a C-P` to select any line from scrollback buffer - (e.g. git status) and use those in another command. -- Urlview: Press `C-a C-U` to select any url in scrollback buffer and open in - browser. - -## Neovim - -This environment is highly tuned towards providing a modern neovim/vim setup for -development using modern languages such as Golang, Typescript etc. - -### vimrc - -You can provide additional `vimrc` settings by adding them to: -`$HOME/.vimrc_local`. You can also use **FuzzyMenu** (``) to tweak -and persist local settings. In addition, you can provide additional vim plugins -by adding them to `$HOME/.vimrc_plugins`. - -Several `colorschemes` are bundled and `gruvbox` is chosen by default. You can -override `colorscheme` by providing `let colorscheme = ` in your -`.vimrc_local` file. - -See `.vimrc` file for available `colorschemes`. Also see -`~/.config/nvim/init.vim` for Neovim specific settings. - -### Discoverability of commands and plugins - -- Landing page for new tabs contains several useful links that help with - discoverability. -- Press `` (double space) or `Shift + LeftMouse` click to open a - contextual FuzzyMenu for the word under cursor or selection. - -### AI-based autocompletion - -- GitHub Copilot - Type `:Copilot setup` in Neovim to set up. -- CodeGPT - Just highlight the code and press `` to see CodeGPT - options in the FuzzyMenu. You must provide `OPENAI_API_KEY` environment - variable in your `.zshrc_local` to use this feature. - -### LanguageTool - -If you have LanguageTool Premium, you can provide `LANGTOOL_HTTP_URI`, -`LANGTOOL_USERNAME` and `LANGTOOL_API_KEY` environment variables to use the -language server in Neovim. - -## Colors - -Unlike `nvim` which allows setting themes easily via `.vimrc_local`, color -themes for terminal interface are spread across multiple settings. - -- **Terminal theme** - - - macOS: For iTerm2, the option will be provided to install bundled profile - that contains font/color settings. If you do not wish to install the - profile, then the colors will be set via terminal escape codes unless - `SET_TERMINAL_COLORS` is set to `false` in your `.zshrc_local`. - - Linux: Colors will be set automatically using terminal escape codes unless - `SET_TERMINAL_COLORS` is set to `false` in your `.zshrc_local`. - Alternatively, you can install default color profile using - `$HOME/assets/install_gruvbox.sh`. Make sure to set `SET_TERMINAL_COLORS` - to `false` in your `.zshrc_local` if you would like to use terminal's color - profiles. -- tmux theme - See `.tmux.conf.settings` for example configuration and override - it in your personal `.tmux.conf_local` file. The tmux theme configures the - tmux status line and not the terminal itself. -- bat theme (cat replacement) - Environment variable `BAT_THEME` sets the theme. - See `bat --list-themes` to get the list. You can override this theme in your - `.zshrc_local` file. Bat is used extensively for fzf previews, git pager - (delta), less command filter and so on. -- FZF colors - Get and source color schemes from - [base16-fzf](https://github.com/fnune/base16-fzf) in your - `$HOME/.zshrc_local`. -- LS_COLORS - We use [vivid](https://github.com/sharkdp/vivid) to set the - themes. Run `vivid themes` to get the list. You can override this theme in - your `.zshrc_local` file. -- Git pager - See `.gitconfig_themes` to see the available themes. You can - override them in your local `.gitconfig_local`. -- Fast Syntax Highlighting (zsh) - You can run `fast-theme -l` to get the list. - To set the theme, first, override `FAST_WORK_DIR` environment variable in your - `.zshrc` and point it to `$HOME/.config/fsh_local`. Next, run - `fast-theme ` to switch the theme. - -Note: Currently all these settings are configured to match `gruvbox-dark` color -palette. But it's pretty easy to override them to match `onedark` or -[Nord](https://www.nordtheme.com) - -Bonus: - -- Slack Gruvbox - Paste this in your DM to Slackbot and click the - `Switch sidebar theme` button. - ` gruvbox dark #282828,#3c3836,#ebdbb2,#1d2021,#3e313c,#ebdbb2,#689d6a,#fb4934` - -## Managing `*_local` override files +1. **Test changes**: Use `make validate` before committing +2. **Security check**: Run `make security` to ensure no security issues +3. **Update documentation**: Keep README.md in sync with changes +4. **Follow conventions**: Use existing patterns for new configurations diff --git a/bin/autoupdate.zsh b/bin/autoupdate.zsh deleted file mode 100755 index 47b5c1126c2..00000000000 --- a/bin/autoupdate.zsh +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env zsh - -# Check whether the script is being sourced or executed -[[ $0 =~ "autoupdate.zsh" ]] && sourced=0 || sourced=1 - -# Configuration -SYSTEM_UPDATE_DAYS=${SYSTEM_UPDATE_DAYS:-7} -SYSTEM_RECEIPT_F=${SYSTEM_RECEIPT_F:-$HOME/local/system_lastupdate} -day_seconds=86400 -system_seconds=$((day_seconds * SYSTEM_UPDATE_DAYS)) -tp='success' -declare -a update_errors - -# Utilities -function update_error() { - local error_cmd=$1 - local error_code=$2 - if [ $error_code -ne 0 ]; then - update_errors+=("$error_cmd: $error_code") - fi -} - -function show_errors() { - if [ ${#update_errors[@]} -ne 0 ]; then - tp='error' - echo "Errors occurred during update:" - for error in "${update_errors[@]}"; do - echo " $error" - done - fi - - if [ $sourced -eq 1 ]; then - term-notify $tp $interval <<<"autoupdate.zsh" - else - [[ $tp == 'success' ]] && exit 0 || exit 1 - fi -} - -function check_interval() { - local now=$(date +%s) - local last_update=0 - [[ -f $1 ]] && last_update=$(<$1) - echo $((now - last_update)) -} - -function revolver_start() { - if command -v revolver >/dev/null 2>&1; then - tput civis - revolver --style dots2 "echo $1" & - REVOLVER_PID=$! - fi -} - -function revolver_update() { - if command -v revolver >/dev/null 2>&1; then - revolver --style dots2 "echo $1" & - REVOLVER_PID=$! - fi -} - -function revolver_stop() { - if [ -n "$REVOLVER_PID" ]; then - kill "$REVOLVER_PID" 2>/dev/null - fi - tput cnorm -} - -# Handle force update -force_update=0 -[[ $1 == "--force" ]] && force_update=1 - -# Main logic -last_system=$(check_interval $SYSTEM_RECEIPT_F) -if [ $last_system -gt $system_seconds ] || [ $force_update -eq 1 ]; then - start_time=$(date +%s) - date +%s > $SYSTEM_RECEIPT_F - echo "It has been $((last_system / day_seconds)) days since system was updated" - echo "Updating system... Please open a new terminal to continue your work in parallel..." - - revolver_start "Pulling latest dotfiles..." - cd ~ && chezmoi --force update -v - update_error dotfiles $? - - revolver_stop - - revolver_update "Running personal autoupdates..." - [[ -f $HOME/local/autoupdate_local.zsh ]] && eval "$(<$HOME/local/autoupdate_local.zsh)" - update_error local_autoupdate $? - revolver_stop - - $HOME/bin/sync_brews.sh - update_error sync_brews $? - - revolver_update "Updating zinit..." - source $HOME/.local/share/zinit/zinit.git/zinit.zsh && \ - zinit self-update && \ - zinit update --quiet --parallel 8 && \ - zinit cclear - update_error zinit $? - revolver_stop - - revolver_update "Updating nvim..." - nvim -c "source $HOME/dotfiles/dot_vimrc" +PlugUpgrade +PlugClean! +PlugUpdate +PlugInstall +CocUpdateSync +TSUpdateSync +qall - update_error nvim $? - revolver_stop - - revolver_update "Updating npm packages..." - npm update && npm upgrade && npm audit fix --force && npm prune --production --force - update_error npm $? - revolver_stop - - revolver_update "Updating pip packages..." - # The --break-system-packages flag is used to bypass PEP 668 (externally-managed-environment) error. - # This is generally not recommended for long-term Python environment management. - # Consider using pipx or virtual environments for better practice. - pip3 install --quiet --upgrade pip setuptools wheel --break-system-packages && \ - pip3 freeze --local | grep -v '^-e' | cut -d = -f 1 | \ - xargs -n1 pip3 install --quiet --upgrade --break-system-packages - update_error pip $? - revolver_stop - - revolver_update "Updating tldr cache..." - tldr --update - revolver_stop - - revolver_update "Syncing Vale styles in notes..." - pushd $HOME/dotfiles/notes/styles && vale sync && popd - revolver_stop - - $HOME/bin/sync_neopilotai.sh - $HOME/bin/sync_fluxninja.sh - - [[ $TERM == *"tmux"* || -n $TMUX ]] && tmux source-file $HOME/dotfiles/tmux.conf - - stop_time=$(date +%s) - interval=$((stop_time - start_time)) - echo "It took $interval seconds to update the system." - show_errors -fi - -# Cleanup -unset SYSTEM_RECEIPT_F SYSTEM_UPDATE_DAYS day_seconds last_system system_seconds -unset start_time stop_time interval force_update update_errors check_interval error_code error_cmd tp -unset -f update_error show_errors check_interval revolver_stop revolver_start revolver_update diff --git a/bin/sync_neopilotai.sh b/bin/sync_neopilotai.sh deleted file mode 100755 index 86b473af2f9..00000000000 --- a/bin/sync_neopilotai.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -gh_clone_all.sh neopilotai ~/Work -pull_all.sh ~/Work/neopilotai - -# go through all the directories in ~/Work/neopilotai -# look for package.json files in the subdirectories -# and run pnpm install in those directories -find ~/Work/neopilotai -depth 2 -name package.json -exec dirname {} \; | while read dir; do - # if the directory contains a pnpm-lock.yaml file use pnpm - # otherwise look for a yarn.lock file and use yarn - # otherwise look for a package-lock.json file and use npm - if [ -f "$dir/pnpm-lock.yaml" ]; then - echo "Running pnpm install in $dir" - (cd $dir && pnpm install) - elif [ -f "$dir/yarn.lock" ]; then - echo "Running yarn install in $dir" - (cd $dir && yarn install) - elif [ -f "$dir/package-lock.json" ]; then - echo "Running npm install in $dir" - (cd $dir && npm install) - fi -done diff --git a/dot_config/ghostty/config b/dot_config/ghostty/config index 25dff6aa981..51a292bda63 100644 --- a/dot_config/ghostty/config +++ b/dot_config/ghostty/config @@ -1,3 +1,3 @@ -theme = GruvboxDark +theme = Gruvbox Dark font-family = "Hack Nerd Font Mono Regular" font-size = 16 diff --git a/dot_config/nvim/coc-settings.json b/dot_config/nvim/coc-settings.json index e0d30387b80..25c9c2163fc 100644 --- a/dot_config/nvim/coc-settings.json +++ b/dot_config/nvim/coc-settings.json @@ -1,9 +1,9 @@ { "notification.statusLineProgress": false, - "coc.preferences.extensionUpdateCheck": "daily", - "coc.preferences.enableMessageDialog": true, + "coc.preferences.messageDialogKind": "notification", "coc.preferences.enableLinkedEditing": true, - "coc.preferences.silentAutoupdate": true, + "extensions.updateCheck": "daily", + "extensions.silentAutoupdate": true, "coc.preferences.formatOnSave": true, "semanticTokens.enable": true, "colors.enable": true, @@ -52,6 +52,7 @@ }, "snippets.priority": 89, "coc.source.zsh.priority": 99, + "tsserver.maxTsServerMemory": 8192, "go.checkForUpdates": "install", "go.goplsOptions": { "local": "fluxninja.com", @@ -59,7 +60,6 @@ "staticcheck": true, "semanticTokens": true, "analyses": { - "fieldalignment": true, "nilness": true, "unusedparams": true, "unusedwrite": true, @@ -78,39 +78,75 @@ "languageserver": { "graphql": { "command": "graphql-lsp", - "args": ["server", "-m", "stream"], - "filetypes": ["typescript", "typescriptreact", "graphql"] + "args": [ + "server", + "-m", + "stream" + ], + "filetypes": [ + "typescript", + "typescriptreact", + "graphql" + ] }, "terraform": { "command": "terraform-ls", - "args": ["serve"], - "filetypes": ["terraform", "tf"], + "args": [ + "serve" + ], + "filetypes": [ + "terraform", + "tf" + ], "initializationOptions": {} }, "lua": { "command": "lua-lsp", - "filetypes": ["lua"] + "filetypes": [ + "lua" + ] }, "bash": { "command": "bash-language-server", - "args": ["start"], - "filetypes": ["sh", "bash"] + "args": [ + "start" + ], + "filetypes": [ + "sh", + "bash" + ] }, "dockerfile": { "command": "docker-langserver", - "filetypes": ["dockerfile"], - "args": ["--stdio"] + "filetypes": [ + "dockerfile" + ], + "args": [ + "--stdio" + ] }, "buf": { "command": "bufls", - "args": ["serve"], - "filetypes": ["proto"] + "args": [ + "serve" + ], + "filetypes": [ + "proto" + ] }, "jsonnet": { "command": "jsonnet-language-server", - "args": ["-t"], - "rootPatterns": [".git/", "jsonnetfile.json"], - "filetypes": ["jsonnet", "libsonnet"] + "args": [ + "-t" + ], + "rootPatterns": [ + ".git/", + "jsonnetfile.json" + ], + "filetypes": [ + "jsonnet", + "libsonnet" + ] } }, "diagnostic-languageserver.mergeConfig": true, @@ -118,9 +154,18 @@ "diagnostic-languageserver.linters": { "golangci-lint2": { "command": "golangci-lint", - "rootPatterns": ["go.mod"], + "rootPatterns": [ + "go.mod" + ], "debounce": 100, - "args": ["--out-format", "json", "--deadline", "5s", "run", "%dirname"], + "args": [ + "--out-format", + "json", + "--deadline", + "5s", + "run", + "%dirname" + ], "sourceName": "golangci-lint", "parseJson": { "sourceName": "Pos.Filename", @@ -133,7 +178,10 @@ }, "zsh": { "command": "zsh", - "args": ["-n", "%file"], + "args": [ + "-n", + "%file" + ], "isStdout": false, "isStderr": true, "sourceName": "zsh", @@ -195,7 +243,9 @@ "python.formatting.provider": "black", "cSpell.showStatus": false, "cSpell.allowCompoundWords": true, - "cSpell.userWords": [], + "cSpell.userWords": [ + "Agentic" + ], "cSpell.dictionaryDefinitions": [ { "name": "FluxNinja", @@ -216,23 +266,38 @@ "cSpell.languageSettings": [ { "languageId": "python", - "includeRegExpList": ["/#.*/", "/('''|\"\"\")[^\\1]+?\\1/g", "strings"] + "includeRegExpList": [ + "/#.*/", + "/('''|\"\"\")[^\\1]+?\\1/g", + "strings" + ] }, { "languageId": "javascript,typescript", - "includeRegExpList": ["CStyleComment", "strings"] + "includeRegExpList": [ + "CStyleComment", + "strings" + ] }, { "languageId": "cpp,c", // Only check comments and strings - "includeRegExpList": ["CStyleComment", "string"], + "includeRegExpList": [ + "CStyleComment", + "string" + ], // Exclude includes, because they are also strings. - "ignoreRegExpList": ["/#include.*/"] + "ignoreRegExpList": [ + "/#include.*/" + ] }, { "languageId": "go", // Only check comments and strings - "includeRegExpList": ["CStyleComment", "string"], + "includeRegExpList": [ + "CStyleComment", + "string" + ], // Exclude imports, because they are also strings. "ignoreRegExpList": [ // ignore multiline imports @@ -243,11 +308,17 @@ }, { "languageId": "vim", - "includeRegExpList": ["^\\s*\".*", "strings"] + "includeRegExpList": [ + "^\\s*\".*", + "strings" + ] }, { "languageId": "proto", - "includeRegExpList": ["CStyleComment", "string"], + "includeRegExpList": [ + "CStyleComment", + "string" + ], "ignoreRegExpList": [ "/package.*/", "/import.*/", diff --git a/dot_config/nvim/init.vim b/dot_config/nvim/init.vim index 3eda5db2a9a..46e2792a06c 100644 --- a/dot_config/nvim/init.vim +++ b/dot_config/nvim/init.vim @@ -430,8 +430,6 @@ require('tmux-awesome-manager').setup({ open_new_as = 'pane' -- open new command as. options: pane, window, separated_session. }) -require('neopilot').setup() - tmux = require('tmux-awesome-manager') vim.keymap.set('v', 'l', tmux.send_text_to, {}) -- Send text to a open terminal? diff --git a/dot_config/smug/dotfiles-personal.yml b/dot_config/smug/dotfiles-personal.yml index d3ec74a31db..7e55f80666f 100644 --- a/dot_config/smug/dotfiles-personal.yml +++ b/dot_config/smug/dotfiles-personal.yml @@ -5,4 +5,4 @@ windows: - name: nvim-dotfiles-personal layout: main-vertical commands: - - ~/assets/dotfiles-edit.sh personal + - ~/scripts/assets/dotfiles-edit.sh personal diff --git a/dot_config/smug/dotfiles.yml b/dot_config/smug/dotfiles.yml index eff8b83d10e..f6cf053072b 100644 --- a/dot_config/smug/dotfiles.yml +++ b/dot_config/smug/dotfiles.yml @@ -5,4 +5,4 @@ windows: - name: nvim-dotfiles layout: main-vertical commands: - - ~/assets/dotfiles-edit.sh + - ~/scripts/assets/dotfiles-edit.sh diff --git a/dot_vimrc b/dot_vimrc index 289dd464c1b..00b15464124 100644 --- a/dot_vimrc +++ b/dot_vimrc @@ -149,7 +149,6 @@ Plug 'kevinhwang91/nvim-hlslens', has('nvim') ? {} : { 'on': [] } Plug 'petertriho/nvim-scrollbar', has('nvim') ? {} : { 'on': [] } Plug 'otavioschwanck/tmux-awesome-manager.nvim', has('nvim') ? {} : { 'on': [] } Plug 'chrisgrieser/nvim-early-retirement', has('nvim') ? {} : { 'on': [] } -Plug 'neopilot-ai/neopilot.nvim', has('nvim') ? {} : { 'on': [] } if exists('$OPENAI_API_KEY') Plug 'harjotgill/CodeGPT.nvim', has('nvim') ? {} : { 'on': [] } @@ -269,6 +268,7 @@ let g:coc_global_extensions = [ \ 'coc-markmap', \ 'coc-diagnostic', \ 'coc-prettier', + \ 'coc-biome', \ 'coc-marketplace', \ 'coc-vimlsp', \ 'coc-protobuf', diff --git a/dot_zprofile b/dot_zprofile index d8186e32fd0..4172a2fb656 100644 --- a/dot_zprofile +++ b/dot_zprofile @@ -11,7 +11,7 @@ else fi # add python symlinks -export PATH=$HOME/bin:$HOME/go/bin:$HOME/.cargo/bin:$(brew --prefix)/opt/python/libexec/bin:$HOME/.local/bin:$PATH:$HOME/.docker/bin:$HOME/.orbstack/bin +export PATH=$HOME/scripts/bin:$HOME/go/bin:$HOME/.cargo/bin:$(brew --prefix)/opt/python/libexec/bin:$HOME/.local/bin:$PATH:$HOME/.docker/bin:$HOME/.orbstack/bin export JDK_HOME=$HOMEBREW_PREFIX/opt/openjdk@17 export JAVA_HOME=$HOMEBREW_PREFIX/opt/openjdk@17 diff --git a/dot_zshrc b/dot_zshrc index 231e25925f6..a412da067c9 100644 --- a/dot_zshrc +++ b/dot_zshrc @@ -1,7 +1,194 @@ -# This file is now modularized. Do not edit directly. -# Your configurations are now located in dot_zshrc.d/ +# NeoPilot Zsh Configuration +# Modular configuration for better maintainability -# Source modular files -for config_file in "$HOME/dotfiles/dot_zshrc.d"/*.zsh; do - source "$config_file" -done \ No newline at end of file +# Load environment variables and basic setup +source ~/scripts/assets/zsh_env.zsh + +# Terminal detection and configuration +function set_terminal { + if [[ -z "${TERMINAL:-}" ]]; then + OS="$(uname)" + if [[ "$OS" = "Darwin" ]]; then + export TERMINAL=$TERM_PROGRAM + # iTerm2 profile installation (handled automatically) + if [[ ! -e "${HOME}/.iterm2_profile_check_v2" ]]; then + rm -f "${HOME}/.iterm2_profile_check" + if gum confirm "Do you want to use NeoPilot's bundled iTerm2 colors/font profile?"; then + # Install iTerm2 profile + cp ~/scripts/assets/iterm2_gruvbox.json ~/Library/Application\ Support/iTerm2/DynamicProfiles/ + pip3 install iterm2 && python3 ~/scripts/assets/iterm2_default.py && touch "${HOME}/.iterm2_profile_check_v2" || ( + echo; echo; echo "Failed to install iTerm2 profile. You might need to enable Python API within iTerm2 preferences (under Magic tab). Press Enter to continue." && read + ) + # Ask about wallpaper + if gum confirm "Do you want to use matching wallpaper?"; then + osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$HOME/scripts/assets/apple_gruvbox.heic\"" + fi + else + echo "no" > "${HOME}/.iterm2_profile_check_v2" + fi + fi + return + fi + + # Other OS detection + if [[ "${OS#CYGWIN}" != "${OS}" ]]; then + export TERMINAL="mintty" + elif [[ "$TERM" = "xterm-kitty" ]]; then + export TERMINAL="kitty" + else + # Generic terminal detection + pid="$$" + export TERMINAL="$(ps -h -o comm -p $pid)" + while [[ "${TERMINAL:(-2)}" == "sh" ]]; do + pid="$(ps -h -o ppid -p $pid)" + export TERMINAL="$(ps -h -o comm -p $pid)" + done + fi + fi +} + +# Tmux integration +if [[ -z "$START_TMUX" ]]; then + export START_TMUX=true +fi + +# Check for tmux and start if enabled +if [[ -x "$(command -v tmux)" ]]; then + if $START_TMUX; then + export START_TMUX=false + set_terminal + DETACHED_SESSIONS=$(tmux ls 2&>/dev/null | grep -v attached) + if [[ -n "$DETACHED_SESSIONS" ]]; then + DETACHED_SESSIONS=$(tmux ls | grep -v attached) + DETACHED_SESSIONS="New Session\n$DETACHED_SESSIONS" + SESSION_NAME=$(echo "$DETACHED_SESSIONS" | \ + fzf --header="== Attach to a detached session ==" \ + --ansi --color="dark" \ + --preview="$HOME/scripts/assets/.session_preview {}") + if [[ $SESSION_NAME == "New Session" ]]; then + tmux -u new-session + else + SESSION_NAME=$(echo "$SESSION_NAME" | cut -d':' -f1) + tmux -u attach -t $SESSION_NAME + fi + else + tmux -u new-session + fi + exit + fi +fi + +# Homebrew installation check +if ! command -v brew &> /dev/null; then + echo "Installing homebrew..." + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + source ~/.zprofile + ~/scripts/bin/autoupdate.zsh --force +fi + +# Welcome message +figlet -w 80 NeoPilot Zsh && echo "" 2&>/dev/null + +# Load utilities +source ~/scripts/assets/utils.zsh + +# Command expansion function +function expand-command-aliases() { + cmd="$1" + functions[expandaliasestmp]="${cmd}" + print -rn -- "${functions[expandaliasestmp]#$'\t'}" + unset 'functions[expandaliasestmp]' +} + +# Pre-execution hook +_brew_completion_update=false + +func preexec() { + export LAST_COMMAND="$(expand-command-aliases "$1")" + + # Tmux environment sync + if [ -n "$TMUX" ] && tmux ls >/dev/null 2>/dev/null; then + eval "$(tmux show-environment -s | grep -v "^unset")" + local uuid="$(tmux show-environment -g TMUX_UUID 2>/dev/null)" + if [[ -z "$LAST_TMUX_UUID" ]]; then + export LAST_TMUX_UUID="$uuid" + else + if [ "$LAST_TMUX_UUID" != "$uuid" ]; then + export LAST_TMUX_UUID="$uuid" + echo -e "${BLUE_BRIGHT} == Autoupdate detected | Zsh reloading == ${RESET}" + tmux respawn-pane -k -t "$TMUX_PANE" "cd \"$PWD\" && $LAST_COMMAND && zsh --login" + echo + echo -e "${BLUE_BRIGHT} == Zsh reloaded == ${RESET}" + echo + fi + fi + fi + + # Brew completion update trigger + if [[ "$LAST_COMMAND" =~ "brew install" ]] || [[ "$LAST_COMMAND" =~ "brew upgrade" ]] || [[ "$LAST_COMMAND" =~ "brew uninstall" ]] || [[ "$LAST_COMMAND" =~ "brew reinstall" ]]; then + _brew_completion_update=true + fi +} + +# Pre-command hook +function precmd() { + if $_brew_completion_update; then + zinit update brew-completions + _brew_completion_update=false + fi +} + +# GitHub status monitoring +periodic() { silent_background timeout 2 $HOME/scripts/bin/gh_checks_status.sh > /tmp/gh_$$ } +PERIOD=10 + +# Load modular components +source ~/scripts/assets/zsh_prompt.zsh +source ~/scripts/assets/zsh_plugins.zsh +source ~/scripts/assets/zsh_bindings.zsh +source ~/scripts/assets/zsh_integrations.zsh + +# Terminal integration messages +if [[ $TERM == *"tmux"* || $TERM == *"screen"* || -n $TMUX ]]; then + echo -e "${YELLOW_BRIGHT} Welcome to ${CYAN_BRIGHT}tmux${RESET}" + echo -e "${YELLOW_BRIGHT} Press ${CYAN_BRIGHT}${YELLOW_BRIGHT} for fuzzy menu - look for additional commands under ${CYAN_BRIGHT}menu${YELLOW_BRIGHT} selection${RESET}" + echo -e "${YELLOW_BRIGHT} Press ${CYAN_BRIGHT}F12${YELLOW_BRIGHT} for tmux menu${RESET}" +else + sessions=$(tmux list-sessions 2&> /dev/null | cut -d ":" -f1) + # check whether $sessions is not empty + if [ -n "$sessions" ]; then + echo -e "\n${BOLD}${CYAN_BRIGHT} == Active tmux Sessions ==${RESET}"; + for i in $sessions ; do + echo -e "${BOLD}${YELLOW_BRIGHT} [*] $i" + done; + fi + echo -e "${CYAN_BRIGHT} == Run tms to create and select tmux sessions == ${RESET}" + echo -e "${RESET}" +fi + +echo -e "${YELLOW_BRIGHT} Press ${CYAN_BRIGHT}${YELLOW_BRIGHT} to invoke auto-complete menu for commands, arguments and options${RESET}" +echo + +# override terminal profile colors using escape codes +if $SET_TERMINAL_COLORS; then + $HOME/scripts/assets/set_colors.zsh +fi + +# LanguageTool configuration +export LANGTOOL_USERNAME="" +export LANGTOOL_API_KEY="" +export LANGTOOL_HTTP_URI="" + +# FluxNinja Aperture Tilt Environment Variables +export TILT_APERTURE_SSH_KEY_PUB=$HOME/.ssh/id_ed25519.pub +export TILT_GRAFANA_REPO=$HOME/Work/fluxninja/grafana + +# Linux-specific configuration +if [[ $OSTYPE == 'linux'* ]]; then + export QT_QPA_FONTDIR=~/.local/share/fonts +fi + +# Source local configuration +if [ -f ~/.zshrc_local ]; then + source ~/.zshrc_local +fi diff --git a/dot_zshrc.d/00-profile.zsh b/dot_zshrc.d/00-profile.zsh deleted file mode 100644 index 727f74ec762..00000000000 --- a/dot_zshrc.d/00-profile.zsh +++ /dev/null @@ -1,15 +0,0 @@ -# source ~/.zprofile if ZPROFILE_SOURCED is not set -if [[ -z "$ZPROFILE_SOURCED" ]]; then - source ~/.zprofile -fi - -# Check for Homebrew to be present, install if it's missing -if ! command -v brew &> /dev/null; then - echo "Installing homebrew..." - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - # source ~/.zprofile to update PATH - source ~/.zprofile - ~/bin/executable_autoupdate.zsh --force -fi - -figlet -w 80 NeoPilot Zsh && echo "" 2&>/dev/null diff --git a/dot_zshrc.d/10-environment.zsh b/dot_zshrc.d/10-environment.zsh deleted file mode 100644 index 43aa6babd91..00000000000 --- a/dot_zshrc.d/10-environment.zsh +++ /dev/null @@ -1,32 +0,0 @@ -export LS_COLORS="$(vivid generate gruvbox-dark)" - -export BAT_THEME="gruvbox-dark" - -# FZF theme -- See https://github.com/fnune/base16-fzf -source $HOME/assets/base16-gruvbox-dark-medium.config - -export LESSOPEN="|$(brew --prefix)/bin/lesspipe.sh %s" -export LESSCOLORIZER="bat --color=always" -export LESS="-R" - -export MANPAGER="sh -c 'col -bx | bat -l man -p'" - -export EDITOR=nvim -export SET_TERMINAL_COLORS=true - -if [[ -z "$START_TMUX" ]]; then - export START_TMUX=true -fi - -# Set LANGTOOL env to empty values -export LANGTOOL_USERNAME="" -export LANGTOOL_API_KEY="" -export LANGTOOL_HTTP_URI="" - -# FluxNinja Aperture Tilt Env Vars -export TILT_APERTURE_SSH_KEY_PUB=$HOME/.ssh/id_ed25519.pub -export TILT_GRAFANA_REPO=$HOME/Work/fluxninja/grafana - -if [[ $OSTYPE == 'linux'* ]]; then - export QT_QPA_FONTDIR=~/.local/share/fonts -fi diff --git a/dot_zshrc.d/20-functions.zsh b/dot_zshrc.d/20-functions.zsh deleted file mode 100644 index af4d0912f56..00000000000 --- a/dot_zshrc.d/20-functions.zsh +++ /dev/null @@ -1,364 +0,0 @@ -function set_terminal { - if [[ -z "${TERMINAL:-}" ]]; then - - # | - # | Check for the terminal name (depening on os) - # | - OS="$(uname)" - if [[ "$OS" = "Darwin" ]]; then - export TERMINAL=$TERM_PROGRAM - # test whether ~/.iterm2_profile_check_v2 doesn't exist - if [[ ! -e "${HOME}/.iterm2_profile_check_v2" ]]; then - rm -f "${HOME}/.iterm2_profile_check" - if gum confirm "Do you want to use NeoPilot's bundled iTerm2 colors/font profile?"; then - # install iterm2 profile - cp ~/assets/iterm2_gruvbox.json ~/Library/Application\ Support/iTerm2/DynamicProfiles/ - # execute the script - pip3 install iterm2 && python3 ~/assets/iterm2_default.py && touch "${HOME}/.iterm2_profile_check_v2" || (echo; echo; echo "Failed to install iTerm2 profile. You might need to enable Python API within iTerm2 preferences (under Magic tab). Press Enter to continue." && read) - # ask about wallpaper - if gum confirm "Do you want to use matching wallpaper?"; then - # set the wallpaper to ~/assets/apple_gruvbox.heic - osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$HOME/assets/apple_gruvbox.heic\"" - fi - else - echo "no" > "${HOME}/.iterm2_profile_check_v2" - fi - fi - return - fi - - # Other OS'es - if [[ "${OS#CYGWIN}" != "${OS}" ]]; then - export TERMINAL="mintty" - elif [[ "$TERM" = "xterm-kitty" ]]; then - export TERMINAL="kitty" - else - # | - # | Depending on how the script was invoked, we need - # | to loop until pid is no longer a subshell - # | - pid="$$" - export TERMINAL="$(ps -h -o comm -p $pid)" - while [[ "${TERMINAL:(-2)}" == "sh" ]]; do - pid="$(ps -h -o ppid -p $pid)" - export TERMINAL="$(ps -h -o comm -p $pid)" - done - fi - fi -} - - -# check whether tmux command exists -if [[ -x "$(command -v tmux)" ]]; then - if $START_TMUX; then - export START_TMUX=false - set_terminal - DETACHED_SESSIONS=$(tmux ls 2&>/dev/null | grep -v attached) - # check whether tmux has sessions that are in detached state - if [[ -n "$DETACHED_SESSIONS" ]]; then - # get the list of detached sessions - DETACHED_SESSIONS=$(tmux ls | grep -v attached) - # Add "New Session" to the list of detached sessions - DETACHED_SESSIONS="New Session\n$DETACHED_SESSIONS" - #local PREVIEW="TOKEN={} && echo 'token: $TOKEN'" - # use fzf to select a session - SESSION_NAME=$(echo "$DETACHED_SESSIONS" | - fzf --header="== Attach to a detached session ==" \ - --ansi --color="dark" \ - --preview="$HOME/assets/.session_preview {}") - # if the user selected a session, attach to it - # otherwise, create a new session - if [[ $SESSION_NAME == "New Session" ]]; then - tmux -u new-session - else - # extract session name - SESSION_NAME=$(echo "$SESSION_NAME" | cut -d':' -f1) - tmux -u attach -t $SESSION_NAME - fi - else - tmux -u new-session - fi - exit - fi -fi - -source ~/assets/utils.zsh - -# See https://unix.stackexchange.com/q/150649/126543 -function expand-command-aliases() { - cmd="$1" - functions[expandaliasestmp]="${cmd}" - print -rn -- "${functions[expandaliasestmp]#$' '}" - unset 'functions[expandaliasestmp]' -} - -_brew_completion_update=false - -func preexec() { - export LAST_COMMAND="$(expand-command-aliases "$1")" - # Do nothing at all if we are not in tmux, second test is needed in - # case of an ssh session being run from within tmux, which could result - # in $TMUX from the parent session being set without tmux being - # connected. - if [ -n "$TMUX" ] && tmux ls >/dev/null 2>/dev/null; then - eval "$(tmux show-environment -s | grep -v \'^unset')" - local uuid="$(tmux show-environment -g TMUX_UUID 2>/dev/null)" - # check whether $LAST_TMUX_UUID is set - if [[ -z "$LAST_TMUX_UUID" ]]; then - export LAST_TMUX_UUID="$uuid" - else - # check whether $LAST_TMUX_UUID is the same as $uuid - if [ "$LAST_TMUX_UUID" != "$uuid" ]; then - export LAST_TMUX_UUID="$uuid" - echo -e "${BLUE_BRIGHT} == Autoupdate detected | Zsh reloading == ${RESET}" - # tmux respawn pane and new login shell to reload zsh - # cd to the current directory - # run the LAST_COMMAND - tmux respawn-pane -k -t "$TMUX_PANE" "cd \"$PWD\" && $LAST_COMMAND && zsh --login" - echo - echo -e "${BLUE_BRIGHT} == Zsh reloaded == ${RESET}" - echo - fi - fi - fi - - # if last command contained "brew install" or "brew upgrade" or "brew uninstall" or "brew reinstall" the set _brew_completion_update=1 - if [[ "$LAST_COMMAND" =~ "brew install" ]] || [[ "$LAST_COMMAND" =~ "brew upgrade" ]] || [[ "$LAST_COMMAND" =~ "brew uninstall" ]] || [[ "$LAST_COMMAND" =~ "brew reinstall" ]]; then - - _brew_completion_update=true - fi -} - -function precmd() { - # if _brew_completion_update is set to true, run "zinit update brew-completions" - if $_brew_completion_update; then - zinit update brew-completions - _brew_completion_update=false - fi -} - -func zshexit() { -#remove gh status -rm /tmp/gh_$$ &>/dev/null -# remove watch on home directory -watchman watch-del $HOME >/dev/null -figlet -w 80 NeoPilot zsh -cowsay -d "zsh exiting... see you later..." -sleep 0.5 -} - -# configure zsh to show hidden files in auto-completion -setopt globdots -setopt interactivecomments - -eval $(thefuck --alias) - -function @yazpt_segment_nl() { -# check whether $last_yazpt_vcs is not equal to $yazpt_state[vcs] -#if [[ "$last_yazpt_vcs" != "$yazpt_state[vcs]" ]]; then -# spinner -q -s "timeout 2 $HOME/bin/gh_checks_status.sh > /tmp/gh_$$" -#fi -last_yazpt_vcs="$yazpt_state[vcs]" -yazpt_state[nl]="" -# read from /tmp/gh_"$$" if it exists -if [[ -e "/tmp/gh_$$" ]]; then - local check="$(cat /tmp/gh_$$" - # check whether check is empty - if [ -n "$check" ]; then - if [ -n "$yazpt_state[vcs]" ]; then - yazpt_state[nl]+=" | " - fi - yazpt_state[nl]+=" GitHub checks $check" - fi -fi - -local hour=$(date +%H) -if (( 23 <= $hour || $hour <= 6 )); then - if [ -n "$yazpt_state[nl]" ] || [ -n "$yazpt_state[vcs]" ]; then - yazpt_state[nl]+=" | " - fi - yazpt_state[nl]+="%F{$YAZPT_CWD_COLOR}it's late, yo - get some sleep!%f" -fi -# check whether $yazpt_state[nl] or $yazpt_state[vcs] is not empty and add a new line if it is not empty -if [ -n "$yazpt_state[nl]" ] || [ -n "$yazpt_state[vcs]" ]; then - yazpt_state[nl]+=$'\n' -fi -} - -function @yazpt_segment_excuse() { -# check whether exit code of last command was not 0 or 127 or 130 -local code="$yazpt_state[exit_code]" -local excuse_msg='' -if [[ $code -ne 0 && $code -ne 127 && "$yazpt_state[exit_code]" -ne 130 ]] && $INSULTS_ENABLED; then - local excuse_msg='💥uh-ho💥 ' - excuse_msg+="$(excuse)" - excuse_msg+=$'\n' -fi -yazpt_state[excuse]=$excuse_msg -} - -APP_CHEERS_PATTERNS=( - "git push" - "git_ship" -) - -function @yazpt_segment_cheers() { -local do_cheers=false -local cheers_msg='' -# check whether exit code of last command was 0 -if $CHEERS_ENABLED && [ "$yazpt_state[exit_code]" -eq 0 ] ; then - # check whether $LAST_COMMAND contained any of the APP_CHEERS_PATTERNS - for pattern in "${APP_CHEERS_PATTERNS[@]}"; do - if [[ "$LAST_COMMAND" == *"$pattern"* ]]; then - do_cheers=true - break - fi - done -fi -if $do_cheers; then - cheers_msg=' 🍻🎉🍻 ' - cheers_msg+="$(compliment)" - cheers_msg+=$'\n' - if [[ $OSTYPE == 'darwin'* ]]; then - # call fireworks if $ITERM2_INTEGRATION_DETECTED is true - if $ITERM2_INTEGRATION_DETECTED; then - $HOME/.iterm2/it2attention fireworks - fi - fi -fi -yazpt_state[cheers]=$cheers_msg -} - -function configure_yazpt { - YAZPT_LAYOUT=$PROMPT_LAYOUT - YAZPT_CWD_COLOR=6 # cyan - YAZPT_EXECTIME_MIN_SECONDS=1 -} - -zvm_config() { - # always identify as xterm-256color to zsh-vi-mode plugin - ZVM_TERM=xterm-256color - ZVM_INSERT_MODE_CURSOR=$ZVM_CURSOR_BLINKING_BEAM - ZVM_NORMAL_MODE_CURSOR=$ZVM_CURSOR_BLOCK - ZVM_OPPEND_MODE_CURSOR=$ZVM_CURSOR_UNDERLINE -} - -zvm_after_init() { - zicompinit - - [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh - - # zoxide - zinit wait lucid atinit'eval "$(zoxide init zsh --cmd cd)"' nocd for /dev/null - - zicdreplay - - # fzf-tab needs to be loaded after compinit, but before fast-syntax-highlighting - zinit light Aloxaf/fzf-tab - # use tmux popups in case we are in tmux - if [ -n "$TMUX" ]; then - zstyle ':fzf-tab:*' fzf-command ftb-tmux-popup - fi - - ### NOTE: In order to generate previews, context is needed. The trick to find the context is to type the commmand to the point where completion is needed and press "C-x h". You will need to call "enable-fzf-tab" after this to reenable fzf-tab. - - # preview git -- these don't work with homebrew completions so we make a copy of zsh's version at ~/.completions/_git - # zsh version - https://github.com/zsh-users/zsh/blob/master/Completion/Unix/Command/_git - zstyle ':fzf-tab:complete:git-(add|diff|restore):*' fzf-preview - 'git diff $word | delta' - zstyle ':fzf-tab:complete:git-(add|diff|restore):*' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:git-(add|diff|restore):*' popup-pad 50 50 - - zstyle ':fzf-tab:complete:git-log:*' fzf-preview - 'git log --color=always $word' - zstyle ':fzf-tab:complete:git-log:*' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:git-log:*' popup-pad 50 50 - - zstyle ':fzf-tab:complete:git-help:*' fzf-preview - 'git help $word | bat -plman --color=always' - zstyle ':fzf-tab:complete::*' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete::*' popup-pad 50 50 - - zstyle ':fzf-tab:complete:git-show:*' fzf-preview - 'case "$group" in - "commit tag") git show --color=always $word ;; - *) git show --color=always $word | delta ;; - esac' - zstyle ':fzf-tab:complete:git-show:*' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:git-show:*' popup-pad 50 50 - - zstyle ':fzf-tab:complete:git-checkout:*' fzf-preview - 'case "$group" in - "modified file") git diff $word ;; - "recent commit object name") git show --color=always $word ;; - *) git log --color=always $word ;; - esac' - zstyle ':fzf-tab:complete:git-checkout:*' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:git-checkout:*' popup-pad 50 50 - - # ignore some patterns - zstyle ':completion::complete:*:*:files' ignored-patterns '.DS_Store' 'Icon?' - zstyle ':completion::complete:*:*:globbed-files' ignored-patterns '.DS_Store' 'Icon?' - zstyle ':completion::complete:rm:*:globbed-files' ignored-patterns - - # disable sort when completing `git checkout` - zstyle ':completion:*:git-checkout:*' sort false - # set descriptions format to enable group support - zstyle ':completion:*:descriptions' format '[%d]' - # set list-colors to enable filename colorizing - zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} - # switch group using `,` and `.` - zstyle ':fzf-tab:*' switch-group 'F1' 'F2' - # give a preview of commandline arguments when completing `kill` - zstyle ':completion:*:*:*:*:processes' command "ps -u $USER -o pid,user,comm -w -w" - zstyle ':fzf-tab:complete:(kill|ps):argument-rest' fzf-preview - '[[ $group == "[process ID]" ]] && ps --pid=$word -o cmd --no-headers -w -w' - zstyle ':fzf-tab:complete:(kill|ps):argument-rest' fzf-flags --preview-window=down:3:wrap - zstyle ':fzf-tab:complete:(kill|ps):*' popup-pad 0 3 - - # preview environment variables - zstyle ':fzf-tab:complete:(-parameter-|-brace-parameter-|export|unset|expand):*' - fzf-preview 'echo ${(P)word}' - zstyle ':fzf-tab:complete:(-parameter-|-brace-parameter-|export|unset|expand):*' popup-pad 0 1 - zstyle ':fzf-tab:complete:(-parameter-|-brace-parameter-|export|unset|expand):*' fzf-flags --preview-window=down:1:wrap - - # use eza for previewing commands that work at directory/path level - zstyle ':fzf-tab:complete:(cd|eza|ls|fd|find|cp|mv|rm):argument-rest' fzf-preview 'eza --git -a -1 --color=always --icons $realpath' - zstyle ':fzf-tab:complete:(cd|eza|ls|fd|find|cp|mv|rm):argument-rest' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:(cd|eza|ls|fd|find|cp|mv|rm):argument-rest' popup-pad 50 50 - - # use lessfilter to preview content files, directories etc. - zstyle ':fzf-tab:complete:(cat|bat|vim|nvim|vimr|nvim-qt):argument-rest' fzf-preview 'LESSOPEN="|~/assets/lessfilter %s" less ${(Q)realpath}' - zstyle ':fzf-tab:complete:(cat|bat|vim|nvim|vimr|nvim-qt):argument-rest' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:(cat|bat|vim|nvim|vimr|nvim-qt):argument-rest' popup-pad 50 50 - - if [[ $OSTYPE == 'linux'* ]]; then - zstyle ':fzf-tab:complete:systemctl-*:*' fzf-preview 'SYSTEMD_COLORS=1 systemctl status $word' - zstyle ':fzf-tab:complete:systemctl-*:*' popup-pad 50 50 - fi - - zstyle ':fzf-tab:complete:tldr:argument-1' fzf-preview 'tldr --color always $word' - zstyle ':fzf-tab:complete:tldr:argument-1' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:tldr:argument-1' popup-pad 50 50 - - zstyle ':fzf-tab:complete:man:' fzf-preview 'batman --color=always $word' - zstyle ':fzf-tab:complete:man:' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:man:' popup-pad 50 50 - - zstyle ':fzf-tab:complete:-command-:*' fzf-preview - '(out=$(tldr --color always "$word") 2>/dev/null && echo $out) || (out=$(batman --color=always "$word") 2>/dev/null && echo $out) || (out=$(source ~/.zprofile && which "$word") && echo $out) || echo "${(P)word}"' - zstyle ':fzf-tab:complete:-command-:*' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:-command-:*' popup-pad 50 50 - - - zstyle ':fzf-tab:complete:brew-(install|uninstall|search|info):*-argument-rest' fzf-preview 'brew info $word' - zstyle ':fzf-tab:complete:brew-(install|uninstall|search|info):*-argument-rest' fzf-flags --preview-window=right:70%:wrap - zstyle ':fzf-tab:complete:brew-(install|uninstall|search|info):*-argument-rest' popup-pad 50 50 - - # these should be the last zinit plugins - FAST_WORK_DIR=~/.config/fsh - zinit wait lucid light-mode for \ - zdharma-continuum/fast-syntax-highlighting \ - atload"_zsh_autosuggest_start" \ - zsh-users/zsh-autosuggestions -} diff --git a/dot_zshrc.d/30-plugins.zsh b/dot_zshrc.d/30-plugins.zsh deleted file mode 100644 index 5f44df6c37e..00000000000 --- a/dot_zshrc.d/30-plugins.zsh +++ /dev/null @@ -1,38 +0,0 @@ -zinit ice wait'!0' atload'source "$yazpt_default_preset_file"; configure_yazpt;yazpt_precmd' nocd lucid -zinit light jakshin/yazpt - -# install git-extras via zinit instead of brew -zinit lucid wait'0a' for as"program" pick"$ZPFX/bin/git- கருவ" src"etc/git-extras-completion.zsh" make"PREFIX=$ZPFX" tj/git-extras - - -# install direnv via zinit instead of brew -zinit from"gh-r" as"program" mv"direnv* -> direnv" atclone'./direnv hook zsh > zhook.zsh' atpull'%atclone' pick"direnv" src="zhook.zsh" for direnv/direnv - -# zinit light zdharma-continuum/zui -# zinit light zdharma-continuum/zbrowse # use '^B' to open zbrowse -# zinit wait lucid for zdharma-continuum/zinit-console - -zinit snippet OMZ::lib/key-bindings.zsh - -zinit light MichaelAquilina/zsh-you-should-use - -# install brew's completions except for git -zinit id-as='brew-completions' wait as='completion' lucid atclone='print Installing Brew completions...; rm -rf $ZPFX/brew_comps_others 2>/dev/null; mkdir -p $ZPFX/brew_comps_others; rm -rf $ZPFX/brew_comps_zsh 2>/dev/null; mkdir -p $ZPFX/brew_comps_zsh; command cp -f $(brew --prefix)/share/zsh/site-functions/^_* $ZPFX/brew_comps_others; command cp -f $(brew --prefix)/share/zsh/site-functions/_* $ZPFX/brew_comps_zsh; command rm $ZPFX/brew_comps_zsh/_git; zinit creinstall -q $ZPFX/brew_comps_zsh; zinit cclear; enable-fzf-tab' atload='fpath=( ${(u)fpath[@]:#$(brew --prefix)/share/zsh/site-functions/*} ); fpath+=( $ZPFX/brew_comps_others )' atpull='%atclone' nocompile run-atpull for zdharma-continuum/null - -zinit id-as='system-completions' wait as='completion' lucid atclone='print Installing system completions...; mkdir -p $ZPFX/zsh_comps; command cp -f $(brew --prefix)/share/zsh/functions/^_* $ZPFX/zsh_comps; zinit creinstall -q $(brew --prefix)/share/zsh/functions; zinit cclear; enable-fzf-tab' atload='fpath=( ${(u)fpath[@]:#$(brew --prefix)/share/zsh/functions/*} ); fpath+=( $ZPFX/zsh_comps )' atpull="%atclone" nocompile run-atpull for zdharma-continuum/null - -zinit id-as='fn-completions' wait as='completion' lucid atclone='print Installing FN completions...; zinit creinstall -q $HOME/.completions; zinit cclear; enable-fzf-tab' atload='fpath=( ${(u)fpath[@]:#$HOME/.completions/*} )' atpull="%atclone" nocompile run-atpull for zdharma-continuum/null - - -zinit ice wait as'completion' lucid -zinit snippet https://github.com/sainnhe/zsh-completions/blob/master/src/custom/_fzf - -#zinit ice wait'0' lucid -#zinit light sainnhe/zsh-completions - -zinit ice wait blockf atpull'zinit creinstall -q .' lucid -zinit light zsh-users/zsh-completions - -zinit ice depth=1 -zinit light jeffreytse/zsh-vi-mode - diff --git a/dot_zshrc.d/40-prompt.zsh b/dot_zshrc.d/40-prompt.zsh deleted file mode 100644 index 0df5eb9c531..00000000000 --- a/dot_zshrc.d/40-prompt.zsh +++ /dev/null @@ -1,25 +0,0 @@ -PS1="$(pwd) > " -PROMPT_LAYOUT='[] ' - -if [[ -z "$ITERM2_INTEGRATION_DETECTED" ]]; then - ITERM2_INTEGRATION_DETECTED=false -fi - -if [[ $OSTYPE == 'darwin'* ]]; then - # check whether $TERMINAL is iTerm.app - if [[ $TERMINAL == "iTerm.app" ]]; then - export ITERM_ENABLE_SHELL_INTEGRATION_WITH_TMUX=true - # iterm2 prompt mark doesn't work under tmux for some reason - test -e "${HOME}/.iterm2_shell_integration.zsh" && source "${HOME}/.iterm2_shell_integration.zsh" && \ - ITERM2_INTEGRATION_DETECTED=true && PROMPT_LAYOUT="%{$(iterm2_prompt_mark)%} $PROMPT_LAYOUT%{$(iterm2_prompt_end)%}" - # read $HOME/.iterm2_profile_check_v2 file and check if it contains "no" - if [[ $(cat "${HOME}/.iterm2_profile_check_v2") == "no" ]]; then - SET_TERMINAL_COLORS=true - else - SET_TERMINAL_COLORS=false - fi - ## if the terminal is ghostty don't set terminal colors - elif [[ $TERMINAL == "ghostty" ]]; then - SET_TERMINAL_COLORS=false - fi -fi diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index d37accce08d..00000000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "dotfiles", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/assets/apple_gruvbox.heic b/scripts/assets/apple_gruvbox.heic similarity index 100% rename from assets/apple_gruvbox.heic rename to scripts/assets/apple_gruvbox.heic diff --git a/assets/base16-gruvbox-dark-medium.config b/scripts/assets/base16-gruvbox-dark-medium.config similarity index 100% rename from assets/base16-gruvbox-dark-medium.config rename to scripts/assets/base16-gruvbox-dark-medium.config diff --git a/bin/executable_dot_session_preview b/scripts/assets/executable_dot_session_preview similarity index 100% rename from bin/executable_dot_session_preview rename to scripts/assets/executable_dot_session_preview diff --git a/bin/executable_dotfiles-edit.sh b/scripts/assets/executable_dotfiles-edit.sh similarity index 88% rename from bin/executable_dotfiles-edit.sh rename to scripts/assets/executable_dotfiles-edit.sh index d6c98b1940e..455b5b44306 100644 --- a/bin/executable_dotfiles-edit.sh +++ b/scripts/assets/executable_dotfiles-edit.sh @@ -10,5 +10,5 @@ cd $HOME if [ "$1" = "personal" ]; then nvim -p .gitconfig_local .vimrc_local .vimrc_plugins .autoupdate_local.zsh .tmux.conf_local .brew_local else - nvim -p .vimrc .config/nvim/init.vim .config/nvim/coc-settings.json .zshrc .gitconfig .gitignore .zprofile .tmux.conf .tmux.conf.settings ~/bin/executable_autoupdate.zsh ~/bin/sync_brews.sh + nvim -p .vimrc .config/nvim/init.vim .config/nvim/coc-settings.json .zshrc .gitconfig .gitignore .zprofile .tmux.conf .tmux.conf.settings ~/scripts/bin/autoupdate.zsh ~/scripts/bin/sync_brews.sh fi diff --git a/bin/executable_install.sh b/scripts/assets/executable_install.sh old mode 100755 new mode 100644 similarity index 75% rename from bin/executable_install.sh rename to scripts/assets/executable_install.sh index 3838b1f53e4..dca2bac27f1 --- a/bin/executable_install.sh +++ b/scripts/assets/executable_install.sh @@ -22,11 +22,13 @@ read -r answer if [ "$answer" = "n" ]; then echo "Installing local homebrew..." mkdir homebrew + # Use official Homebrew installation with verification curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew else # delete local homebrew if it exists rm -rf ~/homebrew echo "Installing system homebrew..." + # Use official installation method /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" fi @@ -40,12 +42,14 @@ brew install chezmoi brew install zsh # install gum brew install gum -# add $(which zsh) to the list of shells if it doesn't exist -if ! grep -q $(which zsh) /etc/shells; then - echo "Adding $(which zsh) to /etc/shells" - sudo sh -c "echo $(which zsh) >> /etc/shells" + +# Safely add zsh to shells if not present +ZSH_PATH=$(which zsh) +if ! grep -q "$ZSH_PATH" /etc/shells 2>/dev/null; then + echo "Adding $ZSH_PATH to /etc/shells" + sudo sh -c "echo '$ZSH_PATH' >> /etc/shells" fi -chsh -s $(which zsh) +chsh -s "$ZSH_PATH" echo "Authenticating with GitHub. Please make sure to choose ssh option for authentication." @@ -79,13 +83,20 @@ chezmoi apply -v # run autoupdate script echo "Running autoupdate script..." -~/bin/executable_autoupdate.zsh --force +~/scripts/bin/autoupdate.zsh --force # if autoupdate failed, exit if [ $? -ne 0 ]; then echo "Failed to run autoupdate script" exit 1 fi -# reboot computer -echo "Restarting computer..." -sudo reboot +# Ask user before rebooting instead of forcing it +echo "Installation complete! A restart is recommended to apply all changes." +echo "Would you like to restart now? [y/N]" +read -r restart_answer +if [[ $restart_answer =~ ^[Yy]$ ]]; then + echo "Restarting computer..." + sudo reboot +else + echo "Please restart your computer manually when convenient." +fi diff --git a/bin/executable_install_gruvbox.sh b/scripts/assets/executable_install_gruvbox.sh similarity index 100% rename from bin/executable_install_gruvbox.sh rename to scripts/assets/executable_install_gruvbox.sh diff --git a/bin/executable_insults.zsh b/scripts/assets/executable_insults.zsh similarity index 99% rename from bin/executable_insults.zsh rename to scripts/assets/executable_insults.zsh index 9ec63e6c818..3ce4a8ed765 100644 --- a/bin/executable_insults.zsh +++ b/scripts/assets/executable_insults.zsh @@ -318,7 +318,7 @@ function insult() { "Puffed up punchinello!" "Thundering herd of zapotecs!" "Borgia!" - "Miserable blundering barbecued blister . . . (Haddock does not complete the curse)" + "Miserable blundering barbecued blister!" "Subtropical sea louse!" "Confounded rattletrap!" "Tin-can contraption!" diff --git a/bin/executable_iterm2_default.py b/scripts/assets/executable_iterm2_default.py similarity index 100% rename from bin/executable_iterm2_default.py rename to scripts/assets/executable_iterm2_default.py diff --git a/bin/executable_lessfilter b/scripts/assets/executable_lessfilter similarity index 100% rename from bin/executable_lessfilter rename to scripts/assets/executable_lessfilter diff --git a/bin/executable_set_colors.zsh b/scripts/assets/executable_set_colors.zsh similarity index 100% rename from bin/executable_set_colors.zsh rename to scripts/assets/executable_set_colors.zsh diff --git a/bin/executable_utils.zsh b/scripts/assets/executable_utils.zsh similarity index 72% rename from bin/executable_utils.zsh rename to scripts/assets/executable_utils.zsh index f743979cbee..d224ee4851b 100644 --- a/bin/executable_utils.zsh +++ b/scripts/assets/executable_utils.zsh @@ -21,8 +21,94 @@ MAGENTA_BRIGHT="\e[95m" CYAN_BRIGHT="\e[96m" WHITE_BRIGHT="\e[97m" -function silent_background() { - set +m && { "$@" 2>&3 & disown; pid=$!; } 3>&2 2>/dev/null && set -m +# Enhanced utility functions with better error handling and status reporting + +# Status reporting functions (enhanced versions of existing color codes) +print_status() { + local status=$1 + local message=$2 + + case $status in + "error") + echo -e "${RED}❌ $message${RESET}" + ;; + "warning") + echo -e "${YELLOW}⚠️ $message${RESET}" + ;; + "success") + echo -e "${GREEN}✅ $message${RESET}" + ;; + "info") + echo -e "${BLUE}ℹ️ $message${RESET}" + ;; + "step") + echo -e "${CYAN}➡️ $message${RESET}" + ;; + "title") + echo -e "${MAGENTA}🔧 $message${RESET}" + ;; + *) + echo -e " $message" + ;; + esac +} + +# Safe command execution with error handling +safe_execute() { + local command="$1" + local error_msg="${2:-Command failed}" + + if eval "$command"; then + return 0 + else + local exit_code=$? + print_status error "$error_msg (exit code: $exit_code)" + return $exit_code + fi +} + +# Check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Platform detection +is_macos() { + [[ "$OSTYPE" == "darwin"* ]] +} + +is_linux() { + [[ "$OSTYPE" == "linux-gnu"* ]] +} + +# Array utilities +array_contains() { + local array="$1[@]" + local seeking=$2 + local in=1 + for element in "${!array}"; do + if [[ $element == "$seeking" ]]; then + in=0 + break + fi + done + return $in +} + +# Enhanced version of silent_background with better error handling +silent_background() { + set +m && { "$@" 2>&3 & disown; pid=$!; } 3>&2 2>/dev/null && set -m +} + +# Error handling utility +handle_error() { + local exit_code=$? + local command="$1" + if [ $exit_code -ne 0 ]; then + print_status error "Command failed: $command (exit code: $exit_code)" + return $exit_code + fi + return 0 } function zsh_stats() { @@ -106,9 +192,9 @@ fi source $HOME/.local/share/zinit/zinit.git/zinit.zsh zinit light marzocchi/zsh-notify -zstyle ':notify:*' error-icon "$HOME/assets/lose.png" +zstyle ':notify:*' error-icon "$HOME/scripts/assets/lose.png" zstyle ':notify:*' error-title "wow such #fail" -zstyle ':notify:*' success-icon "$HOME/assets/win.png" +zstyle ':notify:*' success-icon "$HOME/scripts/assets/win.png" zstyle ':notify:*' success-title "very #success. wow" # aggressively notify when commands complete as we use a whitelist zstyle ':notify:*' command-complete-timeout 1 @@ -121,8 +207,8 @@ if [[ $OSTYPE == 'linux'* ]]; then # linux zstyle ':notify:*' app-name sh zstyle ':notify:*' expire-time 5000 - zstyle ':notify:*' error-sound "$HOME/assets/lose.ogg" - zstyle ':notify:*' success-sound "$HOME/assets/win.ogg" + zstyle ':notify:*' error-sound "$HOME/scripts/assets/lose.ogg" + zstyle ':notify:*' success-sound "$HOME/scripts/assets/win.ogg" fi if [[ $OSTYPE == 'darwin'* ]]; then diff --git a/scripts/assets/font_install.zsh b/scripts/assets/font_install.zsh new file mode 100644 index 00000000000..a44a2e43086 --- /dev/null +++ b/scripts/assets/font_install.zsh @@ -0,0 +1,74 @@ +#!/usr/bin/env zsh + +# Optimized font installation for dotfiles +# This script handles nerd font installation for Linux systems + +install_nerd_fonts() { + local nerd_font='https://github.com/ryanoasis/nerd-fonts/releases/download/v2.3.3' + + # Font mapping: URL -> filename pattern + typeset -A fonts=( + "${nerd_font}/DejaVuSansMono.zip" "DejaVu Sans Mono Nerd Font Complete.ttf" + "${nerd_font}/DroidSansMono.zip" "Droid Sans Mono Nerd Font Complete.otf" + "${nerd_font}/Go-Mono.zip" "Go Mono Nerd Font Complete.ttf" + "${nerd_font}/Hack.zip" "Hack Regular Nerd Font Complete Mono.ttf" + "${nerd_font}/FiraCode.zip" "Fira Code Regular Nerd Font Complete Mono.ttf" + "${nerd_font}/JetBrainsMono.zip" "JetBrains Mono Regular Nerd Font Complete Mono.ttf" + "${nerd_font}/Meslo.zip" "Meslo LG S Regular Nerd Font Complete Mono.ttf" + "${nerd_font}/SourceCodePro.zip" "Sauce Code Pro Nerd Font Complete Mono.ttf" + "https://github.com/googlefonts/noto-emoji/raw/main/fonts/NotoColorEmoji.ttf" "NotoColorEmoji.ttf" + ) + + local fonts_dir="${HOME}/.local/share/fonts" + local install_fonts=() + + # Ensure fonts directory exists + mkdir -p "$fonts_dir" + + # Check which fonts need to be installed + for font_url in "${(@k)fonts}"; do + local font_pattern="${fonts[$font_url]}" + if [[ -z "$(find "$fonts_dir" -name "$font_pattern" -print -quit 2>/dev/null)" ]]; then + install_fonts+=("$font_url") + fi + done + + # Install missing fonts + if [[ ${#install_fonts[@]} -gt 0 ]]; then + print_status info "Installing nerd fonts:" + for font_url in "${install_fonts[@]}"; do + echo " ${fonts[$font_url]}" + done + + for font_url in "${install_fonts[@]}"; do + echo "Downloading $font_url" + local font_file=$(basename "${font_url}") + + if ! wget -q "$font_url" -O "$font_file"; then + print_status warning "Failed to download $font_url" + continue + fi + + if [[ "$font_file" == *".zip" ]]; then + if command -v unzip >/dev/null 2>&1; then + unzip -o "$font_file" -d "$fonts_dir" && rm "$font_file" + else + print_status warning "unzip not available, skipping $font_file" + rm "$font_file" + fi + else + mv "$font_file" "$fonts_dir" + fi + done + + # Clean up Windows font variants + find "$fonts_dir" -name '*Windows Compatible*' -delete 2>/dev/null || true + + # Update font cache + if command -v fc-cache >/dev/null 2>&1; then + fc-cache -fv + fi + else + print_status success "All nerd fonts already installed." + fi +} diff --git a/assets/fuzzymenu.png b/scripts/assets/fuzzymenu.png similarity index 100% rename from assets/fuzzymenu.png rename to scripts/assets/fuzzymenu.png diff --git a/assets/iterm2_gruvbox.json b/scripts/assets/iterm2_gruvbox.json similarity index 100% rename from assets/iterm2_gruvbox.json rename to scripts/assets/iterm2_gruvbox.json diff --git a/assets/lose.ogg b/scripts/assets/lose.ogg similarity index 100% rename from assets/lose.ogg rename to scripts/assets/lose.ogg diff --git a/assets/lose.png b/scripts/assets/lose.png similarity index 100% rename from assets/lose.png rename to scripts/assets/lose.png diff --git a/assets/tmux-fzf.png b/scripts/assets/tmux-fzf.png similarity index 100% rename from assets/tmux-fzf.png rename to scripts/assets/tmux-fzf.png diff --git a/assets/tmux-menu.png b/scripts/assets/tmux-menu.png similarity index 100% rename from assets/tmux-menu.png rename to scripts/assets/tmux-menu.png diff --git a/assets/vim.png b/scripts/assets/vim.png similarity index 100% rename from assets/vim.png rename to scripts/assets/vim.png diff --git a/assets/vim_ide.png b/scripts/assets/vim_ide.png similarity index 100% rename from assets/vim_ide.png rename to scripts/assets/vim_ide.png diff --git a/assets/win.ogg b/scripts/assets/win.ogg similarity index 100% rename from assets/win.ogg rename to scripts/assets/win.ogg diff --git a/assets/win.png b/scripts/assets/win.png similarity index 100% rename from assets/win.png rename to scripts/assets/win.png diff --git a/assets/zsh.png b/scripts/assets/zsh.png similarity index 100% rename from assets/zsh.png rename to scripts/assets/zsh.png diff --git a/scripts/assets/zsh_bindings.zsh b/scripts/assets/zsh_bindings.zsh new file mode 100644 index 00000000000..9b3ca69ca1d --- /dev/null +++ b/scripts/assets/zsh_bindings.zsh @@ -0,0 +1,127 @@ +# Zsh key bindings and completion configuration +# This file contains fzf-tab and completion settings + +# Zsh Vi Mode configuration +zvm_config() { + # Always identify as xterm-256color to zsh-vi-mode plugin + ZVM_TERM=xterm-256color + ZVM_INSERT_MODE_CURSOR=$ZVM_CURSOR_BLINKING_BEAM + ZVM_NORMAL_MODE_CURSOR=$ZVM_CURSOR_BLOCK + ZVM_OPPEND_MODE_CURSOR=$ZVM_CURSOR_UNDERLINE +} + +# Zsh Vi Mode after init +zvm_after_init() { + zicompinit + [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh + + # Zoxide integration + zinit wait lucid atinit'eval "$(zoxide init zsh --cmd cd)"' nocd for /dev/null + zicdreplay + + # Fzf-tab configuration + zinit light Aloxaf/fzf-tab + + # Use tmux popups in tmux + if [ -n "$TMUX" ]; then + zstyle ':fzf-tab:*' fzf-command ftb-tmux-popup + fi + + # Git completion previews + zstyle ':fzf-tab:complete:git-(add|diff|restore):*' fzf-preview 'git diff $word | delta' + zstyle ':fzf-tab:complete:git-(add|diff|restore):*' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:git-(add|diff|restore):*' popup-pad 50 50 + + zstyle ':fzf-tab:complete:git-log:*' fzf-preview 'git log --color=always $word' + zstyle ':fzf-tab:complete:git-log:*' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:git-log:*' popup-pad 50 50 + + zstyle ':fzf-tab:complete:git-help:*' fzf-preview 'git help $word | bat -plman --color=always' + zstyle ':fzf-tab:complete::*' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete::*' popup-pad 50 50 + + zstyle ':fzf-tab:complete:git-show:*' fzf-preview \ + 'case "$group" in + "commit tag") git show --color=always $word ;; + *) git show --color=always $word | delta ;; + esac' + zstyle ':fzf-tab:complete:git-show:*' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:git-show:*' popup-pad 50 50 + + zstyle ':fzf-tab:complete:git-checkout:*' fzf-preview \ + 'case "$group" in + "modified file") git diff $word | delta ;; + "recent commit object name") git show --color=always $word | delta ;; + *) git log --color=always $word ;; + esac' + zstyle ':fzf-tab:complete:git-checkout:*' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:git-checkout:*' popup-pad 50 50 + + # General completion settings + zstyle ':completion::complete:*:*:files' ignored-patterns '.DS_Store' 'Icon?' + zstyle ':completion::complete:*:*:globbed-files' ignored-patterns '.DS_Store' 'Icon?' + zstyle ':completion::complete:rm:*:globbed-files' ignored-patterns + + zstyle ':completion:*:git-checkout:*' sort false + zstyle ':completion:*:descriptions' format '[%d]' + zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} + zstyle ':fzf-tab:*' switch-group 'F1' 'F2' + + # Process completion + zstyle ':completion:*:*:*:*:processes' command "ps -u $USER -o pid,user,comm -w -w" + zstyle ':fzf-tab:complete:(kill|ps):argument-rest' fzf-preview \ + '[[ $group == "[process ID]" ]] && ps --pid=$word -o cmd --no-headers -w -w' + zstyle ':fzf-tab:complete:(kill|ps):argument-rest' fzf-flags --preview-window=down:3:wrap + zstyle ':fzf-tab:complete:(kill|ps):*' popup-pad 0 3 + + # Environment variable completion + zstyle ':fzf-tab:complete:(-parameter-|-brace-parameter-|export|unset|expand):*' \ + fzf-preview 'echo ${(P)word}' + zstyle ':fzf-tab:complete:(-parameter-|-brace-parameter-|export|unset|expand):*' popup-pad 0 1 + zstyle ':fzf-tab:complete:(-parameter-|-brace-parameter-|export|unset|expand):*' fzf-flags --preview-window=down:1:wrap + + # File/directory operations + zstyle ':fzf-tab:complete:(cd|eza|ls|fd|find|cp|mv|rm):argument-rest' fzf-preview 'eza --git -a -1 --color=always --icons $realpath' + zstyle ':fzf-tab:complete:(cd|eza|ls|fd|find|cp|mv|rm):argument-rest' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:(cd|eza|ls|fd|find|cp|mv|rm):argument-rest' popup-pad 50 50 + + # Content preview + zstyle ':fzf-tab:complete:(cat|bat|vim|nvim|vimr|nvim-qt):argument-rest' fzf-preview 'LESSOPEN="|~/scripts/assets/lessfilter %s" less ${(Q)realpath}' + zstyle ':fzf-tab:complete:(cat|bat|vim|nvim|vimr|nvim-qt):argument-rest' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:(cat|bat|vim|nvim|vimr|nvim-qt):argument-rest' popup-pad 50 50 + + # System-specific completions + if [[ $OSTYPE == 'linux'* ]]; then + zstyle ':fzf-tab:complete:systemctl-*:*' fzf-preview 'SYSTEMD_COLORS=1 systemctl status $word' + zstyle ':fzf-tab:complete:systemctl-*:*' popup-pad 50 50 + fi + + # Tool-specific completions + zstyle ':fzf-tab:complete:tldr:argument-1' fzf-preview 'tldr --color always $word' + zstyle ':fzf-tab:complete:tldr:argument-1' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:tldr:argument-1' popup-pad 50 50 + + zstyle ':fzf-tab:complete:man:' fzf-preview 'batman --color=always $word' + zstyle ':fzf-tab:complete:man:' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:man:' popup-pad 50 50 + + zstyle ':fzf-tab:complete:-command-:*' fzf-preview \ + '(out=$(tldr --color always "$word") 2>/dev/null && echo $out) || (out=$(batman --color=always "$word") 2>/dev/null && echo $out) || (out=$(source ~/.zprofile && which "$word") && echo $out) || echo "${(P)word}"' + zstyle ':fzf-tab:complete:-command-:*' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:-command-:*' popup-pad 50 50 + + zstyle ':fzf-tab:complete:brew-(install|uninstall|search|info):*-argument-rest' fzf-preview 'brew info $word' + zstyle ':fzf-tab:complete:brew-(install|uninstall|search|info):*-argument-rest' fzf-flags --preview-window=right:70%:wrap + zstyle ':fzf-tab:complete:brew-(install|uninstall|search|info):*-argument-rest' popup-pad 50 50 + + # Fast syntax highlighting (must be last) + FAST_WORK_DIR=~/.config/fsh + zinit wait lucid light-mode for \ + zdharma-continuum/fast-syntax-highlighting \ + atload"_zsh_autosuggest_start" \ + zsh-users/zsh-autosuggestions +} + +# Load zsh-vi-mode +zinit ice depth=1 +zinit light jeffreytse/zsh-vi-mode diff --git a/bin/zsh_cnf.zsh b/scripts/assets/zsh_cnf.zsh similarity index 100% rename from bin/zsh_cnf.zsh rename to scripts/assets/zsh_cnf.zsh diff --git a/scripts/assets/zsh_env.zsh b/scripts/assets/zsh_env.zsh new file mode 100644 index 00000000000..a764e42b4e7 --- /dev/null +++ b/scripts/assets/zsh_env.zsh @@ -0,0 +1,26 @@ +# Environment variables and exports +# This file contains basic environment setup + +# Source .zprofile if not already sourced +if [[ -z "$ZPROFILE_SOURCED" ]]; then + source ~/.zprofile +fi + +# Color tools +export LS_COLORS="$(vivid generate gruvbox-dark)" +export BAT_THEME="gruvbox-dark" + +# FZF theme +source $HOME/scripts/assets/base16-gruvbox-dark-medium.config + +# Pager configuration +export LESSOPEN="|$(brew --prefix)/bin/lesspipe.sh %s" +export LESSCOLORIZER="bat --color=always" +export LESS="-R" +export MANPAGER="sh -c 'col -bx | bat -l man -p'" + +# Editor +export EDITOR=nvim + +# Terminal colors (can be overridden in .zshrc_local) +export SET_TERMINAL_COLORS=true diff --git a/dot_zshrc.d/50-conditionals.zsh b/scripts/assets/zsh_integrations.zsh similarity index 50% rename from dot_zshrc.d/50-conditionals.zsh rename to scripts/assets/zsh_integrations.zsh index 4dabf68346b..df783dcc345 100644 --- a/dot_zshrc.d/50-conditionals.zsh +++ b/scripts/assets/zsh_integrations.zsh @@ -1,16 +1,7 @@ -if [[ $OSTYPE == 'darwin'* ]]; then - source "$(brew --prefix)/share/google-cloud-sdk/path.zsh.inc" - source "$(brew --prefix)/share/google-cloud-sdk/completion.zsh.inc" -fi - -periodic() { silent_background timeout 2 $HOME/bin/gh_checks_status.sh > /tmp/gh_$$ } -PERIOD=10 - -# source .zshrc_local if it exists -if [ -f ~/.zshrc_local ]; then - source ~/.zshrc_local -fi +# Integration features and utilities +# This file contains integrations, autoupdates, and feature toggles +# Configuration toggles (can be overridden in .zshrc_local) if [ -z "$CHEERS_ENABLED" ]; then CHEERS_ENABLED=true fi @@ -23,18 +14,10 @@ if [ -z "$INSULTS_OFFENSIVE_ENABLED" ]; then INSULTS_OFFENSIVE_ENABLED=false fi -if $INSULTS_ENABLED; then - source $HOME/assets/insults.zsh -fi - if [ -z "$CNF_TF_ENABLED" ]; then CNF_TF_ENABLED=true fi -if $CNF_TF_ENABLED; then - source $HOME/bin/zsh_cnf.zsh -fi - if [ -z "$ASCII_WELCOME_ENABLED" ]; then ASCII_WELCOME_ENABLED=true fi @@ -51,6 +34,16 @@ if [ -z "$AUTO_CLEAR_CACHES_SECONDS" ]; then AUTO_CLEAR_CACHES_SECONDS=7890000 fi +# Load feature modules +if $INSULTS_ENABLED; then + source $HOME/scripts/assets/insults.zsh +fi + +if $CNF_TF_ENABLED; then + source $HOME/scripts/assets/zsh_cnf.zsh +fi + +# Cache clearing functionality if $AUTO_CLEAR_CACHES; then if [ -f "$HOME/.auto_clear_caches" ]; then if [ "$(($(date +%s) - $(cat $HOME/.auto_clear_caches)))" -lt "$AUTO_CLEAR_CACHES_SECONDS" ]; then @@ -63,16 +56,17 @@ if $AUTO_CLEAR_CACHES; then fi fi +# Cache clearing prompts if $AUTO_CLEAR_CACHES; then - # ask the user if they want to clear go installation as it bloats over time - printf "Go installation grows over time and it\'s recommended to clear it periodically.\n" + printf "Go installation grows over time and it's recommended to clear it periodically.\n" if gum confirm "Do you want to clear the go installation?"; then echo "Clearing go installation..." sudo rm -rf $HOME/go echo "Go installation cleared." echo "Sync FluxNinja repos..." - $HOME/bin/sync_fluxninja.sh + $HOME/scripts/bin/sync_fluxninja.sh fi + if gum confirm "Do you want to prune docker builder cache?"; then echo "Pruning docker builder cache..." docker builder prune -f -a @@ -83,7 +77,7 @@ if $AUTO_CLEAR_CACHES; then fi fi -# check timestamp when welcome was last displayed and if it's less than ASCII_WELCOME_SNOOZE then disable ascii art. Also update the timestamp if ascii art is going to be displayed. +# ASCII welcome functionality if $ASCII_WELCOME_ENABLED; then if [ -f "$HOME/.ascii_welcome_last_displayed" ]; then if [ "$(($(date +%s) - $(cat $HOME/.ascii_welcome_last_displayed)))" -lt "$ASCII_WELCOME_SNOOZE" ]; then @@ -96,45 +90,21 @@ if $ASCII_WELCOME_ENABLED; then fi fi -# check whether ascii art is enabled +# Display ASCII welcome if $ASCII_WELCOME_ENABLED; then - # print a random cowsay using fortune using only *.cow files located at $(brew --prefix)/share/cows fortune | cowsay -f $(find $(brew --prefix)/share/cowsay/cows/ -name "*.cow" | shuf -n 1) - (timeout 2 WTTR_PARAMS="1" ~/bin/wttr.sh ; + (timeout 2 WTTR_PARAMS="1" ~/scripts/bin/wttr.sh ;\ echo; echo -e "${CYAN_BRIGHT} ==================================  GitHub Status ================================== ${RESET}"; echo; timeout 2 gh status --org neopilotai) 2&>/dev/null fi +# Cleanup unset ASCII_WELCOME_ENABLED unset ASCII_WELCOME_SNOOZE unset CNF_TF_ENABLED -# run $HOME/bin/executable_autoupdate.zsh by eval it's content -eval "$(cat $HOME/bin/executable_autoupdate.zsh)" +# Autoupdate integration +eval "$(cat $HOME/scripts/bin/autoupdate.zsh)" +# Source aliases source $HOME/.aliases - -if [[ $TERM == *"tmux"* || $TERM == *"screen"* || -n $TMUX ]]; then - echo -e "${YELLOW_BRIGHT} Welcome to ${CYAN_BRIGHT}tmux${RESET}" - echo -e "${YELLOW_BRIGHT} Press ${CYAN_BRIGHT}${YELLOW_BRIGHT} for fuzzy menu - look for additional commands under ${CYAN_BRIGHT}menu${YELLOW_BRIGHT} selection${RESET}" - echo -e "${YELLOW_BRIGHT} Press ${CYAN_BRIGHT}F12${YELLOW_BRIGHT} for tmux menu${RESET}" -else - sessions=$(tmux list-sessions 2&> /dev/null | cut -d ":" -f1) - # check whether $sessions is not empty - if [ -n "$sessions" ]; then - echo -e "\n${BOLD}${CYAN_BRIGHT} == Active tmux Sessions ==${RESET}"; - for i in $sessions ; do - echo -e "${BOLD}${YELLOW_BRIGHT} [*] $i" - done; - fi - echo -e "${CYAN_BRIGHT} == Run tms to create and select tmux sessions == ${RESET}" - echo -e "${RESET}" -fi - -echo -e "${YELLOW_BRIGHT} Press ${CYAN_BRIGHT}${YELLOW_BRIGHT} to invoke auto-complete menu for commands, arguments and options${RESET}" -echo - -# override terminal profile colors using escape codes -if $SET_TERMINAL_COLORS; then - $HOME/assets/set_colors.zsh -fi diff --git a/scripts/assets/zsh_plugins.zsh b/scripts/assets/zsh_plugins.zsh new file mode 100644 index 00000000000..4eccea5aff7 --- /dev/null +++ b/scripts/assets/zsh_plugins.zsh @@ -0,0 +1,66 @@ +# Zinit plugin configuration +# This file contains all zinit plugin setups + +# Core plugins +zinit ice wait'!0' atload'source "$yazpt_default_preset_file"; \ + configure_yazpt;yazpt_precmd' nocd lucid +zinit light jakshin/yazpt + +# Install git-extras via zinit instead of brew +zinit lucid wait'0a' for \ + as"program" pick"$ZPFX/bin/git-*" src"etc/git-extras-completion.zsh" make"PREFIX=$ZPFX" tj/git-extras + +# Install direnv via zinit instead of brew +zinit from"gh-r" as"program" mv"direnv* -> direnv" \ + atclone'./direnv hook zsh > zhook.zsh' atpull'%atclone' \ + pick"direnv" src="zhook.zsh" for \ + direnv/direnv + +# Other plugins +zinit snippet OMZ::lib/key-bindings.zsh +zinit light MichaelAquilina/zsh-you-should-use + +# Completions +zinit id-as='brew-completions' wait as='completion' lucid \ + atclone='print Installing Brew completions...; \ + rm -rf $ZPFX/brew_comps_others 2>/dev/null; \ + mkdir -p $ZPFX/brew_comps_others; \ + rm -rf $ZPFX/brew_comps_zsh 2>/dev/null; \ + mkdir -p $ZPFX/brew_comps_zsh; \ + command cp -f $(brew --prefix)/share/zsh/site-functions/^_* $ZPFX/brew_comps_others; \ + command cp -f $(brew --prefix)/share/zsh/site-functions/_* $ZPFX/brew_comps_zsh; \ + command rm $ZPFX/brew_comps_zsh/_git; \ + zinit creinstall -q $ZPFX/brew_comps_zsh; \ + zinit cclear; \ + enable-fzf-tab' \ + atload='fpath=( ${(u)fpath[@]:#$(brew --prefix)/share/zsh/site-functions/*} ); \ + fpath+=( $ZPFX/brew_comps_others )' \ + atpull='%atclone' nocompile run-atpull for \ + zdharma-continuum/null + +zinit id-as='system-completions' wait as='completion' lucid \ + atclone='print Installing system completions...; \ + mkdir -p $ZPFX/zsh_comps; \ + command cp -f $(brew --prefix)/share/zsh/functions/^_* $ZPFX/zsh_comps; \ + zinit creinstall -q $(brew --prefix)/share/zsh/functions; \ + zinit cclear; \ + enable-fzf-tab' \ + atload='fpath=( ${(u)fpath[@]:#$(brew --prefix)/share/zsh/functions/*} ); \ + fpath+=( $ZPFX/zsh_comps )' \ + atpull="%atclone" nocompile run-atpull for \ + zdharma-continuum/null + +zinit id-as='fn-completions' wait as='completion' lucid \ + atclone='print Installing FN completions...; \ + zinit creinstall -q $HOME/.completions; \ + zinit cclear; \ + enable-fzf-tab' \ + atload='fpath=( ${(u)fpath[@]:#$HOME/.completions/*} )' \ + atpull="%atclone" nocompile run-atpull for \ + zdharma-continuum/null + +# Additional completions +zinit ice wait as'completion' lucid +zinit snippet https://github.com/sainnhe/zsh-completions/blob/master/src/custom/_fzf +zinit ice wait blockf atpull'zinit creinstall -q .' lucid +zinit light zsh-users/zsh-completions diff --git a/scripts/assets/zsh_prompt.zsh b/scripts/assets/zsh_prompt.zsh new file mode 100644 index 00000000000..f7a09928b80 --- /dev/null +++ b/scripts/assets/zsh_prompt.zsh @@ -0,0 +1,91 @@ +# Zsh prompt configuration using yazpt +# Custom segments and prompt layout + +# Prompt layout configuration +PS1="$(pwd) > " +PROMPT_LAYOUT='[] ' + +# Custom prompt segments +function @yazpt_segment_nl() { + # Check if GitHub status should be displayed + local last_yazpt_vcs="$yazpt_state[vcs]" + yazpt_state[nl]="" + + # Read GitHub checks status if available + if [[ -e "/tmp/gh_$$" ]]; then + local check="$(cat /tmp/gh_$$")" + if [ -n "$check" ]; then + if [ -n "$yazpt_state[vcs]" ]; then + yazpt_state[nl]+=" | " + fi + yazpt_state[nl]+=" GitHub checks $check" + fi + fi + + # Add sleep reminder for late hours + local hour=$(date +%H) + if (( 23 <= hour || hour <= 6 )); then + if [ -n "$yazpt_state[nl]" ] || [ -n "$yazpt_state[vcs]" ]; then + yazpt_state[nl]+=" | " + fi + yazpt_state[nl]+="%F{$YAZPT_CWD_COLOR}it's late, yo - get some sleep!%f" + fi + + # Add newline if content exists + if [ -n "$yazpt_state[nl]" ] || [ -n "$yazpt_state[vcs]" ]; then + yazpt_state[nl]+=$'\n' + fi +} + +function @yazpt_segment_excuse() { + local code="$yazpt_state[exit_code]" + local excuse_msg='' + + if [[ $code -ne 0 && $code -ne 127 && "$yazpt_state[exit_code]" -ne 130 ]] && $INSULTS_ENABLED; then + excuse_msg='💥uh-ho💥 ' + excuse_msg+="$(excuse)" + excuse_msg+=$'\n' + fi + + yazpt_state[excuse]=$excuse_msg +} + +# Cheers patterns for successful commands +APP_CHEERS_PATTERNS=( + "git push" + "git_ship" +) + +function @yazpt_segment_cheers() { + local do_cheers=false + local cheers_msg='' + + if $CHEERS_ENABLED && [ "$yazpt_state[exit_code]" -eq 0 ]; then + for pattern in "${APP_CHEERS_PATTERNS[@]}"; do + if [[ "$LAST_COMMAND" == *"$pattern"* ]]; then + do_cheers=true + break + fi + done + fi + + if $do_cheers; then + cheers_msg=' 🍻🎉🍻 ' + cheers_msg+="$(compliment)" + cheers_msg+=$'\n' + + # iTerm2 fireworks integration + if [[ $OSTYPE == 'darwin'* ]] && $ITERM2_INTEGRATION_DETECTED; then + $HOME/.iterm2/it2attention fireworks + fi + fi + + yazpt_state[cheers]=$cheers_msg +} + +# Configure yazpt +function configure_yazpt { + YAZPT_LAYOUT=$PROMPT_LAYOUT + YAZPT_CWD_COLOR=6 # cyan + YAZPT_EXECTIME_MIN_SECONDS=1 +} diff --git a/scripts/bin/executable_autoupdate.zsh b/scripts/bin/executable_autoupdate.zsh new file mode 100644 index 00000000000..5b5a9c04d27 --- /dev/null +++ b/scripts/bin/executable_autoupdate.zsh @@ -0,0 +1,178 @@ +#!/usr/bin/env zsh + +# check whether this script is being eval'ed +[[ $0 =~ "autoupdate.zsh" ]] && sourced=0 || sourced=1 + +# Track errors from various update commands in an array and show the result before exiting +function update_error() { + error_cmd=$1 + error_code=$2 + if [ $error_code -ne 0 ]; then + # add the error to the array + update_errors+=("$error_cmd: $error_code") + fi +} + +tp='success' + +function show_errors() { + if [ ${#update_errors[@]} -ne 0 ]; then + tp='error' + echo "Errors occurred during update:" + for error in "${update_errors[@]}"; do + echo " $error" + done + fi + # $sourced is 1, use term-notify to send notifications + if [ $sourced -eq 1 ]; then + term-notify $tp $interval <<<"autoupdate.zsh" + else + if [ $tp = 'success' ]; then + exit 0 + else + exit 1 + fi + fi +} + +function check_interval() { + now=$(date +%s) + if [ -f ~/${1} ]; then + last_update=$(cat ~/${1}) + else + last_update=0 + fi + interval=$(expr ${now} - ${last_update}) + echo ${interval} +} + +function revolver_stop() { + revolver stop + tput cnorm +} + +if [ -z "$SYSTEM_UPDATE_DAYS" ]; then + SYSTEM_UPDATE_DAYS=7 +fi + +if [ -z "$SYSTEM_RECEIPT_F" ]; then + SYSTEM_RECEIPT_F='.system_lastupdate' +fi + +# check whether force update option was provided +if [ "$1" = "--force" ]; then + force_update=1 +else + force_update=0 +fi + +day_seconds=86400 +system_seconds=$(expr ${day_seconds} \* ${SYSTEM_UPDATE_DAYS}) + +last_system=$(check_interval ${SYSTEM_RECEIPT_F}) + +if [ ${last_system} -gt ${system_seconds} ] || [ $force_update -eq 1 ]; then + # get current time + start_time=$(date +%s) + + $(date +%s >~/${SYSTEM_RECEIPT_F}) + echo "It has been $(expr ${last_system} / $day_seconds) days since system was updated" + echo "Updating system... Please open a new terminal to continue your work in parallel..." + + # check if revolver command exists + if command -v revolver >/dev/null 2>&1; then + tput civis + revolver --style 'dots2' start 'Pulling latest dotfiles...' + fi + + cd ~ && chezmoi --force update -v + update_error dotfiles $? + + revolver update "Running personal autoupdates..." + # run ~/.autoupdate_local.zsh if it exists + if [ -f ~/.autoupdate_local.zsh ]; then + # run ~/.autoupdate_local.zsh by eval it's content + eval "$(cat ~/.autoupdate_local.zsh)" + update_error ~/.autoupdate_local.zsh $? + fi + + if command -v revolver >/dev/null 2>&1; then + revolver_stop + fi + ~/scripts/bin/sync_brews.sh + update_error sync_brews $? + + revolver --style 'dots2' start 'Updating zinit... (Press q or Enter if this is taking too long)' + source $HOME/.local/share/zinit/zinit.git/zinit.zsh && zinit self-update && zinit update --quiet --parallel 8 && zinit cclear + update_error zinit $? + + revolver update "Updating nvim... (Press Spaces if this is taking too long)" + nvim +PlugUpgrade +PlugClean! +PlugUpdate +PlugInstall +CocUpdateSync +TSUpdateSync +qall + update_error nvim $? + + revolver update "Updating npm packages..." + # Update npm packages with safer audit fix + npm update && npm upgrade + # Only run audit fix if package.json exists and has dependencies + if [ -f package.json ] && [ -s package.json ]; then + npm audit fix --dry-run && npm audit fix + fi + npm prune --production + update_error npm $? + + revolver update "Updating pip packages..." + # upgrade pip and pip packages with safer practices + pip3 install --quiet --upgrade pip setuptools wheel + + # Update pip packages if requirements.txt exists, otherwise update all + if [ -f requirements.txt ]; then + pip3 install --quiet --upgrade -r requirements.txt + elif [ -f pyproject.toml ]; then + pip3 install --quiet --upgrade . + else + # Fallback to updating all local packages (less safe but necessary) + pip3 freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip3 install --quiet --upgrade 2>/dev/null || true + fi + update_error pip $? + + + revolver update "Updating tldr cache..." + # update tldr + tldr --update + + revolver update "Syncing styles in $HOME/notes" + pushd $HOME/notes && vale sync && popd + + revolver_stop + + $HOME/scripts/bin/sync_neopilotai.sh + $HOME/scripts/bin/sync_fluxninja.sh + + if [[ $TERM == *"tmux"* || $TERM == *"screen"* || -n $TMUX ]]; then + tmux source-file $HOME/.tmux.conf + fi + + stop_time=$(date +%s) + interval=$(expr ${stop_time} - ${start_time}) + echo "It took $interval seconds to update the system." + show_errors +fi + +unset SYSTEM_RECEIPT_F +unset SYSTEM_UPDATE_DAYS +unset day_seconds +unset last_system +unset system_seconds +unset start_time +unset stop_time +unset interval +unset force_update +unset update_errors +unset check_interval +unset error_code +unset error_cmd +unset tp +unset -f update_error +unset -f check_interval +unset -f show_errors +unset -f revolver_stop diff --git a/bin/explain_prompt b/scripts/bin/executable_explain_prompt similarity index 100% rename from bin/explain_prompt rename to scripts/bin/executable_explain_prompt diff --git a/bin/gh_checks_status.sh b/scripts/bin/executable_gh_checks_status.sh similarity index 100% rename from bin/gh_checks_status.sh rename to scripts/bin/executable_gh_checks_status.sh diff --git a/bin/gh_clone_all.sh b/scripts/bin/executable_gh_clone_all.sh similarity index 100% rename from bin/gh_clone_all.sh rename to scripts/bin/executable_gh_clone_all.sh diff --git a/bin/git_ship b/scripts/bin/executable_git_ship similarity index 100% rename from bin/git_ship rename to scripts/bin/executable_git_ship diff --git a/scripts/bin/executable_lint.zsh b/scripts/bin/executable_lint.zsh new file mode 100644 index 00000000000..35e031b874e --- /dev/null +++ b/scripts/bin/executable_lint.zsh @@ -0,0 +1,194 @@ +#!/usr/bin/env zsh + +# Comprehensive linting script for dotfiles +# This script validates various configuration file formats + +set -e + +echo "🔍 Running comprehensive linting..." + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + local status_type=$1 + local message=$2 + if [ "$status_type" = "error" ]; then + echo -e "${RED}❌ $message${NC}" + elif [ "$status_type" = "warning" ]; then + echo -e "${YELLOW}⚠️ $message${NC}" + elif [ "$status_type" = "success" ]; then + echo -e "${GREEN}✅ $message${NC}" + elif [ "$status_type" = "info" ]; then + echo -e "${BLUE}ℹ️ $message${NC}" + else + echo -e " $message" + fi +} + +# Track overall status +overall_status=0 + +# Check YAML files +print_status info "Linting YAML files..." +if command -v yamllint >/dev/null 2>&1; then + yaml_files=$(find . -name "*.yml" -o -name "*.yaml" | grep -v ".git") + if [ -n "$yaml_files" ]; then + if yamllint $yaml_files 2>/dev/null; then + print_status success "All YAML files passed yamllint validation." + else + print_status warning "Some YAML files have linting issues." + overall_status=1 + fi + else + print_status info "No YAML files found to lint." + fi +else + print_status warning "yamllint not available for YAML validation." +fi + +# Check JSON files +print_status info "Validating JSON files..." +json_files=$(find . -name "*.json" | grep -v ".git" | grep -v "node_modules") +for file in $json_files; do + if ! jq empty "$file" 2>/dev/null; then + print_status error "Invalid JSON in $file" + overall_status=1 + else + print_status success "Valid JSON: $file" + fi +done + +# Check shell scripts +print_status info "Linting shell scripts..." +if command -v shellcheck >/dev/null 2>&1; then + shell_files=$(find . -name "*.sh" -o -name "*.zsh" | grep -v ".git") + if [ -n "$shell_files" ]; then + echo "Running shellcheck on scripts..." + if shellcheck $shell_files 2>/dev/null; then + print_status success "All shell scripts passed shellcheck validation." + else + print_status warning "Some shell scripts have linting issues. Run 'shellcheck' for details." + overall_status=1 + fi + else + print_status info "No shell scripts found to lint." + fi +else + print_status warning "shellcheck not available for shell script validation." +fi + +# Check TOML files +print_status info "Validating TOML files..." +if command -v python3 >/dev/null 2>&1; then + toml_files=$(find . -name "*.toml" | grep -v ".git") + for file in $toml_files; do + if python3 -c "import tomllib; tomllib.load(open('$file', 'rb'))" 2>/dev/null || \ + python3 -c "import toml; toml.load('$file')" 2>/dev/null; then + print_status success "Valid TOML: $file" + else + print_status error "Invalid TOML in $file" + overall_status=1 + fi + done +else + print_status warning "Python not available for TOML validation." +fi + +# Check for chezmoi configuration issues +print_status info "Validating chezmoi configuration..." +if [ -f ".chezmoidot.toml" ]; then + print_status success "Found .chezmoidot.toml" +else + print_status warning "Missing .chezmoidot.toml" +fi + +if [ -f ".chezmoiignore" ]; then + print_status success "Found .chezmoiignore" +else + print_status warning "Missing .chezmoiignore" +fi + +# Check for common issues in dotfiles +print_status info "Checking for common configuration issues..." + +# Check for trailing whitespace +files_with_whitespace=$(find . -name "dot_*" -o -name "*.md" -o -name "*.txt" | xargs grep -l '[[:space:]]$' 2>/dev/null || true) +if [ -n "$files_with_whitespace" ]; then + print_status warning "Files with trailing whitespace found:" + echo "$files_with_whitespace" + overall_status=1 +fi + +# Check for tabs in files that should use spaces +files_with_tabs=$(find . -name "*.md" -o -name "*.yml" -o -name "*.yaml" | xargs grep -l $'\t' 2>/dev/null || true) +if [ -n "$files_with_tabs" ]; then + print_status warning "Files with tabs found (should use spaces):" + echo "$files_with_tabs" + overall_status=1 +fi + +# Check for executable permissions on non-scripts +print_status info "Checking file permissions..." +find . -name "dot_*" -type f | while read -r file; do + if [ -x "$file" ]; then + print_status warning "Executable dotfile found: $file (should not be executable)" + overall_status=1 + fi +done + +# Check for proper shebangs in scripts +print_status info "Checking script shebangs..." +find . -name "*.sh" -o -name "*.zsh" | grep -v ".git" | while read -r file; do + if [ -x "$file" ] && ! head -n 1 "$file" | grep -q "^#!/"; then + print_status warning "Executable script without shebang: $file" + overall_status=1 + fi +done + +# Check README links +print_status info "Checking README links..." +if [ -f "README.md" ]; then + # Check for broken internal links + broken_links=$(grep -o '\[.*\](#[^)]*)' README.md | grep -v 'Table of Contents' | while read -r link; do + target=$(echo "$link" | sed -n 's/.*#\(.*\))/\1/p') + if ! grep -q "^## $target\|^### $target\|^#### $target" README.md 2>/dev/null; then + echo "$link -> #$target" + fi + done) + + if [ -n "$broken_links" ]; then + print_status warning "Potentially broken internal links found:" + echo "$broken_links" + overall_status=1 + else + print_status success "All internal links appear to be valid." + fi +fi + +# Check for required tools mentioned in docs +print_status info "Checking for required tools..." +if [ -f "README.md" ]; then + tools=$(grep -o '`\w*`' README.md | sort | uniq | tr -d '`' | grep -E '^(chezmoi|homebrew|brew|git|gh)$') + for tool in $tools; do + if ! command -v "$tool" >/dev/null 2>&1; then + print_status warning "Tool mentioned in README but not installed: $tool" + fi + done +fi + +# Final status +echo "" +if [ $overall_status -eq 0 ]; then + print_status success "All linting checks passed!" +else + print_status error "Some linting issues found. Please review and fix." + exit 1 +fi + +print_status info "Linting complete!" diff --git a/bin/pull_all.sh b/scripts/bin/executable_pull_all.sh similarity index 100% rename from bin/pull_all.sh rename to scripts/bin/executable_pull_all.sh diff --git a/bin/spinner b/scripts/bin/executable_spinner similarity index 100% rename from bin/spinner rename to scripts/bin/executable_spinner diff --git a/bin/sync_brews.sh b/scripts/bin/executable_sync_brews.sh old mode 100755 new mode 100644 similarity index 99% rename from bin/sync_brews.sh rename to scripts/bin/executable_sync_brews.sh index b731978f628..12c65943178 --- a/bin/sync_brews.sh +++ b/scripts/bin/executable_sync_brews.sh @@ -374,6 +374,7 @@ npm i -q -g turbo npm i -q -g bash-language-server npm i -q -g dockerfile-language-server-nodejs npm i -q -g graphql-language-service-cli +npm i -q -g husky revolver update 'Installing python packages...' #python stuff diff --git a/bin/sync_fluxninja.sh b/scripts/bin/executable_sync_fluxninja.sh old mode 100755 new mode 100644 similarity index 100% rename from bin/sync_fluxninja.sh rename to scripts/bin/executable_sync_fluxninja.sh diff --git a/scripts/bin/executable_sync_neopilotai.sh b/scripts/bin/executable_sync_neopilotai.sh new file mode 100644 index 00000000000..96136787323 --- /dev/null +++ b/scripts/bin/executable_sync_neopilotai.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +gh_clone_all.sh neopilotai ~/Work +pull_all.sh ~/Work/neopilotai + +# go through all the directories in ~/Work/neopilotai +# look for package.json files in the subdirectories +# and run pnpm install in those directories +find ~/Work/neopilotai -depth 2 -name package.json -exec dirname {} \; | while read dir; do + # if the directory contains a pnpm-lock.yaml file use pnpm + # otherwise look for a yarn.lock file and use yarn + # otherwise look for a package-lock.json file and use npm + if [ -f "$dir/pnpm-lock.yaml" ]; then + echo "Running pnpm install in $dir" + (cd $dir && pnpm install) + elif [ -f "$dir/yarn.lock" ]; then + echo "Running yarn install in $dir" + (cd $dir && yarn install) + elif [ -f "$dir/package-lock.json" ]; then + echo "Running npm install in $dir" + (cd $dir && npm install) + fi +done + +# install husky git hooks in neopilotai/mono +if [ -d ~/Work/neopilotai/mono ]; then + echo "Installing husky git hooks in ~/Work/neopilotai/mono" + (cd ~/Work/neopilotai/mono && husky) +fi diff --git a/scripts/bin/executable_validate_security.zsh b/scripts/bin/executable_validate_security.zsh new file mode 100644 index 00000000000..1c42ec167ef --- /dev/null +++ b/scripts/bin/executable_validate_security.zsh @@ -0,0 +1,145 @@ +#!/usr/bin/env zsh + +# Security validation script for dotfiles +# This script checks for common security issues in dotfiles configuration + +set -e + +echo "🔍 Running security validation..." + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + local status_type=$1 + local message=$2 + if [ "$status_type" = "error" ]; then + echo -e "${RED}❌ $message${NC}" + elif [ "$status_type" = "warning" ]; then + echo -e "${YELLOW}⚠️ $message${NC}" + elif [ "$status_type" = "success" ]; then + echo -e "${GREEN}✅ $message${NC}" + else + echo -e "ℹ️ $message" + fi +} + +# Check for hardcoded secrets or sensitive information +print_status info "Checking for hardcoded secrets..." +if grep -r "password\|secret\|key\|token" . --include="*.sh" --include="*.zsh" --include="*.yml" --include="*.yaml" --exclude-dir=.git 2>/dev/null | grep -v "export.*=" | grep -v "#.*password\|secret\|key\|token"; then + print_status warning "Potential hardcoded secrets found. Please use environment variables or secret management." +else + print_status success "No obvious hardcoded secrets found." +fi + +# Check for unsafe file permissions +print_status info "Checking file permissions..." +find . -name "*.sh" -o -name "*.zsh" | while read -r file; do + if [ -x "$file" ]; then + print_status warning "Executable script found: $file" + fi +done + +# Check for unsafe shell patterns +print_status info "Checking for unsafe shell patterns..." +if grep -r "eval.*\$" . --include="*.sh" --include="*.zsh" --exclude-dir=.git 2>/dev/null; then + print_status warning "Found dynamic eval usage. Please review for safety." +fi + +if grep -r "sudo.*\$" . --include="*.sh" --include="*.zsh" --exclude-dir=.git 2>/dev/null; then + print_status warning "Found dynamic sudo usage. Please review for safety." +fi + +# Check for proper input validation +print_status info "Checking input validation..." +if grep -r "read.*\$" . --include="*.sh" --include="*.zsh" --exclude-dir=.git 2>/dev/null | grep -v "read -r"; then + print_status warning "Found 'read' without '-r' flag. Consider using 'read -r' for safety." +fi + +# Check for proper quoting +print_status info "Checking variable quoting..." +if grep -r '\$[A-Za-z_][A-Za-z0-9_]*' . --include="*.sh" --include="*.zsh" --exclude-dir=.git 2>/dev/null | grep -v '"$'; then + print_status warning "Found unquoted variables. Please use proper quoting." +fi + +# Check GitHub Actions workflow +print_status info "Checking GitHub Actions workflow..." +if [ -f ".github/workflows/openai-review.yml" ]; then + if ! grep -q "permissions:" .github/workflows/openai-review.yml; then + print_status error "GitHub Actions workflow missing permissions block!" + else + print_status success "GitHub Actions workflow has proper permissions." + fi + + if grep -q "secrets\." .github/workflows/openai-review.yml; then + print_status success "GitHub Actions workflow properly uses secrets." + fi +else + print_status warning "No GitHub Actions workflow found." +fi + +# Check for proper error handling +print_status info "Checking error handling..." +if grep -r "set -e" . --include="*.sh" --include="*.zsh" --exclude-dir=.git 2>/dev/null; then + print_status success "Found proper error handling with 'set -e'." +fi + +# Check for chezmoi configuration +print_status info "Checking chezmoi configuration..." +if [ -f ".chezmoidot.toml" ]; then + print_status success "Found chezmoi configuration file." +else + print_status error "Missing .chezmoidot.toml file!" +fi + +if [ -f ".chezmoiignore" ]; then + print_status success "Found .chezmoiignore file." +else + print_status warning "Missing .chezmoiignore file!" +fi + +# Check for proper ignore patterns +print_status info "Checking ignore patterns..." +if [ -f ".gitignore" ]; then + print_status success "Found .gitignore file." + # Check for common sensitive patterns + if grep -q ".*_local" .gitignore; then + print_status success ".gitignore properly excludes local override files." + else + print_status warning ".gitignore should exclude *_local files." + fi +else + print_status warning "Missing .gitignore file!" +fi + +# Check for shell script validation +print_status info "Validating shell scripts..." +if command -v shellcheck >/dev/null 2>&1; then + shell_scripts=$(find . -name "*.sh" -o -name "*.zsh" | grep -v ".git") + if [ -n "$shell_scripts" ]; then + echo "Running shellcheck on scripts..." + if shellcheck $shell_scripts 2>/dev/null; then + print_status success "All shell scripts passed shellcheck validation." + else + print_status warning "Some shell scripts have linting issues. Run 'shellcheck' for details." + fi + fi +else + print_status warning "shellcheck not available for script validation." +fi + +print_status info "Security validation complete!" + +echo "" +echo "Security recommendations:" +echo "1. Always use 'read -r' when reading user input" +echo "2. Quote all variable expansions: \"\$variable\"" +echo "3. Use 'set -e' for proper error handling" +echo "4. Avoid dynamic eval and sudo when possible" +echo "5. Store secrets in environment variables or secure vaults" +echo "6. Regularly audit and update dependencies" +echo "7. Use proper ignore patterns to avoid committing sensitive files" diff --git a/bin/win_split b/scripts/bin/executable_win_split similarity index 92% rename from bin/win_split rename to scripts/bin/executable_win_split index b72b6fbcd2c..34870ca1f8c 100644 --- a/bin/win_split +++ b/scripts/bin/executable_win_split @@ -29,7 +29,7 @@ done shift "$((OPTIND - 1))" -cmd="export ZINIT_TURBO=false;source ~/assets/utils.zsh;\ +cmd="export ZINIT_TURBO=false;source ~/scripts/assets/utils.zsh;\ command -v zsh-notify-before-command >/dev/null 2>&1 && zsh-notify-before-command '$*';\ $*;\ command -v zsh-notify-after-command >/dev/null 2>&1 && zsh-notify-after-command" diff --git a/bin/wttr.sh b/scripts/bin/executable_wttr.sh similarity index 100% rename from bin/wttr.sh rename to scripts/bin/executable_wttr.sh