Skip to content

Instantly share code, notes, and snippets.

@subfuzion
Last active April 3, 2025 16:27
Show Gist options
  • Save subfuzion/05c114600f5b070b7c35e2c70b45b396 to your computer and use it in GitHub Desktop.
Save subfuzion/05c114600f5b070b7c35e2c70b45b396 to your computer and use it in GitHub Desktop.
My bash dotfiles for macOS development
# #############################################################################
# Generated by my-linux-setup
# https://github.com/subfuzion/my-linux-setup
# Do not edit; edit template instead:
# /Users/tony/code/my-linux-setup/tmpl/profile
# #############################################################################
#
# custom prompt also used by custom Ctrl-L binding
#
print_relative_dir() {
re="^$HOME(/?.*)"
[[ "$PWD" =~ $re ]] && echo "~${BASH_REMATCH[1]}" || echo "$PWD"
}
is_workspace() {
# Path on macOS will begin with /Volumes
re="^(/Volumes)?(/google/src/cloud)/(${USER})/([^/]+)(/.*)?"
dir="$PWD"
[[ "$dir" =~ $re ]] && return 0 || return 1
}
parse_workspace() {
re="^(/Volumes)?(/google/src/cloud)/(${USER})/([^/]+)(/.*)?"
dir="$PWD"
if [[ ! "$dir" =~ $re ]]; then
print_relative_dir
return 0
fi
project="${BASH_REMATCH[4]}"
wspath="${BASH_REMATCH[5]}"
printf "[%s] %s" "$project" "$(basename $wspath)"
}
parse_client() {
is_workspace || return
ws="piper"
hg root 2>/dev/null 1>&2 ; [[ "$?" -eq 0 ]] && ws="fig"
printf " (%s)" "$ws"
}
parse_git_branch() {
git branch --show-current 2>/dev/null | sed -e 's/\(.*\)/ (\1)/'
}
# used by custom Ctrl-L (should match first line of prompt_generator function)
prompt_header() {
local header="\[\033[01;32m\]\h \[\033[00m\]\[\033[32m\]$(parse_workspace)\[\033[01;32m\]$(parse_client)$(parse_git_branch)\[\033[00m\]"
printf "${header@P}"
}
prompt_generator() {
export PS1="$(prompt_header)\n$ "
}
export PROMPT_COMMAND=prompt_generator
#
# shell customizations
#
alias l="ls -ChF --group-directories-first --color=tty"
alias la="l -A"
alias ll="la -l"
alias lh="ls -a | grep '^\.'"
alias lt="ll -t"
alias lr="ll --recursive"
alias gb="git branch"
alias gc="git checkout"
alias gr="git rebase"
alias gri="gr -i"
alias gs="git status -u"
alias gv="git remote -v"
alias gl="git log --oneline"
alias gg="git log --graph --oneline --decorate"
# skip the shortlog first line and last line
#alias gsl="git shortlog | tail -n +2 | awk '{\$1=\$1}1' | head -n -1"
alias gsl="git shortlog | awk '{\$1=\$1}1' | head -n -1"
rebase() {
wip
if [[ -v 1 ]]; then
git rebase --interactive @~$1
else
git rebase --interactive --root
fi
}
wip() {
git status --short --untracked-files=all
if [ $# -gt 0 ]; then
git add $1
else
git add .
fi
local msg="${2:-wip}"
git commit -m "$msg"
git push
}
refactor() {
git status --short --untracked-files=all
if [ $# -gt 0 ]; then
git add $@
else
git add .
fi
git commit -m refactor
git push
}
# clear (cursor home, clear screen, clear scrollback buffer)
# Not as efficient as Ctrl-L, but works the same as clear, but also clears
# the scrollback buffer. Flickers like clear does.
# Use this when Ctrl-L doesn't work with TMUX inside of JetBrains terminal
# for a multiline promt.
alias c="printf '\e[H\e[2J\e[3J'"
# alternatively, override Ctrl-L
bind -x $'"\C-l":printf "\e[H\e[2J\e[3J$(prompt_header)\n";'
# completions
# bash
if [ -f /opt/local/etc/profile.d/bash_completion.sh ]; then
. /opt/local/etc/profile.d/bash_completion.sh
fi
# fzf
. /opt/local/share/fzf/shell/key-bindings.bash
. /opt/local/share/fzf/shell/completion.bash
# lima
. <(limactl completion bash)
# deno
. ~/.local/share/bash-completion/completions/deno.bash
# #############################################################################
# END (anything below this line was added by some other installer script
# #############################################################################
# Added by Windsurf
export PATH="/Users/tony/.codeium/windsurf/bin:$PATH"
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
# disable prompting for large results
# https://superuser.com/questions/601992/how-can-i-disable-that-display-all-possibilities-and-more-stuff-in-bash
# Increase the default limit before warning prompt for large results
# Or set to 0 to disable
# set completion-query-items [value]
set completion-query-items 0
# to disable default paging of long results
# set page-completions off
# #############################################################################
# Generated by my-linux-setup
# https://github.com/subfuzion/my-linux-setup
# Do not edit; edit template instead:
# /Users/tony/code/my-linux-setup/tmpl/profile
# #############################################################################
# shouldn't need to set this explicitly, but nvm defaults to $HOME/.nvm if not set
export XDG_CONFIG_HOME="$HOME/.config"
# use macport vim (newer than macOS default)
export EDITOR=/opt/local/bin/vim
export VISUAL=/opt/local/bin/vim
# Search paths are *prepended* to $PATH in increasing order of importance to me
# deno
source "$HOME/.deno/env"
# go
export PATH="$PATH:/usr/local/go/bin"
# Node.js
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && source "$NVM_DIR/bash_completion"
# Completions
[ -f "$HOME/.fzf.bash" ] && source "$HOME/.fzf.bash"
[ -f "$HOME/bin/tl-completion.bash" ] && source "$HOME/bin/tl-completion.bash"
[ -f "$HOME/.config/completions/deno.bash" ] && source "$HOME/.config/completions/deno.bash"
# C development
# macports clang for cmake
#alias cmake-init="\cmake -DCMAKE_C_COMPILER=/opt/local/bin/clang"
# Source install cmake ($HOME/code/cmake/cmake)
alias cmake-init="/usr/local/bin/cmake -DCMAKE_C_COMPILER=/opt/local/bin/clang"
# using source built cmake instead of macports-installed version:
alias cmake=/usr/local/bin/cmake
export CC=/opt/local/bin/clang
# #############################################################################
# FINAL settings should run last
# Macports
export PATH="/opt/local/bin:/opt/local/sbin:$PATH"
#
# coreutils has the following notes:
# The tools provided by GNU coreutils are prefixed with the character 'g' by
# default to distinguish them from the BSD commands.
# For example, cp becomes gcp and ls becomes gls.
#
# If you want to use the GNU tools by default, add this directory to the front
# of your PATH environment variable:
# /opt/local/libexec/gnubin/
export PATH="/opt/local/libexec/gnubin:$PATH"
export PATH="$HOME/bin:$PATH"
# If this is a bash shell, then source .bashrc
[ -n "$BASH_VERSION" ] && [ -f "$HOME/.bashrc" ] && source "$HOME/.bashrc"
# END (anything below this line was added by some other installer script
# #############################################################################
# Inspirations:
# http://mutelight.org/practical-tmux
# http://zanshin.net/2013/09/05/my-tmux-configuration/
# http://files.floriancrouzat.net/dotfiles/.tmux.conf
# http://stackoverflow.com/questions/9628435/tmux-status-bar-configuration
# https://github.com/Lokaltog/powerline
# https://github.com/remiprev/teamocil
# http://superuser.com/questions/74492/whats-the-best-prefix-escape-sequence-for-screen-or-tmux
# http://blog.hawkhost.com/2010/07/02/tmux-%E2%80%93-the-terminal-multiplexer-part-2/
#
set -g default-terminal "screen-256color"
# ***WARNING!*** tmux will exit immediately if this plugin is not installed!!!
# http://superuser.com/questions/397076/tmux-exits-with-exited-on-mac-os-x
# set-option -g default-command "reattach-to-user-namespace -l $SHELL"
# change default prefix (C-b) to C-space
unbind C-space
set -g prefix C-space
bind C-space send-prefix
#unbind C-k
#set -g prefix C-k
#bind C-k send-prefix
# start numbering from 0 instead of 1
set -g base-index 0
setw -g pane-base-index 0
# bind C-a C-a to last active window
bind-key C-a last-window
# get rid of delay reading command characters while tmux waits for escape sequence
set -s escape-time 1
# reload ~/.tmux.conf using prefix r
bind r source-file ~/.tmux.conf \; display "tmux reloaded"
# change split prefixes (horizontal: C-space /) (vertical: C-space -)
bind / split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
# make current window the 1st window
bind T swap-window -t 1
# set scrollback history to 10K lines
set -g history-limit 10000
# mouse support
#setw -g mode-mouse on
set -g mouse on
# https://github.com/tmux/tmux/issues/145#issuecomment-151098708
#bind -n WheelUpPane if-shell -F -T = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'copy-mode -e; send-keys -M'"
# https://github.com/tmux/tmux/issues/145#issuecomment-151123624
bind -n WheelUpPane if-shell -F -t = "#{mouse_any_flag}" "send-keys -M" "if -Ft= '#{pane_in_mode}' 'send-keys -M' 'select-pane -t=; copy-mode -e; send-keys -M'"
bind -n WheelDownPane select-pane -t= \; send-keys -M
# vi
# ==
setw -g mode-keys vi
set -g status-keys vi
# setup 'v' to begin selection as in vim
#bind-key -T vi-copy v begin-selection
bind-key -T copy-mode-vi 'v' send-keys -X begin-selection
#bind-key -T vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"
bind-key -T copy-mode-vi 'y' send-keys -X copy-selection
# update default binding of `Enter` to also use copy-pipe (os x)
#unbind -T vi-copy Enter
unbind -T copy-mode-vi 'Enter'
#bind-key -T vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy"
bind-key -T copy-mode-vi 'Enter' send-keys -X copy-selection
# map vi movement keys as pane movement keys
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R
# use vi left and right to cycle thru panes
bind -r C-h select-window -t :-
bind -r C-l select-window -t :+
# resize panes using vi keys
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5
# status bar
# ==========
# set status bar
#set -g status-justify centre
set -g status-justify left
#set -g status-left ""
#set -g status-right "#[fg=green]#H"
# dark theme
#set -g status-bg "#101010"
#set -g status-fg "#005000"
# light theme
#set -g status-bg "#222222"
set -g status-bg "#303030"
set -g status-fg "#009000"
# show host name and IP address on left side of status bar
# set -g status-left-length 70
# informational (but takes room)
# set -g status-left "#h #(curl -4 https://icanhazip.com) #(ifconfig en0 | grep 'inet ' | awk '{print \"en0 \" $2}') #(ifconfig en1 | grep 'inet ' | awk '{print \"en1 \" $2}') #(ifconfig tun0 | grep 'inet ' | awk '{print \"vpn \" $2}') "
# show session name, window & pane number, date and time on right
# of status bar
#set -g status-right-length 60
# set -g status-right "#S #I:#P %d %b %Y %l:%M %p (#(date -u | awk '{print $4}' | cut -c1-5))"
set -g status-right ""
set-option -g set-titles on
# Highlight active window
setw -g window-status-current-style fg=black
setw -g window-status-current-style fg=green
# quiet!
# http://unix.stackexchange.com/questions/169992/why-are-my-windows-highlighted-when-i-first-open-tmux
setw -g monitor-activity off
set -g monitor-silence 0
set -g bell-action none
set -g visual-activity off
set -g visual-bell off
set -g visual-silence off
set -g bell-action none
"====================================================================
" Leader key
"====================================================================
nnoremap <space> <nop>
let g:mapleader = " "
"====================================================================
" Map - keep up-to-date as a quick reference and to avoid conflicts.
"====================================================================
" <leader> |
" a |
" b |
" c |
" d |
" e | netrw explorer
" f |
" g |
" h |
" i |
" j |
" k |
" l | list buffers
" m |
" n | next buffer
" o |
" p | previous buffer
" q |
" r |
" rn | rename symbol
" s |
" t |
" u |
" v |
" w | tree
" x |
" y |
" a |
" <space> | toggle previous buffer
" ; | fzf
" <C-M> | CTRL-Enter: open terminal in tab
"====================================================================
" Basic editor settings
"====================================================================
" Don't pollute current directory
set backupdir=/tmp//
set directory=/tmp//
set undodir=/tmp//
" Disable beep / flash.
set vb t_vb=
set novisualbell
set noerrorbells
set backspace=indent,eol,start
" Zippy
set timeoutlen=300
set updatetime=300
set ttyfast
set clipboard=unnamed
" Capture mouse (prevents tmux from scrolling out of vim).
set mouse=a
set ttymouse=sgr
" Nice vertical lines for window splits.
set fillchars+=vert:\▏
" Scroll a bit extra horizontally when scrolling past side edge.
set sidescroll=6
" Enable line and column display.
set ruler
" Note: set noshowmode if using vim-airline.
set showmode
" Show command in statusline
set showcmd
" Always show statusline even if only window.
"set laststatus=2
set laststatus=1
" Highlight matches when searching.
set hlsearch
" Clear highlighted search items (redraw screen).
nnoremap <silent> \\ :nohlsearch<CR><c-L>
let s:hidden_all = 0
function! ToggleHiddenAll()
if s:hidden_all == 0
let s:hidden_all = 1
"set noshowmode
"set noruler
set laststatus=1
"set noshowcmd
else
let s:hidden_all = 0
"set showmode
"set ruler
set laststatus=2
"set showcmd
endif
endfunction
nnoremap ss :call ToggleHiddenAll()<CR>
"====================================================================
" Unsaved files behavior
"====================================================================
" netrw will use the whole window when `hidden` is set.
set hidden
" Leave buffers without being forced to write changes.
"set noautowriteall
" Automatically save changes when leaving buffers.
" The opposite of the above (maybe useful if you always want changes
" saved when leaving a buffer, such as watching for files changes
" in a dev environment and you don't want to keep saving everything
" explicitly.
set nohidden
set autowriteall
" Get reminded if any unsaved edits when quitting.
set confirm
"====================================================================
" Toggles
" tn - toggle numbers (line numbers)
" tw - toggle wrapping (line wrapping)
" th - toggle highlighting for current line
" ts - toggle syntax highlighting
" tl - toggle list (whitespace characters)
"====================================================================
" Toggle line numbers: tn
set nonumber
nnoremap <silent> tn :set number! number?<CR>
" Toggle soft line wrapping: tw
set nowrap
nnoremap <silent> tw :set wrap! wrap?<CR>
" Toggle list (display) hidden whitespace: tl
set listchars=eol:↲,tab:→\ ,nbsp:_,extends:…,trail:•
set nolist
nnoremap <silent> tl :set list! list?<CR>
" Toggle current line highlighting: th
set cursorline
nnoremap <silent> th :set cursorline!<CR>
" Toggle syntax highlighting: ts
syntax enable
syntax on
"nnoremap <silent> ts :if exists("g:syntax_on") <bar>
nnoremap <silent> ts :if exists("g:syntax_on") <bar>
\ syntax off <bar>
\ else <bar>
\ syntax on <bar>
\ endif <CR>
" Disable syntax highlighting for specific file extensions, for ex:
"au BufNewFile,BufRead *.{json} setlocal syntax=off
au BufNewFile,BufRead *.{txt} setlocal syntax=off
"====================================================================
" Buffers
"====================================================================
" Go to next buffer.
nnoremap <silent> <leader>n :bn<CR>
" Go to previous buffer.
nnoremap <silent> <leader>p :bp<CR>
" Toggle buffer (switch between current and last buffer).
nnoremap <silent> <leader><space> <C-^>
" Page forward and back.
nnoremap <S-f> <c-f>
nnoremap <S-b> <c-b>
" Scroll up and down using same keys for cursor up and down.
nnoremap <C-j> <c-e>
nnoremap <C-k> <c-y>
" Go to buffer.
"
" 1. <space>l
" => list buffers and then enter :b# to go to buffer
" or :b<space><tab> to select
nnoremap <silent> <leader>l :buffers<CR>
"
" 2. <tab><tab>
" => list buffers and select by tabbing
"nnoremap <silent> <Tab> :buffer<space>
nnoremap <silent> ;;<CR> :buffers<CR>
nnoremap <silent> ;; :buffer<space>
nnoremap <silent> ;;p :bprevious<CR>
nnoremap <silent> ;;n :bnext<CR>
"====================================================================
" Windows
" Generally avoid using windows and embrace using buffers primarily.
" However, sometimes you really do need a window. If try to avoid
" being dependent on customizations and embrace the following:
" Avoid the custom settings and embrace the following:
" :new | add horizontal split and active window below
" :vnew | add vertical split and active window to right
" <c-w>h|j|k|l | move to window to left|below|above|right
" <c-w>c | close window (not buffer)
" <c-w>= | resize windows evently
"
" I use windows rarely enough that I don't mind using the mouse
" on those occasions to resize windows, so don't feel a need to
" customize the keys. However, uncomment and use the following
" if you must.
"====================================================================
" If you prefer opening windows to right and below. However, I
" recommend embracing the vim way. Just think of your windows
" as a stack and then the default behavior of opening above and
" to the left make sense.
"set splitright
"set splitbelow
" These are helpful and complement the buffer keys
nnoremap <silent> ;;h <c-w>h
nnoremap <silent> ;;j <c-w>j
nnoremap <silent> ;;k <c-w>k
nnoremap <silent> ;;l <c-w>l
" Resize horizontal splits (change height).
" <c-w><s--> and <c-w><s-=> only shift one line at a time (too slow)
"nnoremap <silent> <C-w>- :exe <C-w><s-->
"nnoremap <silent> <C-w>= :exe <C-w><s-=>
"nnoremap <silent> <leader>- :exe "resize " . (winheight(0) - 10)<CR>
"nnoremap <silent> <leader>= :exe "resize " . (winheight(0) + 10)<CR>
" Resize vertical splits (change width).
" <c-w><s-,> and <c-w><s-.> only shift one line at a time (too slow)
"nnoremap <silent> <C-w>, <C-w><s-,>
"nnoremap <silent> <C-w>. <C-w><s-.>
"nnoremap <silent> <leader>, :exe "vertical resize " . (winwidth(0) - 10)<CR>
"nnoremap <silent> <leader>. :exe "vertical resize " . (winwidth(0) + 10)<CR>
" Resize everything evently.
nnoremap <silent> ;;= <c-w>=
nnoremap <silent> <leader>= <c-w>=
"====================================================================
" Tabs
" I only use tabs for the terminal.
"====================================================================
nnoremap <silent> ttf :tabfirst<CR>
nnoremap <silent> ttl :tablast<CR>
nnoremap <silent> ttn :tabnext<CR>
nnoremap <silent> ttp :tabprev<CR>
nnoremap <silent> ttc :tabclose<CR>
nnoremap <silent> tls :tabs<CR>
"====================================================================
" Terminal
"====================================================================
nnoremap <silent> <C-M> :tab term<CR>
tnoremap <nowait> <expr> <Esc> (&filetype == "fzf") ? "<Esc>" : "<C-w>N"
"====================================================================
" netrw file explorer (project drawer)
" Minimalist configuration; sometimes it's nice to see the file
" directory structure, but the rest of the time, use fzf (below).
" Note: <leader>t has been mapped to the shell tree command as well.
"====================================================================
let g:netrw_banner = 0
let g:netrw_liststyle = 3
" Acts as a toggle, but only works if netrw has been loaded first,
" such as by entering :e .<CR>
nnoremap <silent> <leader>e :Rexplore<CR>
"====================================================================
" fzf
" https://github.com/junegunn/fzf/blob/master/README-VIM.md
" Check out: https://github.com/junegunn/fzf.vim
"====================================================================
"set rtp+=~/.fzf
" macports fzf:
set rtp+=/opt/local/share/fzf/vim
let g:fzf_action = {
\ 'ctrl-t': 'tab split',
\ 'ctrl-x': 'belowright split',
\ 'ctrl-v': 'vsplit' }
" map :fzf to :FZF
cnoreabbrev <expr> fzf getcmdtype() == ":" && getcmdline() == 'fzf' ? 'FZF' : 'fzf'
" map ;; to :FZF
nnoremap <silent> <leader>; :FZF<CR>
" To enable history for MRU...
" I prefer Ctrl-n and Ctrl-p navigates the visual list, not history
"let g:fzf_history_dir = '~/.local/share/fzf-history'
"====================================================================
" Color scheme
"====================================================================
set bg=dark
colorscheme habamax
command! Slate :colorscheme slate
command! Haba :colorscheme habamax
command! Dark :colorscheme quiet|set bg=dark
command! Light :colorscheme quiet|set bg=light
"====================================================================
" Preferences
"====================================================================
" Initial settings likely to change often
function s:default()
" wild menu tab completion
set wildmenu
set wildmode=longest:list,full
" Format
set tabstop=8
set softtabstop=8
set shiftwidth=8
set noexpandtab
set autoindent
filetype plugin indent on
" find
set wildignore=.git/,node_modules/,build/,tmp/,scratch
set path+=**
endfunction
" Reload .vimrc
command! ConfigReload source $MYVIMRC|echom "Reloaded .vimrc"
" Edit .vimrc
command! ConfigEdit edit $MYVIMRC
" Reset just the default settings
command! ConfigDefault call s:default()
" Follow ConfigDefault command pattern to create other setting profiles
augroup AutoEnter
autocmd!
autocmd VimEnter * call s:default()
augroup END
nnoremap <silent> <leader>t :!tree -C \| less -r <CR><CR>
colorscheme habamax
syn off
set nocursorline
set paste
These are my dotfiles tailored specifically for coding on macOS.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment