summaryrefslogtreecommitdiff
path: root/config/profile
diff options
context:
space:
mode:
Diffstat (limited to 'config/profile')
-rwxr-xr-xconfig/profile357
1 files changed, 357 insertions, 0 deletions
diff --git a/config/profile b/config/profile
new file mode 100755
index 0000000..8f63f9e
--- /dev/null
+++ b/config/profile
@@ -0,0 +1,357 @@
+# shellcheck shell=bash
+# profiling helpers
+__profile_enabled=false
+__timestamp() {
+ # date +%s
+ perl -MTime::HiRes=time -e 'printf "%d\n", time * 1000'
+}
+ if [ $__profile_enabled = true ]; then
+ __previous_timestamp=$(__timestamp)
+ fi
+_profile() {
+ if [ $__profile_enabled = true ]; then
+ _new_timestamp=$(__timestamp)
+ _diff=$((_new_timestamp - __previous_timestamp))
+ echo "$_diff $1"
+ __previous_timestamp=$_new_timestamp
+ fi
+}
+
+_profile entry
+
+# The INTERACTIVE layer.
+#
+# Plain environment (PATH, XDG, locale, tool homes) lives in config/env, which
+# is POSIX sh and is loaded by *every* shell — see its header. This file holds
+# only what must NOT run in every shell: aliases, history, terminal setup, and
+# anything expensive (theme, jenv, and whatever profile.d brings in).
+#
+# Reached via ~/.zshrc (interactive zsh) and ~/.profile (login bash). Sourcing
+# config/env here too, because a login bash reaches ~/.profile without ever
+# passing through ~/.zshenv. It is idempotent, so the double load is harmless.
+if [ -r "$HOME/.env" ]; then
+ # shellcheck source=/dev/null
+ . "$HOME/.env"
+else
+ # No ~/.env yet. A pull that does not run link.sh (by hand, or a sync without
+ # --link) can leave this file updated and the ~/.env symlink still absent
+ # - which would silently cost it PATH, XDG, locale and EDITOR. Fall back to
+ # the copy next to this file, found through the ~/.profile symlink that got
+ # us here. Harmless once link.sh has run.
+ __dotfiles_self=$(readlink "$HOME/.profile" 2>/dev/null)
+ if [ -n "$__dotfiles_self" ] && [ -r "${__dotfiles_self%/*}/env" ]; then
+ # shellcheck source=/dev/null
+ . "${__dotfiles_self%/*}/env"
+ fi
+ unset __dotfiles_self
+fi
+_profile env
+
+# Everything below this point is bash/zsh syntax, and this file is not read
+# only by bash and zsh: Ubuntu's /bin/sh is dash, and `sh -l` sources
+# ~/.profile. dash cannot parse `[[ ]]` (noisy but survivable) and refuses a
+# function named `exit`, which is a POSIX special builtin - that one is a fatal
+# parse error, so dash dies here and never runs the command it was given. That
+# silently broke every `sh -lc '...'` on every Linux host; it surfaced as a
+# background daemon spawned that way failing before it could even create the
+# log file its error message pointed at. macOS is unaffected: its /bin/sh is
+# bash, so BASH_VERSION is set and the rest of the file still runs there.
+#
+# config/env above is POSIX and has already been sourced, so a plain sh keeps
+# PATH, XDG, locale and EDITOR. It just stops before the interactive layer,
+# which it had no use for anyway.
+if [ -z "${BASH_VERSION-}" ] && [ -z "${ZSH_VERSION-}" ]; then
+ return 0 2>/dev/null || exit 0
+fi
+
+# Marks that this file is already running, so ~/.bashrc (which we may source at
+# the very end, for login bash) doesn't source us straight back. See the header
+# of config/bashrc for the full two-way handshake.
+__dotfiles_profile=1
+
+if [[ "$(uname)" == "Darwin" ]]
+then
+ # Sometimes, when invoked via Karabiner, the HOME variable
+ # will not be defined, even with a login shell
+ : "${HOME:="/Users/$(whoami)"}"
+elif [[ "$(uname)" == "Linux" ]]
+then
+ if command -v wl-copy >/dev/null && command -v wl-paste >/dev/null; then
+ alias pbcopy='wl-copy'
+ alias pbpaste='wl-paste'
+ else
+ alias pbcopy='xclip -selection clipboard'
+ alias pbpaste='xclip -selection clipboard -o'
+ fi
+fi
+_profile clipboard_tools
+
+# ripgrep
+# Remind to use rg instead of ag
+# ag() {
+# >&2 echo "ERROR: You decided to switch to 'rg' (ripgrep)"
+# return 1
+# # command ag "$@"
+# }
+# if [[ -r "$HOME/.config/ripgrep/config" ]]; then
+# export RIPGREP_CONFIG_PATH="$HOME/.config/ripgrep/config"
+# fi
+
+# XDG_{CONFIG,CACHE,DATA}_HOME are set in config/env.
+
+# Set history file location and size.
+SHELL_NAME="$(basename "$SHELL")"
+SHELL_CACHE="$XDG_CACHE_HOME/$SHELL_NAME"
+mkdir -p "$SHELL_CACHE"
+HISTFILE="$SHELL_CACHE/history"
+HISTSIZE=1000000
+# SAVEHIST is read by zsh itself, which shellcheck can't lint for.
+# shellcheck disable=SC2034
+SAVEHIST=1000000
+
+# detach from tmux by default
+# Guard at call time, not definition time.
+# functions and sources them in non-interactive tool shells that inherit
+# $TMUX, where a bare `exit` must really exit (not detach the terminal).
+exit() {
+ if [[ -n "${TMUX:-}" ]] && [[ $- == *i* ]]; then
+ tmux detach
+ else
+ builtin exit "$@"
+ fi
+}
+exists() { command -v "$1" >/dev/null 2>&1; } # Check if command exists (is in path).
+lspath() { echo "$PATH" | tr ':' '\n'; } # list PATH entries
+pathadd() { [[ -d "$1" ]] && PATH="$1"$(echo ":$PATH:" | sed "s|:$1:|:|" | sed 's|:$||'); }
+pathapp() { [[ -d "$1" ]] && PATH=$(echo ":$PATH:" | sed "s|:$1:|:|" | sed 's|^:||')"$1"; }
+
+# GPG
+GPG_TTY=$(tty)
+export GPG_TTY
+pbsign() { pbpaste | gpg --clearsign | pbcopy; }
+pbverify() { pbpaste | gpg --verify; }
+
+# Show processes listening on TCP sockets
+listening() {
+ lsof -n -P -i4TCP -sTCP:LISTEN \
+ | awk '{ print $9,$1,$2 }' \
+ | awk -F '\:' '{ print $2 }' \
+ | grep -E -v '^$' \
+ | column -t \
+ | sort -n
+}
+
+# https://sites.google.com/site/jimmyxu101/testing/use-tcpdump-to-monitor-http-traffic
+httpdump() {
+ sudo tcpdump -A -i "${2:-lo0}" -s 0 -q "tcp port $1 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)"
+}
+
+alias clc="fc -ln -1 | sed -e 's/\\\\n/\\n/g' -e 's/\\\\t/\\t/g' | pbcopy"
+
+# bash
+
+# DISABLE_AUTO_TITLE, the core PATH entries and the less/PAGER settings are all
+# in config/env.
+# use bash like vi !
+# set -o vi
+_profile bash
+
+# when using sudo, use alias expansion (otherwise sudo ignores your aliases)
+alias sudo='sudo '
+
+# color
+export CLICOLOR=1
+THEME_COLORS="$(theme --colors)"
+export THEME_COLORS
+if [ "$(theme --mode)" = "light" ]; then
+ export LSCOLORS=GxFxCxDxBxegedabagaced
+else
+ export LSCOLORS=GxFxBxDxCxegedabagacad
+fi
+if exists bat ; then
+ # best for light: Coldark-Cold, Github, Monokai Extended Light, OneHalfLight, gruvbox-light
+ # best for dark: 1337, Coldark-Dark, Monokai Extended, OneHalfDark, gruvbox-dark
+ # config file in $XDG_CONFIG_HOME/bat/config takes precedence to this env var
+ export BAT_THEME='ansi' # works well with both light and dark themes
+ export BAT_STYLE='plain'
+ export MANPAGER="sh -c 'col -bx | bat -l man -p'"
+ export FZF_COMPLETION_OPTS='--preview '\''bat --color=always --style=numbers --line-range=:500 {}'\'
+fi
+if exists lsd
+then
+ alias ls='lsd'
+fi
+_profile color
+
+# VISUAL/EDITOR and the node environment are set in config/env.
+
+# # ruby
+# _profile ruby-start
+# export RBENV_ROOT="${RBENV_ROOT:-"$XDG_CACHE_HOME/rbenv"}" # Set rbenv location.
+# activate-rbenv() {
+# if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi
+# }
+# activate-rbenv
+# if [ -d "$HOME/.rbenv/bin" ] ; then
+# pathapp "$HOME/.rbenv/bin"
+# eval "$(rbenv init -)"
+# fi
+
+# # add user installs bin to path
+# if which ruby >/dev/null && which gem >/dev/null; then
+# pathapp "$(ruby -rubygems -e 'puts Gem.user_dir')/bin"
+# fi
+# _profile ruby-done
+
+# python
+# export VIRTUAL_ENV_DISABLE_PROMPT=1 # Add the virtualenv prompt myself.
+# LANG/LC_* are set in config/env — mosh needs a UTF-8 locale in shells that
+# never reach this file.
+# If you want to use pyenv
+# if [ -x "$(command -v pyenv)" ] ; then
+# export PYENV_ROOT="$XDG_DATA_HOME/pyenv"
+# pathadd "$PYENV_ROOT/bin"
+# eval "$(pyenv init --path)"
+# fi
+# Instead of virtualenvwrapper's:
+# mkvirtualenv -p <path/to/python> <name>
+# I prefer to use:
+# virtualenv --python=<path/to/python> .venv
+# If you want to use virtualenvwrapper, uncomment this:
+# if [ -r "$HOME/.local/pipx/venvs" ] ; then
+# export WORKON_HOME="$XDG_DATA_HOME/virtualenvs"
+# export VIRTUALENVWRAPPER_PYTHON="$HOME/.local/pipx/venvs/virtualenvwrapper/bin/python3.9"
+# source "$HOME/.local/bin/virtualenvwrapper.sh"
+# fi
+export PYENV_VIRTUALENV_DISABLE_PROMPT=1
+# The Python user bin is on PATH via config/env.
+_profile python
+
+
+# go — GOPATH and the go bin dirs are in config/env.
+godocserver() { godoc "-http=localhost:6060"; }
+_profile go
+
+# rust — CARGO_HOME/RUSTUP_HOME and the cargo bin dir are in config/env, which
+# also replaces what rustup's own $CARGO_HOME/env does (it only prepends PATH).
+
+# GNU Arm Embedded Toolchain, used to build joeycastillo/Sensor-Watch, is on
+# PATH via config/env.
+
+# java
+if exists jenv > /dev/null && [[ -z "$JENV_LOADED" ]]; then
+ eval "$(jenv init - --no-rehash)";
+ # export JAVA_HOME="${JAVA_HOME:-"$(jenv javahome)"}"
+ # export IDEA_JDK=$JAVA_HOME
+ # to make sure JAVA_HOME is set, enable this plugin - just need to run once:
+ # jenv enable-plugin export
+fi
+_profile jenv-init
+
+# A gradlew / gradle wrapper.
+# https://github.com/gdubw/gng
+# This would be nice but it breaks existing IntelliJ projects
+# export GRADLE_USER_HOME="$XDG_CACHE_HOME/gradle" # Also contains gradle.properties (symlink from XDG_CONFIG_HOME).
+if exists gw > /dev/null; then
+ alias gradle=gw
+fi
+
+_profile java
+
+# ANDROID_HOME and the colima/testcontainers docker vars are in config/env.
+
+# Interactive setup linked in from elsewhere, one file per concern, in name
+# order. This repo ships none: it is where a machine's own layer plugs in, with
+# whatever needs a secret or names a host -- a token wrapper, API keys.
+# ~/.localprofile, below, is for hand-written per-host setup and still has the
+# last word.
+#
+# A function only to scope nullglob: zsh aborts on a glob matching nothing, and
+# bash would hand the loop the literal pattern. The files are sourced inside it,
+# so their plain assignments, exports and functions are global, but `local` or
+# `typeset` in them would not be -- and under zsh neither would a `setopt`,
+# which local_options reverts when the function returns.
+__dotfiles_source_dir() {
+ if [ -n "${ZSH_VERSION-}" ]; then
+ setopt local_options null_glob
+ else
+ # Not `$(shopt -p nullglob)`: that exits 1 when the option is off, and a
+ # caller that sources this under `set -e` would die here without a word.
+ local __dotfiles_nullglob=''
+ shopt -q nullglob || __dotfiles_nullglob='shopt -u nullglob'
+ shopt -s nullglob
+ fi
+ local __dotfiles_f
+ for __dotfiles_f in "$1"/*.sh; do
+ # shellcheck source=/dev/null
+ . "$__dotfiles_f"
+ done
+ if [ -z "${ZSH_VERSION-}" ] && [ -n "$__dotfiles_nullglob" ]; then
+ eval "$__dotfiles_nullglob"
+ fi
+}
+__dotfiles_source_dir "${XDG_CONFIG_HOME:-$HOME/.config}/shell/profile.d"
+unset -f __dotfiles_source_dir
+_profile profile.d
+
+macbook_chassis_regulatory_model() {
+ ioreg -l \
+ | grep '"regulatory-model-number"' \
+ | sed -E 's/.*<([^>]+).*/\1/' \
+ | cut -c1-10 \
+ | xxd -r -p \
+ | tr -d '\000'
+}
+_profile misc
+
+if [[ -r /proc/cpuinfo ]] && \
+ grep -qi 'raspberry pi' /proc/cpuinfo
+then
+ system_temperature() {
+ paste \
+ <(cat /sys/class/thermal/thermal_zone*/type) \
+ <(cat /sys/class/thermal/thermal_zone*/temp | sed 's/\(.\)..$/.\1°C/' ) \
+ | column -s $'\t' -t
+ if [[ -f /sys/class/thermal/cooling_device0/cur_state ]]
+ then
+ echo "Fan state: $(cat /sys/class/thermal/cooling_device0/cur_state)"
+ else
+ echo "No fan"
+ fi
+ }
+fi
+_profile raspberry_pi
+
+# The kimi / cursor-agent / claude env vars are all in config/env.
+
+if [ -n "$ZSH_VERSION" ]; then
+ [[ -d /opt/homebrew/share/zsh/site-functions/ ]] && fpath+=(/opt/homebrew/share/zsh/site-functions/)
+fi
+_profile zsh_specific
+
+# Disable XON/XOFF flow control so Ctrl-Q/Ctrl-S work in apps like nvim
+stty -ixon 2>/dev/null
+# The Ghostty bin dir is on PATH via config/env.
+_profile misc
+
+# Interactive host-local setup. Plain host-local *environment* goes in
+# ~/.localenv, which config/env sources for every shell.
+# shellcheck source=/dev/null
+[ -r "$HOME/.localprofile" ] && source "$HOME/.localprofile"
+_profile local
+
+# A *login* bash reads this file but never ~/.bashrc, so login and non-login
+# interactive bash would otherwise diverge. Source it here to converge them.
+# Skipped when ~/.bashrc is what sourced us, and for zsh, which has no such gap
+# (a login interactive zsh reads both ~/.zprofile and ~/.zshrc).
+if [ -n "${BASH_VERSION:-}" ] && [ -z "${__dotfiles_bashrc:-}" ] && [ -r "$HOME/.bashrc" ]; then
+ # shellcheck source=/dev/null
+ . "$HOME/.bashrc"
+fi
+_profile bashrc
+
+_profile exit
+
+# ~/bin is prepended to PATH in config/env.
+
+# vim: foldmethod=marker filetype=sh tw=100