Compare commits

..

4 commits

Author SHA1 Message Date
29e053af75
Add Neovim config 2026-08-06 23:56:13 +02:00
5a2f500fca
profile: Set dark theme for Gtk, use qt6ct for Qt styling 2026-08-01 17:16:15 +02:00
4a079ad19d
dotfiles script v0.5.3
Change indentation from tabs to spaces.
2026-08-01 17:14:49 +02:00
b197b7e2bc
Normalize indentation to spaces 2026-08-01 17:13:37 +02:00
14 changed files with 714 additions and 457 deletions

View file

@ -2,7 +2,7 @@
# Include all files from ~/.bash_completion.d/ # Include all files from ~/.bash_completion.d/
if [[ -d ~/.bash_completion.d ]]; then if [[ -d ~/.bash_completion.d ]]; then
for f in ~/.bash_completion.d/*; do for f in ~/.bash_completion.d/*; do
[[ -f "$f" ]] && . "$f" [[ -f "$f" ]] && . "$f"
done done
fi fi

30
.bashrc
View file

@ -40,15 +40,15 @@ alias ll='ls -la'
# Colored man pages # Colored man pages
man() { man() {
env \ env \
LESS_TERMCAP_mb=$(printf "\e[1;31m") \ LESS_TERMCAP_mb=$(printf "\e[1;31m") \
LESS_TERMCAP_md=$(printf "\e[1;31m") \ LESS_TERMCAP_md=$(printf "\e[1;31m") \
LESS_TERMCAP_me=$(printf "\e[0m") \ LESS_TERMCAP_me=$(printf "\e[0m") \
LESS_TERMCAP_se=$(printf "\e[0m") \ LESS_TERMCAP_se=$(printf "\e[0m") \
LESS_TERMCAP_so=$(printf "\e[1;44;33m") \ LESS_TERMCAP_so=$(printf "\e[1;44;33m") \
LESS_TERMCAP_ue=$(printf "\e[0m") \ LESS_TERMCAP_ue=$(printf "\e[0m") \
LESS_TERMCAP_us=$(printf "\e[1;32m") \ LESS_TERMCAP_us=$(printf "\e[1;32m") \
man "$@" man "$@"
} }
# (Other aliases are defined in .bashrc.d/10_common_aliases.sh etc.) # (Other aliases are defined in .bashrc.d/10_common_aliases.sh etc.)
@ -67,21 +67,21 @@ TWHITEB='\[\e[1;37m\]' # White bold
# Set default prompt # Set default prompt
if [[ ${EUID} == 0 ]] ; then if [[ ${EUID} == 0 ]] ; then
PS1="${TRED}\u@\h ${TBLUE}\w ${TWHITEB}\$ ${TRESET}" PS1="${TRED}\u@\h ${TBLUE}\w ${TWHITEB}\$ ${TRESET}"
else else
PS1="${TGREEN}\u@\h ${TBLUE}\w ${TWHITEB}\$ ${TRESET}" PS1="${TGREEN}\u@\h ${TBLUE}\w ${TWHITEB}\$ ${TRESET}"
fi fi
# Include drop-in files # Include drop-in files
if [[ -d ~/.config/bashrc.d ]]; then if [[ -d ~/.config/bashrc.d ]]; then
for f in ~/.config/bashrc.d/*; do for f in ~/.config/bashrc.d/*; do
[[ -f $f ]] && source "$f" [[ -f $f ]] && source "$f"
done done
fi fi
# Deprecation warning for old drop-in file locations # Deprecation warning for old drop-in file locations
if [[ -e ~/.bashrc.d || -e ~/.bashrc.local ]]; then if [[ -e ~/.bashrc.d || -e ~/.bashrc.local ]]; then
echo "WARNING: ~/.bashrc.d and ~/.bashrc.local are ignored, please use ~/.config/bashrc.d/ instead." echo "WARNING: ~/.bashrc.d and ~/.bashrc.local are ignored, please use ~/.config/bashrc.d/ instead."
fi fi
# Clean up environment variables # Clean up environment variables

View file

@ -17,64 +17,70 @@ alias suvim='sudo -e'
# Stop Ctrl-S from doing terminally things in vim/vimdiff # Stop Ctrl-S from doing terminally things in vim/vimdiff
vim() { vim() {
local STTYOPTS="$(stty --save)" local STTYOPTS="$(stty --save)"
stty stop '' -ixoff stty stop '' -ixoff
command vim "$@" command vim "$@"
stty "$STTYOPTS" stty "$STTYOPTS"
} }
vimdiff() { vimdiff() {
local STTYOPTS="$(stty --save)" local STTYOPTS="$(stty --save)"
stty stop '' -ixoff stty stop '' -ixoff
command vimdiff "$@" command vimdiff "$@"
stty "$STTYOPTS" stty "$STTYOPTS"
} }
# Neovim shortcuts
alias nv='nvim'
alias nvimr='nvim -R'
alias nvim-config='nvim ~/.config/nvim/init.lua'
# yay without parameters does "pacman -Syu" but I don't want it to do this # yay without parameters does "pacman -Syu" but I don't want it to do this
yay() { yay() {
[[ $# -gt 0 ]] || { echo "error: no operation specified (use -h for help)"; return 1; } [[ $# -gt 0 ]] || { echo "error: no operation specified (use -h for help)"; return 1; }
command yay "$@" command yay "$@"
} }
# Create and cd to temporary directory ~/tmp/tmp.YYYYMMDD.XXXXXX or ~/tmp/tmp.$1.XXXXXX if an argument is given # Create and cd to temporary directory ~/tmp/tmp.YYYYMMDD.XXXXXX or ~/tmp/tmp.$1.XXXXXX if an argument is given
function cdtmp() { function cdtmp() {
cd $(mktemp -d -p ~/tmp tmp.${1:-$(date +%Y%m%d)}.XXXXXX) cd $(mktemp -d -p ~/tmp tmp.${1:-$(date +%Y%m%d)}.XXXXXX)
} }
# Make dir and cd into it (from Mara) # Make dir and cd into it (from Mara)
function mkcd() { function mkcd() {
mkdir -p "$1" mkdir -p "$1"
cd "$1" cd "$1"
} }
# cd into dir + ll (ls -la) # cd into dir + ll (ls -la)
function cdll() { function cdll() {
cd "$1" cd "$1"
ls -la ls -la
} }
# Show content of something, `ls` for dirs (and special files), `cat` for files # Show content of something, `ls` for dirs (and special files), `cat` for files
# TODO: actually `highlight` for fancy colors
function lscat() { function lscat() {
[[ $# -eq 0 ]] && ls -la && return [[ $# -eq 0 ]] && ls -la && return
printnewline="" printnewline=""
for f in "$@"; do for f in "$@"; do
[[ $printnewline ]] && echo [[ $printnewline ]] && echo
printnewline=1 printnewline=1
if [[ -f $f ]]; then if [[ -f $f ]]; then
[[ $# -gt 1 ]] && echo "-- cat \"$f\"" [[ $# -gt 1 ]] && echo "-- cat \"$f\""
cat "$f" cat "$f"
else else
[[ $# -gt 1 ]] && echo "-- ls \"$f\"" [[ $# -gt 1 ]] && echo "-- ls \"$f\""
ls -la "$f" ls -la "$f"
fi fi
done done
} }
# Shortcut for lscat (either c for cat or c for "see") # Shortcut for lscat (either c for cat or c for "see")
alias c='lscat' alias c='lscat'
function calc() { function calc() {
echo "$@" | bc echo "$@" | bc
} }
# termbin.com: terminal pastebin # termbin.com: terminal pastebin

View file

@ -4,7 +4,7 @@
# Open files according to MIME type # Open files according to MIME type
xo() { xo() {
(nohup mimeopen "$@" 2>/dev/null 1>&2 &) (nohup mimeopen "$@" 2>/dev/null 1>&2 &)
} }
# X application aliases # X application aliases

View file

@ -12,7 +12,7 @@ fi
# Set prompt: highlight hostname in red to signalize "you're on a server, be careful" # Set prompt: highlight hostname in red to signalize "you're on a server, be careful"
if [[ ${EUID} == 0 ]] ; then if [[ ${EUID} == 0 ]] ; then
PS1="${TRED}\u@\h ${TBLUE}\w ${TWHITEB}\$ ${TRESET}" PS1="${TRED}\u@\h ${TBLUE}\w ${TWHITEB}\$ ${TRESET}"
else else
PS1="${TGREEN}\u@${TRED}\h ${TBLUE}\w ${TWHITEB}\$ ${TRESET}" PS1="${TGREEN}\u@${TRED}\h ${TBLUE}\w ${TWHITEB}\$ ${TRESET}"
fi fi

View file

@ -1,6 +1,6 @@
[core] [core]
# Normalize line endings # Normalize line endings
autocrlf = input autocrlf = input
[advice] [advice]
detachedHead = false detachedHead = false
@ -41,10 +41,10 @@
helper = /usr/lib/git-core/git-credential-libsecret helper = /usr/lib/git-core/git-credential-libsecret
[filter "lfs"] [filter "lfs"]
required = true required = true
clean = git-lfs clean -- %f clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f smudge = git-lfs smudge -- %f
process = git-lfs filter-process process = git-lfs filter-process
[pretty] [pretty]
ls = tformat:%C(yellow)%h %Cgreen%ad %Creset%s %Cblue[%an]%C(auto)%d ls = tformat:%C(yellow)%h %Cgreen%ad %Creset%s %Cblue[%an]%C(auto)%d

128
.config/nvim/init.lua Normal file
View file

@ -0,0 +1,128 @@
-- Config shortcuts
local o = vim.o
local opt = vim.opt
local keymap = vim.keymap
------------------
-- GENERAL OPTIONS
------------------
-- Line numbers
o.number = true
o.relativenumber = true
-- Highlight the cursor line
o.cursorline = true
-- Amount of screen lines that should be visible above/below the cursor
o.scrolloff = 8
-- Show tabs and trailing spaces
o.list = true
-- Wrap lines at word boundaries
o.linebreak = true
-- Case insensitive search (except when explicitly using uppercase letters)
o.ignorecase = true
o.smartcase = true
-- Indentation settings
o.smartindent = true
o.expandtab = true
o.shiftwidth = 4
o.softtabstop = -1
-- Don't auto-insert comment leader when entering insert mode with o/O
vim.api.nvim_create_autocmd('FileType', {
command = 'set formatoptions-=o',
})
-------------
-- FILE TYPES
-------------
vim.filetype.add {
extension = {
gitconfig = 'gitconfig',
},
}
-- HTML formatting
vim.g.html_indent_autotags = 'html,body'
vim.g.html_indent_inctags = 'p'
-----------
-- MAPPINGS
-----------
-- For keys that are safe to be mapped, see: https://vim.fandom.com/wiki/Unused_keys
-- Exit insert mode with jk
keymap.set('i', 'jk', '<Esc>')
-- Quick exit with Ctrl-q
keymap.set('n', '<C-q>', ':q<CR>')
-- Quick save all open buffers with Ctrl-s
keymap.set('n', '<C-s>', ':wall<CR>')
keymap.set('i', '<C-s>', '<C-o>:wall<CR>')
-- Simple copy and paste to/from system clipboard with Ctrl-c in visual mode
-- and Ctrl-v in insert mode
keymap.set('v', '<C-c>', '"+y')
keymap.set('i', '<C-v>', '<C-\\><C-o>"+P')
-- Navigate between windows with Alt and hjkl
keymap.set('n', '<A-h>', '<C-w>h')
keymap.set('n', '<A-j>', '<C-w>j')
keymap.set('n', '<A-k>', '<C-w>k')
keymap.set('n', '<A-l>', '<C-w>l')
-- Resize windows with Alt and arrow keys
keymap.set('n', '<A-Up>', '<C-w>2-')
keymap.set('n', '<A-Down>', '<C-w>2+')
keymap.set('n', '<A-Left>', '<C-w>4<')
keymap.set('n', '<A-Right>', '<C-w>4>')
-- Shortcuts for jumping to start of line (H) or end of line (L)
keymap.set({'n', 'x'}, 'H', '^')
keymap.set({'n', 'x'}, 'L', '$')
-- Use comma (,) as a "modifier prefix" for alternative functions of regular
-- commands (e.g. yank to system clipboard) or for random shortcuts.
-- TODO: Comma or semicolon or single quote?
keymap.set({'n', 'x'}, ',', '<Nop>')
-- Prefix yank/delete/change/paste commands with "," to use system clipboard
keymap.set({'n', 'x'}, ',y', '"+y')
keymap.set({'n', 'x'}, ',Y', '"+y$')
keymap.set({'n', 'x'}, ',d', '"+d')
keymap.set({'n', 'x'}, ',D', '"+D')
keymap.set({'n', 'x'}, ',c', '"+c')
keymap.set({'n', 'x'}, ',C', '"+C')
keymap.set({'n', 'x'}, ',p', '"+p')
keymap.set({'n', 'x'}, ',P', '"+P')
-- Insert empty line(s) below or above current line without moving the cursor
keymap.set('n', ',o', function()
local line = vim.api.nvim_win_get_cursor(0)[1]
local repeated = vim.fn['repeat']({''}, vim.v.count1)
vim.api.nvim_buf_set_lines(0, line, line, true, repeated)
end)
keymap.set('n', ',O', function()
local line = vim.api.nvim_win_get_cursor(0)[1] - 1
local repeated = vim.fn['repeat']({''}, vim.v.count1)
vim.api.nvim_buf_set_lines(0, line, line, true, repeated)
end)
----------
-- PLUGINS
----------
require('init.theme')
require('init.plugins')

View file

@ -0,0 +1,103 @@
-- Config shortcuts
local keymap = vim.keymap
local vr = vim.version.range
------------------
-- INSTALL PLUGINS
------------------
vim.pack.add {
-- Better code completion
{ src = 'https://github.com/saghen/blink.cmp', version = vr '1.*' },
-- Better marks
'https://github.com/chentoast/marks.nvim',
-- Surround selections with quotes etc.
{ src = 'https://github.com/kylechui/nvim-surround', version = vr '4.*' },
-- Substitute and exchange operator
'https://github.com/gbprod/substitute.nvim',
-- Highlight todo comments
'https://github.com/folke/todo-comments.nvim',
-- Highlight colors (hex codes etc.)
'https://github.com/brenoprata10/nvim-highlight-colors',
}
---------------------
-- INITIALIZE PLUGINS
---------------------
-- Better code completion
require('blink.cmp').setup {
keymap = {
preset = 'super-tab',
},
cmdline = {
keymap = {
preset = 'inherit',
['<Tab>'] = {
'show',
'select_and_accept',
'fallback',
},
},
completion = {
menu = { auto_show = true },
},
},
}
-- Better marks
require('marks').setup {
-- Show builtin marks in gutter: last jump position (`), last change (.),
-- last selection in visual mode (</>).
-- TODO: See which of those are really helpful and remove the others.
builtin_marks = { '`', '.', '<', '>' },
}
-- Surround selections with quotes etc.
require('nvim-surround').setup {}
-- Substitute and exchange operator
local substitute = require('substitute')
substitute.setup {}
-- ... Use "s" key for substitute (by default "s" is equivalent to "cl")
keymap.set('n', 's', substitute.operator)
keymap.set('n', 'ss', substitute.line)
keymap.set('n', 'S', substitute.eol)
keymap.set('x', 's', substitute.visual)
-- ... Prefix with "," to use system clipboard (remap to use the substitute mappings above)
keymap.set({'n', 'x'}, ',s', '"+s', { remap = true })
keymap.set({'n', 'x'}, ',S', '"+S', { remap = true })
-- Highlight todo comments
require('todo-comments').setup {
-- Disable gutter icons
signs = false,
-- Customize highlighting
highlight = {
before = '',
-- By default ("wide"), the surrounding space and colon are highlighted too,
-- which makes the colon invisible
keyword = 'bg',
after = 'fg',
-- Highlight keywords always, not just when followed by a colon (the default)
pattern = '<(KEYWORDS)>',
},
}
-- Highlight colors (hex codes etc.)
require('nvim-highlight-colors').setup {}

View file

@ -0,0 +1,36 @@
-- Install theme plugins
vim.pack.add {
{ src = 'https://github.com/rebelot/kanagawa.nvim', name = 'kanagawa' },
-- { src = 'https://github.com/rose-pine/neovim', name = 'rose-pine' },
-- { src = 'https://github.com/nickkadutskyi/jb.nvim', name = 'jetbrains-theme' },
}
-- Initialize and customize themes
require('kanagawa').setup {
-- Compile colorscheme for fast startup times.
-- Note: When changing the theme, make sure to run `:KanagawaCompile` afterwards!
compile = true,
-- Dim inactive windows
dimInactive = true,
-- Customize colors
colors = {
theme = {
all = {
ui = {
-- Disable background of gutter (line numbers etc.)
bg_gutter = 'none',
},
},
},
},
}
--require('rose-pine').setup {}
--require('jb').setup {}
-- Enable theme
vim.cmd.colorscheme('kanagawa')
--vim.cmd.colorscheme('rose-pine')
--vim.cmd.colorscheme('jb')

View file

@ -0,0 +1,34 @@
{
"plugins": {
"blink.cmp": {
"rev": "78336bc89ee5365633bcf754d93df01678b5c08f",
"src": "https://github.com/saghen/blink.cmp",
"version": "1.0.0 - 2.0.0"
},
"kanagawa": {
"rev": "bb85e4bfc8d89b0e62c8fa53ccdd13d12e2f77b3",
"src": "https://github.com/rebelot/kanagawa.nvim"
},
"marks.nvim": {
"rev": "f353e8c08c50f39e99a9ed474172df7eddd89b72",
"src": "https://github.com/chentoast/marks.nvim"
},
"nvim-highlight-colors": {
"rev": "e4c7af0211866162d999ce0bdd6a029302e19139",
"src": "https://github.com/brenoprata10/nvim-highlight-colors"
},
"nvim-surround": {
"rev": "2e93e154de9ff326def6480a4358bfc149d5da2c",
"src": "https://github.com/kylechui/nvim-surround",
"version": "4.0.0 - 5.0.0"
},
"substitute.nvim": {
"rev": "0d2077398552f069abccbd964a26dd7cd26882cd",
"src": "https://github.com/gbprod/substitute.nvim"
},
"todo-comments.nvim": {
"rev": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668",
"src": "https://github.com/folke/todo-comments.nvim"
}
}
}

View file

@ -14,3 +14,10 @@ export WINEDLLOVERRIDES=winemenubuilder.exe=d
# Firefox: Enable pixel-perfect scrolling # Firefox: Enable pixel-perfect scrolling
export MOZ_USE_XINPUT2=1 export MOZ_USE_XINPUT2=1
# Set dark theme for Gtk applications
export GTK_THEME=Adwaita:dark
# Use qt6ct to configure Qt styling
# (You should install qt6ct-kde from AUR, as well as the breeze theme.)
export QT_QPA_PLATFORMTHEME=qt6ct

View file

@ -22,12 +22,12 @@ export BC_ENV_ARGS="-lq"
# Include drop-in files # Include drop-in files
if [[ -d ~/.config/profile.d ]]; then if [[ -d ~/.config/profile.d ]]; then
for f in ~/.config/profile.d/*; do for f in ~/.config/profile.d/*; do
[[ -f $f ]] && source "$f" [[ -f $f ]] && source "$f"
done done
fi fi
# Deprecation warning for .profile.local # Deprecation warning for .profile.local
if [[ -e ~/.profile.local ]]; then if [[ -e ~/.profile.local ]]; then
echo "WARNING: ~/.profile.local is ignored, please use ~/.config/profile.d/ instead." echo "WARNING: ~/.profile.local is ignored, please use ~/.config/profile.d/ instead."
fi fi

149
.vimrc
View file

@ -1,9 +1,24 @@
" Visual settings " Visual settings
set t_Co=16 set t_Co=16
set bg=dark set bg=dark
set number
highlight LineNr ctermfg=darkgrey highlight LineNr ctermfg=darkgrey
" Disable beeping on console
set belloff=all
" Mouse settings
set mouse=a
" Line numbers
set number
set relativenumber
" Amount of screen lines that should be visible above/below the cursor
set scrolloff=5
" Wrap lines at word boundaries
set linebreak
" Syntax highlighting " Syntax highlighting
syntax on syntax on
set hlsearch set hlsearch
@ -12,12 +27,11 @@ set hlsearch
set ignorecase set ignorecase
set smartcase set smartcase
" Indentation options (yeah let's switch to spaces instead of tabs I guess...) " Indentation settings
set autoindent set smartindent
set expandtab set expandtab
set shiftwidth=4 set shiftwidth=4
set tabstop=4 set softtabstop=-1
set softtabstop=4
" Activate filetype plugin (e.g. for automatically using tabs instead of spaces in Makefiles) " Activate filetype plugin (e.g. for automatically using tabs instead of spaces in Makefiles)
filetype plugin on filetype plugin on
@ -29,120 +43,49 @@ autocmd BufNewFile,BufRead *.rasi set syntax=scss
" Indentation for YAML (use 2 spaces) " Indentation for YAML (use 2 spaces)
autocmd FileType yml,yaml setlocal sts=2 sw=2 autocmd FileType yml,yaml setlocal sts=2 sw=2
" Mouse settings
set mouse=a
" Disable beeping on console
set belloff=all
" Do not insert comment leader when entering insert mode with 'o'/'O' in comment line " Do not insert comment leader when entering insert mode with 'o'/'O' in comment line
autocmd BufNewFile,BufRead * set formatoptions-=o autocmd BufNewFile,BufRead * set formatoptions-=o
" clang autocomplete: do not open completion box automatically
let g:clang_complete_auto=0
" Disable middle mouse button paste when in normal mode
map <MiddleMouse> <Nop>
map <2-MiddleMouse> <Nop>
map <3-MiddleMouse> <Nop>
map <4-MiddleMouse> <Nop>
" Keyboard mappings " Keyboard mappings
" ----------------- " -----------------
nnoremap <C-L> :nohl<CR>:diffupdate<CR><C-L>
nnoremap <C-l> :nohl<CR>:diffupdate<CR><C-l>
set pastetoggle=<F2> set pastetoggle=<F2>
" Toggle line numbers " Exit insert mode with jk
nnoremap <F3> :set number!<CR> inoremap jk <Esc>
" If the current buffer has never been saved, it will have no name, " Quick exit with Ctrl-q
" call the file browser to save it, otherwise just save it. nnoremap <C-q> :q<CR>
command! -nargs=0 -bar Update if &modified nnoremap Q <Nop>
\| if empty(bufname('%'))
\| browse confirm write
\| else
\| confirm write
\| endif
\|endif
" Bind <C-S> to save " Quick save all open buffers with Ctrl-S
nnoremap <silent> <C-s> :<C-u>Update<CR> nnoremap <C-s> :wall<CR>
inoremap <C-s> <C-o>:Update<CR> inoremap <C-s> <C-o>:wall<CR>
" Simple copy and paste to/from system clipboard with Ctrl-c in visual mode
" and Ctrl-v in insert mode
vnoremap <C-c> "+y
inoremap <C-v> <C-\><C-o>"+P
" sudo-write with :w!! " sudo-write with :w!!
cnoremap w!! w !sudo tee >/dev/null % cnoremap w!! w !sudo tee >/dev/null %
" Edit (\ev) and reload (\rv) .vimrc (reload .gvimrc if running gvim)
nnoremap <leader>ev :split $MYVIMRC<CR>
if has('gui_running')
nnoremap <leader>rv :source $MYVIMRC<CR>:source $MYGVIMRC<CR>
else
nnoremap <leader>rv :source $MYVIMRC<CR>
endif
" Split line at cursor with <C-J> (as opposite of <Shift-J> for join lines)
nnoremap <C-J> i<CR><Esc>k$
" Easier buffer switching
" -----------------------
" Mappings to access buffers (don't use "\p" because a
" delay before pressing "p" would accidentally paste).
" \l : list buffers
" \b \n \g : go back/forward/last-used
" \1 \2 \3 : go to buffer 1/2/3 etc
nnoremap <Leader>l :ls<CR>
nnoremap <Leader>b :bp<CR>
nnoremap <Leader>n :bn<CR>
nnoremap <Leader>g :e#<CR>
nnoremap <Leader>1 :1b<CR>
nnoremap <Leader>2 :2b<CR>
nnoremap <Leader>3 :3b<CR>
nnoremap <Leader>4 :4b<CR>
nnoremap <Leader>5 :5b<CR>
nnoremap <Leader>6 :6b<CR>
nnoremap <Leader>7 :7b<CR>
nnoremap <Leader>8 :8b<CR>
nnoremap <Leader>9 :9b<CR>
nnoremap <Leader>0 :10b<CR>
" Compiling and making
nnoremap <F9> :up<CR>:make<CR>:redraw! \| cw<CR>
nnoremap <F10> :up<CR>:make run<CR>:redraw! \| cw<CR>
" Tab buffers
nnoremap <F12> :tab ball<CR>
" Tab movement " Tab movement
noremap <A-[> :-tabmove<CR> noremap <A-[> :-tabmove<CR>
noremap <A-]> :+tabmove<CR> noremap <A-]> :+tabmove<CR>
" Use comma (,) as a "modifier prefix" for alternative functions of regular
" commands (e.g. yank to system clipboard) or for random shortcuts.
noremap , <Nop>
" -- Shortcuts for insert mode " Prefix yank/delete/change/paste commands with "," to use system clipboard
" Exit insert mode noremap ,y "+y
imap ,, <ESC> noremap ,Y "+y$
imap jk <ESC> noremap ,d "+d
inoremap <A-,> <ESC> noremap ,D "+D
noremap ,c "+c
" Quick movement with Alt-h/j/k/l noremap ,C "+C
inoremap <A-h> <C-o>h noremap ,p "+p
inoremap <A-j> <C-o>j noremap ,P "+P
inoremap <A-k> <C-o>k
inoremap <A-l> <C-o>l
" Unindent with Shift-Tab
inoremap <S-Tab> <C-o><<
" Copy to and paste from X clipboard (Ctrl-C in visual mode and Ctrl-V in insert mode)
vmap <C-C> "+y
imap <C-V> <C-\><C-O>"+P
" Undo in insert mode with Ctrl-U
imap <C-U> <C-O>u
" Quick exit
map Q :qa<CR>
" Because I always type q: too fast, which opens the command history...
map q: :q

View file

@ -2,49 +2,49 @@
## ##
## binaryDiv's dotfiles management script ## binaryDiv's dotfiles management script
## Version 0.5.2 ## Version 0.5.3
## ##
usage() { usage() {
cat <<- END_OF_HELPTEXT cat << END_OF_HELPTEXT
Usage: $(basename $0) COMMAND [...] Usage: $(basename $0) COMMAND [...]
Manage dotfiles via git. Manage dotfiles via git.
General commands: General commands:
help print this help message help print this help message
Installation: Installation:
install run this on first start: install dotfiles script in ~/bin, configure git, ... install run this on first start: install dotfiles script in ~/bin, configure git, ...
(this will NOT create links for all dotfiles, though) (this will NOT create links for all dotfiles, though)
Dotfile management: Dotfile management:
ls [DIR] list contents of .dotfiles directory (or DIR relative to it) ls [DIR] list contents of .dotfiles directory (or DIR relative to it)
(-l: list host-specific files, i.e. ~/.dotfiles/_local/HOSTNAME/DIR) (-l: list host-specific files, i.e. ~/.dotfiles/_local/HOSTNAME/DIR)
edit FILE open ~/.dotfiles/FILE in vim edit FILE open ~/.dotfiles/FILE in vim
(-l: open host-specific files, i.e. ~/.dotfiles/_local/HOSTNAME/DIR) (-l: open host-specific files, i.e. ~/.dotfiles/_local/HOSTNAME/DIR)
diff FILE use vimdiff to compare ~/FILE to ~/.dotfiles/FILE diff FILE use vimdiff to compare ~/FILE to ~/.dotfiles/FILE
(-l: compare host-specific files, i.e. ~/.dotfiles/_local/HOSTNAME/DIR) (-l: compare host-specific files, i.e. ~/.dotfiles/_local/HOSTNAME/DIR)
link FILE... create a symlink from ~/FILE to ~/.dotfiles/FILE (multiple files possible) link FILE... create a symlink from ~/FILE to ~/.dotfiles/FILE (multiple files possible)
(-q: be quiet, only print something if an error occurs) (-q: be quiet, only print something if an error occurs)
(-l: link host-specific files, i.e. ~/FILE to ~/.dotfiles/_local/HOSTNAME/FILE) (-l: link host-specific files, i.e. ~/FILE to ~/.dotfiles/_local/HOSTNAME/FILE)
linkstatus [DIR] list contents of .dotfiles with information about whether there are links to linkstatus [DIR] list contents of .dotfiles with information about whether there are links to
them in ~/, whether they differ, etc... them in ~/, whether they differ, etc...
(-l: show linkstatus only for host-specific files, i.e. ~/.dotfiles/_local/HOSTNAME) (-l: show linkstatus only for host-specific files, i.e. ~/.dotfiles/_local/HOSTNAME)
createfrom FILE... copy ~/FILE to ~/.dotfiles/FILE and symlink the file createfrom FILE... copy ~/FILE to ~/.dotfiles/FILE and symlink the file
(-n: only copy, leave the original, do not create symlink) (-n: only copy, leave the original, do not create symlink)
(-l: create host-specific files, i.e. ~/FILE to ~/.dotfiles/_local/HOSTNAME/FILE) (-l: create host-specific files, i.e. ~/FILE to ~/.dotfiles/_local/HOSTNAME/FILE)
Synchronization: Synchronization:
git ARGS... wrapper for git (all arguments are passed on to git) git ARGS... wrapper for git (all arguments are passed on to git)
pull shortcut for git pull pull shortcut for git pull
END_OF_HELPTEXT END_OF_HELPTEXT
} }
# Define root dir for dotfiles management (defaults to $HOME, can be overridden # Define root dir for dotfiles management (defaults to $HOME, can be overridden
# with environment variables for debugging) # with environment variables for debugging)
if [[ -z $DOTFILESROOT ]]; then if [[ -z $DOTFILESROOT ]]; then
DOTFILESROOT="$HOME" DOTFILESROOT="$HOME"
fi fi
# Set variables # Set variables
@ -62,315 +62,315 @@ shift
# Parse command # Parse command
case "$cmd" in case "$cmd" in
help|--help|-h) help|--help|-h)
usage usage
exit 1 exit 1
;; ;;
install) install)
bin_source="$dotfilesdir/bin/dotfiles" bin_source="$dotfilesdir/bin/dotfiles"
bin_target="$homedir/bin/dotfiles" bin_target="$homedir/bin/dotfiles"
bin_dir="$homedir/bin" bin_dir="$homedir/bin"
if [[ ! -e $bin_target ]]; then if [[ ! -e $bin_target ]]; then
echo "* Installing dotfiles script in $bin_dir/" echo "* Installing dotfiles script in $bin_dir/"
mkdir -pv "$bin_dir" mkdir -pv "$bin_dir"
ln -sr "$bin_source" "$bin_target" || exit 1 ln -sr "$bin_source" "$bin_target" || exit 1
elif [[ ! "$(realpath $bin_target)" -ef "$bin_source" ]]; then elif [[ ! "$(realpath $bin_target)" -ef "$bin_source" ]]; then
echo "! Warning: File $bin_target already exists but is NOT a link to $bin_source" echo "! Warning: File $bin_target already exists but is NOT a link to $bin_source"
fi fi
if [[ ":$PATH:" != *":$bin_dir:"* ]]; then if [[ ":$PATH:" != *":$bin_dir:"* ]]; then
echo "! Warning: $bin_dir is not in your PATH." echo "! Warning: $bin_dir is not in your PATH."
fi fi
show_bash_restart_info= show_bash_restart_info=
# Enable user-defined bash completion per directory # Enable user-defined bash completion per directory
bashcompletion_filename=.bash_completion bashcompletion_filename=.bash_completion
if [[ ! -e "$homedir/$bashcompletion_filename" ]] || if [[ ! -e "$homedir/$bashcompletion_filename" ]] ||
[[ ! "$(realpath "$homedir/$bashcompletion_filename")" -ef "$dotfilesdir/$bashcompletion_filename" ]]; [[ ! "$(realpath "$homedir/$bashcompletion_filename")" -ef "$dotfilesdir/$bashcompletion_filename" ]];
then then
echo "* Installing user-defined bash completion (~/.bash_completion.d/)" echo "* Installing user-defined bash completion (~/.bash_completion.d/)"
"$0" link -q "$bashcompletion_filename" && "$0" link -q "$bashcompletion_filename" &&
show_bash_restart_info=1 show_bash_restart_info=1
fi fi
mkdir -p "$homedir/.bash_completion.d" mkdir -p "$homedir/.bash_completion.d"
# Activate dotfiles bash completion # Activate dotfiles bash completion
bashcompletion_dotfiles_filename=.bash_completion.d/10-dotfiles.sh bashcompletion_dotfiles_filename=.bash_completion.d/10-dotfiles.sh
if [[ ! -e "$homedir/$bashcompletion_dotfiles_filename" ]] || if [[ ! -e "$homedir/$bashcompletion_dotfiles_filename" ]] ||
[[ ! "$(realpath "$homedir/$bashcompletion_dotfiles_filename")" -ef "$dotfilesdir/$bashcompletion_dotfiles_filename" ]]; [[ ! "$(realpath "$homedir/$bashcompletion_dotfiles_filename")" -ef "$dotfilesdir/$bashcompletion_dotfiles_filename" ]];
then then
echo "* Installing bash completion for dotfiles script" echo "* Installing bash completion for dotfiles script"
"$0" link -q "$bashcompletion_dotfiles_filename" && "$0" link -q "$bashcompletion_dotfiles_filename" &&
show_bash_restart_info=1 show_bash_restart_info=1
fi fi
if [[ -n $show_bash_restart_info ]]; then if [[ -n $show_bash_restart_info ]]; then
echo " Restart bash or run 'source $homedir/.bash_completion' to activate it now" echo " Restart bash or run 'source $homedir/.bash_completion' to activate it now"
fi fi
echo "* Configuring git settings" echo "* Configuring git settings"
git -C "$dotfilesdir" config merge.ff only git -C "$dotfilesdir" config merge.ff only
;; ;;
ls) ls)
lsdir="$dotfilesdir" lsdir="$dotfilesdir"
[[ $1 = "-l" ]] && { lsdir="$lsdir/$dotfiles_local_prefix"; shift; } [[ $1 = "-l" ]] && { lsdir="$lsdir/$dotfiles_local_prefix"; shift; }
[[ -n $1 ]] && lsdir="$lsdir/$1" [[ -n $1 ]] && lsdir="$lsdir/$1"
echo "$lsdir:" echo "$lsdir:"
ls -lAh --color=auto "$lsdir" ls -lAh --color=auto "$lsdir"
;; ;;
linkstatus) linkstatus)
cd "$dotfilesdir" cd "$dotfilesdir"
subdir="$1" subdir="$1"
[[ $subdir = "-l" ]] && { subdir="$dotfiles_local_prefix/$1"; shift; } [[ $subdir = "-l" ]] && { subdir="$dotfiles_local_prefix/$1"; shift; }
if [[ -n $subdir ]]; then if [[ -n $subdir ]]; then
subdir="${subdir%/}" subdir="${subdir%/}"
[[ $subdir = $dotfiles_local_base ]] && subdir=$dotfiles_local_prefix [[ $subdir = $dotfiles_local_base ]] && subdir=$dotfiles_local_prefix
[[ -e $subdir ]] || { echo "$dotfilesdir/$subdir does not exist"; exit 1; } [[ -e $subdir ]] || { echo "$dotfilesdir/$subdir does not exist"; exit 1; }
[[ -d $subdir ]] && subdir="$subdir/" [[ -d $subdir ]] && subdir="$subdir/"
fi fi
shopt -s nullglob dotglob shopt -s nullglob dotglob
dotdirs=() dotdirs=()
for file in $subdir*; do for file in $subdir*; do
[[ -e $file ]] || continue [[ -e $file ]] || continue
[[ $file = ".git" ]] && continue [[ $file = ".git" ]] && continue
file_home="$homedir/$file" file_home="$homedir/$file"
file_dotfiles="$dotfilesdir/$file" file_dotfiles="$dotfilesdir/$file"
if [[ $subdir == $dotfiles_local_base/* ]]; then if [[ $subdir == $dotfiles_local_base/* ]]; then
file_home="$homedir/${file#$dotfiles_local_prefix/}" file_home="$homedir/${file#$dotfiles_local_prefix/}"
fi fi
if [[ -e $file_home ]]; then if [[ -e $file_home ]]; then
if [[ "$(realpath "$file_home")" -ef "$file_dotfiles" ]]; then if [[ "$(realpath "$file_home")" -ef "$file_dotfiles" ]]; then
file_status=" LINKED " file_status=" LINKED "
elif [[ -d $file_home ]]; then elif [[ -d $file_home ]]; then
dotdirs+=($file) dotdirs+=($file)
continue continue
elif [[ -f $file_home ]] && cmp --silent "$file_home" "$file_dotfiles"; then elif [[ -f $file_home ]] && cmp --silent "$file_home" "$file_dotfiles"; then
file_status="== EQUAL " file_status="== EQUAL "
else else
file_status="<> DIFFERS " file_status="<> DIFFERS "
fi fi
elif [[ $file = $dotfiles_local_base ]]; then elif [[ $file = $dotfiles_local_base ]]; then
dotdirs=("$dotfiles_local_prefix" "${dotdirs[@]}") dotdirs=("$dotfiles_local_prefix" "${dotdirs[@]}")
continue continue
else else
if [[ -d $file_dotfiles ]]; then if [[ -d $file_dotfiles ]]; then
file_status="++ NEW DIR " file_status="++ NEW DIR "
else else
file_status="++ NEW FILE" file_status="++ NEW FILE"
fi fi
fi fi
[[ -d $file_dotfiles ]] && file="$file/" [[ -d $file_dotfiles ]] && file="$file/"
echo "$file_status $file" echo "$file_status $file"
done done
if [[ $dotdirs ]]; then if [[ $dotdirs ]]; then
echo echo
for dir in ${dotdirs[@]}; do for dir in ${dotdirs[@]}; do
echo "[$dir]" echo "[$dir]"
dotfiles linkstatus "$dir" | grep '\(LINKED\|EQUAL\|DIFFERS\|NEW\)' dotfiles linkstatus "$dir" | grep '\(LINKED\|EQUAL\|DIFFERS\|NEW\)'
echo echo
done done
fi fi
;; ;;
edit) edit)
basedir=$dotfilesdir basedir=$dotfilesdir
[[ $1 = "-l" ]] && { basedir="$basedir/$dotfiles_local_prefix"; shift; } [[ $1 = "-l" ]] && { basedir="$basedir/$dotfiles_local_prefix"; shift; }
[[ -n $1 ]] || { echo "$(basename $0) $cmd: Missing argument."; exit 1; } [[ -n $1 ]] || { echo "$(basename $0) $cmd: Missing argument."; exit 1; }
vim "$basedir/$1" vim "$basedir/$1"
;; ;;
diff) diff)
basedir=$dotfilesdir basedir=$dotfilesdir
[[ $1 = "-l" ]] && { basedir="$basedir/$dotfiles_local_prefix"; shift; } [[ $1 = "-l" ]] && { basedir="$basedir/$dotfiles_local_prefix"; shift; }
[[ -n $1 ]] || { echo "$(basename $0) $cmd: Missing argument."; exit 1; } [[ -n $1 ]] || { echo "$(basename $0) $cmd: Missing argument."; exit 1; }
file_A="$homedir/$1" file_A="$homedir/$1"
file_B="$basedir/$1" file_B="$basedir/$1"
if [[ "$(realpath "$file_A")" -ef "$file_B" ]]; then if [[ "$(realpath "$file_A")" -ef "$file_B" ]]; then
echo "$file_A is a link to $file_B" echo "$file_A is a link to $file_B"
else else
vimdiff "$file_A" "$file_B" vimdiff "$file_A" "$file_B"
fi fi
;; ;;
link) link)
while getopts ":ql" opt; do while getopts ":ql" opt; do
case $opt in case $opt in
q) QUIET=1 ;; q) QUIET=1 ;;
l) link_local=1 ;; l) link_local=1 ;;
\?) \?)
echo "Invalid option: -$OPTARG" echo "Invalid option: -$OPTARG"
exit 1 exit 1
;; ;;
esac esac
done done
shift $((OPTIND-1)) shift $((OPTIND-1))
[[ -n $1 ]] || { echo "$(basename $0) $cmd: Missing argument."; exit 1; } [[ -n $1 ]] || { echo "$(basename $0) $cmd: Missing argument."; exit 1; }
for filename in "$@"; do for filename in "$@"; do
file_home="$homedir/$filename" file_home="$homedir/$filename"
file_dotfiles="$dotfilesdir/$filename" file_dotfiles="$dotfilesdir/$filename"
if [[ $link_local ]]; then if [[ $link_local ]]; then
file_dotfiles="$dotfilesdir/$dotfiles_local_prefix/$filename" file_dotfiles="$dotfilesdir/$dotfiles_local_prefix/$filename"
fi fi
if [[ ! -e $file_dotfiles ]]; then if [[ ! -e $file_dotfiles ]]; then
echo "! $file_dotfiles: target file does not exist" echo "! $file_dotfiles: target file does not exist"
exit 1 exit 1
fi fi
if [[ -e $file_home ]]; then if [[ -e $file_home ]]; then
if [[ "$(realpath "$file_home")" -ef "$file_dotfiles" ]]; then if [[ "$(realpath "$file_home")" -ef "$file_dotfiles" ]]; then
# Target is already a link to the correct file # Target is already a link to the correct file
continue continue
fi fi
if cmp --silent "$file_home" "$file_dotfiles"; then if cmp --silent "$file_home" "$file_dotfiles"; then
echo "! $file_home already exists and is equal to $file_dotfiles" echo "! $file_home already exists and is equal to $file_dotfiles"
read -p " Delete $file_home and create link? [y/N] " -r read -p " Delete $file_home and create link? [y/N] " -r
if [[ ! $REPLY =~ ^[Yy]$ ]]; then if [[ ! $REPLY =~ ^[Yy]$ ]]; then
# Don't delete file # Don't delete file
continue continue
fi fi
rm "$file_home" || exit 1 rm "$file_home" || exit 1
else else
echo "! $file_home already exists but is NOT a link to $file_dotfiles, please fix manually" echo "! $file_home already exists but is NOT a link to $file_dotfiles, please fix manually"
exit 1 exit 1
fi fi
fi fi
[[ $QUIET ]] || echo "* Creating link $file_home -> $file_dotfiles" [[ $QUIET ]] || echo "* Creating link $file_home -> $file_dotfiles"
mkdir -p "$(dirname "$file_home")" || exit 1 mkdir -p "$(dirname "$file_home")" || exit 1
ln -sr "$file_dotfiles" "$file_home" || exit 1 ln -sr "$file_dotfiles" "$file_home" || exit 1
done done
;; ;;
createfrom) createfrom)
while getopts ":nl" opt; do while getopts ":nl" opt; do
case $opt in case $opt in
n) NOLINK=1 ;; n) NOLINK=1 ;;
l) create_local=1 ;; l) create_local=1 ;;
\?) \?)
echo "Invalid option: -$OPTARG" echo "Invalid option: -$OPTARG"
exit 1 exit 1
;; ;;
esac esac
done done
shift $((OPTIND-1)) shift $((OPTIND-1))
[[ -n $1 ]] || { echo "$(basename $0) $cmd: Missing argument."; exit 1; } [[ -n $1 ]] || { echo "$(basename $0) $cmd: Missing argument."; exit 1; }
for filename in "$@"; do for filename in "$@"; do
file_home="$homedir/$filename" file_home="$homedir/$filename"
file_dotfiles="$dotfilesdir/$filename" file_dotfiles="$dotfilesdir/$filename"
if [[ $create_local ]]; then if [[ $create_local ]]; then
file_dotfiles="$dotfilesdir/$dotfiles_local_prefix/$filename" file_dotfiles="$dotfilesdir/$dotfiles_local_prefix/$filename"
fi fi
if [[ ! -e $file_home ]]; then if [[ ! -e $file_home ]]; then
echo "! $file_home: source file does not exist" echo "! $file_home: source file does not exist"
exit 1 exit 1
elif [[ -e $file_dotfiles ]]; then elif [[ -e $file_dotfiles ]]; then
echo "! $file_dotfiles already exists" echo "! $file_dotfiles already exists"
exit 1 exit 1
else else
mkdir -p "$(dirname "$file_dotfiles")" mkdir -p "$(dirname "$file_dotfiles")"
[[ $QUIET ]] || echo "* Copy $file_home -> $file_dotfiles" [[ $QUIET ]] || echo "* Copy $file_home -> $file_dotfiles"
cp -n "$file_home" "$file_dotfiles" || exit 1 cp -n "$file_home" "$file_dotfiles" || exit 1
if [[ ! $NOLINK ]]; then if [[ ! $NOLINK ]]; then
[[ $QUIET ]] || echo "* Remove original and link $file_home -> $file_dotfiles" [[ $QUIET ]] || echo "* Remove original and link $file_home -> $file_dotfiles"
rm "$file_home" || exit 1 rm "$file_home" || exit 1
ln -sr "$file_dotfiles" "$file_home" || exit 1 ln -sr "$file_dotfiles" "$file_home" || exit 1
fi fi
fi fi
done done
;; ;;
git) git)
git -C "$dotfilesdir" "$@" git -C "$dotfilesdir" "$@"
;; ;;
pull) pull)
git -C "$dotfilesdir" pull "$@" git -C "$dotfilesdir" pull "$@"
;; ;;
bash-completion) bash-completion)
cat <<- 'END_OF_BASHCOMPLETION' cat << 'END_OF_BASHCOMPLETION'
_dotfiles_filenames() { _dotfiles_filenames() {
compopt -o filenames compopt -o filenames
files=($(compgen -f -X '*/@(.|..|.git)' .dotfiles/$cur)) files=($(compgen -f -X '*/@(.|..|.git)' .dotfiles/$cur))
COMPREPLY=(${files[@]#.dotfiles/}) COMPREPLY=(${files[@]#.dotfiles/})
} }
_dotfiles_filenames_local() { _dotfiles_filenames_local() {
compopt -o filenames compopt -o filenames
dotfiles_prefix=.dotfiles/_local/$(hostname) dotfiles_prefix=.dotfiles/_local/$(hostname)
files=($(compgen -f -X '*/@(.|..|.git)' $dotfiles_prefix/$cur)) files=($(compgen -f -X '*/@(.|..|.git)' $dotfiles_prefix/$cur))
COMPREPLY=(${files[@]#$dotfiles_prefix/}) COMPREPLY=(${files[@]#$dotfiles_prefix/})
} }
_dotfiles() { _dotfiles() {
COMPREPLY=() COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}" local cur="${COMP_WORDS[COMP_CWORD]}"
local commands="help install ls edit diff link linkstatus createfrom git pull" local commands="help install ls edit diff link linkstatus createfrom git pull"
local gitcommands="add commit diff fetch log pull push rebase status" local gitcommands="add commit diff fetch log pull push rebase status"
if [[ $COMP_CWORD -eq 1 ]]; then if [[ $COMP_CWORD -eq 1 ]]; then
COMPREPLY=($(compgen -W "$commands" -- $cur)) COMPREPLY=($(compgen -W "$commands" -- $cur))
else else
case "${COMP_WORDS[1]}" in case "${COMP_WORDS[1]}" in
ls|edit|diff) ls|edit|diff)
[[ $COMP_CWORD -eq 2 ]] && _dotfiles_filenames [[ $COMP_CWORD -eq 2 ]] && _dotfiles_filenames
;; ;;
link|linkstatus) link|linkstatus)
if [[ $COMP_CWORD -gt 2 && ${COMP_WORDS[2]} = "-l" ]]; then if [[ $COMP_CWORD -gt 2 && ${COMP_WORDS[2]} = "-l" ]]; then
_dotfiles_filenames_local _dotfiles_filenames_local
else else
_dotfiles_filenames _dotfiles_filenames
fi fi
;; ;;
createfrom) createfrom)
compopt -o filenames compopt -o filenames
COMPREPLY=($(compgen -f -- ${cur})) COMPREPLY=($(compgen -f -- ${cur}))
;; ;;
git) git)
if [[ $COMP_CWORD -eq 2 ]]; then if [[ $COMP_CWORD -eq 2 ]]; then
COMPREPLY=($(compgen -W "$gitcommands" -- ${cur})) COMPREPLY=($(compgen -W "$gitcommands" -- ${cur}))
else else
_dotfiles_filenames _dotfiles_filenames
fi fi
;; ;;
esac esac
fi fi
} }
complete -F _dotfiles dotfiles complete -F _dotfiles dotfiles
END_OF_BASHCOMPLETION END_OF_BASHCOMPLETION
;; ;;
*) *)
echo "Unknown command '$cmd', use 'help' to show all commands." echo "Unknown command '$cmd', use 'help' to show all commands."
exit 1 exit 1
;; ;;
esac esac