From 85803f7559b69240e2d5dfa1e446bca552dac0ba Mon Sep 17 00:00:00 2001 From: Jason Hilder Date: Thu, 5 Feb 2026 21:41:38 +0200 Subject: [PATCH] Initial commit to the most minimal dotfiles! --- config/fish/conf.d/bob.fish | 1 + config/fish/config.fish | 239 ++++++++++++++++++++++++++++++++ config/fish/fish_variables | 32 +++++ config/kanata/kanata.kbd | 32 +++++ config/nvim/init.lua | 94 +++++++++++++ config/nvim/nvim-pack-lock.json | 32 +++++ install.sh | 181 ++++++++++++++++++++++++ 7 files changed, 611 insertions(+) create mode 100644 config/fish/conf.d/bob.fish create mode 100644 config/fish/config.fish create mode 100644 config/fish/fish_variables create mode 100644 config/kanata/kanata.kbd create mode 100644 config/nvim/init.lua create mode 100644 config/nvim/nvim-pack-lock.json create mode 100755 install.sh diff --git a/config/fish/conf.d/bob.fish b/config/fish/conf.d/bob.fish new file mode 100644 index 0000000..9cf1b45 --- /dev/null +++ b/config/fish/conf.d/bob.fish @@ -0,0 +1 @@ +source "/home/jason/.local/share/bob/env/env.fish" diff --git a/config/fish/config.fish b/config/fish/config.fish new file mode 100644 index 0000000..3dcc686 --- /dev/null +++ b/config/fish/config.fish @@ -0,0 +1,239 @@ +# ============================================================================== +# ENVIRONMENT VARIABLES +# ============================================================================== + +# Disable fish greeting +set -g fish_greeting + +# Core settings +set -gx EDITOR nvim +set -gx VISUAL nvim +set -gx MANPAGER "nvim +Man!" +set -gx BROWSER firefox +set -gx TERM "xterm-256color" +set -gx COLORTERM "truecolor" +set -gx LANG "en_US.UTF-8" +set -gx LC_ALL "en_US.UTF-8" + +# Development +set -gx DEBUG 1 +set -gx GOPATH "$HOME/.go" +set -gx GOCACHE "$HOME/.go/cache" +set -gx GOROOT /usr/local/go +set -gx PATH /usr/local/go/bin $GOPATH/bin $PATH + +# FZF configuration +set -gx FZF_DEFAULT_COMMAND 'fdfind --exclude={.git,.cache,.xmake,.zig-cache,build,tmp,node_modules,elpa} --type f -H' + +set -gx FZF_DEFAULT_OPTS " + --height 40% + --layout=reverse + --border + --ansi + --preview-window=down:30% + --bind 'ctrl-d:preview-page-down,ctrl-u:preview-page-up' + --color=fg:#ffffff,header:#f38ba8,info:#cba6ac,pointer:#f5e0dc + --color=marker:#f5e0dc,fg+:#cdd6f4,prompt:#cba6ac,hl+:#f38ba8" + +# ============================================================================== +# PATH CONFIGURATION +# ============================================================================== + +# Fish's 'fish_add_path' is smart: it checks if the dir exists and prevents duplicates. +fish_add_path "$HOME/.local/bin" +fish_add_path "$HOME/bin" +fish_add_path "/usr/local/bin" +fish_add_path "$HOME/.local/apps/nvim/bin" +fish_add_path "$HOME/.npm-global/bin" +fish_add_path "/var/lib/flatpak/exports/bin" +fish_add_path "$HOME/.local/share/flatpak/exports/bin" +fish_add_path "/usr/local/go/bin" +fish_add_path $GOPATH/bin +fish_add_path "$HOME/.local/bin" +fish_add_path "$HOME/bin" + + +# ============================================================================== +# ALIASES & ABBREVIATIONS +# ============================================================================== + +# List commands +alias ls='ls -lh --color=auto --group-directories-first' +alias ll='ls -lAh --color=auto --group-directories-first' +alias la='ls -la --color=auto --group-directories-first' +alias l='ls -CF --color=auto' +alias tree='tree -C' + +# Safety aliases +alias rm='rm -I --preserve-root' +alias mv='mv -i' +alias cp='cp -i' +alias ln='ln -i' + +# System information +alias df='df -h' +alias du='du -h' +alias free='free -h' +alias top='btop' + +# Application shortcuts +alias vim='nvim' +alias v='nvim' +alias :q='exit' +alias files='nemo .' +alias lg='nvim -c "lua nvgit()"' + +# Custom shortcuts +alias uz='7z' +alias dotman='bash ~/.dotfiles/install.sh' +alias reload='source ~/.config/fish/config.fish' +alias myip='curl ipinfo.io/ip; echo ""' +alias lspmake='bear -- make -B' + +# ============================================================================== +# FUNCTIONS +# ============================================================================== + +# Project Manager +function pp + set -l project_file "$HOME/.projects" + + # Create the file if it doesn't exist + if not test -f "$project_file" + touch "$project_file" + end + + if count $argv > /dev/null + # Case 1: Path provided - Add to list + set -l absolute_path (realpath $argv[1]) + + if grep -Fxq "$absolute_path" "$project_file" + echo "Project already exists in list." + else + echo "$absolute_path" >> "$project_file" + echo "Added: $absolute_path" + end + else + # Case 2: No arguments - Select and Open + set -l selection (cat "$project_file" | fzf --height 40% --reverse --header="Select Project") + + if test -n "$selection" + cd "$selection" + commandline -f repaint # Ensures the prompt updates after cd + nvim . + end + end +end + +# Build wrapper +function build + if contains -- $argv[1] "-h" "--help" + echo "build - Wrapper function for project build.sh files" + echo "Usage: build [arguments...]" + return 0 + end + + if not test -f "./build.sh" + echo "Error: No build.sh found in current directory" >&2 + return 1 + end + + if not test -x "./build.sh" + chmod +x "./build.sh" + end + + ./build.sh $argv +end + +# Extract archive +function extract + if test (count $argv) -ne 1 + echo "Usage: extract " + return 1 + end + + if test -f $argv[1] + switch $argv[1] + case '*.tar.bz2' + tar xjf $argv[1] + case '*.tar.gz' + tar xzf $argv[1] + case '*.bz2' + bunzip2 $argv[1] + case '*.rar' + unrar x $argv[1] + case '*.gz' + gunzip $argv[1] + case '*.tar' + tar xf $argv[1] + case '*.tbz2' + tar xjf $argv[1] + case '*.tgz' + tar xzf $argv[1] + case '*.zip' + unzip $argv[1] + case '*.Z' + uncompress $argv[1] + case '*.7z' + 7z x $argv[1] + case '*.xz' + unxz $argv[1] + case '*.lzma' + unlzma $argv[1] + case '*' + echo "'$argv[1]' cannot be extracted via extract()" + end + else + echo "'$argv[1]' is not a valid file" + end +end + +# ============================================================================== +# PROMPT CONFIGURATION +# ============================================================================== + +function fish_prompt + set -l last_status $status + set -l user_color (set_color green) + set -l host_color (set_color blue) + set -l path_color (set_color cyan) + set -l prompt_symbol "❯" + + # Root user adjustments + if contains $USER root + set user_color (set_color red --bold) + set prompt_symbol "#" + end + + # SSH adjustments + if set -q SSH_CONNECTION + set host_color (set_color magenta) + end + + set -l real_path (string replace -r "^$HOME" '~' $PWD) + + # Print prompt: User@Host Path + printf '%s%s%s@%s%s %s%s%s' \ + (set_color --bold) $user_color $USER $host_color (prompt_hostname) \ + $path_color $real_path (set_color normal) + + # Git integration (Fish built-in) + printf '%s' (fish_git_prompt) + + # Exit code + if test $last_status -ne 0 + printf ' %s✗%s ' (set_color red) $last_status + end + + # New line and symbol + echo + printf '%s%s%s ' (set_color blue) $prompt_symbol (set_color normal) +end + +# Fish's built-in git prompt configuration +set -g __fish_git_prompt_show_informative_status 1 +set -g __fish_git_prompt_color_branch magenta --bold +set -g __fish_git_prompt_color_stagedstate yellow +set -g __fish_git_prompt_color_invalidstate red +set -g __fish_git_prompt_color_cleanstate green --bold + diff --git a/config/fish/fish_variables b/config/fish/fish_variables new file mode 100644 index 0000000..7cdc9e7 --- /dev/null +++ b/config/fish/fish_variables @@ -0,0 +1,32 @@ +# This file contains fish universal variable definitions. +# VERSION: 3.0 +SETUVAR __fish_initialized:3400 +SETUVAR fish_color_autosuggestion:brblack +SETUVAR fish_color_cancel:\x2dr +SETUVAR fish_color_command:blue +SETUVAR fish_color_comment:red +SETUVAR fish_color_cwd:green +SETUVAR fish_color_cwd_root:red +SETUVAR fish_color_end:green +SETUVAR fish_color_error:brred +SETUVAR fish_color_escape:brcyan +SETUVAR fish_color_history_current:\x2d\x2dbold +SETUVAR fish_color_host:normal +SETUVAR fish_color_host_remote:yellow +SETUVAR fish_color_normal:normal +SETUVAR fish_color_operator:brcyan +SETUVAR fish_color_param:cyan +SETUVAR fish_color_quote:yellow +SETUVAR fish_color_redirection:cyan\x1e\x2d\x2dbold +SETUVAR fish_color_search_match:bryellow\x1e\x2d\x2dbackground\x3dbrblack +SETUVAR fish_color_selection:white\x1e\x2d\x2dbold\x1e\x2d\x2dbackground\x3dbrblack +SETUVAR fish_color_status:red +SETUVAR fish_color_user:brgreen +SETUVAR fish_color_valid_path:\x2d\x2dunderline +SETUVAR fish_key_bindings:fish_default_key_bindings +SETUVAR fish_pager_color_completion:normal +SETUVAR fish_pager_color_description:yellow\x1e\x2di +SETUVAR fish_pager_color_prefix:normal\x1e\x2d\x2dbold\x1e\x2d\x2dunderline +SETUVAR fish_pager_color_progress:brwhite\x1e\x2d\x2dbackground\x3dcyan +SETUVAR fish_pager_color_selected_background:\x2dr +SETUVAR fish_user_paths:/home/jason/\x2elocal/share/flatpak/exports/bin\x1e/home/jason/\x2elocal/bin\x1e/usr/local/bin diff --git a/config/kanata/kanata.kbd b/config/kanata/kanata.kbd new file mode 100644 index 0000000..b8240cb --- /dev/null +++ b/config/kanata/kanata.kbd @@ -0,0 +1,32 @@ +(defcfg + process-unmapped-keys yes +) + +;; HHKB Classic layout +(defsrc + esc 1 2 3 4 5 6 7 8 9 0 - = \ grv + tab q w e r t y u i o p [ ] bspc + lctl a s d f g h j k l ; ' ret + lsft z x c v b n m , . / rsft + lmet lalt spc ralt rmet +) + +(deflayer base + @nav 1 2 3 4 5 6 7 8 9 0 - = \ grv + tab q w e r t y u i o p [ ] bspc + lctl a s d f g h j k l ; ' ret + lsft z x c v b n m , . / rsft + lmet lalt spc ralt rmet +) + +(deflayer navigation + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + tab _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ left down up rght _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _ + _ lalt _ _ _ +) + +(defalias + nav (tap-hold 200 200 esc (layer-while-held navigation)) +) diff --git a/config/nvim/init.lua b/config/nvim/init.lua new file mode 100644 index 0000000..44a52e6 --- /dev/null +++ b/config/nvim/init.lua @@ -0,0 +1,94 @@ +vim.opt.mouse = 'a' -- Enables mouse support in all modes +vim.opt.nu = true -- Enables line numbers +vim.opt.relativenumber = true -- Displays relative line numbers in the buffer +vim.opt.tabstop = 4 -- Sets the number of spaces that a tab character represents +vim.opt.softtabstop = 4 -- Sets the number of spaces per tab in the editor's buffer +vim.opt.shiftwidth = 4 -- Sets the width for autoindents +vim.opt.expandtab = true -- Converts tabs to spaces +vim.opt.smartindent = true -- Enables intelligent autoindenting for new lines +vim.opt.wrap = false -- Disables text wrapping +vim.opt.swapfile = false -- Disables swap file creation +vim.opt.backup = false -- Disables making a backup before overwriting a file +vim.opt.ignorecase = true -- Makes searches case insensitive +vim.opt.smartcase = true -- Makes searches case sensitive if there's a capital letter +vim.opt.hlsearch = true -- Highlights all matches of the search pattern +vim.opt.incsearch = true -- Starts searching before typing is finished +vim.opt.termguicolors = true -- Enables true color support +vim.opt.scrolloff = 20 -- Keeps 8 lines visible above/below the cursor +vim.opt.signcolumn = "yes" -- Always show the sign column +vim.opt.isfname:append("@-@") -- Allows '@' in filenames +vim.opt.clipboard = "unnamedplus" -- Uses the system clipboard for all yank, delete, change and put operations +vim.opt.undofile = true -- Enables persistent undo +vim.opt.updatetime = 50 -- Sets the time after which the swap file is written (in milliseconds) +vim.o.breakindent = true -- Makes wrapped lines visually indented +vim.o.termguicolors = true -- Enables true color support (duplicated setting) +vim.o.splitright = true -- Set horizontal splits to the right as default +vim.o.splitbelow = true -- Set vertical splits to the bottom as default +vim.o.completeopt = 'menuone,noselect' -- Configures how the completion menu works +vim.o.winborder = 'rounded' -- LSP hover borders +vim.opt.showmode = true + +--------------------------------------------------------------------------------- +-- [[ PLUGINS ]] +--------------------------------------------------------------------------------- +vim.pack.add({ + { src = "https://github.com/rebelot/kanagawa.nvim" }, + { src = "https://github.com/neovim/nvim-lspconfig" }, + { src = "https://github.com/nvim-mini/mini.nvim" }, + { src = "https://github.com/stevearc/oil.nvim" }, + { src = "https://github.com/akinsho/toggleterm.nvim" }, + { src = "https://github.com/folke/trouble.nvim" }, + { src = "https://github.com/tribela/transparent.nvim" } +}) + +vim.cmd.colorscheme("kanagawa") + +require("trouble").setup() +require("mini.pick").setup() +require("mini.pairs").setup() +require("mini.surround").setup() +require("mini.statusline").setup() +require("oil").setup({ view_options = { show_hidden = true, } }) +require("toggleterm").setup({ open_mapping = [[]], direction = "float" }) + +--------------------------------------------------------------------------------- +-- [[ KEYMAPS ]] +--------------------------------------------------------------------------------- +vim.g.mapleader = " " +vim.keymap.set('n', '', 'noh', { silent = true }) +vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true }) +vim.keymap.set('n', 'j', "v:count == 0 ? 'gj' : 'j'", { expr = true, silent = true }) +vim.keymap.set('n', 'cr', 'lua vim.lsp.buf.rename()') +vim.keymap.set('n', 'ca', 'lua vim.lsp.buf.code_action()') +vim.keymap.set("v", "", "", ">gv") +vim.keymap.set("v", "J", ":m '>+1gv=gv") +vim.keymap.set("v", "K", ":m '<-2gv=gv") +vim.keymap.set("n", "p", "b#") +vim.keymap.set("n", "x", "bd") +vim.keymap.set("n", "f", ":Pick files") +vim.keymap.set("n", "h", ":Pick help") +vim.keymap.set("n", "s", ":Pick grep_live") +vim.keymap.set("n", "b", ":Pick buffers") +vim.keymap.set("n", "q", ":Trouble diagnostics toggle") +vim.keymap.set("n", "e", ":Oil") + +-------------------------------------------------------------------------------- +-- [[ LSP ]] +--------------------------------------------------------------------------------- +local servers = { "gopls" } +for _, server in ipairs(servers) do + vim.lsp.enable(server) +end +-------------------------------------------------------------------------------- +-- [[ AUTOCMDS ]] +--------------------------------------------------------------------------------- +-- Highlight on Yank +vim.api.nvim_create_autocmd('TextYankPost', { + group = vim.api.nvim_create_augroup('YankHighlight', { clear = true }), + callback = function() + vim.highlight.on_yank() + end, + pattern = '*', +}) + diff --git a/config/nvim/nvim-pack-lock.json b/config/nvim/nvim-pack-lock.json new file mode 100644 index 0000000..776af00 --- /dev/null +++ b/config/nvim/nvim-pack-lock.json @@ -0,0 +1,32 @@ +{ + "plugins": { + "kanagawa.nvim": { + "rev": "aef7f5cec0a40dbe7f3304214850c472e2264b10", + "src": "https://github.com/rebelot/kanagawa.nvim" + }, + "mini.nvim": { + "rev": "f28cd08c8be826355d64080400fab1764c9693dd", + "src": "https://github.com/nvim-mini/mini.nvim" + }, + "nvim-lspconfig": { + "rev": "0480b120318ec8bab27b530ffab6ee76a8c4d806", + "src": "https://github.com/neovim/nvim-lspconfig" + }, + "oil.nvim": { + "rev": "f55b25e493a7df76371cfadd0ded5004cb9cd48a", + "src": "https://github.com/stevearc/oil.nvim" + }, + "toggleterm.nvim": { + "rev": "9a88eae817ef395952e08650b3283726786fb5fb", + "src": "https://github.com/akinsho/toggleterm.nvim" + }, + "transparent.nvim": { + "rev": "a4145c52f5421f1626a4d7dc0f41e785c4439944", + "src": "https://github.com/tribela/transparent.nvim" + }, + "trouble.nvim": { + "rev": "bd67efe408d4816e25e8491cc5ad4088e708a69a", + "src": "https://github.com/folke/trouble.nvim" + } + } +} \ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..8abb6c8 --- /dev/null +++ b/install.sh @@ -0,0 +1,181 @@ +#!/bin/bash +# --------------------------------------------------------------------------------- +## Steps taken before running this script +# --------------------------------------------------------------------------------- + +# * apt update && apt upgrade +# * Setup SSH keys + +# * Download kanata binary +# * Setup kanata to start on boot: +# - sudo touch /lib/systemd/system/kanata.service +# ``` +# [Unit] +# Description=Kanata keyboard remapper +# Documentation=https://github.com/jtroo/kanata +# +# [Service] +# Type=simple +# ExecStart=/home/user/.cargo/bin/kanata --cfg /home/user/.config/kanata/config-name.kbd +# Restart=never +# +# [Install] +# WantedBy=default.target +# ``` + +# * Clone dotfiles +# * Run this install script (symlinks configs and install software) +# * Install bob neovim manager +# ``` +# curl -fsSL https://raw.githubusercontent.com/MordechaiHadad/bob/master/scripts/install.sh | bash +# ``` +# * Get fonts, Lato(desktop) and Hack(mono/terminal) +# --------------------------------------------------------------------------------- +## GLOBAL VARS +# --------------------------------------------------------------------------------- + +DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# --------------------------------------------------------------------------------- +## Parse arguments +# --------------------------------------------------------------------------------- +DO_LINKS=false +DO_INSTALL=false +CONFIRM_MODE=true # only true when no args are passed + +usage() { + echo "Usage: $0 [-l] [-i]" + echo " -l Only create symlinks (no confirmation)" + echo " -i Only install system packages (no confirmation)" + echo " (no args = do both, with confirmation)" + exit 1 +} + +if [ $# -eq 0 ]; then + DO_LINKS=true + DO_INSTALL=true + CONFIRM_MODE=true +else + CONFIRM_MODE=false + while getopts ":lih" opt; do + case $opt in + l) DO_LINKS=true ;; + i) DO_INSTALL=true ;; + h) usage ;; + *) usage ;; + esac + done +fi + +# --------------------------------------------------------------------------------- +## Helper function for linking +# --------------------------------------------------------------------------------- +link_file() { + local src="$1" + local dest="$2" + + if [ -L "$dest" ]; then + if [ "$(readlink "$dest")" == "$src" ]; then + echo "✅ Symlink already correct: $dest → $src" + ((SKIPPED++)) + else + echo "⚠️ $dest is a symlink but points to the wrong target." + echo " Replacing with correct symlink..." + rm "$dest" + ln -s "$src" "$dest" + echo "🔁 Fixed: $dest → $src" + ((CREATED++)) + fi + elif [ -e "$dest" ]; then + echo "⚠️ $dest exists but is not a symlink. Skipping." + ((SKIPPED++)) + else + mkdir -p "$(dirname "$dest")" + ln -s "$src" "$dest" + echo "✅ Linked: $dest → $src" + ((CREATED++)) + fi +} + +# --------------------------------------------------------------------------------- +## LINK SYMLINKS +# --------------------------------------------------------------------------------- +if [ "$DO_LINKS" = true ]; then + if [ "$CONFIRM_MODE" = true ]; then + read -p "❓ Do you want to create symlinks for your dotfiles? [y/N] " confirm + case "$confirm" in + [Yy]*) ;; # continue below + *) DO_LINKS=false ;; + esac + fi +fi + +if [ "$DO_LINKS" = true ]; then + echo "🔗 Checking and creating symlinks..." + CREATED=0 + SKIPPED=0 + + link_file "$DOTFILES_DIR/config/fish" "$HOME/.config/fish" + link_file "$DOTFILES_DIR/config/kanata" "$HOME/.config/kanata" + link_file "$DOTFILES_DIR/config/nvim" "$HOME/.config/nvim" + # link_file "$DOTFILES_DIR/config/tmux/.tmux.conf" "$HOME/.tmux.conf" + + echo "" + echo "🧾 Summary: $CREATED symlink(s) created or fixed, $SKIPPED skipped." + echo "" + + echo "✅ Symlink setup complete." + echo "" +fi + +# --------------------------------------------------------------------------------- +## INSTALL SYSTEM PACKAGES +# --------------------------------------------------------------------------------- +if [ "$DO_INSTALL" = true ]; then + if [ "$CONFIRM_MODE" = true ]; then + read -p "❓ Do you want to install system packages? [y/N] " confirm + case "$confirm" in + [Yy]*) ;; # continue below + *) DO_INSTALL=false ;; + esac + fi +fi + +if [ "$DO_INSTALL" = true ]; then + REQUIRED_PACKAGES=( + # system essentials + fzf fd-find btop direnv ripgrep neovim tree + build-essential make bear valgrind fish + ) + + MISSING_PACKAGES=() + + echo "🔍 Checking for missing packages..." + echo "" + + # Check which packages are missing using dpkg + for pkg in "${REQUIRED_PACKAGES[@]}"; do + # dpkg-query checks for the installed status. + # We check for a non-zero exit status which indicates the package is NOT installed. + if ! dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q "install ok installed"; then + MISSING_PACKAGES+=("$pkg") + fi + done + + if [ ${#MISSING_PACKAGES[@]} -eq 0 ]; then + echo "✅ All required packages are already installed." + else + echo "📦 Updating package lists..." + # Update package lists before installing + sudo apt update + + echo "📦 Installing missing packages: ${MISSING_PACKAGES[*]}" + # Use sudo apt install for installing on Debian + sudo apt install "${MISSING_PACKAGES[@]}" + fi + + echo "" + echo "✅ Package setup complete." + echo "" +fi +