commit c0aefae3fb884e98949f708b809fc98de60ce949 Author: Edwin van den Houdt Date: Mon May 4 09:53:30 2026 +0200 init diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md new file mode 100644 index 0000000..d101cb5 --- /dev/null +++ b/GETTING_STARTED.md @@ -0,0 +1,204 @@ +# Getting Started + +This is a minimal development environment for Fedora Linux. +It uses GNU Stow to symlink config files into your home directory. + +Everything is plain text. No magic. Read a file before you use it. + +--- + +## What you need first + +A Fedora machine with internet access and `git` installed: + +```bash +sudo dnf install -y git +``` + +--- + +## Step 1 — Clone this repo + +```bash +git clone git@your-gitea-instance:you/dotfiles.git ~/dotfiles +cd ~/dotfiles +``` + +--- + +## Step 2 — Read provision.sh + +Before running any script, read it: + +```bash +cat provision.sh +``` + +It installs: `stow`, `neovim`, `ripgrep`, `mise` — and symlinks the config +packages into your home directory. Nothing else. + +When you are comfortable with what it does: + +```bash +bash provision.sh --dry-run # see what would happen +bash provision.sh # run it +``` + +--- + +## Step 3 — Edit your git identity + +The `.gitconfig` has placeholder values. Fill them in now: + +```bash +nvim ~/.gitconfig +``` + +Change `Your Name` and `you@example.com` to your actual details. + +--- + +## Step 4 — Install runtimes + +```bash +mise install +``` + +This downloads Node.js (for TypeScript) and .NET (for C#/F#) into +`~/.local/share/mise/`. Nothing goes system-wide. + +Check what was installed: + +```bash +mise ls +``` + +--- + +## Step 5 — Open Neovim + +```bash +nvim +``` + +On first launch, `lazy.nvim` installs all plugins automatically. +Wait for it to finish, then run: + +```vim +:checkhealth +``` + +Fix any warnings it shows before moving on. + +--- + +## Step 6 — Set up your notes repo + +Notes are a separate private repo. Clone it to `~/notes/`: + +```bash +git clone git@your-gitea-instance:you/notes.git ~/notes +``` + +The shell commands (`today`, `thisweek`, `inbox`, `tasks`, `decisions`) +expect `~/notes/` to exist with templates at `~/notes/templates/`. +They will not work until the notes repo is cloned. + +Reload your shell so the note aliases are available: + +```bash +source ~/.bashrc +``` + +Then try: + +```bash +today # creates and opens today's daily note +inbox # opens inbox for capture +tasks # shows all open tasks across notes +``` + +--- + +## Daily workflow in 3 commands + +```bash +inbox # capture anything during the day +today # open today's plan each morning +thisweek # open weekly review on Monday morning +``` + +--- + +## What is in this repo + +``` +dotfiles/ +├── provision.sh # bootstrap script +├── GETTING_STARTED.md # this file +├── README.md # full reference +├── .gitignore +│ +├── bash/ +│ └── .bashrc # shell config, aliases, note commands +│ +├── git/ +│ └── .gitconfig # git settings (edit name/email) +│ +├── mise/ +│ └── .config/mise/ +│ └── config.toml # node + dotnet versions +│ +├── nvim/ +│ └── .config/nvim/ +│ └── init.lua # Neovim — read top to bottom +│ +└── notes/ # templates only, not your actual notes + ├── inbox.md + ├── decisions.md + ├── daily-template.md + └── weekly-template.md +``` + +--- + +## Adding a config file later + +1. Create a package directory: `mkdir -p ~/dotfiles/mypackage` +2. Mirror the target path inside it — if the file belongs at + `~/.config/myapp/config`, create + `~/dotfiles/mypackage/.config/myapp/config` +3. Stow it: `stow --restow --target=$HOME --dir=~/dotfiles mypackage` +4. Commit + +--- + +## Updating an existing config + +Because stow creates symlinks, editing `~/.bashrc` is the same as editing +`~/dotfiles/bash/.bashrc`. Just open the file, save it, then commit: + +```bash +cd ~/dotfiles +git add bash/.bashrc +git commit -m "bashrc: add alias for X" +git push +``` + +--- + +## Troubleshooting + +**Stow says a file already exists** +The target file exists and is not a symlink. Back it up and remove it: +```bash +mv ~/.bashrc ~/.bashrc.bak +stow --restow --target=$HOME --dir=~/dotfiles bash +``` + +**Neovim plugins did not install** +Open nvim and run `:Lazy sync` + +**mise runtimes not found after install** +Make sure your shell sourced `.bashrc`: `source ~/.bashrc` +Then check: `mise ls` diff --git a/README.md b/README.md new file mode 100644 index 0000000..afb2ee1 --- /dev/null +++ b/README.md @@ -0,0 +1,160 @@ +# dotfiles + +Minimal personal development environment for Fedora Linux. + +**Stack:** Bash · Neovim · mise · GNU Stow + +→ **New machine?** Start with [GETTING_STARTED.md](GETTING_STARTED.md) + +--- + +## How stow works + +Stow creates symlinks from `~` into this repo, mirroring each package's +internal directory structure. + +``` +dotfiles/bash/.bashrc → ~/.bashrc +dotfiles/nvim/.config/nvim/init.lua → ~/.config/nvim/init.lua +``` + +Editing the symlink edits the repo file. Then commit like any other change. + +To stow a single package: + +```bash +stow --restow --target=$HOME --dir=~/dotfiles bash +``` + +--- + +## Packages + +| Package | Symlinks to | Purpose | +|---|---|---| +| `bash` | `~/.bashrc` | Shell config, aliases, note functions | +| `git` | `~/.gitconfig` | Git settings | +| `mise` | `~/.config/mise/config.toml` | Runtime versions | +| `nvim` | `~/.config/nvim/init.lua` | Neovim config | + +Note commands in `.bashrc` expect templates at `~/notes/templates/`. +These come from your notes repo, not this one. + +--- + +## Neovim + +Config is a single `init.lua` — read it top to bottom before using it. +Plugins are managed by [lazy.nvim](https://github.com/folke/lazy.nvim) which +bootstraps itself on first launch. + +**Installed plugins:** + +| Plugin | Purpose | +|---|---| +| `nvim-treesitter` | Syntax highlighting | +| `nvim-lspconfig` + `mason` | Language servers | +| `nvim-cmp` | Completion | +| `telescope.nvim` | Fuzzy finder | +| `Comment.nvim` | `gc` to comment | +| `vim-sleuth` | Auto-detect indent | +| `kanagawa.nvim` | Colorscheme | + +**Language servers installed automatically by Mason:** + +- `ts_ls` — TypeScript / JavaScript +- `omnisharp` — C# and F# +- `marksman` — Markdown +- `lua_ls` — Lua (for editing this config) + +**Keymaps (leader = Space):** + +| Keys | Action | +|---|---| +| `Space ff` | Find files | +| `Space fg` | Search text in files | +| `Space fb` | Switch buffer | +| `Space w` | Save | +| `Space e` | File explorer | +| `Space d` | Show diagnostic | +| `Space rn` | Rename symbol | +| `Space ca` | Code action | +| `gd` | Go to definition | +| `K` | Hover docs | +| `[d` / `]d` | Prev / next diagnostic | +| `Ctrl+h/j/k/l` | Move between splits | +| `gcc` | Toggle comment | + +--- + +## mise — runtime versions + +Configured in `mise/.config/mise/config.toml`. + +```bash +mise install # install all configured versions +mise ls # list installed runtimes +mise ls-remote node # list available node versions +``` + +To pin a version in a specific project, add a `.mise.toml` to that project +directory. The global config here is the fallback. + +--- + +## Bash aliases + +| Alias / Function | Does | +|---|---| +| `ll` | `ls -lah` with color | +| `..` / `...` | Navigate up one / two directories | +| `gs` / `ga` / `gc` / `gp` / `gl` | Git shortcuts | +| `today` | Open or create today's daily note | +| `thisweek` | Open or create this week's weekly note | +| `inbox` | Open inbox for quick capture | +| `tasks` | Grep all open tasks across notes | +| `decisions` | Open decisions log | +| `mkcd` | Create directory and cd into it | +| `bashrc` | Edit and reload `.bashrc` | + +--- + +## Notes workflow + +Notes live in `~/notes/` — a separate private git repo, not this one. +The shell commands in `.bashrc` expect this structure to exist: + +``` +~/notes/ +├── inbox.md +├── decisions.md +├── templates/ +│ ├── daily.md +│ └── weekly.md +├── daily/ +└── weekly/ +``` + +Clone your notes repo to `~/notes/` before using the note commands. + +--- + +## Dependencies + +| Tool | Install | +|---|---| +| `stow` | `dnf install stow` | +| `git` | `dnf install git` | +| `neovim` | `dnf install neovim` | +| `ripgrep` | `dnf install ripgrep` (needed by Telescope) | +| `mise` | `curl https://mise.run \| bash` | + +--- + +## Learning resources + +- `nvim +Tutor` — built-in hands-on tutor, ~30 min +- `man bash` — full bash reference +- `https://www.shellcheck.net` — paste a script, get feedback +- `https://mywiki.wooledge.org/BashGuide` — best bash guide +- `:help` in nvim — the built-in docs are good diff --git a/bash/.bashrc b/bash/.bashrc new file mode 100644 index 0000000..b299f45 --- /dev/null +++ b/bash/.bashrc @@ -0,0 +1,125 @@ +# ~/.bashrc +# Loaded for interactive non-login shells. +# Keep this file readable. Each section explains what it does. + +# If not running interactively, do nothing. +# This prevents issues when bash is invoked by scp or scripts. +case $- in + *i*) ;; + *) return ;; +esac + +# ============================================================ +# HISTORY +# ============================================================ +HISTSIZE=10000 +HISTFILESIZE=20000 +HISTCONTROL=ignoredups:erasedups # don't store duplicate lines +shopt -s histappend # append to history, don't overwrite it + +# ============================================================ +# PROMPT +# ============================================================ +# \u = username, \h = hostname, \w = current directory +# \e[COLORm = color code, \e[0m = reset color +# 32 = green, 34 = blue, 33 = yellow +__git_branch() { + local branch + branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) + [ -n "$branch" ] && echo " ($branch)" +} + +PS1='\e[32m\u@\h\e[0m:\e[34m\w\e[33m$(__git_branch)\e[0m\$ ' + +# ============================================================ +# COMPLETION +# ============================================================ +if [ -f /usr/share/bash-completion/bash_completion ]; then + . /usr/share/bash-completion/bash_completion +fi + +# ============================================================ +# EDITOR +# ============================================================ +export EDITOR=nvim +export VISUAL=nvim + +# ============================================================ +# PATH +# ============================================================ +# Add your personal scripts to PATH +export PATH="$HOME/.local/bin:$PATH" + +# mise runtime manager — activates shims for node, dotnet, etc. +# See: ~/.config/mise/config.toml +if command -v mise &>/dev/null; then + eval "$(mise activate bash)" +fi + +# ============================================================ +# ALIASES +# ============================================================ + +# Navigation +alias ..='cd ..' +alias ...='cd ../..' +alias ll='ls -lah --color=auto' +alias la='ls -A --color=auto' +alias l='ls -CF --color=auto' + +# Safety: ask before overwriting +alias rm='rm -i' +alias cp='cp -i' +alias mv='mv -i' + +# Quick edit and reload this file +alias bashrc='${EDITOR} ~/.bashrc && source ~/.bashrc' + +# Git shortcuts (plain, no magic) +alias gs='git status' +alias ga='git add' +alias gc='git commit' +alias gp='git push' +alias gl='git log --oneline --graph --decorate -20' + +# Notes shortcuts +# Opens inbox for quick capture +alias inbox='${EDITOR} ~/notes/inbox.md' + +# Opens or creates today's daily note from template +today() { + local file=~/notes/daily/$(date +%Y-%m-%d).md + mkdir -p ~/notes/daily + if [ ! -f "$file" ]; then + sed "s/YYYY-MM-DD/$(date +%Y-%m-%d)/g" \ + ~/notes/templates/daily.md > "$file" + fi + ${EDITOR} "$file" +} + +# Opens or creates this week's weekly note from template +thisweek() { + local week=~/notes/weekly/$(date +%Y-W%V).md + mkdir -p ~/notes/weekly + if [ ! -f "$week" ]; then + sed "s/YYYY-WNN/$(date +%Y-W%V)/g" \ + ~/notes/templates/weekly.md > "$week" + fi + ${EDITOR} "$week" +} + +# Find all open tasks across all notes +alias tasks='grep -r "\- \[ \]" ~/notes/ --include="*.md"' + +# Open decisions log +alias decisions='${EDITOR} ~/notes/decisions.md' + +# ============================================================ +# FUNCTIONS +# ============================================================ +# Only add functions you can explain line by line. + +# mkcd: create a directory and immediately enter it +mkcd() { + mkdir -p "$1" && cd "$1" +} diff --git a/git/.gitconfig b/git/.gitconfig new file mode 100644 index 0000000..2305b63 --- /dev/null +++ b/git/.gitconfig @@ -0,0 +1,32 @@ +[user] + name = Your Name + email = you@example.com + +[core] + editor = nvim + # Treat files with these line endings consistently on Linux + autocrlf = input + +[init] + defaultBranch = main + +[pull] + # Fail loudly if a pull would need a merge commit — forces you to decide + rebase = false + ff = only + +[push] + # Only push the current branch, not all branches + default = current + +[alias] + # Short log with graph + lg = log --oneline --graph --decorate -20 + # Show what changed in the last commit + last = show --stat HEAD + # Undo the last commit but keep the changes staged + undo = reset --soft HEAD~1 + +[diff] + # Show moved lines differently from changed lines + colorMoved = default diff --git a/mise/.config/mise/config.toml b/mise/.config/mise/config.toml new file mode 100644 index 0000000..dc0b993 --- /dev/null +++ b/mise/.config/mise/config.toml @@ -0,0 +1,20 @@ +# ~/.config/mise/config.toml +# +# mise manages language runtime versions (node, dotnet, etc.) +# so you don't install them system-wide. +# +# After stowing this file, run: +# mise install +# +# To see what's available: +# mise ls-remote node +# mise ls-remote dotnet + +[tools] +node = "lts" # latest LTS release of Node.js (for TypeScript) +dotnet = "latest" # latest .NET SDK (for C# and F#) + +[settings] +# mise will warn if a project directory has no .mise.toml +# Set to false if you find the warnings noisy while learning +verbose = false diff --git a/notes/daily-template.md b/notes/daily-template.md new file mode 100644 index 0000000..f0c66b3 --- /dev/null +++ b/notes/daily-template.md @@ -0,0 +1,27 @@ +# YYYY-MM-DD — Daily + +## Today's focus + +Three things that would make today a success: + +1. +2. +3. + +## Tasks + +Pulled from inbox. Only commit to what is realistic today. + +- [ ] + +## Log + +Running notes during the day. Decisions, context, things that came up. + +--- + +## End of day + +What got done, what didn't, anything to carry forward. + +Undone tasks: move back to inbox or forward to tomorrow explicitly. diff --git a/notes/decisions.md b/notes/decisions.md new file mode 100644 index 0000000..cd8c2ad --- /dev/null +++ b/notes/decisions.md @@ -0,0 +1,17 @@ +# Decisions + +Append-only. Never edit past entries. +Add new decisions at the bottom with a date and context. + +Format: +## YYYY-MM-DD — Short title +**Decision:** What was decided. +**Why:** The reason or constraint behind it. +**Who:** Who made or owns this decision. + +--- + +## YYYY-MM-DD — Example entry +**Decision:** Use SSH keys for git commit signing instead of GPG. +**Why:** Avoids GPG keychain complexity, same key used for auth and signing. +**Who:** Edwin diff --git a/notes/inbox.md b/notes/inbox.md new file mode 100644 index 0000000..782649e --- /dev/null +++ b/notes/inbox.md @@ -0,0 +1,8 @@ +# Inbox + +Everything lands here. Do not organise while capturing. +Process during your daily or weekly review. + +--- + +- [ ] diff --git a/notes/weekly-template.md b/notes/weekly-template.md new file mode 100644 index 0000000..195b085 --- /dev/null +++ b/notes/weekly-template.md @@ -0,0 +1,30 @@ +# YYYY-WNN — Weekly + +## Review last week + +Open last week's note. For each undone task, decide: +- [ ] Still relevant → move to inbox +- [ ] No longer relevant → mark with ~~strikethrough~~ and a note why + +What went well: + +What got in the way: + +## This week's focus + +Three things that would make this week a success: + +1. +2. +3. + +## Tasks + +Pulled from inbox after review. Not everything — only what fits a week. + +- [ ] + +## Notes + +Context, blockers, decisions made this week. +For decisions that should be permanent, copy to decisions.md. diff --git a/nvim/.config/nvim/init.lua b/nvim/.config/nvim/init.lua new file mode 100644 index 0000000..66e365b --- /dev/null +++ b/nvim/.config/nvim/init.lua @@ -0,0 +1,284 @@ +-- init.lua — minimal Neovim config based on kickstart.nvim +-- https://github.com/nvim-lua/kickstart.nvim +-- +-- Read this file top to bottom. Every section explains what it does. +-- Remove anything you don't understand yet — a smaller config you own +-- is better than a large one you don't. + +-- ============================================================ +-- LEADER KEY +-- ============================================================ +-- Must be set before plugins load. Space is the most common choice. +-- is used as a prefix for your custom keymaps below. +vim.g.mapleader = ' ' +vim.g.maplocalleader = ' ' + +-- ============================================================ +-- OPTIONS +-- ============================================================ +-- vim.opt is how you set Neovim options from Lua. +-- :help option-name shows docs for any option. + +vim.opt.number = true -- show line numbers +vim.opt.relativenumber = true -- relative numbers make motions easier (5j, 3k) +vim.opt.mouse = 'a' -- allow mouse in all modes (useful at first) +vim.opt.showmode = false -- mode shown in statusline instead +vim.opt.clipboard = 'unnamedplus' -- sync with system clipboard +vim.opt.breakindent = true -- wrapped lines indent visually +vim.opt.undofile = true -- persist undo history across sessions +vim.opt.ignorecase = true -- case-insensitive search ... +vim.opt.smartcase = true -- ... unless you type a capital +vim.opt.signcolumn = 'yes' -- always show sign column (avoids layout shifts) +vim.opt.updatetime = 250 -- faster completion and diagnostics +vim.opt.splitright = true -- new vertical splits open right +vim.opt.splitbelow = true -- new horizontal splits open below +vim.opt.list = true -- show whitespace characters +vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } +vim.opt.scrolloff = 8 -- keep 8 lines visible above/below cursor +vim.opt.tabstop = 2 -- tabs display as 2 spaces +vim.opt.shiftwidth = 2 -- indent size +vim.opt.expandtab = true -- use spaces instead of tabs +vim.opt.wrap = false -- don't wrap long lines by default + +-- ============================================================ +-- KEYMAPS +-- ============================================================ +-- vim.keymap.set(mode, keys, action, opts) +-- mode: 'n' normal, 'i' insert, 'v' visual, 'x' visual block + +-- Clear search highlights with Escape +vim.keymap.set('n', '', 'nohlsearch') + +-- Move between windows with Ctrl+direction (no need for Ctrl+W first) +vim.keymap.set('n', '', '', { desc = 'Move to left window' }) +vim.keymap.set('n', '', '', { desc = 'Move to right window' }) +vim.keymap.set('n', '', '', { desc = 'Move to lower window' }) +vim.keymap.set('n', '', '', { desc = 'Move to upper window' }) + +-- Quick save +vim.keymap.set('n', 'w', 'write', { desc = 'Save file' }) + +-- Open netrw file explorer (built-in, no plugin needed) +vim.keymap.set('n', 'e', 'Ex', { desc = 'Open file explorer' }) + +-- Diagnostic keymaps (errors from LSP) +vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, { desc = 'Previous diagnostic' }) +vim.keymap.set('n', ']d', vim.diagnostic.goto_next, { desc = 'Next diagnostic' }) +vim.keymap.set('n', 'd', vim.diagnostic.open_float, { desc = 'Show diagnostic' }) + +-- ============================================================ +-- AUTOCOMMANDS +-- ============================================================ +-- These run automatically on specific events. + +-- Highlight text briefly when you yank (copy) +vim.api.nvim_create_autocmd('TextYankPost', { + desc = 'Highlight on yank', + callback = function() + vim.highlight.on_yank() + end, +}) + +-- Markdown-specific settings +vim.api.nvim_create_autocmd('FileType', { + pattern = 'markdown', + callback = function() + vim.opt_local.wrap = true -- wrap lines in markdown + vim.opt_local.spell = true -- enable spellcheck + vim.opt_local.spelllang = 'en' + vim.opt_local.conceallevel = 1 -- hide markdown syntax slightly + end, +}) + +-- ============================================================ +-- PLUGIN MANAGER: lazy.nvim +-- ============================================================ +-- lazy.nvim bootstraps itself if not installed. +-- It clones from GitHub the first time you open Neovim. + +local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim' +if not vim.loop.fs_stat(lazypath) then + vim.fn.system { + 'git', 'clone', '--filter=blob:none', + 'https://github.com/folke/lazy.nvim.git', + '--branch=stable', + lazypath, + } +end +vim.opt.rtp:prepend(lazypath) + +-- ============================================================ +-- PLUGINS +-- ============================================================ +-- Each table is one plugin. 'keys' means the plugin only loads +-- when you press that key (lazy loading). This keeps startup fast. + +require('lazy').setup({ + + -- Detect indent settings from file (tabs vs spaces, width) + -- No config needed — it just works. + 'tpope/vim-sleuth', + + -- Comment lines with gc (gcc for one line, gc in visual mode) + { 'numToStr/Comment.nvim', opts = {} }, + + -- -------------------------------------------------------- + -- TELESCOPE: fuzzy finder + -- -------------------------------------------------------- + -- Requires ripgrep for live_grep: dnf install ripgrep + { + 'nvim-telescope/telescope.nvim', + branch = '0.1.x', + dependencies = { 'nvim-lua/plenary.nvim' }, + config = function() + require('telescope').setup {} + + local builtin = require 'telescope.builtin' + -- f prefix for "find" + vim.keymap.set('n', 'ff', builtin.find_files, { desc = 'Find files' }) + vim.keymap.set('n', 'fg', builtin.live_grep, { desc = 'Find in files' }) + vim.keymap.set('n', 'fb', builtin.buffers, { desc = 'Find open buffers' }) + vim.keymap.set('n', 'fh', builtin.help_tags, { desc = 'Find help' }) + vim.keymap.set('n', 'fd', builtin.diagnostics, { desc = 'Find diagnostics' }) + end, + }, + + -- -------------------------------------------------------- + -- TREESITTER: syntax highlighting and indentation + -- -------------------------------------------------------- + { + 'nvim-treesitter/nvim-treesitter', + build = ':TSUpdate', + config = function() + require('nvim-treesitter.configs').setup { + -- Install these parsers automatically + ensure_installed = { + 'bash', 'lua', 'markdown', 'markdown_inline', + 'typescript', 'javascript', 'c_sharp', + }, + auto_install = true, + highlight = { enable = true }, + indent = { enable = true }, + } + end, + }, + + -- -------------------------------------------------------- + -- LSP: language server protocol + -- -------------------------------------------------------- + -- mason installs language servers for you. + -- mason-lspconfig bridges mason and nvim-lspconfig. + { + 'neovim/nvim-lspconfig', + dependencies = { + 'williamboman/mason.nvim', + 'williamboman/mason-lspconfig.nvim', + }, + config = function() + -- mason must be set up first + require('mason').setup() + require('mason-lspconfig').setup { + -- These servers are installed automatically + ensure_installed = { + 'ts_ls', -- TypeScript / JavaScript + 'omnisharp', -- C# and F# + 'marksman', -- Markdown + 'lua_ls', -- Lua (for editing this config) + }, + } + + -- Keymaps that only activate when an LSP attaches to a buffer + vim.api.nvim_create_autocmd('LspAttach', { + callback = function(event) + local map = function(keys, func, desc) + vim.keymap.set('n', keys, func, { buffer = event.buf, desc = desc }) + end + map('gd', vim.lsp.buf.definition, 'Go to definition') + map('gD', vim.lsp.buf.declaration, 'Go to declaration') + map('gr', vim.lsp.buf.references, 'Go to references') + map('K', vim.lsp.buf.hover, 'Hover documentation') + map('rn', vim.lsp.buf.rename, 'Rename symbol') + map('ca', vim.lsp.buf.code_action, 'Code action') + end, + }) + + -- Server-specific settings + local lspconfig = require 'lspconfig' + + lspconfig.ts_ls.setup {} + + lspconfig.omnisharp.setup { + -- Point to your solution file if needed + -- cmd = { 'omnisharp', '--solution-path', 'YourSolution.sln' }, + } + + lspconfig.marksman.setup {} + + lspconfig.lua_ls.setup { + settings = { + Lua = { + -- Teach the Lua LSP about Neovim's globals + diagnostics = { globals = { 'vim' } }, + }, + }, + } + end, + }, + + -- -------------------------------------------------------- + -- COMPLETION: nvim-cmp + -- -------------------------------------------------------- + { + 'hrsh7th/nvim-cmp', + dependencies = { + 'hrsh7th/cmp-nvim-lsp', -- LSP completions + 'hrsh7th/cmp-buffer', -- completions from current buffer + 'hrsh7th/cmp-path', -- file path completions + 'L3MON4D3/LuaSnip', -- snippet engine (required by cmp) + 'saadparwaiz1/cmp_luasnip', + }, + config = function() + local cmp = require 'cmp' + local luasnip = require 'luasnip' + + cmp.setup { + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert { + [''] = cmp.mapping.select_next_item(), + [''] = cmp.mapping.select_prev_item(), + [''] = cmp.mapping.confirm { select = true }, -- confirm + [''] = cmp.mapping.complete(), -- open manually + }, + sources = { + { name = 'nvim_lsp' }, + { name = 'luasnip' }, + { name = 'buffer' }, + { name = 'path' }, + }, + } + end, + }, + + -- -------------------------------------------------------- + -- COLORSCHEME + -- -------------------------------------------------------- + -- A clean, low-distraction theme. Change to any you prefer. + { + 'rebelot/kanagawa.nvim', + priority = 1000, -- load before other plugins + config = function() + vim.cmd.colorscheme 'kanagawa' + end, + }, + +}, { + -- lazy.nvim options + ui = { + -- Use ascii borders if your terminal font lacks nerdfont icons + border = 'rounded', + }, +}) diff --git a/provision.sh b/provision.sh new file mode 100644 index 0000000..d8cbfae --- /dev/null +++ b/provision.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# provision.sh — set up a new machine from this dotfiles repo +# +# What this does: +# 1. Installs system dependencies (stow, git, neovim, mise, ripgrep) +# 2. Uses stow to symlink each config package into your home directory +# +# What this does NOT do: +# - Set your git name/email (edit git/.gitconfig yourself) +# - Run mise install (do that manually after review) +# +# Usage: +# bash provision.sh # normal run +# bash provision.sh --dry-run # show what would happen, do nothing + +set -euo pipefail + +DRY_RUN=false +if [[ "${1:-}" == "--dry-run" ]]; then + DRY_RUN=true + echo "[dry-run] No changes will be made." +fi + +run() { + if $DRY_RUN; then + echo "[dry-run] $*" + else + "$@" + fi +} + +DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +echo "Dotfiles directory: $DOTFILES_DIR" + +# ============================================================ +# SYSTEM PACKAGES +# ============================================================ +echo "==> Installing system packages..." +run sudo dnf install -y \ + stow \ + git \ + neovim \ + ripgrep \ + curl + +# Install mise if not already present +if ! command -v mise &>/dev/null; then + echo "==> Installing mise..." + run curl https://mise.run | bash +else + echo "==> mise already installed, skipping." +fi + +# ============================================================ +# STOW PACKAGES +# ============================================================ +# Each directory in dotfiles/ is a stow "package". +# stow creates symlinks in ~ that mirror the package directory structure. +# +# Example: bash/.bashrc → ~/.bashrc + +PACKAGES=(bash git mise nvim) + +echo "==> Stowing config packages..." +for pkg in "${PACKAGES[@]}"; do + echo " stow $pkg" + # --restow removes and recreates links (handles updates) + # --target=$HOME is explicit about where links go + run stow --restow --target="$HOME" --dir="$DOTFILES_DIR" "$pkg" +done + +echo "" +echo "Done. Next steps:" +echo " 1. Edit ~/gitconfig — set your name and email" +echo " 2. Run: mise install" +echo " 3. Open nvim — plugins will install automatically on first launch" +echo " 4. In nvim, run :checkhealth to verify your setup"