├── gitexcludes ├── config ├── nvim │ ├── lua │ │ ├── plugins │ │ │ ├── lualine.lua │ │ │ ├── dirvish.lua │ │ │ ├── trouble.lua │ │ │ ├── gruvqueen.lua │ │ │ ├── cmp.lua │ │ │ └── lspconfig.lua │ │ ├── disabled.lua │ │ ├── keymaps.lua │ │ ├── options.lua │ │ └── util.lua │ ├── init.lua │ └── plugin │ │ └── starsearch.vim └── alacritty │ └── alacritty.yml ├── .gitignore ├── scripts ├── install_lscolors.sh ├── hooks │ ├── vim.sh │ ├── colordiff.sh │ ├── ssh.sh │ ├── linux.sh │ ├── homebrew.sh │ ├── grep.sh │ ├── tmux.sh │ ├── fzf.sh │ ├── ls.sh │ └── prompt.sh ├── install_vim_plugins.sh ├── install_neovim.sh ├── install_asdf.sh ├── install_bash_completion.sh ├── git_user_email.sh └── install_aws_cli.sh ├── entries ├── hammerspoon │ ├── Spoons │ │ ├── TapCtrlForEscape.spoon │ │ │ ├── keyboard.png │ │ │ └── init.lua │ │ ├── WindowManagement.spoon │ │ │ └── init.lua │ │ └── FadeLogo.spoon │ │ │ ├── init.lua │ │ │ └── docs.json │ └── init.lua ├── lesskey ├── inputrc ├── bashrc ├── bash_profile ├── gitconfig └── tmux.conf ├── requirements.txt ├── README.md ├── gitmessage ├── xterm-256color.ti ├── tmux-256color.ti ├── ssh_config └── install.sh /gitexcludes: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | .Spotlight-V100 4 | .Trashes 5 | ehthumbs.db 6 | Thumbs.db 7 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/lualine.lua: -------------------------------------------------------------------------------- 1 | require("lualine").setup({ 2 | options = {theme = "auto"} 3 | }) 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | entries/ssh/** 2 | !entries/ssh/config 3 | config/nvim/plugin/packer_compiled.lua 4 | local.sh 5 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/dirvish.lua: -------------------------------------------------------------------------------- 1 | vim.g.dirvish_mode = ':sort r /[^\/]$/|silent keeppatterns g/\.pyc$/d _' 2 | vim.g.dirvish_relative_paths = 1 3 | -------------------------------------------------------------------------------- /scripts/install_lscolors.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | curl -sSLo ~/.lscolors https://raw.githubusercontent.com/trapd00r/LS_COLORS/master/LS_COLORS 4 | -------------------------------------------------------------------------------- /entries/hammerspoon/Spoons/TapCtrlForEscape.spoon/keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnalley/dotfiles/HEAD/entries/hammerspoon/Spoons/TapCtrlForEscape.spoon/keyboard.png -------------------------------------------------------------------------------- /config/nvim/lua/plugins/trouble.lua: -------------------------------------------------------------------------------- 1 | require("trouble").setup{ 2 | auto_open = true, 3 | auto_close = true, 4 | -- use_lsp_diagnostic_signs = true 5 | mode = "document_diagnostics", 6 | } 7 | -------------------------------------------------------------------------------- /scripts/hooks/vim.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | # prefer nvim fallback to vim 4 | for EDITOR in nvim vim; do 5 | inpath "${EDITOR}" && export EDITOR && break 6 | done 7 | -------------------------------------------------------------------------------- /scripts/hooks/colordiff.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | inpath colordiff && colorterm || return 4 | 5 | # enable color output for diff 6 | diff() { command diff "$@" | colordiff | less -R; } 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | black 2 | faker 3 | flake8 4 | ipython 5 | isort 6 | jedi-language-server 7 | memory_profiler 8 | neovim 9 | numpy 10 | pandas 11 | pdbpp 12 | requests 13 | smart-open 14 | tqdm 15 | twine 16 | wheel 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | dotfiles 2 | ========= 3 | 4 | Install 5 | ------- 6 | 7 | Clone: 8 | 9 | git clone git://github.com/jnalley/dotfiles.git ~/.dotfiles 10 | 11 | Create symlinks and install vim plugins: 12 | 13 | ~/.dotfiles/install.sh 14 | -------------------------------------------------------------------------------- /scripts/hooks/ssh.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | # no ssh config 4 | [[ -s ~/.ssh/config ]] || return 1 5 | 6 | # always ignore global ssh config 7 | ssh() { 8 | TERM="${TERM/tmux/xterm}" command ssh -F ~/.ssh/config "$@" 9 | } 10 | -------------------------------------------------------------------------------- /gitmessage: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 50-character subject line 4 | # 5 | # 72-character wrapped longer description. This should answer: 6 | # 7 | # * Why was this change necessary? 8 | # * How does it address the problem? 9 | # * Are there any side effects? 10 | # 11 | # Include a link to the ticket, if any. 12 | -------------------------------------------------------------------------------- /entries/lesskey: -------------------------------------------------------------------------------- 1 | \n undo-hilite 2 | #env 3 | LESS=-RXFi 4 | LESS_TERMCAP_mb= 5 | LESS_TERMCAP_md= 6 | LESS_TERMCAP_me=(B 7 | LESS_TERMCAP_mh= 8 | LESS_TERMCAP_mr= 9 | LESS_TERMCAP_se=(B 10 | LESS_TERMCAP_so= 11 | LESS_TERMCAP_ue=(B 12 | LESS_TERMCAP_us= 13 | -------------------------------------------------------------------------------- /scripts/hooks/linux.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | [[ "$(uname -s)" == *Linux* ]] || return 4 | 5 | # running x windows? 6 | [[ -n "${DISPLAY}" ]] || return 7 | 8 | # skip if xscape is already running 9 | pidof xcape > /dev/null 2>&1 && return 10 | 11 | # swap capslock and CTRL 12 | setxkbmap -option ctrl:nocaps 13 | inpath xcape || return 14 | 15 | # tap CTRL for ESC 16 | xcape -e 'Control_L=Escape' 17 | -------------------------------------------------------------------------------- /xterm-256color.ti: -------------------------------------------------------------------------------- 1 | # fix italics, dim and backspace/delete 2 | # see: 3 | # https://github.com/neovim/neovim/issues/2048 4 | # https://github.com/tmux/tmux/blob/caa9073/FAQ#L355,#L384 5 | xterm-256color|xterm with 256 colors and italic, 6 | sitm=\E[3m, ritm=\E[23m, kbs=\177, 7 | use=xterm-256color, 8 | dim=\E[2m, 9 | sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, 10 | -------------------------------------------------------------------------------- /config/nvim/lua/disabled.lua: -------------------------------------------------------------------------------- 1 | vim.tbl_map( 2 | function(p) 3 | vim.g["loaded_" .. p] = vim.endswith(p, "provider") and 0 or 1 4 | end, 5 | { 6 | "2html_plugin", 7 | "gzip", 8 | "matchit", 9 | "netrw", 10 | "netrwPlugin", 11 | "perl_provider", 12 | "python_provider", 13 | "tar", 14 | "tarPlugin", 15 | "vimball", 16 | "vimballPlugin", 17 | "zip", 18 | "zipPlugin", 19 | } 20 | ) 21 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/gruvqueen.lua: -------------------------------------------------------------------------------- 1 | local errormsg = {fg="red", bg="NONE", style="NONE"} 2 | 3 | require("gruvqueen").setup{ 4 | config = { 5 | transparent_background = true 6 | }, 7 | base = { 8 | Folded = {fg="#008080", bg="NONE"}, 9 | SpellBad = {fg="red"}, 10 | VertSplit = {fg="#353535", bg="NONE", style="NONE"}, 11 | Error = errormsg, 12 | ErrorMsg = errormsg, 13 | NvimInternalError = errormsg, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tmux-256color.ti: -------------------------------------------------------------------------------- 1 | # fix italics, dim and backspace/delete 2 | # see: 3 | # https://github.com/neovim/neovim/issues/2048 4 | # https://github.com/tmux/tmux/blob/caa9073/FAQ#L355,#L384 5 | tmux-256color|tmux with 256 colors, 6 | ritm=\E[23m, rmso=\E[27m, sitm=\E[3m, smso=\E[7m, Ms@, kbs=\177, 7 | use=xterm-256color, use=screen-256color, 8 | dim=\E[2m, 9 | sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m, 10 | -------------------------------------------------------------------------------- /scripts/hooks/homebrew.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | inpath brew || return 4 | 5 | export HOMEBREW_PREFIX="$(brew --prefix)" 6 | # use gnu versions if they are available 7 | # - brew install coreutils gnu-tar findutils 8 | PATH="${HOMEBREW_PREFIX}/opt/coreutils/libexec/gnubin:${PATH}" 9 | MANPATH="${HOMEBREW_PREFIX}/opt/coreutils/libexec/gnuman:${MANPATH##/usr/share/man:}:/usr/share/man" 10 | export PATH MANPATH 11 | 12 | # prevent github rate limiting 13 | source ~/.homebrew.key 2>/dev/null 14 | -------------------------------------------------------------------------------- /scripts/hooks/grep.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | # pick the best recursive grep option available 4 | for _ in 'rg' 'ag'; do 5 | # shellcheck disable=SC2139 6 | inpath $_ && alias g="$_ --ignore-case" && break 7 | done 8 | 9 | # use a function wrapper if we are stuck with plain grep 10 | if ! alias g > /dev/null 2>&1; then 11 | function g() { grep -inRHI "$@" .; } 12 | fi 13 | 14 | # enable color for GNU grep 15 | if command grep --version | grep -qi 'GNU'; then 16 | alias grep='grep --color=auto' 17 | fi 18 | -------------------------------------------------------------------------------- /scripts/hooks/tmux.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | # prevent nested tmux/screen sessions and skip for vscode 4 | [[ ${TERM} == @(tmux-*|screen-*) || ${TERM_PROGRAM} == vscode ]] && return 5 | 6 | TMUXCMD="$(command -v tmux)" 7 | 8 | [[ -x "${TMUXCMD}" ]] || return 9 | 10 | # connect to existing session 11 | if "${TMUXCMD}" has-session 2> /dev/null; then 12 | # only if it has no clients 13 | [[ -z $(${TMUXCMD} list-clients) ]] && \ 14 | exec "${TMUXCMD}" attach 15 | else 16 | # create new session 17 | exec "${TMUXCMD}" new 18 | fi 19 | -------------------------------------------------------------------------------- /scripts/install_vim_plugins.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | die() { echo "$*" && exit 1; } 4 | inpath() { command -v "${1}" >/dev/null || die "Missing ${1}!"; } 5 | 6 | inpath nvim || die "nvim is missing!" 7 | 8 | plug_path=~/.dotfiles/config/nvim/autoload/plug.vim 9 | plug_url='https://raw.github.com/junegunn/vim-plug/master/plug.vim' 10 | 11 | [[ -s "${plug_path}" ]] && 12 | die "Plug is already installed" 13 | 14 | (curl --create-dirs -fsLo "${plug_path}" ${plug_url} && 15 | command nvim --headless +PlugInstall +PlugClean! +qa) || 16 | die "Failed to install plugins!" 17 | -------------------------------------------------------------------------------- /config/nvim/init.lua: -------------------------------------------------------------------------------- 1 | require "options" 2 | require "keymaps" 3 | 4 | local icons = {"kyazdani42/nvim-web-devicons", opt = true} 5 | 6 | require("util").plugins{ 7 | {"christoomey/vim-tmux-navigator"}, 8 | {"Murtaza-Udaipurwala/gruvqueen"}, 9 | {"b3nj5m1n/kommentary"}, 10 | {"folke/trouble.nvim", requires = icons}, 11 | {"hoob3rt/lualine.nvim", requires = icons}, 12 | {"justinmk/vim-dirvish"}, 13 | {'neovim/nvim-lspconfig'}, 14 | {"neovim/nvim-lspconfig"}, 15 | {"hrsh7th/nvim-cmp", requires = {"hrsh7th/cmp-buffer"}}, 16 | {"hrsh7th/cmp-nvim-lsp"}, 17 | {"tpope/vim-characterize"}, 18 | {"tpope/vim-fugitive"}, 19 | {"tpope/vim-repeat"}, 20 | {"tpope/vim-surround"}, 21 | {"tpope/vim-unimpaired"}, 22 | } 23 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/cmp.lua: -------------------------------------------------------------------------------- 1 | local cmp = require "cmp" 2 | 3 | vim.o.completeopt = 'menuone,noselect' 4 | 5 | cmp.setup { 6 | mapping = { 7 | [''] = cmp.mapping(cmp.mapping.select_next_item(), {'i', 's'}), 8 | [''] = cmp.mapping.select_prev_item(), 9 | [''] = cmp.mapping.select_next_item(), 10 | [''] = cmp.mapping.scroll_docs(-4), 11 | [''] = cmp.mapping.scroll_docs(4), 12 | [''] = cmp.mapping.complete(), 13 | [''] = cmp.mapping.close(), 14 | [''] = cmp.mapping.confirm({ 15 | behavior = cmp.ConfirmBehavior.Insert, 16 | select = true, 17 | }) 18 | }, 19 | sources = { 20 | { name = "buffer" }, 21 | { name = "nvim_lsp" }, 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /entries/inputrc: -------------------------------------------------------------------------------- 1 | set bell-style none 2 | set bind-tty-special-chars off 3 | set blink-matching-paren on 4 | set colored-completion-prefix on 5 | set colored-stats on 6 | set completion-ignore-case on 7 | set completion-map-case on 8 | set echo-control-characters off 9 | set editing-mode vi 10 | set expand-tilde off 11 | set keyseq-timeout 300 12 | set mark-directories on 13 | set mark-symlinked-directories on 14 | set menu-complete-display-prefix on 15 | set show-all-if-ambiguous on 16 | set show-all-if-unmodified on 17 | set skip-completed-text on 18 | set visible-stats on 19 | 20 | # set show-mode-in-prompt on 21 | # set vi-ins-mode-string "[I]" 22 | # set vi-cmd-mode-string "[N]" 23 | 24 | "\C-a\C-l": clear-screen 25 | "\C-x\C-r": re-read-init-file 26 | -------------------------------------------------------------------------------- /entries/bashrc: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | # stop here if this is not an interactive shell 4 | [[ $- == *i* ]] || return 5 | 6 | inpath() { command -v "${1}" >/dev/null; } 7 | colorterm() { 8 | local colors=$(tput colors 2>/dev/null) 9 | [[ ${colors:-0} -gt 2 ]] 10 | } 11 | 12 | # report the status of terminated background jobs immediately 13 | set -o notify 14 | 15 | # date in the format YYYYMMDDHHMMSS (ISO 8601) 16 | alias mydate="date +'%G%m%d%H%M%S'" 17 | alias e='${EDITOR}' 18 | inpath htop && alias top=htop 19 | 20 | for _ in ~/.dotfiles/scripts/hooks/*.sh; do 21 | source "$_" 22 | done 23 | 24 | source ~/.asdf/asdf.sh 2>/dev/null 25 | 26 | source ~/.local/etc/profile.d/bash_completion.sh 2>/dev/null 27 | 28 | source ~/.dotfiles/local.sh 2>/dev/null 29 | -------------------------------------------------------------------------------- /config/nvim/lua/keymaps.lua: -------------------------------------------------------------------------------- 1 | local u = require("util") 2 | 3 | -- choose buffer 4 | u.nnoremap("", ":buffers:buffer") 5 | 6 | -- clear highlighted search 7 | u.nnoremap("", ":nohlsearch") 8 | 9 | -- visual shifting (does not exit Visual mode) 10 | u.vnoremap("<", "", ">gv") 12 | 13 | -- wrapped lines goes down/up to next row, rather than next line in file. 14 | u.nnoremap("j", "gj") 15 | u.nnoremap("k", "gk") 16 | 17 | -- execute default register. 18 | u.nnoremap("Q", "@q") 19 | 20 | -- edit config 21 | u.nnoremap("v", ":e! $MYVIMRC") 22 | 23 | -- auto indent pasted text 24 | u.nnoremap("p", "gp=`]") 25 | u.nnoremap("P", "gP=`]") 26 | 27 | -- previous buffer 28 | u.nnoremap("", ":b#") 29 | 30 | -- format buffer 31 | u.nnoremap( 32 | "ff", ":lua vim.lsp.buf.formatting_seq_sync()", 33 | {silent = true} 34 | ) 35 | -------------------------------------------------------------------------------- /scripts/install_neovim.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | NVIM_VERSION="${NVIM_VERSION:-stable}" 4 | 5 | url="https://github.com/neovim/neovim/releases/download/${NVIM_VERSION}" 6 | 7 | die() { echo "$*" && exit 1; } 8 | inpath() { command -v "${1}" >/dev/null; } 9 | 10 | inpath curl || die "Missing curl!" 11 | inpath git || die "Missing git!" 12 | 13 | case "$(uname -s)" in 14 | Darwin) 15 | filename=nvim-macos.tar.gz 16 | ;; 17 | Linux) 18 | filename=nvim-linux64.tar.gz 19 | ;; 20 | *) 21 | die "Unsupported OS!" 22 | ;; 23 | esac 24 | 25 | mkdir -p "${HOME}/.local" || 26 | die "Failed to create ~/.local" 27 | 28 | curl -sSL "${url}/${filename}" | 29 | tar -C "${HOME}/.local" -xz --strip-components=1 -f - || 30 | die "Failed to install Neovim!" 31 | 32 | git clone https://github.com/wbthomason/packer.nvim \ 33 | ~/.local/share/nvim/site/pack/packer/start/packer.nvim 34 | 35 | nvim --headless -c 'autocmd User PackerComplete quitall' -c 'PackerSync' 36 | -------------------------------------------------------------------------------- /ssh_config: -------------------------------------------------------------------------------- 1 | # vim: set ft=sshconfig:ts=2:sw=2:noet:nowrap 2 | 3 | LogLevel ERROR 4 | TCPKeepAlive no 5 | ServerAliveInterval 60 6 | HashKnownHosts no 7 | NoHostAuthenticationForLocalhost yes 8 | ControlMaster auto 9 | ControlPersist 1 10 | ControlPath ~/.ssh/.%C 11 | GlobalKnownHostsFile ~/.ssh/known_hosts 12 | UserKnownHostsFile /dev/null 13 | 14 | ## I don't always add host keys to my known_host file... 15 | ## But when I do - I do it manually with 'ssh-keyscan ' 16 | ## 17 | ## Swapping the roles of GlobalKnownHostsFile and UserKnownHostsFile allows me 18 | ## to manually maintain my known_hosts file rather than have ssh prompt me to 19 | ## add host keys for every host I happen to login to. I then manually add 20 | ## important hosts to ~/.ssh/known_hosts using ssh-keyscan. 21 | 22 | ## bastion host example 23 | # Match host !*bastion* exec "echo %h | grep -q '*host behind bastion regex*'" 24 | # ProxyJump bastion.host 25 | 26 | Include private 27 | 28 | ## defaults 29 | Host * 30 | CheckHostIP no 31 | ForwardX11 no 32 | ForwardAgent no 33 | StrictHostKeyChecking no 34 | GSSAPIAuthentication no 35 | -------------------------------------------------------------------------------- /scripts/install_asdf.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | readonly ASDF_VERSION='v0.8.1' 4 | readonly ASDF_URL='https://github.com/asdf-vm/asdf.git' 5 | 6 | NODEJS_VERSION='14.17.5' # LTS 7 | 8 | readonly -A PLUGINS=( 9 | [python]="${PYTHON_VERSION:-latest}" 10 | [nodejs]="${NODEJS_VERSION:-latest}" 11 | [ruby]="${RUBY_VERSION:-latest}" 12 | [lua]="${LUA_VERSION:-latest}" 13 | ) 14 | 15 | die() { echo "$*" && exit 1; } 16 | have() { command -v "${1}" >/dev/null || die "Missing: ${1}"; } 17 | 18 | have git 19 | have brew # Dependencies will be automatically installed by Homebrew. 20 | 21 | if [[ ! -d ~/.asdf ]]; then 22 | (git -c advice.detachedHead=false \ 23 | clone "${ASDF_URL}" ~/.asdf \ 24 | --single-branch --branch "${ASDF_VERSION}" && 25 | git -C ~/.asdf switch -c "${ASDF_VERSION}") || 26 | die "Failed to clone ${ASDF_URL}" 27 | fi 28 | 29 | source ~/.asdf/asdf.sh 30 | 31 | for plugin in "${!PLUGINS[@]}"; do 32 | echo "Installing: ${plugin} ${PLUGINS[$plugin]}" 33 | asdf plugin-add "${plugin}" 34 | asdf install "${plugin}" "${PLUGINS[$plugin]}" 35 | asdf global "${plugin}" "${PLUGINS[$plugin]}" 36 | done 37 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | die() { echo "$*" && exit 1; } 4 | 5 | # gnu vs bsd ln :-( 6 | command ln --version 2>/dev/null | grep -qi 'GNU' && 7 | params='-vsnf' || params='-vshf' 8 | 9 | EXISTING=$(mktemp -d ~/dotfiles.XXXXX) 10 | 11 | mkdir -p ~/.config ~/.ssh 12 | 13 | # save existing ssh config 14 | [[ ! -L ~/.ssh/config && -s ~/.ssh/config ]] && 15 | mv ~/.ssh/config "${EXISTING}/" 16 | 17 | # link to ssh config 18 | ln "${params}" ../.dotfiles/ssh_config ~/.ssh/config 19 | 20 | # link entries and config 21 | for file in ~/.dotfiles/entries/* ~/.dotfiles/config/*; do 22 | entry=${file#*.dotfiles/} 23 | entry=${entry#entries/} 24 | 25 | # if file exists and is not a symlink move it to the temporary directory 26 | if [[ ! -L "${HOME}/.${entry}" && -e "${HOME}/.${entry}" ]]; then 27 | [[ ${entry} == *config/* ]] && mkdir -p "${EXISTING}/.config" 28 | mv -v "${HOME}/.${entry}" "${EXISTING}/" 29 | fi 30 | 31 | prefix='.dotfiles/entries' 32 | [[ ${entry} == *config/* ]] && prefix='../.dotfiles' 33 | 34 | ln "${params}" "${prefix}/${entry}" "${HOME}/.${entry}" 35 | done 36 | 37 | # fails if the directory contains files 38 | if ! rmdir "${EXISTING}" 2>/dev/null; then 39 | echo "Existing files moved to ${EXISTING}" 40 | fi 41 | -------------------------------------------------------------------------------- /scripts/hooks/fzf.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | inpath fzf || return 4 | 5 | export FZF_DEFAULT_OPTS='--height 30% --border' 6 | 7 | inpath tree && export FZF_ALT_C_OPTS="--preview 'tree -C {} | head -200'" 8 | 9 | [[ -d "${HOMEBREW_PREFIX}" ]] && 10 | source "${HOMEBREW_PREFIX}/opt/fzf/shell/key-bindings.bash" 11 | 12 | inpath fd || return 0 13 | 14 | # --files: List files that would be searched but do not search 15 | # --no-ignore: Do not respect .gitignore, etc... 16 | # --hidden: Search hidden files and folders 17 | # --follow: Follow symlinks 18 | # --glob: Additional conditions for search (in this case ignore everything in the .git/ folder) 19 | export FZF_DEFAULT_COMMAND='fd --type f --exclude .git' 20 | export FZF_CTRL_T_COMMAND="${FZF_DEFAULT_COMMAND}" 21 | 22 | # Use fd (https://github.com/sharkdp/fd) instead of the default find 23 | # command for listing path candidates. 24 | # - The first argument to the function ($1) is the base path to start traversal 25 | # - See the source code (completion.{bash,zsh}) for the details. 26 | _fzf_compgen_path() { 27 | fd --hidden --follow --exclude ".git" . "$1" 28 | } 29 | 30 | # Use fd to generate the list for directory completion 31 | _fzf_compgen_dir() { 32 | fd --type d --hidden --follow --exclude ".git" . "$1" 33 | } 34 | -------------------------------------------------------------------------------- /config/nvim/lua/options.lua: -------------------------------------------------------------------------------- 1 | local vim = vim 2 | local o = vim.opt 3 | 4 | require("disabled") 5 | 6 | -- set leader to SPACE 7 | vim.g.mapleader = " " 8 | 9 | -- tabs/spaces defaults 10 | o.expandtab = true 11 | o.shiftwidth = 2 12 | o.softtabstop = 2 13 | o.tabstop = 2 14 | 15 | o.background = "dark" 16 | o.colorcolumn = "80" 17 | o.diffopt = "vertical" 18 | o.fillchars = { vert="│", fold="‒" } 19 | o.foldmethod = "marker" 20 | o.hidden = true 21 | o.history = 500 22 | o.ignorecase = true 23 | o.infercase = true 24 | o.joinspaces = false 25 | o.lazyredraw = true 26 | o.list = true 27 | o.listchars = { 28 | tab = "▸ ", 29 | extends ="❯", 30 | precedes ="❮", 31 | nbsp = "⌴", 32 | trail = "•" 33 | } 34 | o.matchpairs:append("<:>") 35 | o.mouse = "" 36 | o.number = false 37 | o.numberwidth = 5 38 | o.shortmess:append("I", "c") 39 | o.showbreak = "↪" 40 | o.showmode = false 41 | o.showtabline = 1 42 | o.smartcase = true 43 | o.splitbelow = true 44 | o.splitright = true 45 | o.termguicolors = true 46 | o.ttimeout = true 47 | o.ttimeoutlen = -1 48 | o.virtualedit = "block" 49 | o.whichwrap = "b,s,h,l,<,>,[,]" 50 | o.winminheight = 0 51 | o.wrap = false 52 | o.wildignore:append { 53 | "*.a", 54 | "*.bak", 55 | "*.gem", 56 | "*.o", 57 | "*.obj", 58 | "*.pyc", 59 | "*/.git/*", 60 | "*~" 61 | } 62 | -------------------------------------------------------------------------------- /config/nvim/plugin/starsearch.vim: -------------------------------------------------------------------------------- 1 | " Name: Star search 2 | " Author: Name5566 3 | " Version: 0.1.1 4 | 5 | if exists('loaded_starsearch') 6 | finish 7 | endif 8 | let loaded_starsearch = 1 9 | 10 | let s:savedCpo = &cpo 11 | set cpo&vim 12 | 13 | function! s:VStarsearch_searchCWord() 14 | let wordStr = expand("") 15 | if strlen(wordStr) == 0 16 | echohl ErrorMsg 17 | echo 'E348: No string under cursor' 18 | echohl NONE 19 | return 20 | endif 21 | 22 | if wordStr[0] =~ '\<' 23 | let @/ = '\<' . wordStr . '\>' 24 | else 25 | let @/ = wordStr 26 | endif 27 | 28 | let savedUnnamed = @" 29 | let savedS = @s 30 | normal! "syiw 31 | if wordStr != @s 32 | normal! w 33 | endif 34 | let @s = savedS 35 | let @" = savedUnnamed 36 | endfunction 37 | 38 | " https://github.com/bronson/vim-visual-star-search/ 39 | function! s:VStarsearch_searchVWord() 40 | let savedUnnamed = @" 41 | let savedS = @s 42 | normal! gv"sy 43 | let @/ = '\V' . substitute(escape(@s, '\'), '\n', '\\n', 'g') 44 | let @s = savedS 45 | let @" = savedUnnamed 46 | endfunction 47 | 48 | nnoremap * :call VStarsearch_searchCWord():set hls 49 | vnoremap * :call VStarsearch_searchVWord():set hls 50 | 51 | let &cpo = s:savedCpo 52 | -------------------------------------------------------------------------------- /scripts/hooks/ls.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | [[ -s ~/.lscolors ]] || return 1 4 | 5 | for _ in dircolors gdircolors; do 6 | inpath $_ && eval "$($_ -b ~/.lscolors)" 7 | done 8 | 9 | unalias ll 2>/dev/null 10 | unset -f ll 2>/dev/null 11 | 12 | if inpath exa; then 13 | ll() { 14 | exa -laF \ 15 | --group-directories-first \ 16 | --no-filesize \ 17 | --no-permissions \ 18 | --octal-permissions \ 19 | --sort Name \ 20 | --time-style long-iso "$@" 21 | } 22 | elif command ls --version 2>/dev/null | grep -qi 'GNU'; then 23 | # depends on gnu ls 24 | ll() { 25 | local extra=() 26 | [[ -z $* ]] && extra+=('--dereference') 27 | colorterm && extra+=('--color=always') 28 | command ls -ov \ 29 | --almost-all \ 30 | --escape \ 31 | --classify \ 32 | --human-readable \ 33 | --group-directories-first \ 34 | --literal \ 35 | --time-style=+'%G:%m:%d %T' \ 36 | "${extra[@]}" "$@" | awk \ 37 | '{ 38 | k=0;for(i=0;i<=8;i++) 39 | k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i)); 40 | if(k)printf("[%0o]",k);$1="";$2="";s=$4;$4="";print 41 | }' | grep -v '^[[:space:]]*$' 42 | } 43 | alias ls='command ls --color=auto' 44 | else 45 | # fallback to safe options 46 | alias ll="command ls -AbFho" 47 | fi 48 | -------------------------------------------------------------------------------- /entries/hammerspoon/Spoons/WindowManagement.spoon/init.lua: -------------------------------------------------------------------------------- 1 | local obj = {} 2 | obj.__index = obj 3 | 4 | obj.name = "WindowManagement" 5 | obj.version = "0.1" 6 | obj.author = "Jon Nalley " 7 | obj.homepage = "https://github.com/jnalley/dotfiles" 8 | obj.license = "MIT - https://opensource.org/licenses/MIT" 9 | 10 | local function moveToUnit(unit) 11 | hs.window.focusedWindow():moveToUnit(unit) 12 | end 13 | 14 | local function bind_hotkey(action, modifiers, key) 15 | end 16 | 17 | function obj:init() 18 | hs.grid.setGrid("2x2") 19 | hs.grid.ui.showExtraKeys = true 20 | hs.hotkey.bind({"alt", "cmd"}, "G", function() hs.grid.show() end) 21 | end 22 | 23 | function obj:bindHotKeys(mapping) 24 | for _,action in ipairs{"left", "right", "maximize"} do 25 | if mapping[action] ~= nil then 26 | bind_hotkey( 27 | (action:gsub("^%l", string.upper)), 28 | mapping[action][1], 29 | mapping[action][2] 30 | ) 31 | end 32 | end 33 | end 34 | 35 | 36 | hs.hotkey.bind({"alt", "cmd"}, "Left", 37 | hs.fnutils.partial(moveToUnit, hs.layout.left50) 38 | -- 50% vertical 39 | -- hs.fnutils.partial(moveToUnit, hs.geometry.unitrect(0,0,0.5,0.5)) 40 | ) 41 | hs.hotkey.bind({"alt", "cmd"}, "Right", 42 | hs.fnutils.partial(moveToUnit, hs.layout.right50) 43 | ) 44 | hs.hotkey.bind({"alt", "cmd"}, "Up", 45 | function() hs.window.frontmostWindow():maximize() end 46 | ) 47 | -------------------------------------------------------------------------------- /config/nvim/lua/util.lua: -------------------------------------------------------------------------------- 1 | local m = {} 2 | 3 | local function _keymap(mode, combo, mapping, opts) 4 | local options = {noremap = true} 5 | if opts then 6 | options = vim.tbl_extend("force", options, opts) 7 | end 8 | vim.api.nvim_set_keymap(mode, combo, mapping, options) 9 | end 10 | 11 | function m.partial(f, ...) 12 | local args = {...} 13 | return function(...) 14 | return f(unpack(args), ...) 15 | end 16 | end 17 | 18 | function m.plugins(plugins) 19 | local config = { 20 | display = { 21 | open_fn = function() 22 | return require("packer.util").float({border = "single"}) 23 | end 24 | }, 25 | profile = { 26 | enable = true, 27 | threshold = 1 28 | } 29 | } 30 | 31 | local function packer(use) 32 | use "wbthomason/packer.nvim" 33 | for _, args in ipairs(plugins) do 34 | local plugin = args[1] 35 | local cfg = 36 | plugin:gsub("(.*/)(.*)", "%2"):gsub("^nvim%-", ""):gsub("%.nvim$", ""):gsub( 37 | "-", 38 | "_" 39 | ) 40 | local path = 41 | string.format("%s/lua/plugins/%s.lua", vim.fn.stdpath("config"), cfg) 42 | if vim.loop.fs_stat(path) then 43 | args["config"] = string.format([[require("plugins/%s")]], cfg) 44 | end 45 | use(args) 46 | end 47 | end 48 | 49 | require("packer").startup {packer, config = config} 50 | end 51 | 52 | m.noremap = m.partial(_keymap, "") 53 | m.nnoremap = m.partial(_keymap, "n") 54 | m.vnoremap = m.partial(_keymap, "v") 55 | 56 | return m 57 | -------------------------------------------------------------------------------- /scripts/install_bash_completion.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # - Install bash completion from source - 4 | # 5 | # Although bash completion is generally available through packages, (e.g. 6 | # homebrew, apt) these packages can be quite outdated. More recent versions 7 | # of bash completion supports dynamic loading which prevents potential delay 8 | # when starting new shells. 9 | 10 | RAW_GIT_URL='https://raw.githubusercontent.com' 11 | 12 | : "${VERSION:=2.11}" 13 | : "${DESTDIR:=${HOME}/.local}" 14 | : "${BASE_URL:=https://github.com/scop/bash-completion/releases/download/}" 15 | 16 | BASH_COMPLETION_URL="${BASE_URL}/${VERSION}/bash-completion-${VERSION}.tar.xz" 17 | 18 | declare -A extras=( 19 | [git]="${RAW_GIT_URL}/git/git/master/contrib/completion/git-completion.bash" 20 | ) 21 | 22 | die() { echo -e "$*" ; exit 1 ; } 23 | 24 | tmp=$(mktemp -d -t tmp.XXXXX) || \ 25 | die "Failed to create temporary directory!" 26 | 27 | # shellcheck disable=SC2064 28 | trap "rm -r ${tmp}" EXIT 29 | 30 | curl -sSL "${BASH_COMPLETION_URL}" | \ 31 | tar -C "${tmp}" -xJ --strip-components=1 || \ 32 | die "Failed to download: ${BASH_COMPLETION_URL}" 33 | 34 | (cd "${tmp}" && ./configure --prefix="${DESTDIR}" && make install) || \ 35 | die "Failed to install bash-completion-${VERSION}!" 36 | 37 | [[ -d "${DESTDIR}/share/bash-completion/completions" ]] || \ 38 | die "Completions directory missing!" 39 | 40 | for extra in "${!extras[@]}"; do 41 | curl -sSL -o "${DESTDIR}/share/bash-completion/completions/${extra}" \ 42 | "${extras[${extra}]}" || die "Failed to download: ${extras[${extra}]}" 43 | done 44 | -------------------------------------------------------------------------------- /scripts/git_user_email.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #-----------------------------------------------------------# 4 | # Try to set user.email by matching git url # 5 | #-----------------------------------------------------------# 6 | # first - set user.email to '(none)' in the global config. # 7 | # this causes git to abort on commits if email is not set: # 8 | # git config --global user.email '(none)' # 9 | # # 10 | # set emails using the following format: # 11 | # git config --global user.email-mywork me@mywork.com # 12 | # git config --global user.email-github-com me@mydomain.com # 13 | #-----------------------------------------------------------# 14 | 15 | email="$(git config user.email)" 16 | 17 | # do nothing if email is set 18 | [[ -n ${email} && ${email} != '(none)' ]] && exit 0 19 | 20 | # get remote url 21 | url="$(git config --get remote.origin.url)" 22 | 23 | # bail if no url is set 24 | [[ -n ${url} ]] || exit 1 25 | 26 | # configured domains/emails 27 | IFS=':' read -ra config <<< "$( 28 | git config --get-regexp 'user.email-.*' | tr '\n' ':' 29 | )" 30 | 31 | # iterate entries matching on domain 32 | for ((i = 0; i < ${#config[@]}; i++)); do 33 | set -- ${config[${i}],,} 34 | domain=${1#*-} # everything after the first dash 35 | domain=${domain//-/.} # dashes to dots 36 | address=${2} 37 | # case insensitive 38 | [[ ${url,,} =~ .*${domain}.* ]] && \ 39 | match=${address} && break 40 | done 41 | 42 | # set email if a match was found 43 | if [[ -n ${match} ]]; then 44 | git config user.email ${match} 45 | echo "Setting git email to: $(git config user.email)" 46 | else 47 | echo "Unable to match git email for: ${url,,} =~ ${domain}" 48 | fi 49 | -------------------------------------------------------------------------------- /scripts/hooks/prompt.sh: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | # update terminal title 4 | title() { 5 | [[ ${TERM} == @(tmux-*|screen-*|xterm-*) ]] || return 6 | # don't set title in neovim terminals 7 | [[ -z ${NVIM_LISTEN_ADDRESS} ]] || return 8 | if [[ -z ${_TITLE_} ]]; then 9 | _TITLE_=${PWD/$HOME/\\x7e} 10 | [[ ${#_TITLE_} -gt 24 ]] && 11 | _TITLE_="${_TITLE_:0:12}..${_TITLE_:(-12)}" 12 | fi 13 | # add hostname for remote sessions 14 | [[ -z ${TMUX} && -n ${SSH_CLIENT} ]] && _TITLE_="${HOSTNAME%%.*} ${_TITLE_}" 15 | [[ ${_TITLE_} == \\x7e ]] && _TITLE_="${USER}" 16 | echo -ne "\\033]2;${_TITLE_}\\033\\" # window title 17 | [[ -n ${TMUX} ]] && echo -ne "\\033k${_TITLE_}\\033\\" # session title 18 | } 19 | 20 | # detect directory change 21 | dirchange() { 22 | [[ "${OWD}" == "${PWD}" ]] && return 1 23 | OWD="${PWD}" 24 | return 0 25 | } 26 | 27 | # called prior to displaying the prompt 28 | prompt_command() { 29 | local branch 30 | # write history so that it is available in new shell sessions 31 | history -a 32 | # set default prompt 33 | export PS1=${ps1} 34 | # return if directory did not change 35 | dirchange || return 0 36 | # reset terminal title 37 | unset _TITLE_ 38 | # automatically sets git user.email and updates terminal title 39 | if [[ $(git rev-parse --is-inside-work-tree 2>/dev/null) == "true" ]]; then 40 | ~/.dotfiles/scripts/git_user_email.sh 41 | _TITLE_="$(git rev-parse --show-toplevel | sed 's!.*/!!')" 42 | branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)" 43 | [[ -n "${branch}" ]] && _TITLE_="${_TITLE_}#${branch}" 44 | fi 45 | title 46 | } 47 | 48 | # default prompt 49 | ps1='\W\$' 50 | export PROMPT_COMMAND="prompt_command" 51 | 52 | colorterm || return 0 53 | 54 | # red prompt when root, light cyan otherwise 55 | if [[ ${UID} == 0 ]]; then 56 | ps1="\\[\\]\\[\\]${ps1}\\[\\]" 57 | else 58 | ps1="\\[\\]\\[\\]${ps1}\\[\\]" 59 | fi 60 | -------------------------------------------------------------------------------- /config/nvim/lua/plugins/lspconfig.lua: -------------------------------------------------------------------------------- 1 | local vim = vim 2 | local lspconfig = require "lspconfig" 3 | 4 | vim.lsp.handlers["textDocument/publishDiagnostics"] = 5 | vim.lsp.with( 6 | vim.lsp.diagnostic.on_publish_diagnostics, 7 | { 8 | signs = true, 9 | underline = true, 10 | update_in_insert = false, 11 | virtual_text = false 12 | } 13 | ) 14 | 15 | lspconfig["efm"].setup{ 16 | init_options = {documentFormatting = true}, 17 | root_dir = vim.loop.cwd, 18 | filetypes = { 19 | "python", 20 | "sh", 21 | "yaml" 22 | }, 23 | settings = { 24 | languages = { 25 | python = { 26 | { 27 | formatCommand = "black --line-length 79 -", 28 | formatStdin = true 29 | }, 30 | { 31 | lintCommand = "flake8 --ignore=E203,E266,E501,W503 --per-file-ignores=__init__.py:F401 --max-line-length 79 --format '%(path)s:%(row)d:%(col)d: %(code)s %(code)s %(text)s' --stdin-display-name ${INPUT} -", 32 | lintStdin = true, 33 | lintIgnoreExitCode = true, 34 | lintFormats = {"%f:%l:%c: %t%n%n%n %m"}, 35 | lintSource = "flake8" 36 | }, 37 | { 38 | formatCommand = "isort --stdout --profile black -", 39 | formatStdin = true 40 | } 41 | }, 42 | sh = { 43 | { 44 | lintCommand = "shellcheck -f gcc -x -", 45 | lintStdin = true, 46 | lintFormats = { 47 | "%f:%l:%c: %trror: %m", 48 | "%f:%l:%c: %tarning: %m", 49 | "%f:%l:%c: %tote: %m" 50 | }, 51 | lintSource = "shellcheck" 52 | }, 53 | { 54 | formatCommand = "shfmt -ci -i 2 -s -bn", 55 | formatStdin = true 56 | } 57 | }, 58 | yaml = { 59 | { 60 | lintCommand = "yamllint -f parsable -", 61 | lintStdin = true 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | lspconfig["jedi_language_server"].setup{} 69 | lspconfig["solargraph"].setup{} 70 | lspconfig["bashls"].setup{} 71 | -------------------------------------------------------------------------------- /scripts/install_aws_cli.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | readonly install_path="${HOME}/.aws/aws-cli-bin-$(date +%G%m%d%H%M%S)" 4 | readonly pkgfile="$(mktemp -t tmpfile.XXXXX.bin)" 5 | readonly tmpdir="$(mktemp -t -d tmpdir.XXXXX)" 6 | 7 | declare -a tmpfiles=("${pkgfile}" "${tmpdir}") 8 | 9 | cleanup() { rm -rf "${tmpfiles[@]}"; } 10 | 11 | trap cleanup EXIT 12 | 13 | die() { echo "$*" && exit 1; } 14 | 15 | inpath() { command -v "${1}" >/dev/null || die "Missing ${1}!"; } 16 | 17 | install_from_pkg() { 18 | mkdir -p "${install_path}" || 19 | die "Failed to create ${install_path}" 20 | inpath pkgutil 21 | pkgutil --expand "${pkgfile}" "${tmpdir}/t" || 22 | die "Failed to expand package!" 23 | [[ -s "${tmpdir}/t/aws-cli.pkg/Payload" ]] || 24 | die "Failed to find Payload!" 25 | tar -C "${install_path}" -xz --strip-components=2 \ 26 | -f "${tmpdir}/t/aws-cli.pkg/Payload" 27 | } 28 | 29 | install_from_zip() { 30 | inpath unzip 31 | unzip -q -d "${tmpdir}" "${pkgfile}" 32 | mkdir -p "${install_path%%/aws-cli-bin*}" || 33 | die "Failed to create: ${install_path%%/aws-cli-bin*}" 34 | mv "${tmpdir}/aws/dist" "${install_path}" 35 | } 36 | 37 | install_aws_cli() { 38 | local url="https://awscli.amazonaws.com" 39 | local filename 40 | 41 | case "$(uname -s)" in 42 | Darwin) 43 | filename=AWSCLIV2.pkg 44 | ;; 45 | Linux) 46 | filename=awscli-exe-linux-x86_64.zip 47 | ;; 48 | *) 49 | die "Unsupported OS!" 50 | ;; 51 | esac 52 | 53 | curl -sSL "${url}/${filename}" -o "${pkgfile}" || 54 | die "Failed to download: ${url}/${filename}" 55 | 56 | case "${filename}" in 57 | *.zip) 58 | install_from_zip 59 | ;; 60 | *.pkg) 61 | install_from_pkg 62 | ;; 63 | *) 64 | die "Unsupported file type!" 65 | ;; 66 | esac 67 | 68 | echo "Make sure to add ${install_path} to your PATH" \ 69 | "or create symlinks for ${install_path}/aws and ${install_path}/aws_completer" 70 | } 71 | 72 | install_aws_cli || die "Failed to install AWS CLI!" 73 | -------------------------------------------------------------------------------- /config/alacritty/alacritty.yml: -------------------------------------------------------------------------------- 1 | font: 2 | normal: 3 | family: RobotoMono Nerd Font 4 | style: Light 5 | 6 | bold: 7 | family: RobotoMono Nerd Font 8 | style: Medium 9 | 10 | italic: 11 | family: RobotoMono Nerd Font 12 | style: Italic 13 | 14 | bold_italic: 15 | family: RobotoMono Nerd Font 16 | style: Medium Italic 17 | 18 | size: 14.0 19 | 20 | window: 21 | decorations: none 22 | 23 | mouse: 24 | hide_when_typing: true 25 | 26 | # disable history buffer - relying on tmux 27 | scrolling: 28 | history: 0 29 | faux_multiplier: 0 30 | 31 | selection: 32 | save_to_clipboard: true 33 | 34 | # gruvbox material dark - tweaked 35 | colors: 36 | primary: 37 | background: '0x111111' 38 | foreground: '0xebdbb2' 39 | 40 | normal: 41 | black: '0x665c54' 42 | red: '0xea6962' 43 | green: '0xa9b665' 44 | yellow: '0xe78a4e' 45 | blue: '0x7daea3' 46 | magenta: '0xd3869b' 47 | cyan: '0x89b482' 48 | white: '0xdfbf8e' 49 | 50 | bright: 51 | black: '0x928374' 52 | red: '0xea6962' 53 | green: '0xa9b665' 54 | yellow: '0xe3a84e' 55 | blue: '0x7daea3' 56 | magenta: '0xd3869b' 57 | cyan: '0x89b482' 58 | white: '0xdfbf8e' 59 | 60 | hints: 61 | enabled: 62 | - regex: "(mailto:|https:|http:|file:|git:|ssh:|ftp:)\ 63 | [^\u0000-\u001F\u007F-\u009F<>\"\\s{-}\\^⟨⟩`]+" 64 | command: open 65 | post_processing: true 66 | mouse: 67 | enabled: true 68 | mods: Command 69 | 70 | key_bindings: 71 | - { key: Key0, mods: Command, action: ResetFontSize } 72 | - { key: Equals, mods: Command, action: IncreaseFontSize } 73 | - { key: Plus, mods: Command, action: IncreaseFontSize } 74 | - { key: NumpadAdd, mods: Command, action: IncreaseFontSize } 75 | - { key: Minus, mods: Command, action: DecreaseFontSize } 76 | - { key: NumpadSubtract, mods: Command, action: DecreaseFontSize } 77 | - { key: 36, mods: Command, action: ToggleSimpleFullscreen } 78 | -------------------------------------------------------------------------------- /entries/bash_profile: -------------------------------------------------------------------------------- 1 | # vim: set ft=sh:ts=2:sw=2:noet:nowrap # bash 2 | 3 | export PATH=~/.local/bin:/usr/local/bin:/usr/local/sbin:/bin:/usr/sbin:/usr/bin:/sbin 4 | 5 | # unlimited history 6 | export HISTFILESIZE= 7 | export HISTSIZE= 8 | export HISTTIMEFORMAT="#%s# " 9 | # prevent duplicate history entries 10 | export HISTCONTROL=ignoredups:erasedups:ignorespace 11 | # do not create history entries for the following commands 12 | export HISTIGNORE="&:[ ]*:??:???:exit:ls -al:bg:fg:jobs:history:clear:pwd" 13 | 14 | # format output of ps (gnu ps) 15 | export PS_FORMAT="user:15,pid,state,tt=TTY,etime=TIME,command" 16 | # search path for cd command 17 | export CDPATH=.:~/Projects 18 | 19 | # default editor 20 | export EDITOR=vi 21 | 22 | # disable some shellcheck errors 23 | export SHELLCHECK_OPTS="-e SC1090 -e SC2155 -e SC1091" 24 | 25 | # enable ~/.aws/config 26 | export AWS_SDK_LOAD_CONFIG=true 27 | 28 | export PAGER=less 29 | 30 | # color for BSD ls 31 | export CLICOLOR=1 32 | export LSCOLORS=exfxcxdxbxexexabagacad 33 | 34 | # python 35 | export VIRTUAL_ENV_DISABLE_PROMPT=true 36 | export PYTHONBREAKPOINT=pdb.set_trace 37 | 38 | # shell options: 39 | # - enable programmable completion 40 | # - fix spelling errors when using cd 41 | # - expand directories with completion results 42 | # - fix spelling errors during tab-completion 43 | # - change directory by typing directory name 44 | # - extended pattern matching 45 | # - append to the history file, don't overwrite it 46 | # - check the window size after each command 47 | # - don't complete empty command line 48 | # - recursive globbing (enables ** to recurse all directories) 49 | # - attempt to perform hostname completion 50 | shopt -s progcomp cdspell direxpand dirspell autocd extglob histappend \ 51 | cmdhist checkwinsize no_empty_cmd_completion globstar hostcomplete 52 | 53 | # preserve "shopt" options in subshells 54 | export BASHOPTS 55 | 56 | # check for presence of terminfo files 57 | mapfile -t _ < <( 58 | shopt -s nullglob 59 | echo ~/.terminfo/*/{tmux,xterm}-256color 60 | ) 61 | 62 | # generate terminfo files if missing 63 | [[ ${#_[@]} == 2 ]] || ( 64 | tic -x -o ~/.terminfo ~/.dotfiles/tmux-256color.ti 65 | tic -x -o ~/.terminfo ~/.dotfiles/xterm-256color.ti 66 | ) 2>/dev/null 67 | 68 | source ~/.bashrc 69 | -------------------------------------------------------------------------------- /entries/hammerspoon/Spoons/TapCtrlForEscape.spoon/init.lua: -------------------------------------------------------------------------------- 1 | local obj = {} 2 | obj.__index = obj 3 | 4 | obj.name = "TapCtrlForEscape" 5 | obj.version = "0.1" 6 | obj.author = "Jon Nalley " 7 | obj.homepage = "https://github.com/jnalley/dotfiles" 8 | obj.license = "MIT - https://opensource.org/licenses/MIT" 9 | 10 | obj.logger = hs.logger.new("TapCtrlForEscape") 11 | obj.menubar = nil 12 | 13 | local function enable_secure_mode_indicator() 14 | if obj.menubar ~= nil then 15 | return 16 | end 17 | obj.menubar = hs.menubar.new() 18 | obj.menubar:setTooltip("Secure input is inhibiting TapCtrlForEscape") 19 | obj.menubar:setIcon( 20 | hs.image.imageFromPath( 21 | hs.spoons.resourcePath("keyboard.png")):setSize({h=22,w=24} 22 | ), false 23 | ) 24 | end 25 | 26 | local function disable_secure_mode_indicator() 27 | if obj.menubar ~= nil then 28 | obj.menubar:delete() 29 | obj.menubar = nil 30 | end 31 | end 32 | 33 | local function abort() 34 | return ( 35 | obj.non_modifier_tap:isEnabled() and 36 | obj.non_modifier_tap:stop() and true 37 | ) 38 | end 39 | 40 | local function ctrl_key_up(evt) 41 | return next(evt:getFlags()) == nil and evt:getProperty( 42 | hs.eventtap.event.properties.keyboardEventKeycode 43 | ) == 62 44 | end 45 | 46 | local function modifier_handler(evt) 47 | -- if hs.eventtap.isSecureInputEnabled() then 48 | -- obj.logger.w("Secure input is enabled - TapCtrlForEscape will fail!") 49 | -- enable_secure_mode_indicator() 50 | -- else 51 | -- disable_secure_mode_indicator() 52 | -- end 53 | if evt:getFlags():containExactly({"ctrl"}) and not hs.eventtap.isSecureInputEnabled() then 54 | obj.logger.d("ESCAPE pending") 55 | obj.non_modifier_tap:start() 56 | elseif abort() and ctrl_key_up(evt) then 57 | obj.logger.d("sending ESCAPE") 58 | hs.eventtap.keyStroke({}, "ESCAPE", 3000) 59 | end 60 | end 61 | 62 | function obj:init() 63 | end 64 | 65 | function obj:start() 66 | -- isEnabled() is used as a "flag" for a pending ESCAPE 67 | self.non_modifier_tap = hs.eventtap.new( 68 | {hs.eventtap.event.types.keyDown}, 69 | function() obj.non_modifier_tap:stop() end 70 | ) 71 | 72 | -- modifier key presses 73 | self.modifier_tap = hs.eventtap.new( 74 | {hs.eventtap.event.types.flagsChanged}, modifier_handler 75 | ):start() 76 | 77 | return self 78 | end 79 | 80 | function obj:stop() 81 | for tap in ipairs({"non_modifier_tap", "modifier_tap"}) do 82 | if self[tap] ~= nil then 83 | self[tap]:stop() 84 | end 85 | self[tap] = nil 86 | end 87 | end 88 | 89 | return obj 90 | -------------------------------------------------------------------------------- /entries/gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | useConfigOnly = true 3 | name = (none) 4 | email = (none) 5 | [core] 6 | excludesfile = ~/.dotfiles/gitexcludes 7 | [include] 8 | path = ~/.git.user 9 | [push] 10 | default = nothing 11 | [pull] 12 | rebase = true 13 | [init] 14 | defaultBranch = main 15 | [branch] 16 | autosetuprebase = always 17 | [color] 18 | branch = auto 19 | diff = auto 20 | interactive = auto 21 | status = auto 22 | ui = auto 23 | [color "branch"] 24 | current = yellow 25 | local = yellow bold 26 | remote = magenta 27 | [color "diff"] 28 | commit = yellow bold 29 | frag = yellow bold 30 | func = green dim 31 | meta = green 32 | new = blue 33 | old = red 34 | plain = white bold 35 | whitespace = red reverse 36 | [color "status"] 37 | added = green 38 | changed = blue 39 | untracked = red 40 | branch = yellow bold 41 | [mergetool "vimdiff3"] 42 | cmd = vim -f -d -c \"wincmd J\" \"$MERGED\" \"$LOCAL\" \"$BASE\" \"$REMOTE\" 43 | [difftool "vim"] 44 | cmd = vim \"$MERGED\" 45 | prompt = false 46 | [merge] 47 | stat = true 48 | ff = only 49 | [commit] 50 | template = ~/.dotfiles/gitmessage 51 | [fetch] 52 | prune = true 53 | [rebase] 54 | autosquash = true 55 | autostash = true 56 | [alias] 57 | aa = add --all 58 | br = "!(git x-heads --color=always; git x-remotes --color=always) | column -ts'|'" 59 | x-heads = for-each-ref --sort=-committerdate refs/heads/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset)|%(color:red)%(objectname:short)%(color:reset)|%(authorname)|%(color:green)%(committerdate:relative)%(color:reset)' 60 | x-remotes = for-each-ref --sort=-committerdate refs/remotes/ --format=' %(color:yellow)%(refname:short)%(color:reset)|%(color:red)%(objectname:short)%(color:reset)|%(authorname)|%(color:green)%(committerdate:relative)%(color:reset)' 61 | ci = commit -v 62 | co = checkout 63 | dc = diff --cached 64 | df = diff 65 | st = status --short --branch 66 | l = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=local 67 | g = grep --break --heading --line-number 68 | gg = "!f() { git grep $1 $(git rev-list --all); }; f" 69 | tags = tag --sort=v:refname 70 | fp = push --force-with-lease 71 | # commits not pushed to $1 72 | unpushed = cherry -v 73 | # what tag contains the sha 74 | whatrelease = name-rev --name-only 75 | # what branch contains the sha 76 | contains = branch --contains 77 | # squash ALL commits 78 | squash-all = rebase -i --root 79 | [grep] 80 | extendRegexp = true 81 | lineNumber = true 82 | [filter "lfs"] 83 | required = true 84 | clean = git-lfs clean -- %f 85 | smudge = git-lfs smudge -- %f 86 | process = git-lfs filter-process 87 | -------------------------------------------------------------------------------- /entries/hammerspoon/init.lua: -------------------------------------------------------------------------------- 1 | -- seed the RNG 2 | math.randomseed(os.time()) 3 | 4 | -- default log level 5 | hs.logger.defaultLogLevel = "info" 6 | 7 | -- disable icons 8 | hs.dockIcon(false) 9 | hs.menuIcon(false) 10 | 11 | -- set console colors 12 | hs.console.outputBackgroundColor(hs.drawing.color.ansiTerminalColors.bgBlack) 13 | hs.console.consoleCommandColor(hs.drawing.color.ansiTerminalColors.fgGreen) 14 | 15 | -- only reload if a .lua file changed 16 | local function reload(files) 17 | for _,file in pairs(files) do 18 | if file:sub(-4) == ".lua" then 19 | hs.reload() 20 | end 21 | end 22 | end 23 | 24 | local pw = hs.pathwatcher.new(hs.configdir, reload):start() 25 | 26 | -- a work-around for websites that disable paste 27 | hs.hotkey.bind({"cmd", "ctrl"}, "v", function() 28 | hs.eventtap.keyStrokes(hs.pasteboard.getContents()) 29 | end) 30 | 31 | hs.grid.setGrid("2x2") 32 | hs.grid.ui.showExtraKeys = true 33 | hs.hotkey.bind({"alt", "cmd"}, "G", hs.grid.show) 34 | 35 | hs.hints.style = "vimperator" 36 | hs.window.animationDuration = 0 37 | 38 | local left = { 39 | hs.layout.left50, 40 | hs.geometry.unitrect(0,0,0.5,0.5), 41 | hs.geometry.unitrect(0,0.5,0.5,0.5) 42 | } 43 | 44 | local left_index = nil 45 | 46 | -- window management hotkeys 47 | local function moveToUnit(unit) 48 | hs.window.focusedWindow():moveToUnit(unit) 49 | end 50 | 51 | -- hs.hotkey.bind({"alt", "cmd"}, "t", 52 | -- function() hs.grid.resizeWindowShorter(hs.window.focusedWindow()) end 53 | -- ) 54 | 55 | --[[ 56 | hs.hotkey.bind({"alt", "cmd"}, "t", 57 | function() 58 | left_index, unit = next(left, (left_index or 1) < #left and left_index or nil) 59 | moveToUnit(unit) 60 | end 61 | ) 62 | --]] 63 | 64 | hs.hotkey.bind({"alt", "cmd"}, "Left", 65 | hs.fnutils.partial(moveToUnit, hs.layout.left50) 66 | -- 50% vertical 67 | -- hs.fnutils.partial(moveToUnit, hs.geometry.unitrect(0,0,0.5,0.5)) 68 | ) 69 | hs.hotkey.bind({"alt", "cmd"}, "Right", 70 | hs.fnutils.partial(moveToUnit, hs.layout.right50) 71 | ) 72 | hs.hotkey.bind({"alt", "cmd"}, "Up", 73 | function() hs.window.frontmostWindow():maximize() end 74 | ) 75 | 76 | -- toggles inhibit of system sleep 77 | hs.hotkey.bind({"cmd", "alt"}, "s", function() 78 | hs.alert.show( 79 | hs.caffeinate.toggle("displayIdle") and 80 | "Sleep disabled" or "Normal sleep restored" 81 | ) 82 | end) 83 | 84 | hs.hotkey.bind( 85 | {"alt", "cmd"}, "t", 86 | function() 87 | local app = hs.application.open("alacritty") 88 | local win = app:getWindow() 89 | win:moveToUnit(hs.layout.right50) 90 | end 91 | ) 92 | 93 | -- cli 94 | -- if not hs.ipc.cliStatus() then 95 | -- hs.ipc.cliInstall() 96 | -- end 97 | 98 | -- local hammerspoon = hs.application.open("hammerspoon") 99 | -- hs.timer.doAfter(3, function() print(hammerspoon:bundleID()) end) 100 | 101 | hs.loadSpoon("TapCtrlForEscape"):start() 102 | 103 | -- done 104 | FadeLogo = hs.loadSpoon("FadeLogo") 105 | FadeLogo.run_time = 0.8 106 | FadeLogo:start() 107 | -------------------------------------------------------------------------------- /entries/tmux.conf: -------------------------------------------------------------------------------- 1 | # vim: set ft=conf 2 | 3 | setw -g aggressive-resize on 4 | setw -g allow-rename on 5 | setw -g automatic-rename off 6 | setw -g clock-mode-colour '#008080' 7 | setw -g clock-mode-style 12 8 | setw -g mode-keys vi 9 | setw -g mode-style "fg=#df8700,bg=default" 10 | setw -g monitor-activity on 11 | setw -g pane-base-index 1 12 | setw -g window-status-bell-style "fg=#df0000" 13 | 14 | set -g default-terminal tmux-256color 15 | set -ga terminal-overrides ",*256col*:Tc" 16 | set -as terminal-overrides ',*:smcup@:rmcup@' 17 | set -g base-index 1 18 | set -g bell-action any 19 | set -g display-panes-time 800 20 | set -g display-time 4000 21 | set -g focus-events on 22 | set -g history-limit 10000 23 | set -g monitor-activity on 24 | set -g mouse off 25 | set -g prefix C-a 26 | set -g renumber-windows on 27 | set -g set-titles on 28 | set -g status on 29 | set -g status-interval 0 30 | set -g status-keys vi 31 | set -g visual-bell on 32 | set -sg escape-time 0 33 | 34 | # colors 35 | set -g display-panes-active-colour '#0000af' 36 | set -g display-panes-colour '#585858' 37 | set -g message-command-style "fg=#df8700,bg=#000000" 38 | set -g message-style "fg=#df8700,bg=#000000" 39 | set -g pane-active-border-style "fg=#df8700" 40 | set -g pane-border-style "fg=#df8700" 41 | set -g window-status-activity-style "fg=#df0000" 42 | 43 | # status line 44 | test_ssh='#(test -n "${SSH_CLIENT}" && echo "#[fg=#df0000]")' 45 | set -g status-left '' 46 | set -g status-left-length 0 47 | set -g status-right "#[fg=#df8700][#[fg=#008080]$test_ssh#h#[fg=#df8700]]" 48 | set -g status-right-length 60 49 | set -g status-style "fg=#585858,bg=#000000" 50 | set -g window-status-current-format '#[fg=#df8700][#[fg=#008080]#W#[fg=#df8700]] ' 51 | set -g window-status-format ' #W ' 52 | set -g window-status-separator '' 53 | 54 | # remove some existing bindings 55 | unbind '"' 56 | unbind C-b 57 | unbind [ 58 | unbind \; 59 | unbind ] 60 | unbind w 61 | unbind -T copy-mode-vi C-j 62 | unbind -T copy-mode-vi Enter 63 | unbind -T copy-mode-vi space 64 | unbind -T copy-mode-vi v 65 | unbind M-Up 66 | unbind M-Down 67 | unbind M-Right 68 | unbind M-Left 69 | 70 | # key bindings 71 | bind C-a send-prefix 72 | bind a send-prefix 73 | bind '"' choose-window 74 | bind Escape copy-mode 75 | bind C-p paste-buffer 76 | bind - split-window -v 77 | bind | split-window -h 78 | 79 | # reload tmux configuration 80 | bind r source-file ~/.tmux.conf \; display-message " tmux config reloaded..." 81 | # open man page with / 82 | bind / command-prompt -p "man" "split-window -h 'exec man %%'" 83 | # open a ssh session in a new window with input host 84 | bind S command-prompt -p "ssh:" "new-window -n %1 'ssh %1'" 85 | # write buffer to a file 86 | bind F command-prompt -p 'save output buffer to filename:' \ 87 | -I '~/tmux.buffer' 'capture-pane -S -32768 ; save-buffer %1 ; delete-buffer' 88 | 89 | # copy mode 90 | bind -T copy-mode-vi C-v send -X rectangle-toggle 91 | bind -T copy-mode-vi v send -X begin-selection 92 | bind -T copy-mode-vi y send -X copy-selection 93 | bind -T copy-mode-vi Escape send -X cancel 94 | 95 | # smart pane switching (vim-tmux-navigator) 96 | is_vim='echo "#{pane_current_command}" | grep -iqE "(^|\/)g?(view|n?vim?)(diff)?$"' 97 | bind -n 'C-h' if-shell "$is_vim" "send-keys C-h" "select-pane -L " 98 | bind -n 'C-j' if-shell "$is_vim" "send-keys C-j" "select-pane -D " 99 | bind -n 'C-k' if-shell "$is_vim" "send-keys C-k" "select-pane -U " 100 | bind -n 'C-l' if-shell "$is_vim" "send-keys C-l" "select-pane -R " 101 | bind -n 'C-\' if-shell "$is_vim" "send-keys C-\\" "select-pane -l" 102 | bind -r 'C-o' swap-pane -D 103 | 104 | # clear screen 105 | bind C-l send-keys C-a C-l 106 | 107 | # resize windows 108 | bind -n M-Right resize-pane -R 10 109 | bind -n M-Left resize-pane -L 10 110 | bind -n M-Down resize-pane -D 10 111 | bind -n M-Up resize-pane -U 10 112 | 113 | # move windows 114 | bind -n C-S-Left swap-window -t -1 115 | bind -n C-S-Right swap-window -t +1 116 | 117 | # toggle status bar 118 | bind s set -g status 119 | -------------------------------------------------------------------------------- /entries/hammerspoon/Spoons/FadeLogo.spoon/init.lua: -------------------------------------------------------------------------------- 1 | --- === FadeLogo === 2 | --- 3 | --- Show a fading-and-zooming image in the center of the screen 4 | --- 5 | --- By default the Hammerspoon logo is shown. Typical use is to show it as an indicator when your configuration finishes loading, by adding the following to the bottom of your `~/.hammerspoon/init.lua` file: 6 | --- ``` 7 | --- hs.loadSpoon('FadeLogo'):start() 8 | --- ``` 9 | --- Which looks like this: http://imgur.com/a/TbZOl 10 | --- 11 | --- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/FadeLogo.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/FadeLogo.spoon.zip) 12 | 13 | local obj={} 14 | obj.__index = obj 15 | 16 | -- Metadata 17 | obj.name = "FadeLogo" 18 | obj.version = "0.3" 19 | obj.author = "Diego Zamboni " 20 | obj.homepage = "https://github.com/Hammerspoon/Spoons" 21 | obj.license = "MIT - https://opensource.org/licenses/MIT" 22 | 23 | --- FadeLogo.logger 24 | --- Variable 25 | --- Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon. 26 | obj.logger = hs.logger.new('FadeLogo') 27 | 28 | --- FadeLogo.image 29 | --- Variable 30 | --- Image to display. Must be an `hs.image` object. Defaults to `hs.image.imageFromName(hs.image.systemImageNames.ApplicationIcon)` (the Hammerspoon app icon) 31 | obj.image = hs.image.imageFromName(hs.image.systemImageNames.ApplicationIcon) 32 | 33 | --- FadeLogo.image_size 34 | --- Variable 35 | --- `hs.geometry` object specifying the initial size of the image to display in the center of the screen. The image object will be resizes proportionally to fit in this size. Defaults to `hs.geometry.size(w=200, h=200)` 36 | obj.image_size = hs.geometry.size(200, 200) 37 | 38 | --- FadeLogo.image_alpha 39 | --- Variable 40 | --- Initial transparency of the image. Defaults to 1.0. 41 | obj.image_alpha = 1.0 42 | 43 | --- FadeLogo.zoom 44 | --- Variable 45 | --- Do zoom-and-fade if `true`, otherwise do a regular fade 46 | obj.zoom = true 47 | 48 | --- FadeLogo.fade_in_time 49 | --- Variable 50 | --- Number of seconds over which to fade in the image. Defaults to 0.3. 51 | obj.fade_in_time = 0.3 52 | 53 | --- FadeLogo.fade_out_time 54 | --- Variable 55 | --- Number of seconds over which to fade out the image. Defaults to 0.5. 56 | obj.fade_out_time = 0.5 57 | 58 | --- FadeLogo.run_time 59 | --- Variable 60 | --- Number of seconds to leave the image on the screen when `start()` is called. 61 | obj.run_time = 2.0 62 | 63 | --- FadeLogo.zoom_scale_factor 64 | --- Variable 65 | --- Factor by which to scale the image at every iteration during the zoom-and-fade. Defaults to 1.1. 66 | obj.zoom_scale_factor = 1.1 67 | 68 | --- FadeLogo.zoom_scale_timer 69 | --- Variable 70 | --- Seconds between the zooming iterations 71 | obj.zoom_scale_timer = 0.01 72 | 73 | ---------------------------------------------------------------------- 74 | 75 | -- Internal variable to hold the canvas where the image is drawn 76 | obj.canvas = nil 77 | 78 | --- FadeLogo:delete() 79 | --- Method 80 | --- Hide and delete the canvas 81 | function obj:delete() 82 | if self.canvas then 83 | self.canvas = self.canvas:delete() 84 | end 85 | end 86 | 87 | --- FadeLogo:show() 88 | --- Method 89 | --- Display the image, fading it in over `fade_in_time` seconds 90 | function obj:show() 91 | if self.canvas then self:delete() end 92 | local frame = hs.screen.mainScreen():frame() 93 | local imgsz = self.image_size 94 | self.canvas = hs.canvas.new(frame) 95 | self.canvas[1] = { 96 | type = 'image', 97 | image = self.image, 98 | frame = { 99 | x = (frame.w - imgsz.w) / 2, 100 | y = (frame.h - imgsz.h) / 2, 101 | w = imgsz.w, 102 | h = imgsz.h, 103 | }, 104 | imageAlpha = self.image_alpha, 105 | } 106 | self.canvas:show(self.fade_in_time) 107 | end 108 | 109 | --- FadeLogo:hide() 110 | --- Method 111 | --- Hide the image without zoom, fading it out over `fade_out_time` seconds 112 | function obj:hide() 113 | self.canvas:hide(self.fade_out_time) 114 | end 115 | 116 | --- FadeLogo:zoom_and_fade() 117 | --- Method 118 | --- Zoom-and-fade the image over `fade_out_time` seconds 119 | function obj:zoom_and_fade() 120 | local canvas=self.canvas 121 | local size=hs.geometry.new(canvas[1].frame) 122 | -- This timer will zoom the image while it is fading 123 | local timer 124 | timer=hs.timer.doEvery( 125 | self.zoom_scale_timer, 126 | function() 127 | if canvas:isShowing() then 128 | size:scale(self.zoom_scale_factor) 129 | canvas[1].frame = {x = size.x, y = size.y, w = size.w, h = size.h } 130 | else 131 | timer:stop() 132 | timer = nil 133 | self:delete() 134 | end 135 | end) 136 | canvas:hide(self.fade_out_time) 137 | end 138 | 139 | --- FadeLogo:start() 140 | --- Method 141 | --- Show the image, wait `run_time` seconds, and then zoom-and-fade it out. 142 | function obj:start(howlong) 143 | if not howlong then howlong = self.run_time end 144 | self:show() 145 | obj._timer = hs.timer.doAfter(howlong, hs.fnutils.partial(self.zoom and self.zoom_and_fade or self.hide, self)) 146 | end 147 | 148 | return obj 149 | -------------------------------------------------------------------------------- /entries/hammerspoon/Spoons/FadeLogo.spoon/docs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Command": [], 4 | "Constant": [], 5 | "Constructor": [], 6 | "Deprecated": [], 7 | "Field": [], 8 | "Function": [], 9 | "Method": [ 10 | { 11 | "def": "FadeLogo:delete()", 12 | "desc": "Hide and delete the canvas", 13 | "doc": "Hide and delete the canvas", 14 | "name": "delete", 15 | "signature": "FadeLogo:delete()", 16 | "stripped_doc": "", 17 | "type": "Method" 18 | }, 19 | { 20 | "def": "FadeLogo:hide()", 21 | "desc": "Hide the image without zoom, fading it out over `fade_out_time` seconds", 22 | "doc": "Hide the image without zoom, fading it out over `fade_out_time` seconds", 23 | "name": "hide", 24 | "signature": "FadeLogo:hide()", 25 | "stripped_doc": "", 26 | "type": "Method" 27 | }, 28 | { 29 | "def": "FadeLogo:show()", 30 | "desc": "Display the image, fading it in over `fade_in_time` seconds", 31 | "doc": "Display the image, fading it in over `fade_in_time` seconds", 32 | "name": "show", 33 | "signature": "FadeLogo:show()", 34 | "stripped_doc": "", 35 | "type": "Method" 36 | }, 37 | { 38 | "def": "FadeLogo:start()", 39 | "desc": "Show the image, wait `run_time` seconds, and then zoom-and-fade it out.", 40 | "doc": "Show the image, wait `run_time` seconds, and then zoom-and-fade it out.", 41 | "name": "start", 42 | "signature": "FadeLogo:start()", 43 | "stripped_doc": "", 44 | "type": "Method" 45 | }, 46 | { 47 | "def": "FadeLogo:zoom_and_fade()", 48 | "desc": "Zoom-and-fade the image over `fade_out_time` seconds", 49 | "doc": "Zoom-and-fade the image over `fade_out_time` seconds", 50 | "name": "zoom_and_fade", 51 | "signature": "FadeLogo:zoom_and_fade()", 52 | "stripped_doc": "", 53 | "type": "Method" 54 | } 55 | ], 56 | "Variable": [ 57 | { 58 | "def": "FadeLogo.fade_in_time", 59 | "desc": "Number of seconds over which to fade in the image. Defaults to 0.3.", 60 | "doc": "Number of seconds over which to fade in the image. Defaults to 0.3.", 61 | "name": "fade_in_time", 62 | "signature": "FadeLogo.fade_in_time", 63 | "stripped_doc": "", 64 | "type": "Variable" 65 | }, 66 | { 67 | "def": "FadeLogo.fade_out_time", 68 | "desc": "Number of seconds over which to fade out the image. Defaults to 0.5.", 69 | "doc": "Number of seconds over which to fade out the image. Defaults to 0.5.", 70 | "name": "fade_out_time", 71 | "signature": "FadeLogo.fade_out_time", 72 | "stripped_doc": "", 73 | "type": "Variable" 74 | }, 75 | { 76 | "def": "FadeLogo.image", 77 | "desc": "Image to display. Must be an `hs.image` object. Defaults to `hs.image.imageFromName(hs.image.systemImageNames.ApplicationIcon)` (the Hammerspoon app icon)", 78 | "doc": "Image to display. Must be an `hs.image` object. Defaults to `hs.image.imageFromName(hs.image.systemImageNames.ApplicationIcon)` (the Hammerspoon app icon)", 79 | "name": "image", 80 | "signature": "FadeLogo.image", 81 | "stripped_doc": "", 82 | "type": "Variable" 83 | }, 84 | { 85 | "def": "FadeLogo.image_alpha", 86 | "desc": "Initial transparency of the image. Defaults to 1.0.", 87 | "doc": "Initial transparency of the image. Defaults to 1.0.", 88 | "name": "image_alpha", 89 | "signature": "FadeLogo.image_alpha", 90 | "stripped_doc": "", 91 | "type": "Variable" 92 | }, 93 | { 94 | "def": "FadeLogo.image_size", 95 | "desc": "`hs.geometry` object specifying the initial size of the image to display in the center of the screen. The image object will be resizes proportionally to fit in this size. Defaults to `hs.geometry.size(w=200, h=200)`", 96 | "doc": "`hs.geometry` object specifying the initial size of the image to display in the center of the screen. The image object will be resizes proportionally to fit in this size. Defaults to `hs.geometry.size(w=200, h=200)`", 97 | "name": "image_size", 98 | "signature": "FadeLogo.image_size", 99 | "stripped_doc": "", 100 | "type": "Variable" 101 | }, 102 | { 103 | "def": "FadeLogo.logger", 104 | "desc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", 105 | "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", 106 | "name": "logger", 107 | "signature": "FadeLogo.logger", 108 | "stripped_doc": "", 109 | "type": "Variable" 110 | }, 111 | { 112 | "def": "FadeLogo.run_time", 113 | "desc": "Number of seconds to leave the image on the screen when `start()` is called.", 114 | "doc": "Number of seconds to leave the image on the screen when `start()` is called.", 115 | "name": "run_time", 116 | "signature": "FadeLogo.run_time", 117 | "stripped_doc": "", 118 | "type": "Variable" 119 | }, 120 | { 121 | "def": "FadeLogo.zoom", 122 | "desc": "Do zoom-and-fade if `true`, otherwise do a regular fade", 123 | "doc": "Do zoom-and-fade if `true`, otherwise do a regular fade", 124 | "name": "zoom", 125 | "signature": "FadeLogo.zoom", 126 | "stripped_doc": "", 127 | "type": "Variable" 128 | }, 129 | { 130 | "def": "FadeLogo.zoom_scale_factor", 131 | "desc": "Factor by which to scale the image at every iteration during the zoom-and-fade. Defaults to 1.1.", 132 | "doc": "Factor by which to scale the image at every iteration during the zoom-and-fade. Defaults to 1.1.", 133 | "name": "zoom_scale_factor", 134 | "signature": "FadeLogo.zoom_scale_factor", 135 | "stripped_doc": "", 136 | "type": "Variable" 137 | }, 138 | { 139 | "def": "FadeLogo.zoom_scale_timer", 140 | "desc": "Seconds between the zooming iterations", 141 | "doc": "Seconds between the zooming iterations", 142 | "name": "zoom_scale_timer", 143 | "signature": "FadeLogo.zoom_scale_timer", 144 | "stripped_doc": "", 145 | "type": "Variable" 146 | } 147 | ], 148 | "desc": "Show a fading-and-zooming image in the center of the screen", 149 | "doc": "Show a fading-and-zooming image in the center of the screen\n\nBy default the Hammerspoon logo is shown. Typical use is to show it as an indicator when your configuration finishes loading, by adding the following to the bottom of your `~/.hammerspoon/init.lua` file:\n```\n hs.loadSpoon('FadeLogo'):start()\n```\nWhich looks like this: http://imgur.com/a/TbZOl\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/FadeLogo.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/FadeLogo.spoon.zip)", 150 | "items": [ 151 | { 152 | "def": "FadeLogo:delete()", 153 | "desc": "Hide and delete the canvas", 154 | "doc": "Hide and delete the canvas", 155 | "name": "delete", 156 | "signature": "FadeLogo:delete()", 157 | "stripped_doc": "", 158 | "type": "Method" 159 | }, 160 | { 161 | "def": "FadeLogo.fade_in_time", 162 | "desc": "Number of seconds over which to fade in the image. Defaults to 0.3.", 163 | "doc": "Number of seconds over which to fade in the image. Defaults to 0.3.", 164 | "name": "fade_in_time", 165 | "signature": "FadeLogo.fade_in_time", 166 | "stripped_doc": "", 167 | "type": "Variable" 168 | }, 169 | { 170 | "def": "FadeLogo.fade_out_time", 171 | "desc": "Number of seconds over which to fade out the image. Defaults to 0.5.", 172 | "doc": "Number of seconds over which to fade out the image. Defaults to 0.5.", 173 | "name": "fade_out_time", 174 | "signature": "FadeLogo.fade_out_time", 175 | "stripped_doc": "", 176 | "type": "Variable" 177 | }, 178 | { 179 | "def": "FadeLogo:hide()", 180 | "desc": "Hide the image without zoom, fading it out over `fade_out_time` seconds", 181 | "doc": "Hide the image without zoom, fading it out over `fade_out_time` seconds", 182 | "name": "hide", 183 | "signature": "FadeLogo:hide()", 184 | "stripped_doc": "", 185 | "type": "Method" 186 | }, 187 | { 188 | "def": "FadeLogo.image", 189 | "desc": "Image to display. Must be an `hs.image` object. Defaults to `hs.image.imageFromName(hs.image.systemImageNames.ApplicationIcon)` (the Hammerspoon app icon)", 190 | "doc": "Image to display. Must be an `hs.image` object. Defaults to `hs.image.imageFromName(hs.image.systemImageNames.ApplicationIcon)` (the Hammerspoon app icon)", 191 | "name": "image", 192 | "signature": "FadeLogo.image", 193 | "stripped_doc": "", 194 | "type": "Variable" 195 | }, 196 | { 197 | "def": "FadeLogo.image_alpha", 198 | "desc": "Initial transparency of the image. Defaults to 1.0.", 199 | "doc": "Initial transparency of the image. Defaults to 1.0.", 200 | "name": "image_alpha", 201 | "signature": "FadeLogo.image_alpha", 202 | "stripped_doc": "", 203 | "type": "Variable" 204 | }, 205 | { 206 | "def": "FadeLogo.image_size", 207 | "desc": "`hs.geometry` object specifying the initial size of the image to display in the center of the screen. The image object will be resizes proportionally to fit in this size. Defaults to `hs.geometry.size(w=200, h=200)`", 208 | "doc": "`hs.geometry` object specifying the initial size of the image to display in the center of the screen. The image object will be resizes proportionally to fit in this size. Defaults to `hs.geometry.size(w=200, h=200)`", 209 | "name": "image_size", 210 | "signature": "FadeLogo.image_size", 211 | "stripped_doc": "", 212 | "type": "Variable" 213 | }, 214 | { 215 | "def": "FadeLogo.logger", 216 | "desc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", 217 | "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", 218 | "name": "logger", 219 | "signature": "FadeLogo.logger", 220 | "stripped_doc": "", 221 | "type": "Variable" 222 | }, 223 | { 224 | "def": "FadeLogo.run_time", 225 | "desc": "Number of seconds to leave the image on the screen when `start()` is called.", 226 | "doc": "Number of seconds to leave the image on the screen when `start()` is called.", 227 | "name": "run_time", 228 | "signature": "FadeLogo.run_time", 229 | "stripped_doc": "", 230 | "type": "Variable" 231 | }, 232 | { 233 | "def": "FadeLogo:show()", 234 | "desc": "Display the image, fading it in over `fade_in_time` seconds", 235 | "doc": "Display the image, fading it in over `fade_in_time` seconds", 236 | "name": "show", 237 | "signature": "FadeLogo:show()", 238 | "stripped_doc": "", 239 | "type": "Method" 240 | }, 241 | { 242 | "def": "FadeLogo:start()", 243 | "desc": "Show the image, wait `run_time` seconds, and then zoom-and-fade it out.", 244 | "doc": "Show the image, wait `run_time` seconds, and then zoom-and-fade it out.", 245 | "name": "start", 246 | "signature": "FadeLogo:start()", 247 | "stripped_doc": "", 248 | "type": "Method" 249 | }, 250 | { 251 | "def": "FadeLogo.zoom", 252 | "desc": "Do zoom-and-fade if `true`, otherwise do a regular fade", 253 | "doc": "Do zoom-and-fade if `true`, otherwise do a regular fade", 254 | "name": "zoom", 255 | "signature": "FadeLogo.zoom", 256 | "stripped_doc": "", 257 | "type": "Variable" 258 | }, 259 | { 260 | "def": "FadeLogo:zoom_and_fade()", 261 | "desc": "Zoom-and-fade the image over `fade_out_time` seconds", 262 | "doc": "Zoom-and-fade the image over `fade_out_time` seconds", 263 | "name": "zoom_and_fade", 264 | "signature": "FadeLogo:zoom_and_fade()", 265 | "stripped_doc": "", 266 | "type": "Method" 267 | }, 268 | { 269 | "def": "FadeLogo.zoom_scale_factor", 270 | "desc": "Factor by which to scale the image at every iteration during the zoom-and-fade. Defaults to 1.1.", 271 | "doc": "Factor by which to scale the image at every iteration during the zoom-and-fade. Defaults to 1.1.", 272 | "name": "zoom_scale_factor", 273 | "signature": "FadeLogo.zoom_scale_factor", 274 | "stripped_doc": "", 275 | "type": "Variable" 276 | }, 277 | { 278 | "def": "FadeLogo.zoom_scale_timer", 279 | "desc": "Seconds between the zooming iterations", 280 | "doc": "Seconds between the zooming iterations", 281 | "name": "zoom_scale_timer", 282 | "signature": "FadeLogo.zoom_scale_timer", 283 | "stripped_doc": "", 284 | "type": "Variable" 285 | } 286 | ], 287 | "name": "FadeLogo", 288 | "stripped_doc": "\nBy default the Hammerspoon logo is shown. Typical use is to show it as an indicator when your configuration finishes loading, by adding the following to the bottom of your `~/.hammerspoon/init.lua` file:\n```\n hs.loadSpoon('FadeLogo'):start()\n```\nWhich looks like this: http://imgur.com/a/TbZOl\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/FadeLogo.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/FadeLogo.spoon.zip)", 289 | "submodules": [], 290 | "type": "Module" 291 | } 292 | ] --------------------------------------------------------------------------------