├── .gitignore ├── .gitmodules ├── .pre-commit-config.yaml ├── Brewfile.all ├── Brewfile.ayla ├── Brewfile.fonts ├── Brewfile.hejmo ├── Brewfile.lusankya ├── Brewfile.macos ├── Brewfile.penguin ├── Makefile ├── README.md ├── Vagrantfile ├── _helpers.sh ├── apm.list ├── bash_profile ├── 00_ansi_color_helpers.sh ├── 00_path.sh ├── 01_brew_env.sh ├── 01_pyenv.sh ├── 01_strings.sh ├── 02_navigation.sh ├── 02_upsearch.sh ├── 50_iterm_integration.sh ├── 50_ls.sh ├── 70_editors.sh ├── 99_bat.sh ├── 99_chromecast.sh ├── 99_completions.sh ├── 99_conda.sh ├── 99_conscript.sh ├── 99_converters.sh ├── 99_fzf.sh ├── 99_git.sh ├── 99_gradle.sh ├── 99_hashing.sh ├── 99_history.sh ├── 99_jira-cli.sh ├── 99_kitty.sh ├── 99_kubectl.sh ├── 99_mamba.sh ├── 99_man_colors.sh ├── 99_node_version_manager.sh ├── 99_prompt.sh ├── 99_ruby.sh ├── 99_rust.sh ├── 99_ssh_aliases.sh ├── 99_travis.sh ├── 99_urls.sh ├── 99_z.sh ├── 99_zoom.sh ├── 99_zzz_env_local.sh └── 99_zzz_fix_prompt.sh ├── dotfiles ├── ackrc ├── bash_profile ├── bitbar │ └── work │ │ ├── hours.1m.sh │ │ └── pomodoro2.30s.sh ├── gemrc ├── gitattributes ├── gitconfig ├── gitignore_global ├── hammerspoon │ ├── README.md │ ├── anycomplete.lua │ ├── init.lua │ ├── type.lua │ └── window_mgmt.lua ├── irbrc ├── pryrc ├── rvmrc ├── tmux.conf ├── vim │ ├── airline.vim │ ├── autoload │ │ ├── plug.vim │ │ ├── scss_indent.vim │ │ └── xmlformatter.vim │ ├── bundles.vim │ └── update-plug.sh └── vimrc ├── install-via-coursier.sh ├── iterm ├── Brewfile.iterm ├── Zenburn.itermcolors └── com.googlecode.iterm2.plist ├── link_dotbin.sh ├── link_dotfiles.sh ├── rebuild_bat_config.sh ├── scripts ├── $ ├── 401k_contribution_calc ├── _t_completion ├── add-coursier ├── analyze_t ├── bigtext ├── cb ├── clapify ├── claps ├── clipboard ├── docker-digest ├── docker-image-size-compressed ├── docker-image-size-uncompressed ├── docker-select-tag ├── docker-whoami ├── dtmfplay ├── duration_comparison.py ├── external-ip ├── extract-ips ├── fileweight ├── find-pi ├── flush-dns ├── fraktur ├── frinkconv ├── getline ├── gh-provision-known-hosts ├── gh_token ├── gif-every-other-frame ├── gif2mp4 ├── git-bechdel ├── git-committers-per-file ├── git-file-size-diff ├── git-log-json ├── git-prebase ├── git-todo ├── imgcat ├── json2yaml ├── json_to_yaml_b64.py ├── jwttool ├── kill-tuntaposx ├── killport ├── lines-to-markdown-num ├── list ├── list-shellscripts ├── list2csv ├── listops ├── lobsters ├── log_all_output ├── mailservers ├── make-icons ├── man2pdf ├── md5sum ├── netrc-tools ├── neuron ├── noproxy ├── notifyme ├── now ├── pin_cores ├── plug ├── pypi-get-deps ├── pypi-get-sdist ├── pypi-wheels-list ├── ramdisk-create ├── ramdisk-list ├── reset-osx-camera ├── routes ├── runtime-deps-from-effective-pom ├── rvm-mount-brew ├── rvm-mount-brew-ruby ├── screenshot_cleanup.rb ├── seconds_between.py ├── serve ├── set-hostname ├── sleep_utils.sh ├── spacify ├── speedup ├── split-clip ├── spongebob ├── ssh-copy-id ├── ssh-copy-pub-to-clipboard ├── sshvnc ├── ssid ├── t ├── tabname ├── time_in_tzs ├── use-brewed-bash ├── vagrant-scp ├── vagrant-ssh ├── volume ├── weather ├── whatports ├── whereami ├── widetext ├── wordle-brute-force └── yaml2json ├── setup-alacritty.sh ├── setup-apm.sh ├── setup-bash.sh ├── setup-codespaces.sh ├── setup-debian-derivs.sh ├── setup-docker-linux.sh ├── setup-homebrew.sh ├── setup-internal-proxy.sh ├── setup-iterm.sh ├── setup-mac.sh ├── setup-ruby.sh ├── setup-rust.sh ├── themes └── Zenburn.itermcolors └── windows ├── AutoHotkey.ahk ├── README.md ├── install-allpurposes.ps1 ├── install-chocolatey.ps1 ├── install-desktop.ps1 ├── install-development.ps1 ├── install-gaming.ps1 ├── install-mystack.ps1 └── install-scoop.ps1 /.gitignore: -------------------------------------------------------------------------------- 1 | dotfiles/gitconfig 2 | dotfiles/vim/view 3 | .vagrant 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colindean/hejmo/51743d3474e0bb49fe09d60cab097663faca36e5/.gitmodules -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/sirwart/ripsecrets.git 3 | # use v0.1.6 when it's out 4 | rev: v0.1.9 5 | hooks: 6 | - id: ripsecrets-system 7 | - repo: https://github.com/jumanjihouse/pre-commit-hooks 8 | rev: 3.0.0 9 | hooks: 10 | - id: shellcheck 11 | - id: shfmt 12 | - repo: https://github.com/executablebooks/mdformat 13 | rev: 0.7.22 14 | hooks: 15 | - id: mdformat 16 | additional_dependencies: 17 | - mdformat-black 18 | - mdformat-config 19 | - mdformat-deflist 20 | - mdformat-frontmatter 21 | - mdformat-footnote 22 | - mdformat-gfm 23 | - mdformat-tables 24 | 25 | ci: 26 | skip: 27 | - ripsecrets-system 28 | - shellcheck 29 | - shfmt 30 | -------------------------------------------------------------------------------- /Brewfile.all: -------------------------------------------------------------------------------- 1 | # vim: ft=ruby 2 | tap 'colindean/personal' 3 | 4 | # gotta use bash 5 | brew 'bash' 6 | brew 'bash-completion@2' 7 | 8 | # alternative cat that does syntax highlighting 9 | brew 'bat' 10 | 11 | # better git diff/patch output 12 | brew 'git-delta' 13 | 14 | # gnu coreutils, mostly for GNU date 15 | brew 'coreutils' 16 | 17 | # Esperanto character conversion 18 | brew 'eoconv' 19 | 20 | # fuzzy finder 21 | brew 'fzf' 22 | 23 | # better cd with z 24 | brew 'zoxide' 25 | 26 | # disk usage utility 27 | brew 'diskus' 28 | -------------------------------------------------------------------------------- /Brewfile.fonts: -------------------------------------------------------------------------------- 1 | # vim: ft=ruby 2 | 3 | tap 'homebrew/cask-fonts' 4 | 5 | cask 'font-fira-code' 6 | cask 'font-fira-code-nerd-font' 7 | cask 'font-noto-mono' 8 | cask 'font-noto-mono-for-powerline' 9 | cask 'font-noto-sans' 10 | cask 'font-noto-serif' 11 | cask 'font-open-sans' 12 | cask 'font-libre-franklin' 13 | -------------------------------------------------------------------------------- /Brewfile.hejmo: -------------------------------------------------------------------------------- 1 | # This is for stuff required to work on these scripts 2 | # vim: ft=ruby 3 | 4 | brew "shfmt" 5 | brew "shellcheck" 6 | brew "pre-commit" 7 | brew "make" 8 | brew "ripsecrets" 9 | 10 | -------------------------------------------------------------------------------- /Brewfile.lusankya: -------------------------------------------------------------------------------- 1 | # vim: ft=ruby 2 | 3 | tap 'homebrew/cask' 4 | tap 'homebrew/cask-fonts' 5 | tap 'homebrew/cask-versions' 6 | tap 'colindean/fonts-nonfree' 7 | tap 'coursier/formulas' 8 | 9 | # needed for basically everything, might as well install it 10 | cask 'adoptopenjdk' 11 | # quick screen recording 12 | cask 'licecap' 13 | # IDE for Scala and Java development 14 | cask 'intellij-idea' 15 | 16 | # video conferencing 17 | unless Dir.exist? "/Applications/zoom.us.app" 18 | cask 'zoom' 19 | end 20 | 21 | # macos trash from cli 22 | brew 'trash' 23 | 24 | # journaling 25 | brew 'jrnl' 26 | 27 | # postscript stuff, used for man2pdf 28 | brew 'ghostscript' 29 | 30 | # used for menu bar stuff like time tracking 31 | cask 'xbar' 32 | 33 | # alternative cat that does syntax highlighting 34 | brew 'bat' 35 | 36 | # mac app store apps 37 | #brew 'mas' 38 | #begin 39 | # mas 'Trello', id: 1278508951 40 | #rescue 41 | # echo "mas is unavailable, skipping Mac App Store apps" 42 | #end 43 | 44 | # a better find, use like "fd PATTERN" 45 | brew 'fd' 46 | 47 | # scala dependency retriever and bootstrap setup 48 | #brew 'coursier/formulas/coursier' 49 | 50 | # shell code linting 51 | brew 'shellcheck' 52 | 53 | # packages 54 | brew 'ack' 55 | brew 'aha' 56 | brew 'ant' 57 | brew 'archey' 58 | brew 'aria2' 59 | brew 'aspell' 60 | brew 'gettext' 61 | brew 'libffi' 62 | brew 'pcre' 63 | brew 'glib' 64 | brew 'fontconfig' 65 | brew 'pixman' 66 | brew 'cairo' 67 | brew 'curl' 68 | brew 'git' 69 | brew 'pkg-config' 70 | brew 'gdbm' 71 | brew 'readline' 72 | brew 'gobject-introspection' 73 | brew 'atk' 74 | brew 'autoconf' 75 | brew 'automake' 76 | brew 'bash' 77 | brew 'bash-completion@2' 78 | brew 'bison' 79 | brew 'boost' 80 | brew 'boost-python' 81 | brew 'cabal-install' 82 | brew 'cmake' 83 | brew 'colordiff' 84 | brew 'cowsay' 85 | brew 'dialog' 86 | brew 'diff-so-fancy' 87 | brew 'docker-completion' 88 | brew 'docker-compose-completion' 89 | brew 'docker-machine-completion' 90 | brew 'dos2unix' 91 | brew 'jpeg' 92 | brew 'wxmac' 93 | brew 'elixir' 94 | brew 'emacs' 95 | brew 'lame' 96 | brew 'xvid' 97 | brew 'ffmpeg' 98 | brew 'gd' 99 | brew 'gdk-pixbuf' 100 | brew 'gdub' 101 | brew 'gist' 102 | brew 'glew' 103 | brew 'gmp' 104 | brew 'gnu-getopt' 105 | brew 'gnu-sed' 106 | brew 'lua' 107 | brew 'gnuplot' 108 | brew 'go' 109 | brew 'sdl2' 110 | brew 'sdl2_image' 111 | brew 'gource' 112 | brew 'gradle' 113 | brew 'libtool' 114 | brew 'graphviz' 115 | brew 'hicolor-icon-theme' 116 | brew 'pango' 117 | brew 'gtk+' 118 | brew 'htop' 119 | brew 'hub' 120 | brew 'perl' 121 | brew 'imagemagick' 122 | brew 'intltool' 123 | brew 'jbig2dec' 124 | brew 'jo' 125 | brew 'oniguruma' 126 | brew 'jq' 127 | brew 'ledger' 128 | brew 'leiningen' 129 | brew 'libarchive' 130 | brew 'libcroco' 131 | brew 'libevent' 132 | brew 'libgpg-error' 133 | brew 'libksba' 134 | brew 'librsvg' 135 | brew 'libssh' 136 | brew 'libssh2' 137 | brew 'libvo-aacenc' 138 | brew 'libyaml' 139 | brew 'lnav' 140 | brew 'lynx' 141 | brew 'makedepend' 142 | brew 'maven-completion' 143 | brew 'mercurial' 144 | brew 'mobile-shell' 145 | brew 'tokyo-cabinet' 146 | brew 'mutt' 147 | brew 'mvnvm' 148 | brew 'mysql-connector-c' 149 | brew 'nmap' 150 | brew 'node' 151 | brew 'ragel' 152 | brew 'ohcount' 153 | brew 'openjpeg' 154 | brew 'p7zip' 155 | brew 'pandoc' 156 | brew 'parallel' 157 | brew 'pbzip2' 158 | brew 'plantuml' 159 | brew 'pngcrush' 160 | brew 'poppler' 161 | brew 'qt' 162 | brew 'sip' 163 | brew 'pyqt' 164 | brew 'ripgrep' 165 | brew 'ruby' 166 | brew 'sbt' 167 | brew 'scala' 168 | brew 'scrypt' 169 | brew 'sl' 170 | brew 'spark' 171 | brew 'sshtrix' 172 | brew 'tig' 173 | brew 'tmux' 174 | brew 'tree' 175 | brew 'typespeed' 176 | brew 'unixodbc' 177 | brew 'utf8proc' 178 | brew 'vagrant-completion' 179 | brew 'vim' 180 | brew 'watch' 181 | brew 'wemux' 182 | brew 'wget' 183 | brew 'xmlstarlet' 184 | 185 | -------------------------------------------------------------------------------- /Brewfile.macos: -------------------------------------------------------------------------------- 1 | # vim: ft=ruby 2 | if OS.mac? 3 | # better launcher, license key in Drive 4 | cask 'alfred' 5 | 6 | # text editor 7 | cask 'atom' 8 | 9 | # inhibit screensaver 10 | cask 'keepingyouawake' 11 | 12 | # image editing 13 | cask 'gimp' 14 | 15 | # window management 16 | cask 'hammerspoon' 17 | 18 | # pane management 19 | cask 'hyperswitch' 20 | 21 | # google play music 22 | cask 'marshallofsound-google-play-music-player' 23 | 24 | # network tunnels 25 | cask 'ngrok' 26 | 27 | # better screencast recording, also, streaming 28 | cask 'obs' 29 | 30 | # quicklook plugins I cannot live without 31 | cask "qlcolorcode" 32 | cask "qlmarkdown" 33 | cask "qlprettypatch" 34 | cask "qlstephen" 35 | 36 | # set default email app 37 | cask 'swiftdefaultappsprefpane' 38 | 39 | -------------------------------------------------------------------------------- /Brewfile.penguin: -------------------------------------------------------------------------------- 1 | # Mobility workstation 2 | tap "homebrew/bundle" 3 | tap "homebrew/core" 4 | brew "curl" 5 | brew "fastmod" 6 | brew "fd" 7 | brew "fzf" 8 | brew "git" 9 | brew "pandoc" 10 | brew "pandoc-crossref" 11 | brew "pngcrush" 12 | brew "pre-commit" 13 | brew "ripsecrets" 14 | brew "st" 15 | brew "svgo" 16 | brew "tectonic" 17 | brew "tig" 18 | brew "webp" 19 | brew "zoxide" 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: deps 2 | deps: .pre-commit-config.yaml 3 | brew bundle --file=Brewfile.hejmo --no-lock 4 | pre-commit install 5 | pre-commit install-hooks 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # colindean's Home Directory Stuff 2 | 3 | Abandon all hope, ye who enter here. 4 | 5 | If something gets committed here that you think probably shouldn't be committed 6 | here, please be a friend and tell me. I'll probably toss a few satoshis your 7 | way. 8 | 9 | ## Quickstart on a new machine 10 | 11 | I usually put this into `mkdir ~/Source/Personal` on my work machine or into `mkdir ~/Source/` on a personal machine. 12 | 13 | ```bash 14 | mkdir -p ~/Source/Personal && cd ~/Source/Personal && \ 15 | git clone https://github.com/colindean/hejmo.git && cd hejmo 16 | bash link_dotbin.sh && \ 17 | bash link_dotfiles.sh && \ 18 | bash setup-homebrew.sh 19 | 20 | source ~/.bash_profile # or restart the terminal process 21 | 22 | brew bundle --file=Brewfile.all && \ 23 | brew bundle --file=Brewfile.${INTENDED_HOSTNAME:-$(hostname)} && \ 24 | git remote set-url origin git@github.com:colindean/hejmo.git 25 | ``` 26 | 27 | On Linux only: 28 | 29 | ``` 30 | bash setup-debian-derivs.sh && bash setup-docker-linux.sh 31 | ``` 32 | 33 | On macOS only: 34 | 35 | ``` 36 | bash setup-iterm.sh && bash setup-mac.sh 37 | ``` 38 | 39 | Then handle some standard tooling updates: 40 | 41 | ``` 42 | plug install && plug update # install vim plugins with plug helper 43 | ``` 44 | 45 | And when I need them: 46 | 47 | ``` 48 | bash setup-rust.sh && \ 49 | bash setup-ruby.sh 50 | ``` 51 | 52 | You will see errors about: 53 | 54 | - `__git_ps1` until both `git` and `bash-completion` are installed (from apt or Homebrew) 55 | - `hub` until hub is install from Homebrew 56 | 57 | ## Things to copy 58 | 59 | These files diverge quickly, so I don't version them and instead copypaste them when necessary. Maybe others will find them to be a useful starting point! 60 | 61 | ### `~/.ssh/config` 62 | 63 | Run `mkdir -p ~/.ssh/controls` first and then put this content into the above file: 64 | 65 | ``` 66 | Host * 67 | UseRoaming no 68 | Protocol 2 69 | Compression yes 70 | ControlMaster auto 71 | ControlPath ~/.ssh/controls/sshcontrol-%r@%h:%p 72 | ``` 73 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure('2') do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://vagrantcloud.com/search. 15 | config.vm.box = 'https://vagrant-osx.nyc3.digitaloceanspaces.com/osx-sierra-0.3.1.box' 16 | 17 | # Disable automatic box update checking. If you disable this, then 18 | # boxes will only be checked for updates when the user runs 19 | # `vagrant box outdated`. This is not recommended. 20 | # config.vm.box_check_update = false 21 | 22 | # Create a forwarded port mapping which allows access to a specific port 23 | # within the machine from a port on the host machine. In the example below, 24 | # accessing "localhost:8080" will access port 80 on the guest machine. 25 | # NOTE: This will enable public access to the opened port 26 | # config.vm.network "forwarded_port", guest: 80, host: 8080 27 | 28 | # Create a forwarded port mapping which allows access to a specific port 29 | # within the machine from a port on the host machine and only allow access 30 | # via 127.0.0.1 to disable public access 31 | # config.vm.network "forwarded_port", 32 | # guest: 80, host: 8080, host_ip: "127.0.0.1" 33 | 34 | # Create a private network, which allows host-only access to the machine 35 | # using a specific IP. 36 | # config.vm.network "private_network", ip: "192.168.33.10" 37 | 38 | # Create a public network, which generally matched to bridged network. 39 | # Bridged networks make the machine appear as another physical device on 40 | # your network. 41 | # config.vm.network "public_network" 42 | 43 | # Share an additional folder to the guest VM. The first argument is 44 | # the path on the host to the actual folder. The second argument is 45 | # the path on the guest to mount the folder. And the optional third 46 | # argument is a set of non-required options. 47 | # config.vm.synced_folder "../data", "/vagrant_data" 48 | # 49 | 50 | config.vm.synced_folder '.', '/vagrant', 51 | id: 'core', 52 | nfs: true, 53 | mount_options: ['nolock,vers=3,udp,noatime'] 54 | 55 | # Provider-specific configuration so you can fine-tune various 56 | # backing providers for Vagrant. These expose provider-specific options. 57 | # Example for VirtualBox: 58 | # 59 | # config.vm.provider "virtualbox" do |vb| 60 | # # Display the VirtualBox GUI when booting the machine 61 | # vb.gui = true 62 | # 63 | # # Customize the amount of memory on the VM: 64 | # vb.memory = "1024" 65 | # end 66 | # 67 | # View the documentation for the provider you are using for more 68 | # information on available options. 69 | 70 | # Enable provisioning with a shell script. Additional provisioners such as 71 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the 72 | # documentation for more information about their specific syntax and use. 73 | # config.vm.provision "shell", inline: <<-SHELL 74 | # apt-get update 75 | # apt-get install -y apache2 76 | # SHELL 77 | end 78 | -------------------------------------------------------------------------------- /_helpers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | command_exists() { 4 | local cmd="$1" 5 | command -v "${cmd}" >/dev/null 2>&1 6 | } 7 | 8 | install_homebrew() { 9 | local homebrew_installer_url="https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh" 10 | 11 | command_exists "curl" 12 | curl_exists=$? 13 | if [[ $curl_exists -ne 0 ]]; then 14 | if [[ -n "$(command -v "apt")" ]]; then 15 | sudo apt install curl 16 | else 17 | echo >&2 "curl isn't available. What's up?" 18 | exit 2 19 | fi 20 | fi 21 | 22 | bash -c "$(curl -fsSL ${homebrew_installer_url})" 23 | } 24 | 25 | install_packages() { 26 | local listfile="$1" 27 | local cmd_template="$2" 28 | oldifs="${IFS}" 29 | IFS=$'\n' 30 | 31 | failed=() 32 | for package in `cat ${listfile}`; do 33 | local clean_package=$(echo ${package} | sed -e 's/\//\\\//g') 34 | local cmd=$(echo "${cmd_template}" | sed -e "s/\%PACKAGE\%/${clean_package}/g") 35 | eval $cmd 36 | if [[ $? -ne 0 ]]; then 37 | failed+=("$package") 38 | fi 39 | done 40 | IFS="${oldifs}" 41 | if [[ ${#failed[@]} -gt 0 ]]; then 42 | echo "These packages failed to install:" 43 | printf "\t%s\n" "${failed[@]}" 44 | echo "You can to rerun this script until this message disappears." 45 | echo "Inspect the transcript to find more exact errors." 46 | fi 47 | } 48 | 49 | # from_dir must be an absolute path! 50 | link_all_files_in_dir() { 51 | from_dir="$1" 52 | to_dir="$2" 53 | rm="$3" 54 | prepend="$4" 55 | 56 | case "$(uname -s)" in 57 | Darwin) LN_OPTIONS="sFf" ;; 58 | Linux) LN_OPTIONS="sf" ;; 59 | # TODO: determine safe defaults for OSes I never use 60 | *) LN_OPTIONS="sf" ;; 61 | esac 62 | 63 | for f in $(ls "${from_dir}"); do 64 | TARGET="${from_dir}/${f}" 65 | LINK="${to_dir}/${prepend}${f}" 66 | if [[ ! -z $rm ]]; then 67 | echo "Removing ${LINK}" 68 | rm -f "${LINK}" 69 | fi 70 | echo "Linking ${LINK} to ${TARGET}" 71 | ln -sFf "${TARGET}" "${LINK}" 72 | done 73 | } 74 | 75 | banner_text() { 76 | local text="${@}" 77 | printf "\033#3%s\n" "${text}" 78 | printf "\033#4%s\n" "${text}" 79 | printf "\033#5" 80 | } 81 | -------------------------------------------------------------------------------- /apm.list: -------------------------------------------------------------------------------- 1 | Zen 2 | atomatigit 3 | execute-as-ruby 4 | git-plus 5 | html2haml 6 | language-docker 7 | language-haml 8 | language-latex 9 | language-lua 10 | language-rust 11 | language-scala 12 | language-plantuml 13 | linter-clojure 14 | linter-lua 15 | markdown-writer 16 | ruby-bundler 17 | zenburn 18 | editorconfig 19 | -------------------------------------------------------------------------------- /bash_profile/00_path.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | function join { 3 | local IFS="$1" 4 | shift 5 | echo "$*" 6 | } 7 | 8 | __determine_brew_path() { 9 | local local_brew_path 10 | 11 | if [[ -d "${HOME}/.linuxbrew" ]]; then 12 | local_brew_path="${HOME}/.linuxbrew" 13 | elif [[ -d "$(dirname "${HOME}")/linuxbrew/.linuxbrew" ]]; then 14 | local_brew_path="$(dirname "${HOME}")/linuxbrew/.linuxbrew" 15 | elif [[ -f "/usr/local/bin/brew" ]]; then 16 | local_brew_path="/usr/local/" 17 | elif [[ -f "/opt/homebrew/bin/brew" ]]; then 18 | local_brew_path="/opt/homebrew" 19 | fi 20 | 21 | echo "${local_brew_path}" 22 | } 23 | 24 | brew_path="$(__determine_brew_path)" 25 | 26 | # Setup Homebrew as early as possible 27 | eval "$("${brew_path}/bin/brew" shellenv)" 28 | 29 | # Setup PATH 30 | MYPATH=() 31 | ## my scripts 32 | MYPATH+=("${HOME}/.local/bin" "${HOME}/.bin") 33 | ## locally installed stuff, including homebrew 34 | #MYPATH+=('/usr/local/bin:/usr/local/sbin') 35 | 36 | __brew_keg_only_path() { 37 | local formula="${1}" 38 | local bindir="${brew_path}/opt/${formula}/bin" 39 | if [[ -d "${bindir}" ]]; then 40 | printf "%s" "${bindir}" 41 | fi 42 | } 43 | 44 | ## Homebrew keg-only formulae 45 | MYPATH+=("$(__brew_keg_only_path curl)") 46 | MYPATH+=("$(__brew_keg_only_path llvm)") 47 | 48 | ## java 49 | if [[ "Linux" == "$(uname -s)" ]] && [[ -f /bin/update-alternatives ]]; then 50 | # update-alternatives gives ${JAVA_HOME}/jre/bin/java, so we gotta safely traverse upward 51 | if java_ua_output="$(/bin/update-alternatives --query java 2>/dev/null)"; then 52 | JAVA_HOME="$(dirname "$(dirname "$(dirname "$(echo "${java_ua_output}" | grep "^Value" | cut -f 2 -d ' ')")")")" 53 | export JAVA_HOME 54 | fi 55 | elif [[ "Darwin" == "$(uname -s)" ]]; then 56 | # macOS manages Java smartly 57 | export JAVA_HOME=/Library/Java/Home 58 | else 59 | echo "Could not determine JAVA_HOME for $(uname -s) $( (command -v lsb_release >/dev/null && lsb_release -sd) || true) " 60 | fi 61 | if [[ -n "${JAVA_HOME}" ]]; then 62 | MYPATH+=("${JAVA_HOME}/bin") 63 | fi 64 | 65 | ### Ecosystem-specific binary paths 66 | ## rust 67 | MYPATH+=("${HOME}/.cargo/bin") 68 | 69 | ## haskell 70 | MYPATH+=("${HOME}/.cabal/bin") 71 | 72 | ## go 73 | export GOPATH="${HOME}/.go" 74 | MYPATH+=("${GOPATH}/bin") 75 | 76 | ## coursier 77 | COURSIER_BIN_MAC="${HOME}/Library/Application Support/Coursier/bin" 78 | COURSIER_BIN_LINUX="${HOME}/.local/share/coursier/bin" 79 | if [[ -z "${COURSIER_BIN_DIR}" ]]; then 80 | case "$(uname -s)" in 81 | Darwin) 82 | [[ -d "${COURSIER_BIN_MAC}" ]] && COURSIER_BIN_DIR="${COURSIER_BIN_MAC}" 83 | ;; 84 | Linux) 85 | [[ -d "${COURSIER_BIN_LINUX}" ]] && COURSIER_BIN_DIR="${COURSIER_BIN_LINUX}" 86 | ;; 87 | esac 88 | fi 89 | if [[ -n "${COURSIER_BIN_DIR}" ]]; then 90 | MYPATH+=("${COURSIER_BIN_DIR}") 91 | fi 92 | 93 | ## PATHS, ASSEMBLE 94 | JOINED_PATH=$(join : "${MYPATH[@]}") 95 | export PATH=${JOINED_PATH}:${PATH} 96 | -------------------------------------------------------------------------------- /bash_profile/01_brew_env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ "Linux" = "$(uname -s)" ]]; then 4 | export HOMEBREW_CASK_OPTS="--appdir=/dev/null --fontdir=${HOME}/.fonts" 5 | fi 6 | 7 | XDG_DATA_DIRS="$(__determine_brew_path)/share:$XDG_DATA_DIRS" 8 | export XDG_DATA_DIRS 9 | 10 | -------------------------------------------------------------------------------- /bash_profile/01_pyenv.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This used to be in 00_path but I want to time it separately. 4 | 5 | if command -v pyenv >/dev/null; then 6 | eval "$(pyenv init --path)" && 7 | eval "$(pyenv init - "$(basename "${SHELL}")")" 8 | if pyenv virtualenv-init >/dev/null 2>&1; then 9 | eval "$(pyenv virtualenv-init -)" 10 | fi 11 | fi 12 | -------------------------------------------------------------------------------- /bash_profile/01_strings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # string manipulation functions 3 | 4 | # https://stackoverflow.com/a/3352015 5 | function trim() { 6 | local var="${*}" 7 | # read -rd '' var <<<"$var" || : 8 | (($#)) || read -re var 9 | var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters 10 | var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters 11 | echo -n "$var" 12 | } 13 | 14 | alias eo="eoconv --from=post-x --to=utf-8" 15 | -------------------------------------------------------------------------------- /bash_profile/02_navigation.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # directory navigation 3 | 4 | # move up directories quickly instead of cd ../; cd ../; etc/. 5 | # adapted from http://www.bashoneliners.com/oneliners/oneliner/231/ 6 | up() { 7 | DEEP=${1:-"1"} 8 | OLDPWD_CACHE="${PWD}" 9 | for _ in $(seq 1 "${DEEP}"); do 10 | cd ../ 11 | done 12 | export OLDPWD="${OLDPWD_CACHE}" 13 | } 14 | 15 | hejmo() { 16 | cd "${HEJMO}" || exit 17 | [[ -n "$(command -v tabname)" ]] && tabname 18 | } 19 | -------------------------------------------------------------------------------- /bash_profile/02_upsearch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # upsearch 3 | 4 | #props to @PaulSCoder and @joelmccracken for this wizardry 5 | 6 | UPSEARCH_FOUND=0 7 | UPSEARCH_NOT_FOUND=127 8 | 9 | upsearch_cd_old() { 10 | # if we're at root and the file's not here, return not found 11 | # if the file is in the present working directory, echo the directory and return found 12 | # otherwise go up a directory and execute recursively 13 | # this could get slow if 'cd' is bound to something slow and not a simple changing of pwd 14 | test / == "$PWD" && test ! -e "$1" && return $UPSEARCH_NOT_FOUND || test -e "$1" && echo $PWD && return $UPSEARCH_FOUND || cd .. && upsearch_cd "$1" 15 | } 16 | 17 | upsearch_old() { 18 | (upsearch_cd "$1") 19 | } 20 | 21 | upsearch_cd() { 22 | where=$(upsearch $1) 23 | if [[ $? -eq $UPSEARCH_FOUND ]]; then 24 | cd "$where" 25 | elif [[ $? -eq $UPSEARCH_NOT_FOUND ]]; then 26 | echo >&2 "$1 not found in path" 27 | else 28 | echo >&2 "upsearch returned something weird: $?" 29 | fi 30 | } 31 | 32 | # adapted from gdub's lookup() function: 33 | # https://github.com/dougborg/gdub/blob/70ed1d774ad3f9cbe03041aa81164c81e11003cb/bin/gw#L12 34 | upsearch() { 35 | local file="${1}" 36 | local curr_path="${2}" 37 | [[ -z "${curr_path}" ]] && curr_path="${PWD}" 38 | 39 | # Search recursively upwards for file. 40 | until [[ "${curr_path}" == "/" ]]; do 41 | if [[ -e "${curr_path}/${file}" ]]; then 42 | echo "${curr_path}" 43 | return $UPSEARCH_FOUND 44 | else 45 | curr_path=$(dirname "${curr_path}") 46 | fi 47 | done 48 | return $UPSEARCH_NOT_FOUND 49 | } 50 | -------------------------------------------------------------------------------- /bash_profile/50_iterm_integration.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # don't run if not in interactive mode 4 | if ! (echo "${-}" | grep -q i); then 5 | return 0 6 | fi 7 | 8 | ITERM_INTEGRATION_SCRIPT="${HOME}/.iterm2_shell_integration.bash" 9 | 10 | if [ -z "${NO_ITERM}" ] && [ -f "${ITERM_INTEGRATION_SCRIPT}" ] ; then 11 | # shellcheck source=~/.iterm2_shell_integration.bash 12 | . "${ITERM_INTEGRATION_SCRIPT}" 13 | fi 14 | 15 | disable-iterm-integration() { 16 | local OUTPUT="" 17 | IFS=';' read -ra CMDS <<< "${PROMPT_COMMAND}" 18 | for i in "${CMD[@]}"; do 19 | if [[ ! "${i}" =~ "__bp" ]]; then 20 | OUTPUT="${OUTPUT};${i}" 21 | fi 22 | done 23 | 24 | export PROMPT_COMMAND="${OUTPUT}" 25 | } 26 | 27 | if [ -n "${SSH_CONNECTION}" ]; then 28 | echo "Connected via SSH, disabling iTerm integration." >&2 29 | disable-iterm-integration 30 | fi 31 | -------------------------------------------------------------------------------- /bash_profile/50_ls.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # configures ls and some useful aliases 3 | 4 | export LS_COLORS='no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.svgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:'; 5 | 6 | #Sometimes I can't type 7 | alias ls='ls -G' 8 | if [ -z `which sl` ]; then 9 | alias sl='ls -G' 10 | else 11 | alias sl='sl -a' 12 | fi 13 | alias s='ls -G' 14 | alias l='ls -G' 15 | alias lsl='ls -Glah' 16 | -------------------------------------------------------------------------------- /bash_profile/70_editors.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # editor settings, mostly for EDITOR 3 | 4 | export EDITOR=vim 5 | alias vi='vim' 6 | -------------------------------------------------------------------------------- /bash_profile/99_bat.sh: -------------------------------------------------------------------------------- 1 | # for bat, the syntax highlighting cat 2 | export BAT_THEME=DarkNeon 3 | -------------------------------------------------------------------------------- /bash_profile/99_chromecast.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # chromecasting functions 3 | 4 | function ccyt { 5 | curl -H "Content-Type: application/json" \ 6 | http://"Basement TV.local":8008/apps/YouTube \ 7 | -X POST \ 8 | -d "v=$1"; 9 | } 10 | 11 | function ytsearch() { 12 | curl -s "https://www.youtube.com/results?search_query=$@" | \ 13 | grep -o 'watch?v=[^"]*"[^>]*title="[^"]*' | \ 14 | sed -e 's/^watch\?v=\([^"]*\)".*title="\(.*\)/\1 \2/g' 15 | } 16 | 17 | # maybe use this instead? https://github.com/skorokithakis/catt 18 | 19 | -------------------------------------------------------------------------------- /bash_profile/99_completions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Completions from OS 4 | if ! shopt -oq posix; then 5 | if [ -f /usr/share/bash-completion/bash_completion ]; then 6 | . /usr/share/bash-completion/bash_completion 7 | elif [ -f /etc/bash_completion ]; then 8 | . /etc/bash_completion 9 | fi 10 | fi 11 | 12 | # Completions from Homebrew 13 | 14 | if [ -n "$(command -v brew)" ]; then 15 | if [ -n "${HEJMO_DEBUG_COMPLETIONS}" ]; then 16 | set -x 17 | fi 18 | 19 | # completions 20 | HOMEBREW_PREFIX="$(${BREW_PREFIX})" 21 | export HOMEBREW_COMPLETIONS_DIR="${HOMEBREW_PREFIX}/etc/bash_completion.d" 22 | export BASH_COMPLETION_COMPAT_DIR="${HOMEBREW_COMPLETIONS_DIR}" 23 | HOMEBREW_PROF_COMPLETION_SCRIPT="${HOMEBREW_PREFIX}/etc/profile.d/bash_completion.sh" 24 | export HOMEBREW_SOURCE_COMPLETIONS=yes 25 | 26 | if [ -n "${HEJMO_DEBUG_COMPLETIONS}" ]; then 27 | set +x 28 | fi 29 | 30 | # shellcheck source=/dev/null 31 | if [ -f "${HOMEBREW_PROF_COMPLETION_SCRIPT}" ]; then 32 | # use the bash completion loader from the bash-completion package 33 | source "${HOMEBREW_PROF_COMPLETION_SCRIPT}" 34 | else 35 | # load them manually 36 | for COMPLETION in "${HOMEBREW_COMPLETIONS_DIR}/"*; do 37 | [[ -r "${COMPLETION}" ]] && source "${COMPLETION}" 38 | done 39 | fi 40 | fi 41 | 42 | #autocomplete for g as well 43 | #complete -o default -o nospace -F _git g 44 | #if [ -n "$(command -v __git_complete)" ]; then 45 | # __git_complete g git 46 | #fi 47 | 48 | #autocomplete for t 49 | # shellcheck source=../scripts/_t_completion 50 | if [ -n "$(command -v t)" ]; then 51 | if [ -n "$(command -v _t_completion)" ]; then 52 | source "$(command -v _t_completion)" 53 | fi 54 | fi 55 | 56 | # autocomplete for pandoc 57 | if [ -n "$(command -v pandoc)" ]; then 58 | eval "$(pandoc --bash-completion)" 59 | fi 60 | 61 | # autocomplete for ngrok 62 | if [ -n "$(command -v ngrok)" ]; then 63 | eval "$(ngrok completion)" 64 | fi 65 | -------------------------------------------------------------------------------- /bash_profile/99_conda.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MINICONDA_PATH="${MINICONDA_PATH:-"$(${BREW_PREFIX})/Caskroom/miniconda"}}" 4 | CONDA_BASE_PATH="${MINICONDA_PATH}/base" 5 | CONDA_BIN="${CONDA_BASE_PATH}/bin/conda" 6 | 7 | if [[ -x "${CONDA_BIN}" ]]; then 8 | __conda_setup="$("${CONDA_BIN}" shell.bash hook 2> /dev/null)" 9 | # shellcheck disable=SC2181 10 | if [ $? -eq 0 ]; then 11 | eval "$__conda_setup" 12 | else 13 | if [ -f "${CONDA_BASE_PATH}/etc/profile.d/conda.sh" ]; then 14 | # shellcheck disable=SC1091 15 | . "${CONDA_BASE_PATH}/etc/profile.d/conda.sh" 16 | else 17 | export PATH="${CONDA_BASE_PATH}/bin:$PATH" 18 | fi 19 | fi 20 | unset __conda_setup 21 | fi 22 | -------------------------------------------------------------------------------- /bash_profile/99_conscript.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export CONSCRIPT_HOME="${HOME}/.conscript" 4 | if [[ -d "${CONSCRIPT_HOME}" ]]; then 5 | export CONSCRIPT_OPTS="-XX:MaxPermSize=512M -Dfile.encoding=UTF-8" 6 | export PATH="${CONSCRIPT_HOME}/bin:${PATH}" 7 | fi 8 | -------------------------------------------------------------------------------- /bash_profile/99_converters.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if [ -n "$(command -v rsvg-convert)" ]; then 4 | alias svg2png="rsvg-convert" 5 | fi 6 | -------------------------------------------------------------------------------- /bash_profile/99_fzf.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # mostly copied from https://github.com/tednaleid/shared-zshrc/blob/master/zshrc_base#L265-L279 3 | 4 | default_fzf_location=/opt/homebrew/opt/fzf 5 | if [[ -n "$(command -v brew)" ]]; then 6 | BREW_FZF="$(${BREW_PREFIX} fzf)" 7 | fi 8 | FZF_SHELL="${BREW_FZF:-$default_fzf_location}/shell" 9 | 10 | XARGS="xargs" 11 | if [[ "$(uname -s)" == "Darwin" ]]; then 12 | if command -v gxargs > /dev/null; then 13 | XARGS="gxargs" 14 | else 15 | >&2 echo "Trying to install GNU findutils to enable open_fzf support" 16 | if [[ -n "${BREW_FZF}" ]]; then 17 | brew install findutils 18 | XARGS="gxargs" 19 | fi 20 | fi 21 | fi 22 | 23 | # shellcheck source=/dev/null 24 | if [[ -d "$FZF_SHELL" ]]; then 25 | source "${FZF_SHELL}/completion.bash" 2> /dev/null 26 | source "${FZF_SHELL}/key-bindings.bash" 27 | # end if we have fzf 28 | fi 29 | 30 | export FZF_CTRL_R_OPTS="--min-height=20 --exact --preview 'echo {}' --preview-window down:3:wrap" 31 | export FZF_DEFAULT_COMMAND='rg --files --no-ignore --hidden --follow -g "!{.git,node_modules,build}/*" 2> /dev/null' 32 | export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" 33 | 34 | export FZF_CTRL_T_OPTS=$'--min-height=20 --preview \'[[ $(file --mime {}) =~ binary ]] && echo {} is a binary file || 35 | (bat --style=numbers --color=always {} || 36 | cat {}) 2> /dev/null | head -500 37 | \'' 38 | 39 | export FZF_DEFAULT_OPTS=" 40 | --layout=reverse 41 | --info=inline 42 | --height=80% 43 | --bind '?:toggle-preview' 44 | " 45 | # shellcheck disable=SC2139 # no idea why this works but fixing it breaks it 46 | alias fzfp="fzf $FZF_CTRL_T_OPTS" 47 | 48 | # needs findutils for gxargs and fd for better find 49 | # open a file somewhere under the current directory, press "?" for preview window 50 | # shellcheck disable=SC2016 51 | open_fzf() { 52 | fd -t f -L -H -E ".git" |\ 53 | fzf -m --min-height=20 \ 54 | --preview-window=:hidden \ 55 | --preview '[[ $(file --mime {}) =~ binary ]] && echo {} is a binary file || (bat --style=numbers --color=always {} || cat {}) 2> /dev/null | head -500' |\ 56 | "${XARGS}" -ro -d "\n" open 57 | } 58 | 59 | # cd into a directory based on and fzf directory search 60 | cd_fzf() { 61 | local basedir=${1:-.} # default to starting from current directory (.) but allow override 62 | local directory 63 | if directory=$(fd -t d -L -H -I -E ".git" . "$basedir" | fzf --preview="tree -L 1 {}" ); then 64 | cd "${directory}" && fzf-redraw-prompt 65 | fi 66 | } 67 | 68 | # cd into a directory somewhere under the home directory 69 | cd_home_fzf() { 70 | cd_fzf "$HOME" 71 | } 72 | 73 | # show all branches in a menu 74 | alias gco='git checkout $(git branch | grep -v $(git rev-parse --abbrev-ref HEAD) | fzf)' 75 | -------------------------------------------------------------------------------- /bash_profile/99_git.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # git functions and aliases 3 | 4 | if [ -n "$(command -v hub)" ]; then 5 | eval "$(hub alias -s)" 6 | fi 7 | 8 | alias g="git" 9 | alias igist="GITHUB_URL=\${INTERNAL_GITHUB} gist" 10 | 11 | alias debug_git="GIT_TRACE=true GIT_CURL_VERBOSE=true GIT_SSH_COMMAND='ssh -vvv' git" 12 | -------------------------------------------------------------------------------- /bash_profile/99_gradle.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # gradle functions and aliases 3 | 4 | alias gradle="gw --daemon" 5 | alias gw="gw --daemon" 6 | 7 | if [ -s "$HOME/.gvm/bin/gvm-init.sh" ]; then 8 | "$HOME/.gvm/bin/gvm-init.sh" 9 | fi 10 | 11 | -------------------------------------------------------------------------------- /bash_profile/99_hashing.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # hashing functions and aliases 3 | 4 | if [ -z "$(command -v sha256)" ]; then 5 | alias sha256='shasum -a 256' 6 | fi 7 | if [ -z "$(command -v sha1)" ]; then 8 | alias sha1='shasum -a 1' 9 | fi 10 | 11 | -------------------------------------------------------------------------------- /bash_profile/99_history.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # history management 3 | 4 | #prevent jrnl from appearing in history 5 | export HISTIGNORE="$HISTIGNORE:jrnl *" 6 | # load the last N into memory 7 | export HISTSIZE=5000 8 | # keep the last N on disk 9 | export HISTFILESIZE=100000 10 | export HISTTIMEFORMAT='[@ %Y-%m-%d %T] ' 11 | # don't log any command that begins with an empty space 12 | export HISTCONTROL="ignorespace" 13 | # append the history instead of overwriting it when there are multiple sessions 14 | shopt -s histappend 15 | HISTORY_CMDS="history -a; history -c; history -r" 16 | # write every command to the history log immediately 17 | # this is expensive, because it must be appended, cleared, and re-read for 18 | # every command executed. 19 | # TODO: introduce something that can disable this for a session 20 | case "$PROMPT_COMMAND" in 21 | *history*) ;; 22 | *) PROMPT_COMMAND="${PROMPT_COMMAND:+${PROMPT_COMMAND};}${HISTORY_CMDS}" ;; 23 | esac 24 | export PROMPT_COMMAND 25 | -------------------------------------------------------------------------------- /bash_profile/99_jira-cli.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if command -v jira >/dev/null && [[ -f "${XDG_CONFIG_HOME}/.jira/.config.yml" ]]; then 4 | # shellcheck source=/dev/null 5 | . <(jira completion bash) 6 | fi 7 | -------------------------------------------------------------------------------- /bash_profile/99_kitty.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # kitty terminal specific things 3 | if [ -z "${KITTY_PID}" ]; then 4 | # not in kitty 5 | return 0 6 | fi 7 | export HEJMO_IS_KITTY=1 8 | 9 | alias icat="kitten icat" 10 | alias imgcat="kitten icat" 11 | 12 | iplot() { 13 | cat <>> mamba initialize >>> 4 | # !! Contents within this block are managed by 'mamba init' !! 5 | MAMBA_EXE="$(${BREW_PREFIX} micromamba)/bin/micromamba" 6 | export MAMBA_EXE 7 | export MAMBA_ROOT_PREFIX="${HOME}/.cache/micromamba" 8 | if __mamba_setup="$("$MAMBA_EXE" shell hook --shell bash --prefix "$MAMBA_ROOT_PREFIX" 2>/dev/null)"; then 9 | #if [ $? -eq 0 ]; then 10 | eval "$__mamba_setup" 11 | else 12 | if [ -f "${MAMBA_ROOT_PREFIX}/etc/profile.d/micromamba.sh" ]; then 13 | # shellcheck source=/dev/null 14 | . "${MAMBA_ROOT_PREFIX}/etc/profile.d/micromamba.sh" 15 | else 16 | export PATH="${MAMBA_ROOT_PREFIX}/bin:${PATH}" # extra space after export prevents interference from conda init 17 | fi 18 | fi 19 | unset __mamba_setup 20 | # <<< mamba initialize <<< 21 | -------------------------------------------------------------------------------- /bash_profile/99_man_colors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # manpage colors 3 | 4 | #https://russellparker.me/2018/02/23/adding-colors-to-man/ 5 | 6 | export MANROFFOPT='-c' 7 | 8 | if echo "${-}" | grep -q i; then 9 | export LESS_TERMCAP_mb=$(tput bold; tput setaf 2) 10 | export LESS_TERMCAP_md=$(tput bold; tput setaf 6) 11 | export LESS_TERMCAP_me=$(tput sgr0) 12 | export LESS_TERMCAP_so=$(tput bold; tput setaf 3; tput setab 4) 13 | export LESS_TERMCAP_se=$(tput rmso; tput sgr0) 14 | export LESS_TERMCAP_us=$(tput smul; tput bold; tput setaf 7) 15 | export LESS_TERMCAP_ue=$(tput rmul; tput sgr0) 16 | export LESS_TERMCAP_mr=$(tput rev) 17 | export LESS_TERMCAP_mh=$(tput dim) 18 | fi 19 | -------------------------------------------------------------------------------- /bash_profile/99_node_version_manager.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export NVM_DIR="$HOME/.cache/nvm" 4 | 5 | NVM_PREFIX="$(${BREW_PREFIX} nvm)" 6 | NVM_BASE="${NVM_PREFIX}/nvm.sh" 7 | NVM_COMP="${NVM_PREFIX}/etc/bash_completion.d/nvm" 8 | 9 | if [ -s "${NVM_BASE}" ]; then 10 | mkdir -p "${NVM_DIR}" 11 | # shellcheck source=/dev/null 12 | . "${NVM_BASE}" 13 | fi 14 | 15 | if [ -s "${NVM_COMP}" ]; then 16 | # shellcheck source=/dev/null 17 | . "${NVM_COMP}" 18 | fi 19 | -------------------------------------------------------------------------------- /bash_profile/99_prompt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #command prompt customization 3 | 4 | export GIT_PS1_SHOWDIRTYSTATE=true 5 | export GIT_PS1_SHOWUNTRACKEDFILES=true 6 | 7 | function emoji_number 8 | { 9 | case $1 in 10 | 1) 11 | echo "1️⃣";; 12 | 2) 13 | echo "2️⃣";; 14 | 3) 15 | echo "3️⃣";; 16 | 4) 17 | echo "4️⃣";; 18 | 5) 19 | echo "5️⃣";; 20 | 6) 21 | echo "6️⃣";; 22 | 7) 23 | echo "7️⃣";; 24 | 8) 25 | echo "8️⃣";; 26 | 9) 27 | echo "9️⃣";; 28 | 10) 29 | echo "🔟";; 30 | *) 31 | echo "⏬";; 32 | esac 33 | } 34 | 35 | function prompt 36 | { 37 | local WHITE="\[\033[1;37m\]" 38 | local GREEN="\[\033[0;32m\]" 39 | local CYAN="\[\033[0;36m\]" 40 | local GRAY="\[\033[0;37m\]" 41 | local BLUE="\[\033[0;34m\]" 42 | local LIGHT_BLUE="\[\033[1;34m\]" 43 | local YELLOW="\[\033[1;33m\]" 44 | local RED="\[\033[1;31m\]" 45 | #local RUBY="${LIGHT_BLUE}\$(if [ ! -z \"\`upsearch Gemfile\`\" ]; then echo -n \"(\${RUBY_VERSION})\"; fi)" 46 | local GIT_B="${RED}\$(if [ ! -z \"\`command -v __git_ps1\`\" ]; then _GITPS1=\"\`__git_ps1\`\"; if [ ! -z \"\${_GITPS1}\" ]; then echo -n \"±\${_GITPS1}\"; echo -n ' '; fi; fi)" 47 | local DEPTH="\$(if [ \$SHLVL -gt 1 ]; then echo \"⇟\$SHLVL\"; fi)" 48 | local HOST="${INTENDED_HOSTNAME:-\H}" 49 | export PS1="${WHITE}[${YELLOW}\t ${GREEN}\u@${HOST} ${CYAN}\w ${RUBY}${WHITE}]\n${GIT_B}${GRAY}${DEPTH}\$ " 50 | } 51 | prompt 52 | -------------------------------------------------------------------------------- /bash_profile/99_ruby.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # ruby management 3 | 4 | if [[ -z $NO_RVM ]]; then 5 | if [ -s "$HOME/.rvm/scripts/rvm" ]; then 6 | . "$HOME/.rvm/scripts/rvm" # Load RVM installed locally 7 | elif [ -s "/etc/profile.d/rvm.sh" ]; then 8 | if ! groups | grep rvm > /dev/null; then 9 | >&2 echo "$USER is not in group 'rvm', sourcing /etc/profile.d/rvm.sh may not work as intended." 10 | fi 11 | . "/etc/profile.d/rvm.sh" # Load RVM installed at system level 12 | fi 13 | fi 14 | 15 | if [[ -z $NO_CHRUBY ]]; then 16 | chruby_share="$(${BREW_PREFIX} chruby)/share/chruby" 17 | if [ -s "${chruby_share}/chruby.sh" ]; then 18 | . "${chruby_share}/chruby.sh" 19 | fi 20 | if [ -s "${chruby_share}/auto.sh" ]; then 21 | . "${chruby_share}/auto.sh" 22 | fi 23 | fi 24 | 25 | -------------------------------------------------------------------------------- /bash_profile/99_rust.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # rust management 3 | 4 | if [ -f "$HOME/.cargo/env" ]; then 5 | source "$HOME/.cargo/env" 6 | fi 7 | -------------------------------------------------------------------------------- /bash_profile/99_ssh_aliases.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # ssh functions and aliases 4 | 5 | # removed some ancient stuff, so now there's nothing here! 6 | 7 | -------------------------------------------------------------------------------- /bash_profile/99_travis.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # travis helpers 3 | 4 | if [ -f "$HOME/.travis/travis.sh" ]; then 5 | . "$HOME/.travis/travis.sh" 6 | fi 7 | 8 | -------------------------------------------------------------------------------- /bash_profile/99_urls.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | shellcheck_wiki() { 4 | local ARTICLE="${1}" 5 | local BASE_URL="https://github.com/koalaman/shellcheck/wiki" 6 | local GO_URL="${BASE_URL}/${ARTICLE}" 7 | if [ -n "$(command -v xdg-open)" ]; then 8 | xdg-open "${GO_URL}" 9 | else 10 | open "${GO_URL}" 11 | fi 12 | } 13 | 14 | alias scw="shellcheck_wiki" 15 | 16 | function wttr() { 17 | curl "https://wttr.in/${*}" 18 | } 19 | 20 | function urlencode() { 21 | # @uri for "applies percent-encoding, by mapping all reserved URI characters to a %XX sequence." 22 | jq --slurp --raw-input --raw-output @uri 23 | } 24 | 25 | function urldecode() { 26 | perl -pe 's/\%(\w\w)/chr hex $1/ge' 27 | } 28 | -------------------------------------------------------------------------------- /bash_profile/99_z.sh: -------------------------------------------------------------------------------- 1 | 2 | # setup zoxide 3 | THIS_SHELL="$(basename "${SHELL}")" 4 | 5 | if true && [ -n "$(command -v zoxide)" ]; then 6 | case "${THIS_SHELL}" in 7 | bash) 8 | eval "$(zoxide init bash)";; 9 | zsh) 10 | eval "$(zoxide init zsh)";; 11 | *) 12 | eval "$(zoxide init posix --hook prompt)";; 13 | esac 14 | fi 15 | 16 | # because the zoxide thing messes this up 17 | export PROMPT_COMMAND="${PROMPT_COMMAND/;;/;}" 18 | -------------------------------------------------------------------------------- /bash_profile/99_zoom.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # functions to make zoom more bearable 3 | 4 | function zoom_join() { 5 | local meeting_id="${1}" 6 | local url="zoommtg://zoom.us/join?action=join&confno=${meeting_id}" 7 | echo "Opening ${url}…" 8 | if [ -n "$(command -v xdg-open)" ]; then 9 | # Linux 10 | xdg-open "${url}" 11 | else 12 | # macOS 13 | open "${url}" 14 | fi 15 | } 16 | 17 | alias zoom="zoom_join" 18 | -------------------------------------------------------------------------------- /bash_profile/99_zzz_env_local.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # load env.local in a way it can be timed 3 | 4 | if [ -s "$HOME/.env.local" ]; then 5 | . "$HOME/.env.local" 6 | fi 7 | 8 | -------------------------------------------------------------------------------- /bash_profile/99_zzz_fix_prompt.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROMPT_COMMAND="${PROMPT_COMMAND/;;/;}" 4 | -------------------------------------------------------------------------------- /dotfiles/ackrc: -------------------------------------------------------------------------------- 1 | --with-filename 2 | # sort the files for easier viewing 3 | --sort-files 4 | # all-lower-case is case-insensitive, otherwise it's case sensitive 5 | --smart-case 6 | # colors 7 | --color-filename=blue 8 | --color-lineno=yellow 9 | --color-match=white 10 | # show the context of the found item 11 | --context 12 | # Other file types we want to search 13 | --type-set=haml=.haml 14 | --type-set=sass=.sass 15 | --type-set=scss=.scss 16 | --type-set=erb=.erb 17 | --type-set=coffee=.coffee 18 | --type-set=html=.html 19 | --type-set=css=.css 20 | --type-set=liquid=.liquid 21 | # Don't even bother with some directories 22 | --ignore-dir=public/assets 23 | --ignore-dir=tmp 24 | --ignore-dir=doc 25 | -------------------------------------------------------------------------------- /dotfiles/bash_profile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ######################################### 3 | # HEJMO ################################# 4 | ######################################### 5 | ######################################### 6 | # a home directory system by Colin Dean # 7 | # use at your own risk if you are not ^ # 8 | # (c) 2015 Colin Dean # 9 | # Unlicense # 10 | ######################################### 11 | 12 | ## Track load time 13 | current_time() { 14 | # macos date doesn't provide resolution greater than seconds 15 | # gdate isn't on the path yet when we need this but *almost* 16 | # assuredly perl is and it loads faster than anything else 17 | # https://superuser.com/a/713000 18 | perl -MTime::HiRes -e 'printf("%.0f\n",Time::HiRes::time()*1000)' 19 | } 20 | ## trap failures during startup more, uh, grandiloquently 21 | failure() { 22 | local lineno=$2 23 | local fn=$3 24 | local exitstatus=$4 25 | local msg=$5 26 | local lineno_fns=${1% 0} 27 | if [[ "${lineno_fns}" != "0" ]] ; then 28 | lineno="${lineno} ${lineno_fns}" 29 | fi 30 | echo "${BASH_SOURCE[1]}:${fn}[${lineno}] Failed with status ${exitstatus}: ${msg}" 31 | } 32 | trap 'failure "${BASH_LINENO[*]}" "$LINENO" "${FUNCNAME[*]:-script}" "$?" "$BASH_COMMAND"' ERR 33 | 34 | ## SO IT BEGINS 35 | HEJMO_LOAD_START=$(current_time) 36 | 37 | ## Actually load stuff! 38 | 39 | ## Setup Hejmo base directories 40 | 41 | #this should be a symlink 42 | BASH_PROFILE_PHYSICAL="$(readlink "${BASH_SOURCE[0]}" )" 43 | if [[ -z "${BASH_PROFILE_PHYSICAL}" ]]; then 44 | #but if it isn't 45 | BASH_PROFILE_PHYSICAL="${BASH_SOURCE[0]}" 46 | fi 47 | HEJMO_DOTFILE_DIR="$( cd "$( dirname "${BASH_PROFILE_PHYSICAL}" )" && pwd -P)" 48 | # conveniently, this means that 49 | HEJMO="$(cd "${HEJMO_DOTFILE_DIR}/../" && pwd -P)" 50 | export HEJMO 51 | HEJMO_BASH_PROFILE_DIR="${HEJMO}/bash_profile" 52 | 53 | ## Explicitly set some XDG directories 54 | 55 | export XDG_CONFIG_HOME="${HOME}/.config" 56 | export XDG_CACHE_HOME="${HOME}/.cache" 57 | 58 | ## Explicitly set some early vars and aliases 59 | 60 | alias rebash='source ${HOME}/.bash_profile' 61 | 62 | ## Setup caching of `brew --prefix` responses 63 | ## This reduces `brew --prefix ` by about 100x 64 | ## by writing responses to a file and reading from that 65 | ## file if it's populated. 66 | export CACHE_BREW_PREFIX_DIR="${XDG_CACHE_HOME}/brew_--prefix" 67 | cached_brew_prefix() { 68 | mkdir -p "${CACHE_BREW_PREFIX_DIR}" 69 | local formula="${1}" 70 | local cache_file="${CACHE_BREW_PREFIX_DIR}/${formula:-brew_itself}" 71 | if [[ -s "${cache_file}" ]]; then 72 | cat "${cache_file}" 73 | else 74 | if command -v brew > /dev/null; then 75 | if [[ -n "${formula}" ]]; then 76 | # Because of how brew parses commands, even if an empty string is passed 77 | # it thinks that something was passed. 78 | brew --prefix "${formula}" | tee "${cache_file}" || true 79 | else 80 | brew --prefix | tee "${cache_file}" || true 81 | fi 82 | else 83 | return 1 84 | fi 85 | fi 86 | return 0 87 | } 88 | clear_brew_prefix_cache(){ 89 | rm -rf "${CACHE_BREW_PREFIX_DIR}" 90 | } 91 | export BREW_PREFIX=cached_brew_prefix 92 | 93 | ### BENCHMARKING: 94 | ### Run this command to reload with benchmarking output: 95 | ### HEJMO_BENCH_BASH_PROFILE=1 rebash 96 | ### Run this command to benchmark a whole new shell: 97 | ### HEJMO_BENCH_BASH_PROFILE=1 bash -i 98 | 99 | if [[ -n ${HEJMO_BENCH_BASH_PROFILE} ]]; then 100 | export HEJMO_BENCH_RESULTS="${HOME}/.hejmo_bench_results.txt" 101 | touch "${HEJMO_BENCH_RESULTS}" 102 | printf "" > "${HEJMO_BENCH_RESULTS}" 103 | >&2 echo "Profiling Hejmo load from ${HEJMO_BASH_PROFILE_DIR}, logs in ${HEJMO_BENCH_RESULTS}" 104 | fi 105 | for i in "${HEJMO_BASH_PROFILE_DIR}"/*.sh; do 106 | if [[ -n ${HEJMO_BENCH_BASH_PROFILE} ]]; then 107 | # seconds 108 | TIMEFORMAT="%R = ${i}" 109 | >&2 echo "Loading [$(basename "${i}")]" 110 | # shellcheck source=/dev/null 111 | { time source "${i}" ; } 2>> "${HEJMO_BENCH_RESULTS}" 112 | >&2 echo "...done" 113 | #>&2 printf "...done: [%s]\n" "$(basename "$i")" 114 | unset TIMEFORMAT 115 | else 116 | # shellcheck source=/dev/null 117 | if ! source "${i}"; then 118 | >&2 echo "Error was in loading ${i}" 119 | fi 120 | fi 121 | done; unset i 122 | 123 | HEJMO_LOAD_END=$(current_time) 124 | ((HEJMO_LOAD_TIME=HEJMO_LOAD_END - HEJMO_LOAD_START)) 125 | export HEJMO_LOAD_TIME 126 | 127 | if [[ -n ${HEJMO_BENCH_BASH_PROFILE} ]]; then 128 | >&2 echo "Hejmo Bash loading times, in user seconds" 129 | >&2 echo "------------------------" 130 | if echo "test" | column --table &>/dev/null; then 131 | # Good column 132 | >&2 sort --numeric-sort --reverse "${HEJMO_BENCH_RESULTS}" | column --table --separator " = " --output-separator "\t" || true 133 | else 134 | # Bland BSD column 135 | >&2 sort --numeric-sort --reverse "${HEJMO_BENCH_RESULTS}" | column -t -s " = " || true 136 | fi 137 | >&2 echo "------------------------------" 138 | >&2 echo "Total time: ${HEJMO_LOAD_TIME} milliseconds" 139 | fi 140 | 141 | ## drop the custom error handler 142 | trap - ERR 143 | 144 | ############################################################ 145 | ### ANYTHING added after here was added automatically # 146 | ### and should be added to a file in ${HEJMO}/bash_profile # 147 | ############################################################ 148 | 149 | -------------------------------------------------------------------------------- /dotfiles/bitbar/work/hours.1m.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Time checker 3 | # v1.0 4 | # colindean 5 | # colindean 6 | # 7 | # Runs `t hours` to show the current hours logged today 8 | # 9 | 10 | #Unfortunately, t requires basically everything. 11 | 12 | export TERM=mac 13 | PATH=/usr/local/bin:$PATH 14 | [[ -s "$HOME/.env.local" ]] && source "$HOME/.env.local" 15 | T="$HOME/.bin/t" 16 | 17 | 18 | if [[ ! -f "${T}" ]]; then 19 | echo "⚠️ t" 20 | exit 1 21 | fi 22 | 23 | OUTPUT="$("${T}" hours)" 24 | 25 | if [ 0 -ne $? ]; then 26 | echo "❌ t" 27 | echo "---" 28 | echo "Bad problem running ${T}. Write some debugging code." 29 | fi 30 | 31 | OUTPUT_LINE_COUNT="$(echo -e "${OUTPUT}" | wc -l | awk '{print $1}')" 32 | if [[ "${OUTPUT_LINE_COUNT}" -eq 1 ]]; then 33 | HOURS="$(echo -e "${OUTPUT}" | awk '{print $1}')" 34 | else 35 | HOURS="$(echo -e "${OUTPUT}" | tail -n 1 | sed -e 's/ //g')" 36 | fi 37 | 38 | PREFIX="t:" 39 | 40 | if [[ ! -z "${HOURS}" ]]; then 41 | TIME_HEADLINE="${PREFIX} ${HOURS}" 42 | else 43 | TIME_HEADLINE="㏒ ⏳" 44 | fi 45 | 46 | CURRENT_TASK="$("${T}" cur)" 47 | 48 | echo "${TIME_HEADLINE}" 49 | 50 | if [[ ! -z "${CURRENT_TASK}" ]]; then 51 | echo "${CURRENT_TASK}" 52 | fi 53 | 54 | if [[ "$(date +%A)" == "Friday" ]]; then 55 | echo "w: $("${T}" week | tail -n 1 | sed -e 's/ //g')" 56 | fi 57 | 58 | echo "---" 59 | 60 | echo -e "${OUTPUT}" | sed -e 's/\-/=/g' | sed 's/$/| font=Courier/g' 61 | -------------------------------------------------------------------------------- /dotfiles/gemrc: -------------------------------------------------------------------------------- 1 | --- 2 | :backtrace: false 3 | :bulk_threshold: 1000 4 | :sources: 5 | - https://rubygems.org/ 6 | :update_sources: true 7 | :verbose: true 8 | benchmark: false 9 | gem: --no-document 10 | gem: "--format-executable --env-shebang --no-document" 11 | -------------------------------------------------------------------------------- /dotfiles/gitattributes: -------------------------------------------------------------------------------- 1 | # https://tekin.co.uk/2020/10/better-git-diff-output-for-ruby-python-elixir-and-more 2 | 3 | *.c diff=cpp 4 | *.h diff=cpp 5 | *.c++ diff=cpp 6 | *.h++ diff=cpp 7 | *.cpp diff=cpp 8 | *.hpp diff=cpp 9 | *.cc diff=cpp 10 | *.hh diff=cpp 11 | *.m diff=objc 12 | *.mm diff=objc 13 | *.cs diff=csharp 14 | *.css diff=css 15 | *.html diff=html 16 | *.xhtml diff=html 17 | *.ex diff=elixir 18 | *.exs diff=elixir 19 | *.go diff=golang 20 | *.php diff=php 21 | *.pl diff=perl 22 | *.py diff=python 23 | *.md diff=markdown 24 | *.rb diff=ruby 25 | *.rake diff=ruby 26 | *.rs diff=rust 27 | *.lisp diff=lisp 28 | *.el diff=lisp 29 | 30 | -------------------------------------------------------------------------------- /dotfiles/gitconfig: -------------------------------------------------------------------------------- 1 | # vim: syntax=gitconfig 2 | [user] 3 | name = Colin Dean 4 | #set email in .gitconfig.local 5 | [include] 6 | path = .gitconfig.local 7 | [color] 8 | diff = auto 9 | status = auto 10 | branch = auto 11 | interactive = auto 12 | [core] 13 | whitespace = trailing-space,space-before-tab 14 | excludesfile = ~/.gitignore_global 15 | autocrlf = input 16 | pager = delta 17 | attributesfile = ~/.gitattributes 18 | [interactive] 19 | diffFilter = delta --color-only 20 | [diff] 21 | renames = copies 22 | colorMoved = default 23 | [merge] 24 | conflictstyle = diff3 25 | [delta] 26 | navigate = true 27 | features = zenburn 28 | [rerere] 29 | enabled = true 30 | [alias] 31 | # Better logging 32 | lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit 33 | lsum = log --color --pretty=format:'%s %Cgreen(%cr) %Creset' --abbrev-commit #--not --grep 'maven-release-plugin' 34 | lsince = log --oneline --not --grep '^Merge pull request' --grep '^Merge branch' 35 | log1 = log --pretty=oneline --abbrev-commit 36 | last = log -1 HEAD --format=format:"%Cred%H" # get the full hash of the HEAD commit 37 | graph = log --graph -10 --branches --remotes --tags --format=format:'%Cgreen%h %Creset• %<(75,trunc)%s (%cN, %ar) %Cred%d' --date-order 38 | history = log -10 --format=format:'%Cgreen%h %Creset• %s (%cN, %ar)' 39 | 40 | # Analytics 41 | author-count-commit = !git log --format="%aE" $@ | tr "[:upper:]" "[:lower:]" | sort | uniq -c | sort -nr 42 | author-count-lines = !git ls-files -z | xargs -0n1 git blame --line-porcelain | grep '^author-mail' | cut -d ' ' -f 2 | tr "[:upper:]" "[:lower:]" | sort | uniq -c | sort -rn 43 | contributors = shortlog -s -n # list contributors by number of commits 44 | filetrail = log --follow -p -w # show commits made to a file over time 45 | mergetrail = log --ancestry-path --merges 46 | bigfiles = !git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sed -n 's/^blob //p' | sort --numeric-sort --key=2 | tail -n 10 | cut -c 2-12,41- | $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest 47 | author-latest-commit = !git log --branches --format='%ad %aN' --date=iso --no-merges | sort -k4,4 -u 48 | 49 | # Changes 50 | summary = status -u -s 51 | amend = commit --amend 52 | ## Mark removed files as deleted, and new files as added 53 | addremove = !git add . && git ls-files --deleted | xargs git rm 54 | save = commit -m 55 | resave = commit --amend 56 | unmerged = diff --name-only --diff-filter=U 57 | prestage = diff -w --word-diff=color # show unstaged changes 58 | precommit = diff --cached -w --word-diff=color --word-diff-regex='[^[:space:]<>]+' # show staged changes 59 | unstash = stash pop 60 | untrack = rm -r --cached 61 | 62 | # Searching 63 | grep = grep --line-number --color 64 | 65 | # Branches 66 | sw = switch 67 | unmerged = branch --no-merged 68 | back = checkout "-" 69 | current-branch = symbolic-ref --short -q HEAD 70 | cleanup = !git branch --merged | grep -v '\\*\\|master\\|develop' | xargs -n 1 git branch -d 71 | unstage = reset -q HEAD -- 72 | discard = checkout -- 73 | nevermind = !git reset --hard HEAD && git clean -d -f # clean the repo to pristine 74 | uncommit = reset --mixed HEAD~ 75 | ## Delete local branches also gone from the origin (pass in -D to force-delete) 76 | cleanup-gone-branches = "!f() { git fetch -p && git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch ${1:--d}; }; f" 77 | 78 | # Releases 79 | semtag = !git tag -a $(semver tag) -m \"tagging $(semver tag)\" 80 | 81 | # Pushing 82 | pupr = !git push -u origin HEAD && hub pull-request -o 83 | fpush = !git push --force-with-lease 84 | puoh = !git push -u origin HEAD 85 | 86 | # Et cetera 87 | ## Print URLs of remote repositories. (git config --get-regex '^remote' is a simpler command, but its output isn’t aligned.) 88 | remote-paths = "!grep -A2 '^\\[remote' $(git root)/.git/config" 89 | ## All files under version control in the current revision 90 | manifest = ls-tree -r --full-tree --name-only HEAD 91 | ## Create default .git-blame-ignore-revs file from revs that contain "Reformat" 92 | #write-reformats-to-blame-ignore = !git log --grep Reformat --format="%H%n\0x23 %s" >> .git-blame-ignore-revs 93 | set-blame-ignore-revs = config set blame.ignoreRevsFile .git-blame-ignore-revs 94 | 95 | # Misspellings, Plurals, etc. 96 | ad = add 97 | ass = add 98 | dff = diff 99 | doff = diff 100 | emrge = merge 101 | idff = diff 102 | mergfe = merge 103 | mregetool = mergetool 104 | mt = mergetool 105 | oull = pull 106 | pish = push 107 | pl = pull 108 | ps = push 109 | psuh = push 110 | pu = up 111 | puhs = push 112 | puosh = push 113 | pus = push 114 | pushy = push 115 | reabse = rebase 116 | satsh = stash 117 | sst = status -sb 118 | t = status -sb 119 | tint = init 120 | tpull = pull 121 | tpush = push 122 | ts = status -sb 123 | tst = status -sb 124 | tup = up 125 | move = mv 126 | remove = rm 127 | ## Plurals 128 | tags = tag 129 | branches = branch -a 130 | stashes = stash list 131 | remotes = remote -v 132 | ## Utilties 133 | master-to-main = !git checkout master && git branch -m master main && git fetch && git branch --unset-upstream && git branch -u origin/main && git remote set-head origin -a 134 | ## Debugging remotes 135 | push-loud = !GIT_TRACE=2 GIT_TRACE_PERFORMANCE=2 GIT_TRACE_PACK_ACCESS=2 GIT_TRACE_PACKET=2 GIT_TRACE_PACKFILE=2 GIT_TRACE_SETUP=2 git push 136 | [push] 137 | default = simple 138 | [filter "lfs"] 139 | clean = git-lfs clean -- %f 140 | smudge = git-lfs smudge -- %f 141 | required = true 142 | process = git-lfs filter-process 143 | [color "diff-highlight"] 144 | oldNormal = red bold 145 | oldHighlight = red bold 52 146 | newNormal = green bold 147 | newHighlight = green bold 22 148 | [pull] 149 | ff = only 150 | [init] 151 | defaultBranch = main 152 | [url "git@github.com:colindean"] 153 | insteadof = https://github.com/colindean 154 | [url "git@gitlab.com:colindean"] 155 | insteadof = https://gitlab.com/colindean 156 | [github] 157 | user = colindean 158 | 159 | # Sources: 160 | # https://github.com/gggritso/dotfiles/blob/master/gitconfig.symlink 161 | [blame] 162 | markIgnoredLines = true 163 | markUnblamableLines = true 164 | [safe] 165 | directory = /vela/mosaic-ml-models-extended-service-plan 166 | [branch] 167 | sort = -committerdate 168 | [credential "https://github.com"] 169 | helper = !/home/linuxbrew/.linuxbrew/bin/gh auth git-credential 170 | [credential "https://gist.github.com"] 171 | helper = !/home/linuxbrew/.linuxbrew/bin/gh auth git-credential 172 | 173 | -------------------------------------------------------------------------------- /dotfiles/gitignore_global: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | # ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.pyc 10 | # 11 | # # Packages # 12 | # ############ 13 | # # it's better to unpack these files and commit the raw source 14 | # # git has its own built in compression methods 15 | # *.7z 16 | # *.dmg 17 | # *.gz 18 | # *.iso 19 | # *.jar 20 | # *.rar 21 | # *.tar 22 | # *.zip 23 | # 24 | # # Logs and databases # 25 | # ###################### 26 | # *.log 27 | # *.sql 28 | # *.sqlite 29 | # 30 | # # OS generated files # 31 | # ###################### 32 | .DS_Store 33 | .DS_Store? 34 | ._* 35 | .Spotlight-V100 36 | .Trashes 37 | ehthumbs.db 38 | Thumbs.db 39 | 40 | .pgsql 41 | *.iml 42 | .idea 43 | *.swp 44 | /target/ 45 | **/project/target/ 46 | *.iml 47 | # Elementary Code backup files 48 | *~ 49 | Brewfile.lock.json 50 | -------------------------------------------------------------------------------- /dotfiles/hammerspoon/README.md: -------------------------------------------------------------------------------- 1 | # @colindean's Hammerspoon configuration 2 | 3 | [Hammerspoon](http://www.hammerspoon.org/) is a fantastic window management system for OS X. 4 | 5 | ## Briefly, how I use it 6 | 7 | Hammerspoon enables you to write keybinding action configs in Lua. These actions are triggered using a mashing of meta keys plus a real key to activate. I use Hammerspoon primarily for window management on a 4x2 grid 8 | 9 | I use `⌘^⌥` as my mash plus mostly vim keybindings to move windows around the display: `H` to move left, `L` to move right, `J` down, `K` up. I use multiple monitors often, so I've designated `N` for the next physical monitor, `P` for previous. `M` maximizes, `C` centers. `I` and `O` adjust width of a window, `Y` and `U` adjust height. `T` centers and shrinks to row 1, great for moving a window as close to the camera as it can get. `1`,`2`,`3` move a window to the left and make it take up that many columns on the 4x2 grid. `9`, `0`, `-` do the same but to the right. `;` snaps a window to the grid. `G` shows window position. 10 | 11 | I may have added more. Look [approximately here](https://github.com/colindean/hejmo/blob/master/dotfiles/hammerspoon/window_mgmt.lua#L52) to see what exists these days. 12 | 13 | ## Installation 14 | 15 | Get Hammerspoon from its website or do the following, which is much easier if you 16 | have Homebrew installed (and you probably do if you're looking at this): 17 | 18 | ```shell 19 | brew cask install hammerspoon 20 | ``` 21 | 22 | Then, symlink this directory to ~/.hammerspoon with something such as: 23 | 24 | ```shell 25 | rm -rf ~/.hammerspoon; ln -s `pwd` ~/.hammerspoon 26 | ``` 27 | 28 | You're removing it because there's a pretty good chance that you started 29 | Hammerspoon, and it created an empty directory for you. If you use the same management scripts from higher up in this repository, then you're already set: it'll be linked automatically when you run 'link_dotfiles.sh'. 30 | 31 | You can then start up Hammerspoon and enjoy window management like I do. Read 32 | through the `window_mgmt.lua` script to see what the hotkeys do. It's very 33 | straightforward, especially if you've used Vim previously. 34 | 35 | ## History 36 | 37 | Hammerspoon is a batteries-included version of [Mjolnir](http://mjolnir.io). I used Mjolnir and its many predecessors. My old [mjolnir-config](https://github.com/colindean/mjolnir-config) demonstrates the pedigree of the configuration in this repository as well as how much easier it is to set up Hammerspoon than Mjolnir. 38 | 39 | Migrating from Mjolnir to Hammerspoon was a very quick task because of the abstractions I'd used in creating my configuration. It took about 20 minutes. 40 | -------------------------------------------------------------------------------- /dotfiles/hammerspoon/anycomplete.lua: -------------------------------------------------------------------------------- 1 | -- based on https://github.com/nathancahill/Anycomplete 2 | 3 | local mod = {} 4 | 5 | -- Anycomplete 6 | function mod.anycomplete() 7 | local SEARCH_ENDPOINT = 'https://duckduckgo.com/ac/?q=%s' 8 | local current = hs.application.frontmostApplication() 9 | local tab = nil 10 | local copy = nil 11 | local choices = {} 12 | 13 | local chooser = hs.chooser.new(function(choosen) 14 | if copy then copy:delete() end 15 | if tab then tab:delete() end 16 | current:activate() 17 | hs.eventtap.keyStrokes(choosen.text) 18 | end) 19 | 20 | -- Removes all items in list 21 | function reset() 22 | chooser:choices({}) 23 | end 24 | 25 | tab = hs.hotkey.bind('', 'tab', function() 26 | local id = chooser:selectedRow() 27 | local item = choices[id] 28 | -- If no row is selected, but tab was pressed 29 | if not item then return end 30 | chooser:query(item.text) 31 | reset() 32 | updateChooser() 33 | end) 34 | 35 | copy = hs.hotkey.bind('cmd', 'c', function() 36 | local id = chooser:selectedRow() 37 | local item = choices[id] 38 | if item then 39 | chooser:hide() 40 | hs.pasteboard.setContents(item.text) 41 | hs.alert.show("Copied to clipboard", 1) 42 | else 43 | hs.alert.show("No search result to copy", 1) 44 | end 45 | end) 46 | 47 | function updateChooser() 48 | local string = chooser:query() 49 | local query = hs.http.encodeForQuery(string) 50 | -- Reset list when no query is given 51 | if string:len() == 0 then return reset() end 52 | 53 | hs.http.asyncGet(string.format(SEARCH_ENDPOINT, query), nil, function(status, data) 54 | if not data then return end 55 | 56 | local ok, results = pcall(function() return hs.json.decode(data) end) 57 | if not ok then return end 58 | 59 | choices = hs.fnutils.imap(results, function(result) 60 | return { 61 | ["text"] = result["phrase"], 62 | } 63 | end) 64 | 65 | chooser:choices(choices) 66 | end) 67 | end 68 | 69 | chooser:queryChangedCallback(updateChooser) 70 | 71 | chooser:searchSubText(false) 72 | 73 | chooser:show() 74 | end 75 | 76 | function mod.registerDefaultBindings(mods, key) 77 | mods = mods or {"cmd", "alt", "ctrl"} 78 | key = key or "G" 79 | hs.hotkey.bind(mods, key, mod.anycomplete) 80 | end 81 | 82 | return mod 83 | -------------------------------------------------------------------------------- /dotfiles/hammerspoon/init.lua: -------------------------------------------------------------------------------- 1 | -- @colindean's hammerspoon configuration 2 | 3 | package.path = package.path .. ";" .. os.getenv("HOME") .. "/.hammerspoon/?.lua" 4 | 5 | require "window_mgmt" 6 | require "type" 7 | 8 | local anycomplete = require "anycomplete" 9 | anycomplete.registerDefaultBindings() 10 | 11 | local hotkeyerr, hotkey = pcall(function() return require "hs.hotkey" end) 12 | local alerterr, alert = pcall(function() return require "hs.alert" end) 13 | mash = {"cmd", "alt", "ctrl"} 14 | 15 | function toggle_zoom_mute() 16 | local zoom = hs.application.find("zoom.us") 17 | if not(zoom:findMenuItem("Unmute audio")) then 18 | zoom:selectMenuItem("Mute audio") 19 | alert.show("Zoom 🔇") 20 | elseif not(zoom:findMenuItem("Mute audio")) then 21 | zoom:selectMenuItem("Unmute audio") 22 | alert.show("Zoom 🔈") 23 | end 24 | end 25 | 26 | hotkey.bind(mash, "V", toggle_zoom_mute) 27 | 28 | local alert = require "hs.alert" 29 | alert.show("🔨 ⏰") 30 | 31 | 32 | -------------------------------------------------------------------------------- /dotfiles/hammerspoon/type.lua: -------------------------------------------------------------------------------- 1 | -- quick shortcuts for typing common things 2 | 3 | local eventtaperr, eventtap = pcall(function() return require "hs.eventtap" end) 4 | local hotkeyerr, hotkey = pcall(function() return require "hs.hotkey" end) 5 | local alerterr, alert = pcall(function() return require "hs.alert" end) 6 | 7 | function print_if_not_table(var) 8 | if not(type(var) == "table") then print(var) end 9 | end 10 | 11 | if not eventtaperr or not hotkeyerr or not alerterr then 12 | hs.showerror("Some packages appear to be missing") 13 | print_if_not_table(eventtap) 14 | end 15 | 16 | mash = {"cmd","alt","ctrl"} 17 | 18 | function getUserName() 19 | return os.getenv("USER") 20 | end 21 | 22 | local type_shortcuts = { 23 | Z = function() eventtap.keyStrokes(getUserName()) alert.show("Typed [" .. getUserName() .. "] into current input") end 24 | } 25 | 26 | for key, func in pairs(type_shortcuts) do 27 | hotkey.bind(mash, key, func) 28 | end 29 | -------------------------------------------------------------------------------- /dotfiles/hammerspoon/window_mgmt.lua: -------------------------------------------------------------------------------- 1 | -- @colindean's hammerspoon configuration 2 | -- Window Management 3 | 4 | -- Read through the script to see what it does. It's pretty clear based on 5 | -- function name. 6 | 7 | local griderr, grid = pcall(function() return require "hs.grid" end) 8 | local windowerr, window = pcall(function() return require "hs.window" end) 9 | local hotkeyerr, hotkey = pcall(function() return require "hs.hotkey" end) 10 | local alerterr, alert = pcall(function() return require "hs.alert" end) 11 | 12 | function print_if_not_table(var) 13 | if not(type(var) == "table") then print(var) end 14 | end 15 | 16 | if not griderr or not windowerr or not hotkeyerr or not alerterr then 17 | hs.showerror("Some packages appear to be missing.") 18 | print("At least one package was missing. Have you installed the packages? See README.md.") 19 | print_if_not_table(grid) 20 | print_if_not_table(window) 21 | print_if_not_table(hotkey) 22 | print_if_not_table(alert) 23 | end 24 | 25 | mash = {"cmd", "alt", "ctrl"} 26 | 27 | INITIAL_GRID_HEIGHT = 2 28 | INITIAL_GRID_WIDTH = 4 29 | 30 | -- disable animations, ugh 31 | window.animationDuration = 0 32 | 33 | function centerpoint() 34 | local current = grid.getGrid() 35 | return { x = 1, y = 0, w = current.w / 2, h = current.h } 36 | end 37 | 38 | function fullheightatleftwithwidth(width) 39 | return { x = 0, y = 0, w = width, h = grid.getGrid().h } 40 | end 41 | function fullheightatrightwithwidth(width) 42 | local current = grid.getGrid() 43 | return { x = current.w - width, y = 0, w = width, h = current.h } 44 | end 45 | 46 | function interp(s, tab) 47 | return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end)) 48 | end 49 | 50 | grid.setGrid(hs.geometry({w=INITIAL_GRID_WIDTH, h=INITIAL_GRID_HEIGHT})) 51 | 52 | local grid_shortcuts = { 53 | [";"] = function() grid.snap(window.focusedWindow()) alert.show("╔═╦═╗\n s n \n╠═╬═╣\n a p \n╚═╩═╝") end, 54 | J = function() grid.pushWindowUp() alert.show("🔼") end, 55 | H = function() grid.pushWindowLeft() alert.show("◀️") end, 56 | L = function() grid.pushWindowRight() alert.show("▶️") end, 57 | K = function() grid.pushWindowDown() alert.show("🔽") end, 58 | I = function() grid.resizeWindowThinner() alert.show("⏩⏪") end, 59 | O = function() grid.resizeWindowWider() alert.show("⏪⏩") end, 60 | M = function() grid.maximizeWindow() alert.show("⏪⏫⏬⏩") end, 61 | C = function() grid.set(window.focusedWindow(), centerpoint(), window.focusedWindow():screen()) alert.show("↹") end, 62 | ["1"] = function() grid.set(window.focusedWindow(), fullheightatleftwithwidth(1), window.focusedWindow():screen()) alert.show("1") end, 63 | ["2"] = function() grid.set(window.focusedWindow(), fullheightatleftwithwidth(2), window.focusedWindow():screen()) alert.show("2") end, 64 | ["3"] = function() grid.set(window.focusedWindow(), fullheightatleftwithwidth(3), window.focusedWindow():screen()) alert.show("3") end, 65 | ["9"] = function() grid.set(window.focusedWindow(), fullheightatrightwithwidth(3), window.focusedWindow():screen()) alert.show("9") end, 66 | ["0"] = function() grid.set(window.focusedWindow(), fullheightatrightwithwidth(2), window.focusedWindow():screen()) alert.show("0") end, 67 | ["-"] = function() grid.set(window.focusedWindow(), fullheightatrightwithwidth(1), window.focusedWindow():screen()) alert.show("-") end, 68 | 69 | G = function() 70 | local point = grid.get(window.focusedWindow()) 71 | alert.show(interp("⬌ ${x} ⬍ ${y}\n\t${w} × ${h}", point)) 72 | end, 73 | Y = function() grid.resizeWindowTaller() alert.show("⏫⏬") end, 74 | U = function() grid.resizeWindowShorter() alert.show("⏬⏫") end, 75 | N = function() grid.set(window.focusedWindow(), centerpoint(), window.focusedWindow():screen():next()) alert.show("➡️") end, 76 | P = function() grid.set(window.focusedWindow(), centerpoint(), window.focusedWindow():screen():previous()) alert.show("⬅️") end, 77 | T = function() 78 | local cp = centerpoint() 79 | cp["h"] = 1 80 | grid.set(window.focusedWindow(), cp, window.focusedWindow():screen()) 81 | alert.show("🎥") 82 | end, 83 | } 84 | print("If Hammerspoon console windows can be manipulated, but others cannot, ".. 85 | "ensure that Hammerspoon is allowed in Accessibility preferences.") 86 | 87 | for key, func in pairs(grid_shortcuts) do 88 | hotkey.bind(mash, key, func) 89 | end 90 | -------------------------------------------------------------------------------- /dotfiles/irbrc: -------------------------------------------------------------------------------- 1 | begin 2 | # use Pry if it exists 3 | require 'pry' 4 | Pry.start || exit 5 | rescue LoadError 6 | end 7 | -------------------------------------------------------------------------------- /dotfiles/pryrc: -------------------------------------------------------------------------------- 1 | # vi: ft=ruby : 2 | # encoding: utf-8 3 | 4 | PRY_GOODIES = [] 5 | PRY_BUMMERS = [] 6 | 7 | ruby_version = if defined? RUBY_VERSION && defined? RUBY_PATCHLEVEL 8 | "#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}" 9 | elsif defined? RUBY_DESCRIPTION 10 | RUBY_DESCRIPTION.split(' ')[1].sub('p', '-p') 11 | else 12 | (`ruby -v` || '').split(' ')[1].sub('p', '-p') 13 | end 14 | 15 | %w( 16 | hirb-unicode 17 | hirb 18 | pry-theme 19 | pry-coolline 20 | ).each do |gem| 21 | begin 22 | require gem 23 | PRY_GOODIES << gem 24 | rescue LoadError 25 | PRY_BUMMERS << gem 26 | end 27 | end 28 | 29 | # Slightly dirty hack to fully support in-session Hirb.disable/enable toggling 30 | if defined? Hirb 31 | Hirb::View.instance_eval do 32 | def enable_output_method 33 | @output_method = true 34 | @old_print = Pry.config.print 35 | Pry.config.print = proc do |*args| 36 | Hirb::View.view_or_page_output(args[1]) || @old_print.call(*args) 37 | end 38 | end 39 | 40 | def disable_output_method 41 | Pry.config.print = @old_print 42 | @output_method = nil 43 | end 44 | end 45 | 46 | Hirb.enable 47 | end 48 | 49 | # Awesome print is nice at times. 50 | AwesomePrint.pry! if defined? AwesomePrint 51 | 52 | # Configuration 53 | Pry.config.pager = true 54 | Pry.config.color = true 55 | Pry.config.editor = 'vim' 56 | #Pry.config.prompt = Pry::NAV_PROMPT 57 | Pry.config.theme = 'pry-modern-256' 58 | 59 | Pry.config.commands.instance_eval do 60 | alias_command 'h', 'hist --tail 20', desc: 'Last 20 commands' 61 | end 62 | 63 | # Ensure ~/.pry exists. 64 | File.expand_path('~/.pry/history').tap do |history_file| 65 | dir = File.dirname(history_file) 66 | Dir.mkdir dir unless Dir.exist? dir 67 | #Pry.config.history.file = history_file 68 | end 69 | 70 | # Welcome message. 71 | print "Pry running on #{ruby_version} " 72 | print "with RubyGems #{Gem::VERSION} " if defined? Gem::VERSION 73 | puts "and #{PRY_GOODIES.join ', '}." 74 | puts "Unable to load gems: #{PRY_BUMMERS.join ', '}" unless PRY_BUMMERS.empty? 75 | 76 | # EOF 77 | -------------------------------------------------------------------------------- /dotfiles/rvmrc: -------------------------------------------------------------------------------- 1 | rvm_silence_path_mismatch_check_flag=1 2 | -------------------------------------------------------------------------------- /dotfiles/tmux.conf: -------------------------------------------------------------------------------- 1 | # This configuration will confuse you just like it confuses me 2 | 3 | # http://stahlke.org/dan/tmux-nested/ 4 | # https://github.com/CrystalSpore/tmux-settings/blob/master/.tmux.conf 5 | 6 | # Ctrl-a --> tmux prefix key 7 | # Ctrl-t --> new tab 8 | # Shift-Left --> prev tab 9 | # Shift-Right --> next tab 10 | # Shift-Ctrl-Left --> swap tab left 11 | # Shift-Ctrl-Right --> swap tab right 12 | # Ctrl-a | --> split window horizontally 13 | # Ctrl-a _ --> split window vertically 14 | # Ctrl-a r --> reload config 15 | # Ctrl-a c --> clear tmux history 16 | 17 | # set -g default-terminal "screen-256color" 18 | set -g default-terminal "xterm-256color" 19 | 20 | unbind C-b 21 | set -g prefix C-a 22 | 23 | set -g status-bg colour40 24 | 25 | #setw -g window-status-current-bg colour40 26 | # split panes using | and - 27 | bind | split-window -h 28 | bind _ split-window -v 29 | unbind '"' 30 | unbind % 31 | 32 | # rebind c to clear history 33 | bind c send-keys "clear && tmux clear-history" \; send-keys "Enter" 34 | 35 | # reload config file (change file location to your the tmux.conf you want to use) 36 | bind r source-file ~/.tmux.conf 37 | 38 | # switch panes using Alt-arrow without prefix 39 | bind -n M-Left select-pane -L 40 | bind -n M-Right select-pane -R 41 | bind -n M-Up select-pane -U 42 | bind -n M-Down select-pane -D 43 | 44 | bind -n C-t new-window -a 45 | bind -n S-left prev 46 | bind -n S-right next 47 | bind -n S-C-left swap-window -t -1 48 | bind -n S-C-right swap-window -t +1 49 | 50 | bind -n M-F11 set -qg status-bg colour25 51 | bind -n M-F12 set -qg status-bg colour40 52 | bind -n S-up \ 53 | send-keys M-F12 \; \ 54 | set -qg status-bg colour25 \; \ 55 | unbind -n S-left \; \ 56 | unbind -n S-right \; \ 57 | unbind -n S-C-left \; \ 58 | unbind -n S-C-right \; \ 59 | unbind -n C-t \; \ 60 | set -qg prefix C-b 61 | bind -n S-down \ 62 | send-keys M-F11 \; \ 63 | set -qg status-bg colour40 \; \ 64 | bind -n S-left prev \; \ 65 | bind -n S-right next \; \ 66 | bind -n S-C-left swap-window -t -1 \; \ 67 | bind -n S-C-right swap-window -t +1 \; \ 68 | bind -n C-t new-window -a -c "#{pane_current_path}" \; \ 69 | set -qg prefix C-a 70 | 71 | # turns on mouse support in tmux 2.1+ 72 | set -g mouse on 73 | -------------------------------------------------------------------------------- /dotfiles/vim/airline.vim: -------------------------------------------------------------------------------- 1 | " From https://github.com/binarycleric/dot-vim/blob/master/.vimrc 2 | 3 | " So airline doesn't sit and wait for other things to happen. So annoying. 4 | set ttimeoutlen=50 5 | 6 | let g:airline_powerline_fonts = 1 7 | let g:bufferline_echo = 0 8 | 9 | "let g:airline_left_sep = "" 10 | "let g:airline_left_alt_sep = "" 11 | "let g:airline_right_sep = "" 12 | "let g:airline_right_alt_sep = "" 13 | let g:airline_branch_prefix = "" 14 | let g:airline_readonly_symbol = "" 15 | let g:airline_theme = 'bubblegum' 16 | 17 | if !exists('g:airline_symbols') 18 | let g:airline_symbols = {} 19 | endif 20 | 21 | let g:airline_symbols.crypt = '🔒' 22 | let g:airline_symbols.linenr = '␤' 23 | let g:airline_symbols.maxlinenr = '☰' 24 | let g:airline_symbols.branch = '⎇' 25 | let g:airline_symbols.paste = 'ρ' 26 | let g:airline_symbols.spell = 'Ꞩ' 27 | let g:airline_symbols.notexists = '∄' 28 | let g:airline_symbols.whitespace = 'Ξ' 29 | 30 | let g:airline#extensions#whitespace#checks = ['indent'] 31 | let airline#extensions#hunks#non_zero_only = 1 32 | 33 | if exists('aairline#section#create') " if airline is installed 34 | let g:airline_section_b = "" 35 | let g:airline_section_y = "" 36 | let g:airline_section_z = airline#section#create(['linenr', 'maxlinenr']) 37 | " let g:airline_section_z = "" 38 | endif 39 | -------------------------------------------------------------------------------- /dotfiles/vim/autoload/scss_indent.vim: -------------------------------------------------------------------------------- 1 | " Not sure where I got this 2 | " usage: 3 | " set indentexpr=scss_indent#GetIndent(v:lnum) 4 | fun! scss_indent#GetIndent(lnum) 5 | " { -> increase indent 6 | " } -> decrease indent 7 | if a:lnum == 1 8 | " start at 0 indentation 9 | return 0 10 | endif 11 | 12 | " try to find last line ending with { or } 13 | " ignoring // comments 14 | let regex = '\([{}]\)\%(\/\/.*\)\?$' 15 | let nr = search(regex, 'bnW') 16 | if nr > 0 17 | let last = indent(nr) 18 | let m = matchlist(getline(nr), regex) 19 | let m_curr = matchlist(getline(a:lnum), regex) 20 | echoe string(m).string(m_curr) 21 | if !empty(m_curr) && m_curr[1] == '}' && m[1] == '{' 22 | " last was open, current is close, use same indent 23 | return last 24 | elseif !empty(m_curr) && m_curr[1] == '}' && m[1] == '}' 25 | " } line and last line was }: decrease 26 | return last - &sw 27 | endif 28 | if m[1] == '{' 29 | " line after {: increase indent 30 | return last + &sw 31 | else 32 | " line after } or { - same indent 33 | return last 34 | endif 35 | else 36 | return 0 37 | endif 38 | endfun 39 | -------------------------------------------------------------------------------- /dotfiles/vim/autoload/xmlformatter.vim: -------------------------------------------------------------------------------- 1 | " XML formatter 2 | " Not sure where I got this. 3 | function! DoFormatXML() range 4 | " Save the file type 5 | let l:origft = &ft 6 | 7 | " Clean the file type 8 | set ft= 9 | 10 | " Add fake initial tag (so we can process multiple top-level elements) 11 | exe ":let l:beforeFirstLine=" . a:firstline . "-1" 12 | if l:beforeFirstLine < 0 13 | let l:beforeFirstLine=0 14 | endif 15 | exe a:lastline . "put =''" 16 | exe l:beforeFirstLine . "put =''" 17 | exe ":let l:newLastLine=" . a:lastline . "+2" 18 | if l:newLastLine > line('$') 19 | let l:newLastLine=line('$') 20 | endif 21 | 22 | " Remove XML header 23 | exe ":" . a:firstline . "," . a:lastline . "s/<\?xml\\_.*\?>\\_s*//e" 24 | 25 | " Recalculate last line of the edited code 26 | let l:newLastLine=search('') 27 | 28 | " Execute external formatter 29 | exe ":silent " . a:firstline . "," . l:newLastLine . "!xmllint --noblanks --format --recover -" 30 | 31 | " Recalculate first and last lines of the edited code 32 | let l:newFirstLine=search('') 33 | let l:newLastLine=search('') 34 | 35 | " Get inner range 36 | let l:innerFirstLine=l:newFirstLine+1 37 | let l:innerLastLine=l:newLastLine-1 38 | 39 | " Remove extra unnecessary indentation 40 | exe ":silent " . l:innerFirstLine . "," . l:innerLastLine "s/^ //e" 41 | 42 | " Remove fake tag 43 | exe l:newLastLine . "d" 44 | exe l:newFirstLine . "d" 45 | 46 | " Put the cursor at the first line of the edited code 47 | exe ":" . l:newFirstLine 48 | 49 | " Restore the file type 50 | exe "set ft=" . l:origft 51 | endfunction 52 | command! -range=% FormatXML ,call DoFormatXML() 53 | 54 | nmap x :%FormatXML 55 | vmap x :FormatXML 56 | -------------------------------------------------------------------------------- /dotfiles/vim/bundles.vim: -------------------------------------------------------------------------------- 1 | " vim-plug itself, to get help 2 | Plug 'junegunn/vim-plug' 3 | 4 | " set sensible defaults 5 | Plug 'tpope/vim-sensible' 6 | 7 | " zenburn colorscheme 8 | Plug 'jnurmine/Zenburn' 9 | " distraction-free writing with :Goyo 10 | Plug 'junegunn/goyo.vim', { 'for': 'markdown' } 11 | " Markdown rendering with :MarkdownPreview and :MarkdownPreviewStop 12 | Plug 'iamcco/markdown-preview.nvim', { 'do': { -> mkdp#util#install() }, 'for': ['markdown', 'vim-plug']} 13 | 14 | " airline for nice stats 15 | Plug 'vim-airline/vim-airline' 16 | Plug 'vim-airline/vim-airline-themes' 17 | 18 | " git integration for the gutter 19 | Plug 'airblade/vim-gitgutter' 20 | " git integration everywhere 21 | Plug 'tpope/vim-fugitive' 22 | 23 | " file navigation 24 | Plug 'scrooloose/nerdtree' 25 | " fuzzy finder 26 | Plug 'ctrlpvim/ctrlp.vim' 27 | Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } 28 | Plug 'junegunn/fzf.vim' 29 | " .editorconfig support 30 | Plug 'editorconfig/editorconfig-vim' 31 | " better commenting 32 | Plug 'scrooloose/nerdcommenter' 33 | " whitespace highlighting 34 | Plug 'ntpeters/vim-better-whitespace' 35 | " floating terminal 36 | Plug 'voldikss/vim-floaterm' 37 | 38 | " improves slash searching 39 | Plug 'junegunn/vim-slash' 40 | " hit zz to center a search hit 41 | noremap (slash-after) zz 42 | 43 | " surround control - type cs'" to turn single quotes to double! 44 | Plug 'tpope/vim-surround' 45 | 46 | " syntax checking 47 | "Plug 'vim-syntastic/syntastic' 48 | " linting 49 | Plug 'w0rp/ale' 50 | 51 | " startup screen with most recently used files 52 | Plug 'mhinz/vim-startify' 53 | 54 | """""""" language support 55 | " polyglot handles most of them now 56 | Plug 'sheerun/vim-polyglot' 57 | " hocon for scala 58 | Plug 'GEverding/vim-hocon' 59 | " ledger 60 | Plug 'ledger/vim-ledger', { 'for': 'ledger' } 61 | Plug 'rcaputo/vim-ledger_x', { 'for': 'ledger' } 62 | " folding for yaml 63 | Plug 'pedrohdz/vim-yaml-folds', { 'for': 'yaml' } 64 | " :Rubocop -a 65 | Plug 'ngmy/vim-rubocop', { 'for': 'ruby' } 66 | " Java properties files 67 | Plug 'kamichidu/vim-edit-properties' 68 | 69 | " Gemini text 70 | Plug 'https://tildegit.org/sloum/gemini-vim-syntax.git' 71 | 72 | " automatic formatting - I may regret this 73 | Plug 'Chiel92/vim-autoformat' 74 | 75 | " zettelkasten 76 | Plug 'fiatjaf/neuron.vim' 77 | " jq interactivity - https://github.com/bfrg/vim-jqplay 78 | Plug 'bfrg/vim-jqplay' 79 | " jq language support 80 | Plug 'bfrg/vim-jq' 81 | 82 | " flake8 for python 83 | Plug 'nvie/vim-flake8' 84 | 85 | " Brewfile 86 | Plug 'bfontaine/Brewfile.vim' 87 | 88 | " Language Server Protocol 89 | Plug 'prabirshrestha/vim-lsp' 90 | Plug 'mattn/vim-lsp-settings' 91 | 92 | " Autocomplete 93 | Plug 'prabirshrestha/asyncomplete.vim' 94 | Plug 'prabirshrestha/asyncomplete-lsp.vim' 95 | 96 | 97 | " Confluence, so I can mock up JIRA tickets in VIM without losing data 98 | Plug 'flniu/confluencewiki.vim' 99 | " Starlark, for Vela 100 | Plug 'cappyzawa/starlark.vim' 101 | -------------------------------------------------------------------------------- /dotfiles/vim/update-plug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ 4 | https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim 5 | -------------------------------------------------------------------------------- /dotfiles/vimrc: -------------------------------------------------------------------------------- 1 | " This sucks, make it better. 2 | 3 | set nocompatible " be iMproved, required 4 | filetype off " required 5 | 6 | " set the runtime path to include Vundle and initialize 7 | "set rtp+=~/.vim/bundle/Vundle.vim 8 | "call vundle#begin("~/.vim_bundles") 9 | " let Vundle manage Vundle, required 10 | "Plugin 'VundleVim/Vundle.vim' 11 | 12 | call plug#begin('~/.local/vim/bundles') 13 | 14 | if filereadable(expand("~/.vim/bundles.vim")) 15 | source ~/.vim/bundles.vim 16 | endif 17 | if filereadable(expand("~/.local/vim/bundles.vim")) 18 | source ~/.local/vim/bundles.vim 19 | endif 20 | 21 | call plug#end() 22 | "call vundle#end() " required 23 | filetype plugin indent on " required 24 | 25 | set encoding=utf-8 26 | set fileencoding=utf-8 27 | set backspace=indent,eol,start 28 | 29 | syntax on 30 | set tabstop=2 31 | set shiftwidth=2 32 | set softtabstop=2 33 | set laststatus=2 " always show status bar 34 | 35 | set nocompatible 36 | 37 | filetype on 38 | filetype indent on 39 | filetype plugin on 40 | 41 | set ic 42 | set hls 43 | set showmatch 44 | 45 | set expandtab 46 | set autoindent 47 | 48 | if $TERM_PROGRAM == 'Apple_Terminal' 49 | colorscheme desert 50 | else 51 | if $TERM_PROGRAM == 'MacVim.app' 52 | colorscheme zenburn 53 | else 54 | let &t_8f = "\[38;2;%lu;%lu;%lum" 55 | let &t_8b = "\[48;2;%lu;%lu;%lum" 56 | colorscheme zenburn 57 | set t_Co=256 58 | " this breaks color in mosh 59 | " set termguicolors 60 | endif 61 | endif 62 | 63 | set number 64 | set ruler 65 | 66 | set showmode 67 | set showcmd 68 | set visualbell 69 | set ttyfast 70 | 71 | set incsearch 72 | set showmatch 73 | set hlsearch 74 | 75 | set wrap 76 | set textwidth=79 77 | set formatoptions=qrn1 78 | 79 | inoremap 80 | nnoremap 81 | vnoremap 82 | 83 | nnoremap ; : 84 | 85 | if filereadable(expand("~/.vim/airline.vim")) 86 | set guifont=FiraCodeNerdFontCompleteM-Regular:h16 87 | source ~/.vim/airline.vim 88 | endif 89 | 90 | " XML formatter 91 | function! DoFormatXML() range 92 | " Save the file type 93 | let l:origft = &ft 94 | 95 | " Clean the file type 96 | set ft= 97 | 98 | " Add fake initial tag (so we can process multiple top-level elements) 99 | exe ":let l:beforeFirstLine=" . a:firstline . "-1" 100 | if l:beforeFirstLine < 0 101 | let l:beforeFirstLine=0 102 | endif 103 | exe a:lastline . "put =''" 104 | exe l:beforeFirstLine . "put =''" 105 | exe ":let l:newLastLine=" . a:lastline . "+2" 106 | if l:newLastLine > line('$') 107 | let l:newLastLine=line('$') 108 | endif 109 | 110 | " Remove XML header 111 | exe ":" . a:firstline . "," . a:lastline . "s/<\?xml\\_.*\?>\\_s*//e" 112 | 113 | " Recalculate last line of the edited code 114 | let l:newLastLine=search('') 115 | 116 | " Execute external formatter 117 | exe ":silent " . a:firstline . "," . l:newLastLine . "!xmllint --noblanks --format --recover -" 118 | 119 | " Recalculate first and last lines of the edited code 120 | let l:newFirstLine=search('') 121 | let l:newLastLine=search('') 122 | 123 | " Get inner range 124 | let l:innerFirstLine=l:newFirstLine+1 125 | let l:innerLastLine=l:newLastLine-1 126 | 127 | " Remove extra unnecessary indentation 128 | exe ":silent " . l:innerFirstLine . "," . l:innerLastLine "s/^ //e" 129 | 130 | " Remove fake tag 131 | exe l:newLastLine . "d" 132 | exe l:newFirstLine . "d" 133 | 134 | " Put the cursor at the first line of the edited code 135 | exe ":" . l:newFirstLine 136 | 137 | " Restore the file type 138 | exe "set ft=" . l:origft 139 | endfunction 140 | command! -range=% FormatXML ,call DoFormatXML() 141 | 142 | nmap x :%FormatXML 143 | vmap x :FormatXML 144 | 145 | map :NERDTreeToggle 146 | 147 | "folding settings 148 | set foldmethod=indent "fold based on indent 149 | set foldnestmax=10 "deepest fold is 10 levels 150 | set nofoldenable "dont fold by default 151 | set foldlevel=1 "this is just what i use 152 | 153 | au BufRead,BufNewFile *.scss set filetype=scss 154 | autocmd BufNewFile,BufRead *.md set filetype=markdown 155 | autocmd BufNewFile,BufRead *.gradle set filetype=groovy 156 | autocmd BufWritePre * StripWhitespace 157 | 158 | " RUST 159 | " run rustfmt on save, if available 160 | let g:rustfmt_autosave = 1 161 | " use rust-analyzer for linting 162 | let g:ale_linters = {'rust': ['analyzer']} 163 | " use rust-analyzer with vim-lsp 164 | if executable('rust-analyzer') 165 | au User lsp_setup call lsp#register_server({ 166 | \ 'name': 'Rust Language Server', 167 | \ 'cmd': {server_info->['rust-analyzer']}, 168 | \ 'whitelist': ['rust'], 169 | \ 'initialization_options': { 170 | \ 'cargo': { 171 | \ 'buildScripts': { 172 | \ 'enable': v:true, 173 | \ }, 174 | \ }, 175 | \ 'procMacro': { 176 | \ 'enable': v:true, 177 | \ }, 178 | \ }, 179 | \ }) 180 | endif 181 | 182 | " set goyo distraction-free writing defaults 183 | let g:goyo_width = 100 184 | let g:goyo_height = "85%" 185 | let g:goyo_linenr = 0 186 | 187 | com! FormatJSON %!jq . 188 | nmap =j :FormatJSON 189 | 190 | " run flake8 when saving Python files 191 | autocmd BufWritePost *.py call flake8#Flake8() 192 | 193 | 194 | -------------------------------------------------------------------------------- /install-via-coursier.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | coursier install scalafmt 4 | -------------------------------------------------------------------------------- /iterm/Brewfile.iterm: -------------------------------------------------------------------------------- 1 | cask 'iterm2' 2 | 3 | cask 'font-fira-code' 4 | cask 'font-fira-mono-for-powerline' 5 | -------------------------------------------------------------------------------- /iterm/Zenburn.itermcolors: -------------------------------------------------------------------------------- 1 | ../themes/Zenburn.itermcolors -------------------------------------------------------------------------------- /link_dotbin.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | RM=$1 3 | NO_PREPEND="" 4 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | 6 | source "${SCRIPT_DIR}/_helpers.sh" 7 | 8 | BIN_SCRIPTS_DIR="$SCRIPT_DIR/scripts" 9 | DOTBIN_DIR="$HOME/.bin" 10 | 11 | if [[ ! -d "$BIN_SCRIPTS_DIR" ]]; then 12 | echo "The Hejmo scripts directory does not appear to be present at $BIN_SCRIPTS_DIR" 13 | echo "Please check for its existence." 14 | exit 1 15 | fi 16 | 17 | mkdir -p "$DOTBIN_DIR" 18 | 19 | if [[ ! -d "$DOTBIN_DIR" ]]; then 20 | echo "$DOTBIN_DIR directory does not appear to be present." 21 | echo "Please check for its existence, maybe manually create it." 22 | exit 1 23 | fi 24 | 25 | link_all_files_in_dir "${BIN_SCRIPTS_DIR}" "${DOTBIN_DIR}" "${RM}" "${NO_PREPEND}" 26 | -------------------------------------------------------------------------------- /link_dotfiles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | case "$(uname -s)" in 4 | Darwin) LN_OPTIONS="sFh" ;; 5 | Linux) LN_OPTIONS="sf" ;; 6 | # TODO: determine safe defaults for OSes I never use 7 | *) LN_OPTIONS="sf" ;; 8 | esac 9 | 10 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 11 | 12 | DOTFILES_DIR="${SCRIPT_DIR}/dotfiles" 13 | 14 | for f in $(ls ${DOTFILES_DIR}); do 15 | TARGET="${DOTFILES_DIR}/${f}" 16 | LINK="${HOME}/.${f}" 17 | if [[ ! -z $RM ]]; then 18 | echo "Removing $LINK" 19 | rm -f "$LINK" 20 | fi 21 | echo "Linking $LINK to $TARGET" 22 | ln "-${LN_OPTIONS}" "$TARGET" "$LINK" 23 | done 24 | -------------------------------------------------------------------------------- /rebuild_bat_config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | BAT_CONFIG_DIR="$(bat --config-dir)" 3 | 4 | clone_or_update() { 5 | local dir="${1}" 6 | local repo_url="${2}" 7 | 8 | if [ -d "${dir}" ]; then 9 | echo "${dir} exists, updating…" 10 | pushd "${dir}" > /dev/null || exit 8 11 | git pull 12 | popd > /dev/null || exit 9 13 | else 14 | echo "${dir} doesn't exist, cloning…" 15 | git clone "${repo_url}" "${dir}" 16 | fi 17 | } 18 | 19 | 20 | echo "Rebuilding bat config in ${BAT_CONFIG_DIR}…" 21 | ## 22 | # Syntaxes 23 | ## 24 | BAT_SYNTAXES="${BAT_CONFIG_DIR}/syntaxes" 25 | mkdir -p "${BAT_SYNTAXES}" 26 | cd "${BAT_SYNTAXES}" || (echo "Unable to cd to ${BAT_SYNTAXES}" && exit 2) 27 | 28 | # List syntaxes here! 29 | clone_or_update "Ledger" "https://github.com/vqv/Ledger3.git" 30 | 31 | ## 32 | # Themes 33 | ## 34 | 35 | BAT_THEMES="${BAT_CONFIG_DIR}/themes" 36 | mkdir -p "${BAT_THEMES}" 37 | cd "${BAT_THEMES}" || (echo "Unable to cd to ${BAT_THEMES}" && exit 2) 38 | 39 | # List themes here! 40 | # None right now… 41 | 42 | echo "Rebuilding bat cache…" 43 | bat cache --build 44 | 45 | last="$?" 46 | if [ "${last}" -eq 0 ]; then 47 | echo "It probably worked!" 48 | else 49 | echo "It probably failed." 50 | echo "Reset with [bat cache --clear] if things went real bad." 51 | exit "${last}" 52 | fi 53 | -------------------------------------------------------------------------------- /scripts/$: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Makes pasted commands execute when they're preceded with $ 3 | warning_color="" 4 | command_color="" 5 | reset="" 6 | indicator="⚠️ " 7 | if [[ -z "${NO_WARNING}" ]]; then 8 | >&2 echo "${indicator}${warning_color}pasted command:${command_color}" "${@}" "${reset}" 9 | >&2 echo "Running in 5 seconds..." 10 | sleep 5 11 | fi 12 | "$@" 13 | -------------------------------------------------------------------------------- /scripts/401k_contribution_calc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ## WTF is this? 4 | # 5 | # Some 401k administrators lack an option to set contributions to level that 6 | # achieves the maximum deferrable contribution. For 2017, that amount is $18,000. 7 | # This little script will help you calculate what you percentage you need to use 8 | # when that's the only thing you can set. 9 | # 10 | # Why the multiple percentage ranges? Some 401k administrators don't let you set 11 | # a high precision percentage. These lines will tell you how much you're losing 12 | # because of that imprecision. 13 | # 14 | # TL;DR Tell your 401k administrator to get with the program and do deferral 15 | # maximization. 16 | require 'date' 17 | 18 | # https://www.irs.gov/retirement-plans/plan-participant-employee/retirement-topics-401k-and-profit-sharing-plan-contribution-limits 19 | MAX_DEFERRABLE = (ENV['MAX_DEFERRABLE'] || 23_000.00).to_f 20 | 21 | if ARGV.size <= 1 22 | weeks_remaining_in_current_calendar_year = 52 - Date.today().cweek 23 | me = File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME)) 24 | STDERR.puts "Usage: #{me} [amount already contributed]" 25 | STDERR.puts 'Example, for the beginning of the year for someone who makes $60,000/yr with 26 pay periods:' 26 | STDERR.puts "\t#{me} #{(weeks_remaining_in_current_calendar_year / 2).floor} 2500" 27 | STDERR.puts "Set MAX_DEFERRABLE envvar if it's not #{MAX_DEFERRABLE}." 28 | exit 1 29 | end 30 | 31 | PERIODS_REMAINING = ARGV[0].to_f 32 | PAY_PER_PERIOD = ARGV[1].to_f 33 | 34 | ALREADY_CONTRIBUTED = if ARGV.size == 3 35 | ARGV[2].to_f 36 | else 37 | 0.0 38 | end 39 | 40 | remaining = MAX_DEFERRABLE - ALREADY_CONTRIBUTED 41 | per_period = remaining / PERIODS_REMAINING 42 | 43 | puts <<~EH 44 | #{MAX_DEFERRABLE} max deferrable. 45 | #{ALREADY_CONTRIBUTED} already contributed. 46 | #{remaining} remaining to be contributed. 47 | #{PERIODS_REMAINING} periods remaining. 48 | #{per_period} contribution per period to reach #{remaining}. 49 | #{PAY_PER_PERIOD} pay each period. 50 | EH 51 | 52 | contribution = per_period / PAY_PER_PERIOD 53 | (0...5).each do |places| 54 | percent = (contribution * 100.0).floor(places) 55 | year_total = ((percent / 100.0) * PAY_PER_PERIOD * PERIODS_REMAINING).round(2) 56 | missed_out = (remaining - year_total).round(2) 57 | puts "#{percent}% is recommended contribution at #{places} decimal places, totaling #{year_total} for the year, missing out on #{missed_out} because of safe decimal truncation." 58 | end 59 | -------------------------------------------------------------------------------- /scripts/_t_completion: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | _e() { [[ -n "${DEBUG_COMPLETIONS}" ]] && echo "$1" >> "${HOME}/completions.log"; } 4 | 5 | _main() { 6 | local i=1 cmd 7 | 8 | 9 | _e "comp_words = ${COMP_WORDS[*]}" 10 | 11 | # find the subcommand 12 | while [[ "$i" -lt "$COMP_CWORD" ]] 13 | do 14 | local s="${COMP_WORDS[i]}" 15 | case "$s" in 16 | -*) ;; 17 | *) 18 | cmd="$s" 19 | break 20 | ;; 21 | esac 22 | (( i++ )) 23 | done 24 | 25 | _e "comp_cword = ${COMD_CWORD}" 26 | _e "cmd = $cmd" 27 | 28 | if [[ "$i" -eq "$COMP_CWORD" ]] 29 | then 30 | local cur="${COMP_WORDS[COMP_CWORD]}" 31 | local nocolon 32 | 33 | _get_comp_words_by_ref -n : -c nocolon 34 | 35 | _e "cur = $cur" 36 | _e "nocolon = ${nocolon}" 37 | 38 | COMPREPLY=($(compgen -W "$(t actions)" -- "$cur")) 39 | _e "COMPREPLY = ${COMPREPLY[*]}" 40 | 41 | return # return early if we're still completing the 'current' command 42 | fi 43 | 44 | # we've completed the 'current' command and now need to call the next completion function 45 | # subcommands have their own completion functions 46 | case "$cmd" in 47 | sw|switch|"in") _list_projects ;; 48 | start) _list_projects;; 49 | log) _list_projects;; 50 | *) ;; 51 | esac 52 | } 53 | 54 | _list_projects () 55 | { 56 | local cur="${COMP_WORDS[COMP_CWORD]}" 57 | COMPREPLY=($(compgen -W "$(t projects)" -- "$cur")) 58 | } 59 | export COMP_WORDBREAKS="${COMP_WORDBREAKS//:}" 60 | complete -o bashdefault -F _main t 61 | -------------------------------------------------------------------------------- /scripts/add-coursier: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | SBT_VERSION="${1}" 3 | set -eu 4 | SBT_VERSION_FALLBACK="1.1.10-M11" 5 | BUILD_PLUGINS_SBT="project/plugins.sbt" 6 | META_BUILD_PLUGINS_SBT="project/project/plugins.sbt" 7 | 8 | if [[ -z "${SBT_VERSION}" ]]; then 9 | if [[ -z "$(command -v coursier)" ]]; then 10 | SBT_VERSION=${SBT_VERSION_FALLBACK} 11 | else 12 | SBT_VERSION="$(coursier --help | head -n 1 | cut -d ' ' -f 2)" 13 | fi 14 | fi 15 | 16 | if grep -iq coursier "${BUILD_PLUGINS_SBT}"; then 17 | echo "Coursier is appears in ${BUILD_PLUGINS_SBT}, so it's probably already installed." 18 | echo "Check that file and ${META_BUILD_PLUGINS_SBT}!" 19 | echo "${BUILD_PLUGINS_SBT} should have:" 20 | echo 21 | printf "\t" 22 | echo 'addSbtPlugin("io.get-coursier" % "sbt-coursier" % "'"${SBT_VERSION}"'")' 23 | echo 24 | echo "unless there are other plugins listed there, in which case the above should be in" 25 | echo "${META_BUILD_PLUGINS_SBT} and this should be in ${BUILD_PLUGINS_SBT}:" 26 | echo 27 | printf "\t" 28 | echo "addSbtCoursier" 29 | exit 1 30 | fi 31 | 32 | addCoursierTo() { 33 | target="${1}" 34 | mkdir -p "$(dirname "${target}")" 35 | touch "${target}" 36 | echo -e '\naddSbtPlugin("io.get-coursier" % "sbt-coursier" % "'"${SBT_VERSION}"'")' >> "${target}" 37 | } 38 | addReferenceTo() { 39 | target="${1}" 40 | touch "${target}" 41 | mkdir -p "$(dirname "${target}")" 42 | echo -e '\naddSbtCoursier' >> "${target}" 43 | } 44 | 45 | if [[ -f "${BUILD_PLUGINS_SBT}" ]]; then 46 | addCoursierTo "${META_BUILD_PLUGINS_SBT}" 47 | addReferenceTo "${BUILD_PLUGINS_SBT}" 48 | else 49 | addCoursierTo "${BUILD_PLUGINS_SBT}" 50 | fi 51 | -------------------------------------------------------------------------------- /scripts/analyze_t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'date' 5 | require 'open3' 6 | 7 | # check for requirements 8 | deps = %w[ledger t gnuplot] 9 | # mkmf#find_executable uses which, which cannot find t 10 | deps_loc = deps.map { |cmd| `command -v #{cmd}` } 11 | raise "missing req'd in [${deps}]" unless deps_loc.all? { |s| !s.strip.empty? } 12 | 13 | # needs input from `ledger -J --weekly` 14 | # the last entry for a date is the one we want 15 | def parse_and_extract_weekly_cumul(all_entries) 16 | all_entries.each_with_object({}) do |entry, acc| 17 | date, amt = entry.split(' ') 18 | acc[date] = amt.to_f 19 | end 20 | end 21 | 22 | def cumulative_to_weekly(cumulative_entries) 23 | prev = 0.0 24 | cumulative_entries.map do |date, amt| 25 | weekly_amt = (amt.to_f - prev).round(1) 26 | prev = amt.to_f 27 | overunder40 = weekly_amt - 40 28 | [date, { weekly: weekly_amt, overunder: overunder40 }] 29 | end.to_h 30 | end 31 | 32 | def generate_par_data(first_day, last_day) 33 | start = Date.parse(first_day) 34 | finish = Date.parse(last_day) 35 | 36 | start.upto(finish) 37 | .select { |d| d.wday == start.wday } # same weekday 38 | .drop(1) # drop the first because we're seeding with it 39 | .reduce([[start, 40]]) { |acc, d| acc + [[d, acc.last[1] + 40]] } # add 40 | .to_h 41 | end 42 | 43 | WEEKLY_CUMULATIVE_IMG = 'weekly.png' 44 | def build_weekly_plot(first_day, last_day) 45 | <<~PLOT 46 | set xdata time 47 | set timefmt "%Y-%m-%d" 48 | set xrange ["#{first_day}":"#{last_day}"] 49 | set format x "%Y/%m/%d" 50 | set term png font "Arial" size 1280,720 51 | set xlabel "Date" 52 | set ylabel "Hours" 53 | set grid 54 | set title "Cumulative hours since tracking began, #{first_day}" 55 | set output "#{WEEKLY_CUMULATIVE_IMG}" 56 | set ytics nomirror 57 | set y2label "Hours factor (logarithmic, base 1.6)" 58 | set y2range [-3:6] 59 | set y2tics nomirror 60 | set logscale y2 1.6 61 | set style line 3 linetype 1 linewidth 2 linecolor rgb "green" 62 | set key left top 63 | 64 | plot "weekly_cumulative.dat" using 1:2 ls 1 title "Actual" with lines axis x1y1,\ 65 | "weekly_par.dat" using 1:2 ls 2 title "Par (40 hrs/wk)" with lines axis x1y1,\ 66 | "weekly.dat" using 1:3 ls 3 title "Over/Under 40 hrs/wk" with impulses axis x1y2 67 | PLOT 68 | end 69 | 70 | WEEKLY_BAR_IMG = 'weekly_bar.png' 71 | def build_weekly_bar_plot(first_day, last_day) 72 | <<~PLOT 73 | set term png font "Arial" size 1280,720 74 | set xlabel "Week starting date" 75 | set ylabel "Hours" 76 | set grid ytics 77 | set title "Weekly hours since #{first_day}" 78 | set output "#{WEEKLY_BAR_IMG}" 79 | set boxwidth 0.3 relative 80 | set style fill solid 81 | set xdata time 82 | set timefmt "%Y-%m-%d" 83 | set format x "%Y/%m/%d" 84 | set xrange ["#{first_day}":"#{last_day}"] 85 | set yrange [35:70] 86 | # set arrow from graph 0,first 40 to graph 1,first 40 nohead lc rgb "#000000" front 87 | 88 | # https://km.kkrach.de/p_moving_average_for_gnuplot/ 89 | n = 6 90 | do for [i=1:n] { 91 | eval(sprintf("back_n%d=0", i)) 92 | } 93 | shift = "(" 94 | do for [i=n:2:-1] { 95 | shift = sprintf("%sback_n%d = back_n%d, ", shift, i, i-1) 96 | } 97 | shift = shift."back_n1 = x)" 98 | sum = "(back_n1" 99 | do for [i=2:n] { 100 | sum = sprintf("%s+back_n%d", sum, i) 101 | } 102 | sum = sum.")" 103 | samples(x) = \$0 > (n-1) ? n : (\$0+1) 104 | avg_n(x) = (shift_n(x), @sum/samples(\$0)) 105 | shift_n(x) = @shift 106 | 107 | plot \ 108 | "weekly.dat" using 1:2 title "Hours during week" with boxes, \ 109 | 40 w lines title "Normal 40-hour week", \ 110 | "weekly.dat" using 1:(avg_n($2)) w l lc rgb "red" lw 3 title "avg\\_".n 111 | PLOT 112 | end 113 | 114 | def write_data(filename, data) 115 | File.open(filename, 'w') do |file| 116 | file.write data 117 | end 118 | puts "write: #{data.size} bytes written to #{filename}" 119 | end 120 | 121 | def entries_to_text(entries) 122 | entries.map do |k, v| 123 | values = if v.is_a?(String) 124 | v 125 | elsif v.is_a?(Array) 126 | v.join(' ') 127 | elsif v.is_a?(Hash) 128 | v.values.join(' ') 129 | else 130 | v.to_s 131 | end 132 | "#{k} #{values}" 133 | end.join("\n") 134 | end 135 | 136 | def run_gnuplot(script) 137 | _output, err, status = Open3.capture3('gnuplot', stdin_data: script) 138 | puts "gnuplot: err: #{err}" unless status.success? 139 | end 140 | 141 | def run_ledger_with_timelog(args) 142 | timelog = `t timelog`.strip 143 | cmd = "ledger -f '#{timelog}' #{args}" 144 | output, err, status = Open3.capture3(cmd) 145 | puts "ledger: err: #{cmd}\t\n\t#{err}" unless status.success? 146 | # puts "ledger: out: #{output}" if status.success? 147 | output.split("\n") 148 | end 149 | 150 | # get weekly register data from ledger in cumulative by week 151 | cumulative_weekly_data_lines = run_ledger_with_timelog('-J --weekly reg') 152 | 153 | # extract the last entry for a week because that's the weekly total 154 | cumulative_weekly = parse_and_extract_weekly_cumul(cumulative_weekly_data_lines) 155 | puts "analysis: weeks: #{cumulative_weekly.size}" 156 | 157 | # subtract the differences to get a total for each week individually 158 | per_week = cumulative_to_weekly(cumulative_weekly) 159 | 160 | first_day = per_week.keys.first 161 | last_day = per_week.keys.last 162 | puts "analysis: from #{first_day} to #{last_day}" 163 | 164 | # generate data for what a normal 40 hour week looks like 165 | par_data = generate_par_data(first_day, last_day) 166 | 167 | # do some statistics 168 | weekly_values = per_week.values.map { |pw| pw[:weekly] } 169 | mean = (weekly_values.sum / per_week.size).round(1) 170 | puts "analysis: mean per week, cumulative: #{mean} hrs" 171 | 172 | last_four_full_weeks = weekly_values.select { |v| v > 30 }.last(4) 173 | last_four_full_weeks_mean = (last_four_full_weeks.sum / 4).round(1) 174 | puts "analysis: mean per week, last 4 wks: #{last_four_full_weeks_mean} hrs" 175 | 176 | overunder = (cumulative_weekly.values.last - par_data.values.last).round(1) 177 | puts "analysis: cumulative overwork: #{overunder} hrs" 178 | 179 | # draw some graphs 180 | write_data 'weekly_cumulative.dat', entries_to_text(cumulative_weekly) 181 | write_data 'weekly.dat', entries_to_text(per_week) 182 | write_data 'weekly_par.dat', entries_to_text(par_data) 183 | run_gnuplot(build_weekly_plot(first_day, last_day)) 184 | run_gnuplot(build_weekly_bar_plot(first_day, last_day)) 185 | 186 | puts "plot: weekly cumulative written to #{WEEKLY_CUMULATIVE_IMG}" 187 | puts "plot: weekly bar written to #{WEEKLY_BAR_IMG}" 188 | -------------------------------------------------------------------------------- /scripts/bigtext: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | text="${*}" 3 | printf "\033#3%s\n" "${text}" 4 | printf "\033#4%s\n" "${text}" 5 | printf "\033#5" 6 | -------------------------------------------------------------------------------- /scripts/clapify: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | IFS=" " read -ra WORDS <<< "${@}" 4 | 5 | function join_with { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; } 6 | 7 | CLAP=" 👏 " 8 | 9 | SEPARATOR="${SEP:-$CLAP}" 10 | 11 | join_with "${SEPARATOR}" "${WORDS[@]}" 12 | 13 | -------------------------------------------------------------------------------- /scripts/claps: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "$@" | sed -e 's/\ /\ 👏\ \ /g' 3 | -------------------------------------------------------------------------------- /scripts/clipboard: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if [[ -z "$1" ]]; then 3 | pbpaste 4 | else 5 | pbcopy < "${1}" 6 | fi 7 | -------------------------------------------------------------------------------- /scripts/docker-digest: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Gets the digest of a given image when it's already local 3 | docker inspect -format='{{index .RepoDigests 0}}' "${@}" 4 | -------------------------------------------------------------------------------- /scripts/docker-image-size-compressed: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if [[ "${1}" == "-x" ]]; then 3 | shift 4 | set -x 5 | fi 6 | 7 | docker manifest inspect "${@}" | jq '[.layers[].size] | add' | numfmt --to=iec-i 8 | -------------------------------------------------------------------------------- /scripts/docker-image-size-uncompressed: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | docker inspect -f "{{ .Size }}" "${*}" | numfmt --to=iec-i 4 | -------------------------------------------------------------------------------- /scripts/docker-select-tag: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | 5 | IMAGE_BASE="${1}" 6 | 7 | if [[ -z "${IMAGE_BASE}" ]]; then 8 | >&2 echo "Usage: $0 " 9 | exit 1 10 | fi 11 | if ! command -v fzf >/dev/null; then 12 | >&2 echo "fzf not found, install it." 13 | exit 2 14 | fi 15 | 16 | tags=$(regctl tag list "${IMAGE_BASE}") 17 | 18 | # shellcheck disable=SC2312 19 | tag=$(echo "${tags}" | sort -V | fzf) 20 | 21 | image_tag="$(printf "%s:%s" "${IMAGE_BASE}" "${tag}")" 22 | 23 | digest=$(regctl image digest "${image_tag}") 24 | 25 | printf "%s@%s\n" "${image_tag}" "${digest}" 26 | -------------------------------------------------------------------------------- /scripts/docker-whoami: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Shows what user is used for docker login 3 | # currently only for macOS 4 | jq -r \ 5 | 'if (.credsStore == "osxkeychain") then (.auths | keys) else [] end | .[]' \ 6 | "${HOME}/.docker/config.json" | 7 | docker-credential-osxkeychain get | 8 | jq '{"url": .ServerURL, "user": .Username}' 9 | -------------------------------------------------------------------------------- /scripts/dtmfplay: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | from time import sleep 5 | 6 | tones = { 7 | '1': (697, 1209), 8 | '2': (697, 1336), 9 | '3': (697, 1477), 10 | 'A': (697, 1633), 11 | '4': (770, 1209), 12 | '5': (770, 1336), 13 | '6': (770, 1477), 14 | 'B': (770, 1633), 15 | '7': (852, 1209), 16 | '8': (852, 1336), 17 | '9': (852, 1477), 18 | 'C': (852, 1633), 19 | '*': (941, 1209), 20 | '0': (941, 1336), 21 | '#': (941, 1477), 22 | 'D': (941, 1633), 23 | } 24 | 25 | def play_input(digit): 26 | first, second = tones[digit] 27 | print(f"{digit}: {first},{second}") 28 | os.system(f"play -V1 -n synth 0.3 sin {first} sin {second} remix 1,2") 29 | 30 | def handle_input_char(ch): 31 | if ch in tones: 32 | play_input(ch) 33 | elif ch == ',' or ch == 'P': 34 | print(f"Pause") 35 | sleep(2) 36 | 37 | if __name__ == '__main__': 38 | [ handle_input_char(d) for d in sys.argv[1] ] 39 | 40 | -------------------------------------------------------------------------------- /scripts/duration_comparison.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Compares two Python timedelta duration timestamps 3 | # It'd be awfully nice if timedelta could parse its own string output… 4 | import sys 5 | import logging 6 | from datetime import timedelta 7 | 8 | 9 | def no_leading_zero(num: str) -> str: 10 | if len(num) > 1: 11 | return num.lstrip('0') 12 | else: 13 | # it's probably just 0 14 | return num 15 | 16 | def safely_int(num: str) -> int: 17 | return int(no_leading_zero(num)) 18 | 19 | # TODO: handle days 20 | def parse_duration(dur: str) -> timedelta: 21 | hours, minutes, seconds_and_microseconds = dur.split(':') 22 | seconds, microseconds = seconds_and_microseconds.split('.') 23 | time = list(map(safely_int, [hours, minutes, seconds, microseconds])) 24 | return timedelta( 25 | hours=time[0], 26 | minutes=time[1], 27 | seconds=time[2], 28 | microseconds=time[3]) 29 | 30 | first = parse_duration(sys.argv[1]) 31 | second = parse_duration(sys.argv[2]) 32 | 33 | if second > first: 34 | print(f"Second is {second - first} more than first") 35 | print(f"Second is {round(100*second / first, 3)}% more than first") 36 | print(f"First is {round(100*first / second, 3)}% of second") 37 | if first > second: 38 | print(f"First is {first - second} more than second") 39 | print(f"First is {round(100*first / second, 3)}% more than first") 40 | print(f"Second is {round(100*second / first, 3)}% of first") 41 | 42 | -------------------------------------------------------------------------------- /scripts/external-ip: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | curl -s https://ipchicken.com/ | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | uniq 4 | -------------------------------------------------------------------------------- /scripts/extract-ips: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # shellcheck disable=SC2086 4 | grep ${1:-${EXTRACT_IP_OPTIONS}} --extended-regexp --only-matching "([0-9]{1,3}[\.]){3}[0-9]{1,3}" 5 | -------------------------------------------------------------------------------- /scripts/fileweight: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env tcc -w -run 2 | // vim: set ft=c: 3 | // https://code.rosaelefanten.org/fileweight/file?name=fileweight.c 4 | /* 5 | * How much does a file weigh? 6 | * 7 | * Based on IBM's research, one bit takes between 8 | * 1 and 62.5 million iron atoms on a normal hard 9 | * disk: 10 | * http://gizmodo.com/5875674/ibm-figures-out-how-many-atoms-it-takes-to-hold-a-bit-hint-its-12 11 | * 12 | * This application tries to estimate a medium 13 | * weight for the input file, based on a value of 14 | * (62.5+1)/2 = 31.75 million iron atoms per bit. 15 | * 16 | * Usage: 17 | * cc -o fileweight fileweight.c 18 | * ./fileweight some-file 19 | * 20 | * Licensed under the terms of the WTFPL v2. 21 | * http://wtfpl.net/txt/copying 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #ifndef _WIN32 29 | # include 30 | #else /* ifdef WIN32 */ 31 | # include /* io.h does mostly replace unistd.h */ 32 | # include /* off_t support */ 33 | #endif 34 | 35 | 36 | #define ATOMS_PER_BIT 31750000 37 | #define MG_PER_IRON_ATOM 9.2732796E-20 38 | 39 | 40 | void show_syntax(char *argv[]) { 41 | /* Someone made a mistake. */ 42 | printf("Invalid number of parameters or invalid file parameter specified!\n\n"); 43 | printf("Usage:\n"); 44 | printf(" %s \n\n", argv[0]); 45 | } 46 | 47 | int main(int argc, char *argv[]) { 48 | #ifdef __OpenBSD__ 49 | if (-1 == pledge("stdio rpath", NULL)) { 50 | /* Don't waste priviledges. */ 51 | return(EXIT_FAILURE); 52 | } 53 | #endif 54 | 55 | if (argc != 2) { 56 | show_syntax(argv); 57 | return(EXIT_FAILURE); 58 | } 59 | 60 | off_t file_bytes; 61 | int fd_inputfile = open(argv[1], O_RDONLY); 62 | 63 | if (!fd_inputfile) { 64 | /* Couldn't open the file. */ 65 | show_syntax(argv); 66 | return(EXIT_FAILURE); 67 | } 68 | 69 | file_bytes = lseek(fd_inputfile, 0, SEEK_END); 70 | close(fd_inputfile); 71 | 72 | long double weight = file_bytes * MG_PER_IRON_ATOM * ATOMS_PER_BIT / 1000 * CHAR_BIT; 73 | printf("The file %s weighs about %Le grams.\n\n", argv[1], weight); 74 | 75 | return(EXIT_SUCCESS); 76 | } 77 | -------------------------------------------------------------------------------- /scripts/find-pi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # the MAC prefixes Raspberry Pi Foundation uses 3 | arp -na | \ 4 | grep \ 5 | -e "b8:27:eb" \ 6 | -e "dc:a6:32" \ 7 | -e "e4:5f:01" 8 | 9 | -------------------------------------------------------------------------------- /scripts/flush-dns: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | case "$(uname -s)" in 4 | "Darwin") 5 | sudo dscacheutil -flushcache && \ 6 | sudo killall -HUP mDNSResponder 7 | ;; 8 | *) 9 | echo "$(uname -s) not yet supported in $0" 10 | ;; 11 | esac 12 | -------------------------------------------------------------------------------- /scripts/fraktur: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import fraktur 4 | import sys 5 | 6 | print((fraktur.encode(str(" ".join(sys.argv[1:]))))) 7 | -------------------------------------------------------------------------------- /scripts/frinkconv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # https://github.com/purarue/frinkconv 3 | declare script_name='frinkconv' 4 | 5 | # function to verify an external command is installed 6 | havecmd() { 7 | local BINARY ERRMSG 8 | BINARY="${1:?Must provide command to check}" 9 | if command -v "${BINARY}" >/dev/null 2>&1; then 10 | return 0 11 | else 12 | ERRMSG="'${script_name}' requires '${BINARY}', could not find that on your \$PATH" 13 | if [[ -n "$2" ]]; then 14 | ERRMSG="${ERRMSG}. $2" 15 | fi 16 | printf '%s\n' "${ERRMSG}" 1>&2 17 | return 1 18 | fi 19 | } 20 | 21 | FRINKCONV_JAVA_PATH="${FRINKCONV_JAVA_PATH:-java}" 22 | 23 | set -e 24 | havecmd "${FRINKCONV_JAVA_PATH}" 25 | havecmd rlwrap 26 | havecmd wget 27 | set +e 28 | 29 | declare frink_dir jar unitsfile functionsfile 30 | 31 | frink_dir="${FRINKCONV_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/frinkconv}" 32 | mkdir -p "${frink_dir}" 33 | 34 | jar="${frink_dir}/frink.jar" 35 | unitsfile="${frink_dir}/unitnames.txt" 36 | functionsfile="${frink_dir}/functionnames.txt" 37 | 38 | setup_frink() { 39 | # if the data files don't exist, download them 40 | [[ ! -r "${jar}" ]] && wget "https://frinklang.org/frinkjar/frink.jar" -O "${jar}" 41 | [[ ! -r "${unitsfile}" ]] && wget "https://frinklang.org/frinkjar/unitnames.txt" -O "${unitsfile}" 42 | [[ ! -r "${functionsfile}" ]] && wget "https://frinklang.org/frinkjar/functionnames.txt" -O "${functionsfile}" 43 | } 44 | 45 | repl() { 46 | echo 'Dropping into repl...' 47 | # add unit/functions file to rlwrap flags for completion 48 | local -a rlwrapflags=() 49 | if [[ -f "${unitsfile}" ]]; then 50 | rlwrapflags+=(-f "${unitsfile}") 51 | fi 52 | if [[ -f "${functionsfile}" ]]; then 53 | rlwrapflags+=(-b '$' -f "${functionsfile}") 54 | fi 55 | # add history file 56 | rlwrapflags+=(-H "${FRINKCONV_HISTORY:-${frink_dir}/history.txt}") 57 | rlwrap "${rlwrapflags[@]}" "${FRINKCONV_JAVA_PATH}" -classpath "${jar}" frink.parser.Frink "$@" 58 | } 59 | 60 | # run conversions non-interactively, specified as CLI args 61 | runconversions() { 62 | local -a exprargs 63 | for exp in "$@"; do 64 | exprargs+=(-e "${exp}") 65 | done 66 | "${FRINKCONV_JAVA_PATH}" -classpath "${jar}" frink.parser.Frink "${exprargs[@]}" 67 | } 68 | 69 | main() { 70 | case "$1" in 71 | repl) 72 | shift 73 | repl "$@" 74 | ;; 75 | *) 76 | # default to REPL if nothing is provided 77 | if [[ -z "$1" ]]; then 78 | repl 79 | else 80 | runconversions "$@" 81 | fi 82 | ;; 83 | esac 84 | } 85 | 86 | setup_frink 87 | main "$@" 88 | -------------------------------------------------------------------------------- /scripts/getline: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | PROGNAME=$(basename "${0}") 3 | LINENUM=$1 4 | INFILE=$2 5 | 6 | usage() { 7 | >&2 echo -e "Usage:\t$PROGNAME line-number input-file" 8 | } 9 | 10 | if [[ -z $LINENUM || -z "${INFILE}" ]]; then 11 | usage 12 | exit 1 13 | fi 14 | 15 | sed "${LINENUM}!d;q" "${INFILE}" 16 | -------------------------------------------------------------------------------- /scripts/gh-provision-known-hosts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu -o pipefail 4 | 5 | # from https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/ 6 | 7 | if ! command -v jq >/dev/null; then 8 | if command -v brew >/dev/null; then 9 | brew install jq 10 | elif command -v apt >/dev/null; then 11 | sudo apt install jq 12 | fi 13 | fi 14 | 15 | ssh-keygen -R github.com 16 | curl -L https://api.github.com/meta | jq -r '.ssh_keys | .[]' | sed -e 's/^/github.com /' >>~/.ssh/known_hosts 17 | -------------------------------------------------------------------------------- /scripts/gh_token: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | : "${GITHUB_TOKEN:=}" 4 | : "${SKIP_GH:=}" 5 | : "${SKIP_GH_CONFIG:=}" 6 | : "${SKIP_HUB_CONFIG:=}" 7 | : "${DEBUG:=}" 8 | 9 | set -eu -o pipefail 10 | 11 | SITE="${1:-"github.com"}" 12 | 13 | log() { 14 | if [[ -n "${DEBUG}" ]]; then 15 | >&2 echo "$*" 16 | fi 17 | } 18 | 19 | if [[ -n "${GITHUB_TOKEN}" ]]; then 20 | log "Reading GitHub token from GITHUB_TOKEN envvar..." 21 | printf "%s" "${GITHUB_TOKEN}" 22 | exit 0 23 | fi 24 | 25 | HUB_CONFIG="${XDG_CONFIG_HOME:-"${HOME}/.config"}/hub" 26 | GH_CONFIG="${XDG_CONFIG_HOME:-"${HOME}/.config"}/gh/hosts.yml" 27 | 28 | declare -a config_files 29 | config_files=("${HUB_CONFIG}" "${GH_CONFIG}") 30 | 31 | need_cmd() { 32 | local cmd="${1}" 33 | local msg="${2}" 34 | if ! command -v "${cmd}" >/dev/null; then 35 | log "${msg}" 36 | exit 1 37 | fi 38 | } 39 | 40 | require_yaml2json_and_jq() { 41 | need_cmd yaml2json "Need 'yaml2json' executable to convert from YAML to JSON" 42 | need_cmd jq "Need 'jq' to extract the tokens" 43 | } 44 | 45 | if [[ -z "${SKIP_GH}" ]] && command -v gh >/dev/null; then 46 | log "Reading GitHub token from 'gh' command..." 47 | gh auth token --hostname "${SITE}" 48 | exit $? 49 | fi 50 | 51 | if [[ -z "${SKIP_GH_CONFIG}" ]] && [[ -r "${GH_CONFIG}" ]]; then 52 | require_yaml2json_and_jq 53 | log "Reading GitHub token from 'gh' config file ${GH_CONFIG}..." 54 | 55 | yaml2json "${GH_CONFIG}" | 56 | jq -r --arg site "${SITE}" '.[$site].oauth_token' 57 | 58 | exit $? 59 | fi 60 | 61 | if [[ -z "${SKIP_HUB_CONFIG}" ]] && [[ -r "${HUB_CONFIG}" ]]; then 62 | require_yaml2json_and_jq 63 | log "Reading GitHub token from 'hub' config file ${HUB_CONFIG}..." 64 | 65 | yaml2json "${HUB_CONFIG}" | 66 | jq -r --arg site "${SITE}" '.[$site] | first | .oauth_token' 67 | 68 | exit $? 69 | fi 70 | 71 | printf >&2 "No token in GITHUB_TOKEN and config files in [%s] are missing or does not contain a token for %s\n" "${config_files[*]}" "${SITE}" 72 | exit 1 73 | -------------------------------------------------------------------------------- /scripts/gif-every-other-frame: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # from https://graphicdesign.stackexchange.com/questions/20908/how-to-remove-every-second-frame-from-an-animated-gif 3 | # modified by colindean 4 | # 5 | # This script will take an animated GIF and delete every other frame 6 | # Accepts two parameters: input file and output file 7 | # Usage: ./ input.gif output.gif 8 | 9 | # Make a copy of the file 10 | cp "$1" "$2" 11 | 12 | # Get the number of frames 13 | # this had used `grep -o -P` but -P doesn't exist on BSD grep so it wouldn't work on macOS OOTB 14 | numframes="$(gifsicle "$1" -I | perl -nle'print $& while m{\d+ images}g' | perl -nle'print $& while m{\d+}g')" 15 | 16 | # Deletion 17 | (( i=0 )) 18 | while [[ $i -lt $numframes ]]; do 19 | rem=$(( i % 2 )) 20 | 21 | if [ $rem -eq 0 ] 22 | then 23 | gifsicle "$2" --delete "#"$((i/2)) -o "$2" 24 | fi 25 | 26 | (( i=i+1 )) 27 | done 28 | 29 | -------------------------------------------------------------------------------- /scripts/gif2mp4: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | INPUT="${1}" 4 | OUTPUT="${2}" 5 | 6 | if [ -z "${OUTPUT}" ] || [ -z "${INPUT}" ]; then 7 | >&2 echo "Usage: ${0} input output" 8 | exit 1 9 | fi 10 | 11 | ffmpeg -i "${INPUT}" -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" "${OUTPUT}" 12 | -------------------------------------------------------------------------------- /scripts/git-bechdel: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### Bechdel Test for Software 4 | # 5 | ## What is the Bechdel Test for Software? 6 | # 7 | # https://en.wikipedia.org/wiki/Bechdel_test#Bechdel_test_for_software 8 | # 9 | # This tool doesn't really get it 100% right on, because I just don't know 10 | # enough about static analysis nor can I learn enough in the one night I can 11 | # devote to this little project! 12 | # 13 | # So, this little ditty just collects all of the authors in a git repo and 14 | # reports some statistics based on a map of author to gender. 15 | # 16 | ## Genderfile format 17 | # 18 | # Genderfile is really two columns: a gender indicator and an author name. e.g. 19 | # 20 | # M Colin Dean 21 | # F Jennifer Manning 22 | # 23 | # There's no limitation on what can be used as the indicator. 24 | 25 | OLDIFS="$IFS" 26 | IFS=$'\n' 27 | 28 | declare -A GENDERMAP 29 | 30 | function trim() { 31 | echo "$@" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' 32 | } 33 | 34 | function load_genderfile() { 35 | while read -r -d $'\t' -a author; do 36 | GENDERMAP[$author[1]] = $author[0] 37 | done < (~/.git/Genderfile) 38 | } 39 | 40 | function genderLookup() { 41 | $GENDERMAP[$1] 42 | } 43 | 44 | COUNT_TO_AUTHOR=$(git log --format='%aN' | sort | uniq -c) 45 | TOTAL_COMMITS=$(git rev-list HEAD --count) 46 | 47 | for author in $COUNT_TO_AUTHOR; do 48 | count_raw=$(echo $author | awk '{print $1}') 49 | author_raw=$(echo $author | awk '{$1=""; print $0}') 50 | count=$(trim $count_raw) 51 | author=$(trim $author_raw) 52 | 53 | gender=$(genderLookup "$author") 54 | echo "$author is $gender and has $count commits." 55 | done 56 | 57 | echo $total_commits total commits 58 | -------------------------------------------------------------------------------- /scripts/git-committers-per-file: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | TOTAL_COMMITTERS="$(git log --format="%aE" | tr "[:upper:]" "[:lower:]" | sort | uniq | wc -l | tr -d ' ')" 4 | 5 | for file in $(git ls-files); do 6 | 7 | FILE_COMMITTERS=$(git log --format="%aE" "${file}" | tr "[:upper:]" "[:lower:]" | sort | uniq | wc -l | tr -d ' ') 8 | 9 | if [ "$1" == "json" ]; then 10 | jq --null-input --compact-output \ 11 | --arg file "${file}" \ 12 | --argjson fc "${FILE_COMMITTERS}" \ 13 | --argjson tc "${TOTAL_COMMITTERS}" \ 14 | '{file: $file, file_committers: $fc, total_committers: $tc}' 15 | else 16 | echo -e "${FILE_COMMITTERS}\t${TOTAL_COMMITTERS}\t${file}" 17 | fi 18 | done 19 | -------------------------------------------------------------------------------- /scripts/git-file-size-diff: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | USAGE='[--cached] [...] 3 | 4 | Show file size changes between two commits or the index and a commit.' 5 | 6 | usage() { 7 | >&2 echo "${USAGE}" 8 | } 9 | 10 | . "$(git --exec-path)/git-sh-setup" 11 | args=$(git rev-parse --sq "$@") 12 | [ -n "$args" ] || usage 13 | cmd="diff-tree -r" 14 | [[ $args =~ "--cached" ]] && cmd="diff-index" 15 | eval "git $cmd $args" | { 16 | total=0 17 | while read -r A B C D M P 18 | do 19 | case $M in 20 | M) bytes=$(( $(git cat-file -s "$D") - $(git cat-file -s "$C") )) ;; 21 | A) bytes=$(git cat-file -s "$D") ;; 22 | D) bytes=-$(git cat-file -s "$C") ;; 23 | *) 24 | echo >&2 "warning: unhandled mode $M in \"$A $B $C $D $M $P\"" 25 | continue 26 | ;; 27 | esac 28 | total=$(( total + bytes )) 29 | printf '%d\t%s\n' "$bytes" "$P" 30 | done 31 | echo total $total 32 | } 33 | -------------------------------------------------------------------------------- /scripts/git-log-json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | git log --reverse --pretty=format:'%H%x00%aN <%aE>%x00%cn <%cE>%x00%aI%x00%s%x00' | 4 | jq -R -s '[split("\n")[:-1] | map(split("\u0000")) | .[] | { 5 | "commit": .[0], 6 | "author": .[1], 7 | "committer": .[2], 8 | "date": .[3], 9 | "subject": .[4], 10 | }]' 11 | -------------------------------------------------------------------------------- /scripts/git-prebase: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # from https://gist.github.com/koreno/5893d2d969ccb6b8341d 3 | from subprocess import check_call, check_output 4 | SPACER = "_" 5 | 6 | 7 | def parse_log(first, last): 8 | 9 | gitlog = check_output([ 10 | 'git', 'log', '--name-only', '--oneline', '--no-color', 11 | '--format=#commit %h {idx:4}:%s', 12 | "%s^..%s" % (first, last)], 13 | universal_newlines=True) 14 | 15 | lines = iter(gitlog.splitlines()) 16 | line = next(lines) 17 | 18 | while True: 19 | prefix, _, commit = line.partition(" ") 20 | assert prefix == "#commit" 21 | 22 | files = set() 23 | for line in lines: 24 | if line.startswith("#commit"): 25 | yield (commit, sorted(files)) 26 | break # for 27 | elif line: 28 | files.add(line) 29 | else: 30 | yield (commit, sorted(files)) 31 | break # while 32 | 33 | 34 | def compact(line, length, ellipsis="....", suffix_length=10): 35 | if len(line) <= length: 36 | return line 37 | return line[:length-len(ellipsis)-suffix_length] + ellipsis + line[-suffix_length:] 38 | 39 | 40 | def write_todo(file, first, last, comments): 41 | from itertools import count, chain 42 | from collections import defaultdict 43 | from string import digits, ascii_letters 44 | c = count(0) 45 | file_indices = defaultdict(lambda: next(c)) 46 | SYM = dict(enumerate(chain(digits, ascii_letters))) 47 | lines = [] 48 | log = list(parse_log(first, last)) 49 | width = min(120, max(len(c) for (c, _) in log) if log else 80) 50 | for commit, files in log: 51 | indices = {file_indices[f] for f in files} 52 | placements = "".join(SYM[i % len(SYM)] if i in indices else SPACER for i in range(max(indices)+1)) if indices else "" 53 | lines.append((compact(commit, width).ljust(width), placements)) 54 | lines.reverse() 55 | placements_width = max(file_indices.values()) + 2 56 | for i, (commit, placements) in enumerate(lines, 1): 57 | print("pick", commit.format(idx=i), placements.ljust(placements_width, SPACER), file=file) 58 | 59 | print("", file=file) 60 | for f, i in sorted(file_indices.items(), key=lambda p: p[1]): 61 | pos = SYM[i % len(SYM)].rjust(1+i, SPACER).ljust(placements_width, SPACER) 62 | f = "[%s] %s" % (SYM[i], f) 63 | fname = compact("# %s" % f, width+2).ljust(width+2) 64 | print(fname, pos, file=file) 65 | 66 | print("", file=file) 67 | print(comments, file=file) 68 | 69 | 70 | if __name__ == '__main__': 71 | import sys 72 | import os 73 | 74 | if not os.path.isfile(sys.argv[1]): 75 | base_commit = sys.argv[1] 76 | os.environ['GIT_ORIG_EDITOR'] = check_output(["git", "var", "GIT_EDITOR"], universal_newlines=True).strip() 77 | os.environ['GIT_EDITOR'] = __file__ 78 | os.execlpe("git", "git", "rebase", "-i", base_commit, os.environ) 79 | 80 | todo_file = sys.argv[1] 81 | os.environ['GIT_EDITOR'] = editor = os.environ['GIT_ORIG_EDITOR'] 82 | 83 | if not todo_file.endswith("git-rebase-todo"): 84 | os.execlpe(editor, editor, todo_file, os.environ) 85 | 86 | commits = [] 87 | 88 | with open(todo_file) as f: 89 | for line in f: 90 | if not line.strip(): 91 | break 92 | commits.append(line.split()[1]) 93 | comments = f.read() 94 | 95 | first, *_, last = commits 96 | with open(todo_file, "w") as file: 97 | write_todo(file, first, last, comments) 98 | 99 | check_call([editor, todo_file]) 100 | # subl['-n', '-w', todo_file] & FG 101 | -------------------------------------------------------------------------------- /scripts/git-todo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | if [[ -z "$1" ]]; then 5 | NEEDLE="TODO" 6 | else 7 | NEEDLE="$1" 8 | fi 9 | 10 | main() { 11 | while IFS= read -r todo; do 12 | printf '%s\n' "$(file_path):$(line_number) $(line_author) $(message)" 13 | done < <(todo_list) 14 | } 15 | 16 | todo_list() { 17 | git grep -In "$NEEDLE" 18 | #grep -InR "$NEEDLE" ./* \ 19 | # --exclude-dir=node_modules \ 20 | # --exclude-dir=public \ 21 | # --exclude-dir=vendor \ 22 | # --exclude-dir=compiled \ 23 | # --exclude-dir=git-hooks 24 | } 25 | 26 | line_author() { 27 | LINE=$(line_number "$todo") 28 | FILE=$(file_path "$todo") 29 | tput setaf 6 30 | printf "%s" "$(git log --pretty=format:"%cN" -s -L "$LINE","$LINE":"$FILE" | head -n 1)" 31 | tput sgr0 32 | } 33 | 34 | file_path() { 35 | printf "%s" "$todo" | cut -d':' -f 1 36 | } 37 | 38 | line_number() { 39 | printf "%s" "$todo" | cut -d':' -f 2 40 | } 41 | 42 | message() { 43 | printf "%s" "$todo" | cut -d':' -f 3- 44 | #printf "%s" "$todo" | cut -d':' -f 3- | xargs 45 | } 46 | 47 | main 48 | 49 | exit 0 50 | -------------------------------------------------------------------------------- /scripts/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. 6 | function print_osc() { 7 | if [[ $TERM == screen* ]] ; then 8 | printf "\033Ptmux;\033\033]" 9 | else 10 | printf "\033]" 11 | fi 12 | } 13 | 14 | # More of the tmux workaround described above. 15 | function print_st() { 16 | if [[ $TERM == screen* ]] ; then 17 | printf "\a\033\\" 18 | else 19 | printf "\a" 20 | fi 21 | } 22 | 23 | # print_image filename inline base64contents 24 | # filename: Filename to convey to client 25 | # inline: 0 or 1 26 | # base64contents: Base64-encoded contents 27 | function print_image() { 28 | print_osc 29 | printf '1337;File=' 30 | if [[ -n "$1" ]]; then 31 | printf 'name='`echo -n "$1" | base64`";" 32 | fi 33 | if $(base64 --version 2>&1 | egrep 'fourmilab|GNU' > /dev/null) 34 | then 35 | BASE64ARG=-d 36 | else 37 | BASE64ARG=-D 38 | fi 39 | echo -n "$3" | base64 $BASE64ARG | wc -c | awk '{printf "size=%d",$1}' 40 | printf ";inline=$2" 41 | printf ":" 42 | echo -n "$3" 43 | print_st 44 | printf '\n' 45 | } 46 | 47 | function error() { 48 | echo "ERROR: $*" 1>&2 49 | } 50 | 51 | function show_help() { 52 | echo "Usage: imgcat filename ..." 1>& 2 53 | echo " or: cat filename | imgcat" 1>& 2 54 | } 55 | 56 | ## Main 57 | 58 | if [ -t 0 ]; then 59 | has_stdin=f 60 | else 61 | has_stdin=t 62 | fi 63 | 64 | # Show help if no arguments and no stdin. 65 | if [ $has_stdin = f -a $# -eq 0 ]; then 66 | show_help 67 | exit 68 | fi 69 | 70 | # Look for command line flags. 71 | while [ $# -gt 0 ]; do 72 | case "$1" in 73 | -h|--h|--help) 74 | show_help 75 | exit 76 | ;; 77 | -*) 78 | error "Unknown option flag: $1" 79 | show_help 80 | exit 1 81 | ;; 82 | *) 83 | if [ -r "$1" ] ; then 84 | print_image "$1" 1 "$(base64 < "$1")" 85 | else 86 | error "imgcat: $1: No such file or directory" 87 | exit 2 88 | fi 89 | ;; 90 | esac 91 | shift 92 | done 93 | 94 | # Read and print stdin 95 | if [ $has_stdin = t ]; then 96 | print_image "" 1 "$(cat | base64)" 97 | fi 98 | 99 | exit 0 100 | -------------------------------------------------------------------------------- /scripts/json2yaml: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'json' 3 | require 'yaml' 4 | 5 | file = ARGV.pop 6 | data = if file == '-' 7 | STDIN.read 8 | else 9 | File.read(file) 10 | end 11 | 12 | puts JSON.parse(data).to_yaml 13 | -------------------------------------------------------------------------------- /scripts/json_to_yaml_b64.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Transfers a single-level JSON object in a file to YAML, but 4 | encodes the values as Base64. 5 | """ 6 | import json 7 | import base64 8 | from pathlib import Path 9 | import sys 10 | 11 | 12 | def eprint(s): 13 | print(s, file=sys.stderr) 14 | 15 | 16 | def b64enc(s): 17 | if not type(s) == str: 18 | eprint("Don't know how to handle non-string object values.") 19 | eprint("The behavior after here is undefined. YMMV!") 20 | 21 | return str(base64.standard_b64encode(bytes(s, "utf-8")), "utf-8") 22 | 23 | 24 | secrets_json = Path(sys.argv[1]) 25 | with open(secrets_json, 'r') as file_data: 26 | data = json.load(file_data) 27 | 28 | eprint(f"data has {len(data.keys())} keys: {data.keys()}") 29 | 30 | encoded = {k: b64enc(data[k]) for k in data} 31 | 32 | for k in encoded: 33 | print(f"{k}: {encoded[k]}") 34 | -------------------------------------------------------------------------------- /scripts/jwttool: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'json' 3 | require 'base64' 4 | data = STDIN.read 5 | parts = data.split('.') 6 | if parts.size != 3 7 | STDERR.puts 'JWT malformed: missing three period-separated sections' 8 | exit 1 9 | end 10 | 11 | parts.map! { |part| Base64.decode64 part } 12 | 13 | jwt = { 14 | header: parts[0], 15 | body: parts[1], 16 | signature: parts[2] 17 | } 18 | 19 | def format_json(jsonstr) 20 | obj = JSON.parse(jsonstr) 21 | JSON.pretty_generate(obj) 22 | end 23 | 24 | STDERR.puts 'JWT data:' 25 | jwt.each do |section, jsonstr| 26 | STDERR.puts section 27 | if section == :signature 28 | if jsonstr.start_with? '{' 29 | STDOUT.puts format_json(jsonstr) 30 | else 31 | STDERR.puts 'Signature is binary, not printing.' 32 | end 33 | else 34 | STDOUT.puts format_json(jsonstr) 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /scripts/kill-tuntaposx: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # https://tunnelblick.net/cKextLoadError.html 3 | sudo kextunload -b net.sf.tuntaposx.tap 4 | sudo kextunload -b net.sf.tuntaposx.tun 5 | 6 | -------------------------------------------------------------------------------- /scripts/killport: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | PORT="${1}" 3 | if [ -z "${PORT}" ]; then 4 | >&2 echo "No port provided." 5 | >&2 echo "Usage: $0 port" 6 | fi 7 | 8 | echo "Killing process listening on port $PORT…" 9 | 10 | lsof -i ":${PORT}" | awk 'NR > 1 {print $2}' | xargs --no-run-if-empty kill 11 | -------------------------------------------------------------------------------- /scripts/lines-to-markdown-num: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # awk here removes all preceding whitespace 4 | # nl -s separator 5 | # -n ln = left justification 6 | # -w width, use 1 to prevent significant space between number and text 7 | # -b t = only show non-empty lines 8 | awk '{$1=$1};1' | nl -s ". " -n ln -w 1 -b t 9 | -------------------------------------------------------------------------------- /scripts/list: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ALL_ARGS=("${@}") 3 | 4 | echo "${ALL_ARGS[@]}" | tr -s ' ' '\n' 5 | -------------------------------------------------------------------------------- /scripts/list-shellscripts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SHEBANGS=( 4 | '#!/usr/bin/env bash' 5 | '#!/bin/bash' 6 | '#!/bin/sh' 7 | '#!bash' 8 | ) 9 | LIST="" 10 | for shebang in ${SHEBANGS[*]}; do 11 | LIST+=$(grep -lr --exclude-dir "\\.git" "${shebang}" .) 12 | LIST+="\n" 13 | done 14 | 15 | echo -e "${LIST}" | sort -u 16 | -------------------------------------------------------------------------------- /scripts/list2csv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | gsed -e 's/^\|$/"/g' | gpaste -sd, - 4 | -------------------------------------------------------------------------------- /scripts/listops: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ACTION="${1}" 4 | LEFT="${2}" 5 | RIGHT="${3}" 6 | 7 | case "${ACTION}" in 8 | "only-left") 9 | comm -23 "${LEFT}" "${RIGHT}" 10 | ;; 11 | "only-right") 12 | comm -13 "${LEFT}" "${RIGHT}" 13 | ;; 14 | "both") 15 | comm -12 "${LEFT}" "${RIGHT}" 16 | ;; 17 | *) 18 | >&2 echo "Unknown action. Try one of only-left, only-right, both." 19 | ;; 20 | esac 21 | 22 | 23 | -------------------------------------------------------------------------------- /scripts/lobsters: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Retrieves the latest stories from Lobste.rs 3 | # Prints titles in red bold and links in default color, in a columnar table 4 | 5 | set -eu -o pipefail 6 | 7 | checkfor() { 8 | command -v "${1}" > /dev/null || (echo "need ${1}" && exit 1); 9 | } 10 | 11 | checkfor curl 12 | checkfor xmlstarlet 13 | checkfor awk 14 | checkfor column 15 | 16 | curl -sL https://lobste.rs/rss | \ 17 | xmlstarlet sel -T -t -m "/rss/channel/item" -v title -o "%%" -v link -n | \ 18 | awk -F "%%" '{print "\033[31;1m" $1 "\033[39;22m" "∑" $2 "\033[0m" }' | \ 19 | column -t -s '∑' 20 | -------------------------------------------------------------------------------- /scripts/log_all_output: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # write a process's stderr and stdout to the console as well as to separate files 3 | # inspired by https://stackoverflow.com/a/692407/204052 4 | 5 | stdout="${STDOUT:-stdout.log}" 6 | stderr="${STDERR:-stderr.log}" 7 | 8 | "${@}" >(tee -a "${stdout}") 2> >(tee -a "${stderr}" >&2) 9 | -------------------------------------------------------------------------------- /scripts/mailservers: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # dig +short _submission._tcp.cad.cx srv 4 | # 0 1 587 smtp.fastmail.com. 5 | 6 | DOMAIN="${1}" 7 | 8 | if [ -z ${DOMAIN} ]; then 9 | >&2 echo -e "Usage:\n\t$(basename $0) domain.tld" 10 | exit 1 11 | fi 12 | 13 | IMAP="_imap._tcp.${DOMAIN}" 14 | IMAPS="_imaps._tcp.${DOMAIN}" 15 | POP3="_pop3._tcp.${DOMAIN}" 16 | POP3S="_pop3s._tcp.${DOMAIN}" 17 | SMTP="_submission._tcp.${DOMAIN}" 18 | MX="${DOMAIN}" 19 | 20 | srv() { 21 | dig +short "${1}" srv 22 | } 23 | 24 | mx() { 25 | dig +short "${1}" mx 26 | } 27 | 28 | 29 | IMAP_RESULT="$(srv ${IMAP} | head -n 1)" 30 | IMAPS_RESULT="$(srv ${IMAPS} | head -n 1)" 31 | POP3_RESULT="$(srv ${POP3} | head -n 1)" 32 | POP3S_RESULT="$(srv ${POP3S} | head -n 1)" 33 | SMTP_RESULT="$(srv ${SMTP} | head -n 1)" 34 | MX_RESULT="$(mx ${MX} | head -n 1)" 35 | 36 | 37 | column -t -s "~" <>} 40 | IMAPS~${IMAPS_RESULT:-<>} 41 | POP3~${POP3_RESULT:-<>} 42 | POP3S~${POP3S_RESULT:-<>} 43 | SMTP~${SMTP_RESULT:-<>} 44 | MX~${MX_RESULT:-<>} 45 | MSG 46 | -------------------------------------------------------------------------------- /scripts/make-icons: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ -z "${1}" ] || [ -z "${2}" ]; then 3 | echo "Usage: $0 iconset-name original-icon-at-1024px" 4 | exit 1 5 | fi 6 | NAME="${1}" 7 | ORIG="${2}" 8 | 9 | ICONSET="${NAME}.iconset" 10 | 11 | mkdir "${NAME}.iconset" 12 | sips -z 16 16 "${ORIG}" --out "${ICONSET}"/icon_16x16.png 13 | sips -z 32 32 "${ORIG}" --out "${ICONSET}"/icon_16x16@2x.png 14 | sips -z 32 32 "${ORIG}" --out "${ICONSET}"/icon_32x32.png 15 | sips -z 64 64 "${ORIG}" --out "${ICONSET}"/icon_32x32@2x.png 16 | sips -z 128 128 "${ORIG}" --out "${ICONSET}"/icon_128x128.png 17 | sips -z 256 256 "${ORIG}" --out "${ICONSET}"/icon_128x128@2x.png 18 | sips -z 256 256 "${ORIG}" --out "${ICONSET}"/icon_256x256.png 19 | sips -z 512 512 "${ORIG}" --out "${ICONSET}"/icon_256x256@2x.png 20 | sips -z 512 512 "${ORIG}" --out "${ICONSET}"/icon_512x512.png 21 | cp "${ORIG}" "${ICONSET}"/icon_512x512@2x.png 22 | iconutil -c icns "${ICONSET}" 23 | rm -R "${ICONSET}" 24 | 25 | -------------------------------------------------------------------------------- /scripts/man2pdf: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #man -t ledger | ps2pdf - /tmp/man-ledger.pdf && open /tmp/man-ledger.pdf 4 | MAN_ARGS=("$@") 5 | IDENTIFIER="$(echo "${MAN_ARGS[@]}" | sed -e 's/ //g')" 6 | 7 | PDF_FILENAME="man-${IDENTIFIER}.pdf" 8 | PDF_TARGET="${TMPDIR}${PDF_FILENAME}" 9 | 10 | if [[ -f "${PDF_TARGET}" ]]; then 11 | open "${PDF_TARGET}" 12 | exit 0 13 | fi 14 | 15 | MAN_PATH="$(command -v man)" 16 | if [[ -z "${MAN_PATH}" ]]; then 17 | >&2 echo "No man found, are manpages actually installed?" 18 | exit 1 19 | fi 20 | 21 | PS2PDF_PATH="$(command -v ps2pdf)" 22 | if [[ -z "${PS2PDF_PATH}" ]]; then 23 | >&2 echo "No ps2pdf found, ensure that it is installed." 24 | exit 2 25 | fi 26 | 27 | # ensure it exists first 28 | MANPAGE_PATH="$("${MAN_PATH}" --path ${MAN_ARGS})" 29 | manpath_path_exit=$? 30 | if [[ $manpath_path_exit -ne 0 ]]; then 31 | #>&2 echo "No manpage available for '${MAN_ARGS}'." 32 | exit $manpath_path_exit 33 | fi 34 | 35 | # -t outputs postscript using groff, see `man man` for details. 36 | # ps2pdf - - means convert stdin to pdf and output on stdout 37 | "${MAN_PATH}" -t "${MAN_ARGS[@]}" | "${PS2PDF_PATH}" - - > "${PDF_TARGET}" 38 | 39 | if [[ -f "${PDF_TARGET}" ]]; then 40 | open "${PDF_TARGET}" 41 | exit 0 42 | else 43 | >&2 echo "${PDF_TARGET} does not exist, something went wrong." 44 | exit 4 45 | fi 46 | -------------------------------------------------------------------------------- /scripts/md5sum: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [[ -f "/usr/bin/md5sum" ]]; then 3 | /usr/bin/md5sum "$@" 4 | elif [[ -n "$(command -v md5)" ]]; then 5 | md5 -q "$@" 6 | fi 7 | -------------------------------------------------------------------------------- /scripts/netrc-tools: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu -o pipefail 4 | # based on https://stackoverflow.com/a/73879664/204052 5 | 6 | if command -v ggrep >/dev/null; then 7 | FALLBACK_GREP="ggrep" 8 | else 9 | FALLBACK_GREP="grep" 10 | fi 11 | GREP="${GREP:-${FALLBACK_GREP}}" 12 | 13 | get_netrc_entry() { 14 | machine_entry=$(tr '\n' ' ' <~/.netrc | "${GREP}" -oP "(?<=machine ${1//./\\.} ).*?(?=( machine)|$)") 15 | "${GREP}" -oP '(?<=login ).*?(?=\s|$)' <<<"${machine_entry}" 16 | "${GREP}" -oP '(?<=password ).*?(?=\s|$)' <<<"${machine_entry}" 17 | } 18 | 19 | usage() { 20 | printf "Usage: %s get [login|user|username|password|pass|secret] \n" "${0}" >&2 21 | } 22 | 23 | # shellcheck disable=SC2068 24 | case "${1}" in 25 | get) 26 | shift 27 | case "${1}" in 28 | login | user | username) 29 | shift 30 | get_netrc_entry $@ | head -n 1 31 | ;; 32 | password | pass | secret) 33 | shift 34 | get_netrc_entry $@ | tail -n 1 35 | ;; 36 | *) 37 | get_netrc_entry $@ 38 | ;; 39 | 40 | esac 41 | ;; 42 | *) 43 | usage 44 | ;; 45 | esac 46 | -------------------------------------------------------------------------------- /scripts/neuron: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ZETTELKASTEN_DIR="${ZETTELKASTEN_DIR:-"${HOME}/zettelkasten"}" 4 | LOCAL_INSTALL="/usr/local/bin/neuron" 5 | LISTEN_PORT=1440 6 | DOCKER_NAME="neuron-zettelkasten" 7 | 8 | printf "Starting Neuron in %s " "${ZETTELKASTEN_DIR}" >&2 9 | 10 | declare -a CMD 11 | CMD=${@} 12 | 13 | if [ "${1}" = "serve" ]; then 14 | CMD=("rib -ws 0.0.0.0:${LISTEN_PORT}") 15 | EXTRA_DOCKER_CMDS="--detach --name ${DOCKER_NAME}" 16 | fi 17 | 18 | if [ "${1}" = "kill" ]; then 19 | docker stop "${DOCKER_NAME}" 20 | exit 0 21 | fi 22 | 23 | if [ -x "${LOCAL_INSTALL}" ]; then 24 | printf "using %s\n" "${LOCAL_INSTALL}" >&2 25 | "${LOCAL_INSTALL}" ${CMD[*]} 26 | elif [ -n "$(command -v docker)" ]; then 27 | printf "using docker\n" >&2 28 | docker run --rm --tty --interactive ${EXTRA_DOCKER_CMDS} \ 29 | --publish ${LISTEN_PORT}:${LISTEN_PORT} \ 30 | --volume "${ZETTELKASTEN_DIR}:/notes" \ 31 | sridca/neuron \ 32 | neuron ${CMD[*]} 33 | fi 34 | 35 | -------------------------------------------------------------------------------- /scripts/noproxy: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | NO_PROXY="" 4 | FTP_PROXY="" 5 | RSYNC_PROXY="" 6 | HTTPS_PROXY="" 7 | HTTP_PROXY="" 8 | ALL_PROXY="" 9 | 10 | ${@} 11 | -------------------------------------------------------------------------------- /scripts/notifyme: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | OSA=$(command -v osascript) 3 | 4 | if [[ -z $OSA ]]; then 5 | echo "osascript not found. Are you on a Mac?"; exit 1 6 | fi 7 | 8 | osascript -e "display notification \"$*\"" 9 | -------------------------------------------------------------------------------- /scripts/now: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | SHORT_FORMAT="${1:-"hms"}" 3 | 4 | case "${SHORT_FORMAT}" in 5 | hm) 6 | FORMAT="+%H:%M" 7 | ;; 8 | hms) 9 | FORMAT="+%H:%M:%S" 10 | ;; 11 | ymd) 12 | FORMAT="+%Y-%m-%d" 13 | ;; 14 | *) 15 | exit 1 16 | esac 17 | 18 | date "${FORMAT}" 19 | -------------------------------------------------------------------------------- /scripts/pin_cores: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env swift 2 | // vim: ft=swift 3 | // 4 | // Based on runfg and runbg from https://github.com/alin23/mac-utils 5 | // Inspired by: https://eclecticlight.co/2021/09/14/how-to-run-commands-and-scripts-on-efficiency-cores/ 6 | // Why? https://eclecticlight.co/2022/05/03/running-tasks-on-e-cores-can-use-a-third-of-the-energy-of-p-cores/ 7 | // TL;DR 33% more battery time; a processor-intensive test task took around 8 | // ~0.7 seconds and drew ~10.3 J on P-cores 9 | // ~4.7 seconds and drew ~3.1 J on E-cores 10 | // 11 | // Run directly: 12 | // chmod +x pin_cores 13 | // ./pin_cores p|e command args… 14 | // 15 | // Compile to static binary: 16 | // swiftc pin_cores -o pincores 17 | // ./pincores p|e command args… 18 | // 19 | // Usage examples: 20 | // Optimize all images on the desktop while on battery: pin_cores e imageoptim ~/Desktop 21 | // Re-encode video with ffmpeg to squeeze more bytes: pin_cores p ffmpeg -i big-video.mp4 smaller-video.mp4 22 | // Compile project in background: pin_cores e make -j 4 23 | 24 | import Foundation 25 | 26 | func printStderr(_ items: Any..., separator: String = " ", terminator: String = "\n") { 27 | let output = items 28 | .map { String(describing: $0) } 29 | .joined(separator: separator) + terminator 30 | 31 | FileHandle.standardError.write(output.data(using: .utf8)!) 32 | } 33 | 34 | func printUsage() { 35 | printStderr(CommandLine.arguments[0], "p|e executable args...") 36 | } 37 | 38 | if CommandLine.arguments.count <= 2 { 39 | printUsage() 40 | exit(1) 41 | } 42 | 43 | let SHELL = ProcessInfo.processInfo.environment["SHELL"] ?? "/bin/zsh" 44 | let FM = FileManager() 45 | 46 | @discardableResult func asyncNow(timeout: TimeInterval, _ action: @escaping () -> Void) -> DispatchTimeoutResult { 47 | let task = DispatchWorkItem { action() } 48 | DispatchQueue.global().async(execute: task) 49 | 50 | let result = task.wait(timeout: DispatchTime.now() + timeout) 51 | if result == .timedOut { 52 | task.cancel() 53 | } 54 | 55 | return result 56 | } 57 | 58 | // MARK: - ProcessStatus 59 | 60 | struct ProcessStatus { 61 | var output: Data? 62 | var error: Data? 63 | var success: Bool 64 | 65 | var o: String? { 66 | output?.s?.trimmed 67 | } 68 | 69 | var e: String? { 70 | error?.s?.trimmed 71 | } 72 | } 73 | 74 | func stdout(of process: Process) -> Data? { 75 | let stdout = process.standardOutput as! FileHandle 76 | try? stdout.close() 77 | 78 | guard let path = process.environment?["__swift_stdout"], 79 | let stdoutFile = FileHandle(forReadingAtPath: path) else { return nil } 80 | return try! stdoutFile.readToEnd() 81 | } 82 | 83 | func stderr(of process: Process) -> Data? { 84 | let stderr = process.standardOutput as! FileHandle 85 | try? stderr.close() 86 | 87 | guard let path = process.environment?["__swift_stderr"], 88 | let stderrFile = FileHandle(forReadingAtPath: path) else { return nil } 89 | return try! stderrFile.readToEnd() 90 | } 91 | 92 | func shellProc(_ launchPath: String = "/bin/zsh", args: [String], env: [String: String]? = nil) -> Process? { 93 | let outputDir = try! FM.url( 94 | for: .itemReplacementDirectory, 95 | in: .userDomainMask, 96 | appropriateFor: FM.homeDirectoryForCurrentUser, 97 | create: true 98 | ) 99 | 100 | let stdoutFilePath = outputDir.appendingPathComponent("stdout").path 101 | FM.createFile(atPath: stdoutFilePath, contents: nil, attributes: nil) 102 | 103 | let stderrFilePath = outputDir.appendingPathComponent("stderr").path 104 | FM.createFile(atPath: stderrFilePath, contents: nil, attributes: nil) 105 | 106 | guard let stdoutFile = FileHandle(forWritingAtPath: stdoutFilePath), 107 | let stderrFile = FileHandle(forWritingAtPath: stderrFilePath) 108 | else { 109 | return nil 110 | } 111 | 112 | let task = Process() 113 | task.standardOutput = stdoutFile 114 | task.standardError = stderrFile 115 | task.launchPath = launchPath 116 | task.arguments = args 117 | 118 | var env = env ?? ProcessInfo.processInfo.environment 119 | env["__swift_stdout"] = stdoutFilePath 120 | env["__swift_stderr"] = stderrFilePath 121 | task.environment = env 122 | 123 | do { 124 | try task.run() 125 | } catch { 126 | printStderr("Error running \(launchPath) \(args): \(error)") 127 | return nil 128 | } 129 | 130 | return task 131 | } 132 | 133 | func shell( 134 | _ launchPath: String = "/bin/zsh", 135 | command: String, 136 | timeout: TimeInterval? = nil, 137 | env _: [String: String]? = nil 138 | ) -> ProcessStatus { 139 | shell(launchPath, args: ["-c", command], timeout: timeout) 140 | } 141 | 142 | func shell( 143 | _ launchPath: String = "/bin/zsh", 144 | args: [String], 145 | timeout: TimeInterval? = nil, 146 | env: [String: String]? = nil 147 | ) -> ProcessStatus { 148 | guard let task = shellProc(launchPath, args: args, env: env) else { 149 | return ProcessStatus(output: nil, error: nil, success: false) 150 | } 151 | 152 | guard let timeout = timeout else { 153 | task.waitUntilExit() 154 | return ProcessStatus( 155 | output: stdout(of: task), 156 | error: stderr(of: task), 157 | success: task.terminationStatus == 0 158 | ) 159 | } 160 | 161 | let result = asyncNow(timeout: timeout) { 162 | task.waitUntilExit() 163 | } 164 | if result == .timedOut { 165 | task.terminate() 166 | } 167 | 168 | return ProcessStatus( 169 | output: stdout(of: task), 170 | error: stderr(of: task), 171 | success: task.terminationStatus == 0 172 | ) 173 | } 174 | 175 | extension String { 176 | @inline(__always) var trimmed: String { 177 | trimmingCharacters(in: .whitespacesAndNewlines) 178 | } 179 | } 180 | 181 | extension Data { 182 | var s: String? { String(data: self, encoding: .utf8) } 183 | } 184 | 185 | var mode = CommandLine.arguments[1] 186 | if !(mode == "p" || mode == "e") { 187 | printStderr("ERROR: Invalid mode '\(mode)'.") 188 | printStderr("ERROR: Unsure which cores to use? Pass 'p' for performance and 'e' for efficiency.") 189 | printUsage() 190 | exit(3) 191 | } 192 | 193 | var executable = (CommandLine.arguments[2] as NSString).expandingTildeInPath 194 | if !FM.fileExists(atPath: executable) { 195 | let which = shell(SHELL, command: "which '\(CommandLine.arguments[2])'") 196 | guard which.success, let output = which.o else { 197 | if let err = which.e { 198 | printStderr(err) 199 | } 200 | printStderr("\(executable) not found") 201 | exit(1) 202 | } 203 | executable = output 204 | } 205 | 206 | let p = Process() 207 | 208 | if mode == "p" { 209 | printStderr("Running \(executable) using performance cores only") 210 | p.qualityOfService = .userInteractive 211 | } else if mode == "e" { 212 | printStderr("Running \(executable) using efficiency cores only") 213 | p.qualityOfService = .background 214 | } 215 | p.executableURL = URL(fileURLWithPath: executable) 216 | p.arguments = CommandLine.arguments.suffix(from: 3).map { $0 } 217 | 218 | try! p.run() 219 | 220 | signal(SIGINT) { _ in p.terminate() } 221 | signal(SIGTERM) { _ in p.terminate() } 222 | signal(SIGKILL) { _ in p.terminate() } 223 | 224 | p.waitUntilExit() 225 | 226 | exit(p.terminationStatus) 227 | -------------------------------------------------------------------------------- /scripts/plug: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | EXTRA_VIM_OPTIONS="+qall" 4 | 5 | VIM=$(command -v vim) 6 | if [[ -z "${VIM}" ]]; then 7 | echo "Vim not installed. Can't do much without it." 8 | exit 1 9 | fi 10 | 11 | usage() { 12 | echo "plug wrapper usage:" 13 | echo "$0 install|update|upgrade|status|clean|update-plug" 14 | } 15 | 16 | case $1 in 17 | install ) 18 | "${VIM}" +PlugInstall "${EXTRA_VIM_OPTIONS}" 19 | ;; 20 | update ) 21 | "${VIM}" +PlugUpdate "${EXTRA_VIM_OPTIONS}" 22 | ;; 23 | upgrade ) 24 | "${VIM}" +PlugUpgrade "${EXTRA_VIM_OPTIONS}" 25 | ;; 26 | status ) 27 | "${VIM}" +PlugStatus #"${EXTRA_VIM_OPTIONS}" 28 | ;; 29 | clean ) 30 | "${VIM}" +PlugClean "${EXTRA_VIM_OPTIONS}" 31 | ;; 32 | update-plug ) 33 | curl --progress-bar -fLo ~/.vim/autoload/plug.vim --create-dirs \ 34 | https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim 35 | ;; 36 | -h | --help) 37 | usage 38 | ;; 39 | * ) 40 | echo "Unknown option." 41 | usage 42 | exit 1 43 | ;; 44 | esac 45 | -------------------------------------------------------------------------------- /scripts/pypi-get-deps: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | PKG=$1 4 | 5 | set -x 6 | curl -s -L "https://pypi.python.org/pypi/${PKG}/json" | 7 | jq '.info | {name, version, requires_dist, requires, setup_requires, test_requires, install_requires}' 8 | -------------------------------------------------------------------------------- /scripts/pypi-get-sdist: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | PKG="${1}" 4 | VERS="${2}" 5 | 6 | set -x 7 | curl -s -L "https://pypi.python.org/pypi/${PKG}/${VERS}/json" | 8 | jq -r '.urls | select(map(.package_type == "sdist")) | map(.url) | .[]' 9 | -------------------------------------------------------------------------------- /scripts/pypi-wheels-list: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | usage() { 4 | echo "Get the package files available for a PyPI package" 5 | echo "usage: $0 package [version]" >&2 6 | } 7 | 8 | get_latest_version() { 9 | local package="${1}" 10 | curl -s -L "https://pypi.python.org/pypi/${package}/json" | jq -r '.releases | keys | .[]' | sort -V | tail -n 1 11 | } 12 | 13 | require_command() { 14 | if ! command -v "${1}" >/dev/null; then 15 | echo "Needs ${1}, install it!" >&2 16 | exit 1 17 | fi 18 | } 19 | 20 | require_command curl 21 | require_command jq 22 | require_command sort 23 | require_command tail 24 | 25 | package="${1}" 26 | 27 | if [[ -z "${package}" ]]; then 28 | usage 29 | fi 30 | 31 | printf "Getting packages for %s" "${package}" >&2 32 | 33 | version="${2:-$(get_latest_version "${package}")}" 34 | 35 | printf " v%s\n" "${version}" >&2 36 | 37 | curl -s -L "https://pypi.python.org/pypi/${package}/json" | jq -r --arg release "${version}" '.releases[$release].[].filename' | sort -V 38 | -------------------------------------------------------------------------------- /scripts/ramdisk-create: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -z "${1}" ]; then 3 | echo "You must specify a size in megabytes." 4 | exit 1 5 | fi 6 | size=$1 7 | # multiply by 2048 because the size we need to pass is based on 8 | # 512 byte sectors. Divide the size in _bytes_ by 512. We're passing 9 | # the size in megabytes, so math means 2048. 10 | realsize=$(echo "${size} * 2048" | bc) 11 | 12 | name="${2:-ramdisk}" 13 | 14 | echo "Creating a ${size} MB (${realsize}) ramdisk at /Volumes/${name}..." 15 | 16 | volume=$(hdiutil attach -nomount "ram://${realsize}" | tr -d '[:space:]') 17 | echo "Ramdisk attached at ${volume}" 18 | 19 | # the above seems to take a moment to actually take effect. 20 | sleep 1 21 | 22 | diskutil erasevolume HFS+ "${name}" "${volume}" 23 | echo "Ramdisk at ${volume} formatted HFS+ as ${name}" 24 | 25 | echo "Unmount with: hdiutil eject ${volume}" 26 | echo "Remember, everything will go away the moment it is ejected!" 27 | -------------------------------------------------------------------------------- /scripts/ramdisk-list: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Lists all ramdisks currently existing 4 | 5 | HDIUTIL_SECTION_SEPARATOR = '=' * 48 6 | 7 | q = `hdiutil info` 8 | sections = q.split HDIUTIL_SECTION_SEPARATOR 9 | volumes = sections[1...sections.size] 10 | ramdisks = volumes.select { |v| v.include? 'ram://' } 11 | mapping = ramdisks.map { |d| d.split("\n").last.split("\t\t") }.to_h 12 | 13 | require 'pp' 14 | pp mapping 15 | 16 | puts "Eject any with 'hdiutil eject /dev/disk#'" 17 | -------------------------------------------------------------------------------- /scripts/reset-osx-camera: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo killall VDCAssistant 3 | -------------------------------------------------------------------------------- /scripts/routes: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | case "$(uname -s)" in 4 | Linux) 5 | ip route 6 | ;; 7 | Darwin) 8 | netstat -rn 9 | ;; 10 | *) 11 | echo "$0 doesn't know how to look up routes on $(uname -s)…" >&2 12 | ;; 13 | esac 14 | 15 | -------------------------------------------------------------------------------- /scripts/runtime-deps-from-effective-pom: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | EFFECTIVE_POM="${1:-target/effective-pom.xml}" 3 | >&2 echo "Getting dependencies in group:artifact:version format from effective POM to be output in ${EFFECTIVE_POM}" 4 | if [[ "${EFFECTIVE_POM}" = "pom.xml" ]]; then 5 | >&2 echo "Not overwriting pom.xml, that'd be a really bad idea!" 6 | exit 1 7 | fi 8 | 9 | mvn --quiet help:effective-pom "-Doutput=${EFFECTIVE_POM}" 10 | 11 | xmlstarlet select --omit-decl --noblanks --text -N "pom=http://maven.apache.org/POM/4.0.0" \ 12 | --template \ 13 | --match '/pom:project/pom:dependencies/pom:dependency[pom:scope/text()="compile" or pom:scope/text()="runtime"]' \ 14 | -v "concat(pom:groupId, ':', pom:artifactId, ':', pom:version)" \ 15 | --if "position() != last()" \ 16 | --output ',' \ 17 | "${EFFECTIVE_POM}" 18 | -------------------------------------------------------------------------------- /scripts/rvm-mount-brew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | BREW_RUBY_PATH=$(brew ruby -e "puts File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])") 4 | BREW_RUBY_VERSION=$(brew ruby -- --version | awk '{print $1 "-" $2}') 5 | 6 | set -x 7 | rvm mount "${BREW_RUBY_PATH}" -n "${BREW_RUBY_VERSION}-homebrew" 8 | -------------------------------------------------------------------------------- /scripts/rvm-mount-brew-ruby: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | declare BREW_RUBY 4 | BREW_RUBY="$(brew ruby -e "puts File.join(File.expand_path(RbConfig::CONFIG['bindir'] + '../../..'), 'current/bin', RbConfig::CONFIG['ruby_install_name'])")" 5 | 6 | rvm mount "${BREW_RUBY}" ruby-brew-current 7 | -------------------------------------------------------------------------------- /scripts/screenshot_cleanup.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'mkmf' # this is dangerous, internal use only for extconf.rb 4 | require 'date' 5 | 6 | unless find_executable('trash') 7 | puts "Unable to find trash executable. Install it:\n\tbrew install trash" 8 | exit 1 9 | end 10 | if File.exist? 'mkmf.log' 11 | puts 'Removing temporary mkmf file…' 12 | File.delete 'mkmf.log' 13 | end 14 | 15 | # Associates the time with the file for easier manipulation 16 | class FileWithTime 17 | REGEX = /(\d{4}-\d{2}-\d{2}) at (\d{1,2}\.\d{2}\.\d{2})( [AP]M)?/.freeze 18 | 19 | attr_reader :filename 20 | 21 | def initialize(filename) 22 | @filename = filename 23 | end 24 | 25 | def file 26 | @file ||= File.new filename 27 | end 28 | 29 | def basename 30 | `basename "#{filename}"`.strip 31 | end 32 | 33 | def timestamp 34 | @timestamp ||= extract_timestamp 35 | end 36 | 37 | def age_in_days 38 | (::DateTime.now - timestamp).to_i 39 | end 40 | 41 | def extract_timestamp 42 | matches = REGEX.match(@filename) 43 | date = matches[1] 44 | time = matches[2].tr('.', ':') 45 | timestamp_text = [date, time].join ' ' 46 | ::DateTime.parse timestamp_text 47 | end 48 | 49 | def to_s 50 | "#{age_in_days.to_s.rjust(3)}d ┣ #{basename}" 51 | end 52 | end 53 | 54 | DRY_RUN = ENV['DRY_RUN'] || false 55 | SCREENSHOT_DIR = `defaults read com.apple.screencapture location`.strip.freeze 56 | SCREENSHOT_PREFIX = "Screenshot" 57 | DEFAULT_SCREENSHOT_GLOB = "#{SCREENSHOT_DIR}/#{SCREENSHOT_PREFIX}**".freeze 58 | SCREENSHOT_GLOB = ENV['SCREENSHOT_GLOB'] || DEFAULT_SCREENSHOT_GLOB 59 | DEFAULT_ARCHIVE_GLOB = "#{SCREENSHOT_DIR}/Screenshot Archive/#{SCREENSHOT_PREFIX}**".freeze 60 | ARCHIVE_GLOB = ENV['ARCHIVE_GLOB'] || DEFAULT_ARCHIVE_GLOB 61 | ARCHIVE_DIR = `dirname "#{ARCHIVE_GLOB}"`.strip 62 | 63 | def trash(entry) 64 | puts "🗑 ⬅ #{entry}" 65 | `trash "#{entry.filename}"` unless DRY_RUN 66 | end 67 | 68 | def archive(entry) 69 | puts "🗄 ⬅ #{entry}" 70 | unless Dir.exist? ARCHIVE_DIR 71 | puts "Creating #{ARCHIVE_DIR}" 72 | Dir.mkdir ARCHIVE_DIR 73 | end 74 | new_name = [ARCHIVE_DIR, entry.basename].join(File::SEPARATOR) 75 | File.rename entry.filename, new_name unless DRY_RUN 76 | end 77 | 78 | 79 | puts "Looking at dirglob #{ARCHIVE_GLOB} for deletion…" 80 | # clean archive 81 | Dir[ARCHIVE_GLOB].each do |e| 82 | entry = FileWithTime.new e 83 | if entry.age_in_days > 15 84 | trash entry 85 | else 86 | puts "🗄 ⬇ #{entry}" 87 | end 88 | end 89 | puts "Looking at dirglob #{SCREENSHOT_GLOB} for archival…" 90 | Dir[SCREENSHOT_GLOB].each do |e| 91 | next if File.directory? e 92 | entry = FileWithTime.new e 93 | if entry.age_in_days > 7 94 | archive entry 95 | else 96 | puts "📂 ⬇ #{entry}" 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /scripts/seconds_between.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from datetime import datetime 5 | 6 | if len(sys.argv) < 3: 7 | sys.stderr.write( 8 | f"Usage: {sys.argv[0]} start end [format='%H:%M:%S.%f']\n") 9 | sys.exit(1) 10 | 11 | start = sys.argv[1] 12 | end = sys.argv[2] 13 | strpfmt = sys.argv[3] if len(sys.argv) == 4 else "%H:%M:%S.%f" 14 | 15 | s = datetime.strptime(start, strpfmt) 16 | e = datetime.strptime(end, strpfmt) 17 | d = e - s 18 | print(d.total_seconds()) 19 | -------------------------------------------------------------------------------- /scripts/serve: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if command -v miniserve > /dev/null; then 4 | miniserve "$@" 5 | elif command -v twist > /dev/null; then 6 | twist web "$@" 7 | elif command -v go > /dev/null; then 8 | # https://github.com/eliben/static-server 9 | go run github.com/eliben/static-server@latest "$@" 10 | elif python -V | grep -q "Python 3"; then 11 | python -m http.server "$@" 12 | elif python -V | grep -q "Python 2"; then 13 | python -m SimpleHTTPServer "$@" 14 | fi 15 | -------------------------------------------------------------------------------- /scripts/set-hostname: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | NEW="${1}" 3 | 4 | if [[ -z "${NEW}" ]]; then 5 | >&2 echo "Usage: $0 new-hostname" 6 | exit 1 7 | fi 8 | 9 | if [[ "Darwin" == "$(uname -s)" ]]; then 10 | sudo scutil --set ComputerName "${NEW}" 11 | sudo scutil --set HostName "${NEW}" 12 | sudo scutil --set LocalHostName "${NEW}" 13 | else 14 | sudo hostname "${NEW}" 15 | fi 16 | hostname -f 17 | -------------------------------------------------------------------------------- /scripts/sleep_utils.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sleepFor() { 4 | dots="…" 5 | count=$1 6 | while [ "$count" -ge 1 ]; do 7 | echo -n "$count$dots" 8 | sleep 1 9 | (( count-- )) 10 | done 11 | echo '0!' 12 | } 13 | -------------------------------------------------------------------------------- /scripts/spacify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | unless ARGV[0] 4 | STDERR.puts <<~USAGEDOC 5 | Usage: 6 | #{__FILE__} WORD-TO-SPACIFY 7 | Output: 8 | W O R D - T O - S P A C I F Y 9 | USAGEDOC 10 | exit 1 11 | end 12 | 13 | puts ARGV[0].split('').join(" ") 14 | 15 | -------------------------------------------------------------------------------- /scripts/speedup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | VIDEO_COEFF="${1}" 4 | INPUT="${2}" 5 | OUTPUT="${3}" 6 | 7 | if [ -z "${VIDEO_COEFF}" ] || [ -z "${INPUT}" ]; then 8 | >&2 echo "Usage: ${0} coefficient input output" 9 | exit 1 10 | fi 11 | 12 | AUDIO_COEFF="$(echo "scale=10;1 / ${VIDEO_COEFF}" | bc )" 13 | 14 | ffmpeg -i "${INPUT}" -vf "setpts=${VIDEO_COEFF}*PTS" -filter:a "atempo=${AUDIO_COEFF}" "${OUTPUT}" 15 | -------------------------------------------------------------------------------- /scripts/split-clip: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Written by Alexis Bezverkhyy in 2011 4 | # This is free and unencumbered software released into the public domain. 5 | # For more information, please refer to 6 | 7 | function usage { 8 | echo "Usage : $0 input.file chunk-duration [output-filename-format]" 9 | echo -e "\t - input file may be any kind of file reconginzed by ffmpeg" 10 | echo -e "\t - chunk duration must be in seconds" 11 | echo -e "\t - output filename format must be printf-like, for example myvideo-part-%04d.avi" 12 | echo -e "\t - if no output filename format is given, it will be computed\ 13 | automatically from input filename" 14 | } 15 | 16 | IN_FILE="$1" 17 | OUT_FILE_FORMAT="$3" 18 | typeset -i CHUNK_LEN 19 | CHUNK_LEN="$2" 20 | 21 | DURATION_HMS=$(ffmpeg -i "$IN_FILE" 2>&1 | grep Duration | cut -f 4 -d ' ') 22 | DURATION_H=$(echo "$DURATION_HMS" | cut -d ':' -f 1) 23 | DURATION_M=$(echo "$DURATION_HMS" | cut -d ':' -f 2) 24 | DURATION_S=$(echo "$DURATION_HMS" | cut -d ':' -f 3 | cut -d '.' -f 1) 25 | let "DURATION = ( DURATION_H * 60 + DURATION_M ) * 60 + DURATION_S" 26 | 27 | if [ "$DURATION" = '0' ] ; then 28 | echo "Invalid input video" 29 | usage 30 | exit 1 31 | fi 32 | 33 | if [ "$CHUNK_LEN" = "0" ] ; then 34 | echo "Invalid chunk size" 35 | usage 36 | exit 2 37 | fi 38 | 39 | if [ -z "$OUT_FILE_FORMAT" ] ; then 40 | FILE_EXT=$(echo "$IN_FILE" | sed 's/^.*\.\([a-zA-Z0-9]\+\)$/\1/') 41 | FILE_NAME=$(echo "$IN_FILE" | sed 's/^\(.*\)\.[a-zA-Z0-9]\+$/\1/') 42 | OUT_FILE_FORMAT="${FILE_NAME}-%03d.${FILE_EXT}" 43 | echo "Using default output file format : $OUT_FILE_FORMAT" 44 | fi 45 | 46 | N='1' 47 | OFFSET='0' 48 | let 'N_FILES = DURATION / CHUNK_LEN + 1' 49 | 50 | while [[ "$OFFSET" -lt "$DURATION" ]] ; do 51 | OUT_FILE=$(printf "$OUT_FILE_FORMAT" "$N") 52 | echo "writing $OUT_FILE ($N/$N_FILES)..." 53 | ffmpeg -i "$IN_FILE" -vcodec copy -acodec copy -ss "$OFFSET" -t "$CHUNK_LEN" "$OUT_FILE" 54 | let "N = N + 1" 55 | let "OFFSET = OFFSET + CHUNK_LEN" 56 | done 57 | -------------------------------------------------------------------------------- /scripts/spongebob: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | INPUT = ARGV.join(' ').downcase 4 | 5 | output = [] 6 | # INPUT.each_grapheme_cluster do |c| 7 | INPUT.each_char do |c| 8 | output << (Random.rand(2).zero? ? c.upcase : c) 9 | end 10 | 11 | puts output.join 12 | -------------------------------------------------------------------------------- /scripts/ssh-copy-id: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Shell script to install your public key on a remote machine 4 | # Takes the remote machine name as an argument. 5 | # Obviously, the remote machine must accept password authentication, 6 | # or one of the other keys in your ssh-agent, for this to work. 7 | 8 | ID_FILE="${HOME}/.ssh/id_rsa.pub" 9 | 10 | if [ "-i" = "$1" ]; then 11 | shift 12 | # check if we have 2 parameters left, if so the first is the new ID file 13 | if [ -n "$2" ]; then 14 | if expr "$1" : ".*\.pub" > /dev/null ; then 15 | ID_FILE="$1" 16 | else 17 | ID_FILE="$1.pub" 18 | fi 19 | shift # and this should leave $1 as the target name 20 | fi 21 | else 22 | if [ x$SSH_AUTH_SOCK != x ] && ssh-add -L >/dev/null 2>&1; then 23 | GET_ID="$GET_ID ssh-add -L" 24 | fi 25 | fi 26 | 27 | if [ -z "`eval $GET_ID`" ] && [ -r "${ID_FILE}" ] ; then 28 | GET_ID="cat \"${ID_FILE}\"" 29 | fi 30 | 31 | if [ -z "`eval $GET_ID`" ]; then 32 | echo "$0: ERROR: No identities found" >&2 33 | exit 1 34 | fi 35 | 36 | if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then 37 | echo "Usage: $0 [-i [identity_file]] [user@]machine" >&2 38 | exit 1 39 | fi 40 | 41 | # strip any trailing colon 42 | host=`echo $1 | sed 's/:$//'` 43 | 44 | { eval "$GET_ID" ; } | ssh $host "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys" || exit 1 45 | 46 | cat <&1 ) 8 | if [[ $? -ne 0 ]]; then 9 | date="gdate"; 10 | if [[ -z "$(command -v $date)" ]]; then 11 | >&2 echo "No date command with --date support found." 12 | if [[ "$(uname -s)" == "Darwin" ]]; then 13 | >&2 echo "Try installing GNU Coreutils with 'brew install coreutils' to get GNU date, which supports relative dates." 14 | fi 15 | exit 1 16 | fi 17 | fi 18 | 19 | # Show current timelog 20 | _t_timelog() { 21 | echo "$timelog" 22 | } 23 | 24 | # Run a ledger command on the timelog 25 | _t_ledger() { 26 | ledger -f "$timelog" "$@" 27 | } 28 | 29 | # do something in unix with the timelog 30 | _t_do() { 31 | action=$1; shift 32 | ${action} "$@" "${timelog}" 33 | } 34 | 35 | # Clock in to the given project 36 | # Clock in to the last project if no project is given 37 | _t_in() { 38 | [ ! "$1" ] && set -- "$@" "$(_t_last)" 39 | echo i `$date '+%Y-%m-%d %H:%M:%S'` $* >> "$timelog" 40 | } 41 | 42 | # Clock out 43 | _t_out() { 44 | echo o `$date '+%Y-%m-%d %H:%M:%S'` $* >> "$timelog" 45 | } 46 | 47 | # switch projects 48 | _t_sw() { 49 | if [[ $# -eq 2 ]]; then 50 | SWITCH_TS="$($date --date "${1}" '+%Y-%m-%d %H:%M:%S')" 51 | shift 52 | else 53 | SWITCH_TS="$($date '+%Y-%m-%d %H:%M:%S')" 54 | fi 55 | echo o "${SWITCH_TS}" >> "$timelog" 56 | echo i "${SWITCH_TS}" $* >> "$timelog" 57 | } 58 | 59 | # Show the currently clocked-in project 60 | _t_cur() { 61 | sed -e '/^i/!d;$!d' "${timelog}" | __t_extract_project 62 | } 63 | 64 | # Show the last checked out project 65 | _t_last() { 66 | sed -ne '/^o/{g;p;};h;' "${timelog}" | tail -n 1 | __t_extract_project 67 | } 68 | 69 | _t_start() { 70 | if [[ ! -z "$(_t_cur)" ]]; then 71 | echo "Cannot add an entry when one is checked out. Run '$(basename $0) out' to check out first." 72 | exit 1 73 | fi 74 | local start_date="$($date --date "${1}" '+%Y-%m-%d %H:%M:%S')" 75 | if [[ -z "${start_date}" ]]; then 76 | exit 1 #rely on date to have shown the error 77 | fi 78 | echo i "${start_date}" "${2}" >> "${timelog}" 79 | } 80 | 81 | _t_end() { 82 | local end_date 83 | if [[ -z "${1}" ]]; then 84 | _t_out "${@}" 85 | return 0 86 | fi 87 | end_date="$($date --date "${1}" '+%Y-%m-%d %H:%M:%S')" 88 | if [[ -z "${end_date}" ]]; then 89 | exit 1 #rely on date to have shown the error 90 | fi 91 | echo o "${end_date}" >> "${timelog}" 92 | } 93 | 94 | _t_vacation() { 95 | local account="${3:-A:Vacation}" 96 | local start_date; 97 | start_date="$($date --date "${1}" '+%Y-%m-%d')" 98 | local end_date; 99 | end_date="$($date --date "${2:-$1}" '+%Y-%m-%d')" 100 | local loop_end_date; 101 | loop_end_date="$($date --date "${end_date} + 1 day" '+%Y-%m-%d')" 102 | 103 | if [[ -z "$start_date" ]] || [[ -z "$end_date" ]]; then 104 | echo "A required date was malformed. Check output for hints." 105 | exit 1 106 | fi 107 | 108 | echo "Logging ${account} from ${start_date} to ${end_date}" 109 | local d="${start_date}" 110 | while [ "${d}" != "${loop_end_date}" ]; do 111 | echo "Logging for ${d}…" 112 | _t_log "${d} 09:30" "${d} 17:30" "${account}" 113 | d="$($date --date "${d} + 1 day" '+%Y-%m-%d')" 114 | done 115 | _t_ledger register --begin "${start_date}" --end "${d}" 116 | } 117 | 118 | # Explicitly log a start and end 119 | _t_log() { 120 | _t_start "${1}" "${3}" 121 | _t_end "${2}" 122 | } 123 | 124 | _t_sheet() { 125 | default_start="last Monday" 126 | start_when="${1:-$default_start}" 127 | for i in `seq 0 6`; do 128 | PERIOD="$($date -d "${start_when} + ${i} days" +%Y-%m-%d )"; 129 | _t_ledger -p "${PERIOD}" reg --days-of-week --start-of-week Monday; 130 | echo ''; 131 | done 132 | } 133 | 134 | _t_edit() { 135 | if [[ "${EDITOR}" =~ "vi" ]]; then 136 | # go to the bottom of the file by default for vi/m 137 | EDITOR_OPTIONS=("+ normal GA") 138 | fi 139 | _t_do "${EDITOR}" "${EDITOR_OPTIONS[@]}" "$@" 140 | } 141 | 142 | # Show usage 143 | _t_usage() { 144 | # TODO 145 | cat << EOF | column -t -s '-' 146 | Usage: t action 147 | actions: 148 | in - clock into project or last project 149 | out - clock out of project 150 | sw,switch - switch projects 151 | bal - show balance 152 | hours - show balance for today 153 | week - show balance for this week 154 | edit - edit timelog file 155 | cur - show currently open project 156 | last - show last closed project 157 | grep - grep timelog for argument 158 | cat - show timelog 159 | today - show today's entries in the timelog 160 | less - show timelog in pager 161 | timelog - show timelog file 162 | log - record an exact time <"start"> <"end"> 163 | start - record an exact start time <"start"> 164 | end - record an exact end time to the open project <"end"> 165 | p,projects - list projects used so far 166 | sheet - show a daily register of the previous week, optionally pass a start date 167 | vacation - log a project daily from <"start"> ["end"] [project, default A:Vacation] 168 | EOF 169 | } 170 | 171 | # 172 | # INTERNAL FUNCTIONS 173 | # 174 | 175 | __t_extract_project() { 176 | awk '$1 != "o" { 177 | line = $4 178 | for (i=5; i<=NF; i++) 179 | line = line " " $i; 180 | print line 181 | }' 182 | } 183 | 184 | action=$1; shift 185 | [ "$TIMELOG" ] && timelog="$TIMELOG" || timelog="${HOME}/.timelog.ldg" 186 | 187 | _t_echo_actions() { 188 | echo 'in 189 | out 190 | sw 191 | bal 192 | hours 193 | week 194 | switch 195 | edit 196 | cur 197 | last 198 | grep 199 | cat 200 | today 201 | less 202 | timelog 203 | log 204 | start 205 | end 206 | p 207 | projects 208 | sheet 209 | actions 210 | lastweek 211 | vacation' 212 | } 213 | 214 | case "${action}" in 215 | in) _t_in "$@";; 216 | out) _t_out "$@";; 217 | sw) _t_sw "$@";; 218 | bal) _t_ledger bal "$@";; 219 | hours) _t_ledger bal -p "since today" --end "tomorrow" "$@";; 220 | week) _t_ledger bal -p "this week" "$@";; 221 | lastweek) _t_ledger bal -p "last week" "$@";; 222 | switch) _t_sw "$@";; 223 | edit) _t_edit "$@";; 224 | cur) _t_cur "$@";; 225 | last) _t_last "$@";; 226 | grep) _t_do grep "$@";; 227 | cat) _t_do cat "$@";; 228 | today) _t_do grep "$($date "+%Y-%m-%d")";; 229 | less) _t_do less;; 230 | timelog) _t_timelog "$@";; 231 | log) _t_log "$@";; 232 | start) _t_start "$@";; 233 | end) _t_end "$@";; 234 | p) _t_ledger accounts "$@";; 235 | projects) _t_ledger accounts "$@";; 236 | sheet) _t_sheet "$@";; 237 | actions) _t_echo_actions;; 238 | vacation) _t_vacation "$@";; 239 | 240 | h) _t_usage;; 241 | *) _t_usage;; 242 | esac 243 | 244 | exit 0 245 | -------------------------------------------------------------------------------- /scripts/tabname: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [[ -z "$*" ]]; then 3 | CONTENT=$(basename "$(pwd)") 4 | else 5 | CONTENT=("$@") 6 | fi 7 | echo -ne "\033]0;${CONTENT}\007" 8 | -------------------------------------------------------------------------------- /scripts/time_in_tzs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | declare -A tz_map 3 | 4 | tz_map["P"]="America/Los_Angeles" 5 | tz_map["M"]="America/Denver" 6 | tz_map["C"]="America/Chicago" 7 | tz_map["E"]="America/New_York" 8 | tz_map["I"]="Asia/Kolkata" 9 | 10 | for key in "${!tz_map[@]}"; do 11 | printf "%s@%s\n" "$(TZ=":${tz_map[${key}]}" date "+%H:%M")" "${key}" 12 | done | sort | tr '\n' ' ' 13 | -------------------------------------------------------------------------------- /scripts/use-brewed-bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eu -o pipefail 3 | 4 | SHELLS="/etc/shells" 5 | 6 | check_for_brew() { 7 | [[ -n "$(command -v brew)" ]] 8 | } 9 | 10 | brew_bash_path() { 11 | echo "$(brew --prefix)/bin/bash" 12 | } 13 | 14 | check_etc_shells() { 15 | local SHELL_PATH="${1}" 16 | >&2 echo "Looking for ${SHELL_PATH} in ${SHELLS}…" 17 | grep -q "${SHELL_PATH}" "${SHELLS}" 18 | } 19 | 20 | write_etc_shells() { 21 | local SHELL_PATH="${1}" 22 | >&2 echo "Writing ${SHELL_PATH} to ${SHELLS}…" 23 | printf "\n%s" "${SHELL_PATH}" | sudo tee -a "${SHELLS}" > /dev/null 24 | } 25 | 26 | check_shell() { 27 | local SHELL_PATH="${1}" 28 | >&2 echo "Checking if \$SHELL (which is ${SHELL}) is ${SHELL_PATH}…" 29 | [[ "${SHELL}" == "${SHELL_PATH}" ]] 30 | } 31 | 32 | change_shell() { 33 | local SHELL_PATH="${1}" 34 | >&2 echo "Setting \$SHELL to ${SHELL_PATH}…" 35 | chsh -s "${SHELL_PATH}" 36 | } 37 | 38 | shell_version() { 39 | # assumes bash, safe for now? 40 | "${SHELL_PATH}" --version | head -n 1 | cut -d ' ' -f 4 41 | } 42 | 43 | check_for_brew || (echo "No brew? Install it." && exit 1) 44 | 45 | SHELL_PATH="${1:-"$(brew_bash_path)"}" 46 | 47 | (check_etc_shells "${SHELL_PATH}" || write_etc_shells "${SHELL_PATH}") && \ 48 | (check_shell "${SHELL_PATH}" || change_shell "${SHELL_PATH}") 49 | 50 | 51 | 52 | >&2 echo "Shell should now be ${SHELL_PATH}. Open a new terminal and verify the version (\$BASH_VERSION?) is $(shell_version)." 53 | -------------------------------------------------------------------------------- /scripts/vagrant-scp: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | OPTIONS=$(vagrant ssh-config | awk -v ORS=' ' '{print "-o " $1 "=" $2}') 3 | if [ "${VDEBUG}" ]; then 4 | echo "${OPTIONS}" "$@" 5 | fi 6 | scp "${OPTIONS}" "$@" || echo "Transfer failed. Did you use 'default:' as the target?" 7 | -------------------------------------------------------------------------------- /scripts/vagrant-ssh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PORT=2222 3 | if [ "${VAGPORT}" ]; then 4 | PORT=${VAGPORT} 5 | fi 6 | VAGRANT_GEM="$(dirname "$(gem which vagrant)")/.." 7 | VAGRANT_KEY=${VAGRANT_GEM}/keys/vagrant 8 | chmod 600 "${VAGRANT_KEY}" 9 | ssh -i "${VAGRANT_KEY}" -p "${PORT}" vagrant@localhost 10 | -------------------------------------------------------------------------------- /scripts/volume: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | value="${1}" 3 | 4 | if [[ -z "${value}" ]]; then 5 | echo "Usage: value mute|mid|max|" 6 | fi 7 | 8 | case "${value}" in 9 | mute) value=0 ;; 10 | max) value=10 ;; 11 | mid) value=5 ;; 12 | *) ;; 13 | esac 14 | 15 | sudo osascript -e "set Volume ${value}" 16 | -------------------------------------------------------------------------------- /scripts/weather: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Source: https://github.com/Pinjasaur/dotfiles/blob/193df781b46e1f7e7a556f386172b76f067adcd9/.functions#L35 3 | # If no $1, use the zip code from our IP 4 | # If no $2, use "q0n" as URL params 5 | curl -s -H "Accept-Language: ${LANG%_*}" "http://wttr.in/${1:-$(curl -s http://ipinfo.io/postal)}?${2:-q0n}" 6 | -------------------------------------------------------------------------------- /scripts/whatports: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sudo lsof -iTCP -sTCP:LISTEN -n -P 4 | -------------------------------------------------------------------------------- /scripts/whereami: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ssid_cmd="ssid" 4 | ssid_cmd="$(command -v ssid)" 5 | if [[ -z "${ssid_cmd}" ]]; then 6 | >2& echo "ssid retrieval command not found. Without an SSID, I cannot tell where I am." 7 | exit 1 8 | fi 9 | 10 | ssid="$(ssid)" 11 | 12 | case "${ssid}" in 13 | "Code & Supply") echo "C&S";; 14 | "blackridge.cad.cx") echo "🏠";; 15 | "") echo "Not connected to WiFi, so ¯\\_(ツ)_/¯";; 16 | *) echo "${ssid}";; 17 | esac 18 | -------------------------------------------------------------------------------- /scripts/widetext: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | printf "\033#6%s\n" "${@}" 3 | -------------------------------------------------------------------------------- /scripts/wordle-brute-force: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PATTERN="${1}" 4 | EXCLUDE="${2}" 5 | INCLUDE="${3}" 6 | 7 | log() { 8 | >&2 echo "${@}" 9 | } 10 | 11 | if command -v rg >/dev/null; then 12 | GREP="${GREP:-rg}" 13 | else 14 | GREP="${GREP:-grep}" 15 | fi 16 | 17 | if [[ ! "${PATTERN}" =~ "_" ]]; then 18 | log "First arg must have _ in it to indicate blanks, or you're already done!" 19 | log "Pass excludes as second arg and includes as third." 20 | exit 1 21 | fi 22 | 23 | 24 | log "$(printf \ 25 | "Looking for words fitting [%s] excluding [%s] including [%s]" \ 26 | "${PATTERN}" \ 27 | "${EXCLUDE}" \ 28 | "${INCLUDE}")" 29 | 30 | if [[ -n "${EXCLUDE}" ]] || (echo "${PATTERN}" | grep -vq '\w') ; then 31 | NOT="[^${PATTERN//_/}${EXCLUDE}]" 32 | fi 33 | 34 | REGEX="^${PATTERN//_/${NOT:-'\w'}}$" 35 | 36 | if [[ -n "${DEBUG}" ]]; then 37 | log "with regex: ${REGEX}" 38 | fi 39 | 40 | log "Candidates:" 41 | "${GREP}" "${REGEX}" /usr/share/dict/words | "${GREP}" "${INCLUDE:-}" 42 | -------------------------------------------------------------------------------- /scripts/yaml2json: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'json' 3 | require 'yaml' 4 | 5 | def yaml_as_ruby(data) 6 | YAML.parse(data).to_ruby 7 | end 8 | 9 | pretty = false 10 | file = ARGV.pop 11 | if ['-p', '--pretty'].include? file 12 | pretty = true 13 | file = ARGV.pop 14 | end 15 | data = if file == '-' 16 | STDIN.read 17 | else 18 | File.read(file) 19 | end 20 | 21 | if ENV['PRETTY'] || pretty 22 | puts JSON.pretty_generate(yaml_as_ruby(data)) 23 | else 24 | puts yaml_as_ruby(data).to_json 25 | end 26 | -------------------------------------------------------------------------------- /setup-alacritty.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | INSTALL_GUIDE_URL="https://github.com/alacritty/alacritty/blob/master/INSTALL.md" 4 | 5 | if [ "$(uname -s)" == "Darwin" ]; 6 | brew install alacritty 7 | exit 0 8 | fi 9 | 10 | # Sigh, I wish they'd package this... 11 | 12 | if ! command -v rustc; then 13 | echo "Setting up Rust..." 14 | bash setup-rust.sh 15 | fi 16 | 17 | if command -v apt; then 18 | apt install cmake pkg-config libfreetype6-dev libfontconfig1-dev libxcb-xfixes0-dev libxkbcommon-dev python3 19 | else 20 | echo "Install dependencies manually: ${INSTALL_GUIDE_URL}" 21 | fi 22 | 23 | if ! infocmp alacritty; then 24 | sudo tic -xe alacritty,alacritty-direct extra/alacritty.info 25 | fi 26 | 27 | echo "Installing desktop files..." 28 | 29 | sudo cp target/release/alacritty /usr/local/bin # or anywhere else in $PATH 30 | sudo cp extra/logo/alacritty-term.svg /usr/share/pixmaps/Alacritty.svg 31 | sudo desktop-file-install extra/linux/Alacritty.desktop 32 | sudo update-desktop-database 33 | 34 | echo "Installing man pages..." 35 | 36 | sudo mkdir -p /usr/local/share/man/man1 37 | gzip -c extra/alacritty.man | sudo tee /usr/local/share/man/man1/alacritty.1.gz > /dev/null 38 | gzip -c extra/alacritty-msg.man | sudo tee /usr/local/share/man/man1/alacritty-msg.1.gz > /dev/null 39 | 40 | BASH_COMPLETION_DIR="${BASH_COMPLETION_DIR:-/etc/bash_completion.d}" 41 | 42 | echo "Copying bash completions to ${BASH_COMPLETION_DIR}" 43 | sudo cp extra/completions/alacritty.bash "${BASH_COMPLETION_DIR}/alacritty" 44 | 45 | -------------------------------------------------------------------------------- /setup-apm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | source _helpers.sh 3 | command_exists "apm" 4 | apm_exists=$? 5 | if [[ $apm_exists -ne 0 ]]; then 6 | echo >&2 "apm isn't installed. Has Atom been installed?" 7 | exit 1 8 | fi 9 | 10 | apm install --packages-file apm.list 11 | 12 | # to generate list: 13 | # apm list --installed --bare 14 | -------------------------------------------------------------------------------- /setup-bash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "Setting up the shell to use bash from Homebrew…" 3 | 4 | echo "Current shell is ${SHELL} ($(${SHELL} --version | head -n 1))" 5 | 6 | BREW_DIR=$(brew --prefix bash) 7 | BASH="${BREW_DIR}/bin/bash" 8 | 9 | if [ ! -x "${BASH}" ]; then 10 | echo "Need to install bash, so doing that now…" 11 | brew install bash 12 | fi 13 | 14 | if [ ! -x "${BASH}" ]; then 15 | echo "Homebrew bash in ${BASH} not found even after (re)installing it, do something about it." 16 | exit 1 17 | fi 18 | 19 | echo "Adding $BASH to shells as superuser…" 20 | echo "$BASH" | sudo tee -a /etc/shells >/dev/null 21 | 22 | echo "Setting $BASH as shell for $(whoami)…" 23 | chsh -s "$BASH" 24 | 25 | echo "Now, reopen the terminal or try 'rebash' to reload using the newer bash." 26 | echo "New shell will be ${BASH} ($(${BASH} --version | head -n 1))." 27 | echo "Happy bashing!" 28 | -------------------------------------------------------------------------------- /setup-codespaces.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | install_shfmt() { 4 | # if we have brew, use it 5 | if command -v brew >/dev/null; then 6 | brew install shfmt 7 | return 8 | fi 9 | # we have apt, use it 10 | if ! (sudo apt-get update --yes && sudo apt-get install --yes --no-install-recommends shfmt); then 11 | if command -v go >/dev/null; then 12 | # we've got go, install latest through go 13 | go install mvdan.cc/sh/v3/cmd/shfmt@latest 14 | return 15 | fi 16 | fi 17 | } 18 | 19 | install_fd() { 20 | if command -v brew >/dev/null; then 21 | brew install fd 22 | return 23 | fi 24 | # we have apt, use it 25 | if ! sudo apt-get update --yes && sudo apt-get install --yes --no-install-recommends fd-find; then 26 | export FD_BIN="fdfind" 27 | fi 28 | } 29 | -------------------------------------------------------------------------------- /setup-debian-derivs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . _helpers.sh 4 | 5 | banner_text "Starting Debian deriv setup" 6 | 7 | ##################################### 8 | # setup internal proxy if available # 9 | # it makes downloads so much faster # 10 | ##################################### 11 | 12 | # install netcat, or update and then install netcat 13 | sudo apt-get -qy install netcat || (sudo apt-get update && sudo apt-get -qy install netcat) 14 | bash setup-internal-proxy.sh 15 | 16 | # update and install some basics 17 | 18 | sudo apt-get update 19 | sudo apt-get -qy install software-properties-common 20 | 21 | # setup heroku 22 | sudo apt-get -qy install snapd && sudo snap install heroku --classic 23 | 24 | # other essentials 25 | sudo apt-get -qy install \ 26 | build-essential \ 27 | vim 28 | 29 | # fonts 30 | sudo apt-get -qy install \ 31 | fonts-roboto \ 32 | fonts-noto \ 33 | fonts-lmodern \ 34 | fonts-powerline \ 35 | fonts-open-sans \ 36 | fonts-firacode \ 37 | fonts-liberation2 38 | 39 | # make capslock into escape 40 | if command -v gsettings; then 41 | gsettings set org.gnome.desktop.input-sources xkb-options "['grp:alt_shift_toggle', 'caps:escape']" 42 | elif command -v dconf; then 43 | dconf write /org/gnome/desktop/input-sources/xkb-options "['grp:alt_shift_toggle', 'caps:escape']" 44 | fi 45 | 46 | 47 | # elementaryOS-specific stuff 48 | if [[ "$(lsb_release --id --short)" == "elementary" ]]; then 49 | 50 | sudo apt-get -qy install \ 51 | fonts-raleway-elementary 52 | 53 | gsettings set io.elementary.terminal.settings font 'FiraCode 12' 54 | 55 | if [[ "$(lsb_release --codename --short)" == "hera" ]]; then 56 | sudo add-apt-repository ppa:philip.scott/elementary-tweaks 57 | sudo apt install elementary-tweaks 58 | else 59 | # we're probably on something newer, which switched to Pantheon 60 | sudo add-apt-repository ppa:philip.scott/pantheon-tweaks 61 | sudo apt install pantheon-tweaks 62 | fi 63 | 64 | fi 65 | 66 | # ChromeOS terminal essentials 67 | if [[ "$(hostname)" == "penguin" ]]; then 68 | if [[ "$(lsb_release --id --short)" == "Debian" ]]; then 69 | # setup Debian backports 70 | sudo tee /etc/apt/sources.list.d/debian-backports.list <<- DEBCONF 71 | deb http://deb.debian.org/debian $(lsb_release --codename --short)-backports main 72 | DEBCONF 73 | sudo apt-get update 74 | 75 | # install flatpak 76 | sudo apt install flatpak/$(lsb_release --codename --short)-backports 77 | flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo 78 | 79 | # install some flatpak packages 80 | flatpak install flathub org.videolan.VLC 81 | fi 82 | fi 83 | 84 | echo "Installing Keybase..." 85 | curl --remote-name https://prerelease.keybase.io/keybase_amd64.deb 86 | sudo apt install ./keybase_amd64.deb && rm ./keybase_amd64.deb 87 | 88 | -------------------------------------------------------------------------------- /setup-docker-linux.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . _helpers.sh 4 | 5 | banner_text "Starting Docker for Linux setup" 6 | echo "This script only works for Debian derivatives!" 7 | 8 | banner_text "Installing dependencies from repos" 9 | sudo apt-get update 10 | sudo apt-get -yq install \ 11 | apt-transport-https \ 12 | ca-certificates \ 13 | curl \ 14 | gnupg-agent \ 15 | software-properties-common 16 | 17 | banner_text "Installing Docker upstream GPG key" 18 | curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 19 | 20 | # I'm more likely to be running an Ubuntu derivative 21 | case "$(lsb_release -is)" in 22 | "ubuntu") CODENAME="$(lsb_release -cs)" ;; 23 | *) CODENAME="$(lsb_release -csu)" ;; 24 | esac 25 | 26 | banner_text "Adding repo for ${CODENAME}" 27 | 28 | sudo add-apt-repository \ 29 | "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ 30 | "${CODENAME}" \ 31 | stable" 32 | 33 | banner_text "Installing Docker dependencies from Docker repos" 34 | 35 | sudo apt-get update 36 | sudo apt-get -yq install \ 37 | docker-ce \ 38 | docker-ce-cli \ 39 | containerd.io \ 40 | docker-compose 41 | 42 | banner_text "Checking sudo access to Docker" 43 | sudo docker run hello-world 44 | banner_text "Enabling Docker startup in systemd" 45 | sudo systemctl enable docker 46 | banner_text "Checking docker group sanity" 47 | if [[ ! $(groups "${USER}" | grep -q docker) ]]; then 48 | echo "Adding Docker user group with ${USER} in it" 49 | sudo usermod -aG docker "${USER}" 50 | echo "Using newgrp to check operation..." 51 | newgrp docker <&2 "brew isn't available, installing Homebrew." 9 | install_homebrew 10 | fi 11 | 12 | -------------------------------------------------------------------------------- /setup-internal-proxy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PROXY_DETECTION_SCRIPT_PATH=/usr/local/bin/cadcx-proxy-detect 4 | PROXY_DETECTION_APT_CONF_PATH=/etc/apt/apt.conf.d/99cadcx-proxy-detect 5 | # quotes around the keyword makes bash not substitute inside the HEREDOC 6 | # inside _must_ be tabs for <<- to remove them when writing 7 | sudo tee "${PROXY_DETECTION_SCRIPT_PATH}" > /dev/null <<- "SCRIPT" 8 | #!/bin/bash 9 | HOST=proxy 10 | PORT=3128 11 | # in minutes 12 | FREQUENCY_CHECK=5 13 | 14 | LAST_RESULT_FILE=/tmp/last-proxy-result 15 | 16 | file_if_newer_than_minutes() { 17 | find "${1}" -mmin "-${2}" 18 | } 19 | 20 | write_last_result() { 21 | cat - > "${LAST_RESULT_FILE}" 22 | chmod 644 "${LAST_RESULT_FILE}" 23 | } 24 | 25 | LAST_RESULT="$(file_if_newer_than_minutes "${LAST_RESULT_FILE}" "${FREQUENCY_CHECK}")" 26 | 27 | if [ -n "${LAST_RESULT}" ]; then 28 | cat "${LAST_RESULT}" 29 | else 30 | >&2 echo "Checking proxy for ${@}" 31 | if nc -w2 -z $HOST $PORT; then 32 | >&2 echo "✓ $HOST:$PORT" 33 | echo -n "http://${HOST}:${PORT}" | write_last_result 34 | else 35 | >&2 echo "🗴 DIRECT" 36 | echo -n "DIRECT" | write_last_result 37 | fi 38 | fi 39 | SCRIPT 40 | sudo chmod +x "${PROXY_DETECTION_SCRIPT_PATH}" 41 | sudo tee "${PROXY_DETECTION_APT_CONF_PATH}" > /dev/null << APTCONF 42 | Acquire::http::Proxy-Auto-Detect "${PROXY_DETECTION_SCRIPT_PATH}"; 43 | Acquire::https::Proxy-Auto-Detect "${PROXY_DETECTION_SCRIPT_PATH}"; 44 | APTCONF 45 | -------------------------------------------------------------------------------- /setup-iterm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ -z "${HEJMO}" ]]; then 4 | 2&> echo "HEJMO is unset, so this script cannot determine the directory to which it should point iTerm2 for its configuration." 5 | 2&> echo "Setup Hejmo, eh?" 6 | exit 1 7 | fi 8 | 9 | ITERM_BUNDLE="com.googlecode.iterm2" 10 | ITERM_PREFS="${HEJMO}/iterm" 11 | 12 | echo "Configuring iTerm2 as specified in ${ITERM_PREFS}…" 13 | 14 | # make double sure that it's installed 15 | brew bundle --file="${ITERM_PREFS}/Brewfile.iterm" 16 | 17 | # set the default governing its preferences file 18 | defaults write "${ITERM_BUNDLE}" PrefsCustomFolder "${ITERM_PREFS}" 19 | 20 | echo "Done. Opening iTerm, which should be restarted if it was already open." 21 | 22 | open -b "${ITERM_BUNDLE}" 23 | -------------------------------------------------------------------------------- /setup-mac.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Set computer name (as done via System Preferences → Sharing) 4 | # set INTENDED_HOSTNAME in ~/.env.local 5 | if [ -z ${DISABLE_HOSTNAME_CHANGE+x} ]; then 6 | NEW_HOSTNAME="${INTENDED_HOSTNAME:-$(hostname)}" 7 | >&2 echo "Changing hostname to ${NEW_HOSTNAME}" 8 | sudo scutil --set ComputerName "${NEW_HOSTNAME}" 9 | sudo scutil --set HostName "${NEW_HOSTNAME}" 10 | sudo scutil --set LocalHostName "${NEW_HOSTNAME}" 11 | sudo defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName -string "${NEW_HOSTNAME}" 12 | else 13 | >&2 echo "Not changing hostname from $(hostname) because DISABLE_HOSTNAME_CHANGE is set." 14 | fi 15 | 16 | # enable sshd 17 | sudo systemsetup -f -setremotelogin on 18 | 19 | # enable screen sharing but not with a vnc password, macs only 20 | sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -configure -access -on -users admin -privs -all -restart -agent -menu 21 | 22 | # Expand save panel by default 23 | defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode -bool true 24 | defaults write NSGlobalDomain NSNavPanelExpandedStateForSaveMode2 -bool true 25 | 26 | # Expand print panel by default 27 | defaults write NSGlobalDomain PMPrintingExpandedStateForPrint -bool true 28 | defaults write NSGlobalDomain PMPrintingExpandedStateForPrint2 -bool true 29 | 30 | # Save to disk (not to iCloud) by default 31 | defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false 32 | 33 | # Automatically quit printer app once the print jobs complete 34 | defaults write com.apple.print.PrintingPrefs "Quit When Finished" -bool true 35 | 36 | # Disable the “Are you sure you want to open this application?” dialog 37 | defaults write com.apple.LaunchServices LSQuarantine -bool false 38 | 39 | # Reveal IP address, hostname, OS version, etc. when clicking the clock 40 | # in the login window 41 | sudo defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo HostName 42 | 43 | # Increase sound quality for Bluetooth headphones/headsets 44 | defaults write com.apple.BluetoothAudioAgent "Apple Bitpool Min (editable)" -int 40 45 | 46 | # Enable full keyboard access for all controls 47 | # (e.g. enable Tab in modal dialogs) 48 | defaults write NSGlobalDomain AppleKeyboardUIMode -int 3 49 | 50 | # Set language and text formats 51 | # Note: if you’re in the US, replace `EUR` with `USD`, `Centimeters` with 52 | # `Inches`, `en_GB` with `en_US`, and `true` with `false`. 53 | defaults write NSGlobalDomain AppleLanguages -array "en" 54 | defaults write NSGlobalDomain AppleLocale -string "en_US@currency=USD" 55 | defaults write NSGlobalDomain AppleMeasurementUnits -string "Inches" 56 | defaults write NSGlobalDomain AppleMetricUnits -bool false 57 | 58 | # Save screenshots to the desktop 59 | defaults write com.apple.screencapture location -string "${HOME}/Desktop" 60 | 61 | # Save screenshots in PNG format (other options: BMP, GIF, JPG, PDF, TIFF) 62 | defaults write com.apple.screencapture type -string "png" 63 | 64 | 65 | # Enable subpixel font rendering on non-Apple LCDs 66 | # Reference: https://github.com/kevinSuttle/macOS-Defaults/issues/17#issuecomment-266633501 67 | defaults write NSGlobalDomain AppleFontSmoothing -int 1 68 | 69 | # Enable HiDPI display modes (requires restart) 70 | sudo defaults write /Library/Preferences/com.apple.windowserver DisplayResolutionEnabled -bool true 71 | 72 | # Finder: show hidden files by default 73 | #defaults write com.apple.finder AppleShowAllFiles -bool true 74 | 75 | # Finder: show all filename extensions 76 | defaults write NSGlobalDomain AppleShowAllExtensions -bool true 77 | 78 | # Finder: show status bar 79 | defaults write com.apple.finder ShowStatusBar -bool true 80 | 81 | # Finder: show path bar 82 | defaults write com.apple.finder ShowPathbar -bool true 83 | 84 | # When performing a search, search the current folder by default 85 | defaults write com.apple.finder FXDefaultSearchScope -string "SCcf" 86 | 87 | # Automatically open a new Finder window when a volume is mounted 88 | defaults write com.apple.frameworks.diskimages auto-open-ro-root -bool true 89 | defaults write com.apple.frameworks.diskimages auto-open-rw-root -bool true 90 | defaults write com.apple.finder OpenWindowForNewRemovableDisk -bool true 91 | 92 | # Enable AirDrop over Ethernet and on unsupported Macs running Lion 93 | defaults write com.apple.NetworkBrowser BrowseAllInterfaces -bool true 94 | 95 | # Show the ~/Library folder 96 | chflags nohidden ~/Library 97 | 98 | # Show the /Volumes folder 99 | sudo chflags nohidden /Volumes 100 | 101 | # Only use UTF-8 in Terminal.app 102 | defaults write com.apple.terminal StringEncodings -array 4 103 | 104 | # Show the main window when launching Activity Monitor 105 | defaults write com.apple.ActivityMonitor OpenMainWindow -bool true 106 | 107 | # Visualize CPU usage in the Activity Monitor Dock icon 108 | defaults write com.apple.ActivityMonitor IconType -int 5 109 | 110 | # Show all processes in Activity Monitor 111 | defaults write com.apple.ActivityMonitor ShowCategory -int 0 112 | 113 | # Sort Activity Monitor results by CPU usage 114 | defaults write com.apple.ActivityMonitor SortColumn -string "CPUUsage" 115 | defaults write com.apple.ActivityMonitor SortDirection -int 0 116 | 117 | # automatically hide Dock 118 | defaults write com.apple.dock autohide -bool true && killall Dock 119 | 120 | # show network volumes on the desktop 121 | defaults write com.apple.finder ShowMountedServersOnDesktop -bool true && killall Finder 122 | 123 | # TextEdit should always start in plain text mode 124 | defaults write com.apple.TextEdit RichText -int 0 125 | 126 | 127 | -------------------------------------------------------------------------------- /setup-ruby.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # this will install or update RVM using 3 | # literally the steps from rvm.io 4 | ensure_brew() { 5 | if [[ -z "$(command -v brew)" ]]; then 6 | echo "Homebrew not found, can't install required dependencies." 7 | exit 2 8 | fi 9 | true 10 | } 11 | if [[ -z "$(command -v curl)" ]]; then 12 | echo "cURL not found. Are you even using a computer?" 13 | echo "Let's try to install it with Homebrew but Homebrew relies on cURL already…" 14 | ensure_brew && brew install curl 15 | fi 16 | if [[ -z "$(command -v gpg)" ]]; then 17 | echo "GPG not found, installing it…" 18 | ensure_brew && brew install gpg 19 | if [[ -z "$(command -v gpg)" ]]; then 20 | echo "GPG not available, cannot install RVM without being able to validate it." 21 | exit 1 22 | fi 23 | fi 24 | 25 | if ! gpg --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB; then 26 | curl -sSL https://rvm.io/mpapis.asc | gpg --import - 27 | curl -sSL https://rvm.io/pkuczynski.asc | gpg --import - 28 | fi 29 | 30 | gpg --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB 31 | curl -sSL https://get.rvm.io | bash -s stable 32 | # shellcheck source=/dev/null 33 | . ~/.bash_profile 34 | 35 | install_rvm_with_curlbash() { 36 | gpg --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB 37 | curl -sSL https://get.rvm.io | bash -s stable 38 | } 39 | 40 | install_rvm_for_debian() { 41 | sudo apt-get install --yes software-properties-common 42 | if ! sudo apt-add-repository -y ppa:rael-gc/rvm; then 43 | curl "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x7be3e5681146fd4f1a40eda28094bb14f4e3fbbe" | sudo tee /etc/apt/trusted.gpg.d/rael-gc_ubuntu_rvm.asc 44 | fi 45 | sudo apt-get update --yes 46 | sudo apt-get install --yes rvm 47 | sudo usermod -a -G rvm "${USER}" 48 | } 49 | 50 | if [[ -f /etc/os-release ]]; then 51 | # probably on Linux 52 | # shellcheck source=/dev/null 53 | . /etc/os-release 54 | case "${ID}" in 55 | "ubuntu" | "debian") 56 | install_rvm_for_debian 57 | ;; 58 | *) 59 | install_rvm_with_curlbash 60 | ;; 61 | esac 62 | else 63 | install_rvm_with_curlbash 64 | fi 65 | 66 | 67 | 68 | ## 69 | ## I almost never need a Ruby outside of a project scope since 2023. 70 | ## 71 | # if we're not already using an rvm ruby, install the same version as what the 72 | # system is using and use it. This makes this script a little future-proof. 73 | if ! grep -E -q -o 'rvm' <(command -v ruby); then 74 | system_version=$(/usr/bin/ruby --version | grep -E -o '[[:digit:]]\.[[:digit:]]\.[[:digit:]]') 75 | rvm install "${system_version}" "--with-openssl-dir=$(brew --prefix openssl)" 76 | fi 77 | 78 | -------------------------------------------------------------------------------- /setup-rust.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source "$HEJMO/scripts/sleep_utils.sh" 3 | e=$? 4 | if [[ $e -ne 0 ]]; then 5 | echo "Unable to load sleep_utils, errors might suck…" 6 | fi 7 | 8 | brew_bin=$(command -v brew) 9 | if [[ -z "$brew_bin" ]]; then 10 | echo -n "Homebrew is not available and must be for this script to work without errors. Continuing in " 11 | sleepFor 5 12 | fi 13 | 14 | if [[ -d "$(brew --prefix rust)" ]]; then 15 | echo -n "Removing rust homebrew package because it conflicts with rustup. Continuing in " 16 | sleepFor 5 17 | brew uninstall rust 18 | fi 19 | 20 | echo "Installing rustup in " 21 | sleepFor 2 22 | 23 | curl https://sh.rustup.rs -sSf | sh 24 | 25 | echo "Installing rustup completions in " 26 | sleepFor 2 27 | rustup completions bash > $(brew --prefix)/etc/bash_completion.d/rustup.bash-completion 28 | -------------------------------------------------------------------------------- /themes/Zenburn.itermcolors: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ansi 0 Color 6 | 7 | Blue Component 8 | 0.30196079611778259 9 | Green Component 10 | 0.30196079611778259 11 | Red Component 12 | 0.30196079611778259 13 | 14 | Ansi 1 Color 15 | 16 | Blue Component 17 | 0.31372550129890442 18 | Green Component 19 | 0.31372550129890442 20 | Red Component 21 | 0.43921568989753723 22 | 23 | Ansi 10 Color 24 | 25 | Blue Component 26 | 0.62352943420410156 27 | Green Component 28 | 0.74901962280273438 29 | Red Component 30 | 0.76470589637756348 31 | 32 | Ansi 11 Color 33 | 34 | Blue Component 35 | 0.62352941176470589 36 | Green Component 37 | 0.81176470588235294 38 | Red Component 39 | 0.8784313725490196 40 | 41 | Ansi 12 Color 42 | 43 | Blue Component 44 | 0.9529411792755127 45 | Green Component 46 | 0.74901962280273438 47 | Red Component 48 | 0.58039218187332153 49 | 50 | Ansi 13 Color 51 | 52 | Blue Component 53 | 0.82745099067687988 54 | Green Component 55 | 0.57647061347961426 56 | Red Component 57 | 0.92549020051956177 58 | 59 | Ansi 14 Color 60 | 61 | Blue Component 62 | 0.89019608497619629 63 | Green Component 64 | 0.87843137979507446 65 | Red Component 66 | 0.57647061347961426 67 | 68 | Ansi 15 Color 69 | 70 | Blue Component 71 | 1 72 | Green Component 73 | 1 74 | Red Component 75 | 1 76 | 77 | Ansi 2 Color 78 | 79 | Blue Component 80 | 0.54117649793624878 81 | Green Component 82 | 0.70588237047195435 83 | Red Component 84 | 0.37647059559822083 85 | 86 | Ansi 3 Color 87 | 88 | Blue Component 89 | 0.68627450980392157 90 | Green Component 91 | 0.87450980392156863 92 | Red Component 93 | 0.94117647058823528 94 | 95 | Ansi 4 Color 96 | 97 | Blue Component 98 | 0.43921568989753723 99 | Green Component 100 | 0.37647059559822083 101 | Red Component 102 | 0.31372550129890442 103 | 104 | Ansi 5 Color 105 | 106 | Blue Component 107 | 0.76470589637756348 108 | Green Component 109 | 0.54901963472366333 110 | Red Component 111 | 0.86274510622024536 112 | 113 | Ansi 6 Color 114 | 115 | Blue Component 116 | 0.82745099067687988 117 | Green Component 118 | 0.81568628549575806 119 | Red Component 120 | 0.54901963472366333 121 | 122 | Ansi 7 Color 123 | 124 | Blue Component 125 | 0.80000001192092896 126 | Green Component 127 | 0.86274510622024536 128 | Red Component 129 | 0.86274510622024536 130 | 131 | Ansi 8 Color 132 | 133 | Blue Component 134 | 0.50196081399917603 135 | Green Component 136 | 0.56470590829849243 137 | Red Component 138 | 0.43921568989753723 139 | 140 | Ansi 9 Color 141 | 142 | Blue Component 143 | 0.63921570777893066 144 | Green Component 145 | 0.63921570777893066 146 | Red Component 147 | 0.86274510622024536 148 | 149 | Background Color 150 | 151 | Blue Component 152 | 0.24705882370471954 153 | Green Component 154 | 0.24705882370471954 155 | Red Component 156 | 0.24705882370471954 157 | 158 | Bold Color 159 | 160 | Blue Component 161 | 0.80000001192092896 162 | Green Component 163 | 0.86274510622024536 164 | Red Component 165 | 0.86274510622024536 166 | 167 | Cursor Color 168 | 169 | Blue Component 170 | 0.35294118523597717 171 | Green Component 172 | 0.38823530077934265 173 | Red Component 174 | 0.45098039507865906 175 | 176 | Cursor Text Color 177 | 178 | Blue Component 179 | 0.0 180 | Green Component 181 | 0.0 182 | Red Component 183 | 0.0 184 | 185 | Foreground Color 186 | 187 | Blue Component 188 | 0.80000001192092896 189 | Green Component 190 | 0.86274510622024536 191 | Red Component 192 | 0.86274510622024536 193 | 194 | Selected Text Color 195 | 196 | Blue Component 197 | 0.47843137383460999 198 | Green Component 199 | 0.84705883264541626 200 | Red Component 201 | 0.7607843279838562 202 | 203 | Selection Color 204 | 205 | Blue Component 206 | 0.18431372940540314 207 | Green Component 208 | 0.19607843458652496 209 | Red Component 210 | 0.12941177189350128 211 | 212 | 213 | -------------------------------------------------------------------------------- /windows/AutoHotkey.ahk: -------------------------------------------------------------------------------- 1 | LShift & Capslock:: 2 | SetCapsLockState, % (State:=!State) ? "on" : "alwaysoff" 3 | Return 4 | 5 | g_AbortSendEsc := false 6 | 7 | #InstallKeybdHook 8 | SetCapsLockState, alwaysoff 9 | Capslock:: 10 | g_DoNotAbortSendEsc := true 11 | Send {LControl Down} 12 | KeyWait, CapsLock 13 | Send {LControl Up} 14 | if ( A_PriorKey = "CapsLock" ) 15 | { 16 | if(g_DoNotAbortSendEsc){ 17 | Send {Esc} 18 | } 19 | } 20 | return 21 | 22 | ~*^a:: 23 | ~*^b:: 24 | ~*^c:: 25 | ~*^d:: 26 | ~*^e:: 27 | ~*^f:: 28 | ~*^g:: 29 | ~*^h:: 30 | ~*^i:: 31 | ~*^j:: 32 | ~*^k:: 33 | ~*^l:: 34 | ~*^m:: 35 | ~*^n:: 36 | ~*^o:: 37 | ~*^p:: 38 | ~*^q:: 39 | ~*^r:: 40 | ~*^s:: 41 | ~*^t:: 42 | ~*^u:: 43 | ~*^v:: 44 | ~*^w:: 45 | ~*^x:: 46 | ~*^y:: 47 | ~*^z:: 48 | ~*^1:: 49 | ~*^2:: 50 | ~*^3:: 51 | ~*^4:: 52 | ~*^5:: 53 | ~*^6:: 54 | ~*^7:: 55 | ~*^8:: 56 | ~*^9:: 57 | ~*^0:: 58 | ~*^Space:: 59 | ~*^Backspace:: 60 | ~*^Delete:: 61 | ~*^Insert:: 62 | ~*^Home:: 63 | ~*^End:: 64 | ~*^PgUp:: 65 | ~*^PgDn:: 66 | ~*^Tab:: 67 | ~*^Return:: 68 | ~*^,:: 69 | ~*^.:: 70 | ~*^/:: 71 | ~*^;:: 72 | ~*^':: 73 | ~*^[:: 74 | ~*^]:: 75 | ~*^\:: 76 | ~*^-:: 77 | ~*^=:: 78 | ~*^`:: 79 | ~*^F1:: 80 | ~*^F2:: 81 | ~*^F3:: 82 | ~*^F4:: 83 | ~*^F5:: 84 | ~*^F6:: 85 | ~*^F7:: 86 | ~*^F8:: 87 | ~*^F9:: 88 | ~*^F10:: 89 | ~*^F11:: 90 | ~*^F12:: 91 | g_DoNotAbortSendEsc := false 92 | return 93 | 94 | 95 | -------------------------------------------------------------------------------- /windows/README.md: -------------------------------------------------------------------------------- 1 | # Windows configuration and tools 2 | 3 | I don't use Windows for development most of the time but every now and then I have a reason to test something. These are the tools and scripts I use to quickly ready an environment! Beware, because I also have some video gaming stuff in here since my primary usage of Windows is as effectively a game console. 4 | 5 | ## Chocolatey vs Scoop 6 | 7 | [Chocolatey](http://chocolatey.org/) has been my preferred package manager but I'm slowly switching over to [Scoop](https://scoop.sh/) as it matures into a tool with closer alignment to the goals of [Homebrew](https://brew.sh) in the macOS and Linux world: non-root user installation of development tools. All are great but I tend to prefer lightweight, single-purpose tools for all parts of development. 8 | 9 | ## Contributing 10 | 11 | See something off? Submit a PR! 12 | -------------------------------------------------------------------------------- /windows/install-allpurposes.ps1: -------------------------------------------------------------------------------- 1 | # Software that should be installed on any Windows environment I touch 2 | choco install --yes googlechrome firefox windirstat sysinternals procexp 3 | 4 | scoop install 7zip fd ripgrep -------------------------------------------------------------------------------- /windows/install-chocolatey.ps1: -------------------------------------------------------------------------------- 1 | Set-ExecutionPolicy AllSigned 2 | Set-ExecutionPolicy Bypass -Scope Process -Force 3 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 4 | iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) 5 | -------------------------------------------------------------------------------- /windows/install-desktop.ps1: -------------------------------------------------------------------------------- 1 | # programs that only make sense on a desktop workstation, not necessarily a (temporary) development environment 2 | choco install --yes brave vlc dropbox duplicati filezilla launchy adobereader aquasnap windirstat transgui InkScape bitwarden 3 | 4 | scoop install wincompose ytmdesktop uncap 5 | -------------------------------------------------------------------------------- /windows/install-development.ps1: -------------------------------------------------------------------------------- 1 | # Development software 2 | scoop bucket add extras 3 | scoop install alacritty extras/vcredist2017 putty git bzip2 curl gh coreutils wget xmlstarlet jq starship xsv 4 | 5 | # not needed after installation 6 | scoop uninstall vcredist2017 7 | -------------------------------------------------------------------------------- /windows/install-gaming.ps1: -------------------------------------------------------------------------------- 1 | choco install --yes discord autohotkey steam steam-cleaner goggalaxy battle.net obs-studio 2 | -------------------------------------------------------------------------------- /windows/install-mystack.ps1: -------------------------------------------------------------------------------- 1 | # Install my standard development languages and frameworks 2 | # I'll probably never use this so it's probably out of date! 3 | scoop install sbt ngrok helix netcat wireshark gradle 4 | 5 | # install rustup to install rust instead of installing rust directly 6 | scoop install rustup 7 | rustup install stable 8 | -------------------------------------------------------------------------------- /windows/install-scoop.ps1: -------------------------------------------------------------------------------- 1 | # allow execution after retrieval 2 | set-executionpolicy remotesigned -s currentuser 3 | # get the installer and execute it 4 | iex (new-object net.webclient).downloadstring('https://get.scoop.sh') 5 | # Scoop will use Aria2 for retrieval if it's available. It's a lot faster than built-in stuff! 6 | scoop install aria2 7 | --------------------------------------------------------------------------------