├── config ├── powerline │ ├── colorschemes │ │ ├── shell │ │ │ └── default.json │ │ ├── tmux │ │ │ └── default.json │ │ └── default.json │ ├── colors.json │ ├── config.json │ └── themes │ │ ├── tmux │ │ └── default.json │ │ ├── shell │ │ └── default.json │ │ └── powerline_terminus.json ├── fontconfig │ └── fonts.conf └── htop │ └── htoprc ├── link ├── .aprc ├── .rbenv │ └── default-gems ├── .bash_profile ├── .console-setup ├── .terminfo │ ├── 74 │ │ ├── tmux-256color │ │ └── tmux-256color-italic │ ├── 78 │ │ └── xterm-256color-italic │ └── t │ │ └── tmux-256color-italic ├── .fonts │ ├── iosevka-term-bold.ttf │ ├── iosevka-term-heavy.ttf │ ├── iosevka-term-italic.ttf │ ├── iosevka-term-light.ttf │ ├── iosevka-term-medium.ttf │ ├── iosevka-term-thin.ttf │ ├── m+1 for Powerline.ttf │ ├── ter-powerline-v32b.psf │ ├── ter-powerline-v32n.psf │ ├── iosevka-term-oblique.ttf │ ├── iosevka-term-regular.ttf │ ├── iosevka-term-bolditalic.ttf │ ├── iosevka-term-boldoblique.ttf │ ├── iosevka-term-extralight.ttf │ ├── iosevka-term-heavyitalic.ttf │ ├── iosevka-term-lightitalic.ttf │ ├── iosevka-term-thinitalic.ttf │ ├── iosevka-term-thinoblique.ttf │ ├── iosevka-term-heavyoblique.ttf │ ├── iosevka-term-lightoblique.ttf │ ├── iosevka-term-mediumitalic.ttf │ ├── iosevka-term-mediumoblique.ttf │ ├── iosevka-term-extralightitalic.ttf │ ├── iosevka-term-extralightoblique.ttf │ ├── M+ 1m bold Nerd Font Complete Mono.ttf │ ├── M+ 1m thin Nerd Font Complete Mono.ttf │ ├── M+ 1m light Nerd Font Complete Mono.ttf │ ├── M+ 1m medium Nerd Font Complete Mono.ttf │ ├── M+ 1m regular Nerd Font Complete Mono.ttf │ └── Terminus-PSF-README.md ├── .irbrc ├── .xprofile ├── .gemrc ├── .inputrc ├── .tmuxp │ ├── cb.yaml │ └── toast.yaml ├── .bashrc ├── .ssh │ ├── config │ └── authorized_keys ├── .toprc ├── .gitignore_global ├── .gvimrc ├── .vim │ ├── nerdtree_plugin │ │ └── expanderrific.vim │ └── plugin │ │ └── bclose.vim ├── .tmux.conf └── .vimrc ├── bin ├── subl ├── $ ├── poll-url ├── osx_lock_computer ├── id3cb ├── isip ├── update-rust-nightly ├── ssid ├── pid ├── manp ├── manh ├── resample-dpi ├── curlsubl ├── serve ├── multi_firefox ├── osx_create_installer ├── osx_hide_partition ├── eachdir ├── scan ├── count-commits ├── git-jump ├── gpr └── rename ├── source ├── 01_console.sh ├── 00_dotfiles.sh ├── 50_pebble.sh ├── 01_path.sh ├── 50_ruby.sh ├── 01_prompt.sh ├── 50_ubuntu_desktop.sh ├── 50_history.sh ├── 50_net.sh ├── 50_editor.sh ├── 50_node.sh ├── 50_ubuntu.sh ├── 10_powerline_go.sh ├── 50_misc.sh ├── 50_file.sh ├── 10_tmux.sh ├── 10_powerline.sh ├── 50_osx.sh ├── 50_aws.sh ├── 50_prompt.sh └── 50_vcs.sh ├── conf ├── tic │ ├── xterm-256color-italic.terminfo │ ├── tmux-256color-italic.terminfo │ └── tmux-256color.terminfo ├── manh │ └── styles.css └── osx │ └── NSUserReplacementItems.plist ├── init ├── 50_vim.sh ├── 10_osx_xcode.sh ├── 50_node.sh ├── 50_ruby.sh ├── 30_python_pip.sh ├── 20_osx_homebrew.sh ├── 30_osx_homebrew_recipes.sh ├── 30_osx_homebrew_casks.sh └── 20_ubuntu_apt.sh ├── vendor └── rename │ ├── README.txt │ └── rename ├── .gitignore ├── test ├── test_path_remove.sh ├── test_setdiff.sh └── test_array.sh ├── LICENSE-MIT ├── ansible └── roles │ └── ubuntu.yml ├── .gitmodules ├── copy └── .gitconfig └── README.md /config/powerline/colorschemes/shell/default.json: -------------------------------------------------------------------------------- 1 | ../default.json -------------------------------------------------------------------------------- /config/powerline/colorschemes/tmux/default.json: -------------------------------------------------------------------------------- 1 | ../default.json -------------------------------------------------------------------------------- /link/.aprc: -------------------------------------------------------------------------------- 1 | AwesomePrint.defaults = { 2 | :indent => -2 3 | } 4 | -------------------------------------------------------------------------------- /bin/subl: -------------------------------------------------------------------------------- 1 | /Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl -------------------------------------------------------------------------------- /link/.rbenv/default-gems: -------------------------------------------------------------------------------- 1 | bundler 2 | awesome_print 3 | pry 4 | lolcat 5 | -------------------------------------------------------------------------------- /source/01_console.sh: -------------------------------------------------------------------------------- 1 | # Set up the console 2 | setupcon 2>/dev/null 3 | -------------------------------------------------------------------------------- /link/.bash_profile: -------------------------------------------------------------------------------- 1 | if [ -f ~/.bashrc ]; then 2 | source ~/.bashrc 3 | fi 4 | -------------------------------------------------------------------------------- /link/.console-setup: -------------------------------------------------------------------------------- 1 | # CONFIGURATION FILE FOR SETUPCON 2 | FONT=~/.fonts/ter-powerline-v32b.psf 3 | -------------------------------------------------------------------------------- /link/.terminfo/74/tmux-256color: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.terminfo/74/tmux-256color -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-bold.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-heavy.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-heavy.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-italic.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-light.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-medium.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-thin.ttf -------------------------------------------------------------------------------- /link/.fonts/m+1 for Powerline.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/m+1 for Powerline.ttf -------------------------------------------------------------------------------- /link/.fonts/ter-powerline-v32b.psf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/ter-powerline-v32b.psf -------------------------------------------------------------------------------- /link/.fonts/ter-powerline-v32n.psf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/ter-powerline-v32n.psf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-oblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-oblique.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-regular.ttf -------------------------------------------------------------------------------- /link/.terminfo/t/tmux-256color-italic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.terminfo/t/tmux-256color-italic -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-bolditalic.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-boldoblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-boldoblique.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-extralight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-extralight.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-heavyitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-heavyitalic.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-lightitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-lightitalic.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-thinitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-thinitalic.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-thinoblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-thinoblique.ttf -------------------------------------------------------------------------------- /link/.terminfo/74/tmux-256color-italic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.terminfo/74/tmux-256color-italic -------------------------------------------------------------------------------- /link/.terminfo/78/xterm-256color-italic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.terminfo/78/xterm-256color-italic -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-heavyoblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-heavyoblique.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-lightoblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-lightoblique.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-mediumitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-mediumitalic.ttf -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-mediumoblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-mediumoblique.ttf -------------------------------------------------------------------------------- /config/powerline/colors.json: -------------------------------------------------------------------------------- 1 | { 2 | "gradients": { 3 | "battery_green_orange_red": [ 4 | [22, 94, 1] 5 | ] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-extralightitalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-extralightitalic.ttf -------------------------------------------------------------------------------- /source/00_dotfiles.sh: -------------------------------------------------------------------------------- 1 | # Passing the "source" arg tells it to only define functions, then quit. 2 | source $DOTFILES/bin/dotfiles "source" 3 | -------------------------------------------------------------------------------- /link/.fonts/iosevka-term-extralightoblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/iosevka-term-extralightoblique.ttf -------------------------------------------------------------------------------- /source/50_pebble.sh: -------------------------------------------------------------------------------- 1 | path=~/pebble-dev/PebbleSDK-current/bin 2 | if [[ -e "$path" ]]; then 3 | export PATH=$path:"$(path_remove $path)" 4 | fi 5 | -------------------------------------------------------------------------------- /link/.fonts/M+ 1m bold Nerd Font Complete Mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/M+ 1m bold Nerd Font Complete Mono.ttf -------------------------------------------------------------------------------- /link/.fonts/M+ 1m thin Nerd Font Complete Mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/M+ 1m thin Nerd Font Complete Mono.ttf -------------------------------------------------------------------------------- /conf/tic/xterm-256color-italic.terminfo: -------------------------------------------------------------------------------- 1 | xterm-256color-italic|xterm with 256 colors and italic, 2 | sitm=\E[3m, ritm=\E[23m, 3 | use=xterm-256color, 4 | -------------------------------------------------------------------------------- /link/.fonts/M+ 1m light Nerd Font Complete Mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/M+ 1m light Nerd Font Complete Mono.ttf -------------------------------------------------------------------------------- /link/.fonts/M+ 1m medium Nerd Font Complete Mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/M+ 1m medium Nerd Font Complete Mono.ttf -------------------------------------------------------------------------------- /link/.fonts/M+ 1m regular Nerd Font Complete Mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cowboy/dotfiles/master/link/.fonts/M+ 1m regular Nerd Font Complete Mono.ttf -------------------------------------------------------------------------------- /link/.irbrc: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'interactive_editor' 3 | require 'ap' 4 | 5 | IRB::Irb.class_eval do 6 | def output_value 7 | ap @context.last_value 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /init/50_vim.sh: -------------------------------------------------------------------------------- 1 | # Backups, swaps and undos are stored here. 2 | mkdir -p $DOTFILES/caches/vim 3 | 4 | # Download Vim plugins. 5 | if [[ "$(type -P vim)" ]]; then 6 | vim +PlugUpgrade +PlugUpdate +qall 7 | fi 8 | -------------------------------------------------------------------------------- /vendor/rename/README.txt: -------------------------------------------------------------------------------- 1 | rename 0.1.3 2 | Wednesday, Nov 4, 2009, 00:35 3 | Aristotle Pagaltzis 4 | http://plasmasturm.org/code/rename/ 5 | 6 | Note: downloaded directly because there's no repo to include. 7 | -------------------------------------------------------------------------------- /source/01_path.sh: -------------------------------------------------------------------------------- 1 | paths=( 2 | ~/.local/bin 3 | $DOTFILES/bin 4 | ) 5 | 6 | export PATH 7 | for p in "${paths[@]}"; do 8 | [[ -d "$p" ]] && PATH="$p:$(path_remove "$p")" 9 | done 10 | unset p paths 11 | -------------------------------------------------------------------------------- /link/.xprofile: -------------------------------------------------------------------------------- 1 | # https://wiki.archlinux.org/index.php/Touchpad_Synaptics#Buttonless_touchpads_.28aka_ClickPads.29 2 | xinput set-prop "DLL07BE:01 06CB:7A13 Touchpad" "Synaptics Soft Button Areas" 0 0 0 0 0 0 0 0 2>/dev/null 3 | -------------------------------------------------------------------------------- /link/.gemrc: -------------------------------------------------------------------------------- 1 | --- 2 | :benchmark: false 3 | :update_sources: true 4 | :backtrace: false 5 | :bulk_threshold: 1000 6 | :verbose: true 7 | :sources: 8 | - http://gemcutter.org 9 | - http://gems.rubyforge.org/ 10 | - http://gems.github.com/ 11 | -------------------------------------------------------------------------------- /link/.inputrc: -------------------------------------------------------------------------------- 1 | set editing-mode vi 2 | 3 | # COMMAND MODE 4 | set keymap vi-command 5 | 6 | # INSERT MODE 7 | set keymap vi-insert 8 | 9 | # Up/down arrows search history 10 | "\e[A": history-search-backward 11 | "\e[B": history-search-forward 12 | -------------------------------------------------------------------------------- /bin/$: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Ever pasted "$ somecommand" into the terminal and gotten this error? 4 | # -bash: $: command not found 5 | 6 | # Begone, silly errors! Lazy copy + paste forever!! ETCETERA!!!! 7 | 8 | echo 'Quit pasting in commands from the internet, you lazy bum.' 9 | "$@" 10 | -------------------------------------------------------------------------------- /bin/poll-url: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | url="$1" 4 | string="$2" 5 | 6 | while true; do 7 | echo "Checking URL." 8 | curl -s "$url" | grep -i "$string" >/dev/null && { 9 | echo "\"$string\" found!" | terminal-notifier -message -title "Poll URL" -open "$url" 10 | } 11 | sleep 10 12 | done 13 | -------------------------------------------------------------------------------- /link/.tmuxp/cb.yaml: -------------------------------------------------------------------------------- 1 | session_name: cb 2 | windows: 3 | 4 | - layout: main-vertical 5 | options: 6 | automatic-rename: off 7 | panes: 8 | - shell_command: vim 9 | focus: true 10 | - shell_command: 11 | window_name: dotfiles 12 | start_directory: '~/.dotfiles' 13 | focus: true 14 | -------------------------------------------------------------------------------- /init/10_osx_xcode.sh: -------------------------------------------------------------------------------- 1 | # OSX-only stuff. Abort if not OSX. 2 | is_osx || return 1 3 | 4 | # Some tools look for XCode, even though they don't need it. 5 | # https://github.com/cowboy/dotfiles#os-x-notes 6 | if [[ ! -d "$('xcode-select' -print-path 2>/dev/null)" ]]; then 7 | sudo xcode-select -switch /Library/Developer/CommandLineTools 8 | fi 9 | -------------------------------------------------------------------------------- /init/50_node.sh: -------------------------------------------------------------------------------- 1 | # Install volta if necessary 2 | if [[ ! "$VOLTA_HOME" ]]; then 3 | curl https://get.volta.sh | bash -s -- --skip-setup 4 | export VOLTA_HOME=~/.volta 5 | grep --silent "$VOLTA_HOME/bin" <<< $PATH || export PATH="$VOLTA_HOME/bin:$PATH" 6 | volta install node 7 | volta install yarn 8 | volta install tsc 9 | fi 10 | -------------------------------------------------------------------------------- /source/50_ruby.sh: -------------------------------------------------------------------------------- 1 | export PATH 2 | 3 | if [[ -e /etc/profile.d/rvm.sh ]]; then 4 | # rvm init 5 | source /etc/profile.d/rvm.sh 6 | else 7 | # rbenv init. 8 | PATH="$(path_remove $DOTFILES/vendor/rbenv/bin):$DOTFILES/vendor/rbenv/bin" 9 | 10 | if [[ "$(type -P rbenv)" && ! "$(type -t _rbenv)" ]]; then 11 | eval "$(rbenv init -)" 12 | fi 13 | fi 14 | -------------------------------------------------------------------------------- /bin/osx_lock_computer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sleep 0.5 4 | 5 | if [[ "$(ioreg -c AppleSmartBattery | grep '"ExternalConnected" = Yes')" ]]; then 6 | # Plugged in: start screensaver. 7 | open /System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app 8 | else 9 | # Battery power: go to lock menu. 10 | /System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend 11 | fi 12 | -------------------------------------------------------------------------------- /config/powerline/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "common": { 3 | "term_truecolor": "auto", 4 | "ambiwidth": 1 5 | }, 6 | "ext": { 7 | "shell": { 8 | "colorscheme": "default", 9 | "theme": "default", 10 | "local_themes": { 11 | "continuation": "continuation", 12 | "select": "select" 13 | } 14 | }, 15 | "tmux": { 16 | "colorscheme": "default", 17 | "theme": "default" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /link/.bashrc: -------------------------------------------------------------------------------- 1 | # Where the magic happens. 2 | export DOTFILES=~/.dotfiles 3 | 4 | # Source all files in "source" 5 | function src() { 6 | local file 7 | if [[ "$1" ]]; then 8 | source "$DOTFILES/source/$1.sh" 9 | else 10 | for file in $DOTFILES/source/*; do 11 | source "$file" 12 | done 13 | fi 14 | } 15 | 16 | # Run dotfiles script, then source. 17 | function dotfiles() { 18 | $DOTFILES/bin/dotfiles "$@" && src 19 | } 20 | 21 | src 22 | -------------------------------------------------------------------------------- /source/01_prompt.sh: -------------------------------------------------------------------------------- 1 | # Allow prompt to be restored to default. 2 | if [[ "${#__PROMPT_DEFAULT[@]}" == 0 ]]; then 3 | __PROMPT_DEFAULT=("$PS1" "$PS2" "$PS3" "$PS4") 4 | fi 5 | 6 | # The default prompt. 7 | function prompt_default() { 8 | unset PROMPT_COMMAND 9 | for i in {1..4}; do 10 | eval "PS$i='${__PROMPT_DEFAULT[i-1]}'" 11 | done 12 | } 13 | 14 | # An uber-simple prompt for demos / screenshots. 15 | function prompt_zero() { 16 | prompt_default 17 | PS1='$ ' 18 | } 19 | -------------------------------------------------------------------------------- /init/50_ruby.sh: -------------------------------------------------------------------------------- 1 | # Initialize rbenv. 2 | source $DOTFILES/source/50_ruby.sh 3 | 4 | # Install Ruby. 5 | if [[ "$(type -P rbenv)" ]]; then 6 | versions=(2.4.0) 7 | 8 | rubies=($(setdiff "${versions[*]}" "$(rbenv whence ruby)")) 9 | if (( ${#rubies[@]} > 0 )); then 10 | e_header "Installing Ruby versions: ${rubies[*]}" 11 | for r in "${rubies[@]}"; do 12 | rbenv install "$r" 13 | [[ "$r" == "${versions[0]}" ]] && rbenv global "$r" 14 | done 15 | fi 16 | fi 17 | -------------------------------------------------------------------------------- /source/50_ubuntu_desktop.sh: -------------------------------------------------------------------------------- 1 | # Ubuntu desktop-only stuff. Abort if not Ubuntu desktop. 2 | is_ubuntu_desktop || return 1 3 | 4 | export BROWSER=google-chrome 5 | alias manh='man -H' 6 | 7 | alias pbcopy='xclip -i -selection clipboard' 8 | alias pbpaste='xclip -o -selection clipboard' 9 | 10 | # http://www.omgubuntu.co.uk/2016/06/install-steam-on-ubuntu-16-04-lts 11 | function steam() { 12 | if [[ -e ~/.steam ]]; then 13 | command steam "$@" 14 | else 15 | LD_PRELOAD='/usr/$LIB/libstdc++.so.6 /usr/$LIB/libgcc_s.so.1 /usr/$LIB/libxcb.so.1 /usr/$LIB/libgpg-error.so' command steam 16 | fi 17 | } 18 | -------------------------------------------------------------------------------- /source/50_history.sh: -------------------------------------------------------------------------------- 1 | # History settings 2 | 3 | # Allow use to re-edit a faild history substitution. 4 | shopt -s histreedit 5 | # History expansions will be verified before execution. 6 | shopt -s histverify 7 | 8 | # Entries beginning with space aren't added into history, and duplicate 9 | # entries will be erased (leaving the most recent entry). 10 | export HISTCONTROL="ignorespace:erasedups" 11 | # Give history timestamps. 12 | export HISTTIMEFORMAT="[%F %T] " 13 | # Lots o' history. 14 | export HISTSIZE=10000 15 | export HISTFILESIZE=10000 16 | 17 | # Easily re-execute the last history command. 18 | alias r="fc -s" 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Lots of junk goes in here. 2 | /caches/ 3 | /backups/ 4 | 5 | # Top secret stuff! 6 | /link/.ssh/id_* 7 | /link/.ssh/*.pem 8 | /link/.ssh/known_hosts* 9 | 10 | # Don't commit Vim plugins, vim-plug will install them. 11 | /link/.vim/plugged 12 | 13 | # Don't commit rbenv temp files. 14 | /link/.rbenv/shims/ 15 | /link/.rbenv/versions/ 16 | /link/.rbenv/version 17 | 18 | # Don't commit tmux plugins, tpm will install them. 19 | /link/.tmux/plugins 20 | 21 | # Don't commit tmux resurrect state. 22 | /link/.tmux/resurrect 23 | 24 | # Ignore any file with LOCAL in the name (good for per-machine vars/functions) 25 | *LOCAL* 26 | -------------------------------------------------------------------------------- /link/.ssh/config: -------------------------------------------------------------------------------- 1 | Host * 2 | 3 | # Forward ssh agent to the remote machine. 4 | ForwardAgent yes 5 | 6 | # Automatically add all common hosts to the host file as they are connected to. 7 | StrictHostKeyChecking no 8 | 9 | # Allow MacOS to use the keychain for SSH key passphrases 10 | IgnoreUnknown UseKeychain 11 | Host * 12 | UseKeychain yes 13 | AddKeysToAgent yes 14 | IdentityFile ~/.ssh/id_rsa 15 | 16 | # For vagrant virtual machines 17 | # http://hakunin.com/six-ansible-practices#configure-your-ssh-client 18 | Host 192.168.33.* *.loc 19 | StrictHostKeyChecking no 20 | UserKnownHostsFile=/dev/null 21 | LogLevel ERROR 22 | -------------------------------------------------------------------------------- /bin/id3cb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ ! -e "$1" ]]; then cat < 2 | 3 | 4 | 5 | Consolas 6 | 7 | monospace 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | sans-serif 16 | 17 | 18 | monospace 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /conf/manh/styles.css: -------------------------------------------------------------------------------- 1 | /* Colors from http://ethanschoonover.com/solarized */ 2 | /* Fonts from http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/design/index-en.html */ 3 | 4 | body { 5 | color: #839496; 6 | background: #002b36; 7 | padding: 0; 8 | margin: 0 0 3em 1.5em; 9 | } 10 | 11 | h2 { 12 | color: #2aa198; 13 | } 14 | 15 | b { 16 | color: #93a1a1; 17 | } 18 | 19 | i { 20 | font-style: normal; 21 | text-decoration: underline; 22 | color: #b58900; 23 | } 24 | 25 | h2, 26 | pre { 27 | font-family: mplusNerdFontCM-regular, mplus-2m-regular, Monaco, monospace; 28 | } 29 | 30 | pre { 31 | margin: -0.5em 0 -1.5em; 32 | } 33 | 34 | body > hr, 35 | body > address { 36 | display: none; 37 | } 38 | -------------------------------------------------------------------------------- /conf/tic/tmux-256color-italic.terminfo: -------------------------------------------------------------------------------- 1 | # A xterm-256color based TERMINFO that adds the escape sequences for italic. 2 | # 3 | # Install: 4 | # 5 | # tic xterm-256color-italic.terminfo 6 | # 7 | # Usage: 8 | # 9 | # export TERM=xterm-256color-italic 10 | # 11 | 12 | # tmux-256color-italic|tmux with 256 colors and italic, 13 | # sitm=\ePtmux;\e\E[3m\e\\, ritm=\ePtmux;\e\E[23m\e\\, 14 | # use=screen-256color, 15 | 16 | 17 | 18 | # https://alexpearce.me/2014/05/italics-in-iterm2-vim-tmux/#tmux-21-and-above 19 | tmux|tmux terminal multiplexer, 20 | ritm=\E[23m, rmso=\E[27m, sitm=\E[3m, smso=\E[7m, Ms@, 21 | use=xterm+tmux, use=screen, 22 | 23 | tmux-256color|tmux with 256 colors, 24 | use=xterm+256setaf, use=tmux, 25 | -------------------------------------------------------------------------------- /link/.toprc: -------------------------------------------------------------------------------- 1 | RCfile for "top with windows" # shameless braggin' 2 | Id:a, Mode_altscr=0, Mode_irixps=1, Delay_time=3.000, Curwin=0 3 | Def fieldscur=AEHIOQTWKNMbcdfgjplrsuvyzX 4 | winflags=130745, sortindx=13, maxtasks=0 5 | summclr=2, msgsclr=1, headclr=2, taskclr=2 6 | Job fieldscur=ABcefgjlrstuvyzMKNHIWOPQDX 7 | winflags=62777, sortindx=0, maxtasks=0 8 | summclr=6, msgsclr=6, headclr=7, taskclr=6 9 | Mem fieldscur=ANOPQRSTUVbcdefgjlmyzWHIKX 10 | winflags=62777, sortindx=13, maxtasks=0 11 | summclr=5, msgsclr=5, headclr=4, taskclr=5 12 | Usr fieldscur=ABDECGfhijlopqrstuvyzMKNWX 13 | winflags=62777, sortindx=4, maxtasks=0 14 | summclr=3, msgsclr=3, headclr=2, taskclr=3 15 | -------------------------------------------------------------------------------- /bin/pid: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat < 0 )); then 20 | e_header "Installing pip packages (${#pip_packages[@]})" 21 | for package in "${pip_packages[@]}"; do 22 | e_arrow "$package" 23 | $pip_cmd install "$package" 24 | done 25 | fi 26 | -------------------------------------------------------------------------------- /config/htop/htoprc: -------------------------------------------------------------------------------- 1 | # Beware! This file is rewritten by htop when settings are changed in the interface. 2 | # The parser is also very primitive, and not human-friendly. 3 | fields=0 48 17 18 38 39 40 2 46 47 49 1 4 | sort_key=46 5 | sort_direction=1 6 | hide_threads=0 7 | hide_kernel_threads=1 8 | hide_userland_threads=0 9 | shadow_other_users=0 10 | show_thread_names=0 11 | show_program_path=1 12 | highlight_base_name=0 13 | highlight_megabytes=1 14 | highlight_threads=1 15 | tree_view=0 16 | header_margin=1 17 | detailed_cpu_time=0 18 | cpu_count_from_zero=0 19 | update_process_names=0 20 | account_guest_in_cpu_meter=0 21 | color_scheme=0 22 | delay=15 23 | left_meters=LeftCPUs Memory Clock Uptime 24 | left_meter_modes=1 1 2 2 25 | right_meters=RightCPUs Swap LoadAverage Tasks 26 | right_meter_modes=1 1 2 2 27 | -------------------------------------------------------------------------------- /link/.fonts/Terminus-PSF-README.md: -------------------------------------------------------------------------------- 1 | Terminess Powerline PSF (PC Screen Font) Type 2 files with embedded 2 | unicode table. 3 | 4 | Used primary in Linux EGA/VGA console. As it is required for the font 5 | to contain exactly 256 or 512 characters and Terminus already used all 6 | of them this font files have the following glyphs substituted with the 7 | Powerline glyphs: 8 | 9 | Codepoint Character Name 10 | U+2320 ⌠ TOP HALF INTEGRAL 11 | U+2321 ⌡ BOTTOM HALF INTEGRAL 12 | U+20A7 ₧ PESETA SIGN (Spain currency sign) 13 | U+00BE ¾ VULGAR FRACTION THREE QUARTERS 14 | U+00B3 ³ SUPERSCRIPT THREE 15 | U+00AC ¬ NOT SIGN (angled dash) 16 | U+221A √ SQUARE ROOT 17 | 18 | Note: "substituted" means these codepoints and glyphs were removed, 19 | new glyphs and codepoints were added. Powerline symbols are accessible 20 | using the usual codepoints, not above ones. -------------------------------------------------------------------------------- /source/50_editor.sh: -------------------------------------------------------------------------------- 1 | # Editing 2 | 3 | export VISUAL=vim 4 | 5 | # If mvim is installed, use it instead of native vim 6 | if [[ "$(which mvim)" ]]; then 7 | VISUAL="mvim -v" 8 | alias vim="$VISUAL" 9 | fi 10 | 11 | if [[ ! "$SSH_TTY" ]]; then 12 | if [[ ! "$TMUX" ]]; then 13 | is_osx && VISUAL=mvim || VISUAL=gvim 14 | fi 15 | export LESSEDIT="$VISUAL ?lm+%lm -- %f" 16 | export GIT_EDITOR="$VISUAL -f" 17 | fi 18 | 19 | export EDITOR="$VISUAL" 20 | 21 | # VS Code 22 | if [[ "$(which code)" ]]; then 23 | EDITOR="code --wait" 24 | VISUAL="code --wait --new-window" 25 | unset GIT_EDITOR 26 | fi 27 | 28 | function q() { 29 | if [[ -t 0 ]]; then 30 | $VISUAL "$@" 31 | else 32 | # Read from STDIN (and hide the annoying "Reading from stdin..." message) 33 | $VISUAL - > /dev/null 34 | fi 35 | } 36 | alias qv="q $DOTFILES/link/.{,g}vimrc +'cd $DOTFILES'" 37 | alias qs="q $DOTFILES" 38 | 39 | # For when you have vim on the brain 40 | alias :q=exit 41 | -------------------------------------------------------------------------------- /link/.gitignore_global: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.class 4 | *.dll 5 | *.exe 6 | *.o 7 | *.so 8 | 9 | # Packages # 10 | ############ 11 | # It's better to unpack these files and commit the raw source because 12 | # git has its own built in compression methods. 13 | *.7z 14 | *.jar 15 | *.rar 16 | *.zip 17 | *.gz 18 | *.bzip 19 | *.xz 20 | *.lzma 21 | 22 | #packing-only formats 23 | *.iso 24 | *.tar 25 | 26 | #package management formats 27 | *.dmg 28 | *.xpi 29 | *.gem 30 | *.egg 31 | *.deb 32 | *.rpm 33 | 34 | # Logs and databases # 35 | ###################### 36 | *.log 37 | *.sqlite 38 | 39 | # OS generated files # 40 | ###################### 41 | .DS_Store 42 | 43 | # Thumbnails 44 | ._* 45 | 46 | # Files that might appear on external disk 47 | .Spotlight-V100 48 | .Trashes 49 | 50 | # Windows image file caches 51 | Thumbs.db 52 | 53 | # Folder config file 54 | Desktop.ini 55 | 56 | # Vim 57 | .swp 58 | .swo 59 | .*.swp 60 | .*.swo 61 | 62 | # VS Code 63 | .vscode -------------------------------------------------------------------------------- /link/.tmuxp/toast.yaml: -------------------------------------------------------------------------------- 1 | session_name: 'toast' 2 | windows: 3 | 4 | - layout: main-vertical 5 | options: 6 | automatic-rename: off 7 | panes: 8 | - shell_command: vim 9 | focus: true 10 | - shell_command: './toaster.sh -r --pull --dropDB --startAll' 11 | - shell_command: 12 | start_directory: '~/Toast/git-repos/toast-qa' 13 | window_name: qa 14 | focus: true 15 | 16 | - layout: main-vertical 17 | options: 18 | automatic-rename: off 19 | panes: 20 | - shell_command: vim 21 | focus: true 22 | - shell_command: 'yarn build:watch' 23 | - shell_command: 24 | start_directory: '~/Toast/git-repos/toastweb/resources/online_ordering' 25 | window_name: oo 26 | 27 | - layout: main-vertical 28 | options: 29 | automatic-rename: off 30 | panes: 31 | - shell_command: vim 32 | focus: true 33 | - shell_command: 'yarn build:watch' 34 | - shell_command: 35 | start_directory: '~/Toast/git-repos/toastweb/resources/ui_kit' 36 | window_name: ui_kit 37 | -------------------------------------------------------------------------------- /source/50_node.sh: -------------------------------------------------------------------------------- 1 | [[ "$1" != init && ! -e ~/.volta ]] && return 1 2 | 3 | export VOLTA_HOME=~/.volta 4 | grep --silent "$VOLTA_HOME/bin" <<< $PATH || export PATH="$VOLTA_HOME/bin:$PATH" 5 | 6 | # Use npx instead of installing global npm modules 7 | function make_npx_alias () { 8 | alias $1="npx $@" 9 | } 10 | 11 | make_npx_alias json2yaml 12 | make_npx_alias pushstate-server 13 | make_npx_alias yaml2json 14 | 15 | function get_last_modified_js_file_recursive() { 16 | find . -type d \( -name node_modules -o -name .git -o -name .build \) -prune -o -type f \( -name '*.js' -o -name '*.jsx' \) -print0 \ 17 | | xargs -0 stat -f '%m %N' \ 18 | | sort -rn \ 19 | | head -1 \ 20 | | cut -d' ' -f2- 21 | } 22 | 23 | function watchfile() { 24 | yarn watch --testPathPattern "$(get_last_modified_js_file_recursive | sed -E 's#.*/([^/]+)/([^.]+).*#\1/\2.#')" 25 | } 26 | 27 | function watchdir() { 28 | yarn watch --testPathPattern "$(dirname "$(get_last_modified_js_file_recursive)")" 29 | } 30 | -------------------------------------------------------------------------------- /bin/manp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat </dev/null 2>&1 33 | 34 | # Open PDF (if it does exist). 35 | [[ -e "$file" ]] && open "$file" 36 | -------------------------------------------------------------------------------- /link/.gvimrc: -------------------------------------------------------------------------------- 1 | set go-=T " Hide toolbar 2 | set go-=r " Hide right scrollbar 3 | set go-=L " Hide left scrollbar 4 | 5 | if has('win32') 6 | " My favorite font! 7 | set guifont=M+_1m_for_Powerline:h12 8 | 9 | " Alt-[, ]: Buffer Navigation 10 | nmap :bprev 11 | nmap :bnext 12 | vmap :bprev 13 | vmap :bnext 14 | vmap :set invfugv 15 | else 16 | let s:uname = system("echo -n \"$(uname -s)\"") 17 | if s:uname == "Linux" 18 | set guifont=Iosevka\ Term\ 12 19 | else " OSX 20 | " My favorite font! 21 | set guifont=M+\ 1m\ regular\ Nerd\ Font\ Complete:h16 22 | 23 | " Cmd-[, ]: Buffer Navigation 24 | nmap :bprev 25 | nmap :bnext 26 | vmap :bprev 27 | vmap :bnext 28 | 29 | " Cmd-T: New buffer 30 | macm File.New\ Tab key= 31 | nmap :enew 32 | vmap :enew 33 | 34 | " Cmd-Enter: Toggle Fullscreen 35 | nmap :set invfu 36 | vmap :set invfugv 37 | endif 38 | endif 39 | -------------------------------------------------------------------------------- /link/.ssh/authorized_keys: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAtUUvs69wWAwb2bos+hCOgMlEZcivoniUSDYn4PazXqdvr6GYj2B2nrLDMeTcpnpTC+43lMpWz19xGDGQ8QF86pf1zuUXBKxtUHuNBFJwkIKmjiw816GGEqASsz0dcqBALmSXOZrZ4+ekolL3ec1VnSyo4sBRYfa5du/FvWkCzlJEBISbzrpskJyXHOB5mC2k1J6aMnvLIBG6Z2OPaD37L3lMmgrDwiHkEsqoeQzUNYC+/68WH3i80YEkpjIaFQp06b2u5uA6jGwCjQAmcjMrzL/+4n33y9mD0cXCdVz6ivbr/wOxJHo8kCmMivMUeMkG538yWcPBWjW5bEcYG0BBdw== cowboy@cowbook 2 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDv8aATYKH2OincTSVBBubPMxl7xjEbc+72GCyk9RUGmYS7iX908Qf+sVH5BZ3Opp8BoDfoAaAhXxwDRJu8bXllPbs7pomcuDP1Fn7Zrf5iMS6K7aRhYfFBmUsTKveQ7r8kWEvPhC8hyrcG28W8SK9fxsBMGVxi5K1jr3nCR33XUo7bNbUMm87+jCCgCqGFlv6qNych0EyvBo90NUAXxXniCwtV6nuntAe5f59VUNnCrbfx8aYMZK4P7PtFh70mx7Rult1J4HWJD54+o3sf6udlG/YADa6qtfcRf1Df6j++CoIrgWy3SsYa4IgFu1btPGYdiNNv7H3zRzrLdXSk7aVtaP280xaFZXSfmHhajoWZ69W6cKGbqrisfxPLtnMxLB9It8CFPwpxS7OEK0hPUbRfJH1wDp0at08MLxQ5hQcEK1lwNKKZFzbMK5ejTa+BTs8qNNmwUTGHu08/75QiOgtnuCYFW2LrDuUnkyaljHWIcfCVJu1+VRyg92x78qrBKr4NGC7YO1B8PyQdJkq40JWcyK041OQwHxc2jZvpMYR9aEyAH4kgCM28mKXR8uz8JemtMTExd3xrYz4mtKezvL66ZJb2OgN/M12Jjoiu4XY1sG10Vgg0u9XkpoQcsNjHkR945J20t1095VPubQkHCxi3X2yrqJE3W+oE4nFE8piBnQ== ben.alman@toasttab.com 3 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 "Cowboy" Ben Alman 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /init/20_osx_homebrew.sh: -------------------------------------------------------------------------------- 1 | # OSX-only stuff. Abort if not OSX. 2 | is_osx || return 1 3 | 4 | # Install Homebrew. 5 | if [[ ! "$(type -P brew)" ]]; then 6 | e_header "Installing Homebrew" 7 | true | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 8 | fi 9 | 10 | # Exit if, for some reason, Homebrew is not installed. 11 | [[ ! "$(type -P brew)" ]] && e_error "Homebrew failed to install." && return 1 12 | 13 | e_header "Updating Homebrew" 14 | brew doctor 15 | brew update 16 | 17 | # Functions used in subsequent init scripts. 18 | 19 | # Tap Homebrew kegs. 20 | function brew_tap_kegs() { 21 | kegs=($(setdiff "${kegs[*]}" "$(brew tap)")) 22 | if (( ${#kegs[@]} > 0 )); then 23 | e_header "Tapping Homebrew kegs: ${kegs[*]}" 24 | for keg in "${kegs[@]}"; do 25 | brew tap $keg 26 | done 27 | fi 28 | } 29 | 30 | # Install Homebrew recipes. 31 | function brew_install_recipes() { 32 | recipes=($(setdiff "${recipes[*]}" "$(brew list)")) 33 | if (( ${#recipes[@]} > 0 )); then 34 | e_header "Installing Homebrew recipes: ${recipes[*]}" 35 | for recipe in "${recipes[@]}"; do 36 | brew install $recipe 37 | done 38 | fi 39 | } 40 | -------------------------------------------------------------------------------- /config/powerline/colorschemes/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": { 3 | "hostname": 4 | { "fg": "white", "bg": "darkblue", "attrs": ["bold"] }, 5 | "attached_clients": 6 | { "fg": "white", "bg": "darkestblue", "attrs": ["bold"] }, 7 | "date": 8 | { "fg": "gray8", "bg": "gray2", "attrs": [] }, 9 | "time": 10 | { "fg": "gray10", "bg": "gray2", "attrs": ["bold"] }, 11 | "internal_ip": 12 | { "fg": "gray10", "bg": "darkestpurple", "attrs": [] }, 13 | "external_ip": 14 | { "fg": "white", "bg": "mediumpurple", "attrs": [] }, 15 | "system_load_gradient": 16 | { "fg": "green_yellow_orange_red", "bg": "gray1", "attrs": [] }, 17 | "uptime": 18 | { "fg": "gray10", "bg": "gray2", "attrs": [] }, 19 | "branch": 20 | { "fg": "gray9", "bg": "mediumgreen", "attrs": [] }, 21 | "branch_dirty": 22 | { "fg": "white", "bg": "mediumorange", "attrs": [] }, 23 | "branch_clean": 24 | { "fg": "white", "bg": "mediumgreen", "attrs": [] }, 25 | "battery": 26 | { "fg": "gray8", "bg": "gray0", "attrs": [] }, 27 | "battery_gradient": 28 | { "fg": "white", "bg": "battery_green_orange_red", "attrs": [] } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /source/50_ubuntu.sh: -------------------------------------------------------------------------------- 1 | # Ubuntu-only stuff. Abort if not Ubuntu. 2 | is_ubuntu || return 1 3 | 4 | # Package management 5 | alias update="sudo apt-get -qq update && sudo apt-get upgrade" 6 | alias install="sudo apt-get install" 7 | alias remove="sudo apt-get remove" 8 | alias search="apt-cache search" 9 | 10 | alias say=spd-say 11 | 12 | # Make 'less' more. 13 | [ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" 14 | 15 | # Switch between already-downloaded node versions. 16 | function node_ver() { 17 | ( 18 | ver="${1#v}" 19 | nodes=() 20 | if [[ ! -e "/usr/local/src/node-v$ver" ]]; then 21 | shopt -s extglob 22 | shopt -s nullglob 23 | cd "/usr/local/src" 24 | eval 'for n in node-v*+([0-9]).+([0-9]).+([0-9]); do nodes=("${nodes[@]}" "${n#node-}"); done' 25 | [[ "$1" ]] && echo "Node.js version \"$1\" not found." 26 | echo "Valid versions are: ${nodes[*]}" 27 | [[ "$(type -P node)" ]] && echo "Current version is: $(node --version)" 28 | exit 1 29 | fi 30 | cd "/usr/local/src/node-v$ver" 31 | sudo make install >/dev/null 2>&1 && 32 | echo "Node.js $(node --version) installed." || 33 | echo "Error, $(node --version) installed." 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /bin/manh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat </dev/null && cat > "$file" < 34 | 35 | 36 | 37 | $(MANWIDTH=120 man "$@" 2>/dev/null | man2html -bare -nodepage) 38 | 39 | 40 | EOF 41 | 42 | # Open HTML (if it does exist). 43 | for cmd in xdg-open open; do [[ "$(which $cmd)" ]] && break; done 44 | [[ -e "$file" ]] && $cmd "$file" 45 | -------------------------------------------------------------------------------- /source/10_powerline_go.sh: -------------------------------------------------------------------------------- 1 | if [[ "$(which powerline-go)" ]]; then 2 | # Installed by homebrew on MacOS 3 | powerline_go_cmd=powerline-go 4 | elif [[ -x ${GOPATH:-~/go}/bin/powerline-go ]]; then 5 | # Installed manually (for now) via 6 | # go get -u github.com/justjanne/powerline-go 7 | powerline_go_cmd=${GOPATH:-~/go}/bin/powerline-go 8 | else 9 | return 10 | fi 11 | 12 | function _update_ps1() { 13 | PS1="$($powerline_go_cmd \ 14 | -static-prompt-indicator \ 15 | -cwd-mode plain \ 16 | -numeric-exit-codes \ 17 | -error $? \ 18 | -modules termtitle,time,venv,user,ssh,cwd,perms,git,hg,jobs,newline,exit,root \ 19 | )" 20 | } 21 | 22 | # Ensure exit code is reset when pressing "enter" with no command 23 | # because I'm OCD. 24 | __prompt_stack=() 25 | trap '__prompt_stack=("${__prompt_stack[@]}" "$BASH_COMMAND")' DEBUG 26 | 27 | function __prompt_exit_code() { 28 | local exit_code=$? 29 | # If the first command in the stack is __prompt_command, no command was run. 30 | # Set exit_code to 0. 31 | [[ "${__prompt_stack[0]}" == "__prompt_exit_code" ]] && exit_code=0 32 | # Return the (correct) exit code. 33 | return $exit_code 34 | } 35 | 36 | function __prompt_cleanup() { 37 | # Reset the stack. 38 | __prompt_stack=() 39 | } 40 | 41 | PROMPT_COMMAND='__prompt_exit_code;_update_ps1;__prompt_cleanup' 42 | -------------------------------------------------------------------------------- /ansible/roles/ubuntu.yml: -------------------------------------------------------------------------------- 1 | # Basic Ubuntu machine setup. 2 | # 3 | # Usage: 4 | # 5 | # 1. $ ansible-playbook ansible/roles/ubuntu.yml -i aaa.bbb.ccc.ddd, 6 | # 2. $ ssh aaa.bbb.ccc.ddd 7 | # 3. Install dotfiles! 8 | --- 9 | - hosts: all 10 | remote_user: root 11 | vars: 12 | user: "{{ lookup('env', 'USER') }}" 13 | password: "$6$Som3S@lt$bJOg1GmsbFaHHH1pGTaduyC4QYyGekpniRZKMRxFtzhg.RSH5.s3awqVxZWcV/sWFZ8Ss2K0QclwNQlJXsZH31" 14 | tasks: 15 | - name: update/upgrade apt 16 | apt: upgrade=dist update_cache=yes 17 | 18 | - name: add primary user 19 | user: name={{ user }} shell=/bin/bash groups=sudo append=yes password={{ password }} 20 | 21 | - name: upload primary user ssh public key 22 | authorized_key: user={{ user }} key="{{ lookup('file', '~/.ssh/id_rsa.pub') }}" 23 | 24 | - name: disable root login (and other sshd_config tweaks) 25 | lineinfile: dest=/etc/ssh/sshd_config state={{ item.state }} line="{{ item.line }}" 26 | with_items: 27 | - { state: absent, line: "PermitRootLogin yes" } 28 | - { state: present, line: "PermitRootLogin without-password" } 29 | - { state: present, line: "UseDNS no" } 30 | - { state: present, line: "AllowUsers {{ user }}" } 31 | notify: 32 | - reload ssh 33 | 34 | handlers: 35 | - name: reload ssh 36 | service: name=ssh state=restarted 37 | -------------------------------------------------------------------------------- /link/.vim/nerdtree_plugin/expanderrific.vim: -------------------------------------------------------------------------------- 1 | " expanderrific.vim 2 | " https://github.com/cowboy/dotfiles 3 | " 4 | " Allow right/left to expand/collapse NERDTree dirs in a more meaningful way. 5 | 6 | " Ben Alman 7 | " http://benalman.com/ 8 | 9 | if exists("g:loaded_nerdtree_expanderrific") 10 | finish 11 | endif 12 | let g:loaded_nerdtree_expanderrific = 1 13 | 14 | let expanderrific_expand = ['l', ''] 15 | let expanderrific_collapse = ['h', ''] 16 | 17 | for key in expanderrific_expand 18 | call NERDTreeAddKeyMap({'key': key, 'scope': 'DirNode', 'callback': 'NERDTreeExpanderrificExpand'}) 19 | endfor 20 | 21 | for key in expanderrific_collapse 22 | call NERDTreeAddKeyMap({'key': key, 'scope': 'Node', 'callback': 'NERDTreeExpanderrificCollapse'}) 23 | endfor 24 | 25 | function! NERDTreeExpanderrificExpand(dir) 26 | let opts = {'reuse': 1} 27 | if g:NERDTreeCascadeOpenSingleChildDir == 0 28 | call a:dir.open(opts) 29 | else 30 | call a:dir.openAlong(opts) 31 | endif 32 | call b:NERDTree.render() 33 | endfunction 34 | 35 | function! NERDTreeExpanderrificCollapse(node) 36 | let node = a:node 37 | if !a:node.path.isDirectory || !a:node.isOpen 38 | let node = a:node.parent 39 | endif 40 | if node != b:NERDTreeRoot 41 | call node.close() 42 | call b:NERDTree.render() 43 | call node.putCursorHere(0, 0) 44 | endif 45 | endfunction 46 | 47 | -------------------------------------------------------------------------------- /config/powerline/themes/tmux/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "segments": { 3 | "right": [ 4 | { 5 | "function": "powerline.segments.common.bat.battery", 6 | "priority": 34 7 | }, 8 | { 9 | "function": "powerline.segments.common.sys.uptime", 10 | "priority": 55 11 | }, 12 | { 13 | "function": "powerline.segments.common.sys.system_load", 14 | "priority": 50 15 | }, 16 | { 17 | "function": "powerline.segments.common.net.external_ip", 18 | "priority": 40 19 | }, 20 | { 21 | "function": "powerline.segments.common.net.internal_ip", 22 | "priority": 45 23 | }, 24 | { 25 | "name": "time", 26 | "function": "powerline.segments.common.time.date", 27 | "priority": 30, 28 | "args": { 29 | "format": "%H:%M", 30 | "istime": true 31 | } 32 | }, 33 | { 34 | "name": "date_seg", 35 | "function": "powerline.segments.common.time.date", 36 | "priority": 36 37 | }, 38 | { 39 | "function": "powerline.segments.tmux.attached_clients", 40 | "priority": 25, 41 | "args": { 42 | "minimum": 2 43 | } 44 | }, 45 | { 46 | "function": "powerline.segments.common.net.hostname", 47 | "priority": 20 48 | } 49 | ] 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "rbenv"] 2 | path = vendor/rbenv 3 | url = https://github.com/sstephenson/rbenv.git 4 | [submodule "git-extras"] 5 | path = vendor/git-extras 6 | url = https://github.com/visionmedia/git-extras.git 7 | [submodule "z"] 8 | path = vendor/z 9 | url = https://github.com/rupa/z.git 10 | [submodule ".tmux"] 11 | path = vendor/.tmux 12 | url = https://github.com/gpakosz/.tmux.git 13 | [submodule ".tmux-tpm"] 14 | path = link/.tmux/plugins/tpm 15 | url = https://github.com/tmux-plugins/tpm.git 16 | [submodule "rbenv-vars"] 17 | path = link/.rbenv/plugins/rbenv-vars 18 | url = https://github.com/sstephenson/rbenv-vars.git 19 | [submodule "ruby-build"] 20 | path = link/.rbenv/plugins/ruby-build 21 | url = https://github.com/sstephenson/ruby-build.git 22 | [submodule "rbenv-default-gems"] 23 | path = link/.rbenv/plugins/rbenv-default-gems 24 | url = https://github.com/sstephenson/rbenv-default-gems.git 25 | [submodule "rbenv-gem-rehash"] 26 | path = link/.rbenv/plugins/rbenv-gem-rehash 27 | url = https://github.com/sstephenson/rbenv-gem-rehash.git 28 | [submodule "rbenv-whatis"] 29 | path = link/.rbenv/plugins/rbenv-whatis 30 | url = https://github.com/rkh/rbenv-whatis.git 31 | [submodule "rbenv-use"] 32 | path = link/.rbenv/plugins/rbenv-use 33 | url = https://github.com/rkh/rbenv-use.git 34 | [submodule "rbenv-update"] 35 | path = link/.rbenv/plugins/rbenv-update 36 | url = https://github.com/rkh/rbenv-update.git 37 | -------------------------------------------------------------------------------- /bin/resample-dpi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ ! "$1" || "$1" == "-h" || "$1" == "--help" ]]; then cat </dev/null 2>&1 38 | done 39 | -------------------------------------------------------------------------------- /copy/.gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | name = Ben Alman 3 | email = EMAIL 4 | [core] 5 | autocrlf = input 6 | whitespace = fix,space-before-tab,tab-in-indent,trailing-space 7 | excludesfile = ~/.gitignore_global 8 | [apply] 9 | whitespace = fix 10 | [alias] 11 | br = branch 12 | ci = commit 13 | co = checkout 14 | df = diff 15 | g = grep -I 16 | lg = log -p 17 | pp = !"echo 'Pull'; git pull; echo 'Push'; git push" 18 | rb = rbranch 19 | rv = review 20 | st = status 21 | ksdiff = difftool -y -t Kaleidoscope 22 | [branch "master"] 23 | remote = origin 24 | merge = refs/heads/master 25 | [color] 26 | ui = auto 27 | [color "branch"] 28 | current = yellow reverse 29 | local = yellow 30 | remote = green 31 | [color "diff"] 32 | meta = yellow bold 33 | frag = magenta bold 34 | old = red bold 35 | new = green bold 36 | [color "status"] 37 | added = yellow 38 | changed = green 39 | untracked = cyan 40 | [push] 41 | default = simple 42 | [merge] 43 | log = true 44 | [difftool "Kaleidoscope"] 45 | cmd = ksdiff-wrapper git \"$LOCAL\" \"$REMOTE\" 46 | [rerere] 47 | enabled = 1 48 | [url "git@github.com:"] 49 | insteadOf = "gh:" 50 | pushInsteadOf = "github:" 51 | pushInsteadOf = "git://github.com/" 52 | [url "git://github.com/"] 53 | insteadOf = "github:" 54 | [url "git@gist.github.com:"] 55 | insteadOf = "gst:" 56 | pushInsteadOf = "gist:" 57 | pushInsteadOf = "git://gist.github.com/" 58 | [url "git://gist.github.com/"] 59 | insteadOf = "gist:" 60 | [url "git@heroku.com:"] 61 | insteadOf = "heroku:" 62 | -------------------------------------------------------------------------------- /source/50_misc.sh: -------------------------------------------------------------------------------- 1 | # Case-insensitive globbing (used in pathname expansion) 2 | shopt -s nocaseglob 3 | 4 | # Check the window size after each command and, if necessary, 5 | # update the values of LINES and COLUMNS. 6 | shopt -s checkwinsize 7 | 8 | alias grep='grep --color=auto' 9 | 10 | # Prevent less from clearing the screen while still showing colors. 11 | export LESS=-XR 12 | 13 | # Set the terminal's title bar. 14 | function titlebar() { 15 | echo -n $'\e]0;'"$*"$'\a' 16 | } 17 | 18 | # SSH auto-completion based on entries in known_hosts. 19 | if [[ -e ~/.ssh/known_hosts ]]; then 20 | complete -o default -W "$(cat ~/.ssh/known_hosts | sed 's/[, ].*//' | sort | uniq | grep -v '[0-9]')" ssh scp sftp 21 | fi 22 | 23 | # Disable ansible cows }:] 24 | export ANSIBLE_NOCOWS=1 25 | 26 | # "fuck" 27 | if [[ "$(which thefuck)" ]]; then 28 | eval $(thefuck --alias) 29 | fi 30 | 31 | # Run a command repeatedly in a loop, with a delay (defaults to 1 sec). 32 | # Usage: 33 | # loop [delay] single_command [args] 34 | # loopc [delay] 'command1 [args]; command2 [args]; ...' 35 | # Note, these do the same thing: 36 | # loop 5 bash -c 'echo foo; echo bar; 37 | # loopc 5 'echo foo; echo bar' 38 | function loopc() { loop "$@"; } 39 | function loop() { 40 | local caller=$(caller 0 | awk '{print $2}') 41 | local delay=1 42 | if [[ $1 =~ ^[0-9]*(\.[0-9]+)?$ ]]; then 43 | delay=$1 44 | shift 45 | fi 46 | while true; do 47 | if [[ "$caller" == "loopc" ]]; then 48 | bash -c "$@" 49 | else 50 | "$@" 51 | fi 52 | sleep $delay 53 | done 54 | } 55 | -------------------------------------------------------------------------------- /bin/curlsubl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ ! "$1" || "$1" == "-h" || "$1" == "--help" ]]; then cat </dev/null 59 | fi 60 | if [[ "$(dscl . -read ~ UserShell | awk '{print $2}')" != "$binroot/bash" ]]; then 61 | e_header "Making $binroot/bash your default shell" 62 | sudo chsh -s "$binroot/bash" "$USER" >/dev/null 2>&1 63 | e_arrow "Please exit and restart all your shells." 64 | fi 65 | -------------------------------------------------------------------------------- /source/50_file.sh: -------------------------------------------------------------------------------- 1 | # Files will be created with these permissions: 2 | # files 644 -rw-r--r-- (666 minus 022) 3 | # dirs 755 drwxr-xr-x (777 minus 022) 4 | umask 022 5 | 6 | # Always use color output for `ls` 7 | if is_osx; then 8 | alias ls="command ls -G" 9 | else 10 | alias ls="command ls --color" 11 | 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:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=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:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.ogg=01;35:*.mp3=01;35:*.wav=01;35:' 12 | fi 13 | 14 | # Directory listing 15 | if [[ "$(type -P tree)" ]]; then 16 | alias ll='tree --dirsfirst -aLpughDFiC 1' 17 | alias lsd='ll -d' 18 | else 19 | alias ll='ls -al' 20 | alias lsd='CLICOLOR_FORCE=1 ll | grep --color=never "^d"' 21 | fi 22 | 23 | # Easier navigation: .., ..., - 24 | alias ..='cd ..' 25 | alias ...='cd ../..' 26 | alias -- -='cd -' 27 | 28 | # File size 29 | alias fs="stat -f '%z bytes'" 30 | alias df="df -h" 31 | 32 | # Recursively delete `.DS_Store` files 33 | alias dsstore="find . -name '*.DS_Store' -type f -ls -delete" 34 | 35 | # Aliasing eachdir like this allows you to use aliases/functions as commands. 36 | alias eachdir=". eachdir" 37 | 38 | # Create a new directory and enter it 39 | function md() { 40 | mkdir -p "$@" && cd "$@" 41 | } 42 | 43 | # Fast directory switching 44 | mkdir -p $DOTFILES/caches/z 45 | _Z_NO_PROMPT_COMMAND=1 46 | _Z_DATA=$DOTFILES/caches/z/z 47 | . $DOTFILES/vendor/z/z.sh 48 | -------------------------------------------------------------------------------- /bin/serve: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys, os 3 | import SimpleHTTPServer 4 | args = sys.argv[1:] 5 | 6 | if len(args) and (args[0] == "-h" or args[0] == "--help"): 7 | print """ 8 | Serve a file (or the current directory) 9 | http://benalman.com/ 10 | 11 | Usage: %s [PORT] [FILE] 12 | 13 | If a port isn't specified, use 8080. If a file isn't specified, serve the 14 | current directory. Once started, open the specified file (or the current 15 | directory) with the default web browser. 16 | 17 | Copyright (c) 2012 "Cowboy" Ben Alman 18 | Licensed under the MIT license. 19 | http://benalman.com/about/license/""" % os.path.basename(sys.argv[0]) 20 | sys.exit() 21 | 22 | # Get port, if specified. 23 | port = 8080 24 | if len(args) and args[0].isdigit(): 25 | port = int(args[0]) 26 | args = args[1:] # Shift args. 27 | 28 | # Get file, if specified. 29 | file = args[0] if len(args) else "" 30 | 31 | # If not in an SSH session, open the URL in the default handler. 32 | if not "SSH_TTY" in os.environ: 33 | os.system("open 'http://localhost:%d/%s'" % (port, file)) 34 | 35 | # Redefining the default content-type to text/plain instead of the default 36 | # application/octet-stream allows "unknown" files to be viewable in-browser 37 | # as text instead of being downloaded, which makes me happy. 38 | extensions_map = SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map 39 | # Set the default content type to text/plain. 40 | extensions_map[""] = "text/plain" 41 | # Serving everything as UTF-8 by default makes funky characters render 42 | # correctly and shouldn't break anything (per Mathias Bynens). 43 | for key, value in extensions_map.items(): 44 | extensions_map[key] = value + "; charset=UTF-8" 45 | 46 | # Start the server using the default .test method, because I'm lazy (the port 47 | # is still grabbed from sys.argv[1]). 48 | sys.argv = [sys.argv[0], port] 49 | SimpleHTTPServer.test() 50 | -------------------------------------------------------------------------------- /source/10_tmux.sh: -------------------------------------------------------------------------------- 1 | # Start new tmux session or reattach to an existing session, but only if not 2 | # already inside a tmux session. 3 | function tm() { 4 | local is_source=; [[ "$1" == "SOURCE" ]] && is_source=1 && shift 5 | local tmux_no_logout=~/.dotfiles/caches/tmux-no-logout 6 | if [[ ! "$TMUX" ]]; then 7 | # Clean up any orphaned "no logout" file. 8 | [[ -e $tmux_no_logout ]] && rm $tmux_no_logout 9 | # Actually start tmux. 10 | tmux ls >/dev/null 2>&1 && tmux attach "$@" || tmux "$@" 11 | # If "no logout" doesn't exist, exit. 12 | [[ -e $tmux_no_logout ]] && rm $tmux_no_logout || exit 13 | elif [[ ! "$is_source" ]]; then 14 | echo "Already in a tmux session!" 15 | fi 16 | } 17 | 18 | # Start tmux now (at login), but only if in a login shell and not already 19 | # started (and possibly detached) in this shell. 20 | # if shopt -q login_shell && [[ ! "$TMUX_AUTO_STARTED" ]]; then 21 | # TMUX_AUTO_STARTED=1 22 | # tm SOURCE 23 | # fi 24 | 25 | # Run an arbitrary command in the current tmux window (if only one pane) 26 | # otherwise create a new window and run the command there. 27 | function run_in_fresh_tmux_window() { 28 | local panes="$(tmux list-panes | wc -l)" 29 | if [[ "$panes" != 1 ]]; then 30 | tmux new-window "bash --rcfile <(echo '. ~/.bashrc; $*')" 31 | else 32 | "$@" 33 | fi 34 | } 35 | 36 | # Open editor and shell in new window using main-vertical layout. 37 | # Usage: qq [num-panes] [working-directory] [...other-args] 38 | function qq() { 39 | local panes=1; [[ "$1" =~ ^[0-9]+$ ]] && panes=$1 && shift 40 | local dir="$PWD"; [[ -d "$1" ]] && dir="$(cd "$1" && pwd)" && shift 41 | local win=$(tmux new-window -P -a -c "$dir" -n "$(basename "$dir")") 42 | n_times $panes tmux split-window -t $win -c "$dir" 43 | tmux select-layout -t $win main-vertical 44 | tmux select-pane -t $win 45 | tmux send-keys -t $win "$EDITOR $@" Enter 46 | } 47 | alias q2='qq 2' 48 | alias q3='qq 3' 49 | -------------------------------------------------------------------------------- /conf/tic/tmux-256color.terminfo: -------------------------------------------------------------------------------- 1 | # Reconstructed via infocmp from file: /usr/share/misc/terminfo 2 | tmux-256color|tmux with 256 colors, 3 | OTbs, OTpt, am, ccc@, hs, km, mir, msgr, xenl, AX, G0, 4 | colors#256, cols#80, it#8, lines#24, ncv@, pairs#32767, U8#1, 5 | acsc=++\,\,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~, 6 | bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, civis=\E[?25l, 7 | clear=\E[H\E[J, cnorm=\E[34h\E[?25h, cr=^M, 8 | csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H, 9 | cud=\E[%p1%dB, cud1=^J, cuf=\E[%p1%dC, cuf1=\E[C, 10 | cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\EM, 11 | cvvis=\E[34l, dch=\E[%p1%dP, dch1=\E[P, dim=\E[2m, 12 | dl=\E[%p1%dM, dl1=\E[M, dsl=\E]0;\007, ed=\E[J, el=\E[K, 13 | el1=\E[1K, enacs=\E(B\E)0, flash=\Eg, fsl=^G, home=\E[H, 14 | ht=^I, hts=\EH, ich=\E[%p1%d@, il=\E[%p1%dL, il1=\E[L, 15 | ind=^J, initc@, is2=\E)0, kbs=\177, kcbt=\E[Z, kcub1=\EOD, 16 | kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA, kdch1=\E[3~, 17 | kend=\E[4~, kf1=\EOP, kf10=\E[21~, kf11=\E[23~, 18 | kf12=\E[24~, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\E[15~, 19 | kf6=\E[17~, kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, 20 | khome=\E[1~, kich1=\E[2~, kmous=\E[M, knp=\E[6~, kpp=\E[5~, 21 | nel=\EE, op=\E[39;49m, rc=\E8, rev=\E[7m, ri=\EM, 22 | ritm=\E[23m, rmacs=^O, rmcup=\E[?1049l, rmir=\E[4l, 23 | rmkx=\E[?1l\E>, rmso=\E[27m, rmul=\E[24m, 24 | rs2=\Ec\E[?1000l\E[?25h, sc=\E7, 25 | setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m, 26 | setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m, 27 | setb@, setf@, 28 | sgr=\E[0%?%p6%t;1%;%?%p1%t;3%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;m%?%p9%t\016%e\017%;, 29 | sgr0=\E[m\017, sitm=\E[3m, smacs=^N, smcup=\E[?1049h, 30 | smir=\E[4h, smkx=\E[?1h\E=, smso=\E[7m, smul=\E[4m, 31 | tbc=\E[3g, tsl=\E]0;, Cr=\E]112\007, Cs=\E]12;%p1%s\007, 32 | E0=\E(B, Ms@, S0=\E(%p1%c, Se=\E[2 q, Ss=\E[%p1%d q, 33 | TS=\E]0;, 34 | -------------------------------------------------------------------------------- /bin/multi_firefox: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat < "$bin_path/$bin" <<'BASH' 50 | #!/bin/bash 51 | bin="$(echo $0 | perl -pe's/-bin$//;s/$/.bin/')" 52 | profile="$(echo $0 | perl -ne'm#/(Firefox[^/]*)\.app/# && print $1')" 53 | "$bin" -P "$profile" 54 | BASH 55 | chmod +x "$bin_path/$bin" 56 | done 57 | 58 | echo -e "\nAll done!" 59 | -------------------------------------------------------------------------------- /source/10_powerline.sh: -------------------------------------------------------------------------------- 1 | [[ ! "$(which powerline-daemon)" ]] && return 1 2 | 3 | # Homebrew installs python2 as "python2" 4 | for python_cmd in python2 python FAIL; do [[ "$(which $python_cmd)" ]] && break; done 5 | 6 | # Powerline stuff. 7 | export POWERLINE_PREFIX="$($python_cmd -c "import powerline; print powerline.__path__[0]")" 8 | 9 | powerline-daemon -q 10 | export POWERLINE_BASH_CONTINUATION=1 11 | export POWERLINE_BASH_SELECT=1 12 | 13 | unset PROMPT_COMMAND 14 | . $POWERLINE_PREFIX/bindings/bash/powerline.sh 15 | 16 | # Ensure exit code is reset when pressing "enter" with no command 17 | # because I'm OCD. 18 | __prompt_stack=() 19 | trap '__prompt_stack=("${__prompt_stack[@]}" "$BASH_COMMAND")' DEBUG 20 | 21 | function __prompt_exit_code() { 22 | local exit_code=$? 23 | # If the first command in the stack is __prompt_command, no command was run. 24 | # Set exit_code to 0. 25 | [[ "${__prompt_stack[0]}" == "__prompt_exit_code" ]] && exit_code=0 26 | # Return the (correct) exit code. 27 | return $exit_code 28 | } 29 | 30 | function __prompt_cleanup() { 31 | # Reset the stack. 32 | __prompt_stack=() 33 | } 34 | 35 | PROMPT_COMMAND=$'__prompt_exit_code\n'"$PROMPT_COMMAND"$'\n__prompt_cleanup' 36 | 37 | # Conditionally change the powerline config. 38 | __powerline_command_args=() 39 | __powerline_command_theme=' -t default.' 40 | 41 | # Run at any time to remove extra powerline segments from the prompt. 42 | function prompt_simple() { 43 | __temp=(date_seg hostname battery uptime system_load external_ip internal_ip) 44 | function __temp() { echo "segment_data.$1.display=false"; } 45 | __powerline_command_args=($(array_map __temp __temp)) 46 | __set_powerline_command_args 47 | } 48 | 49 | function __set_powerline_command_args() { 50 | POWERLINE_COMMAND_ARGS= 51 | if [[ "${#__powerline_command_args[@]}" != 0 ]]; then 52 | POWERLINE_COMMAND_ARGS="$__powerline_command_theme$(array_join __powerline_command_args "$__powerline_command_theme")" 53 | fi 54 | } 55 | 56 | # If not in a login shell (eg. "sudo bash") or inside a tmux pane, simplify 57 | # the prompt automatically. 58 | if ! shopt -q login_shell || [[ "$TMUX" ]]; then 59 | prompt_simple 60 | else 61 | __set_powerline_command_args 62 | fi 63 | -------------------------------------------------------------------------------- /bin/osx_create_installer: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ ! "$1" || "$1" == "-h" || "$1" == "--help" ]]; then cat < GUID Partition Table 12 | * Mac OS Extended (Journaled) 13 | * Name: Foobar 14 | 15 | Then run this script like: sudo $(basename "$0") InstallESD.dmg /Volumes/Foobar 16 | 17 | Copyright (c) 2012 "Cowboy" Ben Alman 18 | Licensed under the MIT license. 19 | http://benalman.com/about/license/ 20 | HELP 21 | [[ "$1" ]]; exit; fi 22 | 23 | dmg_path="$1" 24 | usb_path="${2%/}" 25 | 26 | [[ $UID != 0 ]] && echo "Error: please run with sudo" && exit 1 27 | [[ ! -e "$dmg_path" ]] && echo "Error: source \"$dmg_path\" not found" && exit 2 28 | [[ ! -e "$usb_path" ]] && echo "Error: target \"$usb_path\" not found" && exit 3 29 | 30 | usb_device="$(df | grep -w "$usb_path" | awk '{print $1}')" 31 | 32 | # Mount image (invisibly) 33 | dmg_mount="$(hdiutil attach "$dmg_path" -nobrowse | perl -ne 'm#(/Volumes/.*)# && print $1')" 34 | 35 | # Restore image 36 | asr -restore -source "$dmg_path" -target $usb_device -erase -format HFS+ 37 | 38 | # Unmount image 39 | hdiutil detach "$dmg_mount" 40 | 41 | # Mount usb stick (invisibly) 42 | hdiutil attach $usb_device -nobrowse 43 | 44 | usb_name="$(diskutil info $usb_device | perl -ne 'm#Volume Name:\s+(.*)# && print $1')" 45 | usb_mount="$(diskutil info $usb_device | perl -ne 'm#Mount Point:\s+(.*)# && print $1')" 46 | final_name="$(basename "$usb_mount/Install "*.app .app)" 47 | 48 | # Add a drive icon (note: 1024x1024 icons don't appear in the boot screen on older macs) 49 | srcicon=("$usb_mount"/*.app/Contents/Resources/InstallAssistant.icns) 50 | volicon="$usb_mount/.VolumeIcon.icns" 51 | cp "$srcicon" "$volicon" 52 | 53 | # Set some properties to ensure the icon works 54 | SetFile -c icnC "$volicon" 55 | SetFile -a C "$usb_mount" 56 | 57 | # Give it the proper boot screen name and keep the folder from auto-opening 58 | bless --folder "$usb_mount" -label "$final_name" 59 | 60 | # Rename drive 61 | diskutil rename "$usb_name" "$final_name" 62 | 63 | # Re-mount usb stick so that it's visible 64 | diskutil unmount $usb_device 65 | hdiutil attach $usb_device 66 | -------------------------------------------------------------------------------- /bin/osx_hide_partition: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ ! "$1" || "$1" == "-h" || "$1" == "--help" ]]; then cat </dev/null 30 | assert 0 echo "${#setdiff_out[@]}" 31 | 32 | unset setdiff_new setdiff_cur setdiff_out 33 | setdiff_new=(a b c); setdiff_cur=(); setdiff 34 | assert 3 echo "${#setdiff_out[@]}" 35 | assert "a" echo "${setdiff_out[0]}" 36 | assert "b" echo "${setdiff_out[1]}" 37 | assert "c" echo "${setdiff_out[2]}" 38 | 39 | unset setdiff_new setdiff_cur setdiff_out 40 | setdiff_new=(a b c); setdiff_cur=(a); setdiff 41 | assert 2 echo "${#setdiff_out[@]}" 42 | assert "b" echo "${setdiff_out[0]}" 43 | assert "c" echo "${setdiff_out[1]}" 44 | 45 | unset setdiff_new setdiff_cur setdiff_out 46 | setdiff_new=(a b c); setdiff_cur=(c a); setdiff 47 | assert 1 echo "${#setdiff_out[@]}" 48 | assert "b" echo "${setdiff_out[0]}" 49 | 50 | unset setdiff_new setdiff_cur setdiff_out 51 | setdiff_new=("a b" c); setdiff_cur=(a b c); setdiff 52 | assert 1 echo "${#setdiff_out[@]}" 53 | assert "a b" echo "${setdiff_out[0]}" 54 | 55 | unset setdiff_new setdiff_cur setdiff_out 56 | setdiff_new=(a b "a b" c "c d"); setdiff_cur=(a c); setdiff 57 | assert 3 echo "${#setdiff_out[@]}" 58 | assert "b" echo "${setdiff_out[0]}" 59 | assert "a b" echo "${setdiff_out[1]}" 60 | assert "c d" echo "${setdiff_out[2]}" 61 | 62 | unset setdiff_new setdiff_cur setdiff_out 63 | setdiff_new=(a b "a b" c "c d"); setdiff_cur=(b "c d"); setdiff 64 | assert 3 echo "${#setdiff_out[@]}" 65 | assert "a" echo "${setdiff_out[0]}" 66 | assert "a b" echo "${setdiff_out[1]}" 67 | assert "c" echo "${setdiff_out[2]}" 68 | -------------------------------------------------------------------------------- /init/30_osx_homebrew_casks.sh: -------------------------------------------------------------------------------- 1 | # OSX-only stuff. Abort if not OSX. 2 | is_osx || return 1 3 | 4 | # Exit if Homebrew is not installed. 5 | [[ ! "$(type -P brew)" ]] && e_error "Brew casks need Homebrew to install." && return 1 6 | 7 | # Ensure the cask kegs are installed. 8 | kegs=( 9 | homebrew/cask-drivers 10 | homebrew/cask-fonts 11 | homebrew/cask-versions 12 | ) 13 | brew_tap_kegs 14 | 15 | # Hack to show the first-run brew-cask password prompt immediately. 16 | brew cask info this-is-somewhat-annoying 2>/dev/null 17 | 18 | # Homebrew casks 19 | casks=( 20 | # Applications 21 | a-better-finder-rename 22 | alfred 23 | android-platform-tools 24 | bartender 25 | battle-net 26 | bettertouchtool 27 | betterzip 28 | caprine 29 | charles 30 | chromium 31 | chronosync 32 | controllermate 33 | datagrip 34 | docker 35 | dropbox 36 | fastscripts 37 | firefox 38 | gimp 39 | gyazo 40 | hex-fiend 41 | iterm2 42 | karabiner-elements 43 | licecap 44 | macvim 45 | microsoft-remote-desktop-beta 46 | midi-monitor 47 | moom 48 | ngrok 49 | numi 50 | omnidisksweeper 51 | postman 52 | reaper 53 | robo-3t 54 | scroll-reverser 55 | skype 56 | slack 57 | sourcetree 58 | spotify 59 | steam 60 | the-unarchiver 61 | tower 62 | vagrant 63 | virtualbox 64 | visual-studio-code 65 | vlc 66 | xscreensaver 67 | zeplin 68 | # Quick Look plugins 69 | qlcolorcode 70 | qlmarkdown 71 | qlprettypatch 72 | qlstephen 73 | quicklook-csv 74 | quicklook-json 75 | quicknfo 76 | suspicious-package 77 | webpquicklook 78 | # Drivers 79 | sonos 80 | xbox360-controller-driver-unofficial 81 | # Fonts 82 | font-m-plus 83 | font-mplus-nerd-font 84 | font-mplus-nerd-font-mono 85 | ) 86 | 87 | # Install Homebrew casks. 88 | casks=($(setdiff "${casks[*]}" "$(brew cask list 2>/dev/null)")) 89 | if (( ${#casks[@]} > 0 )); then 90 | e_header "Installing Homebrew casks: ${casks[*]}" 91 | for cask in "${casks[@]}"; do 92 | brew cask install $cask 93 | done 94 | fi 95 | 96 | # Work around colorPicker symlink issue. 97 | # https://github.com/caskroom/homebrew-cask/issues/7004 98 | cps=() 99 | for f in ~/Library/ColorPickers/*.colorPicker; do 100 | [[ -L "$f" ]] && cps=("${cps[@]}" "$f") 101 | done 102 | 103 | if (( ${#cps[@]} > 0 )); then 104 | e_header "Fixing colorPicker symlinks" 105 | for f in "${cps[@]}"; do 106 | target="$(readlink "$f")" 107 | e_arrow "$(basename "$f")" 108 | rm "$f" 109 | cp -R "$target" ~/Library/ColorPickers/ 110 | done 111 | fi 112 | -------------------------------------------------------------------------------- /bin/eachdir: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function _eachdir() { 4 | 5 | if [[ "$1" == "-h" || "$1" == "--help" ]]; then cat <&1 )" 71 | if [[ "$output" ]]; then 72 | # If the command had output, display a header and that output. 73 | echo -e "${h1}${d}${h2}\n$output\n" 74 | else 75 | # Otherwise push it onto an array for later display. 76 | nops=("${nops[@]}" "$d") 77 | fi 78 | done 79 | 80 | # List any dirs that had no output. 81 | if [[ ${#nops[@]} > 0 ]]; then 82 | echo "${h1}no output from${h2}" 83 | for d in "${nops[@]}"; do echo "$d"; done 84 | fi 85 | 86 | } 87 | 88 | # By putting the above code inside a function, if this file is sourced (which 89 | # is required for external aliases/functions to be used as commands), vars 90 | # can be local and return can be used to exit. 91 | _eachdir "$@" 92 | -------------------------------------------------------------------------------- /link/.vim/plugin/bclose.vim: -------------------------------------------------------------------------------- 1 | " Modified to use :BD or :BD! as the command, and to prevent 'Press ENTER' 2 | " prompt when run the first time (sometimes) - Cowboy 3 | 4 | " Delete buffer while keeping window layout (don't close buffer's windows). 5 | " Version 2008-11-18 from http://vim.wikia.com/wiki/VimTip165 6 | if v:version < 700 || exists('loaded_bclose') || &cp 7 | finish 8 | endif 9 | let loaded_bclose = 1 10 | if !exists('bclose_multiple') 11 | let bclose_multiple = 1 12 | endif 13 | 14 | " Display an error message. 15 | function! s:Warn(msg) 16 | echohl ErrorMsg 17 | echomsg a:msg 18 | echohl NONE 19 | endfunction 20 | 21 | " Command ':Bclose' executes ':bd' to delete buffer in current window. 22 | " The window will show the alternate buffer (Ctrl-^) if it exists, 23 | " or the previous buffer (:bp), or a blank buffer if no previous. 24 | " Command ':Bclose!' is the same, but executes ':bd!' (discard changes). 25 | " An optional argument can specify which buffer to close (name or number). 26 | function! s:Bclose(bang, buffer) 27 | if empty(a:buffer) 28 | let btarget = bufnr('%') 29 | elseif a:buffer =~ '^\d\+$' 30 | let btarget = bufnr(str2nr(a:buffer)) 31 | else 32 | let btarget = bufnr(a:buffer) 33 | endif 34 | if btarget < 0 35 | call s:Warn('No matching buffer for '.a:buffer) 36 | return 37 | endif 38 | if empty(a:bang) && getbufvar(btarget, '&modified') 39 | call s:Warn('No write since last change for buffer '.btarget.' (use :BD!)') 40 | return 41 | endif 42 | " Numbers of windows that view target buffer which we will delete. 43 | let wnums = filter(range(1, winnr('$')), 'winbufnr(v:val) == btarget') 44 | if !g:bclose_multiple && len(wnums) > 1 45 | call s:Warn('Buffer is in multiple windows (use ":let bclose_multiple=1")') 46 | return 47 | endif 48 | let wcurrent = winnr() 49 | for w in wnums 50 | execute w.'wincmd w' 51 | let prevbuf = bufnr('#') 52 | if prevbuf > 0 && buflisted(prevbuf) && prevbuf != w 53 | buffer # 54 | else 55 | silent bprevious 56 | endif 57 | if btarget == bufnr('%') 58 | " Numbers of listed buffers which are not the target to be deleted. 59 | let blisted = filter(range(1, bufnr('$')), 'buflisted(v:val) && v:val != btarget') 60 | " Listed, not target, and not displayed. 61 | let bhidden = filter(copy(blisted), 'bufwinnr(v:val) < 0') 62 | " Take the first buffer, if any (could be more intelligent). 63 | let bjump = (bhidden + blisted + [-1])[0] 64 | if bjump > 0 65 | execute 'buffer '.bjump 66 | else 67 | execute 'enew'.a:bang 68 | endif 69 | endif 70 | endfor 71 | execute 'bdelete'.a:bang.' '.btarget 72 | execute wcurrent.'wincmd w' 73 | endfunction 74 | command! -bang -complete=buffer -nargs=? BD call s:Bclose('', '') 75 | " nnoremap bd :Bclose 76 | -------------------------------------------------------------------------------- /conf/osx/NSUserReplacementItems.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | on 7 | 1 8 | replace 9 | ... 10 | with 11 | 12 | 13 | 14 | on 15 | 1 16 | replace 17 | <<_ 18 | with 19 | 20 | 21 | 22 | on 23 | 1 24 | replace 25 | >>_ 26 | with 27 | 28 | 29 | 30 | on 31 | 1 32 | replace 33 | ^^_ 34 | with 35 | 36 | 37 | 38 | on 39 | 1 40 | replace 41 | VV_ 42 | with 43 | 44 | 45 | 46 | on 47 | 1 48 | replace 49 | <>_ 50 | with 51 | 52 | 53 | 54 | on 55 | 1 56 | replace 57 | ^V_ 58 | with 59 | 60 | 61 | 62 | on 63 | 1 64 | replace 65 | <<F 66 | with 67 | 68 | 69 | 70 | on 71 | 1 72 | replace 73 | >>F 74 | with 75 | 76 | 77 | 78 | on 79 | 1 80 | replace 81 | ^^F 82 | with 83 | 84 | 85 | 86 | on 87 | 1 88 | replace 89 | VVF 90 | with 91 | 92 | 93 | 94 | on 95 | 1 96 | replace 97 | <3_ 98 | with 99 | 100 | 101 | 102 | on 103 | 1 104 | replace 105 | <333 106 | with 107 | 💜 108 | 109 | 110 | on 111 | 1 112 | replace 113 | CMD_ 114 | with 115 | ⌘- 116 | 117 | 118 | on 119 | 1 120 | replace 121 | OPT_ 122 | with 123 | ⌥- 124 | 125 | 126 | on 127 | 1 128 | replace 129 | CTRL_ 130 | with 131 | ⌃- 132 | 133 | 134 | on 135 | 1 136 | replace 137 | SHFT_ 138 | with 139 | ⇧- 140 | 141 | 142 | on 143 | 1 144 | replace 145 | frunt 146 | with 147 | grunt 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /test/test_array.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source $DOTFILES/source/00_dotfiles.sh 3 | 4 | e_header "$(basename "$0" .sh)" 5 | 6 | function test_assert() { assert "$actual" "$expected"; } 7 | 8 | # Fixtures 9 | empty=() 10 | fixture1=(a b "" "c d" " e " " 'f' " " \"g'h\" " i "") 11 | 12 | # Tests 13 | e_header array_map 14 | 15 | IFS= read -rd '' actual < <(array_map empty) 16 | expected=$'' 17 | test_assert 18 | 19 | IFS= read -rd '' actual < <(array_map fixture1) 20 | expected=$'a\nb\n\nc d\n e \n \'f\' \n \"g\'h\" \ni\n\n' 21 | test_assert 22 | 23 | function map() { echo "<$2:${1:-X}>"; } 24 | IFS= read -rd '' actual < <(array_map fixture1 map) 25 | expected=$'<0:a>\n<1:b>\n<2:X>\n<3:c d>\n<4: e >\n<5: \'f\' >\n<6: \"g\'h\" >\n<7:i>\n<8:X>\n' 26 | test_assert 27 | 28 | e_header array_print 29 | 30 | IFS= read -rd '' actual < <(array_print empty) 31 | expected=$'' 32 | test_assert 33 | 34 | IFS= read -rd '' actual < <(array_print fixture1) 35 | expected=$'0 \n1 \n2 <>\n3 \n4 < e >\n5 < \'f\' >\n6 < \"g\'h\" >\n7 \n8 <>\n' 36 | test_assert 37 | 38 | 39 | e_header array_filter 40 | 41 | IFS= read -rd '' actual < <(array_filter empty) 42 | expected=$'' 43 | test_assert 44 | 45 | IFS= read -rd '' actual < <(array_filter fixture1) 46 | expected=$'a\nb\nc d\n e \n \'f\' \n \"g\'h\" \ni\n' 47 | test_assert 48 | 49 | function filter() { [[ "$1" && ! "$1" =~ [[:space:]] ]]; } 50 | IFS= read -rd '' actual < <(array_filter fixture1 filter) 51 | expected=$'a\nb\ni\n' 52 | test_assert 53 | 54 | function filter() { [[ "$1" && "$1" =~ [[:space:]] ]]; } 55 | IFS= read -rd '' actual < <(array_filter fixture1 filter) 56 | expected=$'c d\n e \n \'f\' \n \"g\'h\" \n' 57 | test_assert 58 | 59 | function filter() { [[ $(($2 % 2)) == 0 ]]; } 60 | IFS= read -rd '' actual < <(array_filter fixture1 filter) 61 | expected=$'a\n\n e \n \"g\'h\" \n\n' 62 | test_assert 63 | 64 | function filter() { [[ $(($2 % 2)) == 1 ]]; } 65 | IFS= read -rd '' actual < <(array_filter fixture1 filter) 66 | expected=$'b\nc d\n \'f\' \ni\n' 67 | test_assert 68 | 69 | 70 | e_header array_filter_i 71 | 72 | IFS= read -rd '' actual < <(array_filter_i empty) 73 | expected=$'' 74 | test_assert 75 | 76 | IFS= read -rd '' actual < <(array_filter_i fixture1) 77 | expected=$'0\n1\n3\n4\n5\n6\n7\n' 78 | test_assert 79 | 80 | function filter() { [[ "$1" && ! "$1" =~ [[:space:]] ]]; } 81 | IFS= read -rd '' actual < <(array_filter_i fixture1 filter) 82 | expected=$'0\n1\n7\n' 83 | test_assert 84 | 85 | function filter() { [[ "$1" && "$1" =~ [[:space:]] ]]; } 86 | IFS= read -rd '' actual < <(array_filter_i fixture1 filter) 87 | expected=$'3\n4\n5\n6\n' 88 | test_assert 89 | 90 | function filter() { [[ $(($2 % 2)) == 0 ]]; } 91 | IFS= read -rd '' actual < <(array_filter_i fixture1 filter) 92 | expected=$'0\n2\n4\n6\n8\n' 93 | test_assert 94 | 95 | function filter() { [[ $(($2 % 2)) == 1 ]]; } 96 | IFS= read -rd '' actual < <(array_filter_i fixture1 filter) 97 | expected=$'1\n3\n5\n7\n' 98 | test_assert 99 | 100 | 101 | e_header array_join 102 | 103 | IFS= read -rd '' actual < <(array_join empty ',') 104 | expected=$'' 105 | test_assert 106 | 107 | IFS= read -rd '' actual < <(array_join fixture1 ',') 108 | expected=$'a,b,,c d, e , \'f\' , \"g\'h\" ,i,\n' 109 | test_assert 110 | 111 | IFS= read -rd '' actual < <(array_join fixture1 ', ') 112 | expected=$'a, b, , c d, e , \'f\' , \"g\'h\" , i, \n' 113 | test_assert 114 | 115 | 116 | e_header array_join_filter 117 | 118 | IFS= read -rd '' actual < <(array_join_filter empty ',') 119 | expected=$'' 120 | test_assert 121 | 122 | IFS= read -rd '' actual < <(array_join_filter fixture1 ',') 123 | expected=$'a,b,c d, e , \'f\' , \"g\'h\" ,i\n' 124 | test_assert 125 | 126 | IFS= read -rd '' actual < <(array_join_filter fixture1 ', ') 127 | expected=$'a, b, c d, e , \'f\' , \"g\'h\" , i\n' 128 | test_assert 129 | -------------------------------------------------------------------------------- /source/50_osx.sh: -------------------------------------------------------------------------------- 1 | # OSX-only stuff. Abort if not OSX. 2 | is_osx || return 1 3 | 4 | # APPLE, Y U PUT /usr/bin B4 /usr/local/bin?! 5 | PATH="/usr/local/bin:$(path_remove /usr/local/bin)" 6 | export PATH 7 | 8 | # Trim new lines and copy to clipboard 9 | alias c="tr -d '\n' | pbcopy" 10 | 11 | # Make 'less' more. 12 | [[ "$(type -P lesspipe.sh)" ]] && eval "$(lesspipe.sh)" 13 | 14 | # Start ScreenSaver. This will lock the screen if locking is enabled. 15 | alias ss="open /System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app" 16 | 17 | # Iterm 2 shell integration 18 | test -e "${HOME}/.iterm2_shell_integration.bash" && source "${HOME}/.iterm2_shell_integration.bash" 19 | 20 | # Create a new Parallels VM from template, replacing the existing one. 21 | function vm_template() { 22 | local name="$@" 23 | local basename="$(basename "$name" ".zip")" 24 | local dest_dir="$HOME/Documents/Parallels" 25 | local dest="$dest_dir/$basename" 26 | local src_dir="$dest_dir/Templates" 27 | local src="$src_dir/$name" 28 | if [[ ! "$name" || ! -e "$src" ]]; then 29 | echo "You must specify a valid VM template from this list:"; 30 | shopt -s nullglob 31 | for f in "$src_dir"/*.pvm "$src_dir"/*.pvm.zip; do 32 | echo " * $(basename "$f")" 33 | done 34 | shopt -u nullglob 35 | return 1 36 | fi 37 | if [[ -e "$dest" ]]; then 38 | echo "Deleting old VM" 39 | rm -rf "$dest" 40 | fi 41 | echo "Restoring VM template" 42 | if [[ "$name" == "$basename" ]]; then 43 | cp -R "$src" "$dest" 44 | else 45 | unzip -q "$src" -d "$dest_dir" && rm -rf "$dest_dir/__MACOSX" 46 | fi && \ 47 | echo "Starting VM" && \ 48 | open -g "$dest" 49 | } 50 | 51 | # Bus Pirate as FTDI Cable 52 | # https://blog.zencoffee.org/2011/07/bus-pirate-as-ftdi-cable/ 53 | # http://dangerousprototypes.com/blog/2009/08/12/bus-pirate-connecting-with-mac-osx/ 54 | buspirate_device=usbserial-A105BQH0 55 | buspirate_baud=115200 56 | 57 | function buspirate_init() { 58 | cat < "$backup" && 96 | echo "File ~${backup#$HOME} written." 97 | } 98 | 99 | # Import Localization.prefPane text substitution rules. 100 | function txt_sub_restore() { 101 | local prefs=~/Library/Preferences/.GlobalPreferences.plist 102 | local backup=$DOTFILES/conf/osx/NSUserReplacementItems.plist 103 | if [[ ! -e "$backup" ]]; then 104 | echo "Error: file ~${backup#$HOME} does not exist!" 105 | return 1 106 | fi 107 | cmds=( 108 | "Delete NSUserReplacementItems" 109 | "Add NSUserReplacementItems array" 110 | "Merge '$backup' NSUserReplacementItems" 111 | ) 112 | for cmd in "${cmds[@]}"; do /usr/libexec/PlistBuddy -c "$cmd" "$prefs"; done 113 | } 114 | -------------------------------------------------------------------------------- /config/powerline/themes/powerline_terminus.json: -------------------------------------------------------------------------------- 1 | { 2 | "dividers": { 3 | "left": { 4 | "hard": " ", 5 | "soft": " " 6 | }, 7 | "right": { 8 | "hard": " ", 9 | "soft": " " 10 | } 11 | }, 12 | "spaces": 1, 13 | "segment_data": { 14 | "branch": { 15 | "before": " " 16 | }, 17 | "stash": { 18 | "before": "⌆ " 19 | }, 20 | "cwd": { 21 | "args": { 22 | "ellipsis": "⋯ " 23 | } 24 | }, 25 | 26 | "line_current_symbol": { 27 | "contents": " " 28 | }, 29 | "player": { 30 | "args": { 31 | "state_symbols": { 32 | "fallback": "♫ ", 33 | "play": "▶ ", 34 | "pause": "▮▮", 35 | "stop": "■ " 36 | } 37 | } 38 | }, 39 | 40 | "time": { 41 | "before": "⌚ " 42 | }, 43 | "external_ip": { 44 | "args": { 45 | "query_url": "http://ipecho.net/plain" 46 | } 47 | }, 48 | 49 | "powerline.segments.common.net.network_load": { 50 | "args": { 51 | "recv_format": "⬇ {value:>8}", 52 | "sent_format": "⬆ {value:>8}" 53 | } 54 | }, 55 | "powerline.segments.common.net.hostname": { 56 | "args": { 57 | "only_if_ssh": false 58 | }, 59 | "before": " " 60 | }, 61 | "powerline.segments.common.bat.battery": { 62 | "args": { 63 | "full_heart": "♥", 64 | "empty_heart": "♥", 65 | "online": "⚡︎", 66 | "offline": "🔋" 67 | } 68 | }, 69 | "powerline.segments.common.sys.uptime": { 70 | "before": "⇑ " 71 | }, 72 | "powerline.segments.common.mail.email_imap_alert": { 73 | "before": "✉ " 74 | }, 75 | "powerline.segments.common.env.virtualenv": { 76 | "before": "ⓔ " 77 | }, 78 | "powerline.segments.common.wthr.weather": { 79 | "args": { 80 | "icons": { 81 | "day": "〇", 82 | "blustery": "⚑ ", 83 | "rainy": "☔ ", 84 | "cloudy": "☁ ", 85 | "snowy": "❅ ", 86 | "stormy": "☈ ", 87 | "foggy": "≡ ", 88 | "sunny": "☼ ", 89 | "night": "☾ ", 90 | "windy": "☴ ", 91 | "not_available": "� ", 92 | "unknown": "⚠ " 93 | } 94 | } 95 | }, 96 | "powerline.segments.common.time.fuzzy_time": { 97 | "args": { 98 | "unicode_text": true 99 | } 100 | }, 101 | 102 | "powerline.segments.vim.mode": { 103 | "args": { 104 | "override": { 105 | "n": "NORMAL", 106 | "no": "N·OPER", 107 | "v": "VISUAL", 108 | "V": "V·LINE", 109 | "^V": "V·BLCK", 110 | "s": "SELECT", 111 | "S": "S·LINE", 112 | "^S": "S·BLCK", 113 | "i": "INSERT", 114 | "R": "RPLACE", 115 | "Rv": "V·RPLC", 116 | "c": "COMMND", 117 | "cv": "VIM·EX", 118 | "ce": "NRM·EX", 119 | "r": "PROMPT", 120 | "rm": "-MORE-", 121 | "r?": "CNFIRM", 122 | "!": "!SHELL" 123 | } 124 | } 125 | }, 126 | "powerline.segments.vim.visual_range": { 127 | "args": { 128 | "CTRL_V_text": "↕{rows} ↔{vcols}", 129 | "v_text_oneline": "↔{vcols}", 130 | "v_text_multiline": "↕{rows}", 131 | "V_text": "⇕{rows}" 132 | } 133 | }, 134 | "powerline.segments.vim.readonly_indicator": { 135 | "args": { 136 | "text": "" 137 | } 138 | }, 139 | "powerline.segments.vim.modified_indicator": { 140 | "args": { 141 | "text": "+" 142 | } 143 | }, 144 | 145 | "powerline.segments.i3wm.scratchpad": { 146 | "args": { 147 | "icons": { 148 | "fresh": "●", 149 | "changed": "○" 150 | } 151 | } 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /bin/scan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | if ARGV.include? '-h' or ARGV.include? '--help' then puts <<-HELP 4 | Port-scan one machine or everything on your subnet(s). 5 | http://benalman.com/ 6 | 7 | Usage: #{File.basename $0} [--full] [host_or_ip_or_wildcard ...] 8 | 9 | Scans your subnet(s) using nmap, displaying results in a pretty format. If * 10 | appears at the end of the line, that IP is currently bound to this machine. 11 | 12 | Specify --full for a full subnet port scan (this can take a while), or specify 13 | one or more hosts, IPs or wildcards on which to perform a full port scan. The 14 | --full option is implicit when any hosts, IPs or wildcards are specified. 15 | 16 | Maybe it'll help you find that server you lost. It didn't help me--but that's 17 | only because the machine I was looking for wasn't connected. Whoops. 18 | 19 | Copyright (c) 2012 "Cowboy" Ben Alman 20 | Licensed under the MIT license. 21 | http://benalman.com/about/license/ 22 | HELP 23 | exit; end 24 | 25 | # my "test suite" 26 | %s{ 27 | scans=("" "x" "192.168.0.69" "192.168.0.232" "192.168.0.1" "192.168.0.1 192.168.0.107" "--full"); \ 28 | for s in "${scans[@]}"; do echo -e "===\nargs: $s\n---"; scan $s; echo -e "---\nexit code: $?"; done 29 | } 30 | 31 | ips = [] 32 | subnets = [] 33 | 34 | # Get IPs and subnets we care about from ifconfig. Basically, from any network 35 | # device starting with the letter "e" (en0, en1, eth0, eth1, etc). 36 | ether = nil 37 | %x{ifconfig}.each_line do |line| 38 | if line =~ /^(\S)/ 39 | # If the line starts with a letter, set a flag if that letter is "e". 40 | ether = $1 == 'e' 41 | elsif ether && line =~ /inet (?:addr:)?((\d+\.\d+\.\d+)\.\d+)/ 42 | # Save IP address (1.2.3.4) and subnet (1.2.3.*) for later. 43 | ips << $1 44 | subnets << "#{$2}.*" 45 | end 46 | end 47 | 48 | # Parse things to scan from the passed arguments. 49 | args = ARGV.reject{|a| a =~ /^-/}.join ' ' 50 | # Full scan? 51 | full = ARGV.include?('--full') || !args.empty? 52 | # Get a space-delimited list of unique subnets to be scanned, but only if 53 | # things to scan weren't already passed as arguments. 54 | things_to_scan = !args.empty? ? args : subnets.uniq.join(' ') 55 | 56 | # Since nmap only supports saving greppable output to a file and not STDOUT, 57 | # create a tempfile. 58 | require 'tempfile' 59 | tmp = Tempfile.new 'scan' 60 | 61 | if full 62 | puts "Scanning #{things_to_scan} (full scan, be patient)" 63 | args = "-sT #{things_to_scan}" # The works (full port scan). 64 | # Skip ping if there no wildcards were passed. 65 | args = "-PN #{args}" unless things_to_scan.include? '*' 66 | else 67 | puts "Scanning #{things_to_scan}" 68 | args = "-sP #{things_to_scan}" # Relatively quick scan. 69 | end 70 | 71 | # Actually perform scan. 72 | %x{nmap -oG "#{tmp.path}" -T4 #{args} >/dev/null 2>&1} 73 | puts 74 | 75 | # Parse scan results. 76 | skip = '' 77 | exit_code = 0 78 | tmp.read.each_line do |line| 79 | if line =~ /^Host: (\S+) \((\S*)\).*Status: Up$/ 80 | # Found an IP. 81 | ip = $1 82 | hostname = $2.empty? ? '???' : $2 83 | # If the found IP is bound to a local adapter we care about, show a *. 84 | isbound = ips.include?(ip) ? ' *' : '' 85 | # Output the IP / hostname. 86 | puts "#{skip}#{ip}#{' ' * (16 - ip.length)}#{hostname}#{isbound}" 87 | elsif line =~ /Ports: (.*?)\t/ 88 | # This only appears in the tempfile if a full port scan was done. 89 | # Output the port details. 90 | $1.split(', ').each do |part| 91 | parts = part.split '/' 92 | printf ' :%-5d %s %s', parts[0], parts[2], parts[4] 93 | print " (#{parts[6]})" if parts[6] 94 | puts 95 | end 96 | # The next time an IP is displayed, skip a line. 97 | skip = "\n" 98 | elsif line =~ /# Nmap done.* (\d+ IP address.*)/ 99 | exit_code = 1 if $1.start_with? '0 IP addresses' 100 | puts unless $1.include? '(0 hosts up)' 101 | puts $1 102 | end 103 | end 104 | 105 | # Cleanup. 106 | tmp.close 107 | tmp.unlink 108 | 109 | # Quit. 110 | exit exit_code 111 | -------------------------------------------------------------------------------- /source/50_aws.sh: -------------------------------------------------------------------------------- 1 | 2 | # Get currently logged in aws account name 3 | function aws-account() { 4 | aws iam list-account-aliases | jq ".AccountAliases[0]" -r 5 | } 6 | 7 | # List all clusters for the current role 8 | function aws-list-clusters() { 9 | aws ecs list-clusters | jq -r '.clusterArns|map((./"/")[1])|.[]' 10 | } 11 | 12 | # List all services for the specified cluster 13 | function aws-list-services() { 14 | aws ecs list-services --cluster $1 | jq -r '.serviceArns|map((./"/")[1])|.[]' 15 | } 16 | 17 | # List all services by cluster for the current role 18 | function aws-list-services-by-cluster() { 19 | local clusters services 20 | clusters=($(aws-list-clusters)) 21 | for c in "${clusters[@]}"; do 22 | services=($(aws-list-services $c)) 23 | for s in "${services[@]}"; do 24 | echo "$c $s" 25 | done 26 | [[ ${#services[@]} > 0 ]] && echo 27 | done 28 | } 29 | 30 | # List all aws tasks for the given cluster and service 31 | function aws-list-tasks() { 32 | aws ecs list-tasks --cluster $1 --service-name $2 \ 33 | | jq -r '.taskArns|map((./"/")[1])|.[]' 34 | } 35 | 36 | # List task definitions for all running tasks for the given cluster and service 37 | function aws-list-task-definitions() { 38 | local t=$(aws ecs describe-tasks --cluster $1 --tasks $(aws-list-tasks $1 $2)) 39 | echo $t | jq -r '.tasks|map((.taskDefinitionArn/"/")[1])|.[]' 40 | } 41 | 42 | # Return the current task definition for the given cluster and service 43 | function aws-task-definition() { 44 | local tds 45 | if [[ "$1" =~ : ]]; then 46 | tds=($1) 47 | else 48 | tds=($(aws-list-task-definitions $1 $2 | uniq)) 49 | shift 50 | fi 51 | shift 52 | for td in "${tds[@]}"; do 53 | aws ecs describe-task-definition --task-definition $td | jq "$@" 54 | done 55 | } 56 | 57 | # List all diffs over time for a given task definition env vars 58 | function aws-task-definition-env-history() { 59 | local cur=$2 max=$3 next diff a b 60 | [[ ! "$cur" ]] && cur=0 61 | [[ ! "$max" ]] && max=9999 62 | if [[ $(($cur+1-1)) != "$cur" || $(($max+1-1)) != "$max" ]]; then 63 | echo "Usage: aws-task-definition-env-history td-name [start-rev] [end-rev]" 64 | return 1 65 | fi 66 | while [[ $cur != $max ]]; do 67 | next=$((cur+1)) 68 | b=$(aws-task-definition-env $1:$next 2>/dev/null | sort) 69 | if [[ ! "$b" ]]; then 70 | echo "No more revisions." 71 | return 72 | fi 73 | a= 74 | if [[ $cur != 0 ]]; then 75 | echo -ne "\rComparing revisions $cur and $next..." 1>&2 76 | a=$(aws-task-definition-env $1:$cur 2>/dev/null | sort) 77 | fi 78 | diff=$(diff <(echo "$a") <(echo "$b")) 79 | if [[ "$diff" ]]; then 80 | echo -ne '\r' 1>&2 81 | if [[ $cur == 0 ]]; then 82 | echo "Initial values" 83 | else 84 | echo "Differences between revisions $cur and $next" 85 | fi 86 | echo "-------------------------------------------" 87 | echo "$diff" 88 | echo "===========================================" 89 | fi 90 | cur=$((cur+1)) 91 | done 92 | } 93 | 94 | # Print out VAR=VALUE lines for env of the current task definition for the given 95 | # cluster and service 96 | function aws-task-definition-env() { 97 | aws-task-definition "$@" \ 98 | -r '.taskDefinition.containerDefinitions[0].environment|map(.name+"="+.value)|.[]' 99 | } 100 | 101 | # Stop all aws tasks for the given cluster and service 102 | function aws-stop-tasks() { 103 | local tasks count cluster pad s t 104 | cluster=$1; shift 105 | for s in "$@"; do 106 | [[ "$pad" ]] && echo; pad=1 107 | echo "Finding tasks for service <$s> on cluster <$cluster>" 108 | tasks=($(aws-list-tasks $cluster $s)) 109 | count=${#tasks[@]} 110 | if [[ $count == 0 ]]; then 111 | echo "No tasks found, skipping" 112 | continue 113 | fi 114 | echo "${#tasks[@]} task(s) found" 115 | for t in "${tasks[@]}"; do 116 | echo "Stopping task $t" 117 | aws ecs stop-task --cluster $cluster --task $t --query 'task.stoppedReason' --output=text 118 | done 119 | done 120 | } 121 | 122 | # Log info lines to stderr 123 | function info() { 124 | local prefix=$1; shift 125 | echo "[$prefix] $@" 1>&2 126 | } 127 | 128 | # aws logs get-log-events --log-group-name tech-products/precision-enrollment-worker --log-stream-name v2.1.0/precision-enrollment-worker/f29fdf40-708b-43d0-8b2a-1d2501f17f0c --start-time 1506964074570 --limit 5 129 | function aws-logs() { 130 | local token text line next_token 131 | local group_name=$1; shift 132 | local stream_name=$1; shift 133 | [[ "$1" ]] && token="--next-token $1" 134 | text=$( 135 | aws logs get-log-events --log-group-name $group_name --log-stream-name $stream_name \ 136 | --query '[nextForwardToken,events[*].[timestamp,message]]' \ 137 | --output text $token \ 138 | --start-from-head 139 | ) 140 | while read -r line; do 141 | if [[ ! "$next_token" ]]; then 142 | next_token="$line" 143 | else 144 | local parts=($line) 145 | printf "[%(%F %T)T] ${parts[*]:1}\n" $((${parts[0]}/1000)) 146 | fi 147 | done <<< "$text" 148 | if [[ "$next_token" != "$1" ]]; then 149 | info LOG "Fetching more..." 150 | aws_logs $group_name $stream_name $next_token 151 | else 152 | info LOG "Done!" 153 | fi 154 | } 155 | -------------------------------------------------------------------------------- /bin/count-commits: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | if ARGV.include? '-h' or ARGV.include? '--help' then puts <<-HELP 4 | Count git commits across multiple projects. 5 | http://benalman.com/ 6 | 7 | Usage: #{File.basename $0} [directories] > counts.txt 8 | 9 | If directories aren't specified, all child directories of the current directory 10 | will be searched. 11 | 12 | Arbitrary name and email changes that can be accounted for will be reflected 13 | in the output. Counts/names/emails are sent to STDOUT in the following format: 14 | 15 | commitcount email1, email2, ... (name1, name2, ...) 16 | 17 | Eg: 18 | 19 | 1843 cowboy@rj3.net (Ben Alman, cowboy) 20 | 1202 tyler@sleekcode.net (Tyler Kellen, tkellen) 21 | 695 kyle@dontkry.com, kyle@kyletyoung.com (Kyle Robinson Young, shama) 22 | 402 vlad.filippov@gmail.com (vladikoff, Vlad Filippov) 23 | 388 sindresorhus@gmail.com (Sindre Sorhus, sindresorhus) 24 | 25 | All other messages are sent to STDERR. 26 | 27 | Copyright (c) 2014 "Cowboy" Ben Alman 28 | Licensed under the MIT license. 29 | http://benalman.com/about/license/ 30 | HELP 31 | exit; end 32 | 33 | require 'open3' 34 | 35 | def warn(msg) $stderr.puts msg end 36 | def fatal(msg) $stderr.puts msg; exit 1 end 37 | def debug(msg) $stderr.puts "> #{msg}" end 38 | 39 | # Validate specified dirs. 40 | def get_dirs(dirs) 41 | # Use all child dirs of the current dir if none were specified. 42 | if dirs.empty? 43 | dirs = Dir.glob('*/') 44 | end 45 | # Remove non-dirs 46 | dirs.select! {|d| File.directory? d} 47 | # Remove trailing slashes 48 | dirs.map! {|d| d.sub %r{/$}, ''} 49 | # Fail if no dirs were found. 50 | if dirs.empty? 51 | fatal 'Error: No directories found.' 52 | end 53 | dirs 54 | end 55 | 56 | # Get computed total number of commits. 57 | def get_computed_total() 58 | $committers.reduce(0) {|sum, committer| sum + committer[:commit_count]} 59 | end 60 | 61 | # Add a commit. 62 | def add_commit(email, name) 63 | # debug "#{email} #{name}" 64 | emails = [email] 65 | names = [name] 66 | commit_count = 1 67 | 68 | # Get the corresponding committer object(s) indexed by name and email. 69 | committer_by_email = $committers_by_email[email] 70 | committer_by_name = $committers_by_name[name] 71 | 72 | # Two committer objects exist, but they're not the same object. Combine them! 73 | if committer_by_email and committer_by_name and committer_by_email != committer_by_name 74 | emails = committer_by_name[:emails] 75 | names = committer_by_name[:names] 76 | commit_count += committer_by_name[:commit_count] 77 | # We save committer_by_email and kill off committer_by_name. 78 | $committers.reject! {|committer| committer == committer_by_name} 79 | committer = committer_by_email 80 | 81 | # One committer object exists, use it. 82 | elsif committer_by_email 83 | committer = committer_by_email 84 | elsif committer_by_name 85 | committer = committer_by_name 86 | 87 | # No committer object exists, create one! 88 | else 89 | committer = Hash.new 90 | committer[:emails] = [] 91 | committer[:names] = [] 92 | committer[:commit_count] = 0 93 | $committers << committer 94 | end 95 | # Update committers_by_name/committers_by_email maps. 96 | names.each {|name| $committers_by_name[name] = committer} 97 | emails.each {|email| $committers_by_email[email] = committer} 98 | # Update committer object with new data. 99 | committer[:names].concat(names).uniq! 100 | committer[:emails].concat(emails).uniq! 101 | committer[:commit_count] += commit_count 102 | end 103 | 104 | # Our data store. 105 | $committers = [] 106 | $committers_by_email = Hash.new 107 | $committers_by_name = Hash.new 108 | 109 | # Raw counters based on lines parsed. 110 | $commit_count = 0 111 | $project_count = 0 112 | 113 | # Get commits for each specified dir. 114 | get_dirs(ARGV).each do |dir| 115 | dir.sub! %r{/$}, '' 116 | stdin, stdout, stderr = Open3.popen3('git log --format="%aE%x09%aN"', :chdir => dir) 117 | if !stderr.readlines.empty? 118 | warn %Q{Error running "git log" in "#{dir}" directory.} 119 | else 120 | $project_count += 1 121 | stdout.readlines.each do |line| 122 | $commit_count += 1 123 | email, name = line.chomp.split "\t" 124 | add_commit(email, name) 125 | end 126 | end 127 | end 128 | 129 | # Sort committer names and email fields. 130 | $committers.each do |committer| 131 | committer[:names].sort! {|a, b| a.downcase <=> b.downcase} 132 | committer[:emails].sort! {|a, b| a.downcase <=> b.downcase} 133 | end 134 | 135 | # Sort committers first by commit count (descending) then by name. 136 | $committers.sort! do |a, b| 137 | comp = b[:commit_count] <=> a[:commit_count] 138 | comp.zero? ? (a[:names][0].downcase <=> b[:names][0].downcase) : comp 139 | end 140 | 141 | # Whoops? 142 | $total = get_computed_total 143 | if $total != $commit_count 144 | fatal "Error: Parsed #{$commit_count} commits, but for some reason only #{$total} appear." 145 | end 146 | 147 | # Useful output to STDOUT 148 | $committers.each do |c| 149 | puts "%#{$total.to_s.length}d %s (%s)" % [c[:commit_count], c[:emails].join(", "), c[:names].join(", ")] 150 | end 151 | 152 | # Totals. 153 | def pl(n, str) "#{n} #{str}#{n == 1 ? '' : ?s}" end 154 | warn "#{pl $commit_count, 'commit'} by #{pl $committers.length, 'author'} in #{pl $project_count, 'project'}." 155 | -------------------------------------------------------------------------------- /source/50_prompt.sh: -------------------------------------------------------------------------------- 1 | # My awesome bash prompt 2 | # 3 | # Copyright (c) 2012 "Cowboy" Ben Alman 4 | # Licensed under the MIT license. 5 | # http://benalman.com/about/license/ 6 | # 7 | # Example: 8 | # [master:!?][cowboy@CowBook:~/.dotfiles] 9 | # [11:14:45] $ 10 | # 11 | # Read more (and see a screenshot) in the "Prompt" section of 12 | # https://github.com/cowboy/dotfiles 13 | 14 | # Abort if a prompt is already defined. 15 | [[ "$PROMPT_COMMAND" ]] && return 16 | 17 | # ANSI CODES - SEPARATE MULTIPLE VALUES WITH ; 18 | # 19 | # 0 reset 4 underline 20 | # 1 bold 7 inverse 21 | # 22 | # FG BG COLOR FG BG COLOR 23 | # 30 40 black 34 44 blue 24 | # 31 41 red 35 45 magenta 25 | # 32 42 green 36 46 cyan 26 | # 33 43 yellow 37 47 white 27 | 28 | if [[ ! "${__prompt_colors[@]}" ]]; then 29 | __prompt_colors=( 30 | "36" # information color 31 | "37" # bracket color 32 | "31" # error color 33 | ) 34 | 35 | if [[ "$SSH_TTY" ]]; then 36 | # connected via ssh 37 | __prompt_colors[0]="32" 38 | elif [[ "$USER" == "root" ]]; then 39 | # logged in as root 40 | __prompt_colors[0]="35" 41 | fi 42 | fi 43 | 44 | # Inside a prompt function, run this alias to setup local $c0-$c9 color vars. 45 | alias __prompt_get_colors='__prompt_colors[9]=; local i; for i in ${!__prompt_colors[@]}; do local c$i="\[\e[0;${__prompt_colors[$i]}m\]"; done' 46 | 47 | # Exit code of previous command. 48 | function __prompt_exit_code() { 49 | __prompt_get_colors 50 | [[ $1 != 0 ]] && echo " $c2$1$c9" 51 | } 52 | 53 | # Git status. 54 | function __prompt_git() { 55 | __prompt_get_colors 56 | local status branch flags 57 | status="$(git status 2>/dev/null)" 58 | [[ $? != 0 ]] && return 1; 59 | branch="$(echo "$status" | awk '/# Initial commit/ {print "(init)"}')" 60 | [[ "$branch" ]] || branch="$(echo "$status" | awk '/# On branch/ {print $4}')" 61 | [[ "$branch" ]] || branch="$(git branch | perl -ne '/^\* \(detached from (.*)\)$/ ? print "($1)" : /^\* (.*)/ && print $1')" 62 | flags="$( 63 | echo "$status" | awk 'BEGIN {r=""} \ 64 | /^(# )?Changes to be committed:$/ {r=r "+"}\ 65 | /^(# )?Changes not staged for commit:$/ {r=r "!"}\ 66 | /^(# )?Untracked files:$/ {r=r "?"}\ 67 | END {print r}' 68 | )" 69 | __prompt_vcs_info=("$branch" "$flags") 70 | } 71 | 72 | # hg status. 73 | function __prompt_hg() { 74 | __prompt_get_colors 75 | local summary branch bookmark flags 76 | summary="$(hg summary 2>/dev/null)" 77 | [[ $? != 0 ]] && return 1; 78 | branch="$(echo "$summary" | awk '/branch:/ {print $2}')" 79 | bookmark="$(echo "$summary" | awk '/bookmarks:/ {print $2}')" 80 | flags="$( 81 | echo "$summary" | awk 'BEGIN {r="";a=""} \ 82 | /(modified)/ {r= "+"}\ 83 | /(unknown)/ {a= "?"}\ 84 | END {print r a}' 85 | )" 86 | __prompt_vcs_info=("$branch" "$bookmark" "$flags") 87 | } 88 | 89 | # SVN info. 90 | function __prompt_svn() { 91 | __prompt_get_colors 92 | local info last current 93 | info="$(svn info . 2> /dev/null)" 94 | [[ ! "$info" ]] && return 1 95 | last="$(echo "$info" | awk '/Last Changed Rev:/ {print $4}')" 96 | current="$(echo "$info" | awk '/Revision:/ {print $2}')" 97 | __prompt_vcs_info=("$last" "$current") 98 | } 99 | 100 | # Maintain a per-execution call stack. 101 | __prompt_stack=() 102 | trap '__prompt_stack=("${__prompt_stack[@]}" "$BASH_COMMAND")' DEBUG 103 | 104 | function __prompt_command() { 105 | local i exit_code=$? 106 | # If the first command in the stack is __prompt_command, no command was run. 107 | # Set exit_code to 0 and reset the stack. 108 | [[ "${__prompt_stack[0]}" == "__prompt_command" ]] && exit_code=0 109 | __prompt_stack=() 110 | 111 | # Manually load z here, after $? is checked, to keep $? from being clobbered. 112 | [[ "$(type -t _z)" ]] && _z --add "$(pwd -P 2>/dev/null)" 2>/dev/null 113 | 114 | # While the simple_prompt environment var is set, disable the awesome prompt. 115 | [[ "$simple_prompt" ]] && PS1='\n$ ' && return 116 | 117 | __prompt_get_colors 118 | # http://twitter.com/cowboy/status/150254030654939137 119 | PS1="\n" 120 | __prompt_vcs_info=() 121 | # git: [branch:flags] 122 | __prompt_git || \ 123 | # hg: [branch:bookmark:flags] 124 | __prompt_hg || \ 125 | # svn: [repo:lastchanged] 126 | __prompt_svn 127 | # Iterate over all vcs info parts, outputting an escaped var name that will 128 | # be interpolated automatically. This ensures that malicious branch names 129 | # can't execute arbitrary commands. For more info, see this PR: 130 | # https://github.com/cowboy/dotfiles/pull/68 131 | if [[ "${#__prompt_vcs_info[@]}" != 0 ]]; then 132 | PS1="$PS1$c1[$c0" 133 | for i in "${!__prompt_vcs_info[@]}"; do 134 | if [[ "${__prompt_vcs_info[i]}" ]]; then 135 | [[ $i != 0 ]] && PS1="$PS1$c1:$c0" 136 | PS1="$PS1\${__prompt_vcs_info[$i]}" 137 | fi 138 | done 139 | PS1="$PS1$c1]$c9" 140 | fi 141 | # misc: [cmd#:hist#] 142 | # PS1="$PS1$c1[$c0#\#$c1:$c0!\!$c1]$c9" 143 | # path: [user@host:path] 144 | PS1="$PS1$c1[$c0\u$c1@$c0\h$c1:$c0\w$c1]$c9" 145 | PS1="$PS1\n" 146 | # date: [HH:MM:SS] 147 | PS1="$PS1$c1[$c0$(date +"%H$c1:$c0%M$c1:$c0%S")$c1]$c9" 148 | # exit code: 127 149 | PS1="$PS1$(__prompt_exit_code "$exit_code")" 150 | PS1="$PS1 \$ " 151 | } 152 | 153 | PROMPT_COMMAND="__prompt_command" 154 | -------------------------------------------------------------------------------- /bin/git-jump: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function help() { 4 | cat </dev/null 74 | # If the commit was successful, tag it (overwriting any previous tag) 75 | if [[ $? == 0 ]]; then 76 | status="*" 77 | git tag -f "git-jump-$head_sha" >/dev/null 78 | fi 79 | echo "Previous HEAD was $head_sha$status, $(git_commit_subject $head_sha)" 80 | } 81 | 82 | # Restore previously-saved changes 83 | function restore() { 84 | local status="" 85 | # Save current changes before restoring 86 | save 87 | # Attempt to restore saved changes for specified commit 88 | git checkout "git-jump-$1" 2>/dev/null 89 | if [[ $? == 0 ]]; then 90 | # If the restore was successful, figure out exactly what was saved, check 91 | # out the original commit, then restore the saved changes on top of it 92 | status="*" 93 | local patch="$(git format-patch HEAD^ --stdout)" 94 | git checkout HEAD^ 2>/dev/null 95 | echo "$patch" | git apply - 96 | else 97 | # Otherwise, just restore the original commit 98 | git checkout "$1" 2>/dev/null 99 | fi 100 | echo "HEAD is now $1$status, $(git_commit_subject $1)" 101 | } 102 | 103 | # Clean (permanently) current changes and remove the current saved tag 104 | function clean() { 105 | local head_sha=$(git_head_sha) 106 | git tag -d "git-jump-$head_sha" &>/dev/null 107 | if [[ $? == 0 ]]; then 108 | echo "Removed stored data for commit $head_sha." 109 | fi 110 | local repo_root="$(git_repo_toplevel)" 111 | git reset HEAD "$repo_root" >/dev/null 112 | git clean -f -d -q -- "$repo_root" >/dev/null 113 | git checkout -- "$repo_root" >/dev/null 114 | echo "Unstaged changes and untracked files removed." 115 | } 116 | 117 | # Remove (permanently) all saved tags 118 | function clean_all_tags() { 119 | git for-each-ref refs/tags --format='%(refname:short)' | \ 120 | while read tag; do 121 | if [[ "$tag" =~ ^git-jump- ]]; then 122 | git tag -d "$tag" 123 | fi 124 | done 125 | } 126 | 127 | # Jump to next commit 128 | function next() { 129 | local next_sha=$(git_next_sha) 130 | if [[ "$next_sha" == "$(git_head_sha)" ]]; then 131 | # Abort if no more commits 132 | echo "Already at last commit in $git_branch. Congratulations!" 133 | else 134 | # Checkout branch by name if at its HEAD 135 | if [[ "$next_sha" == "$(git_branch_sha)" ]]; then 136 | next_sha="$git_branch" 137 | fi 138 | echo "Jumping ahead to next commit." 139 | restore $next_sha 140 | fi 141 | } 142 | 143 | # Jump to previous commit 144 | function prev() { 145 | local prev_sha=$(git_prev_sha) 146 | if [[ "$prev_sha" == "$(git_head_sha)" ]]; then 147 | # Abort if no more commits 148 | echo "Already at first commit in $git_branch." 149 | else 150 | echo "Jumping back to previous commit." 151 | restore $prev_sha 152 | fi 153 | } 154 | 155 | # Show help if requested 156 | if [[ "$1" == "--help" || "$1" == "-h" ]]; then 157 | help 158 | exit 159 | fi 160 | 161 | # Check if branch is valid 162 | git rev-parse "$git_branch" &>/dev/null 163 | if [[ $? != 0 ]]; then 164 | echo "Error: Branch \"$git_branch\" does not appear to be valid." 165 | echo "Try $(basename "$0") --help for more information." 166 | exit 1 167 | fi 168 | 169 | # Handle CLI arguments 170 | if [[ "$1" == "next" ]]; then 171 | next 172 | elif [[ "$1" == "prev" ]]; then 173 | prev 174 | elif [[ "$1" == "clean" ]]; then 175 | clean 176 | elif [[ "$1" == "cleanall" ]]; then 177 | clean_all_tags 178 | clean 179 | else 180 | usage 181 | exit 1 182 | fi 183 | -------------------------------------------------------------------------------- /link/.tmux.conf: -------------------------------------------------------------------------------- 1 | source "$POWERLINE_PREFIX/bindings/tmux/powerline.conf" 2 | 3 | # PREFIX 4 | set -g prefix2 C-a # GNU-Screen compatible prefix 5 | bind C-a send-prefix -2 6 | 7 | # GENERAL 8 | set -gq status-utf8 on # Expect UTF-8 (tmux < 2.2) 9 | set -gq utf8 on 10 | set -s escape-time 0 # Fastest command sequences 11 | set -sg repeat-time 600 # Increase repeat timeout 12 | set -s focus-events on 13 | set -g status-interval 2 # Update status frequently 14 | set -g history-limit 50000 # Increase history size 15 | set -g mouse on # Enable mouse mode 16 | set -g renumber-windows on # Renumber windows whenever any window is closed 17 | 18 | setw -g xterm-keys on 19 | setw -g aggressive-resize off 20 | 21 | # https://github.com/tmux/tmux/issues/435#issuecomment-226849415 22 | # http://joehanchoi.com/quick-fixes-for-tmux-2-1-on-osx/ 23 | set -g default-terminal "tmux-256color" # Color and italics! 24 | set -as terminal-overrides ',xterm*:sitm=\E[3m' # OS X only? 25 | 26 | set -g display-panes-active-colour brightgreen 27 | set -g display-panes-colour blue 28 | 29 | set -g @continuum-restore 'on' 30 | 31 | # edit configuration 32 | bind e new-window -n 'tmux.conf' "sh -c 'vim ~/.tmux.conf && tmux source ~/.tmux.conf && tmux display \"~/.tmux.conf sourced\"'" 33 | 34 | # reload configuration 35 | bind r source-file ~/.tmux.conf \; display '~/.tmux.conf sourced' 36 | 37 | # Ensure pbpaste/pbcopy work in OSX 38 | # https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard 39 | if 'test "$(uname -s)" = Darwin' 'set -g default-command "exec reattach-to-user-namespace -l $SHELL"' 40 | 41 | # Ensure 2nd column in the main-vertical layout is 80 chars wide 42 | set -g other-pane-width 80 43 | 44 | # vim-tmux integration helper 45 | is_vim="ps -o state= -o comm= -t '#{pane_tty}' \ 46 | | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'" 47 | 48 | # Ctrl-Left/Right/Up/Down Move focus among splits 49 | bind-key -n C-Up if "$is_vim" "send C-Up" "select-pane -U" 50 | bind-key -n C-Down if "$is_vim" "send C-Down" "select-pane -D" 51 | bind-key -n C-Left if "$is_vim" "send C-Left" "select-pane -L" 52 | bind-key -n C-Right if "$is_vim" "send C-Right" "select-pane -R" 53 | # Ctrl-\ Last pane 54 | bind-key -n C-\ if "$is_vim" "send C-\\" "select-pane -l" 55 | 56 | # Ctrl-Shift-Left/Right/Up/Down Resize the current split by 1 57 | bind-key -n C-S-Up display-panes \; resize-pane -U 1 58 | bind-key -n C-S-Down display-panes \; resize-pane -D 1 59 | bind-key -n C-S-Left display-panes \; resize-pane -L 1 60 | bind-key -n C-S-Right display-panes \; resize-pane -R 1 61 | 62 | # Alt-Up Zoom pane in/out 63 | bind-key -n M-Up resize-pane -Z 64 | 65 | # Alt-Down Cycle through layouts 66 | bind-key -n M-Down display-panes \; next-layout 67 | 68 | # Alt-,/. Move focus among windows 69 | bind-key -n M-, previous-window 70 | bind-key -n M-. next-window 71 | 72 | # Alt-[/] Move focus among sessions 73 | bind-key -n M-[ switch-client -p 74 | bind-key -n M-] switch-client -n 75 | 76 | # Alt-Shift-Left/Right/Up/Down Create a new split in the given direction 77 | bind-key -n M-S-Left split-window -h -c "#{pane_current_path}" \; swap-pane -s :. -t :.- \; select-pane -t :.- \; display-panes 78 | bind-key -n M-S-Up split-window -v -c "#{pane_current_path}" \; swap-pane -s :. -t :.- \; select-pane -t :.- \; display-panes 79 | bind-key -n M-S-Right display-panes \; split-window -h -c "#{pane_current_path}" 80 | bind-key -n M-S-Down display-panes \; split-window -v -c "#{pane_current_path}" 81 | 82 | # Alt-BackSpace/Delete Kill current focused split 83 | bind-key -n M-DC kill-pane 84 | bind-key -n M-BSpace kill-pane 85 | 86 | # Shift-F7 Save history to $BYOBU_RUN_DIR/printscreen 87 | # bind-key -n S-F7 capture-pane -S -32768 \; save-buffer "$BYOBU_RUN_DIR/printscreen" \; delete-buffer \; new-window -n "PRINTSCREEN" "$EDITOR $BYOBU_RUN_DIR/printscreen" 88 | 89 | # Shift-Up Enter scrollback mode 90 | bind-key -n S-Up if "$is_vim" "send S-Up" "copy-mode" 91 | # Shift-Up/Down Copy mode: scroll up/down a half-page at a time 92 | bind-key -T copy-mode-vi S-Up send -X halfpage-up 93 | bind-key -T copy-mode-vi S-Down send -X halfpage-down 94 | # bind-key -T copy-mode-vi 95 | # bind-key -T copy-mode-vi MouseDragEnd1Pane send -X copy-pipe-and-cancel "$clipboard_copy_command" 96 | 97 | # F1 Used by X11 98 | 99 | # Shift-F1 100 | bind-key -n S-F1 new-window -k -n "tmux help" "man tmux" 101 | 102 | # F2 New window 103 | bind-key -n F2 command-prompt -p \ 104 | "[New window] Enter name or Ctrl-C to cancel:" \ 105 | "new-window -c '#{pane_current_path}'; run-shell 'a=%%; tmux rename-window \${a:--}'" 106 | # Shift-F2 Rename window 107 | bind-key -n S-F2 command-prompt -p \ 108 | "[Rename window] Enter name or Ctrl-C to cancel (current=#W):" \ 109 | "run-shell 'a=%%; tmux rename-window \${a:-#W}'" 110 | 111 | # F3 New session 112 | bind-key -n F3 command-prompt -p \ 113 | "[New session] Enter name or Ctrl-C to cancel:" \ 114 | "new-session; run-shell 'a=%%; tmux rename-session \${a:--}'" 115 | # Shift-F3 Rename session 116 | bind-key -n S-F3 command-prompt -p \ 117 | "[Rename session] Enter name or Ctrl-C to cancel (current=#S):" \ 118 | "run-shell 'a=%%; tmux rename-session \${a:-#S} || true'" 119 | 120 | 121 | # Alt-F3 Expand pane to a full window 122 | # bind-key -n M-F3 break-pane 123 | # Ctrl-F3 Join window into a vertical split 124 | # bind-key -n C-F3 join-pane -h -s :. -t :-1 125 | 126 | # F9 Detach session and then logout 127 | bind-key -n F9 detach-client 128 | # Shift-F9 Detach session and do not logout 129 | bind-key -n S-F9 run-shell "exec touch $DOTFILES/caches/tmux-no-logout" \; detach 130 | # Ctrl-F9 Detach all clients but the current one 131 | bind-key -n C-F9 detach-client -a 132 | 133 | 134 | # F10 Used by X11 135 | # F11 Used by X11 136 | 137 | # Ctrl-Shift-Left/Right Swap the current split with another 138 | # bind-key -n C-S-Left display-panes \; swap-pane -s :. -t :.- \; select-pane -t :.- 139 | # bind-key -n C-S-Right display-panes \; swap-pane -s :. -t :.+ \; select-pane -t :.+ 140 | 141 | # Ctrl-Shift-Up Balance panes horizontally 142 | # bind-key -n C-S-Up display-panes \; select-layout even-horizontal 143 | 144 | 145 | # F3/F4 Move focus among windows 146 | # bind-key -n F3 previous-window 147 | # bind-key -n F4 next-window 148 | # Shift-F3/F4 Move focus among splits 149 | # bind-key -n S-F3 display-panes \; select-pane -t :.- 150 | # bind-key -n S-F4 display-panes \; select-pane -t :.+ 151 | # Ctrl-Shift-F3/F4 Move a window 152 | # bind-key -n C-S-F3 swap-window -t :-1 153 | # bind-key -n C-S-F4 swap-window -t :+1 154 | 155 | # Alt-F9 Toggle sending keyboard input to all splits 156 | # bind-key -n M-F9 display-panes \; setw synchronize-panes 157 | 158 | 159 | 160 | # Plugins 161 | set -g @plugin 'tmux-plugins/tpm' 162 | set -g @plugin 'tmux-plugins/tmux-yank' 163 | set -g @plugin 'tmux-plugins/tmux-resurrect' 164 | set -g @plugin 'tmux-plugins/tmux-continuum' 165 | 166 | # Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf) 167 | run '~/.tmux/plugins/tpm/tpm' 168 | -------------------------------------------------------------------------------- /bin/gpr: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function help() { 4 | pr=123 5 | local_ref=foo 6 | script="$(basename "$0") $pr" 7 | cat </dev/null 141 | git config --global --add gpr.token $token 142 | echo "Authorization successful, token saved." 143 | exit 144 | else 145 | echo "Error authorizing with GitHub, please try again." 146 | exit 5 147 | fi 148 | fi 149 | 150 | pr="$1"; shift 151 | script="$(basename "$0") $pr" 152 | branch="pr$pr" 153 | 154 | repo="$(git remote show -n origin | perl -ne '/Fetch URL: .*github\.com[:\/](.*\/.*)\.git/ && print $1')" 155 | 156 | # Let's fetch some JSON. 157 | token="$(git config --get gpr.token)" 158 | json="$(curl -fsSL "https://api.github.com/repos/$repo/pulls/$pr?access_token=$token" 2>/dev/null)" 159 | if [[ $? != 0 || ! "$json" ]]; then 160 | echo "Error fetching GitHub API data for $repo PR $pr!" 161 | echo "If you're trying to access a private repo and haven't yet done so, please run" 162 | echo "the \"$(basename "$0") auth\" command to generate a GitHub auth token." 163 | exit 2 164 | fi 165 | 166 | # Let's parse some JSON. 167 | remote_url="$(node -pe "($json).head.repo.git_url")" 168 | remote_ref="$(node -pe "($json).head.ref")" 169 | local_url="$(node -pe "($json).base.repo.git_url")" 170 | local_ref="$(node -pe "($json).base.ref")" 171 | num_commits="$(node -pe "($json).commits")" 172 | 173 | # Let's get the project's .git folder. 174 | git_dir="$(git rev-parse --show-toplevel)/.git" 175 | 176 | function del_branch() { 177 | if [[ "$(git branch | grep " $1\$")" ]]; then 178 | git checkout "$local_ref" 2>/dev/null 179 | git branch -D "$1" 2>/dev/null 180 | fi 181 | } 182 | 183 | # Use the specified step, otherwise attempt to auto-detect it. 184 | if [[ "$1" ]]; then 185 | step=$1 186 | elif [[ "$(git branch | grep " $branch-squash\$")" ]]; then 187 | # STEP 3 should never auto-execute twice. 188 | if [[ "$(git branch --contains "$(git rev-parse $branch-squash)" | grep " $local_ref\$")" ]]; then 189 | echo "Error merging branch \"$branch-squash\" into \"$local_ref\" branch! (already done)" 190 | echo 191 | echo "Redo the last step with: $script 3" 192 | exit 4 193 | fi 194 | step=3 195 | elif [[ "$(git branch | grep " $branch\$")" ]]; then 196 | step=2 197 | else 198 | step=1 199 | fi 200 | 201 | # Let's do some stuff. 202 | if [[ $step == 1 ]]; then 203 | header 1 204 | 205 | # Clean up any prior work on this PR. 206 | del_branch "$branch" 207 | del_branch "$branch-squash" 208 | 209 | # Fetch remote, create a branch, etc. 210 | if [[ "$remote_url" == "$local_url" ]]; then 211 | git fetch origin "$remote_ref" 212 | else 213 | git fetch "$remote_url" "$remote_ref" 214 | fi 215 | git checkout -b "$branch" FETCH_HEAD 216 | 217 | # Save ref to last PR author commit for later use 218 | git tag --force "_${branch}_author_head" FETCH_HEAD 219 | 220 | # Rebase! 221 | git rebase "$local_ref" 222 | if [[ $? != 0 ]]; then 223 | echo "Error while attempting rebase!" 224 | exit 3 225 | fi 226 | 227 | echo 228 | echo "Changed files in HEAD~$num_commits:" 229 | git --no-pager diff --name-only HEAD~"$num_commits" 230 | 231 | echo 232 | echo "-=[ Next Steps ]=============================================================-" 233 | echo "$(help_step2 1) with: $script" 234 | echo " Or redo the current step with: $script 1" 235 | 236 | elif [[ $step == 2 ]]; then 237 | header 2 238 | 239 | # Clean up any prior squashes for this PR. 240 | del_branch "$branch-squash" 241 | 242 | # Create branch and squash merge all commits. 243 | git checkout -b "$branch-squash" "$local_ref" 244 | git merge --squash "$branch" 245 | 246 | # Append useful information to commit message. 247 | squash_msg_file="$git_dir/SQUASH_MSG" 248 | echo -e "\nCloses gh-$pr." >> "$squash_msg_file" 249 | 250 | # Retrieve author name and email from stored commit, and commit. 251 | author="$(git log "_${branch}_author_head" -n1 --format="%an <%ae>")" 252 | git commit --author="$author" 253 | 254 | echo 255 | echo "-=[ Next Steps ]=============================================================-" 256 | echo "$(help_step3 1) with: $script" 257 | echo " Or redo the current step with: $script 2" 258 | 259 | elif [[ $step == 3 ]]; then 260 | header 3 261 | 262 | # Actually merge squashed commits into branch. 263 | git checkout "$local_ref" 264 | git merge "$branch-squash" 265 | 266 | echo 267 | echo "-=[ Next Steps ]=============================================================-" 268 | echo "$(help_step4 1) with: $script 4" 269 | echo " Or redo the current step with: $script 3" 270 | 271 | elif [[ $step == 4 ]]; then 272 | header 4 273 | 274 | del_branch "$branch" 275 | del_branch "$branch-squash" 276 | git tag -d "_${branch}_author_head" 2>/dev/null 277 | 278 | echo 279 | echo "All done." 280 | fi 281 | -------------------------------------------------------------------------------- /source/50_vcs.sh: -------------------------------------------------------------------------------- 1 | 2 | # Git shortcuts 3 | 4 | alias g='git' 5 | function ga() { git add "${@:-.}"; } # Add all files by default 6 | alias gp='git push' 7 | alias gpup='gp --set-upstream origin $(gbs)' 8 | alias gpa='gp --all' 9 | alias gu='git pull' 10 | alias gl='git log' 11 | alias gg='gl --decorate --oneline --graph --date-order --all' 12 | alias gs='git status' 13 | alias gst='gs' 14 | alias gd='git diff' 15 | alias gdc='gd --cached' 16 | alias gm='git commit -m' 17 | alias gma='git commit -am' 18 | alias gb='git branch' 19 | alias gba='git branch -a' 20 | alias gbup='gb --set-upstream-to=origin/$(gbs) $(gbs)' 21 | function gc() { git checkout "${@:-master}"; } # Checkout master by default 22 | alias gco='gc' 23 | alias gcb='gc -b' 24 | alias gbc='gc -b' # Dyslexia 25 | alias gr='git remote' 26 | alias grv='gr -v' 27 | #alias gra='git remote add' 28 | alias grr='git remote rm' 29 | alias gcl='git clone' 30 | alias gcd='git rev-parse 2>/dev/null && cd "./$(git rev-parse --show-cdup)"' 31 | 32 | # Current branch or SHA if detached. 33 | alias gbs='git branch | perl -ne '"'"'/^\* (?:\(detached from (.*)\)|(.*))/ && print "$1$2"'"'"'' 34 | 35 | # Run commands in each subdirectory. 36 | alias gu-all='eachdir git pull' 37 | alias gp-all='eachdir git push' 38 | alias gs-all='eachdir git status' 39 | 40 | # Set upstream branch 41 | function gsu() { 42 | local branch_name=$(git symbolic-ref --short HEAD) 43 | [[ ! "$branch_name" ]] && echo 'Error: current git branch not detected' && return 1 44 | local upstream="$(git config "branch.$branch_name.merge")" 45 | [[ "$upstream" ]] && echo "Upstream for branch '$branch_name' already set." && return 46 | git branch --set-upstream-to=origin/$branch_name $branch_name 47 | } 48 | 49 | # Rebase topic branch onto origin parent branch and update local parent branch 50 | # to match origin parent branch 51 | function grbo() { 52 | local parent topic parent_sha origin_sha 53 | parent=$1 54 | topic=$2 55 | [[ ! "$parent" ]] && _grbo_err "Missing parent branch." && return 1 56 | parent_sha=$(git rev-parse $parent 2>/dev/null) 57 | [[ $? != 0 ]] && _grbo_err "Invalid parent branch: $parent" && return 1 58 | origin_sha=$(git ls-remote origin $parent | awk '{print $1}') 59 | [[ ! "$origin_sha" ]] && _grbo_err "Invalid origin parent branch: origin/$parent" && return 1 60 | [[ "$parent_sha" == "$origin_sha" ]] && echo "Same SHA for parent and origin/parent. Nothing to do!" && return 61 | if [[ "$topic" ]]; then 62 | git rev-parse "$topic" >/dev/null 2>&1 63 | [[ $? != 0 ]] && _grbo_err "Invalid topic branch: $topic" && return 1 64 | else 65 | topic="$(git rev-parse --abbrev-ref HEAD)" 66 | fi 67 | [[ "$topic" == "HEAD" ]] && _grbo_err "Missing or invalid topic branch." && return 1 68 | [[ "$topic" == "$parent" ]] && _grbo_err "Topic and parent branch must be different!" && return 1 69 | read -n 1 -r -p "About to rebase $topic onto origin/$parent. Are you sure? [y/N] " 70 | if [[ $REPLY =~ ^[Yy]$ ]]; then 71 | echo 72 | git fetch && 73 | git rebase --onto origin/$parent $parent "$topic" && 74 | git branch -f $parent origin/$parent 75 | else 76 | echo "Aborted by user." 77 | fi 78 | } 79 | function _grbo_err() { 80 | echo "Error: $@" 81 | echo "Usage: grbo parent-branch [topic-branch]" 82 | } 83 | 84 | # open all changed files (that still actually exist) in the editor 85 | function ged() { 86 | local files 87 | local _IFS="$IFS" 88 | IFS=$'\n' 89 | files=($(git diff --name-status "$@" | grep -v '^D' | cut -f2 | sort | uniq)) 90 | if [[ "$2" ]]; then 91 | echo "Opening files modified between $1 and $2" 92 | else 93 | files+=($(git ls-files --others --exclude-standard)) 94 | if [[ "$1" ]]; then 95 | echo "Opening files modified since $1" 96 | else 97 | echo "Opening unstaged/untracked modified files" 98 | fi 99 | fi 100 | IFS="$_IFS" 101 | gcd 102 | if [[ "$(which code)" ]]; then 103 | code "$(git rev-parse --show-toplevel)" -n "${files[@]}" 104 | else 105 | q "${files[@]}" 106 | fi 107 | cd - > /dev/null 108 | } 109 | 110 | # add a github remote by github username 111 | function gra() { 112 | if (( "${#@}" != 1 )); then 113 | echo "Usage: gra githubuser" 114 | return 1; 115 | fi 116 | local repo=$(gr show -n origin | perl -ne '/Fetch URL: .*github\.com[:\/].*\/(.*)/ && print $1') 117 | gr add "$1" "git://github.com/$1/$repo" 118 | } 119 | 120 | # GitHub URL for current repo. 121 | function gurl() { 122 | local remotename="${@:-origin}" 123 | local remote="$(git remote -v | awk '/^'"$remotename"'.*\(push\)$/ {print $2}')" 124 | [[ "$remote" ]] || return 125 | local host="$(echo "$remote" | perl -pe 's/.*@//;s/:.*//')" 126 | local user_repo="$(echo "$remote" | perl -pe 's/.*://;s/\.git$//')" 127 | echo "https://$host/$user_repo" 128 | } 129 | # GitHub URL for current repo, including current branch + path. 130 | alias gurlp='echo $(gurl)/tree/$(gbs)/$(git rev-parse --show-prefix)' 131 | 132 | # git log with per-commit cmd-clickable GitHub URLs (iTerm) 133 | function gf() { 134 | git log $* --name-status --color | awk "$(cat < $file_len )) && file_len=${#file} 180 | done 181 | graph_len=$(($COLUMNS-$file_len-10)) 182 | (( $graph_len <= 0 )) && graph_len=1 183 | 184 | lines=($(git diff -M --stat --stat-width=999 --stat-name-width=$file_len \ 185 | --stat-graph-width=$graph_len --color "$range")) 186 | e=$(echo -e "\033") 187 | r="$e[0m" 188 | declare -A c=([M]="1;33" [D]="1;31" [A]="1;32" [R]="1;34") 189 | for line in "${lines[@]}"; do 190 | file="$(echo "$line" | perl -pe "$line_regex")" 191 | if [[ "$file" =~ \{.+\=\>.+\} ]]; then 192 | mode=R 193 | line="$(echo "$line" | perl -pe "s/(^|=>|\})/$r$e[${c[R]}m\$1$r$e[${c[A]}m/g")" 194 | line="$(echo "$line" | perl -pe "s/(\{)/$r$e[${c[R]}m\$1$r$e[${c[D]}m/")" 195 | else 196 | mode=${modes["$file"]} 197 | color=0; [[ "$mode" ]] && color=${c[$mode]} 198 | line="$e[${color}m$line" 199 | fi 200 | echo "$line" | sed "s/\|/$e[0m$mode \|/" 201 | done 202 | unset IFS 203 | } 204 | 205 | # Rename/delete diff helper 206 | # (pipe to pbcopy for github comment-friendly output) 207 | # 208 | # 1. Check out a branch 209 | # 2. Get a list of changed files since master: 210 | # $ git diff master --name-status 211 | # 3. Organize listed files into M/D pairs, eg: 212 | # M src/File.jsx 213 | # D src/FileFeatureFlagName.jsx 214 | # 215 | # M src/File.test.jsx 216 | # D src/FileFeatureFlagName.test.jsx 217 | # 4. For each pair, run this function, eg: 218 | # $ git_diff_rename src/File.jsx src/FileFeatureFlagName.jsx 219 | # $ git_diff_rename src/File.test.jsx src/FileFeatureFlagName.test.jsx 220 | function git_diff_rename() { 221 | local prev_commit="$1" 222 | local before="$3" 223 | local after="$2" 224 | if [ -p /dev/stdout ]; then 225 | echo -en "
\n Diff of $before -> $after\n\n" 226 | echo -en 'Command:\n```sh\n' 227 | echo git diff $prev_commit:"$before" HEAD:"$after" 228 | echo -en '```\n\nDiff:\n```diff\n' 229 | fi 230 | git diff $prev_commit:"$before" HEAD:"$after" 231 | if [ -p /dev/stdout ]; then 232 | echo -en '```\n
\n' 233 | fi 234 | } 235 | 236 | # Open a handful of PRs to test the CI system (defaults to 5) 237 | function git_pr_blaster() { 238 | local i new_branch branch="$(gbs)" 239 | for i in $(seq 1 ${1:-5}); do 240 | new_branch="$branch-test-do-not-merge-$i" 241 | git checkout -b "$new_branch" && \ 242 | echo "$new_branch" >> TEST_PR_DO_NOT_MERGE.txt && \ 243 | git add . && \ 244 | git commit -m "$new_branch" && \ 245 | git push --no-verify && \ 246 | git checkout - && \ 247 | git branch -D "$new_branch" && \ 248 | open "$(gurl)/pull/new/$new_branch" 249 | done 250 | } 251 | 252 | # OSX-specific Git shortcuts 253 | if is_osx; then 254 | alias gdk='git ksdiff' 255 | alias gdkc='gdk --cached' 256 | function gt() { 257 | local path repo 258 | { 259 | pushd "${1:-$PWD}" 260 | path="$PWD" 261 | repo="$(git rev-parse --show-toplevel)" 262 | popd 263 | } >/dev/null 2>&1 264 | if [[ -e "$repo" ]]; then 265 | echo "Opening git repo $repo." 266 | gittower "$repo" 267 | else 268 | echo "Error: $path is not a git repo." 269 | fi 270 | } 271 | fi 272 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dotfiles 2 | 3 | My OSX / Ubuntu dotfiles. 4 | 5 | ## About this project 6 | 7 | I've been using bash on-and-off for a long time (since Slackware Linux was distributed on 1.44MB floppy disks). In all that time, every time I've set up a new Linux or OS X machine, I've copied over my `.bashrc` file and my `~/bin` folder to each machine manually. And I've never done a very good job of actually maintaining these files. It's been a total mess. 8 | 9 | I finally decided that I wanted to be able to execute a single command to "bootstrap" a new system to pull down all of my dotfiles and configs, as well as install all the tools I commonly use. In addition, I wanted to be able to re-execute that command at any time to synchronize anything that might have changed. Finally, I wanted to make it easy to re-integrate changes back in, so that other machines could be updated. 10 | 11 | That command is [dotfiles][dotfiles], and this is my "dotfiles" Git repo. 12 | 13 | [dotfiles]: bin/dotfiles 14 | 15 | ## How the "dotfiles" command works 16 | 17 | When [dotfiles][dotfiles] is run for the first time, it does a few things: 18 | 19 | 1. In Ubuntu, Git is installed if necessary via APT (it's already there in OSX). 20 | 1. This repo is cloned into your user directory, under `~/.dotfiles`. 21 | 1. Files in `/copy` are copied into `~/`. ([read more](#the-copy-step)) 22 | 1. Files in `/link` are symlinked into `~/`. ([read more](#the-link-step)) 23 | 1. You are prompted to choose scripts in `/init` to be executed. The installer attempts to only select relevant scripts, based on the detected OS and the script filename. 24 | 1. Your chosen init scripts are executed (in alphanumeric order, hence the funky names). ([read more](#the-init-step)) 25 | 26 | On subsequent runs, step 1 is skipped, step 2 just updates the already-existing repo, and step 5 remembers what you selected the last time. The other steps are the same. 27 | 28 | ### Other subdirectories 29 | 30 | * The `/backups` directory gets created when necessary. Any files in `~/` that would have been overwritten by files in `/copy` or `/link` get backed up there. 31 | * The `/bin` directory contains executable shell scripts (including the [dotfiles][dotfiles] script) and symlinks to executable shell scripts. This directory is added to the path. 32 | * The `/caches` directory contains cached files, used by some scripts or functions. 33 | * The `/conf` directory just exists. If a config file doesn't **need** to go in `~/`, reference it from the `/conf` directory. 34 | * The `/source` directory contains files that are sourced whenever a new shell is opened (in alphanumeric order, hence the funky names). 35 | * The `/test` directory contains unit tests for especially complicated bash functions. 36 | * The `/vendor` directory contains third-party libraries. 37 | 38 | ### The "copy" step 39 | Any file in the `/copy` subdirectory will be copied into `~/`. Any file that _needs_ to be modified with personal information (like [copy/.gitconfig](copy/.gitconfig) which contains an email address and private key) should be _copied_ into `~/`. Because the file you'll be editing is no longer in `~/.dotfiles`, it's less likely to be accidentally committed into your public dotfiles repo. 40 | 41 | ### The "link" step 42 | Any file in the `/link` subdirectory gets symlinked into `~/` with `ln -s`. Edit one or the other, and you change the file in both places. Don't link files containing sensitive data, or you might accidentally commit that data! If you're linking a directory that might contain sensitive data (like `~/.ssh`) add the sensitive files to your [.gitignore](.gitignore) file! 43 | 44 | ### The "init" step 45 | Scripts in the `/init` subdirectory will be executed. A whole bunch of things will be installed, but _only_ if they aren't already. 46 | 47 | #### OS X 48 | 49 | * Minor XCode init via the [init/10_osx_xcode.sh](init/10_osx_xcode.sh) script 50 | * Homebrew via the [init/20_osx_homebrew.sh](init/20_osx_homebrew.sh) script 51 | * Homebrew recipes via the [init/30_osx_homebrew_recipes.sh](init/30_osx_homebrew_recipes.sh) script 52 | * Homebrew casks via the [init/30_osx_homebrew_casks.sh](init/30_osx_homebrew_casks.sh) script 53 | * [Fonts](/cowboy/dotfiles/tree/master/conf/osx/fonts) via the [init/50_osx_fonts.sh](init/50_osx_fonts.sh) script 54 | 55 | #### Ubuntu 56 | * APT packages and git-extras via the [init/20_ubuntu_apt.sh](init/20_ubuntu_apt.sh) script 57 | 58 | #### Both 59 | * Node.js, npm and nave via the [init/50_node.sh](init/50_node.sh) script 60 | * Ruby, gems and rbenv via the [init/50_ruby.sh](init/50_ruby.sh) script 61 | * Vim plugins via the [init/50_vim.sh](init/50_vim.sh) script 62 | 63 | ## Hacking my dotfiles 64 | 65 | Because the [dotfiles][dotfiles] script is completely self-contained, you should be able to delete everything else from your dotfiles repo fork, and it will still work. The only thing it really cares about are the `/copy`, `/link` and `/init` subdirectories, which will be ignored if they are empty or don't exist. 66 | 67 | If you modify things and notice a bug or an improvement, [file an issue](https://github.com/cowboy/dotfiles/issues) or [a pull request](https://github.com/cowboy/dotfiles/pulls) and let me know. 68 | 69 | Also, before installing, be sure to [read my gently-worded note](#heed-this-critically-important-warning-before-you-install). 70 | 71 | ## Installation 72 | 73 | ### OS X Notes 74 | 75 | You need to have [XCode](https://developer.apple.com/downloads/index.action?=xcode) or, at the very minimum, the [XCode Command Line Tools](https://developer.apple.com/downloads/index.action?=command%20line%20tools), which are available as a much smaller download. 76 | 77 | The easiest way to install the XCode Command Line Tools in OSX 10.9+ is to open up a terminal, type `xcode-select --install` and [follow the prompts](http://osxdaily.com/2014/02/12/install-command-line-tools-mac-os-x/). 78 | 79 | _Tested in OSX 10.15_ 80 | 81 | ### Ubuntu Notes 82 | 83 | You might want to set up your ubuntu server [like I do it](https://github.com/cowboy/dotfiles/wiki/ubuntu-setup), but then again, you might not. 84 | 85 | Either way, you should at least update/upgrade APT with `sudo apt-get -qq update && sudo apt-get -qq dist-upgrade` first. 86 | 87 | _Tested in Ubuntu 14.04 LTS_ 88 | 89 | ### Heed this critically important warning before you install 90 | 91 | **If you're not me, please _do not_ install dotfiles directly from this repo!** 92 | 93 | Why? Because I often completely break this repo while updating. Which means that if I do that and you run the `dotfiles` command, your home directory will burst into flames, and you'll have to go buy a new computer. No, not really, but it will be very messy. 94 | 95 | ### Actual installation (for you) 96 | 97 | 1. [Read my gently-worded note](#heed-this-critically-important-warning-before-you-install) 98 | 1. Fork this repo 99 | 1. Open a terminal/shell and do this (change `cowboy` and `master` as appropriate): 100 | 101 | #### Ubuntu 102 | 103 | ```sh 104 | export DOTFILES_GH_USER=cowboy 105 | export DOTFILES_GH_BRANCH=master 106 | bash -c "$(wget -qO- https://raw.github.com/$DOTFILES_GH_USER/dotfiles/$DOTFILES_GH_BRANCH/bin/dotfiles)" && source ~/.bashrc 107 | ``` 108 | 109 | #### macOS 110 | 111 | ```sh 112 | export DOTFILES_GH_USER=cowboy 113 | export DOTFILES_GH_BRANCH=master 114 | bash -c "$(curl -fsSL https://raw.github.com/$DOTFILES_GH_USER/dotfiles/$DOTFILES_GH_BRANCH/bin/dotfiles)" && source ~/.bashrc 115 | ``` 116 | 117 | Since you'll be using the [dotfiles][dotfiles] command on subsequent runs, you'll only have to set the `DOTFILES_GH_USER` variable for the initial install, but if you have a custom branch, you _will_ need to export `DOTFILES_GH_BRANCH` for subsequent runs. 118 | 119 | There's a lot of stuff that requires admin access via `sudo`, so be warned that you might need to enter your password here or there. 120 | 121 | ### Actual installation (for me) 122 | 123 | #### Ubuntu 124 | 125 | ```sh 126 | bash -c "$(wget -qO- https://bit.ly/cowboy-dotfiles)" && source ~/.bashrc 127 | ``` 128 | 129 | #### macOS 130 | 131 | ```sh 132 | bash -c "$(curl -fsSL https://bit.ly/cowboy-dotfiles)" && source ~/.bashrc 133 | ``` 134 | 135 | ## Aliases and Functions 136 | To keep things easy, the `~/.bashrc` and `~/.bash_profile` files are extremely simple, and should never need to be modified. Instead, add your aliases, functions, settings, etc into one of the files in the `source` subdirectory, or add a new file. They're all automatically sourced when a new shell is opened. Take a look, I have [a lot of aliases and functions](source). I even have a [fancy prompt](source/50_prompt.sh) that shows the current directory, time and current git/svn repo status. 137 | 138 | ## Scripts 139 | In addition to the aforementioned [dotfiles][dotfiles] script, there are a few other [bin scripts](bin). This includes [nave](https://github.com/isaacs/nave), which is a [git submodule](vendor). 140 | 141 | * [dotfiles][dotfiles] - (re)initialize dotfiles. It might ask for your password (for `sudo`). 142 | * [src](link/.bashrc#L8-18) - (re)source all files in `/source` directory 143 | * Look through the [bin](bin) subdirectory for a few more. 144 | 145 | ## Prompt 146 | I think [my bash prompt](source/50_prompt.sh) is awesome. It shows git and svn repo status, a timestamp, error exit codes, and even changes color depending on how you've logged in. 147 | 148 | Git repos display as **[branch:flags]** where flags are: 149 | 150 | **?** untracked files 151 | **!** changed (but unstaged) files 152 | **+** staged files 153 | 154 | SVN repos display as **[rev1:rev2]** where rev1 and rev2 are: 155 | 156 | **rev1** last changed revision 157 | **rev2** revision 158 | 159 | Check it out: 160 | 161 | ![My awesome bash prompt](http://farm8.staticflickr.com/7142/6754488927_563dd73553_b.jpg) 162 | 163 | ## Inspiration 164 | 165 | 166 | (and 15+ years of accumulated crap) 167 | 168 | ## License 169 | Copyright (c) 2014 "Cowboy" Ben Alman 170 | Licensed under the MIT license. 171 | 172 | -------------------------------------------------------------------------------- /bin/rename: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use strict; 3 | use warnings; 4 | 5 | =head1 NAME 6 | 7 | rename - renames multiple files 8 | 9 | =head1 SYNOPSIS 10 | 11 | F 12 | S> 13 | 14 | F 15 | S> 16 | 17 | F 18 | S> 19 | S> 20 | S> 21 | S> 22 | S> 23 | S> 24 | S> 25 | S> 26 | S> 27 | S> 28 | S> 29 | 30 | =head1 DESCRIPTION 31 | 32 | C renames the filenames supplied according to the rules specified. If a given filename is not modified, it will not be renamed. If no filenames are given on the command line, filenames will be read via standard input. 33 | 34 | For example, to rename all files matching C<*.bak> to strip the extension, you might say 35 | 36 | rename 's/\.bak$//' *.bak 37 | 38 | If are confident that none of the filenames has C<.bak> anywhere else than at the end, you can also use the much easier typed 39 | 40 | rename -s .bak '' *.bak 41 | 42 | You can always do multiple changes in one ago: 43 | 44 | rename -s .tgz .tar.gz -s .tbz2 .tar.bz2 *.tar.* 45 | 46 | Note however that expressive options are order sensitive. The following would probably surprise you: 47 | 48 | rename -s foo bar -s bar baz * 49 | 50 | Since operations are cumulative, this would end up substituting (some of) the F matches in filenames with F! So pay attention to order. You may want to request a verbose dry run with C<-nv> for the first stab at a complex rename operation. 51 | 52 | rename -nv -s bar baz -s foo bar * 53 | 54 | You can combine the various expressive options to suit your needs. F.ex files from Microsoft(tm) Windows systems often have blanks and (sometimes nothing but) capital letters in their names. Let's say you have a bunch of such files to clean up, and you also want to move them to subdirectories based on extension. The following command should help, provided all directories already exist: 55 | 56 | rename -cz -e '$_ = "$1/$_" if /(\..*)\z/' * 57 | 58 | Again you need to pay attention to order sensitivity for expressive options. If you placed the C<-c> after the C<-e> in the above example, files with F<.zip> and F<.ZIP> extensions would be (attempted to be) moved to different directories because the directory name prefix would be added before the filenames were normalized. Once again, use verbose dry run requested using C<-nv> to get an idea of what exactly a complex rename operation is going to do. 59 | 60 | =head1 ARGUMENTS 61 | 62 | =over 4 63 | 64 | =item B<-h>, B<--help> 65 | 66 | See a synopsis. 67 | 68 | =item B<--man> 69 | 70 | Browse the manpage. 71 | 72 | =back 73 | 74 | =head1 OPTIONS 75 | 76 | =over 4 77 | 78 | =item B<-0>, B<--null> 79 | 80 | When reading file names from C, split on NUL bytes instead of newlines. This is useful in combination with GNU find's C<-print0> option, GNU grep's C<-Z> option, and GNU sort's C<-z> option, to name just a few. B 81 | 82 | =item B<-c>, B<--lower-case> 83 | 84 | Converts file names to all lower case. 85 | 86 | =item B<-C>, B<--upper-case> 87 | 88 | Converts file names to all upper case. 89 | 90 | =item B<-e>, B<--expr> 91 | 92 | The C argument to this option should be a Perl expression that assumes the filename in the C<$_> variable and modifies it for the filenames to be renamed. When no other C<-c>, C<-C>, C<-e>, C<-s>, or C<-z> options are given, you can omit the C<-e> from infront of the code. 93 | 94 | =item B<-g>, B<--glob> 95 | 96 | Glob filename arguments. This is useful if you're using a braindead shell such as F which won't expand wildcards on behalf of the user. 97 | 98 | =item B<-f>, B<--force> 99 | 100 | Rename even when a file with the destination name already exists. 101 | 102 | =item B<-i>, B<--interactive> 103 | 104 | Ask the user to confirm every action before it is taken. 105 | 106 | =item B<-k>, B<--backwards>, B<--reverse-order> 107 | 108 | Process the list of files in reverse order, last file first. This prevents conflicts when renaming files to names which are currently taken but would be freed later during the process of renaming. 109 | 110 | =item B<-l>, B<--symlink> 111 | 112 | Create symlinks from the new names to the existing ones, instead of renaming the files. B.> 113 | 114 | =item B<-L>, B<--hardlink> 115 | 116 | Create hard links from the new names to the existing ones, instead of renaming the files. B.> 117 | 118 | =item B<-n>, B<--dry-run>, B<--just-print> 119 | 120 | Show how the files would be renamed, but don't actually do anything. 121 | 122 | =item B<-s>, B<--subst>, B<--simple> 123 | 124 | Perform a simple textual substitution of C to C. The C and C parameters must immediately follow the argument. 125 | 126 | Quoting issues aside, this is equivalent to supplying a C<-e 's/\Qfrom/to/'>. 127 | 128 | =item B<-v>, B<--verbose> 129 | 130 | Print additional information about the operations (not) executed. 131 | 132 | =item B<-z>, B<--sanitize> 133 | 134 | Replaces consecutive blanks, shell meta characters, and control characters in filenames with underscores. 135 | 136 | =back 137 | 138 | =head1 SEE ALSO 139 | 140 | mv(1), perl(1), find(1), grep(1), sort(1) 141 | 142 | =head1 BUGS 143 | 144 | None currently known. 145 | 146 | =head1 AUTHORS 147 | 148 | Aristotle Pagaltzis 149 | 150 | Idea, inspiration and original code from Larry Wall and Robin Barker. 151 | 152 | =head1 COPYRIGHT 153 | 154 | This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself. 155 | 156 | =cut 157 | 158 | use Pod::Usage; 159 | use Getopt::Long 2.24, qw(:config bundling no_ignore_case no_auto_abbrev); 160 | 161 | use constant ERROR => do { bless \(my $l = 0), 'LOGLEVEL' }; 162 | use constant INFO => do { bless \(my $l = 1), 'LOGLEVEL' }; 163 | use constant DEBUG => do { bless \(my $l = 2), 'LOGLEVEL' }; 164 | use constant VERB_FOR => { 165 | link => { 166 | inf => 'link', 167 | pastp => 'linked', 168 | exec => sub { link shift, shift or die }, 169 | }, 170 | symlink => { 171 | inf => 'symlink', 172 | pastp => 'symlinked', 173 | exec => sub { symlink shift, shift or die }, 174 | }, 175 | rename => { 176 | inf => 'rename', 177 | pastp => 'renamed', 178 | exec => sub { rename shift, shift or die }, 179 | }, 180 | }; 181 | 182 | sub argv_to_subst_expr { 183 | my $modifier = shift || ''; 184 | pod2usage( -verbose => 1 ) if @ARGV < 2; 185 | my ($from, $to) = map quotemeta, splice @ARGV, 0, 2; 186 | # the ugly \${\""} construct is necessary because unknown backslash escapes are 187 | # not treated the same in pattern- vs doublequote-quoting context; only the 188 | # latter lets us do the right thing with problematic input like 189 | # ']{ool(haracter$' or maybe '>>' 190 | sprintf 's/\Q${\"%s"}/%s/%s', $from, $to, $modifier; 191 | } 192 | 193 | my @EXPR; 194 | 195 | GetOptions( 196 | 'h|help' => sub { pod2usage( -verbose => 1 ) }, 197 | 'man' => sub { pod2usage( -verbose => 2 ) }, 198 | '0|null' => \my $opt_null, 199 | 'c|lower-case' => sub { push @EXPR, 's/([[:upper:]]+)/\L$1/g' }, 200 | 'C|upper-case' => sub { push @EXPR, 's/([[:lower:]]+)/\U$1/g' }, 201 | 'e|expr=s' => \@EXPR, 202 | 'f|force' => \my $opt_force, 203 | 'g|glob' => \my $opt_glob, 204 | 'i|interactive' => \my $opt_interactive, 205 | 'k|backwards|reverse-order' => \my $opt_backwards, 206 | 'l|symlink' => \my $opt_symlink, 207 | 'L|hardlink' => \my $opt_hardlink, 208 | 'n|just-print|dry-run' => \my $opt_dryrun, 209 | 'p|mkpath|make-dirs' => \my $opt_mkpath, 210 | 'v|verbose+' => \(my $opt_verbose = 0), 211 | 'z|sanitize' => sub { push @EXPR, 's/[!"\$&()=?`*\';<>|_[:cntrl:][:blank:]]+/_/g' }, 212 | 's|subst|simple' => sub { push @EXPR, argv_to_subst_expr }, 213 | 'S|subst-global' => sub { push @EXPR, argv_to_subst_expr('g') }, 214 | ) or pod2usage( -verbose => 1 ); 215 | 216 | die "TODO" if $opt_mkpath; 217 | 218 | if(not @EXPR) { 219 | pod2usage( -verbose => 1 ) if not @ARGV or -e $ARGV[0]; 220 | push @EXPR, shift; 221 | } 222 | 223 | pod2usage( -verbose => 1 ) 224 | if ($opt_hardlink and $opt_symlink) 225 | or ($opt_null and @ARGV); 226 | 227 | ++$opt_verbose if $opt_dryrun; 228 | 229 | BEGIN { 230 | *CORE::GLOBAL::warn = sub { 231 | if(ref $_[0] eq 'LOGLEVEL') { 232 | my $msglevel = ${(shift)}; 233 | print "@_\n" if $opt_verbose >= $msglevel; 234 | return; 235 | } 236 | warn @_; 237 | }; 238 | } 239 | 240 | my $code = do { 241 | my $cat = "sub { ".join('; ', @EXPR)." }"; 242 | warn DEBUG, "Using expression: $cat"; 243 | 244 | my $evaled = eval $cat; 245 | die $@ if $@; 246 | die "Evaluation to subref failed. Check expression using -vn\n" 247 | unless 'CODE' eq ref $evaled; 248 | 249 | $evaled; 250 | }; 251 | 252 | my $verb = VERB_FOR->{ 253 | $opt_hardlink ? 'link' : 254 | $opt_symlink ? 'symlink' : 255 | do { 'rename' } 256 | }; 257 | 258 | if (!@ARGV) { 259 | warn INFO, "Reading filenames from STDIN"; 260 | @ARGV = do { 261 | if($opt_null) { 262 | warn INFO, "Splitting on NUL bytes"; 263 | local $/ = "\0"; 264 | } 265 | ; 266 | }; 267 | chomp @ARGV; 268 | } 269 | 270 | @ARGV = map glob, @ARGV if $opt_glob; 271 | 272 | @ARGV = reverse @ARGV if $opt_backwards; 273 | 274 | for (@ARGV) { 275 | my $old = $_; 276 | 277 | $code->(); 278 | 279 | if($old eq $_) { 280 | warn DEBUG, "'$old' unchanged"; 281 | next; 282 | } 283 | 284 | if(!$opt_force and -e) { 285 | warn ERROR, "'$old' not $verb->{pastp}: '$_' already exists"; 286 | next; 287 | } 288 | 289 | if($opt_dryrun) { 290 | warn INFO, "'$old' would be $verb->{pastp} to '$_'"; 291 | next; 292 | } 293 | 294 | if($opt_interactive) { 295 | print "\u$verb->{inf} '$old' to '$_'? [n] "; 296 | if( !~ /^y(?:es)?$/i) { 297 | warn DEBUG, "Skipping '$old'."; 298 | next; 299 | } 300 | } 301 | 302 | eval { $verb->{exec}($old, $_) }; 303 | 304 | if($@) { 305 | warn ERROR, "Can't $verb->{inf} '$old' to '$_': $!"; 306 | next; 307 | } 308 | 309 | warn INFO, "'$old' $verb->{pastp} to '$_'"; 310 | } 311 | -------------------------------------------------------------------------------- /vendor/rename/rename: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use strict; 3 | use warnings; 4 | 5 | =head1 NAME 6 | 7 | rename - renames multiple files 8 | 9 | =head1 SYNOPSIS 10 | 11 | F 12 | S> 13 | 14 | F 15 | S> 16 | 17 | F 18 | S> 19 | S> 20 | S> 21 | S> 22 | S> 23 | S> 24 | S> 25 | S> 26 | S> 27 | S> 28 | S> 29 | 30 | =head1 DESCRIPTION 31 | 32 | C renames the filenames supplied according to the rules specified. If a given filename is not modified, it will not be renamed. If no filenames are given on the command line, filenames will be read via standard input. 33 | 34 | For example, to rename all files matching C<*.bak> to strip the extension, you might say 35 | 36 | rename 's/\.bak$//' *.bak 37 | 38 | If are confident that none of the filenames has C<.bak> anywhere else than at the end, you can also use the much easier typed 39 | 40 | rename -s .bak '' *.bak 41 | 42 | You can always do multiple changes in one ago: 43 | 44 | rename -s .tgz .tar.gz -s .tbz2 .tar.bz2 *.tar.* 45 | 46 | Note however that expressive options are order sensitive. The following would probably surprise you: 47 | 48 | rename -s foo bar -s bar baz * 49 | 50 | Since operations are cumulative, this would end up substituting (some of) the F matches in filenames with F! So pay attention to order. You may want to request a verbose dry run with C<-nv> for the first stab at a complex rename operation. 51 | 52 | rename -nv -s bar baz -s foo bar * 53 | 54 | You can combine the various expressive options to suit your needs. F.ex files from Microsoft(tm) Windows systems often have blanks and (sometimes nothing but) capital letters in their names. Let's say you have a bunch of such files to clean up, and you also want to move them to subdirectories based on extension. The following command should help, provided all directories already exist: 55 | 56 | rename -cz -e '$_ = "$1/$_" if /(\..*)\z/' * 57 | 58 | Again you need to pay attention to order sensitivity for expressive options. If you placed the C<-c> after the C<-e> in the above example, files with F<.zip> and F<.ZIP> extensions would be (attempted to be) moved to different directories because the directory name prefix would be added before the filenames were normalized. Once again, use verbose dry run requested using C<-nv> to get an idea of what exactly a complex rename operation is going to do. 59 | 60 | =head1 ARGUMENTS 61 | 62 | =over 4 63 | 64 | =item B<-h>, B<--help> 65 | 66 | See a synopsis. 67 | 68 | =item B<--man> 69 | 70 | Browse the manpage. 71 | 72 | =back 73 | 74 | =head1 OPTIONS 75 | 76 | =over 4 77 | 78 | =item B<-0>, B<--null> 79 | 80 | When reading file names from C, split on NUL bytes instead of newlines. This is useful in combination with GNU find's C<-print0> option, GNU grep's C<-Z> option, and GNU sort's C<-z> option, to name just a few. B 81 | 82 | =item B<-c>, B<--lower-case> 83 | 84 | Converts file names to all lower case. 85 | 86 | =item B<-C>, B<--upper-case> 87 | 88 | Converts file names to all upper case. 89 | 90 | =item B<-e>, B<--expr> 91 | 92 | The C argument to this option should be a Perl expression that assumes the filename in the C<$_> variable and modifies it for the filenames to be renamed. When no other C<-c>, C<-C>, C<-e>, C<-s>, or C<-z> options are given, you can omit the C<-e> from infront of the code. 93 | 94 | =item B<-g>, B<--glob> 95 | 96 | Glob filename arguments. This is useful if you're using a braindead shell such as F which won't expand wildcards on behalf of the user. 97 | 98 | =item B<-f>, B<--force> 99 | 100 | Rename even when a file with the destination name already exists. 101 | 102 | =item B<-i>, B<--interactive> 103 | 104 | Ask the user to confirm every action before it is taken. 105 | 106 | =item B<-k>, B<--backwards>, B<--reverse-order> 107 | 108 | Process the list of files in reverse order, last file first. This prevents conflicts when renaming files to names which are currently taken but would be freed later during the process of renaming. 109 | 110 | =item B<-l>, B<--symlink> 111 | 112 | Create symlinks from the new names to the existing ones, instead of renaming the files. B.> 113 | 114 | =item B<-L>, B<--hardlink> 115 | 116 | Create hard links from the new names to the existing ones, instead of renaming the files. B.> 117 | 118 | =item B<-n>, B<--dry-run>, B<--just-print> 119 | 120 | Show how the files would be renamed, but don't actually do anything. 121 | 122 | =item B<-s>, B<--subst>, B<--simple> 123 | 124 | Perform a simple textual substitution of C to C. The C and C parameters must immediately follow the argument. 125 | 126 | Quoting issues aside, this is equivalent to supplying a C<-e 's/\Qfrom/to/'>. 127 | 128 | =item B<-v>, B<--verbose> 129 | 130 | Print additional information about the operations (not) executed. 131 | 132 | =item B<-z>, B<--sanitize> 133 | 134 | Replaces consecutive blanks, shell meta characters, and control characters in filenames with underscores. 135 | 136 | =back 137 | 138 | =head1 SEE ALSO 139 | 140 | mv(1), perl(1), find(1), grep(1), sort(1) 141 | 142 | =head1 BUGS 143 | 144 | None currently known. 145 | 146 | =head1 AUTHORS 147 | 148 | Aristotle Pagaltzis 149 | 150 | Idea, inspiration and original code from Larry Wall and Robin Barker. 151 | 152 | =head1 COPYRIGHT 153 | 154 | This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself. 155 | 156 | =cut 157 | 158 | use Pod::Usage; 159 | use Getopt::Long 2.24, qw(:config bundling no_ignore_case no_auto_abbrev); 160 | 161 | use constant ERROR => do { bless \(my $l = 0), 'LOGLEVEL' }; 162 | use constant INFO => do { bless \(my $l = 1), 'LOGLEVEL' }; 163 | use constant DEBUG => do { bless \(my $l = 2), 'LOGLEVEL' }; 164 | use constant VERB_FOR => { 165 | link => { 166 | inf => 'link', 167 | pastp => 'linked', 168 | exec => sub { link shift, shift or die }, 169 | }, 170 | symlink => { 171 | inf => 'symlink', 172 | pastp => 'symlinked', 173 | exec => sub { symlink shift, shift or die }, 174 | }, 175 | rename => { 176 | inf => 'rename', 177 | pastp => 'renamed', 178 | exec => sub { rename shift, shift or die }, 179 | }, 180 | }; 181 | 182 | sub argv_to_subst_expr { 183 | my $modifier = shift || ''; 184 | pod2usage( -verbose => 1 ) if @ARGV < 2; 185 | my ($from, $to) = map quotemeta, splice @ARGV, 0, 2; 186 | # the ugly \${\""} construct is necessary because unknown backslash escapes are 187 | # not treated the same in pattern- vs doublequote-quoting context; only the 188 | # latter lets us do the right thing with problematic input like 189 | # ']{ool(haracter$' or maybe '>>' 190 | sprintf 's/\Q${\"%s"}/%s/%s', $from, $to, $modifier; 191 | } 192 | 193 | my @EXPR; 194 | 195 | GetOptions( 196 | 'h|help' => sub { pod2usage( -verbose => 1 ) }, 197 | 'man' => sub { pod2usage( -verbose => 2 ) }, 198 | '0|null' => \my $opt_null, 199 | 'c|lower-case' => sub { push @EXPR, 's/([[:upper:]]+)/\L$1/g' }, 200 | 'C|upper-case' => sub { push @EXPR, 's/([[:lower:]]+)/\U$1/g' }, 201 | 'e|expr=s' => \@EXPR, 202 | 'f|force' => \my $opt_force, 203 | 'g|glob' => \my $opt_glob, 204 | 'i|interactive' => \my $opt_interactive, 205 | 'k|backwards|reverse-order' => \my $opt_backwards, 206 | 'l|symlink' => \my $opt_symlink, 207 | 'L|hardlink' => \my $opt_hardlink, 208 | 'n|just-print|dry-run' => \my $opt_dryrun, 209 | 'p|mkpath|make-dirs' => \my $opt_mkpath, 210 | 'v|verbose+' => \(my $opt_verbose = 0), 211 | 'z|sanitize' => sub { push @EXPR, 's/[!"\$&()=?`*\';<>|_[:cntrl:][:blank:]]+/_/g' }, 212 | 's|subst|simple' => sub { push @EXPR, argv_to_subst_expr }, 213 | 'S|subst-global' => sub { push @EXPR, argv_to_subst_expr('g') }, 214 | ) or pod2usage( -verbose => 1 ); 215 | 216 | die "TODO" if $opt_mkpath; 217 | 218 | if(not @EXPR) { 219 | pod2usage( -verbose => 1 ) if not @ARGV or -e $ARGV[0]; 220 | push @EXPR, shift; 221 | } 222 | 223 | pod2usage( -verbose => 1 ) 224 | if ($opt_hardlink and $opt_symlink) 225 | or ($opt_null and @ARGV); 226 | 227 | ++$opt_verbose if $opt_dryrun; 228 | 229 | BEGIN { 230 | *CORE::GLOBAL::warn = sub { 231 | if(ref $_[0] eq 'LOGLEVEL') { 232 | my $msglevel = ${(shift)}; 233 | print "@_\n" if $opt_verbose >= $msglevel; 234 | return; 235 | } 236 | warn @_; 237 | }; 238 | } 239 | 240 | my $code = do { 241 | my $cat = "sub { ".join('; ', @EXPR)." }"; 242 | warn DEBUG, "Using expression: $cat"; 243 | 244 | my $evaled = eval $cat; 245 | die $@ if $@; 246 | die "Evaluation to subref failed. Check expression using -vn\n" 247 | unless 'CODE' eq ref $evaled; 248 | 249 | $evaled; 250 | }; 251 | 252 | my $verb = VERB_FOR->{ 253 | $opt_hardlink ? 'link' : 254 | $opt_symlink ? 'symlink' : 255 | do { 'rename' } 256 | }; 257 | 258 | if (!@ARGV) { 259 | warn INFO, "Reading filenames from STDIN"; 260 | @ARGV = do { 261 | if($opt_null) { 262 | warn INFO, "Splitting on NUL bytes"; 263 | local $/ = "\0"; 264 | } 265 | ; 266 | }; 267 | chomp @ARGV; 268 | } 269 | 270 | @ARGV = map glob, @ARGV if $opt_glob; 271 | 272 | @ARGV = reverse @ARGV if $opt_backwards; 273 | 274 | for (@ARGV) { 275 | my $old = $_; 276 | 277 | $code->(); 278 | 279 | if($old eq $_) { 280 | warn DEBUG, "'$old' unchanged"; 281 | next; 282 | } 283 | 284 | if(!$opt_force and -e) { 285 | warn ERROR, "'$old' not $verb->{pastp}: '$_' already exists"; 286 | next; 287 | } 288 | 289 | if($opt_dryrun) { 290 | warn INFO, "'$old' would be $verb->{pastp} to '$_'"; 291 | next; 292 | } 293 | 294 | if($opt_interactive) { 295 | print "\u$verb->{inf} '$old' to '$_'? [n] "; 296 | if( !~ /^y(?:es)?$/i) { 297 | warn DEBUG, "Skipping '$old'."; 298 | next; 299 | } 300 | } 301 | 302 | eval { $verb->{exec}($old, $_) }; 303 | 304 | if($@) { 305 | warn ERROR, "Can't $verb->{inf} '$old' to '$_': $!"; 306 | next; 307 | } 308 | 309 | warn INFO, "'$old' $verb->{pastp} to '$_'"; 310 | } 311 | -------------------------------------------------------------------------------- /init/20_ubuntu_apt.sh: -------------------------------------------------------------------------------- 1 | # Ubuntu-only stuff. Abort if not Ubuntu. 2 | is_ubuntu || return 1 3 | 4 | apt_keys=() 5 | apt_source_files=() 6 | apt_source_texts=() 7 | apt_packages=() 8 | deb_installed=() 9 | deb_sources=() 10 | 11 | installers_path="$DOTFILES/caches/installers" 12 | 13 | # Ubuntu distro release name, eg. "xenial" 14 | release_name=$(lsb_release -c | awk '{print $2}') 15 | 16 | function add_ppa() { 17 | apt_source_texts+=($1) 18 | IFS=':/' eval 'local parts=($1)' 19 | apt_source_files+=("${parts[1]}-ubuntu-${parts[2]}-$release_name") 20 | } 21 | 22 | ############################# 23 | # WHAT DO WE NEED TO INSTALL? 24 | ############################# 25 | 26 | # Misc. 27 | apt_packages+=( 28 | awscli 29 | build-essential 30 | cmatrix 31 | cowsay 32 | curl 33 | docker.io 34 | docker-compose 35 | git-core 36 | groff 37 | hollywood 38 | htop 39 | id3tool 40 | imagemagick 41 | jq 42 | mercurial 43 | nmap 44 | postgresql 45 | python-pip 46 | silversearcher-ag 47 | sl 48 | telnet 49 | thefuck 50 | tree 51 | ) 52 | 53 | apt_packages+=(vim) 54 | is_ubuntu_desktop && apt_packages+=(vim-gnome) 55 | 56 | # https://github.com/neovim/neovim/wiki/Installing-Neovim 57 | add_ppa ppa:neovim-ppa/stable 58 | apt_packages+=(neovim) 59 | 60 | # https://launchpad.net/~stebbins/+archive/ubuntu/handbrake-releases 61 | add_ppa ppa:stebbins/handbrake-releases 62 | apt_packages+=(handbrake-cli) 63 | is_ubuntu_desktop && apt_packages+=(handbrake-gtk) 64 | 65 | # https://github.com/rvm/ubuntu_rvm 66 | add_ppa ppa:rael-gc/rvm 67 | apt_packages+=(rvm) 68 | 69 | # https://github.com/rbenv/ruby-build/wiki 70 | apt_packages+=( 71 | autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev 72 | libncurses5-dev libffi-dev libgdbm3 libgdbm-dev zlib1g-dev 73 | ) 74 | 75 | # https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-ansible-on-ubuntu-16-04 76 | add_ppa ppa:ansible/ansible 77 | apt_packages+=(ansible) 78 | 79 | # http://tipsonubuntu.com/2016/09/13/vim-8-0-released-install-ubuntu-16-04/ 80 | add_ppa ppa:jonathonf/vim 81 | apt_packages+=(vim) 82 | 83 | # https://launchpad.net/~hnakamur/+archive/ubuntu/tmux 84 | add_ppa ppa:hnakamur/tmux 85 | 86 | # https://github.com/greymd/tmux-xpanes 87 | add_ppa ppa:greymd/tmux-xpanes 88 | apt_packages+=(tmux-xpanes) 89 | 90 | if is_ubuntu_desktop; then 91 | # http://www.omgubuntu.co.uk/2016/06/install-latest-arc-gtk-theme-ubuntu-16-04 92 | # apt_keys+=(http://download.opensuse.org/repositories/home:Horst3180/xUbuntu_16.04/Release.key) 93 | # apt_source_files+=(arc-theme) 94 | # apt_source_texts+=("deb http://download.opensuse.org/repositories/home:/Horst3180/xUbuntu_16.04/ /") 95 | # apt_packages+=(arc-theme) 96 | 97 | add_ppa ppa:fossfreedom/arc-gtk-theme-daily 98 | apt_packages+=(arc-theme) 99 | 100 | # https://www.techrepublic.com/article/how-to-connect-a-linux-machine-to-google-cloud-print/ 101 | # sudo /usr/share/cloudprint-cups/setupcloudprint.py 102 | add_ppa ppa:simon-cadman/niftyrepo 103 | apt_packages+=(cupscloudprint) 104 | 105 | # https://github.com/tagplus5/vscode-ppa 106 | apt_keys+=(https://tagplus5.github.io/vscode-ppa/ubuntu/gpg.key) 107 | apt_source_files+=(vscode.list) 108 | apt_source_texts+=("deb https://tagplus5.github.io/vscode-ppa/ubuntu ./") 109 | apt_packages+=(code code-insiders) 110 | 111 | # https://www.ubuntuupdates.org/ppa/google_chrome 112 | apt_keys+=(https://dl-ssl.google.com/linux/linux_signing_key.pub) 113 | apt_source_files+=(google-chrome) 114 | apt_source_texts+=("deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main") 115 | apt_packages+=(google-chrome-stable) 116 | 117 | # https://www.charlesproxy.com/documentation/installation/apt-repository/ 118 | apt_keys+=(https://www.charlesproxy.com/packages/apt/PublicKey) 119 | apt_source_files+=(charles) 120 | apt_source_texts+=("deb https://www.charlesproxy.com/packages/apt/ charles-proxy3 main") 121 | apt_packages+=(charles-proxy) 122 | 123 | # https://github.com/aluxian/Messenger-for-Desktop#linux 124 | apt_keys+=('--keyserver pool.sks-keyservers.net --recv 6DDA23616E3FE905FFDA152AE61DA9241537994D') 125 | apt_source_files+=(aluxian) 126 | apt_source_texts+=("deb https://dl.bintray.com/aluxian/deb/ beta main") 127 | apt_packages+=(messengerfordesktop) 128 | 129 | # https://www.spotify.com/us/download/linux/ 130 | apt_keys+=('--keyserver hkp://keyserver.ubuntu.com:80 --recv-keys BBEBDCB318AD50EC6865090613B00F1FD2C19886') 131 | apt_source_files+=(spotify) 132 | apt_source_texts+=("deb http://repository.spotify.com stable non-free") 133 | apt_packages+=(spotify-client) 134 | 135 | # https://tecadmin.net/install-oracle-virtualbox-on-ubuntu/ 136 | apt_keys+=(https://www.virtualbox.org/download/oracle_vbox_2016.asc) 137 | apt_source_files+=(virtualbox) 138 | apt_source_texts+=("deb http://download.virtualbox.org/virtualbox/debian $release_name contrib") 139 | apt_packages+=(virtualbox-5.1) 140 | 141 | # https://www.skype.com/en/download-skype/skype-for-linux/ 142 | # https://community.skype.com/t5/Linux/Skype-for-Linux-Beta-signatures-couldn-t-be-verified-because-the/td-p/4645756 143 | apt_keys+=(https://repo.skype.com/data/SKYPE-GPG-KEY) 144 | apt_source_files+=(skype-stable) 145 | apt_source_texts+=("deb https://repo.skype.com/deb stable main") 146 | apt_packages+=(skypeforlinux) 147 | 148 | # http://askubuntu.com/a/190674 149 | add_ppa ppa:webupd8team/java 150 | apt_packages+=(oracle-java8-installer) 151 | function preinstall_oracle-java8-installer() { 152 | echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections 153 | echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections 154 | } 155 | 156 | # https://github.com/colinkeenan/silentcast/#ubuntu 157 | # https://github.com/colinkeenan/silentcast/#ubuntu-linux-full-install 158 | add_ppa ppa:sethj/silentcast 159 | add_ppa ppa:webupd8team/y-ppa-manager 160 | apt_packages+=( 161 | libav-tools x11-xserver-utils xdotool wininfo wmctrl python-gobject python-cairo xdg-utils yad 162 | silentcast 163 | ) 164 | 165 | # Misc 166 | apt_packages+=(adb fastboot) 167 | apt_packages+=( 168 | chromium-browser 169 | fonts-mplus 170 | gnome-tweak-tool 171 | k4dirstat 172 | rofi 173 | network-manager-openconnect 174 | network-manager-openconnect-gnome 175 | openssh-server 176 | shutter 177 | unity-tweak-tool 178 | vlc 179 | xclip 180 | zenmap 181 | ) 182 | 183 | # Manage online accounts via "gnome-control-center" in launcher 184 | apt_packages+=(gnome-control-center gnome-online-accounts) 185 | 186 | # https://github.com/mitchellh/vagrant/issues/7411 187 | deb_installed+=(/usr/bin/vagrant) 188 | deb_sources+=(https://releases.hashicorp.com/vagrant/1.9.2/vagrant_1.9.2_x86_64.deb) 189 | # https://github.com/vagrant-libvirt/vagrant-libvirt/issues/575 190 | # apt_packages+=(vagrant) 191 | # function postinstall_vagrant() { 192 | # sudo sed -i'' "s/Specification.all = nil/Specification.reset/" /usr/lib/ruby/vendor_ruby/vagrant/bundler.rb 193 | # } 194 | 195 | # https://be5invis.github.io/Iosevka/ 196 | # https://launchpad.net/~laurent-boulard/+archive/ubuntu/fonts 197 | add_ppa ppa:laurent-boulard/fonts 198 | apt_packages+=(fonts-iosevka) 199 | 200 | # https://launchpad.net/grub-customizer 201 | add_ppa ppa:danielrichter2007/grub-customizer 202 | apt_packages+=(grub-customizer) 203 | 204 | # https://support.gitkraken.com/how-to-install 205 | deb_installed+=(/usr/bin/gitkraken) 206 | deb_sources+=(https://release.gitkraken.com/linux/gitkraken-amd64.deb) 207 | 208 | # http://www.get-notes.com/linux-download-debian-ubuntu 209 | apt_packages+=(libqt5concurrent5) 210 | deb_installed+=(/usr/bin/notes) 211 | deb_sources+=("https://github.com/nuttyartist/notes/releases/download/v1.0.0/notes_1.0.0_amd64-$release_name.deb") 212 | 213 | # https://www.dropbox.com/install-linux 214 | apt_packages+=(python-gtk2 python-gpgme) 215 | deb_installed+=(/usr/bin/dropbox) 216 | deb_sources+=("https://www.dropbox.com/download?dl=packages/ubuntu/dropbox_2015.10.28_amd64.deb") 217 | 218 | # http://askubuntu.com/a/852727 219 | apt_packages+=(cabextract) 220 | deb_installed+=(/usr/share/fonts/truetype/msttcorefonts) 221 | deb_sources+=(deb_source_msttcorefonts) 222 | function deb_source_msttcorefonts() { 223 | echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | sudo debconf-set-selections 224 | echo http://ftp.debian.org/debian/pool/contrib/m/msttcorefonts/ttf-mscorefonts-installer_3.6_all.deb 225 | } 226 | 227 | # https://slack.com/downloads/instructions/linux 228 | deb_installed+=(/usr/bin/slack) 229 | deb_sources+=(https://downloads.slack-edge.com/linux_releases/slack-desktop-2.5.2-amd64.deb) 230 | 231 | # https://discordapp.com/download 232 | deb_installed+=(/usr/bin/discord) 233 | deb_sources+=("https://discordapp.com/api/download?platform=linux&format=deb") 234 | 235 | # http://askubuntu.com/questions/854480/how-to-install-the-steam-client/854481#854481 236 | apt_packages+=(python-apt) 237 | deb_installed+=(/usr/bin/steam) 238 | deb_sources+=(deb_source_steam) 239 | function deb_source_steam() { 240 | local steam_root steam_file 241 | steam_root=http://repo.steampowered.com/steam/pool/steam/s/steam/ 242 | steam_file="$(wget -q -O- "$steam_root?C=M;O=D" | sed -En '/steam-launcher/{s/.*href="([^"]+)".*/\1/;p;q;}')" 243 | echo "$steam_root$steam_file" 244 | } 245 | # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=772598 246 | # apt_packages+=(steam) 247 | # function preinstall_steam() { 248 | # echo steam steam/question select I AGREE | sudo debconf-set-selections 249 | # echo steam steam/license note | sudo debconf-set-selections 250 | # } 251 | fi 252 | 253 | function other_stuff() { 254 | # Install Git Extras 255 | if [[ ! "$(type -P git-extras)" ]]; then 256 | e_header "Installing Git Extras" 257 | ( 258 | cd $DOTFILES/vendor/git-extras && 259 | sudo make install 260 | ) 261 | fi 262 | # Install misc bins from zip file. 263 | install_from_zip ngrok 'https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip' 264 | install_from_zip terraform 'https://releases.hashicorp.com/terraform/0.9.2/terraform_0.9.2_linux_amd64.zip' 265 | } 266 | 267 | #################### 268 | # ACTUALLY DO THINGS 269 | #################### 270 | 271 | # Add APT keys. 272 | keys_cache=$DOTFILES/caches/init/apt_keys 273 | IFS=$'\n' GLOBIGNORE='*' command eval 'setdiff_cur=($(<$keys_cache))' 274 | setdiff_new=("${apt_keys[@]}"); setdiff; apt_keys=("${setdiff_out[@]}") 275 | unset setdiff_new setdiff_cur setdiff_out 276 | 277 | if (( ${#apt_keys[@]} > 0 )); then 278 | e_header "Adding APT keys (${#apt_keys[@]})" 279 | for key in "${apt_keys[@]}"; do 280 | e_arrow "$key" 281 | if [[ "$key" =~ -- ]]; then 282 | sudo apt-key adv $key 283 | else 284 | wget -qO- $key | sudo apt-key add - 285 | fi && \ 286 | echo "$key" >> $keys_cache 287 | done 288 | fi 289 | 290 | # Add APT sources. 291 | function __temp() { [[ ! -e /etc/apt/sources.list.d/$1.list ]]; } 292 | source_i=($(array_filter_i apt_source_files __temp)) 293 | 294 | if (( ${#source_i[@]} > 0 )); then 295 | e_header "Adding APT sources (${#source_i[@]})" 296 | for i in "${source_i[@]}"; do 297 | source_file=${apt_source_files[i]} 298 | source_text=${apt_source_texts[i]} 299 | if [[ "$source_text" =~ ppa: ]]; then 300 | e_arrow "$source_text" 301 | sudo add-apt-repository -y $source_text 302 | else 303 | e_arrow "$source_file" 304 | sudo sh -c "echo '$source_text' > /etc/apt/sources.list.d/$source_file.list" 305 | fi 306 | done 307 | fi 308 | 309 | # Update APT. 310 | e_header "Updating APT" 311 | sudo apt-get -qq update 312 | 313 | # Only do a dist-upgrade on initial install, otherwise do an upgrade. 314 | e_header "Upgrading APT" 315 | if is_dotfiles_bin; then 316 | sudo apt-get -qy upgrade 317 | else 318 | sudo apt-get -qy dist-upgrade 319 | fi 320 | 321 | # Install APT packages. 322 | installed_apt_packages="$(dpkg --get-selections | grep -v deinstall | awk 'BEGIN{FS="[\t:]"}{print $1}' | uniq)" 323 | apt_packages=($(setdiff "${apt_packages[*]}" "$installed_apt_packages")) 324 | 325 | if (( ${#apt_packages[@]} > 0 )); then 326 | e_header "Installing APT packages (${#apt_packages[@]})" 327 | for package in "${apt_packages[@]}"; do 328 | e_arrow "$package" 329 | [[ "$(type -t preinstall_$package)" == function ]] && preinstall_$package 330 | sudo apt-get -qq install "$package" && \ 331 | [[ "$(type -t postinstall_$package)" == function ]] && postinstall_$package 332 | done 333 | fi 334 | 335 | # Install debs via dpkg 336 | function __temp() { [[ ! -e "$1" ]]; } 337 | deb_installed_i=($(array_filter_i deb_installed __temp)) 338 | 339 | if (( ${#deb_installed_i[@]} > 0 )); then 340 | mkdir -p "$installers_path" 341 | e_header "Installing debs (${#deb_installed_i[@]})" 342 | for i in "${deb_installed_i[@]}"; do 343 | e_arrow "${deb_installed[i]}" 344 | deb="${deb_sources[i]}" 345 | [[ "$(type -t "$deb")" == function ]] && deb="$($deb)" 346 | installer_file="$installers_path/$(echo "$deb" | sed 's#.*/##')" 347 | wget -O "$installer_file" "$deb" 348 | sudo dpkg -i "$installer_file" 349 | done 350 | fi 351 | 352 | # install bins from zip file 353 | function install_from_zip() { 354 | local name=$1 url=$2 bins b zip tmp 355 | shift 2; bins=("$@"); [[ "${#bins[@]}" == 0 ]] && bins=($name) 356 | if [[ ! "$(which $name)" ]]; then 357 | mkdir -p "$installers_path" 358 | e_header "Installing $name" 359 | zip="$installers_path/$(echo "$url" | sed 's#.*/##')" 360 | wget -O "$zip" "$url" 361 | tmp=$(mktemp -d) 362 | unzip "$zip" -d "$tmp" 363 | for b in "${bins[@]}"; do 364 | sudo cp "$tmp/$b" "/usr/local/bin/$(basename $b)" 365 | done 366 | rm -rf $tmp 367 | fi 368 | } 369 | 370 | # Run anything else that may need to be run. 371 | type -t other_stuff >/dev/null && other_stuff 372 | -------------------------------------------------------------------------------- /link/.vimrc: -------------------------------------------------------------------------------- 1 | " Change mapleader 2 | let mapleader="," 3 | let maplocalleader="\\" 4 | 5 | " Move more naturally up/down when wrapping is enabled. 6 | nnoremap j gj 7 | nnoremap k gk 8 | 9 | " Map F1 to Esc because I'm sick of seeing help pop up 10 | map 11 | imap 12 | 13 | " Local dirs 14 | if !has('win32') && !empty($DOTFILES) 15 | set backupdir=$DOTFILES/caches/vim 16 | set directory=$DOTFILES/caches/vim 17 | set undodir=$DOTFILES/caches/vim 18 | let g:netrw_home = expand('$DOTFILES/caches/vim') 19 | endif 20 | 21 | " Create vimrc autocmd group and remove any existing vimrc autocmds, 22 | " in case .vimrc is re-sourced. 23 | augroup vimrc 24 | autocmd! 25 | augroup END 26 | 27 | " Per-mode cursor shape 28 | " http://vim.wikia.com/wiki/Change_cursor_shape_in_different_modes 29 | if has('unix') 30 | let &t_SI = "\[6 q" 31 | let &t_SR = "\[4 q" 32 | let &t_EI = "\[2 q" 33 | elseif has('macuinx') 34 | if exists('$TMUX') 35 | let &t_SI = "\Ptmux;\\]50;CursorShape=1\x7\\\" 36 | let &t_SR = "\Ptmux;\\]50;CursorShape=2\x7\\\" 37 | let &t_EI = "\Ptmux;\\]50;CursorShape=0\x7\\\" 38 | else 39 | let &t_SI = "\]50;CursorShape=1\x7" 40 | let &t_SR = "\]50;CursorShape=2\x7" 41 | let &t_EI = "\]50;CursorShape=0\x7" 42 | endif 43 | endif 44 | 45 | " Theme / Syntax highlighting 46 | 47 | " " Show trailing whitespace. 48 | autocmd vimrc ColorScheme * :hi ExtraWhitespace ctermbg=red guibg=red 49 | 50 | " Visual settings 51 | set cursorline " Highlight current line 52 | set number " Enable line numbers. 53 | set showtabline=2 " Always show tab bar. 54 | set relativenumber " Use relative line numbers. Current line is still in status bar. 55 | set title " Show the filename in the window titlebar. 56 | set nowrap " Do not wrap lines. 57 | set noshowmode " Don't show the current mode (airline.vim takes care of us) 58 | set laststatus=2 " Always show status line 59 | 60 | " Show absolute numbers in insert mode, otherwise relative line numbers. 61 | autocmd vimrc InsertEnter * :set norelativenumber 62 | autocmd vimrc InsertLeave * :set relativenumber 63 | 64 | set textwidth=80 65 | " Show 120 columns but make it obvious where 80 characters is 66 | let &colorcolumn="81,".join(range(120,999),",") 67 | 68 | " Scrolling 69 | set scrolloff=3 " Start scrolling three lines before horizontal border of window. 70 | set sidescrolloff=3 " Start scrolling three columns before vertical border of window. 71 | 72 | " Indentation 73 | set autoindent " Copy indent from last line when starting new line. 74 | set shiftwidth=2 " The # of spaces for indenting. 75 | set smarttab " At start of line, inserts shiftwidth spaces, deletes shiftwidth spaces. 76 | set softtabstop=2 " Tab key results in 2 spaces 77 | set tabstop=2 " Tabs indent only 2 spaces 78 | set expandtab " Expand tabs to spaces 79 | 80 | " Reformatting 81 | set nojoinspaces " Only insert single space after a '.', '?' and '!' with a join command. 82 | 83 | " Toggle show tabs and trailing spaces (,v) 84 | if has('win32') 85 | set listchars=tab:>\ ,trail:.,eol:$,nbsp:_,extends:>,precedes:< 86 | else 87 | set listchars=tab:▸\ ,trail:·,eol:¬,nbsp:_,extends:»,precedes:« 88 | endif 89 | "set fillchars=fold:- 90 | nnoremap v :call ToggleInvisibles() 91 | 92 | " Extra whitespace 93 | autocmd vimrc BufWinEnter * :2match ExtraWhitespaceMatch /\s\+$/ 94 | autocmd vimrc InsertEnter * :2match ExtraWhitespaceMatch /\s\+\%#\@ss :call StripExtraWhiteSpace() 118 | 119 | " Search / replace 120 | set gdefault " By default add g flag to search/replace. Add g to toggle. 121 | set hlsearch " Highlight searches 122 | set incsearch " Highlight dynamically as pattern is typed. 123 | set ignorecase " Ignore case of searches. 124 | set smartcase " Ignore 'ignorecase' if search pattern contains uppercase characters. 125 | 126 | " Clear last search 127 | map / :nohlsearch 128 | 129 | " Ignore things 130 | set wildignore+=*.jpg,*.jpeg,*.gif,*.png,*.gif,*.psd,*.o,*.obj,*.min.js 131 | set wildignore+=*/bower_components/*,*/node_modules/* 132 | set wildignore+=*/vendor/*,*/.git/*,*/.hg/*,*/.svn/*,*/log/*,*/tmp/* 133 | 134 | " Vim commands 135 | set hidden " When a buffer is brought to foreground, remember undo history and marks. 136 | set report=0 " Show all changes. 137 | set mouse=a " Enable mouse in all modes. 138 | set ttymouse=xterm2 " Ensure mouse works inside tmux 139 | set shortmess+=I " Hide intro menu. 140 | 141 | " Splits 142 | set splitbelow " New split goes below 143 | set splitright " New split goes right 144 | 145 | let g:tmux_navigator_no_mappings = 1 146 | let g:tmux_navigator_disable_when_zoomed = 1 147 | " Ctrl-arrows select split 148 | nnoremap :TmuxNavigateUp 149 | nnoremap :TmuxNavigateDown 150 | nnoremap :TmuxNavigateLeft 151 | nnoremap :TmuxNavigateRight 152 | " This seems to be necessary in gnome-terminal 153 | nnoremap  :TmuxNavigateUp 154 | nnoremap  :TmuxNavigateDown 155 | nnoremap  :TmuxNavigateLeft 156 | nnoremap  :TmuxNavigateRight 157 | " Ctrl-J/K/L/H select split 158 | nnoremap :TmuxNavigateUp 159 | nnoremap :TmuxNavigateDown 160 | nnoremap :TmuxNavigateLeft 161 | nnoremap :TmuxNavigateRight 162 | " Previous split 163 | nnoremap :TmuxNavigatePrevious 164 | 165 | " Buffer navigation 166 | nnoremap b :CtrlPBuffer " List other buffers 167 | map :b# " Switch between the last two files 168 | map gb :bnext " Next buffer 169 | map gB :bprev " Prev buffer 170 | 171 | " Switch buffers with Alt-Left/Right 172 | nmap :bprev 173 | nmap :bnext 174 | vmap :bprev 175 | vmap :bnext 176 | nmap  :bprev 177 | nmap  :bnext 178 | vmap  :bprev 179 | vmap  :bnext 180 | 181 | " Resize panes with Shift-Left/Right/Up/Down 182 | nnoremap :resize +1 183 | nnoremap :resize -1 184 | nnoremap :vertical resize +1 185 | nnoremap :vertical resize -1 186 | nnoremap  :resize +1 187 | nnoremap  :resize -1 188 | nnoremap  :vertical resize +1 189 | nnoremap  :vertical resize -1 190 | 191 | " Ctrl-J, the opposite of Shift-J 192 | nnoremap ik:.s/\s\+$//ej^ 193 | 194 | " Jump to buffer number 1-9 with , or 1-99 with gb 195 | let c = 1 196 | while c <= 99 197 | if c < 10 198 | " execute "nnoremap " . c . " :" . c . "b" 199 | execute "nmap " . c . " AirlineSelectTab" . c 200 | endif 201 | execute "nnoremap " . c . "gb :" . c . "b" 202 | let c += 1 203 | endwhile 204 | 205 | " Fix page up and down 206 | map 207 | map 208 | imap 209 | imap 210 | 211 | " Use Q for formatting the current paragraph (or selection) 212 | " vmap Q gq 213 | " nmap Q gqap 214 | 215 | " Allow saving of files as sudo when I forgot to start vim using sudo. 216 | cmap w!! w !sudo tee > /dev/null % 217 | 218 | " When editing a file, always jump to the last known cursor position. Don't do 219 | " it for commit messages, when the position is invalid, or when inside an event 220 | " handler (happens when dropping a file on gvim). 221 | autocmd vimrc BufReadPost * 222 | \ if &ft != 'gitcommit' && line("'\"") > 0 && line("'\"") <= line("$") | 223 | \ exe "normal g`\"" | 224 | \ endif 225 | 226 | " The :Src command will source .vimrc & .gvimrc files 227 | command! Src :call SourceConfigs() 228 | 229 | if !exists("*SourceConfigs") 230 | function! SourceConfigs() 231 | let files = ".vimrc" 232 | source $MYVIMRC 233 | if has("gui_running") 234 | let files .= ", .gvimrc" 235 | source $MYGVIMRC 236 | endif 237 | echom "Sourced " . files 238 | endfunction 239 | endif 240 | 241 | " FILE TYPES 242 | 243 | autocmd vimrc BufRead .vimrc,*.vim set keywordprg=:help 244 | autocmd vimrc BufRead,BufNewFile *.md set filetype=markdown 245 | autocmd vimrc BufRead,BufNewFile *.tmpl set filetype=html 246 | autocmd vimrc FileType sql :let b:vimpipe_command="psql mydatabase" 247 | autocmd vimrc FileType sql :let b:vimpipe_filetype="postgresql" 248 | 249 | " PLUGINS 250 | 251 | " Airline 252 | let g:airline_powerline_fonts = 1 " TODO: detect this? 253 | let g:airline#extensions#tabline#enabled = 1 254 | let g:airline#extensions#tabline#buffer_nr_format = '%s ' 255 | let g:airline#extensions#tabline#buffer_nr_show = 1 256 | " let g:airline#extensions#tabline#fnamecollapse = 0 257 | " let g:airline#extensions#tabline#fnamemod = ':t' 258 | 259 | let g:airline#extensions#tabline#tab_nr_type = 1 " tab number 260 | let g:airline#extensions#tabline#show_tab_nr = 1 261 | let g:airline#extensions#tabline#formatter = 'default' 262 | let g:airline#extensions#tabline#fnametruncate = 16 263 | let g:airline#extensions#tabline#fnamecollapse = 2 264 | let g:airline#extensions#tabline#buffer_idx_mode = 1 265 | let g:airline#extensions#syntastic#enabled = 1 266 | 267 | " NERDTree 268 | let NERDTreeShowHidden = 1 269 | let NERDTreeMouseMode = 2 270 | let NERDTreeMinimalUI = 1 271 | map n :NERDTreeToggle 272 | autocmd vimrc StdinReadPre * let s:std_in=1 273 | " If no file or directory arguments are specified, open NERDtree. 274 | " If a directory is specified as the only argument, open it in NERDTree. 275 | autocmd vimrc VimEnter * 276 | \ if argc() == 0 && !exists("s:std_in") | 277 | \ NERDTree | 278 | \ elseif argc() == 1 && isdirectory(argv(0)) | 279 | \ bd | 280 | \ exec 'cd' fnameescape(argv(0)) | 281 | \ NERDTree | 282 | \ end 283 | 284 | " Signify 285 | let g:signify_vcs_list = ['git', 'hg', 'svn'] 286 | 287 | " CtrlP.vim 288 | " map p 289 | " map r :CtrlPMRUFiles 290 | " let g:ctrlp_match_window_bottom = 0 " Show at top of window 291 | let g:ctrlp_show_hidden = 1 292 | 293 | " Vim-pipe 294 | let g:vimpipe_invoke_map = 'r' 295 | let g:vimpipe_close_map = 'p' 296 | 297 | " DBExt 298 | let g:dbext_default_profile_PG_skillsbot = 'type=pgsql:host=rds.bocoup.com:dbname=skillsbot-dev:user=skillsbot-dev' 299 | let g:dbext_default_profile = 'PG_skillsbot' 300 | 301 | " Indent Guides 302 | let g:indent_guides_start_level = 1 303 | let g:indent_guides_guide_size = 1 304 | 305 | " Mustache/handlebars 306 | let g:mustache_abbreviations = 1 307 | 308 | " Ack/ag 309 | if executable('ag') 310 | let g:ackprg = 'ag --vimgrep' 311 | endif 312 | let g:ack_autoclose = 1 313 | nnoremap a :Ack! 314 | 315 | " Multiple cursors 316 | nnoremap :MultipleCursorsFind / 317 | vnoremap :MultipleCursorsFind / 318 | nnoremap j :MultipleCursorsFind / 319 | vnoremap j :MultipleCursorsFind / 320 | 321 | " Ale 322 | let g:ale_sign_column_always = 1 323 | let g:airline#extensions#ale#enabled = 1 324 | let g:ale_fixers = { 325 | \ 'javascript': ['prettier-eslint'], 326 | \} 327 | " let g:ale_fix_on_save = 1 328 | 329 | " Syntastic 330 | let g:syntastic_always_populate_loc_list = 1 331 | let g:syntastic_auto_loc_list = 1 332 | let g:syntastic_check_on_open = 1 333 | let g:syntastic_check_on_wq = 0 334 | let g:syntastic_javascript_checkers = ['eslint'] 335 | let g:syntastic_javascript_eslint_exe = 'node_modules/.bin/eslint' 336 | let g:syntastic_json_checkers = ['jsonlint'] 337 | 338 | " Emmet 339 | " imap emmet#expandAbbrIntelligent("\") 340 | let g:user_emmet_settings = { 341 | \ 'javascript.jsx' : { 342 | \ 'extends' : 'jsx', 343 | \ }, 344 | \} 345 | 346 | " https://github.com/junegunn/vim-plug 347 | " Reload .vimrc and :PlugInstall to install plugins. 348 | call plug#begin('~/.vim/plugged') 349 | Plug 'tpope/vim-sensible' " Core config 350 | Plug 'rafi/awesome-vim-colorschemes' " Color schemes 351 | Plug 'bling/vim-airline' " Status bar 352 | Plug 'tpope/vim-surround' " Quotes / parens / tags 353 | Plug 'tpope/vim-fugitive' " Git wrapper 354 | Plug 'tpope/vim-rhubarb' " Github helper 355 | Plug 'tpope/vim-vinegar' " File browser (?) 356 | Plug 'tpope/vim-repeat' " Enable . repeat in plugins 357 | Plug 'tpope/vim-commentary' " (gcc) Better commenting 358 | Plug 'tpope/vim-unimpaired' " Pairs of mappings with [ ] 359 | Plug 'tpope/vim-eunuch' " Unix helpers 360 | Plug 'scrooloose/nerdtree' " (,n) File browser 361 | Plug 'ctrlpvim/ctrlp.vim' " (C-P)(,b) Fuzzy file/buffer/mru/tag finder 362 | if v:version < 705 && !has('patch-7.4.785') 363 | Plug 'vim-scripts/PreserveNoEOL' " Preserve missing final newline on save 364 | endif 365 | Plug 'editorconfig/editorconfig-vim' " EditorConfig 366 | Plug 'nathanaelkane/vim-indent-guides' " (,ig) Visible indent guides 367 | Plug 'pangloss/vim-javascript', {'for': 'javascript'} 368 | Plug 'mxw/vim-jsx', {'for': 'javascript.jsx'} " React JSX highlighting/indenting 369 | Plug 'AndrewRadev/splitjoin.vim' " (gS)(gJ) Split/join multi-line statements 370 | Plug 'mhinz/vim-signify' " VCS status in the sign column 371 | Plug 'mattn/emmet-vim' " (C-Y,) Expand HTML abbreviations 372 | Plug 'chase/vim-ansible-yaml' " Ansible YAML highlighting 373 | Plug 'klen/python-mode', {'for': 'python'} " Python mode 374 | Plug 'terryma/vim-multiple-cursors' " (C-N) Multiple selections/cursors 375 | Plug 'vim-scripts/dbext.vim' 376 | Plug 'krisajenkins/vim-pipe' " (,r) Run a buffer through a command 377 | Plug 'krisajenkins/vim-postgresql-syntax' 378 | Plug 'jparise/vim-graphql' " GraphQL 379 | Plug 'mileszs/ack.vim' 380 | Plug 'tmux-plugins/vim-tmux' 381 | Plug 'christoomey/vim-tmux-navigator' 382 | Plug 'elzr/vim-json' 383 | Plug 'othree/eregex.vim' 384 | if v:version >= 800 385 | Plug 'w0rp/ale' 386 | else 387 | Plug 'vim-syntastic/syntastic' 388 | endif 389 | call plug#end() 390 | 391 | let g:gruvbox_bold = 1 392 | let g:gruvbox_italic = 1 393 | let g:gruvbox_italicize_comments = 1 394 | let g:gruvbox_contrast_dark = 'medium' 395 | set background=dark 396 | colorscheme gruvbox 397 | --------------------------------------------------------------------------------