├── .brew.leaves ├── .config └── fish │ ├── aliases.fish │ ├── config.fish │ ├── env.fish │ └── functions │ ├── __bass.py │ ├── abspath.fish │ ├── append-copy.fish │ ├── append-to-path.fish │ ├── bass.fish │ ├── prepend-paste.fish │ ├── prepend-to-path.fish │ ├── prepend-vim.fish │ └── search-for-pboard.fish ├── .gitconfig ├── .gitignore ├── .iterm2_shell_integration.fish ├── .psqlrc ├── .tigrc ├── Raycast User Scripts ├── README.md ├── default-browser-chrome.applescript ├── default-browser-chromium.applescript ├── default-browser-firefox.applescript └── default-browser-safari.applescript └── bin ├── api-diff ├── autodate ├── binary ├── brew-all-the-things ├── comma-separate ├── deps ├── drop-until ├── exclude-from-backups-re.txt ├── find-dates ├── find-extensions ├── fix-repo-for-vim ├── flow-limit ├── git-new ├── git-overview ├── glui ├── imgcat ├── imgls ├── ips ├── kill-by-port ├── lstrip ├── make-mp3s-smaller-for-yfke ├── nonempty ├── npm-ls-uniq ├── oh-shut-up-yjs ├── osx-settings.sh ├── patch-annoying-node-libs ├── pipsi-all-the-things ├── pipsi-reinstall ├── quote ├── remove-dist-tags ├── rsort-clipboard ├── rstrip ├── set-bg-color ├── shiftl ├── shiftr ├── shuffle ├── smart-pattern ├── sort-clipboard ├── strip-indents ├── test-all.sh ├── touchx ├── treediff ├── tsc-limit ├── uniq-clipboard ├── unquote └── unsmart-quotes /.brew.leaves: -------------------------------------------------------------------------------- 1 | awscli 2 | bat 3 | colordiff 4 | comby 5 | coreutils 6 | direnv 7 | elm 8 | exiftool 9 | fd 10 | fdupes 11 | ffind 12 | ffmpeg 13 | fish 14 | fzf 15 | gh 16 | git 17 | graphviz 18 | guetzli 19 | heroku/brew/heroku 20 | httpie 21 | hub 22 | imagemagick 23 | jq 24 | moreutils 25 | neovim 26 | nginx 27 | nmap 28 | node@16 29 | noti 30 | nvie/tap/sr 31 | openssl@3 32 | optipng 33 | php 34 | pipenv 35 | postgresql 36 | protobuf 37 | pyenv 38 | rbenv 39 | reattach-to-user-namespace 40 | redis 41 | ripgrep 42 | ssh-copy-id 43 | tig 44 | tree 45 | vim 46 | watchman 47 | wget 48 | yarn 49 | -------------------------------------------------------------------------------- /.config/fish/aliases.fish: -------------------------------------------------------------------------------- 1 | # Quick edits 2 | alias ea 'nvim ~/.config/fish/aliases.fish' 3 | alias ef 'nvim ~/.config/fish/config.fish' 4 | alias eg 'nvim ~/.gitconfig' 5 | alias ev 'nvim ~/.config/nvim/init.vim' 6 | alias evv 'vim ~/.vimrc' 7 | alias es 'nvim ~/bin/autosort' 8 | 9 | alias zz 'open -a Zed .' 10 | 11 | alias vim-norc 'vim -u NORC' 12 | alias vim-none 'vim -u NONE' 13 | alias nvim-norc 'nvim -u NORC' 14 | alias nvim-none 'nvim -u NONE' 15 | 16 | function pdftext 17 | pdftotext -layout $argv[1] - 18 | end 19 | 20 | function serve 21 | npx http-server --port 8000 $argv 22 | end 23 | 24 | function timestamp 25 | python -c 'import time; print(int(time.time()))' 26 | end 27 | 28 | set LS_COLORS dxfxcxdxbxegedabagacad 29 | 30 | alias df 'df -m' 31 | alias j jobs 32 | alias l ls 33 | # alias ll 'ls -la' 34 | alias ls 'ls -FG' 35 | alias su 'su -m' 36 | 37 | function lsd -d 'List only directories (in the current dir)' 38 | ls -d */ | sed -Ee 's,/+$,,' 39 | end 40 | 41 | # Colorized cat (will guess file type based on contents) 42 | alias ccat 'pygmentize -g' 43 | 44 | alias g git 45 | alias c clear 46 | alias vv 'command vim' 47 | alias v nvim 48 | alias vim nvim 49 | alias x 'tig HEAD' 50 | alias xx 'tig --exclude=production --exclude="*/production" --exclude=canary --exclude="*/canary" --exclude="*/dependabot/*" --branches' 51 | alias xxa 'tig --exclude=production --exclude="*/production" --exclude=canary --exclude="*/canary" --exclude="*/dependabot/*" --all' 52 | alias xxaa 'tig --all' 53 | alias notes 'rg --hidden "TODO|HACK|FIXME|OPTIMIZE"' 54 | 55 | # Common typos I make 56 | alias gaa 'git aa' 57 | alias gst 'git st' 58 | alias gpr 'git pr' 59 | 60 | alias m make 61 | alias mm 'make run' 62 | 63 | alias xxx 'sr -s "\b(XXX|YYY)(_vincent)?\b"' 64 | alias xxxx 'sr -s "\b(XXX)(_vincent)?\b"' 65 | alias vx 'rg --hidden -l --null "\b(XXX|YYY)(_vincent)?\b" -- 2>/dev/null | xargs -0 -o nvim -c "/\v<(XXX|YYY)(_vincent)?>"' 66 | alias vxx 'rg --hidden -l "\b(XXX(_vincent)?)\b" -- 2>/dev/null | grep -vFEe .git/ | xargs -o nvim -c "/\v<(XXX(_vincent)?)>"' 67 | 68 | alias reset-mailbox 'rm -v ~/Library/Caches/com.dropbox.mbd.external-beta/mailbox.db' 69 | 70 | function brew-outdated-leaves -d "List outdated packages, but only _leaf_ packages" 71 | combine (brew outdated | cut -d'(' -f1 | cut -d'@' -f1 | psub) and (brew leaves | psub) | xargs brew outdated 72 | end 73 | 74 | function da -d "Allow or disallow .envrc after printing it." 75 | echo ------------------------------------------------ 76 | cat .envrc 77 | echo ------------------------------------------------ 78 | echo "To allow, hit Return." 79 | read answer 80 | direnv allow 81 | end 82 | 83 | function def -d "Quickly jump to place where a function, method, or variable is defined" 84 | va "^\s*(def\s+$argv|$argv\s*[=])" 85 | end 86 | 87 | function vimff 88 | nvim (ffind -tf $argv) 89 | end 90 | 91 | function f 92 | git ls-tree -r --name-only HEAD 93 | end 94 | 95 | alias drop-dependabot-branches "rm -rvf (git rev-parse --git-dir)/refs/remotes/origin/dependabot" 96 | 97 | function vf 98 | edit ( f | fzf ) 99 | end 100 | 101 | function val 102 | set pattern $argv[1] 103 | if test (count $argv) -gt 1 104 | set argv $argv[2..-1] 105 | else 106 | set argv 107 | end 108 | 109 | function to_safe 110 | sed -E -e 's/[\\][=]/__EQ__/g' -e 's/[\\][<]/__LT__/g' -e 's/[\\][>]/__GT__/g' 111 | end 112 | 113 | function to_unsafe_rg 114 | sed -E -e 's/__LT__//g' -e 's/__EQ__/=/g' 115 | end 116 | 117 | function to_unsafe_vim 118 | sed -E -e 's/__LT__/[<]/g' -e 's/__GT__/[>]/g' -e 's/__EQ__/[=]/g' 119 | end 120 | 121 | set rg_pattern (echo $pattern | to_safe | sed -E -e 's/[<>]/\\\\b/g' | to_unsafe_rg) 122 | set vim_pattern (echo $pattern | to_safe | sed -E -e 's,([/=]),\\\\\1,g' -e 's,.*,/\\\\v&,' | to_unsafe_vim) 123 | rg --hidden -l --smart-case $rg_pattern -- $argv 2>/dev/null 124 | end 125 | 126 | function va 127 | set pattern $argv[1] 128 | if test (count $argv) -gt 1 129 | set argv $argv[2..-1] 130 | else 131 | set argv 132 | end 133 | 134 | function to_safe 135 | sed -E -e 's/[\\][=]/__EQ__/g' -e 's/[\\][<]/__LT__/g' -e 's/[\\][>]/__GT__/g' 136 | end 137 | 138 | function to_unsafe_rg 139 | sed -E -e 's/__LT__//g' -e 's/__EQ__/=/g' 140 | end 141 | 142 | function to_unsafe_vim 143 | sed -E -e 's/__LT__/[<]/g' -e 's/__GT__/[>]/g' -e 's/__EQ__/[=]/g' -e 's/@/[@]/g' 144 | end 145 | 146 | set rg_pattern (echo $pattern | to_safe | sed -E -e 's/[<>]/\\\\b/g' | to_unsafe_rg) 147 | set vim_pattern (echo $pattern | to_safe | sed -E -e 's,([/=]),\\\\\1,g' -e 's,.*,/\\\\v&,' | to_unsafe_vim) 148 | rg --hidden -l --smart-case --null $rg_pattern -- $argv 2>/dev/null | xargs -0 -o nvim -c $vim_pattern 149 | end 150 | 151 | # "va", but case-sensitive (it's a copy of the above, but without the 152 | # `--smart-case` argument in the final call) 153 | function vacs 154 | set pattern $argv[1] 155 | if test (count $argv) -gt 1 156 | set argv $argv[2..-1] 157 | else 158 | set argv 159 | end 160 | 161 | function to_safe 162 | sed -E -e 's/[\\][=]/__EQ__/g' -e 's/[\\][<]/__LT__/g' -e 's/[\\][>]/__GT__/g' 163 | end 164 | 165 | function to_unsafe_rg 166 | sed -E -e 's/__LT__//g' -e 's/__EQ__/=/g' 167 | end 168 | 169 | function to_unsafe_vim 170 | sed -E -e 's/__LT__/[<]/g' -e 's/__GT__/[>]/g' -e 's/__EQ__/[=]/g' 171 | end 172 | 173 | set rg_pattern (echo $pattern | to_safe | sed -E -e 's/[<>]/\\\\b/g' | to_unsafe_rg) 174 | set vim_pattern (echo $pattern | to_safe | sed -E -e 's,([/=]),\\\\\1,g' -e 's,.*,/\\\\v&,' | to_unsafe_vim) 175 | rg --hidden -l --null $rg_pattern -- $argv 2>/dev/null | xargs -0 -o nvim -c $vim_pattern 176 | end 177 | 178 | function vc 179 | if git modified -q $argv 180 | nvim (git modified $argv | sed -Ee 's/^"(.*)"$/\1/') 181 | else 182 | echo '(nothing changed)' 183 | end 184 | end 185 | 186 | function vca 187 | if git modified -qi 188 | nvim (git modified -i | sed -Ee 's/^"(.*)"$/\1/') 189 | else 190 | echo '(nothing changed)' 191 | end 192 | end 193 | 194 | function vci 195 | if git modified -qi 196 | nvim (begin; git modified -i; git modified; end | sort | uniq -u | sed -Ee 's/^"(.*)"$/\1/') 197 | else 198 | echo '(nothing changed)' 199 | end 200 | end 201 | 202 | # Open all files from the last commit that changes any files in the current directory 203 | alias vch 'vc (git log -1 --pretty=%H .)' 204 | 205 | # Run test and open the first failing test in Vim, jumping straight to the assertion that failed 206 | alias vt 'vitest --bail 1 --run --no-color 2>&1 | grep -oEe \'❯ test.*:[[:digit:]]+\' | head -n1 | cut -d" " -f2 | cut -d: -f1,2 | rev | sed -Ee "s/:/\+ /" | rev | xargs -o nvim' 207 | 208 | # Open all files from the nth-last commit 209 | alias vch0 'vc HEAD' 210 | alias vch1 'vc HEAD~1' 211 | alias vch2 'vc HEAD~2' 212 | alias vch3 'vc HEAD~3' 213 | alias vch4 'vc HEAD~4' 214 | 215 | function vu 216 | if git modified -u $argv 217 | nvim (git modified -u $argv | sed -Ee 's/^"(.*)"$/\1/') 218 | else 219 | echo 'no files with conflicts' 220 | end 221 | end 222 | 223 | function vw 224 | nvim (which "$argv") 225 | end 226 | 227 | function vconflicts -d 'Opens all files with merge conflict markers in Vim' 228 | va '^(\<{7}|\>{7}|\={7})([ ].*)?$' 229 | end 230 | 231 | function fll -d 'Lists all files with Flow issues' 232 | flow --show-all-errors --json | jq -r '.errors[].message[].path' | sort -u | map realpath --relative-to=. 233 | end 234 | 235 | # 236 | # The following helper can be invoked like so: 237 | # 238 | # $ edit ( produce | grep -Ee foo ) 239 | # ^^^^^^^^^^^^^^^^^^^^^^^^^^ 240 | # Any Unix command producing a list of file 241 | # paths on stdout. 242 | # 243 | # This is to replace usage of the following structure: 244 | # 245 | # $ produce | grep -Ee foo | xargs -o $EDITOR 246 | # 247 | # Which unfortunately suffers from an annoying bug in Fish related to how 248 | # Ctrl+Z and `fg` then work. See also the bug report: 249 | # https://github.com/fish-shell/fish-shell/issues/8263 250 | # 251 | function edit -d 'Opens $EDITOR with the files given, but is a no-op if the list is empty' 252 | if test ( count $argv ) -gt 0 253 | $EDITOR $argv 254 | end 255 | end 256 | 257 | function veslint -d 'Opens all files in Vim with ESLint issues' 258 | edit ( eslint $argv | grep -Ee '^/' ) 259 | end 260 | 261 | function vjest -d 'Opens the first failing test case in Vim and jumps to the failing line' 262 | edit ( jest $argv --bail --silent 2>&1 | grep -oEe '^\s+at .*\(([^:]+):(\d+)' | grep -vEe '(node_modules|dist|lib)/' | cut -d'(' -f2 | head -n1 | sed -Ee "s/:/\n+/" ) 263 | end 264 | 265 | function tsf -d 'Lists all files with TypeScript issues' 266 | tsc $argv | grep -vEe '^\s' | cut -d: -f1 | rev | cut -d'(' -f2- | rev | sort -u 267 | end 268 | 269 | function vts -d 'Opens all files with TypeScript issues in Vim' 270 | if test "$argv[1]" = --incremental 271 | echo "No longer needed to specify --incremental here 😇" >&2 272 | else 273 | edit ( tsf --incremental $argv ) 274 | end 275 | end 276 | 277 | # alias git hub 278 | alias gti git 279 | alias a 'git amend --allow-empty --no-verify' 280 | alias gs 'git status -s' 281 | alias gb 'git recent-branches 2.days.ago' 282 | alias ggco 'git iswitch' 283 | alias ggbd 'git branch -D (git local-branches | grep -vxEe "$(git current-branch)" | fzf)' 284 | alias fl 'clear; and flow-limit' 285 | alias fflow 'flow stop; and flow' 286 | alias tll "tsc | grep -Ee 'TS\d+' | cut -d'(' -f1 | sort -u" 287 | 288 | function git-search 289 | git log -S"$argv" --pretty=format:%H | map git show 290 | end 291 | 292 | function cleanpycs 293 | find . -name '.git' -prune -o -name __pycache__ -delete 294 | find . -name '.git' -prune -o -name '*.py[co]' -delete 295 | end 296 | 297 | function cleanorigs 298 | find . '(' -name '*.orig' -o -name '*.BACKUP.*' -o -name '*.BASE.*' -o -name '*.LOCAL.*' -o -name '*.REMOTE.*' ')' -print0 | xargs -0 rm -f 299 | end 300 | 301 | function cleandsstores 302 | find . -name '.DS_Store' -exec rm -f '{}' ';' 303 | end 304 | 305 | alias json prettify-json 306 | alias map 'xargs -n1' 307 | alias collapse "sed -e 's/ */ /g'" 308 | alias cuts 'cut -d\ ' 309 | 310 | function p -d "Start the best Python shell that is available" 311 | set -l cmd 312 | 313 | if test -f manage.py 314 | if pip freeze 2>/dev/null | grep -iq django-extensions 315 | set cmd (which python) manage.py shell_plus 316 | else 317 | if pip freeze 2>/dev/null | grep -iq flask-script 318 | # do nothing, use manage.py, fall through 319 | set -e cmd 320 | else 321 | set cmd (which python) manage.py shell 322 | end 323 | end 324 | end 325 | 326 | if test -z $cmd 327 | set -l interpreters (which bpython 2>/dev/null; which ipython 2>/dev/null; which python 2>/dev/null) 328 | 329 | if test -z "$interpreters" 330 | set_color red 331 | echo "No python interpreters found on the PATH." 332 | set_color normal 333 | return 127 334 | end 335 | 336 | # Try to find the first interpreter within the current virtualenv 337 | # Rationale: it's more important to start a Python interpreter in the 338 | # current virtualenv than it is to start an _IPython_ interpreter (for 339 | # example, when the current virtualenv has no ipython installed, but such 340 | # would be installed system-wide). 341 | for interp in $interpreters 342 | #echo '-' $interp 343 | #echo '-' (dirname (dirname $interp)) 344 | if test (dirname (dirname $interp)) = "$VIRTUAL_ENV" 345 | set cmd $interp 346 | break 347 | end 348 | end 349 | 350 | # If they all fall outside the virtualenv, pick the first match 351 | # (preferring ipython over python) 352 | if test -z "$cmd" 353 | set cmd $interpreters[1] 354 | end 355 | end 356 | 357 | # Run the command 358 | printf "Using " 359 | set_color green 360 | echo $cmd 361 | set_color normal 362 | eval $cmd $argv 363 | end 364 | 365 | # alias pm 'python manage.py' 366 | # alias pmm 'python manage.py migrate' 367 | # alias pmmm 'python manage.py makemigrations' 368 | # alias pms 'python manage.py shell_plus' 369 | # alias pmr 'python manage.py runserver_plus 0.0.0.0:8000' 370 | 371 | function pipr -d "Find & install all requirements for this project" 372 | pushd (git root) 373 | begin 374 | if test -f requirements.txt 375 | pip install -r requirements.txt 376 | end 377 | if test -f dev-requirements.txt 378 | pip install -r dev-requirements.txt 379 | end 380 | if test -f .pipignore 381 | pip install -r .pipignore 382 | end 383 | end 384 | popd 385 | end 386 | 387 | # Directories {{{ 388 | 389 | function cdff --description "cd's into the current front-most open Finder window's directory" 390 | cd (ff $argv) 391 | end 392 | 393 | function ff 394 | echo ' 395 | tell application "Finder" 396 | if (1 <= (count Finder windows)) then 397 | get POSIX path of (target of window 1 as alias) 398 | else 399 | get POSIX path of (desktop as alias) 400 | end if 401 | end tell 402 | ' | osascript - 403 | end 404 | 405 | alias cd.. 'cd ..' 406 | alias cd... 'cd ../..' 407 | alias .. 'cd ..' 408 | alias ... 'cd ../..' 409 | #alias .... 'cd ../../..' 410 | #alias ..... 'cd ../../../..' 411 | 412 | function take 413 | set -l dir $argv[1] 414 | mkdir -p $dir; and cd $dir 415 | end 416 | alias cx 'chmod +x' 417 | alias c-x 'chmod -x' 418 | 419 | # }}} 420 | 421 | function colorize-pboard 422 | if test (count $argv) -gt 0 423 | set lang $argv[1] 424 | else 425 | set lang python 426 | end 427 | pbpaste | strip-indents | color-syntax | pbcopy 428 | end 429 | 430 | function color-syntax 431 | if test (count $argv) -gt 0 432 | set lang $argv[1] 433 | else 434 | set lang python 435 | end 436 | pygmentize -f rtf -l $lang 437 | end 438 | 439 | function st -d "Set a terminal badge for the current tab, based on the current project/directory" 440 | npx iterm2-tab-set (string replace -r '^liveblocks-' '' (basename (git root))) 441 | end 442 | 443 | alias gp='cd ~/Projects/liveblocks/liveblocks' 444 | alias ga='cd ~/Projects/liveblocks/liveblocks.io' 445 | alias cdio='cd ~/Projects/liveblocks/liveblocks.io && set-bg-color 0 0 0' 446 | alias cdcc='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-core && set-bg-color' 447 | alias cdc='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-client && set-bg-color' 448 | alias cdr='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-react && set-bg-color 13 21 52' 449 | alias cde='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-emails && set-bg-color 13 21 52' 450 | alias cdru='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-react-ui && set-bg-color 10 21 52' 451 | alias cdrc=cdru 452 | alias cdrr='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-redux && set-bg-color 38 8 45' 453 | alias cdrl='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-react-lexical && set-bg-color 38 8 45' 454 | alias cdrb='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-react-blocknote && set-bg-color 38 8 45' 455 | alias cdrt='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-react-tiptap && set-bg-color 38 8 45' 456 | alias cdnl='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-node-lexical && set-bg-color 38 8 45' 457 | alias cdy='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-yjs' 458 | alias cdz='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-zustand && set-bg-color 35 8 35' 459 | alias cdzz='cd ~/Projects/liveblocks/liveblocks-backend/shared/zenrouter && set-bg-color 35 8 35' 460 | alias cdn='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-node && set-bg-color 9 34 9' 461 | alias cdd='cd ~/Projects/liveblocks/liveblocks/packages/liveblocks-devtools && set-bg-color 47 26 6' 462 | alias cda='cd ~/Projects/liveblocks/admin' 463 | alias cdf='cd ~/Projects/liveblocks/liveblocks-backend/apps/cloudflare && set-bg-color 8 0 38' 464 | alias cdbb='cd ~/Projects/liveblocks/liveblocks-backend && set-bg-color 27 22 0' 465 | alias cdbj='cd ~/Projects/liveblocks/liveblocks-backend/apps/aws-jobs && set-bg-color 27 22 0' 466 | alias cdbr='cd ~/Projects/liveblocks/liveblocks-backend/apps/lambda-rest-api && set-bg-color 27 22 0' 467 | alias cdbm='cd ~/Projects/liveblocks/liveblocks-backend/tools/mongodb-migration && set-bg-color 27 22 0' 468 | alias cdb='cd ~/Projects/liveblocks/liveblocks-backend/apps/bun-server && set-bg-color 38 28 7' 469 | alias cds='cd ~/Projects/liveblocks/liveblocks-backend/shared/liveblocks-server && set-bg-color 0 29 32' 470 | alias cdsc='cd ~/Projects/liveblocks/liveblocks/schema-lang/liveblocks-schema' 471 | alias cdi='cd ~/Projects/liveblocks/liveblocks/schema-lang/infer-schema' 472 | alias cdq='cd ~/Projects/liveblocks/liveblocks-backend/shared/liveblocks-query-parser' 473 | alias cdR=cdbr 474 | alias cddocs='cd ~/Projects/liveblocks/liveblocks/docs' 475 | alias liveblocks-dependencies="jq -r '((.dependencies,.peerDependencies,.devDependencies) // []) | keys[]' package.json | sort -u | grep --color=never -Ee @liveblocks/" 476 | 477 | function wtf -d "Print which and --version output for the given command" 478 | for arg in $argv 479 | echo $arg: (which $arg) 480 | echo $arg: (sh -c "$arg --version") 481 | end 482 | end 483 | 484 | function turbo_or_npm 485 | if which -s turbo 486 | turbo $argv 487 | else 488 | npm run $argv 489 | end 490 | end 491 | 492 | function turboshhhh_or_npm 493 | if which -s turbo 494 | turbo --log-prefix none $argv 495 | else 496 | npm run $argv 497 | end 498 | end 499 | 500 | alias tb 'turbo_or_npm build' 501 | alias tbf 'turbo_or_npm build:firefox' 502 | alias tt 'turbo_or_npm test' 503 | alias td 'turbo_or_npm dev' 504 | alias ttt 'turbo_or_npm test:types' 505 | alias ttd 'turbo_or_npm test:deps' 506 | alias ttu 'turbo_or_npm test:ui' 507 | alias tte 'turbo_or_npm test:e2e' 508 | alias tl 'turboshhhh_or_npm lint' 509 | alias tlp 'turbo_or_npm lint:package' 510 | alias tf 'turbo_or_npm format' 511 | alias tp 'turbo_or_npm package' 512 | alias ncu 'npx npm-check-updates --interactive' 513 | alias ncuw 'npx npm-check-updates --interactive --root --workspaces' 514 | 515 | # Quick bisecting 516 | alias gbr 'git bisect reset' 517 | alias gbs 'cd (git root) && git bisect start (git current-branch) (git merge-base (git current-branch) main)' 518 | alias good 'git bisect good' 519 | alias bad 'git bisect bad' 520 | -------------------------------------------------------------------------------- /.config/fish/config.fish: -------------------------------------------------------------------------------- 1 | . ~/.config/fish/aliases.fish 2 | 3 | # Fish prompt/color config {{{ 4 | 5 | #set fish_color_hostname 'a67523' 6 | set -gx fish_greeting '' 7 | 8 | function fish_prompt 9 | set last_status $status 10 | 11 | echo ' ' 12 | 13 | set user (whoami) 14 | 15 | set_color magenta 16 | printf '%s' $user 17 | set_color normal 18 | 19 | # printf ' at ' 20 | # set_color yellow 21 | # printf '%s' (hostname -s) 22 | # set_color normal 23 | 24 | printf ' in ' 25 | set_color $fish_color_cwd 26 | printf '%s' (echo $PWD | sed -e "s|^$HOME|~|" -e 's|^/private||' -e 's|~/Projects/liveblocks/||') 27 | set_color normal 28 | 29 | git_prompt 30 | 31 | set_color normal 32 | printf ' (%s)' (date +%H:%M) 33 | # printf ' @ node ' 34 | # set_color blue 35 | # printf '%s' (node --version | cut -d. -f1 | cut -dv -f2) 36 | # set_color normal 37 | echo 38 | 39 | #if test $last_status -eq 0 40 | # set_color white -o 41 | # printf '><((°> ' 42 | #else 43 | # set_color red -o 44 | # printf '><((ˣ> ' 45 | # set_color white -o 46 | # printf '[%d] ' $last_status 47 | #end 48 | 49 | if test $last_status -ne 0 50 | set_color white -o 51 | printf '[%d] ' $last_status 52 | set_color normal 53 | end 54 | printf '$ ' 55 | 56 | set_color normal 57 | end 58 | 59 | function demo-mode 60 | function fish_prompt 61 | set last_status $status 62 | printf '$ ' 63 | end 64 | end 65 | 66 | function git_current_branch -d 'Prints a human-readable representation of the current branch' 67 | set -l ref (git symbolic-ref HEAD 2>/dev/null; or git rev-parse --short HEAD 2>/dev/null) 68 | if test -n "$ref" 69 | echo $ref | sed -e s,refs/heads/,, 70 | return 0 71 | end 72 | end 73 | 74 | function git_prompt 75 | if git rev-parse --show-toplevel >/dev/null 2>&1 76 | set_color normal 77 | printf ' on ' 78 | set_color yellow 79 | printf '%s' (git_current_branch) 80 | set_color green 81 | #git_prompt_status 82 | set_color normal 83 | end 84 | end 85 | 86 | #function orig_fish_prompt 87 | # set_color white 88 | # echo -n (whoami) 89 | # set_color normal 90 | # echo -n @ 91 | # set_color $fish_color_hostname 92 | # echo -n (hostname -s) 93 | # #set_color normal 94 | # echo -n ' % ' 95 | #end 96 | 97 | #function fish_right_prompt 98 | # set_color $fish_color_cwd 99 | # echo -n (prompt_pwd) 100 | #end 101 | 102 | # }}} 103 | 104 | # Globals 105 | set -gx EDITOR nvim 106 | #set -gx PIP_DOWNLOAD_CACHE ... 107 | 108 | # Auto push/pop of directories {{{ 109 | 110 | # 111 | # Unfortunately, fish's pushd/popd behaviour seems a little buggy, and since 112 | # pushd uses "cd" under the covers, I'm unable to alias cd to be pushd under 113 | # the hood, so I've reimplemented this myself, using the $dirprev env variable. 114 | # 115 | function po --description 'Pop back to previous directory on the dir stack' 116 | set -l last $dirprev[-1] 117 | 118 | # "Pop" the last one off 119 | set -e dirprev[-1] 120 | 121 | # Switch to the last dir 122 | cd $last 123 | 124 | # Then discard this switch (which gets recorded in the dir history) 125 | set -e dirprev[-1] 126 | end 127 | 128 | # }}} 129 | 130 | # Key bindings {{{ 131 | function fish_user_key_bindings 132 | bind \ec append-copy 133 | bind \ep prepend-paste 134 | bind \ev prepend-vim 135 | bind \ea search-for-pboard 136 | bind \ey 'commandline -b | pbcopy' 137 | bind \e'>' 'commandline -a -- "| shiftr"' 138 | bind \e'<' 'commandline -a -- "| shiftl"' 139 | end 140 | # }}} 141 | 142 | # Interactive/login shells {{{ 143 | if status is-login 144 | . ~/.config/fish/env.fish 145 | end 146 | 147 | if status is-interactive 148 | set CDPATH . \ 149 | ~/Projects/liveblocks/liveblocks/packages \ 150 | ~/Projects/liveblocks/liveblocks/tools \ 151 | ~/Projects/liveblocks/liveblocks-backend/apps \ 152 | ~/Projects/liveblocks/liveblocks-backend/shared \ 153 | ~/Projects/liveblocks/liveblocks-backend/tools \ 154 | ~/Projects/liveblocks/liveblocks/schema-lang \ 155 | ~/Projects/tsdiff/apps \ 156 | ~/Projects/tsdiff/packages \ 157 | ~/Projects/liveblocks/liveblocks \ 158 | ~/Projects/liveblocks/liveblocks-backend \ 159 | ~/Projects/liveblocks \ 160 | ~/Projects 161 | end 162 | # }}} 163 | 164 | # Direnv {{{ 165 | direnv hook fish | source 166 | # }}} 167 | 168 | # iTerm shell integration {{{ 169 | test -e ~/.iterm2_shell_integration.fish; and source ~/.iterm2_shell_integration.fish 170 | # }}} 171 | 172 | set -gx __fish_initialized 1 173 | 174 | # Nvm {{{ 175 | 176 | load_nvm >/dev/stderr 177 | 178 | # }}} 179 | 180 | # bun 181 | set --export BUN_INSTALL "$HOME/.bun" 182 | set --export PATH $BUN_INSTALL/bin $PATH 183 | 184 | # pnpm 185 | set -gx PNPM_HOME "$HOME/Library/pnpm" 186 | if not string match -q -- $PNPM_HOME $PATH 187 | set -gx PATH "$PNPM_HOME" $PATH 188 | end 189 | -------------------------------------------------------------------------------- /.config/fish/env.fish: -------------------------------------------------------------------------------- 1 | # This file is sourced on login shells only (responsible for setting up the 2 | # initial environment) 3 | 4 | set -gx PATH /bin 5 | 6 | append-to-path /sbin 7 | append-to-path /usr/bin 8 | append-to-path /usr/sbin 9 | append-to-path ~/bin 10 | append-to-path ~/.local/bin 11 | append-to-path ~/.cargo/bin 12 | append-to-path ~/.bun/bin 13 | append-to-path ~/Projects/syncfrom 14 | append-to-path ~/Projects/git-toolbelt 15 | append-to-path ~/Projects/linenos/bin 16 | append-to-path "/Applications/Visual Studio Code.app/Contents/Resources/app/bin" 17 | append-to-path "/Applications/Docker.app/Contents/Resources/bin" 18 | append-to-path ~/Projects/liveblocks/liveblocks/scripts 19 | 20 | prepend-to-path /opt/homebrew/opt/node@18/bin 21 | prepend-to-path /opt/homebrew/sbin 22 | prepend-to-path /opt/homebrew/bin 23 | 24 | # Old MySQL version (5.7) 25 | # append-to-path /opt/homebrew/Cellar/mysql@5.7/5.7.37/bin 26 | 27 | # Old MongoDB version (3.0) for Sleutelzorg/Heroku 28 | # append-to-path /usr/local/opt/mongodb@3.0/bin 29 | 30 | # Python: source pyenv config for fish 31 | set -gx PIP_DOWNLOAD_CACHE ~/Library/Caches/pip-downloads 32 | set -Ux PYENV_ROOT $HOME/.pyenv 33 | append-to-path $PYENV_ROOT/bin 34 | status is-login; and pyenv init --path | source 35 | pyenv init - | source 36 | 37 | # Set locale 38 | set -gx LC_ALL en_US.UTF-8 39 | set -gx LANG en_US.UTF-8 40 | 41 | # Configure fzf to use fd by default (fd respects .gitignore defaults) 42 | set -gx FZF_DEFAULT_COMMAND 'fd --type f' 43 | -------------------------------------------------------------------------------- /.config/fish/functions/__bass.py: -------------------------------------------------------------------------------- 1 | """ 2 | To be used with a companion fish function like this: 3 | 4 | function refish 5 | set -l _x (python /tmp/bass.py source ~/.nvm/nvim.sh ';' nvm use iojs); source $_x; and rm -f $_x 6 | end 7 | 8 | """ 9 | 10 | from __future__ import print_function 11 | 12 | import json 13 | import os 14 | import signal 15 | import subprocess 16 | import sys 17 | import traceback 18 | 19 | 20 | BASH = 'bash' 21 | 22 | FISH_READONLY = [ 23 | 'PWD', 'SHLVL', 'history', 'pipestatus', 'status', 'version', 24 | 'FISH_VERSION', 'fish_pid', 'hostname', '_', 'fish_private_mode' 25 | ] 26 | 27 | IGNORED = [ 28 | 'PS1', 'XPC_SERVICE_NAME' 29 | ] 30 | 31 | def ignored(name): 32 | if name == 'PWD': # this is read only, but has special handling 33 | return False 34 | # ignore other read only variables 35 | if name in FISH_READONLY: 36 | return True 37 | if name in IGNORED or name.startswith("BASH_FUNC"): 38 | return True 39 | return False 40 | 41 | def escape(string): 42 | # use json.dumps to reliably escape quotes and backslashes 43 | return json.dumps(string).replace(r'$', r'\$') 44 | 45 | def escape_identifier(word): 46 | return escape(word.replace('?', '\\?')) 47 | 48 | def comment(string): 49 | return '\n'.join(['# ' + line for line in string.split('\n')]) 50 | 51 | def gen_script(): 52 | # Use the following instead of /usr/bin/env to read environment so we can 53 | # deal with multi-line environment variables (and other odd cases). 54 | env_reader = "%s -c 'import os,json; print(json.dumps({k:v for k,v in os.environ.items()}))'" % (sys.executable) 55 | args = [BASH, '-c', env_reader] 56 | output = subprocess.check_output(args, universal_newlines=True) 57 | old_env = output.strip() 58 | 59 | pipe_r, pipe_w = os.pipe() 60 | if sys.version_info >= (3, 4): 61 | os.set_inheritable(pipe_w, True) 62 | command = 'eval $1 && ({}; alias) >&{}'.format( 63 | env_reader, 64 | pipe_w 65 | ) 66 | args = [BASH, '-c', command, 'bass', ' '.join(sys.argv[1:])] 67 | p = subprocess.Popen(args, universal_newlines=True, close_fds=False) 68 | os.close(pipe_w) 69 | with os.fdopen(pipe_r) as f: 70 | new_env = f.readline() 71 | alias_str = f.read() 72 | if p.wait() != 0: 73 | raise subprocess.CalledProcessError( 74 | returncode=p.returncode, 75 | cmd=' '.join(sys.argv[1:]), 76 | output=new_env + alias_str 77 | ) 78 | new_env = new_env.strip() 79 | 80 | old_env = json.loads(old_env) 81 | new_env = json.loads(new_env) 82 | 83 | script_lines = [] 84 | 85 | for k, v in new_env.items(): 86 | if ignored(k): 87 | continue 88 | v1 = old_env.get(k) 89 | if not v1: 90 | script_lines.append(comment('adding %s=%s' % (k, v))) 91 | elif v1 != v: 92 | script_lines.append(comment('updating %s=%s -> %s' % (k, v1, v))) 93 | # process special variables 94 | if k == 'PWD': 95 | script_lines.append('cd %s' % escape(v)) 96 | continue 97 | else: 98 | continue 99 | if k == 'PATH': 100 | value = ' '.join([escape(directory) 101 | for directory in v.split(':')]) 102 | else: 103 | value = escape(v) 104 | script_lines.append('set -g -x %s %s' % (k, value)) 105 | 106 | for var in set(old_env.keys()) - set(new_env.keys()): 107 | script_lines.append(comment('removing %s' % var)) 108 | script_lines.append('set -e %s' % var) 109 | 110 | script = '\n'.join(script_lines) 111 | 112 | alias_lines = [] 113 | for line in alias_str.splitlines(): 114 | _, rest = line.split(None, 1) 115 | k, v = rest.split("=", 1) 116 | alias_lines.append("alias " + escape_identifier(k) + "=" + v) 117 | alias = '\n'.join(alias_lines) 118 | 119 | return script + '\n' + alias 120 | 121 | script_file = os.fdopen(3, 'w') 122 | 123 | if not sys.argv[1:]: 124 | print('__bass_usage', file=script_file, end='') 125 | sys.exit(0) 126 | 127 | try: 128 | script = gen_script() 129 | except subprocess.CalledProcessError as e: 130 | sys.exit(e.returncode) 131 | except Exception: 132 | print('Bass internal error!', file=sys.stderr) 133 | raise # traceback will output to stderr 134 | except KeyboardInterrupt: 135 | signal.signal(signal.SIGINT, signal.SIG_DFL) 136 | os.kill(os.getpid(), signal.SIGINT) 137 | else: 138 | script_file.write(script) 139 | -------------------------------------------------------------------------------- /.config/fish/functions/abspath.fish: -------------------------------------------------------------------------------- 1 | function abspath -d 'Calculates the absolute path for the given path' 2 | set -l cwd '' 3 | set -l curr (pwd) 4 | cd $argv[1]; and set cwd (pwd); and cd $curr 5 | echo $cwd 6 | end 7 | -------------------------------------------------------------------------------- /.config/fish/functions/append-copy.fish: -------------------------------------------------------------------------------- 1 | function append-copy 2 | commandline -a -- ' | pbcopy' 3 | end 4 | -------------------------------------------------------------------------------- /.config/fish/functions/append-to-path.fish: -------------------------------------------------------------------------------- 1 | function append-to-path -d 'Adds the given directory to the end of the PATH' 2 | set -l dir '' 3 | if test (count $argv) -ne 0 4 | set dir $argv[1] 5 | end 6 | 7 | if test -d $dir 8 | set dir (abspath $dir) 9 | if not contains $dir $PATH 10 | set PATH $PATH $dir 11 | end 12 | else 13 | echo "Dir $dir does not exist?" 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /.config/fish/functions/bass.fish: -------------------------------------------------------------------------------- 1 | function bass 2 | set -l bash_args $argv 3 | set -l bass_debug 4 | if test "$bash_args[1]_" = '-d_' 5 | set bass_debug true 6 | set -e bash_args[1] 7 | end 8 | 9 | set -l script_file (mktemp) 10 | if command -v python3 >/dev/null 2>&1 11 | command python3 -sS (dirname (status -f))/__bass.py $bash_args 3>$script_file 12 | else 13 | command python -sS (dirname (status -f))/__bass.py $bash_args 3>$script_file 14 | end 15 | set -l bass_status $status 16 | if test $bass_status -ne 0 17 | return $bass_status 18 | end 19 | 20 | if test -n "$bass_debug" 21 | cat $script_file 22 | end 23 | source $script_file 24 | command rm $script_file 25 | end 26 | 27 | function __bass_usage 28 | echo "Usage: bass [-d] " 29 | end 30 | -------------------------------------------------------------------------------- /.config/fish/functions/prepend-paste.fish: -------------------------------------------------------------------------------- 1 | function prepend-paste 2 | commandline -- 'pbpaste | '(commandline) 3 | end 4 | -------------------------------------------------------------------------------- /.config/fish/functions/prepend-to-path.fish: -------------------------------------------------------------------------------- 1 | function prepend-to-path --description 'Adds the given directory to the front of the PATH' 2 | set -l dir '' 3 | if test (count $argv) -ne 0 4 | set dir $argv[1] 5 | end 6 | 7 | if test -d $dir 8 | set dir (abspath $dir) 9 | 10 | # If this path is already in the PATH array, remove all occurrences 11 | # and add it to the head 12 | for i in (seq (count $PATH) 1) 13 | if test $PATH[$i] = $dir 14 | set -e PATH[$i] 15 | end 16 | end 17 | set PATH $dir $PATH 18 | else 19 | echo "Dir $dir does not exist?" 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /.config/fish/functions/prepend-vim.fish: -------------------------------------------------------------------------------- 1 | function prepend-vim 2 | commandline -- 'nvim '(commandline) 3 | end 4 | -------------------------------------------------------------------------------- /.config/fish/functions/search-for-pboard.fish: -------------------------------------------------------------------------------- 1 | function search-for-pboard 2 | commandline -- 'va \''( 3 | pbpaste \ 4 | | head -n1 \ 5 | | sed -E \ 6 | -e 's/^[[:space:]]*//' \ 7 | -e 's/[[:space:]]*$//' \ 8 | -e "s/[.]/__DOT__/g" \ 9 | -e "s/[]['\"\\`()*{}+^\$?|<>&]/./g" \ 10 | -e "s/__DOT__/\[.\]/g" \ 11 | )'\'' 12 | end 13 | -------------------------------------------------------------------------------- /.gitconfig: -------------------------------------------------------------------------------- 1 | [init] 2 | defaultBranch = main 3 | 4 | [user] 5 | name = Vincent Driessen 6 | email = me@nvie.com 7 | 8 | [core] 9 | excludesfile = ~/.git/ignore-global 10 | quotepath = false 11 | trustctime = false 12 | # Taken from (and adapted) 13 | # https://github.com/paulirish/dotfiles/commit/6743b907ff586c28cd36e08d1e1c634e2968893e#commitcomment-13349456 14 | # pager = sh -c '/opt/homebrew/share/git-core/contrib/diff-highlight/diff-highlight | less -r' - 15 | hooksPath = "$HOME/dir/that/definitely/does/not/exist/to/finally/disable/git/hooks/globally/forever" 16 | 17 | [merge] 18 | tool = splice 19 | conflictstyle = diff3 # or zdiff3 20 | 21 | [mergetool "mvimdiff"] 22 | cmd = "mvim -f -d $MERGED $LOCAL $BASE $REMOTE -c 'wincmd J'" 23 | trustExitCode = true 24 | keepbackup = false 25 | 26 | [mergetool "splice"] 27 | cmd = "mvim -f $BASE $LOCAL $REMOTE $MERGED -c 'SpliceInit'" 28 | trustExitCode = true 29 | keepbackup = false 30 | 31 | [color] 32 | ui = auto 33 | 34 | [color "diff-highlight"] 35 | oldNormal = "red" 36 | oldHighlight = "red 52" 37 | newNormal = "green" 38 | newHighlight = "green 22" 39 | 40 | [alias] 41 | amend = commit --amend --no-verify 42 | fw = !"git fixup-with" 43 | br = branch -a 44 | bd = branch -d 45 | bdd = branch -D 46 | lb = local-branches 47 | ci = commit --no-verify 48 | civ = commit --no-verify -v 49 | co = checkout 50 | sw = switch 51 | cp = cherry-pick 52 | dc = diff --cached 53 | di = diff 54 | incoming = !git fetch -q github develop && git log HEAD..FETCH_HEAD 55 | kick = push 56 | la = !git lg --all 57 | last = !git show | awk \"NR==1 {print \\$2}\" 58 | copylast = !git last | xargs echo -n | pbcopy 59 | lg = log --graph \"--pretty=format:%C(yellow bold)%h%Creset by %C(red)%an%Creset (%ar)%C(cyan bold)%d%Creset%n%s%n%b\" 60 | jsonlog = log --pretty=format:'{%n \"commit\": \"%H\",%n \"abbreviated_commit\": \"%h\",%n \"tree\": \"%T\",%n \"abbreviated_tree\": \"%t\",%n \"parent\": \"%P\",%n \"abbreviated_parent\": \"%p\",%n \"refs\": \"%D\",%n \"encoding\": \"%e\",%n \"subject\": \"%s\",%n \"sanitized_subject_line\": \"%f\",%n \"body\": \"%b\",%n \"commit_notes\": \"%N\",%n \"verification_flag\": \"%G?\",%n \"signer\": \"%GS\",%n \"signer_key\": \"%GK\",%n \"author\": {%n \"name\": \"%aN\",%n \"email\": \"%aE\",%n \"date\": \"%aD\"%n },%n \"commiter\": {%n \"name\": \"%cN\",%n \"email\": \"%cE\",%n \"date\": \"%cD\"%n }%n},' 61 | outgoing = !git fetch -q github develop && git log FETCH_HEAD..HEAD 62 | praise = blame 63 | st = status -s -b 64 | su = submodule update 65 | wtf = what-the-hell-just-happened 66 | wth = what-the-hell-just-happened 67 | x = !"f () { if [ $# -ge 1 ]; then gitx \"$@\"; else gitx HEAD; fi }; f" 68 | aa = add --all 69 | au = add -u 70 | pullff = pull --ff-only 71 | hd = log -1 \"--pretty=format:%C(yellow bold)%h%Creset by %C(red)%an%Creset (%ar)%C(cyan bold)%d%Creset%n%s%n%b\" 72 | expand = rev-list -1 73 | ap = add -p 74 | cc = reset HEAD 75 | rh = reset --hard 76 | rhh = !"echo $(git reset --hard HEAD~1)' (was' $(git rev-parse --short HEAD@{1})')'" 77 | ra = rebase --abort 78 | rc = rebase --continue 79 | ri = rebase --interactive --autosquash --autostash 80 | r2 = rebase --interactive --autosquash --autostash HEAD~2 81 | r3 = rebase --interactive --autosquash --autostash HEAD~3 82 | r4 = rebase --interactive --autosquash --autostash HEAD~4 83 | r5 = rebase --interactive --autosquash --autostash HEAD~5 84 | r6 = rebase --interactive --autosquash --autostash HEAD~6 85 | r7 = rebase --interactive --autosquash --autostash HEAD~7 86 | r8 = rebase --interactive --autosquash --autostash HEAD~8 87 | r9 = rebase --interactive --autosquash --autostash HEAD~9 88 | sep = separator --no-verify 89 | shatter = shatter-by-file 90 | #mt = mergetool 91 | pr = pull --rebase=merges --autostash 92 | cdf = clean -df 93 | 94 | # really, really, really stash 95 | rrrs = stash-everything 96 | rrrsp = stash pop 97 | 98 | # fetch, for fuck's sake 99 | # ff = !"git fetch origin '+refs/heads/*:refs/remotes/origin/*' \"+$(git main-branch):$(git main-branch)\" \"+release-2.0:release-2.0\"" 100 | ff = !"git fetch origin '+refs/heads/*:refs/remotes/origin/*' \"+$(git main-branch):$(git main-branch)\"" 101 | ffb = !"git fetch origin '+refs/heads/*:refs/remotes/origin/*' \"+$(git main-branch):$(git main-branch)\" \"+beta:beta\"" 102 | ffn = !"git fetch origin '+refs/heads/*:refs/remotes/origin/*' \"+$(git main-branch):$(git main-branch)\" \"+next:next\"" 103 | 104 | # Restore some of my favorite Hub subcommands as Git aliases. 105 | # Previously I could simply alias hub => git entirely, but this didn't work 106 | # as they extended the number of subcommands to conflicth with some of my 107 | # favorite daily commands. 108 | browse = !hub browse 109 | ci-status = !hub ci-status 110 | compare = !hub compare 111 | prs = !hub pr 112 | release = !hub release 113 | 114 | pulls = !hub browse -- pulls 115 | blast = !hub browse -- commit/`git last` 116 | wiki = !hub browse -- wiki 117 | browse-commit = !"hub browse -- commit/\"$1\"" 118 | bc = !"git browse-commit $(git sha ${1:-@})" 119 | # snap = !"git aa && git ci -m CHECKPOINT" 120 | sw = switch 121 | 122 | # Interactive switch 123 | iswitch = !"git recent-branches | grep -vEe \"^$(git current-branch)$\" | fzf | ifne xargs git switch" 124 | 125 | pc = push-current 126 | pt = push --tags 127 | ms = merge-status 128 | ua = update-all 129 | b = !hub browse 130 | 131 | graft = "!f() { git rebase --onto ${1:-@} $(git merge-base HEAD ${1:-@}); }; f" 132 | 133 | [url "https://github.com/"] 134 | insteadOf = gh 135 | 136 | [diff] 137 | # compactionHeuristic = true # for more beautiful diffs that favor whitespace lines to the hunk boundaries 138 | indentHeuristic = true # for more beautiful diffs that favor whitespace lines to the hunk boundaries 139 | tool = mvim -d 140 | algorithm = patience 141 | renameLimit = 3000 142 | noprefix = true 143 | 144 | [help] 145 | autocorrect = 1 146 | 147 | [push] 148 | default = simple 149 | 150 | [filter "media"] 151 | clean = git-media-clean %f 152 | smudge = git-media-smudge %f 153 | 154 | [credential] 155 | helper = osxkeychain 156 | 157 | [advice] 158 | skippedCherryPicks = false 159 | 160 | [filter "lfs"] 161 | clean = git-lfs clean -- %f 162 | smudge = git-lfs smudge -- %f 163 | process = git-lfs filter-process 164 | required = true 165 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # non-dot files 2 | /[^.]* 3 | !/bin 4 | 5 | # Don't include files with sensitive data 6 | /.zshrc-secrets 7 | 8 | # iJunk 9 | .DS_Store 10 | .MacOSX 11 | .Trash 12 | 13 | # Node stuff 14 | /.v8flags.* 15 | 16 | # ZSH junk 17 | /.zcompdump* 18 | /.zsh-update 19 | 20 | # Virtual envs 21 | /.virtualenvs 22 | /.rvm 23 | /.nvm 24 | 25 | # History files 26 | /.*history 27 | 28 | # Dotfiles 29 | /*Drobo* 30 | /.*-dropbox-token 31 | /.ackrc 32 | /.adobe 33 | /.alvzfmtrc 34 | /.android 35 | /.ansible/ 36 | /.ansible_galaxy 37 | /.ansible_roles/ 38 | /.appcfg_cookies 39 | /.appcfg_nag 40 | /.ascii.io 41 | /.atom/ 42 | /.autoenv 43 | /.autoenv_authorized 44 | /.autoenv_authorized.tmp 45 | /.aws/ 46 | /.babel.json 47 | /.belastingdienst.nl 48 | /.bi_li3 49 | /.bower 50 | /.bun 51 | /.bundle 52 | /.bup 53 | /.bzr.log 54 | /.cache 55 | /.cargo 56 | /.cassandra 57 | /.cdk 58 | /.CFUserTextEncoding 59 | /.chef 60 | /.config 61 | /.cookiecutters 62 | /.cups 63 | /.dbshell 64 | /.degit 65 | /.devpi 66 | /.direnvrc 67 | /.docker/ 68 | /.dropbox 69 | /.dropbox-master 70 | /.dts/ 71 | /.dvdcss 72 | /.eaglerc 73 | /.elm 74 | /.emacs.d 75 | /.eslint_d 76 | /.flow-typed/ 77 | /.fontconfig 78 | /.ftcurlish.json 79 | /.gem 80 | /.gh-credentials 81 | /.gist 82 | /.gist-vim 83 | /.gitconfig 84 | /.git 85 | /.gitk 86 | /.gnupg 87 | /.grc 88 | /.heroku 89 | /.httpie 90 | /.ipython 91 | /.irssi 92 | /.iterm2 93 | /.js 94 | /.jupyter/ 95 | /.keybase-installer 96 | /.lein 97 | /.lesshst 98 | /.local 99 | /.locks 100 | /.m2 101 | /.matplotlib 102 | /.mitmproxy 103 | /.mongorc.js 104 | /.msgsrc 105 | /.my.cnf 106 | /.netrc 107 | /.ngrok/ 108 | /.ngrok2/ 109 | /.njxnqxgn 110 | /.node/ 111 | /.node-gyp/ 112 | /.npm 113 | /.npmrc 114 | /.nuxtrc 115 | /.oh-my-zsh 116 | /.parallel 117 | /.pip 118 | /.pip-accel 119 | /.pip-tools 120 | /.pkg-cache 121 | /.pm2/ 122 | /.pnpm-state/ 123 | /.pre-commit/ 124 | /.profile 125 | /.pyenv/ 126 | /.pylint.d 127 | /.pypirc 128 | /.python-eggs 129 | /.pythonhist 130 | /.pythonrc.py 131 | /.pythonz 132 | /.rbenv 133 | /.resty 134 | /.ri 135 | /.rnd 136 | /.rustup 137 | /.s3cfg 138 | /.serverless 139 | /.serverlessrc 140 | /.srl 141 | /.ssh 142 | /.subversion 143 | /.tmux.conf 144 | /.tox 145 | /.tsd-cache/ 146 | /.ttytterkey 147 | /.vagrant.d 148 | /.vim* 149 | /.volta/ 150 | /.vscode/ 151 | /.wget-hsts 152 | /.wrangler 153 | /.Xauthority 154 | /.XcodeDefaultPerspective.mode1v3 155 | /.yarn* 156 | /.yesgraph-* 157 | /.z* 158 | 159 | # Directories 160 | Projects 161 | 162 | # Vim generated documentation 163 | /doc/tags 164 | 165 | # Powerline-specific cruft that isn't ignored in their own plugin 166 | Powerline_*.cache 167 | 168 | # Postgres stuff 169 | /.pg* 170 | 171 | # MongoDB 172 | /.mongodb 173 | -------------------------------------------------------------------------------- /.iterm2_shell_integration.fish: -------------------------------------------------------------------------------- 1 | # This program is free software; you can redistribute it and/or 2 | # modify it under the terms of the GNU General Public License 3 | # as published by the Free Software Foundation; either version 2 4 | # of the License, or (at your option) any later version. 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | # GNU General Public License for more details. 10 | # 11 | # You should have received a copy of the GNU General Public License 12 | # along with this program; if not, write to the Free Software 13 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 14 | 15 | if begin; status --is-interactive; and not functions -q -- iterm2_status; and [ "$ITERM_ENABLE_SHELL_INTEGRATION_WITH_TMUX""$TERM" != screen ]; and [ "$TERM" != dumb ]; and [ "$TERM" != linux ]; end 16 | function iterm2_status 17 | printf "\033]133;D;%s\007" $argv 18 | end 19 | 20 | # Mark start of prompt 21 | function iterm2_prompt_mark 22 | printf "\033]133;A\007" 23 | end 24 | 25 | # Mark end of prompt 26 | function iterm2_prompt_end 27 | printf "\033]133;B\007" 28 | end 29 | 30 | # Tell terminal to create a mark at this location 31 | function iterm2_preexec --on-event fish_preexec 32 | # For other shells we would output status here but we can't do that in fish. 33 | printf "\033]133;C;\007" 34 | end 35 | 36 | # Usage: iterm2_set_user_var key value 37 | # These variables show up in badges (and later in other places). For example 38 | # iterm2_set_user_var currentDirectory "$PWD" 39 | # Gives a variable accessible in a badge by \(user.currentDirectory) 40 | # Calls to this go in iterm2_print_user_vars. 41 | function iterm2_set_user_var 42 | printf "\033]1337;SetUserVar=%s=%s\007" "$argv[1]" (printf "%s" "$argv[2]" | base64 | tr -d "\n") 43 | end 44 | 45 | function iterm2_write_remotehost_currentdir_uservars 46 | printf "\033]1337;RemoteHost=%s@%s\007\033]1337;CurrentDir=%s\007" $USER $iterm2_hostname $PWD 47 | 48 | # Users can define a function called iterm2_print_user_vars. 49 | # It should call iterm2_set_user_var and produce no other output. 50 | if functions -q -- iterm2_print_user_vars 51 | iterm2_print_user_vars 52 | end 53 | 54 | end 55 | 56 | functions -c fish_prompt iterm2_fish_prompt 57 | 58 | functions -c fish_mode_prompt iterm2_fish_mode_prompt 59 | function fish_mode_prompt --description 'Write out the mode prompt; do not replace this. Instead, change fish_mode_prompt before sourcing .iterm2_shell_integration.fish, or modify iterm2_fish_mode_prompt instead.' 60 | set -l last_status $status 61 | 62 | iterm2_status $last_status 63 | iterm2_write_remotehost_currentdir_uservars 64 | if not functions iterm2_fish_prompt | grep iterm2_prompt_mark > /dev/null 65 | iterm2_prompt_mark 66 | end 67 | sh -c "exit $last_status" 68 | 69 | iterm2_fish_mode_prompt 70 | end 71 | 72 | function fish_prompt --description 'Write out the prompt; do not replace this. Instead, change fish_prompt before sourcing .iterm2_shell_integration.fish, or modify iterm2_fish_prompt instead.' 73 | # Remove the trailing newline from the original prompt. This is done 74 | # using the string builtin from fish, but to make sure any escape codes 75 | # are correctly interpreted, use %b for printf. 76 | printf "%b" (string join "\n" (iterm2_fish_prompt)) 77 | 78 | iterm2_prompt_end 79 | end 80 | 81 | # If hostname -f is slow for you, set iterm2_hostname before sourcing this script 82 | if not set -q -g iterm2_hostname 83 | set -g iterm2_hostname (hostname -f 2>/dev/null) 84 | # some flavors of BSD (i.e. NetBSD and OpenBSD) don't have the -f option 85 | if test $status -ne 0 86 | set -g iterm2_hostname (hostname) 87 | end 88 | end 89 | 90 | iterm2_write_remotehost_currentdir_uservars 91 | printf "\033]1337;ShellIntegrationVersion=10;shell=fish\007" 92 | end 93 | 94 | alias imgcat=$HOME/.iterm2/imgcat;alias imgls=$HOME/.iterm2/imgls;alias it2api=$HOME/.iterm2/it2api;alias it2attention=$HOME/.iterm2/it2attention;alias it2check=$HOME/.iterm2/it2check;alias it2copy=$HOME/.iterm2/it2copy;alias it2dl=$HOME/.iterm2/it2dl;alias it2getvar=$HOME/.iterm2/it2getvar;alias it2git=$HOME/.iterm2/it2git;alias it2setcolor=$HOME/.iterm2/it2setcolor;alias it2setkeylabel=$HOME/.iterm2/it2setkeylabel;alias it2ul=$HOME/.iterm2/it2ul;alias it2universion=$HOME/.iterm2/it2universion 95 | -------------------------------------------------------------------------------- /.psqlrc: -------------------------------------------------------------------------------- 1 | -- automatically switch between extended and normal 2 | \x auto 3 | 4 | -- always show how long a query takes 5 | \timing 6 | -------------------------------------------------------------------------------- /.tigrc: -------------------------------------------------------------------------------- 1 | # set reference-format = ❬branch❭ ⟪remote⟫ [tag] 2 | set reference-format = ⟪branch⟫ ⟪remote⟫ [tag] 3 | 4 | set main-view-date-display = custom 5 | set main-view-date-format = "%b %d %H:%M %Z" 6 | set main-view-author-display = abbreviated 7 | set main-view-author-width = 9 8 | 9 | # Custom colors 10 | # Format: 11 | # color [attributes] 12 | color main-head white default 13 | 14 | # 'unbind' the default quit key binding 15 | # bind main Q none 16 | 17 | # Cherry-pick selected commit onto current branch 18 | # bind generic C !git cherry-pick %(commit) 19 | 20 | # Revert the selected commit 21 | bind generic R !git revert --no-edit %(commit) 22 | bind generic Y !sh -c "echo %(commit) | tr -d '\\n' | pbcopy; echo 'SHA \"%(commit)\" copied to clipboard'" 23 | bind generic M !git merge --ff-only %(commit) 24 | -------------------------------------------------------------------------------- /Raycast User Scripts/README.md: -------------------------------------------------------------------------------- 1 | Most of these scripts are just copy-pasted from this repo: 2 | https://github.com/raycast/script-commands 3 | 4 | Raycast must be configured to use this directory as a known script directory. 5 | -------------------------------------------------------------------------------- /Raycast User Scripts/default-browser-chrome.applescript: -------------------------------------------------------------------------------- 1 | #!/usr/bin/osascript 2 | 3 | # Dependency: requires defaultbrowser (https://github.com/kerma/defaultbrowser) 4 | # Install via Homebrew: `brew install defaultbrowser` 5 | 6 | # Required parameters: 7 | # @raycast.schemaVersion 1 8 | # @raycast.title Default to Chrome 9 | # @raycast.mode silent 10 | # @raycast.packageName Browser 11 | 12 | # Optional parameters: 13 | # @raycast.icon images/chrome.png 14 | 15 | # Documentation: 16 | # @raycast.author Marcos Sánchez-Dehesa 17 | # @raycast.authorURL https://github.com/dehesa 18 | # @raycast.description Set Google Chrome as the default browser. 19 | 20 | set repeatCount to 0 21 | 22 | tell application "System Events" 23 | try 24 | my changeDefaultBrowser("chrome") 25 | repeat until button 2 of window 1 of process "CoreServicesUIAgent" exists 26 | delay 0.01 27 | set repeatCount to repeatCount + 1 28 | if repeatCount = 15 then exit repeat 29 | end repeat 30 | try 31 | click button 2 of window 1 of process "CoreServicesUIAgent" 32 | log "Google Chrome is now your default browser" 33 | on error 34 | log "Google Chrome is already your default browser" 35 | end try 36 | on error 37 | log "The \"defaultbrowser\" CLI tool is required: https://github.com/kerma/defaultbrowser 🔥" 38 | end try 39 | end tell 40 | 41 | to changeDefaultBrowser(thebrowser) 42 | do shell script " 43 | if ! command -v defaultbrowser &> /dev/null; then 44 | exit 1 45 | fi 46 | defaultbrowser " & thebrowser & " 47 | exit 0 48 | " 49 | end changeDefaultBrowser -------------------------------------------------------------------------------- /Raycast User Scripts/default-browser-chromium.applescript: -------------------------------------------------------------------------------- 1 | #!/usr/bin/osascript 2 | 3 | # Dependency: requires defaultbrowser (https://github.com/kerma/defaultbrowser) 4 | # Install via Homebrew: `brew install defaultbrowser` 5 | 6 | # Required parameters: 7 | # @raycast.schemaVersion 1 8 | # @raycast.title Default to Chromium 9 | # @raycast.mode silent 10 | # @raycast.packageName Browser 11 | 12 | # Optional parameters: 13 | # @raycast.icon images/chrome-icon.png 14 | 15 | # Documentation: 16 | # @raycast.author Marcos Sánchez-Dehesa 17 | # @raycast.authorURL https://github.com/dehesa 18 | # @raycast.description Set Chromium as the default browser. 19 | 20 | set repeatCount to 0 21 | 22 | tell application "System Events" 23 | try 24 | my changeDefaultBrowser("chromium") 25 | repeat until button 2 of window 1 of process "CoreServicesUIAgent" exists 26 | delay 0.01 27 | set repeatCount to repeatCount + 1 28 | if repeatCount = 15 then exit repeat 29 | end repeat 30 | try 31 | click button 2 of window 1 of process "CoreServicesUIAgent" 32 | log "Chromium is now your default browser" 33 | on error 34 | log "Chromium is already your default browser" 35 | end try 36 | on error 37 | log "The \"defaultbrowser\" CLI tool is required: https://github.com/kerma/defaultbrowser 🔥" 38 | end try 39 | end tell 40 | 41 | to changeDefaultBrowser(thebrowser) 42 | do shell script " 43 | if ! command -v defaultbrowser &> /dev/null; then 44 | exit 1 45 | fi 46 | defaultbrowser " & thebrowser & " 47 | exit 0 48 | " 49 | end changeDefaultBrowser -------------------------------------------------------------------------------- /Raycast User Scripts/default-browser-firefox.applescript: -------------------------------------------------------------------------------- 1 | #!/usr/bin/osascript 2 | 3 | # Dependency: requires defaultbrowser (https://github.com/kerma/defaultbrowser) 4 | # Install via Homebrew: `brew install defaultbrowser` 5 | 6 | # Required parameters: 7 | # @raycast.schemaVersion 1 8 | # @raycast.title Default to Firefox 9 | # @raycast.mode silent 10 | # @raycast.packageName Browser 11 | 12 | # Optional parameters: 13 | # @raycast.icon images/firefox.png 14 | 15 | # Documentation: 16 | # @raycast.author Marcos Sánchez-Dehesa 17 | # @raycast.authorURL https://github.com/dehesa 18 | # @raycast.description Set Firefox as the default browser. 19 | 20 | # check to see what the current browser is 21 | set currentDefaultBrowser to my getCurrentDefaultBrowser() 22 | 23 | set repeatCount to 0 24 | 25 | tell application "System Events" 26 | try 27 | my changeDefaultBrowser("firefox") 28 | repeat until button 2 of window 1 of process "CoreServicesUIAgent" exists 29 | delay 0.01 30 | set repeatCount to repeatCount + 1 31 | if repeatCount = 15 then exit repeat 32 | end repeat 33 | try 34 | # if Chrome is the current default browser, the order of the buttons is reversed. Click button 1 to change the default browser to FF. 35 | if currentDefaultBrowser contains "com.google.chrome" then 36 | click button 1 of window 1 of process "CoreServicesUIAgent" 37 | else # otherwise click button 2 to change the default browser to FF. 38 | click button 2 of window 1 of process "CoreServicesUIAgent" 39 | end if 40 | log "Firefox is now your default browser" 41 | on error 42 | log "Firefox is already your default browser" 43 | end try 44 | on error 45 | log "The \"defaultbrowser\" CLI tool is required: https://github.com/kerma/defaultbrowser 🔥" 46 | end try 47 | end tell 48 | 49 | to getCurrentDefaultBrowser() 50 | set filePath to "~/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist" 51 | 52 | set output to do shell script "plutil -p " & filePath & " | awk '/LSHandlerRoleAll/{a=$3}/LSHandlerURLScheme/{if($3==\"\\\"https\\\"\") print a}'" 53 | return output 54 | end getCurrentDefaultBrowser 55 | 56 | to changeDefaultBrowser(thebrowser) 57 | do shell script " 58 | if ! command -v defaultbrowser &> /dev/null; then 59 | exit 1 60 | fi 61 | defaultbrowser " & thebrowser & " 62 | exit 0 63 | " 64 | end changeDefaultBrowser 65 | -------------------------------------------------------------------------------- /Raycast User Scripts/default-browser-safari.applescript: -------------------------------------------------------------------------------- 1 | #!/usr/bin/osascript 2 | 3 | # Dependency: requires defaultbrowser (https://github.com/kerma/defaultbrowser) 4 | # Install via Homebrew: `brew install defaultbrowser` 5 | 6 | # Required parameters: 7 | # @raycast.schemaVersion 1 8 | # @raycast.title Default to Safari 9 | # @raycast.mode silent 10 | # @raycast.packageName Browser 11 | 12 | # Optional parameters: 13 | # @raycast.icon images/safari.png 14 | 15 | # Documentation: 16 | # @raycast.author Marcos Sánchez-Dehesa 17 | # @raycast.authorURL https://github.com/dehesa 18 | # @raycast.description Set Safari as the default browser. 19 | 20 | # check to see what the current browser is 21 | set currentDefaultBrowser to my getCurrentDefaultBrowser() 22 | 23 | set repeatCount to 0 24 | 25 | tell application "System Events" 26 | try 27 | my changeDefaultBrowser("safari") 28 | repeat until button 2 of window 1 of process "CoreServicesUIAgent" exists 29 | delay 0.01 30 | set repeatCount to repeatCount + 1 31 | if repeatCount = 15 then exit repeat 32 | end repeat 33 | try 34 | # if Chrome is the current default browser, the order of the buttons is reversed. Click button 1 to change the default browser to Safari. 35 | if currentDefaultBrowser contains "com.google.chrome" then 36 | click button 1 of window 1 of process "CoreServicesUIAgent" 37 | else # otherwise click button 2 to change the default browser to Safari. 38 | click button 2 of window 1 of process "CoreServicesUIAgent" 39 | end if 40 | log "Safari is now your default browser" 41 | on error 42 | log "Safari is already your default browser" 43 | end try 44 | on error 45 | log "The \"defaultbrowser\" CLI tool is required: https://github.com/kerma/defaultbrowser 🔥" 46 | end try 47 | end tell 48 | 49 | to getCurrentDefaultBrowser() 50 | set filePath to "~/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist" 51 | 52 | set output to do shell script "plutil -p " & filePath & " | awk '/LSHandlerRoleAll/{a=$3}/LSHandlerURLScheme/{if($3==\"\\\"https\\\"\") print a}'" 53 | return output 54 | end getCurrentDefaultBrowser 55 | 56 | to changeDefaultBrowser(thebrowser) 57 | do shell script " 58 | if ! command -v defaultbrowser &> /dev/null; then 59 | exit 1 60 | fi 61 | defaultbrowser " & thebrowser & " 62 | exit 0 63 | " 64 | end changeDefaultBrowser 65 | -------------------------------------------------------------------------------- /bin/api-diff: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | usage () { 5 | echo "usage: api-diff [-t] []" >&2 6 | echo >&2 7 | echo "Options:" >&2 8 | echo "-t Print only the type diffs, not the implementation." >&2 9 | echo >&2 10 | echo "Build the given sha, and the current sha, and compare the build outputs." >&2 11 | echo "" >&2 12 | } 13 | 14 | types_only=0 15 | while getopts th flag; do 16 | case "$flag" in 17 | t) types_only=1;; 18 | h) usage; exit 2;; 19 | *) usage; exit 2;; 20 | esac 21 | done 22 | shift $(($OPTIND - 1)) 23 | 24 | base="$(basename "$(pwd)")" 25 | 26 | if [ "$base" != "liveblocks-core" -a "$base" != "liveblocks-client" -a "$base" != "liveblocks-react" ]; then 27 | echo "Please run this script from the liveblocks-{core,client,react} directory" 28 | exit 1 29 | fi 30 | 31 | # Changes rollup to produce a build without internal APIs. This way, we will 32 | # not generate a shared.d.mts, making the final diff easier to compare. 33 | hack_the_build () { 34 | sr -s 'entry: \[.*\]' -r 'entry: ["src/index.ts"]' tsup.config.ts 35 | sr -s 'target: ".*"' -r 'target: "esnext"' tsup.config.ts 36 | sr -s 'format: \[.*\]' -r 'format: ["esm"]' tsup.config.ts 37 | } 38 | 39 | build_output () { 40 | npm i 41 | rm -rf lib dist 42 | hack_the_build 43 | turbo build 44 | 45 | if [ -d dist ]; then 46 | prettier --write dist/index.*s 47 | else 48 | prettier --write lib/index.*s 49 | fi 50 | } 51 | 52 | # ----------------------------------------------------------------------------- 53 | # Now first generate the index.d.mts file for the _current_ public API (the base 54 | # for the comparison) 55 | if [ $# -ne 1 ]; then 56 | echo "usage: api-diff " 57 | exit 1 58 | fi 59 | 60 | PREV_OUTDIR="/tmp/$base/$1" 61 | mkdir -p "$PREV_OUTDIR" 62 | 63 | CURR_OUTDIR="/tmp/$base/currsha" 64 | mkdir -p "$CURR_OUTDIR" 65 | 66 | if [ ! -f "$PREV_OUTDIR/index.d.mts" ]; then 67 | git is-clean -v 68 | git checkout "$1" 69 | build_output 70 | 71 | # Store the results in /tmp 72 | if [ -d dist ]; then 73 | cp dist/index.* "$PREV_OUTDIR" 74 | else 75 | cp lib/index.* "$PREV_OUTDIR" 76 | fi 77 | 78 | git drop-local-changes 79 | 80 | # Switch back 81 | git checkout - 82 | fi 83 | 84 | # ----------------------------------------------------------------------------- 85 | # Next, generate the public index.d.mts for the current branch 86 | 87 | git is-clean -v 88 | build_output 89 | 90 | # Store the results in /tmp 91 | if [ -d dist ]; then 92 | cp dist/index.* "$CURR_OUTDIR" 93 | else 94 | cp lib/index.* "$CURR_OUTDIR" 95 | fi 96 | 97 | git drop-local-changes 98 | 99 | # Show the diff 100 | if [ "$types_only" -eq 1 ]; then 101 | colordiff -u "$PREV_OUTDIR/index.d.mts" "$CURR_OUTDIR/index.d.mts" | less -R 102 | else 103 | colordiff -u "$PREV_OUTDIR" "$CURR_OUTDIR" | less -R 104 | fi 105 | 106 | # rm -rf "$PREV_OUTDIR" "$CURR_OUTDIR" 107 | -------------------------------------------------------------------------------- /bin/autodate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Renames the given files 4 | # 5 | set -e 6 | 7 | if [ "$#" -eq 0 ]; then 8 | echo "usage: autodate [ ...]" 9 | exit 2 10 | fi 11 | 12 | # Prerequisites 13 | brew install -q pdfgrep # will also install pdftotext (as a dependency) 14 | 15 | 16 | rename_pdf () { 17 | filename="$1" 18 | 19 | sha=$(shasum "$filename" | cut -c -8) 20 | pdftotext -layout "$filename" - | find-dates | while read date; do 21 | dir=$(dirname "$filename") 22 | output="$dir/$date - $sha.pdf" 23 | echo "$filename => $output" 24 | mv "$filename" "$output" 25 | break # process only the first ever match 26 | done 27 | } 28 | 29 | 30 | main () { 31 | for filename in "$@"; do 32 | rename_pdf "$filename" 33 | done 34 | } 35 | 36 | 37 | main "$@" 38 | -------------------------------------------------------------------------------- /bin/binary: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Checks whether the given input file is a binary file or not. 3 | 4 | usage() { 5 | echo "usage: $(basename "$0") " >&2 6 | echo "Exit code tells whether the file is binary (0) or not (1)." >&2 7 | } 8 | 9 | if [ $# -eq 1 ]; then 10 | dd if="$1" bs=8k count=1 2>/dev/null | od -b | egrep -q '\b000\b' 11 | else 12 | usage 13 | exit 2 14 | fi 15 | -------------------------------------------------------------------------------- /bin/brew-all-the-things: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PACKAGES=" 3 | gibsjose/crypto/bcrypt-hash 4 | bup 5 | colordiff 6 | coreutils 7 | cowsay 8 | cscope 9 | ctags 10 | diff-pdf 11 | direnv 12 | docbook-xsl 13 | docker-compose 14 | doxygen 15 | fd 16 | ffind 17 | ffmpeg 18 | figlet 19 | fish 20 | fzf 21 | gcc 22 | git 23 | gnupg 24 | graphviz 25 | guetzli 26 | hub 27 | imagemagick 28 | jq 29 | libevent 30 | libssh2 31 | libxmlsec1 32 | lolcat 33 | moreutils 34 | mysql 35 | mysql@5.7 36 | nginx 37 | ngrep 38 | openssl@1.1 39 | optipng 40 | pdfgrep 41 | pipenv 42 | pngquant 43 | postgresql 44 | pv 45 | pyenv 46 | reattach-to-user-namespace 47 | redis 48 | ripgrep 49 | sphinx-doc 50 | ssh-copy-id 51 | tesseract 52 | tig 53 | tldr 54 | tree 55 | unrar 56 | vim 57 | watch 58 | watchman 59 | wget 60 | yarn 61 | " 62 | 63 | echo "$PACKAGES" | while read line; do 64 | if [ "$line" != "" ]; then 65 | brew install "$line" 66 | fi 67 | done 68 | -------------------------------------------------------------------------------- /bin/comma-separate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | grep . | tr '\n' ',' | sed -E -e 's/^,+//' -e 's/,+$//' 3 | -------------------------------------------------------------------------------- /bin/deps: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | usage () { 5 | echo "usage: deps [-pdPh]" >&2 6 | echo >&2 7 | echo "Options:" >&2 8 | echo "-p List production dependencies" >&2 9 | echo "-d List dev dependencies" >&2 10 | echo "-P List peer dependencies" >&2 11 | echo "-v Also list versions" >&2 12 | echo "-l Print \"@latest\" as versions" >&2 13 | echo "-h Print this help" >&2 14 | echo >&2 15 | echo "List dependencies from package.json" >&2 16 | echo "" >&2 17 | } 18 | 19 | prod=0 20 | dev=0 21 | peer=0 22 | show_versions=0 23 | show_latest=0 24 | while getopts pdPvlh flag; do 25 | case "$flag" in 26 | p) prod=1;; 27 | d) dev=1;; 28 | P) peer=1;; 29 | v) show_versions=1; show_latest=0;; 30 | l) show_latest=1; show_versions=0;; 31 | h) usage; exit 2;; 32 | *) usage; exit 2;; 33 | esac 34 | done 35 | shift $(($OPTIND - 1)) 36 | 37 | if [ "$prod" -eq 0 -a "$dev" -eq 0 -a "$peer" -eq 0 ]; then 38 | prod=1 39 | dev=1 40 | peer=1 41 | fi 42 | 43 | latest_query=' as $k | "\($k)@latest"' 44 | versions_query=' as $k | "\($k)@\(.[$k])"' 45 | 46 | query () { 47 | key="$1" 48 | query="(.$key // []) | keys[]" 49 | if [ $show_versions -eq 1 ]; then 50 | query="$query$versions_query" 51 | elif [ $show_latest -eq 1 ]; then 52 | query="$query$latest_query" 53 | fi 54 | jq -r "$query" package.json 55 | } 56 | 57 | if [ "$prod" -eq 1 ]; then 58 | query dependencies 59 | fi 60 | 61 | if [ "$dev" -eq 1 ]; then 62 | query devDependencies 63 | fi 64 | 65 | if [ "$peer" -eq 1 ]; then 66 | query peerDependencies 67 | fi 68 | -------------------------------------------------------------------------------- /bin/drop-until: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | pattern="$1" 5 | 6 | awk " 7 | BEGIN { matched = 0; } 8 | /$pattern/ { matched = 1 } 9 | { if (matched) { print \$0 } } 10 | " 11 | -------------------------------------------------------------------------------- /bin/exclude-from-backups-re.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Base list to exclude from Mac OSX (from Honza's blog post) 3 | # http://honza.ca/2013/07/how-i-back-up-my-laptop 4 | # 5 | 6 | # Anchored 7 | ^/afs/ 8 | ^/automount/ 9 | ^/cores/ 10 | ^/dev/ 11 | ^/Network/ 12 | ^/private/ 13 | ^/Previous Systems\.localized 14 | ^/tmp/ 15 | ^/Volumes/ 16 | ^/\.DocumentRevisions-.*/ 17 | ^/\.MobileBackups/ 18 | 19 | # Exclude homebrew 20 | ^/usr/local/Cellar/ 21 | 22 | # Non-anchored dirs 23 | /\.Trash/ 24 | /\.Spotlight-.*/ 25 | /\.Trashes/ 26 | 27 | # Exclude typically large files I don't need 28 | ^/Users/[^/]+/\.cache/ 29 | ^/Users/[^/]+/\.pip-tools/ 30 | ^/Users/[^/]+/Caches/ 31 | ^/Users/[^/]+/Downloads/ 32 | 33 | # Various locations of caches 34 | /Library/Caches/ 35 | 36 | # Dirs I typically don't care about 37 | /\.direnv/ 38 | /\.tox/ 39 | /site-packages/ 40 | /\.DS_Store 41 | 42 | # Very large apps 43 | ^/Applications/Xcode\.app/ 44 | ^/Applications/Xcode-Beta\.app/ 45 | -------------------------------------------------------------------------------- /bin/find-dates: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Finds any dates occurring in standard input, and prints them to stdout in 4 | # a YYYY-MM-DD format. 5 | # 6 | 7 | import re 8 | import sys 9 | 10 | months = [ 11 | ('jan', 'januari', 'january'), 12 | ('feb', 'febr', 'februari', 'february'), 13 | ('mar', 'mrt', 'maart', 'march'), 14 | ('apr', 'april'), 15 | ('mei', 'may'), 16 | ('jun', 'juni', 'june'), 17 | ('jul', 'juli', 'july'), 18 | ('aug', 'augustus', 'august'), 19 | ('sep', 'sept', 'september'), 20 | ('okt', 'oct', 'oktober', 'october'), 21 | ('nov', 'november'), 22 | ('dec', 'december'), 23 | ] 24 | month_lut = {month: i for i, spellings in enumerate(months, start=1) for month in spellings} 25 | 26 | dutch_date_with_nonnumeric_month_re = re.compile(r'(?P[0-9]{1,2})[-.\s]*(?P' + 27 | '|'.join(month_lut) + 28 | ')[-.\s]*(?P[0-9]{4})') # noqa 29 | dutch_date_with_numeric_month_re = re.compile(r'(?P[0-9]{1,2})[-/.\s]+(?P[0-9]{1,2})[-/.\s]+(?P[0-9]{4})') 30 | # us_date_with_numeric_month_re = re.compile(r'...') 31 | 32 | for line in sys.stdin: 33 | line = line.lower() # match case-insensitive 34 | m = (dutch_date_with_nonnumeric_month_re.search(line) or 35 | dutch_date_with_numeric_month_re.search(line)) 36 | if m: 37 | doc = m.groupdict() 38 | year, month, day = doc['year'], doc['month'], doc['day'] 39 | 40 | year = int(year) 41 | if not (1970 <= year < 2100): 42 | continue # year out of range 43 | 44 | if month.isdigit(): 45 | month = int(month) 46 | else: 47 | month = month_lut.get(month, 0) 48 | 49 | if not (1 <= month <= 12): 50 | continue # not a valid month 51 | 52 | day = int(day) 53 | if not (1 <= day <= 31): 54 | continue # not a valid day 55 | 56 | print("{year:04}-{month:02}-{day:02}".format(year=year, month=month, day=day)) 57 | -------------------------------------------------------------------------------- /bin/find-extensions: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | extensions=$* 5 | 6 | main() { 7 | if [ -z "$extensions" ]; then 8 | find . 9 | else 10 | echo "find . $(build_find_command_arguments)" | sh 11 | fi 12 | } 13 | 14 | build_find_command_arguments() { 15 | args="" 16 | for ext in $extensions; do 17 | args="${args} -o -name '*.${ext}'" 18 | done 19 | echo $args | cut -c 4- 20 | } 21 | 22 | main 23 | -------------------------------------------------------------------------------- /bin/fix-repo-for-vim: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | # Fail if we're not in a Git repo 5 | git is-clean -v 6 | 7 | GIT_ROOT="$(git root)" 8 | COC_FILE="${GIT_ROOT}/.vim/coc-settings.json" 9 | GIT_IGNORE="${GIT_ROOT}/.gitignore" 10 | 11 | if [ ! -f "$COC_FILE" ]; then 12 | mkdir -p "$(dirname "$COC_FILE")" 13 | echo "{" > "$COC_FILE" 14 | echo ' // "tsserver.useLocalTdsk": true,' >> "$COC_FILE" 15 | echo " \"tsserver.tsdk\": \"${GIT_ROOT}/node_modules/typescript/lib\"" >> "$COC_FILE" 16 | echo "}" >> "$COC_FILE" 17 | fi 18 | 19 | if ! grep -qx '.vim/' "${GIT_IGNORE}"; then 20 | echo ".vim/" >> "${GIT_IGNORE}" 21 | fi 22 | 23 | echo "Repo fixed" 24 | -------------------------------------------------------------------------------- /bin/flow-limit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | if [ $# -ge 1 -a "$1" -eq "$1" ] 2>/dev/null; then 5 | # ^^^^^^^^^^^^^ Checks if this is a valid number 6 | max=$1 7 | shift 8 | else 9 | max=1 10 | fi 11 | 12 | width=$(expr $(tput cols) - 1) 13 | flow --color=always --message-width="${width}" --show-all-errors "$@" | awk -v max=$max ' 14 | BEGIN { num = 0; } 15 | /^([^[:space:]]+)(Error|Warning) -+/ { num++ } 16 | num <= max { print $0 } 17 | ' 18 | -------------------------------------------------------------------------------- /bin/git-new: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | if [ $# -ne 1 ]; then 5 | echo "usage: git new " >&2 6 | exit 2 7 | fi 8 | 9 | main="$(git main-branch)" 10 | if [ "$main" = "$(git current-branch)" ]; then 11 | git pr 12 | else 13 | git ff 14 | fi 15 | 16 | git switch -c "$1" "$main" 17 | -------------------------------------------------------------------------------- /bin/git-overview: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | git log \ 5 | --color=always \ 6 | --oneline \ 7 | --decorate \ 8 | --decorate-refs-exclude="refs/remotes/*" \ 9 | --decorate-refs-exclude="refs/heads/origin/*" \ 10 | --graph \ 11 | --simplify-by-decoration \ 12 | $(git local-branches) \ 13 | --pretty="tformat:%h%C(bold)%d%C(reset)" \ 14 | | sed -E \ 15 | -e 's/origin\/[^, )]+//g' \ 16 | -e 's/HEAD -\> //' -e 's/, //g' \ 17 | -e 's/\(\)//' \ 18 | | less -R 19 | -------------------------------------------------------------------------------- /bin/glui: -------------------------------------------------------------------------------- 1 | scrot -------------------------------------------------------------------------------- /bin/imgcat: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # tmux requires unrecognized OSC sequences to be wrapped with DCS tmux; 4 | # ST, and for all ESCs in to be replaced with ESC ESC. It 5 | # only accepts ESC backslash for ST. We use TERM instead of TMUX because TERM 6 | # gets passed through ssh. 7 | function print_osc() { 8 | if [[ $TERM == screen* ]] ; then 9 | printf "\033Ptmux;\033\033]" 10 | else 11 | printf "\033]" 12 | fi 13 | } 14 | 15 | # More of the tmux workaround described above. 16 | function print_st() { 17 | if [[ $TERM == screen* ]] ; then 18 | printf "\a\033\\" 19 | else 20 | printf "\a" 21 | fi 22 | } 23 | 24 | # print_image filename inline base64contents print_filename 25 | # filename: Filename to convey to client 26 | # inline: 0 or 1 27 | # base64contents: Base64-encoded contents 28 | # print_filename: If non-empty, print the filename 29 | # before outputting the image 30 | function print_image() { 31 | print_osc 32 | printf '1337;File=' 33 | if [[ -n "$1" ]]; then 34 | printf 'name='`printf "%s" "$1" | base64`";" 35 | fi 36 | 37 | VERSION=$(base64 --version 2>&1) 38 | if [[ "$VERSION" =~ fourmilab ]]; then 39 | BASE64ARG=-d 40 | elif [[ "$VERSION" =~ GNU ]]; then 41 | BASE64ARG=-di 42 | else 43 | BASE64ARG=-D 44 | fi 45 | 46 | printf "%s" "$3" | base64 $BASE64ARG | wc -c | awk '{printf "size=%d",$1}' 47 | printf ";inline=$2" 48 | printf ":" 49 | printf "%s" "$3" 50 | print_st 51 | printf '\n' 52 | if [[ -n "$4" ]]; then 53 | echo $1 54 | fi 55 | } 56 | 57 | function error() { 58 | echo "ERROR: $*" 1>&2 59 | } 60 | 61 | function show_help() { 62 | echo "Usage: imgcat [-p] filename ..." 1>& 2 63 | echo " or: cat filename | imgcat" 1>& 2 64 | } 65 | 66 | function check_dependency() { 67 | if ! (builtin command -V "$1" > /dev/null 2>& 1); then 68 | echo "imgcat: missing dependency: can't find $1" 1>& 2 69 | exit 1 70 | fi 71 | } 72 | 73 | ## Main 74 | 75 | if [ -t 0 ]; then 76 | has_stdin=f 77 | else 78 | has_stdin=t 79 | fi 80 | 81 | # Show help if no arguments and no stdin. 82 | if [ $has_stdin = f -a $# -eq 0 ]; then 83 | show_help 84 | exit 85 | fi 86 | 87 | check_dependency awk 88 | check_dependency base64 89 | check_dependency wc 90 | 91 | # Look for command line flags. 92 | while [ $# -gt 0 ]; do 93 | case "$1" in 94 | -h|--h|--help) 95 | show_help 96 | exit 97 | ;; 98 | -p|--p|--print) 99 | print_filename=1 100 | ;; 101 | -u|--u|--url) 102 | check_dependency curl 103 | encoded_image=$(curl -s "$2" | base64) || (error "No such file or url $2"; exit 2) 104 | has_stdin=f 105 | print_image "$2" 1 "$encoded_image" "$print_filename" 106 | set -- ${@:1:1} "-u" ${@:3} 107 | if [ "$#" -eq 2 ]; then 108 | exit 109 | fi 110 | ;; 111 | -*) 112 | error "Unknown option flag: $1" 113 | show_help 114 | exit 1 115 | ;; 116 | *) 117 | if [ -r "$1" ] ; then 118 | has_stdin=f 119 | print_image "$1" 1 "$(base64 < "$1")" "$print_filename" 120 | else 121 | error "imgcat: $1: No such file or directory" 122 | exit 2 123 | fi 124 | ;; 125 | esac 126 | shift 127 | done 128 | 129 | # Read and print stdin 130 | if [ $has_stdin = t ]; then 131 | print_image "" 1 "$(cat | base64)" "" 132 | fi 133 | 134 | exit 0 135 | -------------------------------------------------------------------------------- /bin/imgls: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # tmux requires unrecognized OSC sequences to be wrapped with DCS tmux; 3 | # ST, and for all ESCs in to be replaced with ESC ESC. It 4 | # only accepts ESC backslash for ST. 5 | function print_osc() { 6 | if [ x"$TERM" = "xscreen" ] ; then 7 | printf "\033Ptmux;\033\033]" 8 | else 9 | printf "\033]" 10 | fi 11 | } 12 | 13 | function check_dependency() { 14 | if ! (builtin command -V "$1" > /dev/null 2>& 1); then 15 | echo "imgcat: missing dependency: can't find $1" 1>& 2 16 | exit 1 17 | fi 18 | } 19 | 20 | # More of the tmux workaround described above. 21 | function print_st() { 22 | if [ x"$TERM" = "xscreen" ] ; then 23 | printf "\a\033\\" 24 | else 25 | printf "\a" 26 | fi 27 | } 28 | 29 | function list_file() { 30 | fn=$1 31 | dims=$(php -r 'if (!is_file($argv[1])) exit(1); $a = getimagesize($argv[1]); if ($a==FALSE) exit(1); else { echo $a[0] . "x" .$a[1]; exit(0); }' "$fn") 32 | rc=$? 33 | if [[ $rc == 0 ]] ; then 34 | print_osc 35 | printf '1337;File=name='`echo -n "$fn" | base64`";" 36 | wc -c "$fn" | awk '{printf "size=%d",$1}' 37 | printf ";inline=1;height=3;width=3;preserveAspectRatio=true" 38 | printf ":" 39 | base64 < "$fn" 40 | print_st 41 | if [ x"$TERM" == "xscreen" ] ; then 42 | # This works in plain-old tmux but does the wrong thing in iTerm2's tmux 43 | # integration mode. tmux doesn't know that the cursor moves when the 44 | # image code is sent, while iTerm2 does. I had to pick one, since 45 | # integration mode is undetectable, so I picked the failure mode that at 46 | # least produces useful output (there is just too much whitespace in 47 | # integration mode). This could be fixed by not moving the cursor while 48 | # in integration mode. A better fix would be for tmux to interpret the 49 | # image sequence, though. 50 | # 51 | # tl;dr: If you use tmux in integration mode, replace this with the printf 52 | # from the else clause. 53 | printf '\033[4C\033[Bx' 54 | else 55 | printf '\033[A' 56 | fi 57 | echo -n "$dims " 58 | ls -ld "$fn" 59 | else 60 | ls -ld "$fn" 61 | fi 62 | } 63 | 64 | check_dependency php 65 | check_dependency base64 66 | check_dependency wc 67 | 68 | if [ $# -eq 0 ]; then 69 | for fn in * 70 | do 71 | list_file "$fn" 72 | done < <(ls -ls) 73 | else 74 | for fn in "$@" 75 | do 76 | list_file "$fn" 77 | done 78 | fi 79 | 80 | -------------------------------------------------------------------------------- /bin/ips: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ifconfig | awk ' 3 | 4 | /^[a-zA-Z0-9]+:/ { 5 | name=$1 6 | } 7 | 8 | /inet / { 9 | print name, $2 10 | } 11 | 12 | ' 13 | 14 | echo "external: $(curl -s http://icanhazip.com/)" 15 | -------------------------------------------------------------------------------- /bin/kill-by-port: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Shamelessly stolen from https://github.com/nficano/dotfiles/blob/master/bin/kill-by-port 3 | set -eu 4 | 5 | PORT="$1" 6 | 7 | find_proc_by_port () { 8 | lsof -i :"$1" | grep LISTEN | sed -Ee 's/^[^0-9]+([0-9]+).*$/\1/' 9 | } 10 | 11 | if [ "$(find_proc_by_port "$PORT" | wc -l)" -ge 1 ]; then 12 | THEPID="$(find_proc_by_port "$PORT")" 13 | echo kill "$THEPID" 14 | kill "$THEPID" 15 | 16 | echo "" 17 | echo "If the above did not work, try these:" 18 | echo "" 19 | echo " kill -9 $THEPID" 20 | echo " sudo kill -9 $THEPID" 21 | echo "" 22 | else 23 | echo "(no processes owning port $@)" >&2 24 | exit 0 25 | fi 26 | -------------------------------------------------------------------------------- /bin/lstrip: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | 4 | 5 | def main(): 6 | for line in sys.stdin: 7 | print(line.lstrip(), end='') 8 | 9 | 10 | if __name__ == '__main__': 11 | main() 12 | -------------------------------------------------------------------------------- /bin/make-mp3s-smaller-for-yfke: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | usage () { 5 | echo "usage: make-mp3s-smaller-for-yfke [-Q ] [-O ] [-m(ono)] " >&2 6 | } 7 | 8 | quality="128k" 9 | num_channels=2 10 | output_dir=~/Desktop/LQ\ Music 11 | while getopts Q:O:mh flag; do 12 | case "$flag" in 13 | Q) quality="$OPTARG";; 14 | O) output_dir="$OPTARG";; 15 | m) num_channels=1;; 16 | h) usage; exit 2;; 17 | esac 18 | done 19 | shift $(($OPTIND - 1)) 20 | 21 | mkdir -p "$output_dir" 22 | open "$output_dir" 23 | for f in "$@"; do 24 | rel=$(basename "$f") 25 | relmp3=$(echo "$rel" | sed -Ee 's/^(.*)[.]([^.]+)$/\1.mp3/') 26 | ffmpeg -v 5 -y -i "$f" -acodec libmp3lame -ac $num_channels -ab "$quality" "$output_dir/$relmp3" 27 | du -h "$output_dir/$relmp3" 28 | done 29 | du -h "$output_dir" 30 | -------------------------------------------------------------------------------- /bin/nonempty: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # A simpler helper script that echoes everything on stdin to stdout, like cat, 4 | # but exits with a non-zero exit code when only whitespace (or nothing) has 5 | # been outputted. 6 | # 7 | # If you know of a pipeline of standard Unix tools that does the same, 8 | # pipeline, please do get in touch with me. I'm on Twitter: @nvie. 9 | # 10 | import sys 11 | 12 | 13 | def main(): 14 | empty = True 15 | 16 | for line in sys.stdin.readlines(): 17 | if line.strip(): 18 | empty = False 19 | sys.stdout.write(line) 20 | sys.stdout.flush() 21 | 22 | sys.exit(int(empty)) 23 | 24 | 25 | if __name__ == '__main__': 26 | main() 27 | -------------------------------------------------------------------------------- /bin/npm-ls-uniq: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | npm ls "$1" | grep -vEe deduped | tr '─└│├┬' ' ' | sed -Ee 's/[[:space:]]+//' | grep -Ee "^$1@" | sort -u 5 | -------------------------------------------------------------------------------- /bin/oh-shut-up-yjs: -------------------------------------------------------------------------------- 1 | patch-annoying-node-libs -------------------------------------------------------------------------------- /bin/osx-settings.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # Increase keyboard speed 5 | defaults write -g InitialKeyRepeat -int 14 6 | defaults write -g KeyRepeat -int 1 7 | defaults write -g ApplePressAndHoldEnabled -bool no 8 | 9 | # Finder 10 | defaults write com.apple.finder AppleShowAllExtensions -boolean yes 11 | defaults write com.apple.finder AppleShowAllFiles -boolean yes 12 | defaults write com.apple.finder PathBarRootAtHome -bool yes 13 | defaults write com.apple.finder _FXShowPosixPathInTitle -bool yes 14 | 15 | # Dock 16 | defaults write com.apple.dock orientation -string "left" 17 | defaults write com.apple.dock autohide -boolean yes 18 | defaults write com.apple.dock magnification -boolean yes 19 | defaults write com.apple.dock largesize 65 # magnification factor 20 | 21 | # Make dock appear faster 22 | defaults write com.apple.dock autohide-delay -float 0 23 | defaults write com.apple.dock autohide-time-modifier -float 0.5 24 | defaults write com.apple.dock expose-animation-duration -float 0.15 25 | 26 | # Show battery percentage 27 | defaults write com.apple.menuextra.battery ShowPercent -string "YES" 28 | 29 | # Hot corners 30 | # Possible values: 31 | # 0: no-op 32 | # 2: Mission Control 33 | # 3: Show application windows 34 | # 4: Desktop 35 | # 5: Start screen saver 36 | # 6: Disable screen saver 37 | # 7: Dashboard 38 | # 10: Put display to sleep 39 | # 11: Launchpad 40 | # 12: Notification Center 41 | 42 | # Top left screen corner 43 | defaults write com.apple.dock wvous-tl-corner -int 6 44 | defaults write com.apple.dock wvous-tl-modifier -int 0 45 | 46 | # Top right screen corner 47 | defaults write com.apple.dock wvous-tr-corner -int 10 48 | defaults write com.apple.dock wvous-tr-modifier -int 0 49 | 50 | # Bottom left screen corner 51 | defaults write com.apple.dock wvous-bl-corner -int 0 52 | defaults write com.apple.dock wvous-bl-modifier -int 0 53 | 54 | # Bottom left screen corner 55 | defaults write com.apple.dock wvous-br-corner -int 4 56 | defaults write com.apple.dock wvous-br-modifier -int 0 57 | 58 | killall cfprefsd 59 | killall Finder 60 | killall Dock 61 | killall SystemUIServer 62 | -------------------------------------------------------------------------------- /bin/patch-annoying-node-libs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # 5 | # This script uses "sr", which is a search & replace tool. 6 | # To install it, run: 7 | # 8 | # $ brew install nvie/tap/sr 9 | # 10 | sr -s ' (console.error..Yjs was already imported)' \ 11 | -r ' // $1' \ 12 | node_modules/yjs/dist/*.{cjs,mjs} 13 | 14 | # Also hide deprecated messages 15 | sr -s "@deprecated (Use .buf.toString..base64|Use .Buffer.from.data. .base64)" \ 16 | -r 'deprecated $1' \ 17 | node_modules/@types/node/buffer.d.ts 18 | -------------------------------------------------------------------------------- /bin/pipsi-all-the-things: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | python2="/Users/nvie/.pyenv/versions/2.7.16/bin/python2" 5 | python3="/Users/nvie/.pyenv/versions/3.7.4/bin/python3" 6 | 7 | # pipsi install --python $python2 autopep8 8 | # pipsi install --python $python2 bpython 9 | # pipsi install --python $python2 cookiecutter 10 | # pipsi install --python $python2 devpi-client 11 | # pipsi install --python $python2 flake8 12 | pipsi install --python $python2 howdoi 13 | pipsi install --python $python2 httpie 14 | # pipsi install --python $python3 invoke 15 | pipsi install --python $python3 iron[all] 16 | pipsi install --python $python2 pygments 17 | # pipsi install --python $python3 python-fu 18 | pipsi install --python $python2 sr 19 | # pipsi install --python $python2 supervisor 20 | # pipsi install --python $python2 tox 21 | # pipsi install --python $python2 unp 22 | # pipsi install --python $python2 watchdog 23 | 24 | # Custom projects 25 | (cd ~/Projects/git-setdate && pipsi install --python $python3 --editable .) 26 | (cd ~/Projects/important-bits && pipsi install --python $python2 --editable .) 27 | 28 | # Unreleased (newer) version of s3cmd 29 | # pipsi install --python $python2 https://pypi.python.org/packages/source/s/s3cmd/s3cmd-1.5.0-alpha3.tar.gz#egg=s3cmd 30 | 31 | # Upgrade all pip versions 32 | for pip in ~/.local/venvs/*/bin/pip; do 33 | eval $pip install --upgrade pip 34 | done 35 | -------------------------------------------------------------------------------- /bin/pipsi-reinstall: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # Remove all stuff pipsi leaves behind 5 | # It puts all venvs inside ~/.local/venvs, and symlinks binaries from ~/.local/bin 6 | # Let's only remove the binaries that are pointing to these pipsi "venvs", so 7 | # we don't remove stuff that isn't pipsi's 8 | pipsi_bins() { 9 | find ~/.local/bin -maxdepth 1 -type l | \ 10 | while read f; do 11 | echo "$f,$(readlink "$f")" 12 | done | \ 13 | grep -Ee '\.local/venvs' | \ 14 | cut -d, -f1 15 | } 16 | 17 | rm -rf $(pipsi_bins) ~/.local/venvs 18 | curl https://raw.githubusercontent.com/nvie/pipsi/master/get-pipsi.py | python3 19 | 20 | pipsi-all-the-things 21 | -------------------------------------------------------------------------------- /bin/quote: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Required parameters: 4 | # @raycast.schemaVersion 1 5 | # @raycast.title Quote (for Markdown) 6 | # @raycast.mode silent 7 | 8 | # Optional parameters: 9 | # @raycast.icon 📋 10 | 11 | # Documentation: 12 | # @raycast.description Quotes clipboard contents (for Markdown) 13 | # @raycast.author Vincent Driessen 14 | # @raycast.authorURL https://twitter.com/nvie 15 | 16 | pbpaste | sed -Ee 's/^/> /' | pbcopy 17 | -------------------------------------------------------------------------------- /bin/remove-dist-tags: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | if [ "$1" = "beta" -o "$1" = "latest" -o -z "$1" ]; then 5 | echo "Specify a valid tag name." >&2 6 | echo "" >&2 7 | echo "Usage:" >&2 8 | echo " remove-dist-tags " >&2 9 | echo "" >&2 10 | exit 2 11 | fi 12 | 13 | echo "OTP?" 14 | read otp 15 | 16 | set +e 17 | npm dist-tag rm --otp "$otp" "@liveblocks/yjs" "$1" || false 18 | npm dist-tag rm --otp "$otp" "@liveblocks/zustand" "$1" || false 19 | npm dist-tag rm --otp "$otp" "@liveblocks/redux" "$1" || false 20 | npm dist-tag rm --otp "$otp" "@liveblocks/react" "$1" || false 21 | npm dist-tag rm --otp "$otp" "@liveblocks/client" "$1" || false 22 | npm dist-tag rm --otp "$otp" "@liveblocks/core" "$1" || false 23 | set -e 24 | -------------------------------------------------------------------------------- /bin/rsort-clipboard: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Required parameters: 4 | # @raycast.schemaVersion 1 5 | # @raycast.title Reverse-sort clipboard contents 6 | # @raycast.mode silent 7 | 8 | # Optional parameters: 9 | # @raycast.icon 📋 10 | 11 | # Documentation: 12 | # @raycast.description Reverse-sort clipboard contents 13 | # @raycast.author Vincent Driessen 14 | # @raycast.authorURL https://twitter.com/nvie 15 | 16 | pbpaste | sort -r | pbcopy 17 | -------------------------------------------------------------------------------- /bin/rstrip: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | 4 | 5 | def main(): 6 | for line in sys.stdin: 7 | print(line.rstrip()) 8 | 9 | 10 | if __name__ == '__main__': 11 | main() 12 | -------------------------------------------------------------------------------- /bin/set-bg-color: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | R=${1:-0} 3 | G=${2:-24} 4 | B=${3:-30} 5 | 6 | RR=$(echo "scale=2; $R*201.5" | bc) 7 | GG=$(echo "scale=2; $G*201.5" | bc) 8 | BB=$(echo "scale=2; $B*201.5" | bc) 9 | # ^^^^^ 10 | # NOTE: This weird constant found through 11 | # trial-and-error. Don't ask. 12 | 13 | osascript <);' 3 | -------------------------------------------------------------------------------- /bin/smart-pattern: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | # 5 | # This makes comby pattern writing a lot easier! 6 | # 7 | 8 | boundary="§§" 9 | space=" " 10 | varstart="§@" 11 | varend="@§" 12 | 13 | mask_comby_vars () { 14 | sed -Ee 's/:[[]([[:alnum:]]+)[]]/'"$varstart"'\1'"$varend"'/g' 15 | } 16 | 17 | # This will strip whitespace in the pattern itself, i.e. to make 18 | # the following all equivalent patterns: 19 | # 20 | # - foo(x,y) 21 | # - foo(x , y) 22 | # - foo ( x , y ) 23 | # 24 | strip_whitespace () { 25 | sed -Ee 's/[[:space:]]+/'"$space"'/g' 26 | } 27 | 28 | # This will surround identifiers with word boundaries, so "if 29 | # ( ... )" will only match the keyword `if`, and not a function 30 | # call like `gif()`. 31 | surround_identifiers () { 32 | sed -E \ 33 | -e 's/([[:<:]][[:alnum:]_]+[[:>:]])/'"$boundary"'\1'"$boundary"'/g' \ 34 | -e 's/'"$varstart$boundary"'([[:alnum:]_]+)'"$boundary$varend"'/'"$varstart"'\1'"$varend"'/g' 35 | } 36 | 37 | # This will translate a pattern like `foo(x, y)` into `foo(x, y)` 38 | surround_punctuation () { 39 | sed -Ee 's/([][()<>,;:^&*!.])/'"$space"'\1'"$space"'/g' 40 | } 41 | 42 | replace_boundaries () { 43 | sed -Ee 's/('"$boundary"')+/'":[~\\\\b]"'/g' 44 | } 45 | 46 | replace_whitespace () { 47 | sed -Ee 's/('"$space"')+/'":[~\\\\s*]"'/g' 48 | } 49 | 50 | replace_vars () { 51 | sed -E \ 52 | -e 's/('"$varstart"')/:[/g' \ 53 | -e 's/('"$varend"')/]/g' 54 | } 55 | 56 | echo "$1" \ 57 | | mask_comby_vars \ 58 | | strip_whitespace \ 59 | | surround_identifiers \ 60 | | surround_punctuation \ 61 | | replace_vars \ 62 | | replace_boundaries \ 63 | | replace_whitespace 64 | -------------------------------------------------------------------------------- /bin/sort-clipboard: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Required parameters: 4 | # @raycast.schemaVersion 1 5 | # @raycast.title Sort clipboard contents 6 | # @raycast.mode silent 7 | 8 | # Optional parameters: 9 | # @raycast.icon 📋 10 | 11 | # Documentation: 12 | # @raycast.description Sort clipboard contents 13 | # @raycast.author Vincent Driessen 14 | # @raycast.authorURL https://twitter.com/nvie 15 | 16 | pbpaste | sort | pbcopy 17 | -------------------------------------------------------------------------------- /bin/strip-indents: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import string 4 | 5 | 6 | def get_indent(line): 7 | for col, char in enumerate(line): 8 | if char not in string.whitespace: 9 | return col 10 | raise RuntimeError('Unexpected situation.') 11 | 12 | 13 | def get_indentation_level(lines): 14 | return min([get_indent(line) for line in lines if line]) 15 | 16 | 17 | def strip_indents(lines, level): 18 | for line in lines: 19 | yield line[level:] 20 | 21 | 22 | def main(): 23 | # Read stdin into memory 24 | lines = [line.rstrip() for line in sys.stdin] 25 | level = get_indentation_level(lines) 26 | for line in strip_indents(lines, level): 27 | print line 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /bin/test-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | # Ensure this script can assume it's run from the repo's 5 | # root directory, even if the current working directory is 6 | # different. 7 | ROOT="$HOME/Projects/liveblocks/liveblocks" 8 | if [ "$(pwd)" != "$ROOT" ]; then 9 | ( cd "$ROOT" && exec "$0" "$@" ) 10 | exit $? 11 | fi 12 | 13 | err () { 14 | echo "$@" >&2 15 | } 16 | 17 | usage () { 18 | err "usage: test-all.sh [-hpec]" 19 | err 20 | err "Runs test suites." 21 | err 22 | err "Options:" 23 | err "-h Show this help" 24 | err "-p Run tests for all packages" 25 | err "-e Run E2E tests (slow)" 26 | err "-c Run Cloudflare tests (slow)" 27 | } 28 | 29 | run_packages=0 30 | run_e2e=0 31 | run_cloudflare=0 32 | while getopts hpec flag; do 33 | case "$flag" in 34 | p) run_packages=1 ;; 35 | e) run_e2e=1 ;; 36 | c) run_cloudflare=1 ;; 37 | *) usage; exit 2;; 38 | esac 39 | done 40 | shift $(($OPTIND - 1)) 41 | 42 | if [ "$run_packages" -eq 0 -a "$run_e2e" -eq 0 -a "$run_cloudflare" -eq 0 ]; then 43 | usage 44 | exit 1 45 | fi 46 | 47 | CLOUDFLARE_ROOT="$HOME/Projects/liveblocks/liveblocks-cloudflare" 48 | 49 | test_client () { 50 | chronic npm install 51 | chronic node_modules/.bin/tsc --noEmit 52 | chronic node_modules/.bin/eslint src 53 | chronic node_modules/.bin/jest 54 | } 55 | 56 | test_secondary_pkg () { 57 | chronic link-liveblocks.sh 58 | chronic node_modules/.bin/tsc --noEmit 59 | chronic node_modules/.bin/eslint src 60 | chronic node_modules/.bin/jest 61 | npm run build 62 | } 63 | 64 | test_cloudflare () { 65 | rm -rf node_modules 66 | chronic npm install 67 | chronic "$ROOT/scripts/link-liveblocks.sh" 68 | node_modules/.bin/tsc 69 | npm run test-ci 70 | } 71 | 72 | test_e2e () { 73 | rm -rf node_modules .next 74 | chronic npm install 75 | chronic link-liveblocks.sh 76 | npm run test 77 | } 78 | 79 | err_context () { 80 | err "^^^ Errors happened in $1" 81 | exit 2 82 | } 83 | 84 | # Clear all builds 85 | rm -rf "$ROOT/packages/liveblocks-"*"/{lib,node_modules}" 86 | rm -rf "$ROOT/e2e/next-sandbox/{lib,node_modules,.next}" 87 | 88 | if [ "$run_packages" -eq 1 ]; then 89 | err "" 90 | err "===== @liveblocks/client =====================================================" 91 | ( cd packages/liveblocks-client && test_client ) || err_context "liveblocks-client" 92 | 93 | err "" 94 | err "===== @liveblocks/react ======================================================" 95 | ( cd packages/liveblocks-react && test_secondary_pkg ) || err_context "liveblocks-react" 96 | 97 | err "" 98 | err "===== @liveblocks/redux ======================================================" 99 | ( cd packages/liveblocks-redux && test_secondary_pkg ) || err_context "liveblocks-redux" 100 | 101 | err "" 102 | err "===== @liveblocks/zustand ====================================================" 103 | ( cd packages/liveblocks-zustand && test_secondary_pkg ) || err_context "liveblocks-zustand" 104 | else 105 | err "==> Skipping package tests" 106 | fi 107 | 108 | if [ "$run_cloudflare" -eq 1 ]; then 109 | err "" 110 | err "===== liveblocks-cloudflare ==================================================" 111 | ( cd "$CLOUDFLARE_ROOT" && test_cloudflare ) || err_context "liveblocks-cloudflare" 112 | else 113 | err "==> Skipping Cloudflare tests" 114 | fi 115 | 116 | if [ "$run_e2e" -eq 1 ]; then 117 | err "" 118 | err "===== Liveblocks E2E test suite ==============================================" 119 | ( cd e2e/next-sandbox && test_e2e ) || err_context "next-sandbox" 120 | else 121 | err "==> Skipping E2E tests" 122 | fi 123 | -------------------------------------------------------------------------------- /bin/touchx: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | touch "$1" && chmod +x "$1" 3 | -------------------------------------------------------------------------------- /bin/treediff: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | dir1="$1" 3 | dir2="$2" 4 | 5 | if [ ! -d "$dir1" ]; then 6 | echo "Directory $dir1 does not exist." 7 | exit 2 8 | fi 9 | 10 | if [ ! -d "$dir2" ]; then 11 | echo "Directory $dir2 does not exist." 12 | exit 2 13 | fi 14 | 15 | listfiles () { 16 | (cd "$1"; find . -type f) | sort -f 17 | } 18 | 19 | diff -u <(listfiles "$dir1") <(listfiles "$dir2") 20 | -------------------------------------------------------------------------------- /bin/tsc-limit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | if [ $# -ge 1 -a "$1" -eq "$1" ] 2>/dev/null; then 5 | # ^^^^^^^^^^^^^ Checks if this is a valid number 6 | max=$1 7 | shift 8 | else 9 | max=1 10 | fi 11 | 12 | tsc --pretty --noEmit "$@" | awk -v max=$max ' 13 | BEGIN { num = 0; } 14 | /TS[0-9]+:/ { num++ } 15 | num <= max { print $0 } 16 | ' 17 | -------------------------------------------------------------------------------- /bin/uniq-clipboard: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Required parameters: 4 | # @raycast.schemaVersion 1 5 | # @raycast.title Sort + de-dupe clipboard contents 6 | # @raycast.mode silent 7 | 8 | # Optional parameters: 9 | # @raycast.icon 📋 10 | 11 | # Documentation: 12 | # @raycast.description Sort + de-dupe clipboard contents 13 | # @raycast.author Vincent Driessen 14 | # @raycast.authorURL https://twitter.com/nvie 15 | 16 | pbpaste | sort -u | pbcopy 17 | -------------------------------------------------------------------------------- /bin/unquote: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Required parameters: 4 | # @raycast.schemaVersion 1 5 | # @raycast.title Unquote (from Markdown) 6 | # @raycast.mode silent 7 | 8 | # Optional parameters: 9 | # @raycast.icon 📋 10 | 11 | # Documentation: 12 | # @raycast.description Unquote clipboard contents (from Markdown) 13 | # @raycast.author Vincent Driessen 14 | # @raycast.authorURL https://twitter.com/nvie 15 | 16 | pbpaste | sed -Ee 's/^> //' | pbcopy 17 | -------------------------------------------------------------------------------- /bin/unsmart-quotes: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | 4 | def unsmart_quotes(s): 5 | replace_table = { 6 | u"\u2018": "'", 7 | u"\u2019": "'", 8 | u"\u201c": '"', 9 | u"\u201d": '"', 10 | } 11 | for k, v in replace_table.items(): 12 | s = s.replace(k, v) 13 | return s 14 | 15 | 16 | def main(): 17 | contents = sys.stdin.read() 18 | print(unsmart_quotes(contents.decode('utf-8')).encode('utf-8')) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | --------------------------------------------------------------------------------