init
This commit is contained in:
204
GETTING_STARTED.md
Normal file
204
GETTING_STARTED.md
Normal file
@@ -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`
|
||||
160
README.md
Normal file
160
README.md
Normal file
@@ -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
|
||||
125
bash/.bashrc
Normal file
125
bash/.bashrc
Normal file
@@ -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"
|
||||
}
|
||||
32
git/.gitconfig
Normal file
32
git/.gitconfig
Normal file
@@ -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
|
||||
20
mise/.config/mise/config.toml
Normal file
20
mise/.config/mise/config.toml
Normal file
@@ -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
|
||||
27
notes/daily-template.md
Normal file
27
notes/daily-template.md
Normal file
@@ -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.
|
||||
17
notes/decisions.md
Normal file
17
notes/decisions.md
Normal file
@@ -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
|
||||
8
notes/inbox.md
Normal file
8
notes/inbox.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Inbox
|
||||
|
||||
Everything lands here. Do not organise while capturing.
|
||||
Process during your daily or weekly review.
|
||||
|
||||
---
|
||||
|
||||
- [ ]
|
||||
30
notes/weekly-template.md
Normal file
30
notes/weekly-template.md
Normal file
@@ -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.
|
||||
284
nvim/.config/nvim/init.lua
Normal file
284
nvim/.config/nvim/init.lua
Normal file
@@ -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.
|
||||
-- <leader> 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', '<Esc>', '<cmd>nohlsearch<CR>')
|
||||
|
||||
-- Move between windows with Ctrl+direction (no need for Ctrl+W first)
|
||||
vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move to left window' })
|
||||
vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move to right window' })
|
||||
vim.keymap.set('n', '<C-j>', '<C-w><C-j>', { desc = 'Move to lower window' })
|
||||
vim.keymap.set('n', '<C-k>', '<C-w><C-k>', { desc = 'Move to upper window' })
|
||||
|
||||
-- Quick save
|
||||
vim.keymap.set('n', '<leader>w', '<cmd>write<CR>', { desc = 'Save file' })
|
||||
|
||||
-- Open netrw file explorer (built-in, no plugin needed)
|
||||
vim.keymap.set('n', '<leader>e', '<cmd>Ex<CR>', { 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', '<leader>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'
|
||||
-- <leader>f prefix for "find"
|
||||
vim.keymap.set('n', '<leader>ff', builtin.find_files, { desc = 'Find files' })
|
||||
vim.keymap.set('n', '<leader>fg', builtin.live_grep, { desc = 'Find in files' })
|
||||
vim.keymap.set('n', '<leader>fb', builtin.buffers, { desc = 'Find open buffers' })
|
||||
vim.keymap.set('n', '<leader>fh', builtin.help_tags, { desc = 'Find help' })
|
||||
vim.keymap.set('n', '<leader>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('<leader>rn', vim.lsp.buf.rename, 'Rename symbol')
|
||||
map('<leader>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 {
|
||||
['<C-n>'] = cmp.mapping.select_next_item(),
|
||||
['<C-p>'] = cmp.mapping.select_prev_item(),
|
||||
['<C-y>'] = cmp.mapping.confirm { select = true }, -- confirm
|
||||
['<C-Space>'] = 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',
|
||||
},
|
||||
})
|
||||
77
provision.sh
Normal file
77
provision.sh
Normal file
@@ -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"
|
||||
Reference in New Issue
Block a user