From f9d88a6c3b219fa1fd32cb5fd2589ac6b04450762c34f8c92a08d0c1bc29a63c Mon Sep 17 00:00:00 2001 From: empathicqubit Date: Fri, 24 Jan 2025 10:01:12 +0100 Subject: [PATCH] Initial commit --- .Xmodmap | 0 .bash_aliases | 131 + .bash_logout | 9 + .bashrc.d/00-path.sh | 44 + .bashrc.d/01-brew.sh | 2 + .bashrc.d/02-walktoroot.sh | 14 + .bashrc.d/03-preexec.sh | 341 +++ .bashrc.d/04-colors.sh | 21 + .bashrc.d/05-prompt.sh | 203 ++ .bashrc.d/10-tmux.sh | 29 + .bashrc.d/20-git.sh | 50 + .bashrc.d/30-fzf.bash | 16 + .bashrc.d/99-aliases.sh | 65 + .bashrc.d/99-archivebox.sh | 12 + .bashrc.d/99-direnv.sh | 37 + .bashrc.d/99-docker.sh | 1 + .bashrc.d/99-flutter.sh | 43 + .bashrc.d/99-node.sh | 4 + .bashrc.d/99-overcast.sh | 8 + .bashrc.d/99-recovery.sh | 7 + .bashrc.d/99-windows.sh | 16 + .bashrc.d/cdf/.gitignore | 3 + .bashrc.d/cdf/CHANGELOG.md | 3 + .bashrc.d/cdf/README.md | 2 + .bashrc.d/cdf/analysis_options.yaml | 30 + .bashrc.d/cdf/bin/cdf.dart | 8 + .bashrc.d/cdf/lib/cdf.dart | 25 + .bashrc.d/cdf/pubspec.lock | 381 +++ .bashrc.d/cdf/pubspec.yaml | 16 + .bashrc.d/cdf/test/cdf_test.dart | 8 + .bashrc.d/node-commands.js | 20 + .bashrc.d/package.json | 10 + .bashrc.d/yarn.lock | 108 + .config/dark-mode-notify/.DS_Store.bak | 1 + .config/dark-mode-notify/.DS_Store.bak.bak | Bin 0 -> 6148 bytes .config/dark-mode-notify/dark-mode-notify | 1 + .../run.d/daynight.applescript | 31 + .config/dark-mode-notify/run.d/teams.sh | 17 + .../layouts/layout-NEATDONK.json | 458 +++ .config/i3/.gitignore | 1 + .config/i3/config | 247 ++ .config/i3/i3status.conf | 62 + .config/i3/nerd-dictation.sh | 0 .config/i3/wallpaper-reddit.sh | 49 + .config/i3/wallpaper.sh | 15 + .config/pip/pip.conf | 2 + .config/xfce4/terminal/accels.scm | 58 + .gitconfig | 42 + .gitignore | 71 + .ideavimrc | 1 + .inputrc | 5 + .nvim | 1 + .nvimrc | 1 + .tern-project | 5 + .vim/autoload/plug.vim | 2503 +++++++++++++++++ .vim/init.vim | 1 + .vimrc | 211 ++ .vsvimrc | 3 + script/.eslintrc.js | 13 + script/attrnorm | 42 + script/attrsec | 4 + script/cmus-hook | 3 + script/dev-node.sh | 32 + script/docker.js | 167 ++ script/flickr-wallpaper.py | 225 ++ script/git-walk | 25 + script/gtk-theme-toggler | 8 + script/kexec-now | 3 + script/markdown-toc.rb | 19 + script/openport.js | 12 + script/package.json | 17 + script/pnpm-lock.yaml | 1434 ++++++++++ script/svn-diffwrap | 16 + script/unfuckusb.sh | 21 + script/vimcat | 2 + setup/setup.sh | 178 ++ yarn.lock | 4 + 77 files changed, 7678 insertions(+) create mode 100644 .Xmodmap create mode 100644 .bash_aliases create mode 100644 .bash_logout create mode 100755 .bashrc.d/00-path.sh create mode 100755 .bashrc.d/01-brew.sh create mode 100755 .bashrc.d/02-walktoroot.sh create mode 100755 .bashrc.d/03-preexec.sh create mode 100755 .bashrc.d/04-colors.sh create mode 100755 .bashrc.d/05-prompt.sh create mode 100755 .bashrc.d/10-tmux.sh create mode 100755 .bashrc.d/20-git.sh create mode 100755 .bashrc.d/30-fzf.bash create mode 100755 .bashrc.d/99-aliases.sh create mode 100755 .bashrc.d/99-archivebox.sh create mode 100755 .bashrc.d/99-direnv.sh create mode 100755 .bashrc.d/99-docker.sh create mode 100755 .bashrc.d/99-flutter.sh create mode 100755 .bashrc.d/99-node.sh create mode 100755 .bashrc.d/99-overcast.sh create mode 100755 .bashrc.d/99-recovery.sh create mode 100755 .bashrc.d/99-windows.sh create mode 100644 .bashrc.d/cdf/.gitignore create mode 100644 .bashrc.d/cdf/CHANGELOG.md create mode 100644 .bashrc.d/cdf/README.md create mode 100644 .bashrc.d/cdf/analysis_options.yaml create mode 100644 .bashrc.d/cdf/bin/cdf.dart create mode 100644 .bashrc.d/cdf/lib/cdf.dart create mode 100644 .bashrc.d/cdf/pubspec.lock create mode 100644 .bashrc.d/cdf/pubspec.yaml create mode 100644 .bashrc.d/cdf/test/cdf_test.dart create mode 100644 .bashrc.d/node-commands.js create mode 100644 .bashrc.d/package.json create mode 100644 .bashrc.d/yarn.lock create mode 120000 .config/dark-mode-notify/.DS_Store.bak create mode 100644 .config/dark-mode-notify/.DS_Store.bak.bak create mode 120000 .config/dark-mode-notify/dark-mode-notify create mode 100644 .config/dark-mode-notify/run.d/daynight.applescript create mode 100755 .config/dark-mode-notify/run.d/teams.sh create mode 100644 .config/i3-layout-manager/layouts/layout-NEATDONK.json create mode 100644 .config/i3/.gitignore create mode 100644 .config/i3/config create mode 100644 .config/i3/i3status.conf create mode 100644 .config/i3/nerd-dictation.sh create mode 100755 .config/i3/wallpaper-reddit.sh create mode 100755 .config/i3/wallpaper.sh create mode 100644 .config/pip/pip.conf create mode 100644 .config/xfce4/terminal/accels.scm create mode 100644 .gitconfig create mode 100644 .gitignore create mode 100644 .ideavimrc create mode 100644 .inputrc create mode 120000 .nvim create mode 120000 .nvimrc create mode 100644 .tern-project create mode 100644 .vim/autoload/plug.vim create mode 120000 .vim/init.vim create mode 100644 .vimrc create mode 100644 .vsvimrc create mode 100644 script/.eslintrc.js create mode 100755 script/attrnorm create mode 100755 script/attrsec create mode 100755 script/cmus-hook create mode 100755 script/dev-node.sh create mode 100755 script/docker.js create mode 100755 script/flickr-wallpaper.py create mode 100755 script/git-walk create mode 100755 script/gtk-theme-toggler create mode 100755 script/kexec-now create mode 100755 script/markdown-toc.rb create mode 100755 script/openport.js create mode 100644 script/package.json create mode 100644 script/pnpm-lock.yaml create mode 100755 script/svn-diffwrap create mode 100755 script/unfuckusb.sh create mode 100755 script/vimcat create mode 100755 setup/setup.sh create mode 100644 yarn.lock diff --git a/.Xmodmap b/.Xmodmap new file mode 100644 index 0000000..473a0f4 diff --git a/.bash_aliases b/.bash_aliases new file mode 100644 index 0000000..145026f --- /dev/null +++ b/.bash_aliases @@ -0,0 +1,131 @@ +#! /bin/bash +# This is just a bootstrap file for the .d folder. Don't put anything meaninguful here. +__bashrc_debug_startup=${__bashrc_debug_startup:-0} + +if ((_bashrc_debug_startup)) ; then + PS4='+ $EPOCHREALTIME\011 ' + exec 3>&2 2>/tmp/bashstart.$$.log + set -x +fi + +function rlbashrc { + source "$HOME/.bashrc" +} + +function getmac { + echo 00:$(head -c5 /dev/urandom | hexdump -e '"%02x"' | sed -r 's/(..)/\1:/g;s/:$//;') +} + +function find { + if which gfind &>/dev/null ; then + gfind "$@" + else + command find "$@" + fi +} + +function readlink { + if which greadlink &>/dev/null ; then + greadlink "$@" + else + command readlink "$@" + fi +} + +__bashrc_debug_order=${__bashrc_debug_order:-0} + +# This is here so we don't have to modify the distro provided bashrc. +if [ -d "$HOME/.bashrc.d" ] ; then + while read FILE ; do + if ((__bashrc_debug_order > 0)) ; then + echo "$FILE" + fi + . "$FILE" + + # It's a bit stupid that I need to do this. + done < <( find "$HOME/.bashrc.d/." -maxdepth 1 -type f -executable | sort ) +fi + +# For secrets and commands we don't want to commit to git. +if [ -d "$HOME/.bashrc.local.d" ] ; then + while read FILE ; do + . "$FILE" + + done < <( find "$HOME/.bashrc.local.d/." -type f -executable | sort ) +fi + +export EDITOR='vim' + +# wrap_alias takes three arguments: +# $1: The name of the alias +# $2: The command used in the alias +# $3: The arguments in the alias all in one string +# Generate a wrapper completion function (completer) for an alias +# based on the command and the given arguments, if there is a +# completer for the command, and set the wrapper as the completer for +# the alias. +function wrap_alias() { + [[ "$#" == 3 ]] || return 1 + + local alias_name="$1" + local aliased_command="$2" + local alias_arguments="$3" + local num_alias_arguments + local completion + IFS= read -r num_alias_arguments < <(wc -w <<< "$alias_arguments") + + # The completion currently being used for the aliased command. + IFS= read -r completion < <(complete -p $aliased_command 2>/dev/null) + + # Only a completer based on a function can be wrapped so look for -F + # in the current completion. This check will also catch commands + # with no completer for which $completion will be empty. + grep -q -- -F <<< "$completion" || return 0 + + local namespace=alias_completion:: + + # Extract the name of the completion function from a string that + # looks like: something -F function_name something + # First strip the beginning of the string up to the function name by + # removing "* -F " from the front. + local completion_function=${completion##* -F } + # Then strip " *" from the end, leaving only the function name. + completion_function=${completion_function%% *} + + # Try to prevent an infinite loop by not wrapping a function + # generated by this function. This can happen when the user runs + # this twice for an alias like ls='ls --color=auto' or alias l='ls' + # and alias ls='l foo' + [[ "${completion_function#$namespace}" != $completion_function ]] && return 0 + + local wrapper_name="${namespace}${alias_name}" + + eval " +function ${wrapper_name}() { + let COMP_CWORD+=$num_alias_arguments + args=( \"${alias_arguments}\" ) + COMP_WORDS=( $aliased_command \${args[@]} \${COMP_WORDS[@]:1} ) + $completion_function + } +" + + # To create the new completion we use the old one with two + # replacements: + # 1) Replace the function with the wrapper. + local new_completion=${completion/-F * /-F $wrapper_name } + # 2) Replace the command being completed with the alias. + new_completion="${new_completion% *} $alias_name" + + eval "$new_completion" +} + +# For each defined alias, extract the necessary elements and use them +# to call wrap_alias. +eval "$(alias -p | sed -e 's/alias \([^=][^=]*\)='\''\([^ ][^ ]*\) *\(.*\)'\''/wrap_alias \1 \2 '\''\3'\'' /')" + +unset wrap_alias + +if ((_bashrc_debug_startup)) ; then + set +x + exec 2>&3 3>&- +fi diff --git a/.bash_logout b/.bash_logout new file mode 100644 index 0000000..a15a7ab --- /dev/null +++ b/.bash_logout @@ -0,0 +1,9 @@ +# ~/.bash_logout: executed by bash(1) when login shell exits. + +# when leaving the console clear the screen to increase privacy + +if [ "$SHLVL" = 1 ]; then + [ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q +fi + +__kill_promptutilserver diff --git a/.bashrc.d/00-path.sh b/.bashrc.d/00-path.sh new file mode 100755 index 0000000..edac854 --- /dev/null +++ b/.bashrc.d/00-path.sh @@ -0,0 +1,44 @@ +#! /bin/bash +export PATH="$PATH:$HOME/script:$HOME/.vim/plugged/github:$HOME/bin:$HOME/.local/bin:~/.pyenv/bin:$HOME/c64-devkit/bin:/usr/lib/goattracker:$HOME/.nix-profile/bin:$HOME/google-cloud-sdk/bin:$HOME/go/bin:$HOME/flutter/bin" + +function addpythonpath () { + local PY3PATH + local PYPATH + + if which python &>/dev/null ; then + PYPATH="$(python -c 'import sys ; print(sys.path)' | tr "'" '"' | jq -r ".[] | select(contains(\"$HOME\"))" | awk -F'/lib/' '{print $1}')/bin" + PATH="$PATH:$PYPATH" + fi + + if which python3 &>/dev/null ; then + PY3PATH="$(python3 -c 'import sys ; print(sys.path)' | tr "'" '"' | jq -r ".[] | select(contains(\"$HOME\"))" | awk -F'/lib/' '{print $1}')/bin" + PATH="$PATH:$PY3PATH" + fi +} + +addpythonpath + +function addcondapath () { + local each + + for each in "/usr/local/anaconda"*"/bin" ; do + export PATH="$PATH:$each" + done +} + +addcondapath + +for gempath in $HOME/.gem/ruby/*/bin ; do + export PATH="$PATH:$gempath" +done + +export HISTCONTROL=ignorespace:ignoredups:erasedups # no duplicate entries +export HISTSIZE=100000 # big big history +export HISTFILESIZE=100000 # big big history +shopt -s histappend # append to history, don't overwrite it + +if [ ! -z "$DISPLAY" ] ; then + export TMOUT= # never time out if we're graphical +else + export TMOUT=$((5*60)) # use a less crazy timeout than the system default +fi diff --git a/.bashrc.d/01-brew.sh b/.bashrc.d/01-brew.sh new file mode 100755 index 0000000..20a8928 --- /dev/null +++ b/.bashrc.d/01-brew.sh @@ -0,0 +1,2 @@ +#! /bin/bash +[ -f /usr/local/etc/bash_completion ] && . /usr/local/etc/bash_completion diff --git a/.bashrc.d/02-walktoroot.sh b/.bashrc.d/02-walktoroot.sh new file mode 100755 index 0000000..51e4c04 --- /dev/null +++ b/.bashrc.d/02-walktoroot.sh @@ -0,0 +1,14 @@ +#! /bin/bash +function walktoroot { + local DIR="$1" + shift + + if [ "$DIR" = "/" ]; then + return + fi + + if ! "$@" "$DIR" ; then + local PARENTDIR="$(dirname "$DIR")" + walktoroot "$PARENTDIR" "$@" + fi +} diff --git a/.bashrc.d/03-preexec.sh b/.bashrc.d/03-preexec.sh new file mode 100755 index 0000000..44300bc --- /dev/null +++ b/.bashrc.d/03-preexec.sh @@ -0,0 +1,341 @@ +#!/bin/bash +# +# bash-preexec.sh -- Bash support for ZSH-like 'preexec' and 'precmd' functions. +# https://github.com/rcaloras/bash-preexec +# +# +# 'preexec' functions are executed before each interactive command is +# executed, with the interactive command as its argument. The 'precmd' +# function is executed before each prompt is displayed. +# +# Author: Ryan Caloras (ryan@bashhub.com) +# Forked from Original Author: Glyph Lefkowitz +# +# V0.3.7 +# + +# General Usage: +# +# 1. Source this file at the end of your bash profile so as not to interfere +# with anything else that's using PROMPT_COMMAND. +# +# 2. Add any precmd or preexec functions by appending them to their arrays: +# e.g. +# precmd_functions+=(my_precmd_function) +# precmd_functions+=(some_other_precmd_function) +# +# preexec_functions+=(my_preexec_function) +# +# 3. Consider changing anything using the DEBUG trap or PROMPT_COMMAND +# to use preexec and precmd instead. Preexisting usages will be +# preserved, but doing so manually may be less surprising. +# +# Note: This module requires two Bash features which you must not otherwise be +# using: the "DEBUG" trap, and the "PROMPT_COMMAND" variable. If you override +# either of these after bash-preexec has been installed it will most likely break. + +# Avoid duplicate inclusion +if [[ "$__bp_imported" == "defined" ]]; then + return 0 +fi +__bp_imported="defined" + +# Should be available to each precmd and preexec +# functions, should they want it. +__bp_last_ret_value="$?" +__bp_last_argument_prev_command="$_" + +__bp_inside_precmd=0 +__bp_inside_preexec=0 +__bp_time_functions=0 + +# Remove ignorespace and or replace ignoreboth from HISTCONTROL +# so we can accurately invoke preexec with a command from our +# history even if it starts with a space. +__bp_adjust_histcontrol() { + local histcontrol + histcontrol="${HISTCONTROL//ignorespace}" + # Replace ignoreboth with ignoredups + if [[ "$histcontrol" == *"ignoreboth"* ]]; then + histcontrol="ignoredups:${histcontrol//ignoreboth}" + fi; + export HISTCONTROL="$histcontrol" +} + +# This variable describes whether we are currently in "interactive mode"; +# i.e. whether this shell has just executed a prompt and is waiting for user +# input. It documents whether the current command invoked by the trace hook is +# run interactively by the user; it's set immediately after the prompt hook, +# and unset as soon as the trace hook is run. +__bp_preexec_interactive_mode="" + +__bp_trim_whitespace() { + local var=$@ + var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters + var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters + echo -n "$var" +} + +# This function is installed as part of the PROMPT_COMMAND; +# It sets a variable to indicate that the prompt was just displayed, +# to allow the DEBUG trap to know that the next command is likely interactive. +__bp_interactive_mode() { + __bp_preexec_interactive_mode="on"; +} + +__bp_precmd_invoke_cmd_loop() { + # Invoke every function defined in our function array. + local precmd_function + for precmd_function in "${precmd_functions[@]}"; do + + # Only execute this function if it actually exists. + # Test existence of functions with: declare -[Ff] + if type -t "$precmd_function" 1>/dev/null; then + __bp_set_ret_value "$__bp_last_ret_value" "$__bp_last_argument_prev_command" + # Quote our function invocation to prevent issues with IFS + if (( __bp_time_functions > 0 )) ; then + echo "$precmd_function" + time "$precmd_function" + else + "$precmd_function" + fi + fi + done +} + +# This function is installed as part of the PROMPT_COMMAND. +# It will invoke any functions defined in the precmd_functions array. +__bp_precmd_invoke_cmd() { + # Save the returned value from our last command. Note: this MUST be the + # first thing done in this function. + __bp_last_ret_value="$?" + + # Don't invoke precmds if we are inside an execution of an "original + # prompt command" by another precmd execution loop. This avoids infinite + # recursion. + if (( __bp_inside_precmd > 0 )); then + return + fi + local __bp_inside_precmd=1 + + if (( __bp_time_functions > 0 )) ; then + time __bp_precmd_invoke_cmd_loop + echo "total" + else + __bp_precmd_invoke_cmd_loop + fi +} + +# Sets a return value in $?. We may want to get access to the $? variable in our +# precmd functions. This is available for instance in zsh. We can simulate it in bash +# by setting the value here. +__bp_set_ret_value() { + return $1 +} + +__bp_in_prompt_command() { + + local prompt_command_array + IFS=';' read -ra prompt_command_array <<< "$PROMPT_COMMAND" + + local trimmed_arg + IFS= read -r trimmed_arg < <(__bp_trim_whitespace "$1") + + local command + for command in "${prompt_command_array[@]}"; do + local trimmed_command + IFS= read -r trimmed_command < <(__bp_trim_whitespace "$command") + # Only execute each function if it actually exists. + if [[ "$trimmed_command" == "$trimmed_arg" ]]; then + return 0 + fi + done + + return 1 +} + +__bp_preexec_invoke_exec_loop() { + # If none of the previous checks have returned out of this function, then + # the command is in fact interactive and we should invoke the user's + # preexec functions. + + # Invoke every function defined in our function array. + local preexec_function + local preexec_function_ret_value + local preexec_ret_value=0 + for preexec_function in "${preexec_functions[@]}"; do + + # Only execute each function if it actually exists. + # Test existence of function with: declare -[fF] + if type -t "$preexec_function" 1>/dev/null; then + __bp_set_ret_value $__bp_last_ret_value + # Quote our function invocation to prevent issues with IFS + if (( __bp_time_functions > 0 )) ; then + echo "$preexec_function" + time "$preexec_function" "$this_command" + else + "$preexec_function" "$this_command" + fi + + preexec_function_ret_value="$?" + if [[ "$preexec_function_ret_value" != 0 ]]; then + preexec_ret_value="$preexec_function_ret_value" + fi + fi + done + + # Restore the last argument of the last executed command, and set the return + # value of the DEBUG trap to be the return code of the last preexec function + # to return an error. + # If `extdebug` is enabled a non-zero return value from any preexec function + # will cause the user's command not to execute. + # Run `shopt -s extdebug` to enable + __bp_set_ret_value "$preexec_ret_value" "$__bp_last_argument_prev_command" +} + +# This function is installed as the DEBUG trap. It is invoked before each +# interactive prompt display. Its purpose is to inspect the current +# environment to attempt to detect if the current command is being invoked +# interactively, and invoke 'preexec' if so. +__bp_preexec_invoke_exec() { + # Save the contents of $_ so that it can be restored later on. + # https://stackoverflow.com/questions/40944532/bash-preserve-in-a-debug-trap#40944702 + __bp_last_argument_prev_command="$1" + + # Don't invoke preexecs if we are inside of another preexec. + if (( __bp_inside_preexec > 0 )); then + return + fi + local __bp_inside_preexec=1 + + # Checks if the file descriptor is not standard out (i.e. '1') + # __bp_delay_install checks if we're in test. Needed for bats to run. + # Prevents preexec from being invoked for functions in PS1 + if [[ ! -t 1 && -z "$__bp_delay_install" ]]; then + return + fi + + if [[ -n "$COMP_LINE" ]]; then + # We're in the middle of a completer. This obviously can't be + # an interactively issued command. + return + fi + if [[ -z "$__bp_preexec_interactive_mode" ]]; then + # We're doing something related to displaying the prompt. Let the + # prompt set the title instead of me. + return + else + # If we're in a subshell, then the prompt won't be re-displayed to put + # us back into interactive mode, so let's not set the variable back. + # In other words, if you have a subshell like + # (sleep 1; sleep 2) + # You want to see the 'sleep 2' as a set_command_title as well. + if [[ 0 -eq "$BASH_SUBSHELL" ]]; then + __bp_preexec_interactive_mode="" + fi + fi + + if __bp_in_prompt_command "$BASH_COMMAND"; then + # If we're executing something inside our prompt_command then we don't + # want to call preexec. Bash prior to 3.1 can't detect this at all :/ + __bp_preexec_interactive_mode="" + return + fi + + local this_command + local _ + IFS=" " read -r _ this_command < <( HISTTIMEFORMAT= builtin history 1 ) + + # Sanity check to make sure we have something to invoke our function with. + if [[ -z "$this_command" ]]; then + return + fi + + if (( __bp_time_functions > 0 )) ; then + time __bp_preexec_invoke_exec_loop + echo "total" + else + __bp_preexec_invoke_exec_loop + fi +} + +__bp_install() { + # Exit if we already have this installed. + if [[ "$PROMPT_COMMAND" == *"__bp_precmd_invoke_cmd"* ]]; then + return 1; + fi + + trap '__bp_preexec_invoke_exec "$_"' DEBUG + + # Preserve any prior DEBUG trap as a preexec function + local prior_trap + IFS= read -r prior_trap < <( sed "s/[^']*'\(.*\)'[^']*/\1/" <<<"$__bp_trap_string" ) + unset __bp_trap_string + if [[ -n "$prior_trap" ]]; then + eval '__bp_original_debug_trap() { + '"$prior_trap"' + }' + preexec_functions+=(__bp_original_debug_trap) + fi + + # Adjust our HISTCONTROL Variable if needed. + __bp_adjust_histcontrol + + + # Issue #25. Setting debug trap for subshells causes sessions to exit for + # backgrounded subshell commands (e.g. (pwd)& ). Believe this is a bug in Bash. + # + # Disabling this by default. It can be enabled by setting this variable. + if [[ -n "$__bp_enable_subshells" ]]; then + + # Set so debug trap will work be invoked in subshells. + set -o functrace > /dev/null 2>&1 + shopt -s extdebug > /dev/null 2>&1 + fi; + + # Install our hooks in PROMPT_COMMAND to allow our trap to know when we've + # actually entered something. + PROMPT_COMMAND="__bp_precmd_invoke_cmd; __bp_interactive_mode" + + # Add two functions to our arrays for convenience + # of definition. + precmd_functions+=(precmd) + preexec_functions+=(preexec) + + # Since this function is invoked via PROMPT_COMMAND, re-execute PC now that it's properly set + eval "$PROMPT_COMMAND" +} + +# Sets our trap and __bp_install as part of our PROMPT_COMMAND to install +# after our session has started. This allows bash-preexec to be inlucded +# at any point in our bash profile. Ideally we could set our trap inside +# __bp_install, but if a trap already exists it'll only set locally to +# the function. +__bp_install_after_session_init() { + + # Make sure this is bash that's running this and return otherwise. + if [[ -z "$BASH_VERSION" ]]; then + return 1; + fi + + # If there's an existing PROMPT_COMMAND capture it and convert it into a function + # So it is preserved and invoked during precmd. + if [[ -n "$PROMPT_COMMAND" ]]; then + eval '__bp_original_prompt_command() { + '"$PROMPT_COMMAND"' + }' + precmd_functions+=(__bp_original_prompt_command) + fi + + # Installation is finalized in PROMPT_COMMAND, which allows us to override the DEBUG + # trap. __bp_install sets PROMPT_COMMAND to its final value, so these are only + # invoked once. + # It's necessary to clear any existing DEBUG trap in order to set it from the install function. + # Using \n as it's the most universal delimiter of bash commands + PROMPT_COMMAND=$'\n__bp_trap_string="$(trap -p DEBUG)"\ntrap DEBUG\n__bp_install\n' +} + +# Run our install so long as we're not delaying it. +if [[ -z "$__bp_delay_install" ]]; then + __bp_install_after_session_init +fi; diff --git a/.bashrc.d/04-colors.sh b/.bashrc.d/04-colors.sh new file mode 100755 index 0000000..6730e55 --- /dev/null +++ b/.bashrc.d/04-colors.sh @@ -0,0 +1,21 @@ +#! /bin/bash + +COLORSOFF='\033[0m' + +RED='\033[00;31m' +GREEN='\033[00;32m' +YELLOW='\033[00;33m' +BLUE='\033[00;34m' +PURPLE='\033[00;35m' +CYAN='\033[00;36m' +LIGHTGRAY='\033[00;37m' + +LRED='\033[01;31m' +LGREEN='\033[01;32m' +LYELLOW='\033[01;33m' +LBLUE='\033[01;34m' +LPURPLE='\033[01;35m' +LCYAN='\033[01;36m' +WHITE='\033[01;37m' + +export CLICOLOR=1 diff --git a/.bashrc.d/05-prompt.sh b/.bashrc.d/05-prompt.sh new file mode 100755 index 0000000..423970f --- /dev/null +++ b/.bashrc.d/05-prompt.sh @@ -0,0 +1,203 @@ +#! /bin/bash +__bashrc_prompt_timings=${__bashrc_prompt_timings:-0} + +function tmux_set_title { + if [ ! -z "$TMUX" ] ; then + printf '\033]2;%s\033\\' "$1" + fi +} + + +function middle_truncate { + local max=$(($1)) + + local mid + local rem + local left + local right + + IFS= read -r str + local len=${#str} + + if ((len <= max)) ; then + echo -n "$str" + return + fi + + if ((max == 1)) ; then + echo -n "${str:0:1}"$'\U00002026' + return + fi + + mid=$((len / 2)) + rem=$((len - max + 1)) + left=$((rem / 2)) + right=$((rem - left)) + + echo "${str:0:$((mid - left))}"$'\U00002026'"${str:$((mid + right))}" +} + +function add_preexec_function { + local func="$1" + for each in "${preexec_functions[@]}" ; do + [ "$each" = "$func" ] && return 1 + done + + preexec_functions+=("$func") + + return 0 +} + +function add_precmd_function { + local func="$1" + for each in "${precmd_functions[@]}" ; do + [ "$each" = "$func" ] && return 1 + done + + precmd_functions+=("$func") + + return 0 +} + +function seconds_since_epoch { + date '+%s' +} + +function __precmd_debug_timings { + PS4='+ $EPOCHREALTIME\011 ' + exec 3>&2 2>/tmp/bashstart.$$.log + set -x +} + +if ((__bashrc_prompt_timings)) ; then + add_precmd_function __precmd_debug_timings +fi + +function __preexec_tmux_title { + local this_command="$1" + local TRUNC_PWD + local TRUNC_CMD + + IFS= read -r TRUNC_PWD < <(basename "$PWD") + IFS= read -r TRUNC_PWD < <(middle_truncate 8 <<< "$TRUNC_PWD") + IFS= read -r TRUNC_CMD < <(middle_truncate 12 <<< "$this_command") + + tmux_set_title "$TRUNC_PWD - $TRUNC_CMD" +} + +add_preexec_function __preexec_tmux_title + +function __precmd_ran_once { + PROMPT_COMMAND_ONCE=1 +} + +add_precmd_function __precmd_ran_once + +function __precmd_tmux_title { + local TRUNC_PWD + + if [[ "$PWD" == "$HOME" ]] ; then + tmux_set_title "" + else + IFS= read -r TRUNC_PWD < <(basename "$PWD") + IFS= read -r TRUNC_PWD < <(middle_truncate 20 <<< "$TRUNC_PWD") + + tmux_set_title "$TRUNC_PWD" + fi +} + +add_precmd_function __precmd_tmux_title + +PROMPT_HOOKS=() + +function git_prompty { + local OUTPUT + local SOMETHING + local UPSTREAM + local FAILURE + local STATUS + local TMP + + IFS= read -r -d '' STATUS < <( git status --porcelain 2>/dev/null || echo 'FATAL') + + if [[ "$STATUS" =~ ^FATAL ]] ; then + return + fi + + IFS= read -r -d '' OUTPUT < <(grep -o '^..' <<< "$STATUS") + + echo -n "\[${GREEN}\][ git: " + + IFS= read -r UPSTREAM < <(git rev-list --count '@{upstream}..HEAD' 2>/dev/null) + if ((UPSTREAM > 0)) ; then + echo -n "${PURPLE}ahead ${UPSTREAM} ${GREEN}| " + fi + + if [[ "$OUTPUT" =~ "M" ]]; then + SOMETHING=1 + echo -n "\[${YELLOW}\]~ " + fi + + if [[ "$OUTPUT" =~ "R" ]] ; then + SOMETHING=1 + echo -n "\[${YELLOW}\]> " + fi + + if [[ "$OUTPUT" =~ "D" ]] ; then + SOMETHING=1 + echo -n "\[${RED}\]- " + fi + + if [[ "$OUTPUT" =~ "A" ]] ; then + SOMETHING=1 + echo -n "\[${GREEN}\]+ " + fi + + if ((!SOMETHING)) ; then + echo -n "\[${CYAN}\]= " + fi + + echo -n "\[${GREEN}\]] ${COLORSOFF}" +} + +function __precmd_host_prompt { + local RANDOM_CHARS=( + ">" + ) + + local RANDOM_CHAR="${RANDOM_CHARS[RANDOM % ${#RANDOM_CHARS[@]}]}" + + local HOSTY="$(hostname)" + + if [ "$(type -t __host_alts)" == "function" ] ; then + __host_alts "$HOSTY" + fi + + local NEW_PROMPT='\u@'"$HOSTY"':\w '"$(git_prompty)\n\[${GREEN}\]${PROMPT_CHAR:-$RANDOM_CHAR}\[${COLORSOFF}\] " + + for each in "${PROMPT_HOOKS[@]}" ; do + $each "$NEW_PROMPT" + + NEW_PROMPT="${PROMPT_HOOK_RESULT:-${NEW_PROMPT}}" + done + + export PS1="$NEW_PROMPT" +} + +add_precmd_function __precmd_host_prompt + +function __precmd_debug_timings_end { + set +x + exec 2>&3 3>&- +} + +if ((__bashrc_prompt_timings)) ; then + add_precmd_function __precmd_debug_timings_end +fi + +function __main { + local CURDIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" +} + +__main +unset -f __main diff --git a/.bashrc.d/10-tmux.sh b/.bashrc.d/10-tmux.sh new file mode 100755 index 0000000..dcce21f --- /dev/null +++ b/.bashrc.d/10-tmux.sh @@ -0,0 +1,29 @@ +#! /bin/bash + +function tmux() { + local SOMMELIER=$(which sommelier 2>/dev/null) + if [[ ! -z "$SOMMELIER" ]] ; then + SOMMELIER="$SOMMELIER -X --glamor" + fi + if [[ $# -eq 0 ]] ; then + command $SOMMELIER tmux new-session \; new-window \; new-window \; new-window \; new-window \; new-window + else + command $SOMMELIER tmux "$@" + fi +} + +tmxsync () { + export _TMUX_SYNC=1; + for w in $(tmux lsw -F '#{window_index}#{window_active}'|sed -ne 's/0$//p'); do + tmux joinp -d -b -s $w -v -t $(tmux lsp -F '#{pane_index}'|tail -n 1) + done + tmux setw synchronize-panes +} +tmxunsync () { + [ -z "$_TMUX_SYNC" ] && return + for p in $(tmux lsp -F '#{pane_index}#{pane_active}' | sed -ne 's/0$//p'); do + tmux breakp -d -t 1 + done + unset _TMUX_SYNC + tmux setw synchronize-panes +} diff --git a/.bashrc.d/20-git.sh b/.bashrc.d/20-git.sh new file mode 100755 index 0000000..95157d3 --- /dev/null +++ b/.bashrc.d/20-git.sh @@ -0,0 +1,50 @@ +#! /bin/bash +function git { + + if [ "$1" == "push" ] ; then + git log @{upstream}.. + fi + + local HASHES= + local PULLSTATUS= + if [ "$1" == "pull" ] && [ "$OSTYPE" != "msys" ] ; then + local SCRIPTTMP="$(mktemp)" + local SCRIPTCOMMAND=("script" "--return" "-c" "git $*" "$SCRIPTTMP") + if [ "$(type -t script)" == "file" ] ; then + SCRIPTCOMMAND=("script" "-q" "$SCRIPTTMP" "git" "$@") + fi + + "${SCRIPTCOMMAND[@]}" + + IFS= read -r HASHES < <(grep -i -o -E '[0-9a-f]+\.\.[0-9a-f]+' "$SCRIPTTMP") + + rm "$SCRIPTTMP" + + if [ ! -z "$HASHES" ] ; then + git diff "$HASHES" + fi + else + command git "$@" + fi +} + +alias gO='git push' +alias gI='git pull' +alias gOoh='git push -u origin HEAD' +alias gC='git commit' +alias gCa='git commit -a' +alias gco='git checkout' +alias gcou='git checkout HEAD^' +alias ga='git add' +alias gad='git add .' +alias gap='git add -p' +alias gs='git stash' +alias gd='git diff' +alias gcob='git checkout -b' +alias gm='git merge' +alias gr='git reset' +alias gR='git reset --hard' +alias grb='git rebase' +alias gl='git log' +alias cdg='cd "$(git rev-parse --show-toplevel)"' +alias hub='git-hub' diff --git a/.bashrc.d/30-fzf.bash b/.bashrc.d/30-fzf.bash new file mode 100755 index 0000000..88eb741 --- /dev/null +++ b/.bashrc.d/30-fzf.bash @@ -0,0 +1,16 @@ +#! /bin/bash +# Setup fzf +# --------- +if [[ ! "$PATH" == *$HOME/.vim/plugged/fzf/bin* ]]; then + export PATH="$PATH:$HOME/.vim/plugged/fzf/bin" +fi + +# Auto-completion +# --------------- +[[ $- == *i* ]] && source "$HOME/.vim/plugged/fzf/shell/completion.bash" 2> /dev/null + +# Key bindings +# ------------ +source "$HOME/.vim/plugged/fzf/shell/key-bindings.bash" + +bind -x '"\C-p":"fzf-file-widget"' diff --git a/.bashrc.d/99-aliases.sh b/.bashrc.d/99-aliases.sh new file mode 100755 index 0000000..f34866f --- /dev/null +++ b/.bashrc.d/99-aliases.sh @@ -0,0 +1,65 @@ +#! /bin/bash +# Random aliases without a home +function xo { + if which open &>/dev/null ; then + open "$@" + else + xdg-open "$@" + fi +} + +function set_aws_profile { + local PROFILES=$(grep '\[' "$HOME/.aws/credentials" | tr '[]' ' ') + + if [ -n "$1" ] ; then + local COUNT=$(($1)) + local ACCOUNT + while read ACCOUNT ; do + ((COUNT--)) + if ((!COUNT)) ; then + break + fi + done < <(echo "$PROFILES") + + export AWS_PROFILE="$ACCOUNT" + else + echo "AWS Profiles: " + echo "$PROFILES" | nl + + echo " +Syntax: ${FUNCNAME[0]} +" + fi +} + +function yarn { + if which yarnpkg &>/dev/null ; then + yarnpkg "$@" + else + command yarn "$@" + fi +} + +function vim { + if which nvim &>/dev/null ; then + nvim "$@" + else + command vim "$@" + fi +} + +function dotnet { + if which dotnet-sdk.dotnet 2>&1 >/dev/null ; then + dotnet-sdk.dotnet "$@" + else + command dotnet "$@" + fi +} + +alias ...='cd ..' + +whichrm=$(which grm rm 2>/dev/null | head -1) + +function rm { + $whichrm -I "$@" +} diff --git a/.bashrc.d/99-archivebox.sh b/.bashrc.d/99-archivebox.sh new file mode 100755 index 0000000..339c026 --- /dev/null +++ b/.bashrc.d/99-archivebox.sh @@ -0,0 +1,12 @@ +#! /bin/bash + + +function archivebox { + local ARGS=() + if [ "$1" == "add" ] ; then + shift + ARGS+=("add" "--extract" "singlefile,title,favicon") + fi + ARGS+=("$@") + CHROME_USER_DATA_DIR="$HOME/.config/archivebox/chrome_profile" CHROME_USER_AGENT='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36' TIMEOUT=120 command archivebox "${ARGS[@]}" +} diff --git a/.bashrc.d/99-direnv.sh b/.bashrc.d/99-direnv.sh new file mode 100755 index 0000000..1c0a94a --- /dev/null +++ b/.bashrc.d/99-direnv.sh @@ -0,0 +1,37 @@ +#! /bin/bash +direnv() { + if [ "$1" == "allow" ] || [ "$1" == "check" ] ; then + cat "$2/.envrc" + echo + echo -e "${YELLOW}If you really want to allow the above file, use \`direnv really\`${COLORSOFF}" + + return + fi + + if [ "$1" == "really" ] ; then + shift + command direnv allow "$@" + + return + fi + + command direnv "$@" +} + +__precmd_direnv_hook() { + which direnv 2>&1 >/dev/null || return + IFS= read -r DIRENV < <(direnv export bash) + eval "$DIRENV" +} + +__main() { + alias dea='direnv allow' + alias der='direnv really' + + local DIRENV + + add_precmd_function __precmd_direnv_hook +} + +__main +unset -f __main diff --git a/.bashrc.d/99-docker.sh b/.bashrc.d/99-docker.sh new file mode 100755 index 0000000..5e230b6 --- /dev/null +++ b/.bashrc.d/99-docker.sh @@ -0,0 +1 @@ +#alias docker="docker.js" diff --git a/.bashrc.d/99-flutter.sh b/.bashrc.d/99-flutter.sh new file mode 100755 index 0000000..67fd13a --- /dev/null +++ b/.bashrc.d/99-flutter.sh @@ -0,0 +1,43 @@ +function cdf { + local CURDIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" + local FILENAMES=() + + local GROOT="$(git rev-parse --show-toplevel 2>/dev/null)" + + if [[ -z "$GROOT" ]] ; then + echo "Not a git repo!" + fi + + # bash on macos will not handle exclamation marks in math expressions correctly! + while read FILENAME ; do + if [[ $(yq -r '.flutter != null' "$FILENAME") != true ]] ; then + continue + fi + if [[ $(yq -r '.flutter != null and .flutter.plugin != null' "$FILENAME") == true ]] ; then + continue + fi + + FILENAME="$(readlink -m "$(dirname "$FILENAME")")" + FILENAMES+=("$FILENAME") + done < <( find "$GROOT" -iname 'pubspec.yaml' ) + + local LAUNCH_JSON="$GROOT/.vscode/launch.json" + if [[ ${#FILENAMES[@]} -gt 0 ]] ; then + while read VSCODEPATH ; do + VSCODEPATH="$(readlink -m "$GROOT/$VSCODEPATH")" + for FILENAME in "${FILENAMES[@]}" ; do + if [[ "$FILENAME" == "$VSCODEPATH" ]] ; then + cd "$FILENAME" + return + fi + done + done < <( dart run "$CURDIR/cdf/bin/cdf.dart" "$LAUNCH_JSON" ) + + for FILENAME in "${FILENAMES[@]}" ; do + cd "$FILENAME" + return + done + fi + + echo 'No matching dart projects!' +} diff --git a/.bashrc.d/99-node.sh b/.bashrc.d/99-node.sh new file mode 100755 index 0000000..c052131 --- /dev/null +++ b/.bashrc.d/99-node.sh @@ -0,0 +1,4 @@ +#! /bin/bash +node_add_debug () { + node ~/.bashrc.d/node-commands.js add_debug +} diff --git a/.bashrc.d/99-overcast.sh b/.bashrc.d/99-overcast.sh new file mode 100755 index 0000000..b136814 --- /dev/null +++ b/.bashrc.d/99-overcast.sh @@ -0,0 +1,8 @@ +# Overcast Tab completion +_overcast_completions() { + local cur=${COMP_WORDS[COMP_CWORD]} + COMPREPLY=($(compgen -W "`overcast completions`" -- "$cur")) + return 0 +} + +which overcast 2>&1 >/dev/null && complete -F _overcast_completions overcast diff --git a/.bashrc.d/99-recovery.sh b/.bashrc.d/99-recovery.sh new file mode 100755 index 0000000..c9420a2 --- /dev/null +++ b/.bashrc.d/99-recovery.sh @@ -0,0 +1,7 @@ +#! /bin/bash +mount_chroot () { + sudo mount "$1" "$2" || return $? + for each in dev proc sys run ; do + sudo mount --bind "/$each" "$2/$each" + done +} diff --git a/.bashrc.d/99-windows.sh b/.bashrc.d/99-windows.sh new file mode 100755 index 0000000..a673a61 --- /dev/null +++ b/.bashrc.d/99-windows.sh @@ -0,0 +1,16 @@ +#! /bin/bash +function __main() { + local GARBAGE + # Placeholder for WSL, etc. +} + +function docker-machine-env-windows() { + eval $(docker-machine.exe env --shell bash "$@" | sed -e 's@\\@/@g' -e 's@"\([a-zA-Z]\):/@"/mnt/\L\1/@g') +} + +function fixcodepage() { + cmd.exe /c "chcp 850 && $* && chcp 65001 || chcp 65001" +} + +__main +unset -f __main; diff --git a/.bashrc.d/cdf/.gitignore b/.bashrc.d/cdf/.gitignore new file mode 100644 index 0000000..c3399b7 --- /dev/null +++ b/.bashrc.d/cdf/.gitignore @@ -0,0 +1,3 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ diff --git a/.bashrc.d/cdf/CHANGELOG.md b/.bashrc.d/cdf/CHANGELOG.md new file mode 100644 index 0000000..13dda2a --- /dev/null +++ b/.bashrc.d/cdf/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/.bashrc.d/cdf/README.md b/.bashrc.d/cdf/README.md new file mode 100644 index 0000000..3c12931 --- /dev/null +++ b/.bashrc.d/cdf/README.md @@ -0,0 +1,2 @@ +A sample command-line application with an entrypoint in `bin/`, library code +in `lib/`, and example unit test in `test/`. diff --git a/.bashrc.d/cdf/analysis_options.yaml b/.bashrc.d/cdf/analysis_options.yaml new file mode 100644 index 0000000..57ff5a1 --- /dev/null +++ b/.bashrc.d/cdf/analysis_options.yaml @@ -0,0 +1,30 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:lints/recommended.yaml + +# Uncomment the following section to specify additional rules. + +# linter: +# rules: +# - camel_case_types + +# analyzer: +# exclude: +# - path/to/excluded/files/** + +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/.bashrc.d/cdf/bin/cdf.dart b/.bashrc.d/cdf/bin/cdf.dart new file mode 100644 index 0000000..413e2bd --- /dev/null +++ b/.bashrc.d/cdf/bin/cdf.dart @@ -0,0 +1,8 @@ +import 'package:cdf/cdf.dart' as cdf; + +Future main(List arguments) async { + final cwds = await cdf.loadVsCodeTargets(arguments[0]); + for (final cwd in cwds) { + print(cwd); + } +} diff --git a/.bashrc.d/cdf/lib/cdf.dart b/.bashrc.d/cdf/lib/cdf.dart new file mode 100644 index 0000000..6fcf8d6 --- /dev/null +++ b/.bashrc.d/cdf/lib/cdf.dart @@ -0,0 +1,25 @@ +import 'dart:io'; + +import 'package:json5/json5.dart'; + +Future> loadVsCodeTargets(String path) async { + final contents = await File(path).readAsString(); + final data = JSON5.parse(contents); + final cfgs = data['configurations'] as List; + final cwds = []; + for (final cfg in cfgs) { + final type = cfg['type'] as String; + if (type != 'dart') { + continue; + } + + String? cwd = cfg['cwd'] as String?; + if (cwd == null) { + continue; + } + + cwds.add(cwd); + } + + return cwds; +} diff --git a/.bashrc.d/cdf/pubspec.lock b/.bashrc.d/cdf/pubspec.lock new file mode 100644 index 0000000..f04aa0d --- /dev/null +++ b/.bashrc.d/cdf/pubspec.lock @@ -0,0 +1,381 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "36a321c3d2cbe01cbcb3540a87b8843846e0206df3e691fa7b23e19e78de6d49" + url: "https://pub.dev" + source: hosted + version: "65.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: dfe03b90ec022450e22513b5e5ca1f01c0c01de9c3fba2f7fd233cb57a6b9a07 + url: "https://pub.dev" + source: hosted + version: "6.3.0" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" + url: "https://pub.dev" + source: hosted + version: "1.7.2" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json5: + dependency: "direct main" + description: + name: json5 + sha256: b67d6e06c9e225c8277d3c43f796677af7975a2a2b0669ff12ba38ff466a31f4 + url: "https://pub.dev" + source: hosted + version: "0.8.2" + lints: + dependency: "direct dev" + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + meta: + dependency: transitive + description: + name: meta + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: "direct dev" + description: + name: test + sha256: "3d028996109ad5c253674c7f347822fb994a087614d6f353e6039704b4661ff2" + url: "https://pub.dev" + source: hosted + version: "1.25.0" + test_api: + dependency: transitive + description: + name: test_api + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + test_core: + dependency: transitive + description: + name: test_core + sha256: "2bc4b4ecddd75309300d8096f781c0e3280ca1ef85beda558d33fcbedc2eead4" + url: "https://pub.dev" + source: hosted + version: "0.6.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: a2662fb1f114f4296cf3f5a50786a2d888268d7776cf681aa17d660ffa23b246 + url: "https://pub.dev" + source: hosted + version: "14.0.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.2.3 <4.0.0" diff --git a/.bashrc.d/cdf/pubspec.yaml b/.bashrc.d/cdf/pubspec.yaml new file mode 100644 index 0000000..66fd738 --- /dev/null +++ b/.bashrc.d/cdf/pubspec.yaml @@ -0,0 +1,16 @@ +name: cdf +description: A sample command-line application. +version: 1.0.0 +# repository: https://github.com/my_org/my_repo + +environment: + sdk: ^3.2.3 + +# Add regular dependencies here. +dependencies: + json5: ^0.8.2 + # path: ^1.8.0 + +dev_dependencies: + lints: ^2.1.0 + test: ^1.24.0 diff --git a/.bashrc.d/cdf/test/cdf_test.dart b/.bashrc.d/cdf/test/cdf_test.dart new file mode 100644 index 0000000..bb433fe --- /dev/null +++ b/.bashrc.d/cdf/test/cdf_test.dart @@ -0,0 +1,8 @@ +import 'package:cdf/cdf.dart'; +import 'package:test/test.dart'; + +void main() { + test('calculate', () { + expect(calculate(), 42); + }); +} diff --git a/.bashrc.d/node-commands.js b/.bashrc.d/node-commands.js new file mode 100644 index 0000000..0c2edbb --- /dev/null +++ b/.bashrc.d/node-commands.js @@ -0,0 +1,20 @@ +const shell = require('shelljs'); +const fs = require('fs').promises; +const scriptName = process.argv[2] +const scripts = { + add_debug: () => { + shell.config.fatal = true; + shell.exec('yarn add nodemon'); + const packagePath = process.cwd() + '/package.json'; + const package = require(packagePath); + package.scripts = package.scripts || {}; + package.scripts.debug = 'nodemon -- --inspect-brk ./index.js'; + return Promise.resolve() + .then(() => fs.writeFile(packagePath, JSON.stringify(package, null, 4), 'utf8')); + } +}; + +scripts[scriptName]() + .catch(e => { + process.exit(1); + }); diff --git a/.bashrc.d/package.json b/.bashrc.d/package.json new file mode 100644 index 0000000..ff1c13b --- /dev/null +++ b/.bashrc.d/package.json @@ -0,0 +1,10 @@ +{ + "name": "bashrc", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "private": true, + "dependencies": { + "shelljs": "^0.8.2" + } +} diff --git a/.bashrc.d/yarn.lock b/.bashrc.d/yarn.lock new file mode 100644 index 0000000..f0da606 --- /dev/null +++ b/.bashrc.d/yarn.lock @@ -0,0 +1,108 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +glob@^7.0.0: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +interpret@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-parse@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + +resolve@^1.1.6: + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== + dependencies: + path-parse "^1.0.5" + +shelljs@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" + integrity sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= diff --git a/.config/dark-mode-notify/.DS_Store.bak b/.config/dark-mode-notify/.DS_Store.bak new file mode 120000 index 0000000..34ca9a1 --- /dev/null +++ b/.config/dark-mode-notify/.DS_Store.bak @@ -0,0 +1 @@ +/home/empathicqubit/dotfiles/setup/../.config/dark-mode-notify/.DS_Store.bak \ No newline at end of file diff --git a/.config/dark-mode-notify/.DS_Store.bak.bak b/.config/dark-mode-notify/.DS_Store.bak.bak new file mode 100644 index 0000000000000000000000000000000000000000000000000000000000000000..f5198ed1ef837d5740d9a7abc7f70bd1361e52abefb7b797bd0d1c32b2f6d041 GIT binary patch literal 6148 zcmeHKOH0E*5Z>*>rW7Fug&qT5i>68r;w8lT2aM=Jr6#0kFlI|0_D~8r>mTx$_-EVdtyO|HN55^ex%4p1($rv-BA#zk21kH`EmJUYba*ilmPSLjfEXYKh=J{7 zK%WQ3U^~mFs)+$&;0Fe9f3Tn-x*98ma_fK&ug~c3AfkYdZwW+8qpPt}2p$lwQUO&e z*G~+t(!p-&I9Fq(P^B|2SB81?%Jt)g%hkbd$#BM9h13%R#K0y4Z8bFU{J(%-rty)# znL;CCfEf5^4DimxpLkG|K3l()hi9z??ExAJ##N|*fWC1FfC26!L+Mn03w4NdHC767 T7PQNBK)MJ>LZ~AKeu056ya`Hj literal 0 HcmV?d00001 diff --git a/.config/dark-mode-notify/dark-mode-notify b/.config/dark-mode-notify/dark-mode-notify new file mode 120000 index 0000000..9d1926b --- /dev/null +++ b/.config/dark-mode-notify/dark-mode-notify @@ -0,0 +1 @@ +/home/empathicqubit/dotfiles/setup/../.config/dark-mode-notify \ No newline at end of file diff --git a/.config/dark-mode-notify/run.d/daynight.applescript b/.config/dark-mode-notify/run.d/daynight.applescript new file mode 100644 index 0000000..a552068 --- /dev/null +++ b/.config/dark-mode-notify/run.d/daynight.applescript @@ -0,0 +1,31 @@ +property waitKey : 0.001 +property waitTransition : 0.25 +on run argv + set darkMode to item 1 of argv + set settingsString to item 2 of argv + + activate application "Microsoft Teams" + tell application "System Events" + key code 53 + delay waitTransition + tell process "Microsoft Teams" + click menu item settingsString of menu "Microsoft Teams" of menu bar 1 + end tell + delay waitTransition + + keystroke tab + delay waitKey + + if darkMode is "1" then + key code 124 # right arrow + delay waitKey + end if + + keystroke return + delay waitKey + key code 53 + delay waitTransition + + keystroke tab using command down + end tell +end run diff --git a/.config/dark-mode-notify/run.d/teams.sh b/.config/dark-mode-notify/run.d/teams.sh new file mode 100755 index 0000000..b5e9261 --- /dev/null +++ b/.config/dark-mode-notify/run.d/teams.sh @@ -0,0 +1,17 @@ +#! /bin/bash + +export PATH="$PATH:/opt/homebrew/bin" +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +jq -r '..|.language? | select(.)' storage.json | head -1 + +TEAMS_PATH="$(dirname "$(ps -x -o command | grep Contents/MacOS/Teams | grep -v grep)")" +if [ -z "$TEAMS_PATH" ] ; then + exit 0; +fi + +STORAGE_FILE="$HOME/Library/Application Support/Microsoft/Teams/storage.json" +TEAMS_LOCALE="$(jq -r '..|.language? | select(.)' "$STORAGE_FILE" | head -1)" +LOCALE_FILE="$TEAMS_PATH/../Resources/locales/locale-$TEAMS_LOCALE.json" +SETTINGS_STRING="$(jq -r .strings.usertask_settings "$LOCALE_FILE")" + +osascript "$SCRIPT_DIR/daynight.applescript" "$DARKMODE" "$SETTINGS_STRING" diff --git a/.config/i3-layout-manager/layouts/layout-NEATDONK.json b/.config/i3-layout-manager/layouts/layout-NEATDONK.json new file mode 100644 index 0000000..e7b711c --- /dev/null +++ b/.config/i3-layout-manager/layouts/layout-NEATDONK.json @@ -0,0 +1,458 @@ +[ + { + "border": "normal", + "floating": "auto_off", + "layout": "splith", + "percent": 1, + "type": "con", + "nodes": [ + { + "border": "normal", + "floating": "auto_off", + "layout": "splitv", + "percent": 0.25, + "type": "con", + "nodes": [ + { + "border": "normal", + "floating": "auto_off", + "layout": "tabbed", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 106, + "x": 0, + "y": 0 + }, + "name": " - Terminal", + "percent": 0.333333333333333, + "swallows": [ + { + "title": "[Tt]erminal" + } + ], + "type": "con" + }, + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 114, + "x": 0, + "y": 0 + }, + "name": "lsnes: Messages", + "percent": 0.333333333333333, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Messages" + } + ], + "type": "con" + }, + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 122, + "x": 0, + "y": 0 + }, + "name": "lsnes rr2-β24 [null core]", + "percent": 0.333333333333333, + "swallows": [ + { + "class": "^Lsnes$", + "title": "null " + } + ], + "type": "con" + } + ] + }, + { + "border": "normal", + "floating": "auto_off", + "layout": "tabbed", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 1914, + "x": 0, + "y": 0 + }, + "name": "lsnes rr2-β24 [bsnes v085 (Compatibility core)]", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Compatibility" + } + ], + "type": "con" + }, + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 634, + "x": 0, + "y": 0 + }, + "name": "lsnes: Messages", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Messages" + } + ], + "type": "con" + } + ] + } + ] + }, + { + "border": "normal", + "floating": "auto_off", + "layout": "splitv", + "percent": 0.25, + "type": "con", + "nodes": [ + { + "border": "normal", + "floating": "auto_off", + "layout": "tabbed", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 954, + "x": 0, + "y": 0 + }, + "name": "lsnes rr2-β24 [bsnes v085 (Compatibility core)]", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Compatibility" + } + ], + "type": "con" + }, + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 474, + "x": 0, + "y": 0 + }, + "name": "lsnes: Messages", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Messages" + } + ], + "type": "con" + } + ] + }, + { + "border": "normal", + "floating": "auto_off", + "layout": "tabbed", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 378, + "x": 0, + "y": 0 + }, + "name": "lsnes rr2-β24 [bsnes v085 (Compatibility core)]", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Compatibility" + } + ], + "type": "con" + }, + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 234, + "x": 0, + "y": 0 + }, + "name": "lsnes: Messages", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Messages" + } + ], + "type": "con" + } + ] + } + ] + }, + { + "border": "normal", + "floating": "auto_off", + "layout": "splitv", + "percent": 0.25, + "type": "con", + "nodes": [ + { + "border": "normal", + "floating": "auto_off", + "layout": "tabbed", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 314, + "x": 0, + "y": 0 + }, + "name": "lsnes rr2-β24 [bsnes v085 (Compatibility core)]", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Compatibility" + } + ], + "type": "con" + }, + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 208, + "x": 0, + "y": 0 + }, + "name": "lsnes: Messages", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Messages" + } + ], + "type": "con" + } + ] + }, + { + "border": "normal", + "floating": "auto_off", + "layout": "tabbed", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 269, + "x": 0, + "y": 0 + }, + "name": "lsnes rr2-β24 [bsnes v085 (Compatibility core)]", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Compatibility" + } + ], + "type": "con" + }, + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 154, + "x": 0, + "y": 0 + }, + "name": "lsnes: Messages", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Messages" + } + ], + "type": "con" + } + ] + } + ] + }, + { + "border": "normal", + "floating": "auto_off", + "layout": "splitv", + "percent": 0.25, + "type": "con", + "nodes": [ + { + "border": "normal", + "floating": "auto_off", + "layout": "tabbed", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 186, + "x": 0, + "y": 0 + }, + "name": "lsnes rr2-β24 [bsnes v085 (Compatibility core)]", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Compatibility" + } + ], + "type": "con" + }, + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 132, + "x": 0, + "y": 0 + }, + "name": "lsnes: Messages", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Messages" + } + ], + "type": "con" + } + ] + }, + { + "border": "normal", + "floating": "auto_off", + "layout": "tabbed", + "percent": 0.5, + "type": "con", + "nodes": [ + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 168, + "x": 0, + "y": 0 + }, + "name": "lsnes rr2-β24 [bsnes v085 (Compatibility core)]", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Compatibility" + } + ], + "type": "con" + }, + { + "border": "normal", + "current_border_width": 3, + "floating": "auto_off", + "geometry": { + "height": 1030, + "width": 141, + "x": 0, + "y": 0 + }, + "name": "lsnes: Messages", + "percent": 0.5, + "swallows": [ + { + "class": "^Lsnes$", + "title": "Messages" + } + ], + "type": "con" + } + ] + } + ] + } + ] + } +] diff --git a/.config/i3/.gitignore b/.config/i3/.gitignore new file mode 100644 index 0000000..2501b66 --- /dev/null +++ b/.config/i3/.gitignore @@ -0,0 +1 @@ +local.sh diff --git a/.config/i3/config b/.config/i3/config new file mode 100644 index 0000000..23e4a25 --- /dev/null +++ b/.config/i3/config @@ -0,0 +1,247 @@ +# vim: syntax=i3config + +# This file has been auto-generated by i3-config-wizard(1). +# It will not be overwritten, so edit it as you like. +# +# Should you change your keyboard layout some time, delete +# this file and re-run i3-config-wizard(1). +# + +# i3 config file (v4) +# +# Please see https://i3wm.org/docs/userguide.html for a complete reference! + +no_focus [class=".*"] +set $mod Mod4 + +# Font for window titles. Will also be used by the bar unless a different font +# is used in the bar {} block below. +font pango:monospace 8 + +# This font is widely installed, provides lots of unicode glyphs, right-to-left +# text rendering and scalability on retina/hidpi displays (thanks to pango). +#font pango:DejaVu Sans Mono 8 + +# Window colors +for_window [class="Firefox"] title_format "%title" +for_window [class="(?i)office"] title_format "%title" +for_window [class="Code"] title_format "%title" +for_window [class="keepassxc"] title_format "%title" + +for_window [class="Firefox" floating] sticky enable + +# Misc window rules + +exec --no-startup-id "~/.vim/plugged/i3-battery-popup/i3-battery-popup -n" +for_window [title="Battery Warning"] sticky enable + +bindsym $mod+semicolon exec xfce4-screensaver-command --activate + +# Cannabilize some xfce services +exec --no-startup-id xfsettingsd +exec --no-startup-id xfce4-screensaver + +bindsym $mod+Shift+e exec code ~/.config/i3 + +bindsym $mod+Escape exec ~/.config/i3/nerd-dictation.sh begin +bindsym $mod+Shift+Escape exec ~/.config/i3/nerd-dictation.sh end + +bindsym Print exec xfce4-screenshooter + +exec_always --no-startup-id "~/.config/i3/wallpaper.sh" + +# Local modifications that won't work with every computer + +exec "~/.config/i3/local.sh" + +exec --no-startup-id "gxkb" + +exec --no-startup-id "fcitx -d" + +exec --no-startup-id "xbattbar -c" + +bindsym $mod+m exec --no-startup-id "~/.vim/plugged/i3-layout-manager/layout_manager.sh" +bindsym $mod+d exec --no-startup-id "i3-dmenu-desktop" + +exec_always --no-startup-id exec i3-workspace-names-daemon + +exec dex -ae i3 + +bindsym $mod+F1 exec "cat ~/.config/i3/config | zenity --text-info --filename=/dev/stdin" +bindsym $mod+F2 exec setxkbmap us -variant dvorak-intl +bindsym $mod+F3 exec setxkbmap us +bindsym $mod+F4 exec setxkbmap de -variant neo +bindsym $mod+F7 exec --no-startup-id "~/.config/i3/screen-switcher.sh" + +# Use pactl to adjust volume in PulseAudio. +set $refresh_i3status killall -SIGUSR1 i3status +bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +5% && $refresh_i3status +bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -5% && $refresh_i3status +bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status +bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status + +# Playback controls +bindsym XF86AudioPlay exec playerctl play-pause +bindsym XF86AudioPause exec playerctl play-pause +bindsym XF86AudioNext exec playerctl next +bindsym XF86AudioPrev exec playerctl previous + +#Brightness +bindsym XF86MonBrightnessUp exec --no-startup-id bash -c 'b=$(xrandr --verbose | grep -i brightness | head -n 1 | cut -d" " -f2) && b2=$(echo -e "import math\nf = lambda x: (1 - 1/(1+math.exp(4*x-2)))\nprint(\\\"%.2f\\\" % f(0.1+$b))" | python) && xrandr --output DP-4 --brightness $b2' +bindsym XF86MonBrightnessDown exec --no-startup-id bash -c 'b=$(xrandr --verbose | grep -i brightness | head -n 1 | cut -d" " -f2) && b2=$(echo -e "import math\nf = lambda x: (1 - 1/(1+math.exp(4*x-2)))\nprint(\\\"%.2f\\\" % f(-0.1+$b))" | python) && xrandr --output DP-4 --brightness $b2' + +# Use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# start a terminal +bindsym $mod+Return exec i3-sensible-terminal + +# kill focused window +bindsym $mod+q kill + +# start dmenu (a program launcher) +bindsym $mod+space exec dmenu_run +# There also is the (new) i3-dmenu-desktop which only displays applications +# shipping a .desktop file. It is a wrapper around dmenu, so you need that +# installed. +# bindsym $mod+d exec --no-startup-id i3-dmenu-desktop + +# change focus +bindsym $mod+h focus left +bindsym $mod+j focus down +bindsym $mod+k focus up +bindsym $mod+l focus right + +# alternatively, you can use the cursor keys: +bindsym $mod+Left focus left +bindsym $mod+Down focus down +bindsym $mod+Up focus up +bindsym $mod+Right focus right + +# move focused window +bindsym $mod+Shift+h move left +bindsym $mod+Shift+j move down +bindsym $mod+Shift+k move up +bindsym $mod+Shift+l move right + +# alternatively, you can use the cursor keys: +bindsym $mod+Shift+Left move left +bindsym $mod+Shift+Down move down +bindsym $mod+Shift+Up move up +bindsym $mod+Shift+Right move right + +# split in horizontal orientation +bindsym $mod+v split h + +# split in vertical orientation +bindsym $mod+s split v + +# enter fullscreen mode for the focused container +bindsym $mod+f fullscreen toggle + +# change container layout (stacked, tabbed, toggle split) +bindsym $mod+minus layout stacking +bindsym $mod+Tab layout tabbed +bindsym $mod+backslash layout toggle split + +bindsym $mod+t sticky toggle + +# toggle tiling / floating +bindsym $mod+Shift+f floating toggle + +bindsym $mod+bracketright move scratchpad +bindsym $mod+Shift+bracketright [workspace=__focused__] move scratchpad +bindsym $mod+bracketleft scratchpad show +bindsym $mod+Shift+bracketleft floating toggle + +# change focus between tiling / floating windows +bindsym $mod+plus focus mode_toggle + +# focus the parent container +bindsym $mod+a focus parent + +# focus the child container +#bindsym $mod+d focus child + +# Define names for default workspaces for which we configure key bindings later on. +# We use variables to avoid repeating the names in multiple places. +set $ws1 "1" +set $ws2 "2" +set $ws3 "3" +set $ws4 "4" +set $ws5 "5" +set $ws6 "6" +set $ws7 "7" +set $ws8 "8" +set $ws9 "9" +set $ws10 "10" + +bindsym $mod+1 workspace number $ws1 +bindsym $mod+2 workspace number $ws2 +bindsym $mod+3 workspace number $ws3 +bindsym $mod+4 workspace number $ws4 +bindsym $mod+5 workspace number $ws5 +bindsym $mod+6 workspace number $ws6 +bindsym $mod+7 workspace number $ws7 +bindsym $mod+8 workspace number $ws8 +bindsym $mod+9 workspace number $ws9 +bindsym $mod+0 workspace number $ws10 + +# move focused container to workspace +bindsym $mod+Shift+1 move container to workspace number $ws1 +bindsym $mod+Shift+2 move container to workspace number $ws2 +bindsym $mod+Shift+3 move container to workspace number $ws3 +bindsym $mod+Shift+4 move container to workspace number $ws4 +bindsym $mod+Shift+5 move container to workspace number $ws5 +bindsym $mod+Shift+6 move container to workspace number $ws6 +bindsym $mod+Shift+7 move container to workspace number $ws7 +bindsym $mod+Shift+8 move container to workspace number $ws8 +bindsym $mod+Shift+9 move container to workspace number $ws9 +bindsym $mod+Shift+0 move container to workspace number $ws10 + +# Reset all window positions to root +bindsym $mod+p [tiling workspace="__focused__"] move workspace "__reorder__"; [workspace="__reorder__"] move workspace current + +# reload the configuration file +bindsym $mod+Shift+r reload +# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) +bindsym $mod+Shift+p restart +# exit i3 (logs you out of your X session) +bindsym $mod+Shift+q exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -B 'Yes, exit i3' 'i3-msg exit'" + +# resize window (you can also use the mouse for that) +mode "resize" { + # These bindings trigger as soon as you enter the resize mode + + # Pressing left will shrink the window’s width. + # Pressing right will grow the window’s width. + # Pressing up will shrink the window’s height. + # Pressing down will grow the window’s height. + bindsym h resize shrink width 10 px or 10 ppt + bindsym j resize grow height 10 px or 10 ppt + bindsym k resize shrink height 10 px or 10 ppt + bindsym l resize grow width 10 px or 10 ppt + + # same bindings, but for the arrow keys + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Down resize grow height 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt + bindsym Right resize grow width 10 px or 10 ppt + + # back to normal: Enter or Escape or $mod+r + bindsym Return mode "default" + bindsym Escape mode "default" + bindsym $mod+p mode "default" +} + +bindsym $mod+r mode "resize" + +## Start i3bar to display a workspace bar (plus the system information i3status +## finds out, if available) +#bar { +# position top +# tray_output primary +# status_command i3status --config ~/.config/i3/i3status.conf +#} + +exec --no-startup-id "xfce4-panel --disable-wm-check" diff --git a/.config/i3/i3status.conf b/.config/i3/i3status.conf new file mode 100644 index 0000000..45df5e8 --- /dev/null +++ b/.config/i3/i3status.conf @@ -0,0 +1,62 @@ +general { + colors = true + interval = 5 +} + +order += "disk /" +order += "disk /home" +order += "memory" +order += "cpu_usage" +order += "load" +order += "wireless _first_" +order += "ethernet _first_" +order += "tztime local" +order += "battery all" + +cpu_usage { + format= "CPU %usage" + max_threshold= 75 +} + +wireless _first_ { + format_up = "W (%bitrate) %ip" + format_down = "" +} + +ethernet _first_ { + format_up = "E %ip (%speed)" + format_down = "" +} + +battery all { + format = "%status %emptytime" + format_down = "" + status_chr = "🔌" + status_bat = "🔋" + status_unk = "UNK" + status_full = "🔋💯" + path = "/sys/class/power_supply/BAT%d/uevent" + low_threshold = 10 +} + +tztime local { + format = "%Y-%m-%d %H:%M" +} + +load { + format = "🏋️ %1min %5min %15min" +} + +memory { + format = "🧠 %percentage_used" + threshold_degraded = "10%" + format_degraded = "MEMORY: %free" +} + +disk "/" { + format = "💾 %percentage_used" +} + +disk "/home" { + format = "🏠 %percentage_used" +} diff --git a/.config/i3/nerd-dictation.sh b/.config/i3/nerd-dictation.sh new file mode 100644 index 0000000..473a0f4 diff --git a/.config/i3/wallpaper-reddit.sh b/.config/i3/wallpaper-reddit.sh new file mode 100755 index 0000000..9abafba --- /dev/null +++ b/.config/i3/wallpaper-reddit.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# date: 2018-06-26 +# version: 2.3 +# author: xereeto +# licence: wtfpl + +tries=0 +trap "exit 1" TERM +export TOP_PID=$$ +CACHE_FOLDER="$HOME/.cache/xereeto-wallpaper" +CONFIG_FOLDER="$HOME/.config/xereeto-wallpaper" +[[ -z $DISPLAY ]] && export DISPLAY=:0 +[[ -d "$CACHE_FOLDER" ]] || mkdir -p "$CACHE_FOLDER" +[[ -d "$CONFIG_FOLDER" ]] || mkdir -p "$CONFIG_FOLDER" +[[ -f "$CONFIG_FOLDER/subreddits" ]] || echo -e "wallpapers\nwallpaper\nearthporn\nspaceporn" > "$CONFIG_FOLDER/subreddits" +addJpegIfImgur(){ + while read url; do + isImgur=$(echo "$url" | grep imgur); + url=$(echo $url | sed -e 's/"url": "//' -e 's/",//' -e 's/gallery\///') + [[ -z "$isImgur" ]] && echo $url || echo $url | sed -e 's/$/\.jpg/' + done +} +startOver(){ + getWallpaper "shitsfucked" +} +wallargs=() +getWallpaper(){ + local time=`date +%s-%N` + local this_wallpaper="$CACHE_FOLDER/$time.jpg" + if [[ $tries > 10 ]]; then echo "too many failed attempts, exiting"; kill -s TERM $TOP_PID; fi + tries=$((tries+1)) + [[ -z "$1" ]] || echo "that didn't work, let's try again" + echo "getting wallpaper..." + curl -s -A "/u/xereeto's wallpaper bot" https://www.reddit.com/r/`grep -v "#" "$CONFIG_FOLDER/subreddits" | shuf -n 1`/.json | jq -r '.data.children[] | .data.url' | addJpegIfImgur | shuf -n 1 - | xargs wget --quiet -O "$this_wallpaper" 2>/dev/null + return + width=$(identify -format %w "$this_wallpaper") 2>/dev/null + height=$(identify -format %h "$this_wallpaper") 2>/dev/null + [[ "$width" -ge 1920 && "$height" -ge 1050 ]] || startOver + wallargs+=("--bg-fill" "$this_wallpaper") + tries=0 +} +NUMACTIVE=$(xrandr --listactivemonitors | head -1 | awk '{print $NF}') +for (( i=0; i/dev/null || startOver +echo "hope you like your new wp" diff --git a/.config/i3/wallpaper.sh b/.config/i3/wallpaper.sh new file mode 100755 index 0000000..3f72f26 --- /dev/null +++ b/.config/i3/wallpaper.sh @@ -0,0 +1,15 @@ +#!/bin/bash +WALLPAPERDIR="$HOME/Bilder/Wallpapers" +NUMACTIVE=$(xrandr --listactivemonitors | head -1 | awk '{print $NF}') +mkdir -p "$WALLPAPERDIR" +wallargs=() +while read FILENAME ; do + echo "$FILENAME" + wallargs+=("--bg-fill" "$FILENAME") + echo "${wallargs[@]}" +done < <( find "$WALLPAPERDIR" -type f | shuf -n "$NUMACTIVE" - ) +if [[ "${#wallargs[@]}" -eq 0 ]] ; then + exit 1 +fi +echo feh "${wallargs[@]}" +feh "${wallargs[@]}" diff --git a/.config/pip/pip.conf b/.config/pip/pip.conf new file mode 100644 index 0000000..5d3eda9 --- /dev/null +++ b/.config/pip/pip.conf @@ -0,0 +1,2 @@ +[global] +break-system-packages = true diff --git a/.config/xfce4/terminal/accels.scm b/.config/xfce4/terminal/accels.scm new file mode 100644 index 0000000..ed5d0f3 --- /dev/null +++ b/.config/xfce4/terminal/accels.scm @@ -0,0 +1,58 @@ +; xfce4-terminal GtkAccelMap rc-file -*- scheme -*- +; this file is an automated accelerator map dump +; +(gtk_accel_path "/terminal-window/goto-tab-2" "2") +(gtk_accel_path "/terminal-window/goto-tab-9" "9") +; (gtk_accel_path "/terminal-window/copy-input" "") +; (gtk_accel_path "/terminal-window/close-other-tabs" "") +; (gtk_accel_path "/terminal-window/move-tab-right" "Page_Down") +(gtk_accel_path "/terminal-window/goto-tab-7" "7") +; (gtk_accel_path "/terminal-window/set-title-color" "") +; (gtk_accel_path "/terminal-window/edit-menu" "") +; (gtk_accel_path "/terminal-window/zoom-menu" "") +(gtk_accel_path "/terminal-window/goto-tab-1" "1") +; (gtk_accel_path "/terminal-window/fullscreen" "F11") +; (gtk_accel_path "/terminal-window/read-only" "") +(gtk_accel_path "/terminal-window/goto-tab-5" "5") +; (gtk_accel_path "/terminal-window/preferences" "") +; (gtk_accel_path "/terminal-window/reset-and-clear" "") +; (gtk_accel_path "/terminal-window/about" "") +(gtk_accel_path "/terminal-window/goto-tab-4" "4") +; (gtk_accel_path "/terminal-window/close-window" "q") +; (gtk_accel_path "/terminal-window/reset" "") +; (gtk_accel_path "/terminal-window/save-contents" "") +(gtk_accel_path "/terminal-window/toggle-menubar" "F10") +; (gtk_accel_path "/terminal-window/copy" "c") +; (gtk_accel_path "/terminal-window/copy-html" "") +; (gtk_accel_path "/terminal-window/last-active-tab" "") +; (gtk_accel_path "/terminal-window/show-borders" "") +; (gtk_accel_path "/terminal-window/view-menu" "") +; (gtk_accel_path "/terminal-window/detach-tab" "d") +; (gtk_accel_path "/terminal-window/scroll-on-output" "") +; (gtk_accel_path "/terminal-window/show-toolbar" "") +; (gtk_accel_path "/terminal-window/next-tab" "Page_Down") +; (gtk_accel_path "/terminal-window/tabs-menu" "") +; (gtk_accel_path "/terminal-window/search-next" "") +; (gtk_accel_path "/terminal-window/search-prev" "") +; (gtk_accel_path "/terminal-window/undo-close-tab" "") +; (gtk_accel_path "/terminal-window/set-title" "s") +; (gtk_accel_path "/terminal-window/contents" "F1") +; (gtk_accel_path "/terminal-window/zoom-reset" "0") +; (gtk_accel_path "/terminal-window/close-tab" "w") +; (gtk_accel_path "/terminal-window/new-tab" "t") +; (gtk_accel_path "/terminal-window/new-window" "n") +; (gtk_accel_path "/terminal-window/terminal-menu" "") +; (gtk_accel_path "/terminal-window/show-menubar" "") +; (gtk_accel_path "/terminal-window/select-all" "a") +; (gtk_accel_path "/terminal-window/paste" "v") +; (gtk_accel_path "/terminal-window/move-tab-left" "Page_Up") +; (gtk_accel_path "/terminal-window/search" "f") +; (gtk_accel_path "/terminal-window/file-menu" "") +; (gtk_accel_path "/terminal-window/prev-tab" "Page_Up") +; (gtk_accel_path "/terminal-window/paste-selection" "") +; (gtk_accel_path "/terminal-window/zoom-in" "plus") +; (gtk_accel_path "/terminal-window/zoom-out" "minus") +(gtk_accel_path "/terminal-window/goto-tab-8" "8") +; (gtk_accel_path "/terminal-window/help-menu" "") +(gtk_accel_path "/terminal-window/goto-tab-3" "3") +(gtk_accel_path "/terminal-window/goto-tab-6" "6") diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..93fcede --- /dev/null +++ b/.gitconfig @@ -0,0 +1,42 @@ +[user] + name=empathicqubit + email=empathicqubit@entan.gl + +[diff "bin"] + textconv = xxd +[diff] + colorMoved=zebra +[core] + autoclrf=input + trustctime=false +[mergetool.fugitive] + cmd=vim -f -c Gvdiff "$MERGED" +[mergetool.kdiff3] + path="C:/Program Files/KDiff3/kdiff3.exe" + trustExitCode=false +[mergetool "vscode"] + cmd = code --wait $MERGED +[merge] + renamelimit=24000 + tool=fugitive +[branch] + autosetuprebase=always +[bash] + enableGitStatus = true + enableStatusSymbol = true +[push] + default = simple + +[alias] + lg = !"git lg1" + lg1 = !"git lg1-specific --all" + lg2 = !"git lg2-specific --all" + lg3 = !"git lg3-specific --all" + + branches = !"git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads | less" + + lg1-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)' + lg2-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(auto)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' + lg3-specific = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset) %C(bold cyan)(committed: %cD)%C(reset) %C(auto)%d%C(reset)%n'' %C(white)%s%C(reset)%n'' %C(dim white)- %an <%ae> %C(reset) %C(dim white)(committer: %cn <%ce>)%C(reset)' +[init] + defaultBranch = main diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6192290 --- /dev/null +++ b/.gitignore @@ -0,0 +1,71 @@ +* + +# Includes must go first! + +# Folders + +!/.bashrc.d/ +!/.bashrc.d/** + +!/.config/ + +!/.config/i3/ +!/.config/i3/** + +!/.config/pip/ +!/.config/pip/** + +!/.config/i3-layout-manager/ +!/.config/i3-layout-manager/** + +!/.config/dark-mode-notify*/ +!/.config/dark-mode-notify*/** + +!/.config/xfce4/ +!/.config/xfce4/** + +!/.tmux/ +!/.tmux/* +!/.tmux/plugins/tpm/** + +!/.vim/ +!/.vim/** + +!/script/ +!/script/** + +!/setup/ +!/setup/** + +# Files + +!/.bash_aliases +!/.bash_logout +!/.gitconfig +!/.ideavimrc +!/.inputrc +!/.nvim +!/.nvimrc +!/.tern-project +!/.tmux.config +!/.vimrc +!/.vsvimrc +!/.Xmodmap + +!/yarn.lock +!/.gitignore + +# Then the generic excludes after + +*.s[^c]? +node_modules/ +.netrwhist +.bashrc.local.d/ +.vim/plugged + +*.log +*.orig +*.rej + +.layout_backup.txt +all-layouts.json diff --git a/.ideavimrc b/.ideavimrc new file mode 100644 index 0000000..21f2449 --- /dev/null +++ b/.ideavimrc @@ -0,0 +1 @@ +imap jj diff --git a/.inputrc b/.inputrc new file mode 100644 index 0000000..a8529c7 --- /dev/null +++ b/.inputrc @@ -0,0 +1,5 @@ +set editing-mode vi + +set keymap vi-insert + +"jj": vi-movement-mode diff --git a/.nvim b/.nvim new file mode 120000 index 0000000..d38e244 --- /dev/null +++ b/.nvim @@ -0,0 +1 @@ +.vim \ No newline at end of file diff --git a/.nvimrc b/.nvimrc new file mode 120000 index 0000000..3f48b16 --- /dev/null +++ b/.nvimrc @@ -0,0 +1 @@ +.vimrc \ No newline at end of file diff --git a/.tern-project b/.tern-project new file mode 100644 index 0000000..adf1f11 --- /dev/null +++ b/.tern-project @@ -0,0 +1,5 @@ +{ + "plugins": { + "node": {} + } +} diff --git a/.vim/autoload/plug.vim b/.vim/autoload/plug.vim new file mode 100644 index 0000000..57f6066 --- /dev/null +++ b/.vim/autoload/plug.vim @@ -0,0 +1,2503 @@ +" vim-plug: Vim plugin manager +" ============================ +" +" Download plug.vim and put it in ~/.vim/autoload +" +" curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ +" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim +" +" Edit your .vimrc +" +" call plug#begin('~/.vim/plugged') +" +" " Make sure you use single quotes +" +" " Shorthand notation; fetches https://github.com/junegunn/vim-easy-align +" Plug 'junegunn/vim-easy-align' +" +" " Any valid git URL is allowed +" Plug 'https://github.com/junegunn/vim-github-dashboard.git' +" +" " Multiple Plug commands can be written in a single line using | separators +" Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets' +" +" " On-demand loading +" Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' } +" Plug 'tpope/vim-fireplace', { 'for': 'clojure' } +" +" " Using a non-master branch +" Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' } +" +" " Using a tagged release; wildcard allowed (requires git 1.9.2 or above) +" Plug 'fatih/vim-go', { 'tag': '*' } +" +" " Plugin options +" Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' } +" +" " Plugin outside ~/.vim/plugged with post-update hook +" Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' } +" +" " Unmanaged plugin (manually installed and updated) +" Plug '~/my-prototype-plugin' +" +" " Initialize plugin system +" call plug#end() +" +" Then reload .vimrc and :PlugInstall to install plugins. +" +" Plug options: +" +"| Option | Description | +"| ----------------------- | ------------------------------------------------ | +"| `branch`/`tag`/`commit` | Branch/tag/commit of the repository to use | +"| `rtp` | Subdirectory that contains Vim plugin | +"| `dir` | Custom directory for the plugin | +"| `as` | Use different name for the plugin | +"| `do` | Post-update hook (string or funcref) | +"| `on` | On-demand loading: Commands or ``-mappings | +"| `for` | On-demand loading: File types | +"| `frozen` | Do not update unless explicitly specified | +" +" More information: https://github.com/junegunn/vim-plug +" +" +" Copyright (c) 2017 Junegunn Choi +" +" MIT License +" +" Permission is hereby granted, free of charge, to any person obtaining +" a copy of this software and associated documentation files (the +" "Software"), to deal in the Software without restriction, including +" without limitation the rights to use, copy, modify, merge, publish, +" distribute, sublicense, and/or sell copies of the Software, and to +" permit persons to whom the Software is furnished to do so, subject to +" the following conditions: +" +" The above copyright notice and this permission notice shall be +" included in all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +if exists('g:loaded_plug') + finish +endif +let g:loaded_plug = 1 + +let s:cpo_save = &cpo +set cpo&vim + +let s:plug_src = 'https://github.com/junegunn/vim-plug.git' +let s:plug_tab = get(s:, 'plug_tab', -1) +let s:plug_buf = get(s:, 'plug_buf', -1) +let s:mac_gui = has('gui_macvim') && has('gui_running') +let s:is_win = has('win32') || has('win64') +let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win) +let s:vim8 = has('patch-8.0.0039') && exists('*job_start') +let s:me = resolve(expand(':p')) +let s:base_spec = { 'branch': 'master', 'frozen': 0 } +let s:TYPE = { +\ 'string': type(''), +\ 'list': type([]), +\ 'dict': type({}), +\ 'funcref': type(function('call')) +\ } +let s:loaded = get(s:, 'loaded', {}) +let s:triggers = get(s:, 'triggers', {}) + +function! plug#begin(...) + if a:0 > 0 + let s:plug_home_org = a:1 + let home = s:path(fnamemodify(expand(a:1), ':p')) + elseif exists('g:plug_home') + let home = s:path(g:plug_home) + elseif !empty(&rtp) + let home = s:path(split(&rtp, ',')[0]) . '/plugged' + else + return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.') + endif + if fnamemodify(home, ':t') ==# 'plugin' && fnamemodify(home, ':h') ==# s:first_rtp + return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.') + endif + + let g:plug_home = home + let g:plugs = {} + let g:plugs_order = [] + let s:triggers = {} + + call s:define_commands() + return 1 +endfunction + +function! s:define_commands() + command! -nargs=+ -bar Plug call plug#() + if !executable('git') + return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.') + endif + command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(0, []) + command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(0, []) + command! -nargs=0 -bar -bang PlugClean call s:clean(0) + command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif + command! -nargs=0 -bar PlugStatus call s:status() + command! -nargs=0 -bar PlugDiff call s:diff() + command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(0, ) +endfunction + +function! s:to_a(v) + return type(a:v) == s:TYPE.list ? a:v : [a:v] +endfunction + +function! s:to_s(v) + return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n" +endfunction + +function! s:glob(from, pattern) + return s:lines(globpath(a:from, a:pattern)) +endfunction + +function! s:source(from, ...) + let found = 0 + for pattern in a:000 + for vim in s:glob(a:from, pattern) + execute 'source' s:esc(vim) + let found = 1 + endfor + endfor + return found +endfunction + +function! s:assoc(dict, key, val) + let a:dict[a:key] = add(get(a:dict, a:key, []), a:val) +endfunction + +function! s:ask(message, ...) + call inputsave() + echohl WarningMsg + let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) ')) + echohl None + call inputrestore() + echo "\r" + return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0 +endfunction + +function! s:ask_no_interrupt(...) + try + return call('s:ask', a:000) + catch + return 0 + endtry +endfunction + +function! plug#end() + if !exists('g:plugs') + return s:err('Call plug#begin() first') + endif + + if exists('#PlugLOD') + augroup PlugLOD + autocmd! + augroup END + augroup! PlugLOD + endif + let lod = { 'ft': {}, 'map': {}, 'cmd': {} } + + if exists('g:did_load_filetypes') + filetype off + endif + for name in g:plugs_order + if !has_key(g:plugs, name) + continue + endif + let plug = g:plugs[name] + if get(s:loaded, name, 0) || !has_key(plug, 'on') && !has_key(plug, 'for') + let s:loaded[name] = 1 + continue + endif + + if has_key(plug, 'on') + let s:triggers[name] = { 'map': [], 'cmd': [] } + for cmd in s:to_a(plug.on) + if cmd =~? '^.\+' + if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i')) + call s:assoc(lod.map, cmd, name) + endif + call add(s:triggers[name].map, cmd) + elseif cmd =~# '^[A-Z]' + let cmd = substitute(cmd, '!*$', '', '') + if exists(':'.cmd) != 2 + call s:assoc(lod.cmd, cmd, name) + endif + call add(s:triggers[name].cmd, cmd) + else + call s:err('Invalid `on` option: '.cmd. + \ '. Should start with an uppercase letter or ``.') + endif + endfor + endif + + if has_key(plug, 'for') + let types = s:to_a(plug.for) + if !empty(types) + augroup filetypedetect + call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim') + augroup END + endif + for type in types + call s:assoc(lod.ft, type, name) + endfor + endif + endfor + + for [cmd, names] in items(lod.cmd) + execute printf( + \ 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "", , , , %s)', + \ cmd, string(cmd), string(names)) + endfor + + for [map, names] in items(lod.map) + for [mode, map_prefix, key_prefix] in + \ [['i', '', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']] + execute printf( + \ '%snoremap %s %s:call lod_map(%s, %s, %s, "%s")', + \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix) + endfor + endfor + + for [ft, names] in items(lod.ft) + augroup PlugLOD + execute printf('autocmd FileType %s call lod_ft(%s, %s)', + \ ft, string(ft), string(names)) + augroup END + endfor + + call s:reorg_rtp() + filetype plugin indent on + if has('vim_starting') + if has('syntax') && !exists('g:syntax_on') + syntax enable + end + else + call s:reload_plugins() + endif +endfunction + +function! s:loaded_names() + return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)') +endfunction + +function! s:load_plugin(spec) + call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim') +endfunction + +function! s:reload_plugins() + for name in s:loaded_names() + call s:load_plugin(g:plugs[name]) + endfor +endfunction + +function! s:trim(str) + return substitute(a:str, '[\/]\+$', '', '') +endfunction + +function! s:version_requirement(val, min) + for idx in range(0, len(a:min) - 1) + let v = get(a:val, idx, 0) + if v < a:min[idx] | return 0 + elseif v > a:min[idx] | return 1 + endif + endfor + return 1 +endfunction + +function! s:git_version_requirement(...) + if !exists('s:git_version') + let s:git_version = map(split(split(s:system('git --version'))[2], '\.'), 'str2nr(v:val)') + endif + return s:version_requirement(s:git_version, a:000) +endfunction + +function! s:progress_opt(base) + return a:base && !s:is_win && + \ s:git_version_requirement(1, 7, 1) ? '--progress' : '' +endfunction + +if s:is_win + function! s:rtp(spec) + return s:path(a:spec.dir . get(a:spec, 'rtp', '')) + endfunction + + function! s:path(path) + return s:trim(substitute(a:path, '/', '\', 'g')) + endfunction + + function! s:dirpath(path) + return s:path(a:path) . '\' + endfunction + + function! s:is_local_plug(repo) + return a:repo =~? '^[a-z]:\|^[%~]' + endfunction +else + function! s:rtp(spec) + return s:dirpath(a:spec.dir . get(a:spec, 'rtp', '')) + endfunction + + function! s:path(path) + return s:trim(a:path) + endfunction + + function! s:dirpath(path) + return substitute(a:path, '[/\\]*$', '/', '') + endfunction + + function! s:is_local_plug(repo) + return a:repo[0] =~ '[/$~]' + endfunction +endif + +function! s:err(msg) + echohl ErrorMsg + echom '[vim-plug] '.a:msg + echohl None +endfunction + +function! s:warn(cmd, msg) + echohl WarningMsg + execute a:cmd 'a:msg' + echohl None +endfunction + +function! s:esc(path) + return escape(a:path, ' ') +endfunction + +function! s:escrtp(path) + return escape(a:path, ' ,') +endfunction + +function! s:remove_rtp() + for name in s:loaded_names() + let rtp = s:rtp(g:plugs[name]) + execute 'set rtp-='.s:escrtp(rtp) + let after = globpath(rtp, 'after') + if isdirectory(after) + execute 'set rtp-='.s:escrtp(after) + endif + endfor +endfunction + +function! s:reorg_rtp() + if !empty(s:first_rtp) + execute 'set rtp-='.s:first_rtp + execute 'set rtp-='.s:last_rtp + endif + + " &rtp is modified from outside + if exists('s:prtp') && s:prtp !=# &rtp + call s:remove_rtp() + unlet! s:middle + endif + + let s:middle = get(s:, 'middle', &rtp) + let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])') + let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)') + let rtp = join(map(rtps, 'escape(v:val, ",")'), ',') + \ . ','.s:middle.',' + \ . join(map(afters, 'escape(v:val, ",")'), ',') + let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g') + let s:prtp = &rtp + + if !empty(s:first_rtp) + execute 'set rtp^='.s:first_rtp + execute 'set rtp+='.s:last_rtp + endif +endfunction + +function! s:doautocmd(...) + if exists('#'.join(a:000, '#')) + execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '' : '') join(a:000) + endif +endfunction + +function! s:dobufread(names) + for name in a:names + let path = s:rtp(g:plugs[name]).'/**' + for dir in ['ftdetect', 'ftplugin'] + if len(finddir(dir, path)) + if exists('#BufRead') + doautocmd BufRead + endif + return + endif + endfor + endfor +endfunction + +function! plug#load(...) + if a:0 == 0 + return s:err('Argument missing: plugin name(s) required') + endif + if !exists('g:plugs') + return s:err('plug#begin was not called') + endif + let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000 + let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)') + if !empty(unknowns) + let s = len(unknowns) > 1 ? 's' : '' + return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', '))) + end + let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)') + if !empty(unloaded) + for name in unloaded + call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) + endfor + call s:dobufread(unloaded) + return 1 + end + return 0 +endfunction + +function! s:remove_triggers(name) + if !has_key(s:triggers, a:name) + return + endif + for cmd in s:triggers[a:name].cmd + execute 'silent! delc' cmd + endfor + for map in s:triggers[a:name].map + execute 'silent! unmap' map + execute 'silent! iunmap' map + endfor + call remove(s:triggers, a:name) +endfunction + +function! s:lod(names, types, ...) + for name in a:names + call s:remove_triggers(name) + let s:loaded[name] = 1 + endfor + call s:reorg_rtp() + + for name in a:names + let rtp = s:rtp(g:plugs[name]) + for dir in a:types + call s:source(rtp, dir.'/**/*.vim') + endfor + if a:0 + if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2)) + execute 'runtime' a:1 + endif + call s:source(rtp, a:2) + endif + call s:doautocmd('User', name) + endfor +endfunction + +function! s:lod_ft(pat, names) + let syn = 'syntax/'.a:pat.'.vim' + call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn) + execute 'autocmd! PlugLOD FileType' a:pat + call s:doautocmd('filetypeplugin', 'FileType') + call s:doautocmd('filetypeindent', 'FileType') +endfunction + +function! s:lod_cmd(cmd, bang, l1, l2, args, names) + call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) + call s:dobufread(a:names) + execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args) +endfunction + +function! s:lod_map(map, names, with_prefix, prefix) + call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) + call s:dobufread(a:names) + let extra = '' + while 1 + let c = getchar(0) + if c == 0 + break + endif + let extra .= nr2char(c) + endwhile + + if a:with_prefix + let prefix = v:count ? v:count : '' + let prefix .= '"'.v:register.a:prefix + if mode(1) == 'no' + if v:operator == 'c' + let prefix = "\" . prefix + endif + let prefix .= v:operator + endif + call feedkeys(prefix, 'n') + endif + call feedkeys(substitute(a:map, '^', "\", '') . extra) +endfunction + +function! plug#(repo, ...) + if a:0 > 1 + return s:err('Invalid number of arguments (1..2)') + endif + + try + let repo = s:trim(a:repo) + let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec + let name = get(opts, 'as', fnamemodify(repo, ':t:s?\.git$??')) + let spec = extend(s:infer_properties(name, repo), opts) + if !has_key(g:plugs, name) + call add(g:plugs_order, name) + endif + let g:plugs[name] = spec + let s:loaded[name] = get(s:loaded, name, 0) + catch + return s:err(v:exception) + endtry +endfunction + +function! s:parse_options(arg) + let opts = copy(s:base_spec) + let type = type(a:arg) + if type == s:TYPE.string + let opts.tag = a:arg + elseif type == s:TYPE.dict + call extend(opts, a:arg) + if has_key(opts, 'dir') + let opts.dir = s:dirpath(expand(opts.dir)) + endif + else + throw 'Invalid argument type (expected: string or dictionary)' + endif + return opts +endfunction + +function! s:infer_properties(name, repo) + let repo = a:repo + if s:is_local_plug(repo) + return { 'dir': s:dirpath(expand(repo)) } + else + if repo =~ ':' + let uri = repo + else + if repo !~ '/' + throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo) + endif + let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git') + let uri = printf(fmt, repo) + endif + return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri } + endif +endfunction + +function! s:install(force, names) + call s:update_impl(0, a:force, a:names) +endfunction + +function! s:update(force, names) + call s:update_impl(1, a:force, a:names) +endfunction + +function! plug#helptags() + if !exists('g:plugs') + return s:err('plug#begin was not called') + endif + for spec in values(g:plugs) + let docd = join([s:rtp(spec), 'doc'], '/') + if isdirectory(docd) + silent! execute 'helptags' s:esc(docd) + endif + endfor + return 1 +endfunction + +function! s:syntax() + syntax clear + syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber + syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX + syn match plugNumber /[0-9]\+[0-9.]*/ contained + syn match plugBracket /[[\]]/ contained + syn match plugX /x/ contained + syn match plugDash /^-/ + syn match plugPlus /^+/ + syn match plugStar /^*/ + syn match plugMessage /\(^- \)\@<=.*/ + syn match plugName /\(^- \)\@<=[^ ]*:/ + syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/ + syn match plugTag /(tag: [^)]\+)/ + syn match plugInstall /\(^+ \)\@<=[^:]*/ + syn match plugUpdate /\(^* \)\@<=[^:]*/ + syn match plugCommit /^ \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag + syn match plugEdge /^ \X\+$/ + syn match plugEdge /^ \X*/ contained nextgroup=plugSha + syn match plugSha /[0-9a-f]\{7,9}/ contained + syn match plugRelDate /([^)]*)$/ contained + syn match plugNotLoaded /(not loaded)$/ + syn match plugError /^x.*/ + syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/ + syn match plugH2 /^.*:\n-\+$/ + syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean + hi def link plug1 Title + hi def link plug2 Repeat + hi def link plugH2 Type + hi def link plugX Exception + hi def link plugBracket Structure + hi def link plugNumber Number + + hi def link plugDash Special + hi def link plugPlus Constant + hi def link plugStar Boolean + + hi def link plugMessage Function + hi def link plugName Label + hi def link plugInstall Function + hi def link plugUpdate Type + + hi def link plugError Error + hi def link plugDeleted Ignore + hi def link plugRelDate Comment + hi def link plugEdge PreProc + hi def link plugSha Identifier + hi def link plugTag Constant + + hi def link plugNotLoaded Comment +endfunction + +function! s:lpad(str, len) + return a:str . repeat(' ', a:len - len(a:str)) +endfunction + +function! s:lines(msg) + return split(a:msg, "[\r\n]") +endfunction + +function! s:lastline(msg) + return get(s:lines(a:msg), -1, '') +endfunction + +function! s:new_window() + execute get(g:, 'plug_window', 'vertical topleft new') +endfunction + +function! s:plug_window_exists() + let buflist = tabpagebuflist(s:plug_tab) + return !empty(buflist) && index(buflist, s:plug_buf) >= 0 +endfunction + +function! s:switch_in() + if !s:plug_window_exists() + return 0 + endif + + if winbufnr(0) != s:plug_buf + let s:pos = [tabpagenr(), winnr(), winsaveview()] + execute 'normal!' s:plug_tab.'gt' + let winnr = bufwinnr(s:plug_buf) + execute winnr.'wincmd w' + call add(s:pos, winsaveview()) + else + let s:pos = [winsaveview()] + endif + + setlocal modifiable + return 1 +endfunction + +function! s:switch_out(...) + call winrestview(s:pos[-1]) + setlocal nomodifiable + if a:0 > 0 + execute a:1 + endif + + if len(s:pos) > 1 + execute 'normal!' s:pos[0].'gt' + execute s:pos[1] 'wincmd w' + call winrestview(s:pos[2]) + endif +endfunction + +function! s:finish_bindings() + nnoremap R :call retry() + nnoremap D :PlugDiff + nnoremap S :PlugStatus + nnoremap U :call status_update() + xnoremap U :call status_update() + nnoremap ]] :silent! call section('') + nnoremap [[ :silent! call section('b') +endfunction + +function! s:prepare(...) + if empty(getcwd()) + throw 'Invalid current working directory. Cannot proceed.' + endif + + for evar in ['$GIT_DIR', '$GIT_WORK_TREE'] + if exists(evar) + throw evar.' detected. Cannot proceed.' + endif + endfor + + call s:job_abort() + if s:switch_in() + if b:plug_preview == 1 + pc + endif + enew + else + call s:new_window() + endif + + nnoremap q :if b:plug_preview==1pcendifbd + if a:0 == 0 + call s:finish_bindings() + endif + let b:plug_preview = -1 + let s:plug_tab = tabpagenr() + let s:plug_buf = winbufnr(0) + call s:assign_name() + + for k in ['', 'L', 'o', 'X', 'd', 'dd'] + execute 'silent! unmap ' k + endfor + setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell + setf vim-plug + if exists('g:syntax_on') + call s:syntax() + endif +endfunction + +function! s:assign_name() + " Assign buffer name + let prefix = '[Plugins]' + let name = prefix + let idx = 2 + while bufexists(name) + let name = printf('%s (%s)', prefix, idx) + let idx = idx + 1 + endwhile + silent! execute 'f' fnameescape(name) +endfunction + +function! s:chsh(swap) + let prev = [&shell, &shellcmdflag, &shellredir] + if s:is_win + set shell=cmd.exe shellcmdflag=/c shellredir=>%s\ 2>&1 + elseif a:swap + set shell=sh shellredir=>%s\ 2>&1 + endif + return prev +endfunction + +function! s:bang(cmd, ...) + try + let [sh, shellcmdflag, shrd] = s:chsh(a:0) + " FIXME: Escaping is incomplete. We could use shellescape with eval, + " but it won't work on Windows. + let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd + if s:is_win + let batchfile = tempname().'.bat' + call writefile(['@echo off', cmd], batchfile) + let cmd = batchfile + endif + let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%') + execute "normal! :execute g:_plug_bang\\" + finally + unlet g:_plug_bang + let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] + if s:is_win + call delete(batchfile) + endif + endtry + return v:shell_error ? 'Exit status: ' . v:shell_error : '' +endfunction + +function! s:regress_bar() + let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '') + call s:progress_bar(2, bar, len(bar)) +endfunction + +function! s:is_updated(dir) + return !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"', a:dir)) +endfunction + +function! s:do(pull, force, todo) + for [name, spec] in items(a:todo) + if !isdirectory(spec.dir) + continue + endif + let installed = has_key(s:update.new, name) + let updated = installed ? 0 : + \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir)) + if a:force || installed || updated + execute 'cd' s:esc(spec.dir) + call append(3, '- Post-update hook for '. name .' ... ') + let error = '' + let type = type(spec.do) + if type == s:TYPE.string + if spec.do[0] == ':' + if !get(s:loaded, name, 0) + let s:loaded[name] = 1 + call s:reorg_rtp() + endif + call s:load_plugin(spec) + try + execute spec.do[1:] + catch + let error = v:exception + endtry + if !s:plug_window_exists() + cd - + throw 'Warning: vim-plug was terminated by the post-update hook of '.name + endif + else + let error = s:bang(spec.do) + endif + elseif type == s:TYPE.funcref + try + let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged') + call spec.do({ 'name': name, 'status': status, 'force': a:force }) + catch + let error = v:exception + endtry + else + let error = 'Invalid hook type' + endif + call s:switch_in() + call setline(4, empty(error) ? (getline(4) . 'OK') + \ : ('x' . getline(4)[1:] . error)) + if !empty(error) + call add(s:update.errors, name) + call s:regress_bar() + endif + cd - + endif + endfor +endfunction + +function! s:hash_match(a, b) + return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0 +endfunction + +function! s:checkout(spec) + let sha = a:spec.commit + let output = s:system('git rev-parse HEAD', a:spec.dir) + if !v:shell_error && !s:hash_match(sha, s:lines(output)[0]) + let output = s:system( + \ 'git fetch --depth 999999 && git checkout '.s:esc(sha).' --', a:spec.dir) + endif + return output +endfunction + +function! s:finish(pull) + let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen')) + if new_frozen + let s = new_frozen > 1 ? 's' : '' + call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s)) + endif + call append(3, '- Finishing ... ') | 4 + redraw + call plug#helptags() + call plug#end() + call setline(4, getline(4) . 'Done!') + redraw + let msgs = [] + if !empty(s:update.errors) + call add(msgs, "Press 'R' to retry.") + endif + if a:pull && len(s:update.new) < len(filter(getline(5, '$'), + \ "v:val =~ '^- ' && stridx(v:val, 'Already up-to-date') < 0")) + call add(msgs, "Press 'D' to see the updated changes.") + endif + echo join(msgs, ' ') + call s:finish_bindings() +endfunction + +function! s:retry() + if empty(s:update.errors) + return + endif + echo + call s:update_impl(s:update.pull, s:update.force, + \ extend(copy(s:update.errors), [s:update.threads])) +endfunction + +function! s:is_managed(name) + return has_key(g:plugs[a:name], 'uri') +endfunction + +function! s:names(...) + return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)')) +endfunction + +function! s:check_ruby() + silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'") + if !exists('g:plug_ruby') + redraw! + return s:warn('echom', 'Warning: Ruby interface is broken') + endif + let ruby_version = split(g:plug_ruby, '\.') + unlet g:plug_ruby + return s:version_requirement(ruby_version, [1, 8, 7]) +endfunction + +function! s:update_impl(pull, force, args) abort + let sync = index(a:args, '--sync') >= 0 || has('vim_starting') + let args = filter(copy(a:args), 'v:val != "--sync"') + let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ? + \ remove(args, -1) : get(g:, 'plug_threads', 16) + + let managed = filter(copy(g:plugs), 's:is_managed(v:key)') + let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') : + \ filter(managed, 'index(args, v:key) >= 0') + + if empty(todo) + return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install')) + endif + + if !s:is_win && s:git_version_requirement(2, 3) + let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : '' + let $GIT_TERMINAL_PROMPT = 0 + for plug in values(todo) + let plug.uri = substitute(plug.uri, + \ '^https://git::@github\.com', 'https://github.com', '') + endfor + endif + + if !isdirectory(g:plug_home) + try + call mkdir(g:plug_home, 'p') + catch + return s:err(printf('Invalid plug directory: %s. '. + \ 'Try to call plug#begin with a valid directory', g:plug_home)) + endtry + endif + + if has('nvim') && !exists('*jobwait') && threads > 1 + call s:warn('echom', '[vim-plug] Update Neovim for parallel installer') + endif + + let use_job = s:nvim || s:vim8 + let python = (has('python') || has('python3')) && !use_job + let ruby = has('ruby') && !use_job && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && threads > 1 && s:check_ruby() + + let s:update = { + \ 'start': reltime(), + \ 'all': todo, + \ 'todo': copy(todo), + \ 'errors': [], + \ 'pull': a:pull, + \ 'force': a:force, + \ 'new': {}, + \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1, + \ 'bar': '', + \ 'fin': 0 + \ } + + call s:prepare(1) + call append(0, ['', '']) + normal! 2G + silent! redraw + + let s:clone_opt = get(g:, 'plug_shallow', 1) ? + \ '--depth 1' . (s:git_version_requirement(1, 7, 10) ? ' --no-single-branch' : '') : '' + + if has('win32unix') + let s:clone_opt .= ' -c core.eol=lf -c core.autocrlf=input' + endif + + " Python version requirement (>= 2.7) + if python && !has('python3') && !ruby && !use_job && s:update.threads > 1 + redir => pyv + silent python import platform; print platform.python_version() + redir END + let python = s:version_requirement( + \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6]) + endif + + if (python || ruby) && s:update.threads > 1 + try + let imd = &imd + if s:mac_gui + set noimd + endif + if ruby + call s:update_ruby() + else + call s:update_python() + endif + catch + let lines = getline(4, '$') + let printed = {} + silent! 4,$d _ + for line in lines + let name = s:extract_name(line, '.', '') + if empty(name) || !has_key(printed, name) + call append('$', line) + if !empty(name) + let printed[name] = 1 + if line[0] == 'x' && index(s:update.errors, name) < 0 + call add(s:update.errors, name) + end + endif + endif + endfor + finally + let &imd = imd + call s:update_finish() + endtry + else + call s:update_vim() + while use_job && sync + sleep 100m + if s:update.fin + break + endif + endwhile + endif +endfunction + +function! s:log4(name, msg) + call setline(4, printf('- %s (%s)', a:msg, a:name)) + redraw +endfunction + +function! s:update_finish() + if exists('s:git_terminal_prompt') + let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt + endif + if s:switch_in() + call append(3, '- Updating ...') | 4 + for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))')) + let [pos, _] = s:logpos(name) + if !pos + continue + endif + if has_key(spec, 'commit') + call s:log4(name, 'Checking out '.spec.commit) + let out = s:checkout(spec) + elseif has_key(spec, 'tag') + let tag = spec.tag + if tag =~ '\*' + let tags = s:lines(s:system('git tag --list '.s:shellesc(tag).' --sort -version:refname 2>&1', spec.dir)) + if !v:shell_error && !empty(tags) + let tag = tags[0] + call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag)) + call append(3, '') + endif + endif + call s:log4(name, 'Checking out '.tag) + let out = s:system('git checkout -q '.s:esc(tag).' -- 2>&1', spec.dir) + else + let branch = s:esc(get(spec, 'branch', 'master')) + call s:log4(name, 'Merging origin/'.branch) + let out = s:system('git checkout -q '.branch.' -- 2>&1' + \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only origin/'.branch.' 2>&1')), spec.dir) + endif + if !v:shell_error && filereadable(spec.dir.'/.gitmodules') && + \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir)) + call s:log4(name, 'Updating submodules. This may take a while.') + let out .= s:bang('git submodule update --init --recursive 2>&1', spec.dir) + endif + let msg = s:format_message(v:shell_error ? 'x': '-', name, out) + if v:shell_error + call add(s:update.errors, name) + call s:regress_bar() + silent execute pos 'd _' + call append(4, msg) | 4 + elseif !empty(out) + call setline(pos, msg[0]) + endif + redraw + endfor + silent 4 d _ + try + call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")')) + catch + call s:warn('echom', v:exception) + call s:warn('echo', '') + return + endtry + call s:finish(s:update.pull) + call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.') + call s:switch_out('normal! gg') + endif +endfunction + +function! s:job_abort() + if (!s:nvim && !s:vim8) || !exists('s:jobs') + return + endif + + for [name, j] in items(s:jobs) + if s:nvim + silent! call jobstop(j.jobid) + elseif s:vim8 + silent! call job_stop(j.jobid) + endif + if j.new + call s:system('rm -rf ' . s:shellesc(g:plugs[name].dir)) + endif + endfor + let s:jobs = {} +endfunction + +function! s:last_non_empty_line(lines) + let len = len(a:lines) + for idx in range(len) + let line = a:lines[len-idx-1] + if !empty(line) + return line + endif + endfor + return '' +endfunction + +function! s:job_out_cb(self, data) abort + let self = a:self + let data = remove(self.lines, -1) . a:data + let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]') + call extend(self.lines, lines) + " To reduce the number of buffer updates + let self.tick = get(self, 'tick', -1) + 1 + if !self.running || self.tick % len(s:jobs) == 0 + let bullet = self.running ? (self.new ? '+' : '*') : (self.error ? 'x' : '-') + let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines) + call s:log(bullet, self.name, result) + endif +endfunction + +function! s:job_exit_cb(self, data) abort + let a:self.running = 0 + let a:self.error = a:data != 0 + call s:reap(a:self.name) + call s:tick() +endfunction + +function! s:job_cb(fn, job, ch, data) + if !s:plug_window_exists() " plug window closed + return s:job_abort() + endif + call call(a:fn, [a:job, a:data]) +endfunction + +function! s:nvim_cb(job_id, data, event) dict abort + return a:event == 'stdout' ? + \ s:job_cb('s:job_out_cb', self, 0, join(a:data, "\n")) : + \ s:job_cb('s:job_exit_cb', self, 0, a:data) +endfunction + +function! s:spawn(name, cmd, opts) + let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''], + \ 'batchfile': (s:is_win && (s:nvim || s:vim8)) ? tempname().'.bat' : '', + \ 'new': get(a:opts, 'new', 0) } + let s:jobs[a:name] = job + let cmd = has_key(a:opts, 'dir') ? s:with_cd(a:cmd, a:opts.dir) : a:cmd + if !empty(job.batchfile) + call writefile(['@echo off', cmd], job.batchfile) + let cmd = job.batchfile + endif + let argv = add(s:is_win ? ['cmd', '/c'] : ['sh', '-c'], cmd) + + if s:nvim + call extend(job, { + \ 'on_stdout': function('s:nvim_cb'), + \ 'on_exit': function('s:nvim_cb'), + \ }) + let jid = jobstart(argv, job) + if jid > 0 + let job.jobid = jid + else + let job.running = 0 + let job.error = 1 + let job.lines = [jid < 0 ? argv[0].' is not executable' : + \ 'Invalid arguments (or job table is full)'] + endif + elseif s:vim8 + let jid = job_start(s:is_win ? join(argv, ' ') : argv, { + \ 'out_cb': function('s:job_cb', ['s:job_out_cb', job]), + \ 'exit_cb': function('s:job_cb', ['s:job_exit_cb', job]), + \ 'out_mode': 'raw' + \}) + if job_status(jid) == 'run' + let job.jobid = jid + else + let job.running = 0 + let job.error = 1 + let job.lines = ['Failed to start job'] + endif + else + let job.lines = s:lines(call('s:system', [cmd])) + let job.error = v:shell_error != 0 + let job.running = 0 + endif +endfunction + +function! s:reap(name) + let job = s:jobs[a:name] + if job.error + call add(s:update.errors, a:name) + elseif get(job, 'new', 0) + let s:update.new[a:name] = 1 + endif + let s:update.bar .= job.error ? 'x' : '=' + + let bullet = job.error ? 'x' : '-' + let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines) + call s:log(bullet, a:name, empty(result) ? 'OK' : result) + call s:bar() + + if has_key(job, 'batchfile') && !empty(job.batchfile) + call delete(job.batchfile) + endif + call remove(s:jobs, a:name) +endfunction + +function! s:bar() + if s:switch_in() + let total = len(s:update.all) + call setline(1, (s:update.pull ? 'Updating' : 'Installing'). + \ ' plugins ('.len(s:update.bar).'/'.total.')') + call s:progress_bar(2, s:update.bar, total) + call s:switch_out() + endif +endfunction + +function! s:logpos(name) + for i in range(4, line('$')) + if getline(i) =~# '^[-+x*] '.a:name.':' + for j in range(i + 1, line('$')) + if getline(j) !~ '^ ' + return [i, j - 1] + endif + endfor + return [i, i] + endif + endfor + return [0, 0] +endfunction + +function! s:log(bullet, name, lines) + if s:switch_in() + let [b, e] = s:logpos(a:name) + if b > 0 + silent execute printf('%d,%d d _', b, e) + if b > winheight('.') + let b = 4 + endif + else + let b = 4 + endif + " FIXME For some reason, nomodifiable is set after :d in vim8 + setlocal modifiable + call append(b - 1, s:format_message(a:bullet, a:name, a:lines)) + call s:switch_out() + endif +endfunction + +function! s:update_vim() + let s:jobs = {} + + call s:bar() + call s:tick() +endfunction + +function! s:tick() + let pull = s:update.pull + let prog = s:progress_opt(s:nvim || s:vim8) +while 1 " Without TCO, Vim stack is bound to explode + if empty(s:update.todo) + if empty(s:jobs) && !s:update.fin + call s:update_finish() + let s:update.fin = 1 + endif + return + endif + + let name = keys(s:update.todo)[0] + let spec = remove(s:update.todo, name) + let new = !isdirectory(spec.dir) + + call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...') + redraw + + let has_tag = has_key(spec, 'tag') + if !new + let [error, _] = s:git_validate(spec, 0) + if empty(error) + if pull + let fetch_opt = (has_tag && !empty(globpath(spec.dir, '.git/shallow'))) ? '--depth 99999999' : '' + call s:spawn(name, printf('git fetch %s %s 2>&1', fetch_opt, prog), { 'dir': spec.dir }) + else + let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 } + endif + else + let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 } + endif + else + call s:spawn(name, + \ printf('git clone %s %s %s %s 2>&1', + \ has_tag ? '' : s:clone_opt, + \ prog, + \ s:shellesc(spec.uri), + \ s:shellesc(s:trim(spec.dir))), { 'new': 1 }) + endif + + if !s:jobs[name].running + call s:reap(name) + endif + if len(s:jobs) >= s:update.threads + break + endif +endwhile +endfunction + +function! s:update_python() +let py_exe = has('python') ? 'python' : 'python3' +execute py_exe "<< EOF" +import datetime +import functools +import os +try: + import queue +except ImportError: + import Queue as queue +import random +import re +import shutil +import signal +import subprocess +import tempfile +import threading as thr +import time +import traceback +import vim + +G_NVIM = vim.eval("has('nvim')") == '1' +G_PULL = vim.eval('s:update.pull') == '1' +G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1 +G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)')) +G_CLONE_OPT = vim.eval('s:clone_opt') +G_PROGRESS = vim.eval('s:progress_opt(1)') +G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads')) +G_STOP = thr.Event() +G_IS_WIN = vim.eval('s:is_win') == '1' + +class PlugError(Exception): + def __init__(self, msg): + self.msg = msg +class CmdTimedOut(PlugError): + pass +class CmdFailed(PlugError): + pass +class InvalidURI(PlugError): + pass +class Action(object): + INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-'] + +class Buffer(object): + def __init__(self, lock, num_plugs, is_pull): + self.bar = '' + self.event = 'Updating' if is_pull else 'Installing' + self.lock = lock + self.maxy = int(vim.eval('winheight(".")')) + self.num_plugs = num_plugs + + def __where(self, name): + """ Find first line with name in current buffer. Return line num. """ + found, lnum = False, 0 + matcher = re.compile('^[-+x*] {0}:'.format(name)) + for line in vim.current.buffer: + if matcher.search(line) is not None: + found = True + break + lnum += 1 + + if not found: + lnum = -1 + return lnum + + def header(self): + curbuf = vim.current.buffer + curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs) + + num_spaces = self.num_plugs - len(self.bar) + curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ') + + with self.lock: + vim.command('normal! 2G') + vim.command('redraw') + + def write(self, action, name, lines): + first, rest = lines[0], lines[1:] + msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)] + msg.extend([' ' + line for line in rest]) + + try: + if action == Action.ERROR: + self.bar += 'x' + vim.command("call add(s:update.errors, '{0}')".format(name)) + elif action == Action.DONE: + self.bar += '=' + + curbuf = vim.current.buffer + lnum = self.__where(name) + if lnum != -1: # Found matching line num + del curbuf[lnum] + if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]): + lnum = 3 + else: + lnum = 3 + curbuf.append(msg, lnum) + + self.header() + except vim.error: + pass + +class Command(object): + CD = 'cd /d' if G_IS_WIN else 'cd' + + def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None): + self.cmd = cmd + if cmd_dir: + self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd) + self.timeout = timeout + self.callback = cb if cb else (lambda msg: None) + self.clean = clean if clean else (lambda: None) + self.proc = None + + @property + def alive(self): + """ Returns true only if command still running. """ + return self.proc and self.proc.poll() is None + + def execute(self, ntries=3): + """ Execute the command with ntries if CmdTimedOut. + Returns the output of the command if no Exception. + """ + attempt, finished, limit = 0, False, self.timeout + + while not finished: + try: + attempt += 1 + result = self.try_command() + finished = True + return result + except CmdTimedOut: + if attempt != ntries: + self.notify_retry() + self.timeout += limit + else: + raise + + def notify_retry(self): + """ Retry required for command, notify user. """ + for count in range(3, 0, -1): + if G_STOP.is_set(): + raise KeyboardInterrupt + msg = 'Timeout. Will retry in {0} second{1} ...'.format( + count, 's' if count != 1 else '') + self.callback([msg]) + time.sleep(1) + self.callback(['Retrying ...']) + + def try_command(self): + """ Execute a cmd & poll for callback. Returns list of output. + Raises CmdFailed -> return code for Popen isn't 0 + Raises CmdTimedOut -> command exceeded timeout without new output + """ + first_line = True + + try: + tfile = tempfile.NamedTemporaryFile(mode='w+b') + preexec_fn = not G_IS_WIN and os.setsid or None + self.proc = subprocess.Popen(self.cmd, stdout=tfile, + stderr=subprocess.STDOUT, + stdin=subprocess.PIPE, shell=True, + preexec_fn=preexec_fn) + thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,)) + thrd.start() + + thread_not_started = True + while thread_not_started: + try: + thrd.join(0.1) + thread_not_started = False + except RuntimeError: + pass + + while self.alive: + if G_STOP.is_set(): + raise KeyboardInterrupt + + if first_line or random.random() < G_LOG_PROB: + first_line = False + line = '' if G_IS_WIN else nonblock_read(tfile.name) + if line: + self.callback([line]) + + time_diff = time.time() - os.path.getmtime(tfile.name) + if time_diff > self.timeout: + raise CmdTimedOut(['Timeout!']) + + thrd.join(0.5) + + tfile.seek(0) + result = [line.decode('utf-8', 'replace').rstrip() for line in tfile] + + if self.proc.returncode != 0: + raise CmdFailed([''] + result) + + return result + except: + self.terminate() + raise + + def terminate(self): + """ Terminate process and cleanup. """ + if self.alive: + if G_IS_WIN: + os.kill(self.proc.pid, signal.SIGINT) + else: + os.killpg(self.proc.pid, signal.SIGTERM) + self.clean() + +class Plugin(object): + def __init__(self, name, args, buf_q, lock): + self.name = name + self.args = args + self.buf_q = buf_q + self.lock = lock + self.tag = args.get('tag', 0) + + def manage(self): + try: + if os.path.exists(self.args['dir']): + self.update() + else: + self.install() + with self.lock: + thread_vim_command("let s:update.new['{0}'] = 1".format(self.name)) + except PlugError as exc: + self.write(Action.ERROR, self.name, exc.msg) + except KeyboardInterrupt: + G_STOP.set() + self.write(Action.ERROR, self.name, ['Interrupted!']) + except: + # Any exception except those above print stack trace + msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip()) + self.write(Action.ERROR, self.name, msg.split('\n')) + raise + + def install(self): + target = self.args['dir'] + if target[-1] == '\\': + target = target[0:-1] + + def clean(target): + def _clean(): + try: + shutil.rmtree(target) + except OSError: + pass + return _clean + + self.write(Action.INSTALL, self.name, ['Installing ...']) + callback = functools.partial(self.write, Action.INSTALL, self.name) + cmd = 'git clone {0} {1} {2} {3} 2>&1'.format( + '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'], + esc(target)) + com = Command(cmd, None, G_TIMEOUT, callback, clean(target)) + result = com.execute(G_RETRIES) + self.write(Action.DONE, self.name, result[-1:]) + + def repo_uri(self): + cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url' + command = Command(cmd, self.args['dir'], G_TIMEOUT,) + result = command.execute(G_RETRIES) + return result[-1] + + def update(self): + actual_uri = self.repo_uri() + expect_uri = self.args['uri'] + regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$') + ma = regex.match(actual_uri) + mb = regex.match(expect_uri) + if ma is None or mb is None or ma.groups() != mb.groups(): + msg = ['', + 'Invalid URI: {0}'.format(actual_uri), + 'Expected {0}'.format(expect_uri), + 'PlugClean required.'] + raise InvalidURI(msg) + + if G_PULL: + self.write(Action.UPDATE, self.name, ['Updating ...']) + callback = functools.partial(self.write, Action.UPDATE, self.name) + fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else '' + cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS) + com = Command(cmd, self.args['dir'], G_TIMEOUT, callback) + result = com.execute(G_RETRIES) + self.write(Action.DONE, self.name, result[-1:]) + else: + self.write(Action.DONE, self.name, ['Already installed']) + + def write(self, action, name, msg): + self.buf_q.put((action, name, msg)) + +class PlugThread(thr.Thread): + def __init__(self, tname, args): + super(PlugThread, self).__init__() + self.tname = tname + self.args = args + + def run(self): + thr.current_thread().name = self.tname + buf_q, work_q, lock = self.args + + try: + while not G_STOP.is_set(): + name, args = work_q.get_nowait() + plug = Plugin(name, args, buf_q, lock) + plug.manage() + work_q.task_done() + except queue.Empty: + pass + +class RefreshThread(thr.Thread): + def __init__(self, lock): + super(RefreshThread, self).__init__() + self.lock = lock + self.running = True + + def run(self): + while self.running: + with self.lock: + thread_vim_command('noautocmd normal! a') + time.sleep(0.33) + + def stop(self): + self.running = False + +if G_NVIM: + def thread_vim_command(cmd): + vim.session.threadsafe_call(lambda: vim.command(cmd)) +else: + def thread_vim_command(cmd): + vim.command(cmd) + +def esc(name): + return '"' + name.replace('"', '\"') + '"' + +def nonblock_read(fname): + """ Read a file with nonblock flag. Return the last line. """ + fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK) + buf = os.read(fread, 100000).decode('utf-8', 'replace') + os.close(fread) + + line = buf.rstrip('\r\n') + left = max(line.rfind('\r'), line.rfind('\n')) + if left != -1: + left += 1 + line = line[left:] + + return line + +def main(): + thr.current_thread().name = 'main' + nthreads = int(vim.eval('s:update.threads')) + plugs = vim.eval('s:update.todo') + mac_gui = vim.eval('s:mac_gui') == '1' + + lock = thr.Lock() + buf = Buffer(lock, len(plugs), G_PULL) + buf_q, work_q = queue.Queue(), queue.Queue() + for work in plugs.items(): + work_q.put(work) + + start_cnt = thr.active_count() + for num in range(nthreads): + tname = 'PlugT-{0:02}'.format(num) + thread = PlugThread(tname, (buf_q, work_q, lock)) + thread.start() + if mac_gui: + rthread = RefreshThread(lock) + rthread.start() + + while not buf_q.empty() or thr.active_count() != start_cnt: + try: + action, name, msg = buf_q.get(True, 0.25) + buf.write(action, name, ['OK'] if not msg else msg) + buf_q.task_done() + except queue.Empty: + pass + except KeyboardInterrupt: + G_STOP.set() + + if mac_gui: + rthread.stop() + rthread.join() + +main() +EOF +endfunction + +function! s:update_ruby() + ruby << EOF + module PlugStream + SEP = ["\r", "\n", nil] + def get_line + buffer = '' + loop do + char = readchar rescue return + if SEP.include? char.chr + buffer << $/ + break + else + buffer << char + end + end + buffer + end + end unless defined?(PlugStream) + + def esc arg + %["#{arg.gsub('"', '\"')}"] + end + + def killall pid + pids = [pid] + if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM + pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil } + else + unless `which pgrep 2> /dev/null`.empty? + children = pids + until children.empty? + children = children.map { |pid| + `pgrep -P #{pid}`.lines.map { |l| l.chomp } + }.flatten + pids += children + end + end + pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil } + end + end + + def compare_git_uri a, b + regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$} + regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1) + end + + require 'thread' + require 'fileutils' + require 'timeout' + running = true + iswin = VIM::evaluate('s:is_win').to_i == 1 + pull = VIM::evaluate('s:update.pull').to_i == 1 + base = VIM::evaluate('g:plug_home') + all = VIM::evaluate('s:update.todo') + limit = VIM::evaluate('get(g:, "plug_timeout", 60)') + tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1 + nthr = VIM::evaluate('s:update.threads').to_i + maxy = VIM::evaluate('winheight(".")').to_i + vim7 = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/ + cd = iswin ? 'cd /d' : 'cd' + tot = VIM::evaluate('len(s:update.todo)') || 0 + bar = '' + skip = 'Already installed' + mtx = Mutex.new + take1 = proc { mtx.synchronize { running && all.shift } } + logh = proc { + cnt = bar.length + $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})" + $curbuf[2] = '[' + bar.ljust(tot) + ']' + VIM::command('normal! 2G') + VIM::command('redraw') + } + where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } } + log = proc { |name, result, type| + mtx.synchronize do + ing = ![true, false].include?(type) + bar += type ? '=' : 'x' unless ing + b = case type + when :install then '+' when :update then '*' + when true, nil then '-' else + VIM::command("call add(s:update.errors, '#{name}')") + 'x' + end + result = + if type || type.nil? + ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"] + elsif result =~ /^Interrupted|^Timeout/ + ["#{b} #{name}: #{result}"] + else + ["#{b} #{name}"] + result.lines.map { |l| " " << l } + end + if lnum = where.call(name) + $curbuf.delete lnum + lnum = 4 if ing && lnum > maxy + end + result.each_with_index do |line, offset| + $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp) + end + logh.call + end + } + bt = proc { |cmd, name, type, cleanup| + tried = timeout = 0 + begin + tried += 1 + timeout += limit + fd = nil + data = '' + if iswin + Timeout::timeout(timeout) do + tmp = VIM::evaluate('tempname()') + system("(#{cmd}) > #{tmp}") + data = File.read(tmp).chomp + File.unlink tmp rescue nil + end + else + fd = IO.popen(cmd).extend(PlugStream) + first_line = true + log_prob = 1.0 / nthr + while line = Timeout::timeout(timeout) { fd.get_line } + data << line + log.call name, line.chomp, type if name && (first_line || rand < log_prob) + first_line = false + end + fd.close + end + [$? == 0, data.chomp] + rescue Timeout::Error, Interrupt => e + if fd && !fd.closed? + killall fd.pid + fd.close + end + cleanup.call if cleanup + if e.is_a?(Timeout::Error) && tried < tries + 3.downto(1) do |countdown| + s = countdown > 1 ? 's' : '' + log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type + sleep 1 + end + log.call name, 'Retrying ...', type + retry + end + [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"] + end + } + main = Thread.current + threads = [] + watcher = Thread.new { + if vim7 + while VIM::evaluate('getchar(1)') + sleep 0.1 + end + else + require 'io/console' # >= Ruby 1.9 + nil until IO.console.getch == 3.chr + end + mtx.synchronize do + running = false + threads.each { |t| t.raise Interrupt } unless vim7 + end + threads.each { |t| t.join rescue nil } + main.kill + } + refresh = Thread.new { + while true + mtx.synchronize do + break unless running + VIM::command('noautocmd normal! a') + end + sleep 0.2 + end + } if VIM::evaluate('s:mac_gui') == 1 + + clone_opt = VIM::evaluate('s:clone_opt') + progress = VIM::evaluate('s:progress_opt(1)') + nthr.times do + mtx.synchronize do + threads << Thread.new { + while pair = take1.call + name = pair.first + dir, uri, tag = pair.last.values_at *%w[dir uri tag] + exists = File.directory? dir + ok, result = + if exists + chdir = "#{cd} #{iswin ? dir : esc(dir)}" + ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil + current_uri = data.lines.to_a.last + if !ret + if data =~ /^Interrupted|^Timeout/ + [false, data] + else + [false, [data.chomp, "PlugClean required."].join($/)] + end + elsif !compare_git_uri(current_uri, uri) + [false, ["Invalid URI: #{current_uri}", + "Expected: #{uri}", + "PlugClean required."].join($/)] + else + if pull + log.call name, 'Updating ...', :update + fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : '' + bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil + else + [true, skip] + end + end + else + d = esc dir.sub(%r{[\\/]+$}, '') + log.call name, 'Installing ...', :install + bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc { + FileUtils.rm_rf dir + } + end + mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok + log.call name, result, ok + end + } if running + end + end + threads.each { |t| t.join rescue nil } + logh.call + refresh.kill if refresh + watcher.kill +EOF +endfunction + +function! s:shellesc_cmd(arg) + let escaped = substitute(a:arg, '[&|<>()@^]', '^&', 'g') + let escaped = substitute(escaped, '%', '%%', 'g') + let escaped = substitute(escaped, '"', '\\^&', 'g') + let escaped = substitute(escaped, '\(\\\+\)\(\\^\)', '\1\1\2', 'g') + return '^"'.substitute(escaped, '\(\\\+\)$', '\1\1', '').'^"' +endfunction + +function! s:shellesc(arg) + if &shell =~# 'cmd.exe$' + return s:shellesc_cmd(a:arg) + endif + return shellescape(a:arg) +endfunction + +function! s:glob_dir(path) + return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)') +endfunction + +function! s:progress_bar(line, bar, total) + call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']') +endfunction + +function! s:compare_git_uri(a, b) + " See `git help clone' + " https:// [user@] github.com[:port] / junegunn/vim-plug [.git] + " [git@] github.com[:port] : junegunn/vim-plug [.git] + " file:// / junegunn/vim-plug [/] + " / junegunn/vim-plug [/] + let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$' + let ma = matchlist(a:a, pat) + let mb = matchlist(a:b, pat) + return ma[1:2] ==# mb[1:2] +endfunction + +function! s:format_message(bullet, name, message) + if a:bullet != 'x' + return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))] + else + let lines = map(s:lines(a:message), '" ".v:val') + return extend([printf('x %s:', a:name)], lines) + endif +endfunction + +function! s:with_cd(cmd, dir) + return printf('cd%s %s && %s', s:is_win ? ' /d' : '', s:shellesc(a:dir), a:cmd) +endfunction + +function! s:system(cmd, ...) + try + let [sh, shellcmdflag, shrd] = s:chsh(1) + let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd + if s:is_win + let batchfile = tempname().'.bat' + call writefile(['@echo off', cmd], batchfile) + let cmd = batchfile + endif + return system(s:is_win ? '('.cmd.')' : cmd) + finally + let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] + if s:is_win + call delete(batchfile) + endif + endtry +endfunction + +function! s:system_chomp(...) + let ret = call('s:system', a:000) + return v:shell_error ? '' : substitute(ret, '\n$', '', '') +endfunction + +function! s:git_validate(spec, check_branch) + let err = '' + if isdirectory(a:spec.dir) + let result = s:lines(s:system('git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url', a:spec.dir)) + let remote = result[-1] + if v:shell_error + let err = join([remote, 'PlugClean required.'], "\n") + elseif !s:compare_git_uri(remote, a:spec.uri) + let err = join(['Invalid URI: '.remote, + \ 'Expected: '.a:spec.uri, + \ 'PlugClean required.'], "\n") + elseif a:check_branch && has_key(a:spec, 'commit') + let result = s:lines(s:system('git rev-parse HEAD 2>&1', a:spec.dir)) + let sha = result[-1] + if v:shell_error + let err = join(add(result, 'PlugClean required.'), "\n") + elseif !s:hash_match(sha, a:spec.commit) + let err = join([printf('Invalid HEAD (expected: %s, actual: %s)', + \ a:spec.commit[:6], sha[:6]), + \ 'PlugUpdate required.'], "\n") + endif + elseif a:check_branch + let branch = result[0] + " Check tag + if has_key(a:spec, 'tag') + let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir) + if a:spec.tag !=# tag && a:spec.tag !~ '\*' + let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.', + \ (empty(tag) ? 'N/A' : tag), a:spec.tag) + endif + " Check branch + elseif a:spec.branch !=# branch + let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.', + \ branch, a:spec.branch) + endif + if empty(err) + let [ahead, behind] = split(s:lastline(s:system(printf( + \ 'git rev-list --count --left-right HEAD...origin/%s', + \ a:spec.branch), a:spec.dir)), '\t') + if !v:shell_error && ahead + if behind + " Only mention PlugClean if diverged, otherwise it's likely to be + " pushable (and probably not that messed up). + let err = printf( + \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n" + \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', a:spec.branch, ahead, behind) + else + let err = printf("Ahead of origin/%s by %d commit(s).\n" + \ .'Cannot update until local changes are pushed.', + \ a:spec.branch, ahead) + endif + endif + endif + endif + else + let err = 'Not found' + endif + return [err, err =~# 'PlugClean'] +endfunction + +function! s:rm_rf(dir) + if isdirectory(a:dir) + call s:system((s:is_win ? 'rmdir /S /Q ' : 'rm -rf ') . s:shellesc(a:dir)) + endif +endfunction + +function! s:clean(force) + call s:prepare() + call append(0, 'Searching for invalid plugins in '.g:plug_home) + call append(1, '') + + " List of valid directories + let dirs = [] + let errs = {} + let [cnt, total] = [0, len(g:plugs)] + for [name, spec] in items(g:plugs) + if !s:is_managed(name) + call add(dirs, spec.dir) + else + let [err, clean] = s:git_validate(spec, 1) + if clean + let errs[spec.dir] = s:lines(err)[0] + else + call add(dirs, spec.dir) + endif + endif + let cnt += 1 + call s:progress_bar(2, repeat('=', cnt), total) + normal! 2G + redraw + endfor + + let allowed = {} + for dir in dirs + let allowed[s:dirpath(fnamemodify(dir, ':h:h'))] = 1 + let allowed[dir] = 1 + for child in s:glob_dir(dir) + let allowed[child] = 1 + endfor + endfor + + let todo = [] + let found = sort(s:glob_dir(g:plug_home)) + while !empty(found) + let f = remove(found, 0) + if !has_key(allowed, f) && isdirectory(f) + call add(todo, f) + call append(line('$'), '- ' . f) + if has_key(errs, f) + call append(line('$'), ' ' . errs[f]) + endif + let found = filter(found, 'stridx(v:val, f) != 0') + end + endwhile + + 4 + redraw + if empty(todo) + call append(line('$'), 'Already clean.') + else + let s:clean_count = 0 + call append(3, ['Directories to delete:', '']) + redraw! + if a:force || s:ask_no_interrupt('Delete all directories?') + call s:delete([6, line('$')], 1) + else + call setline(4, 'Cancelled.') + nnoremap d :set opfunc=delete_opg@ + nmap dd d_ + xnoremap d :call delete_op(visualmode(), 1) + echo 'Delete the lines (d{motion}) to delete the corresponding directories' + endif + endif + 4 + setlocal nomodifiable +endfunction + +function! s:delete_op(type, ...) + call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0) +endfunction + +function! s:delete(range, force) + let [l1, l2] = a:range + let force = a:force + while l1 <= l2 + let line = getline(l1) + if line =~ '^- ' && isdirectory(line[2:]) + execute l1 + redraw! + let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1) + let force = force || answer > 1 + if answer + call s:rm_rf(line[2:]) + setlocal modifiable + call setline(l1, '~'.line[1:]) + let s:clean_count += 1 + call setline(4, printf('Removed %d directories.', s:clean_count)) + setlocal nomodifiable + endif + endif + let l1 += 1 + endwhile +endfunction + +function! s:upgrade() + echo 'Downloading the latest version of vim-plug' + redraw + let tmp = tempname() + let new = tmp . '/plug.vim' + + try + let out = s:system(printf('git clone --depth 1 %s %s', s:plug_src, tmp)) + if v:shell_error + return s:err('Error upgrading vim-plug: '. out) + endif + + if readfile(s:me) ==# readfile(new) + echo 'vim-plug is already up-to-date' + return 0 + else + call rename(s:me, s:me . '.old') + call rename(new, s:me) + unlet g:loaded_plug + echo 'vim-plug has been upgraded' + return 1 + endif + finally + silent! call s:rm_rf(tmp) + endtry +endfunction + +function! s:upgrade_specs() + for spec in values(g:plugs) + let spec.frozen = get(spec, 'frozen', 0) + endfor +endfunction + +function! s:status() + call s:prepare() + call append(0, 'Checking plugins') + call append(1, '') + + let ecnt = 0 + let unloaded = 0 + let [cnt, total] = [0, len(g:plugs)] + for [name, spec] in items(g:plugs) + if has_key(spec, 'uri') + if isdirectory(spec.dir) + let [err, _] = s:git_validate(spec, 1) + let [valid, msg] = [empty(err), empty(err) ? 'OK' : err] + else + let [valid, msg] = [0, 'Not found. Try PlugInstall.'] + endif + else + if isdirectory(spec.dir) + let [valid, msg] = [1, 'OK'] + else + let [valid, msg] = [0, 'Not found.'] + endif + endif + let cnt += 1 + let ecnt += !valid + " `s:loaded` entry can be missing if PlugUpgraded + if valid && get(s:loaded, name, -1) == 0 + let unloaded = 1 + let msg .= ' (not loaded)' + endif + call s:progress_bar(2, repeat('=', cnt), total) + call append(3, s:format_message(valid ? '-' : 'x', name, msg)) + normal! 2G + redraw + endfor + call setline(1, 'Finished. '.ecnt.' error(s).') + normal! gg + setlocal nomodifiable + if unloaded + echo "Press 'L' on each line to load plugin, or 'U' to update" + nnoremap L :call status_load(line('.')) + xnoremap L :call status_load(line('.')) + end +endfunction + +function! s:extract_name(str, prefix, suffix) + return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$') +endfunction + +function! s:status_load(lnum) + let line = getline(a:lnum) + let name = s:extract_name(line, '-', '(not loaded)') + if !empty(name) + call plug#load(name) + setlocal modifiable + call setline(a:lnum, substitute(line, ' (not loaded)$', '', '')) + setlocal nomodifiable + endif +endfunction + +function! s:status_update() range + let lines = getline(a:firstline, a:lastline) + let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)') + if !empty(names) + echo + execute 'PlugUpdate' join(names) + endif +endfunction + +function! s:is_preview_window_open() + silent! wincmd P + if &previewwindow + wincmd p + return 1 + endif +endfunction + +function! s:find_name(lnum) + for lnum in reverse(range(1, a:lnum)) + let line = getline(lnum) + if empty(line) + return '' + endif + let name = s:extract_name(line, '-', '') + if !empty(name) + return name + endif + endfor + return '' +endfunction + +function! s:preview_commit() + if b:plug_preview < 0 + let b:plug_preview = !s:is_preview_window_open() + endif + + let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7,9}') + if empty(sha) + return + endif + + let name = s:find_name(line('.')) + if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir) + return + endif + + if exists('g:plug_pwindow') && !s:is_preview_window_open() + execute g:plug_pwindow + execute 'e' sha + else + execute 'pedit' sha + wincmd P + endif + setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable + try + let [sh, shellcmdflag, shrd] = s:chsh(1) + let cmd = 'cd '.s:shellesc(g:plugs[name].dir).' && git show --no-color --pretty=medium '.sha + if s:is_win + let batchfile = tempname().'.bat' + call writefile(['@echo off', cmd], batchfile) + let cmd = batchfile + endif + execute 'silent %!' cmd + finally + let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] + if s:is_win + call delete(batchfile) + endif + endtry + setlocal nomodifiable + nnoremap q :q + wincmd p +endfunction + +function! s:section(flags) + call search('\(^[x-] \)\@<=[^:]\+:', a:flags) +endfunction + +function! s:format_git_log(line) + let indent = ' ' + let tokens = split(a:line, nr2char(1)) + if len(tokens) != 5 + return indent.substitute(a:line, '\s*$', '', '') + endif + let [graph, sha, refs, subject, date] = tokens + let tag = matchstr(refs, 'tag: [^,)]\+') + let tag = empty(tag) ? ' ' : ' ('.tag.') ' + return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date) +endfunction + +function! s:append_ul(lnum, text) + call append(a:lnum, ['', a:text, repeat('-', len(a:text))]) +endfunction + +function! s:diff() + call s:prepare() + call append(0, ['Collecting changes ...', '']) + let cnts = [0, 0] + let bar = '' + let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)') + call s:progress_bar(2, bar, len(total)) + for origin in [1, 0] + let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))')))) + if empty(plugs) + continue + endif + call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:') + for [k, v] in plugs + let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..' + let diff = s:system_chomp('git log --graph --color=never '.join(map(['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range], 's:shellesc(v:val)')), v.dir) + if !empty(diff) + let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' + call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) + let cnts[origin] += 1 + endif + let bar .= '=' + call s:progress_bar(2, bar, len(total)) + normal! 2G + redraw + endfor + if !cnts[origin] + call append(5, ['', 'N/A']) + endif + endfor + call setline(1, printf('%d plugin(s) updated.', cnts[0]) + \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : '')) + + if cnts[0] || cnts[1] + nnoremap :silent! call preview_commit() + nnoremap o :silent! call preview_commit() + endif + if cnts[0] + nnoremap X :call revert() + echo "Press 'X' on each block to revert the update" + endif + normal! gg + setlocal nomodifiable +endfunction + +function! s:revert() + if search('^Pending updates', 'bnW') + return + endif + + let name = s:find_name(line('.')) + if empty(name) || !has_key(g:plugs, name) || + \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y' + return + endif + + call s:system('git reset --hard HEAD@{1} && git checkout '.s:esc(g:plugs[name].branch).' --', g:plugs[name].dir) + setlocal modifiable + normal! "_dap + setlocal nomodifiable + echo 'Reverted' +endfunction + +function! s:snapshot(force, ...) abort + call s:prepare() + setf vim + call append(0, ['" Generated by vim-plug', + \ '" '.strftime("%c"), + \ '" :source this file in vim to restore the snapshot', + \ '" or execute: vim -S snapshot.vim', + \ '', '', 'PlugUpdate!']) + 1 + let anchor = line('$') - 3 + let names = sort(keys(filter(copy(g:plugs), + \'has_key(v:val, "uri") && !has_key(v:val, "commit") && isdirectory(v:val.dir)'))) + for name in reverse(names) + let sha = s:system_chomp('git rev-parse --short HEAD', g:plugs[name].dir) + if !empty(sha) + call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha)) + redraw + endif + endfor + + if a:0 > 0 + let fn = expand(a:1) + if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?')) + return + endif + call writefile(getline(1, '$'), fn) + echo 'Saved as '.a:1 + silent execute 'e' s:esc(fn) + setf vim + endif +endfunction + +function! s:split_rtp() + return split(&rtp, '\\\@'], ['{', '}'], ['[', ']']] + +let g:LanguageClient_serverCommands = { 'haskell': ['hie-wrapper'] } + +let g:LanguageClient_rootMarkers = ['*.cabal', 'stack.yaml'] + +function! _GitDiffWindowSetup() abort + setlocal buftype=nofile + setlocal bufhidden=hide + setlocal noswapfile + .!git diff -b && git diff --staged -b + setlocal filetype=diff +endfunction + +function! GitDiffWindow() abort + vert new +call\ _GitDiffWindowSetup() + wincmd J + wincmd p + resize 10 +endfunction + +autocmd BufRead */.git/COMMIT_EDITMSG call GitDiffWindow() + +if has('win32') + let g:python3_host_prog = 'C:/Python36/python.exe' + set guifont=Liberation_Mono:h10:cANSI:qDRAFT +endif + +let g:deoplete#enable_at_startup = 1 + +let g:deoplete#omni_patterns = {} +let g:deoplete#omni_patterns.terraform = '[^ *\t"{=$]\w*' + +let g:deoplete#omni#input_patterns.scala='[^. *\t]\.\w*' + + +let g:airline#extensions#tabline#enabled = 1 +let g:airline_theme='simple' + +let g:tern#is_show_argument_hints_enabled = 1 + +" Tabs +set shiftwidth=4 expandtab tabstop=8 softtabstop=4 smartindent + +if has('win32') + set bs=2 +else + set backspace=indent,eol,start +endif + +set showcmd hlsearch + +command W :w suda://% + +set hidden + +if has('win32') + silent exec "!mkdir $HOME/.vimswap" +else + silent exec "!mkdir $HOME/.vimswap 2>/dev/null" +endif + +set directory=$HOME/.vimswap// + +set modeline +set secure +set autoread +set number + +set laststatus=2 + +set encoding=utf8 + +if(!has('win32') || ( has('win32') && has('gui_running') )) + set background=dark + colorscheme palenight + + let g:palenight_terminal_italics=1 +endif + +let mapleader="," + +map dl :call vimspector#Launch() +map dn :call vimspector#StepOver() +map dc :call vimspector#Continue() +map di :call vimspector#StepInto() +map do :call vimspector#StepOut() +map dr :VimspectorReset +map ds :call vimspector#Stop() +map dp :call vimspector#Pause() +map db :call vimspector#ToggleBreakpoint() + +map cz :ColorHighlight +map ev :e $HOME/.vimrc +map rv :source $HOME/.vimrc +map pi :PlugInstall +map pt :set paste! +map ag :Ag +map _ f_x~ + +noremap :GFiles + +imap jj +imap hh + +inoremap pumvisible() ? "\" : "\" +inoremap pumvisible() ? "\" : "\" + +autocmd BufRead * RainbowParentheses + +autocmd BufWritePost *.scala silent :EnTypeCheck +nnoremap t :EnType + +" https://vim.fandom.com/wiki/Different_syntax_highlighting_within_regions_of_a_file + +function! TextEnableCodeSnip(filetype,start,end,textSnipHl) abort + let ft=toupper(a:filetype) + let group='textGroup'.ft + if exists('b:current_syntax') + let s:current_syntax=b:current_syntax + " Remove current syntax definition, as some syntax files (e.g. cpp.vim) + " do nothing if b:current_syntax is defined. + unlet b:current_syntax + endif + execute 'syntax include @'.group.' syntax/'.a:filetype.'.vim' + try + execute 'syntax include @'.group.' after/syntax/'.a:filetype.'.vim' + catch + endtry + if exists('s:current_syntax') + let b:current_syntax=s:current_syntax + else + unlet b:current_syntax + endif + execute 'syntax region textSnip'.ft.' + \ matchgroup='.a:textSnipHl.' + \ keepend + \ start="'.a:start.'" end="'.a:end.'" + \ contains=@'.group +endfunction + +call TextEnableCodeSnip( 'javascript', '# BEGIN JS', '# END JS', 'SpecialComment') diff --git a/.vsvimrc b/.vsvimrc new file mode 100644 index 0000000..05c03e5 --- /dev/null +++ b/.vsvimrc @@ -0,0 +1,3 @@ +inoremap jj +inoremap kk +inoremap hh diff --git a/script/.eslintrc.js b/script/.eslintrc.js new file mode 100644 index 0000000..389419c --- /dev/null +++ b/script/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = + { + "env": { + "node": true, + }, + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module", + }, + "rules": { + "no-undef": "error" + } + }; diff --git a/script/attrnorm b/script/attrnorm new file mode 100755 index 0000000..daacaed --- /dev/null +++ b/script/attrnorm @@ -0,0 +1,42 @@ +#! /bin/bash + +## file: app/appointment-messenger/node_modules/lodash/fp/pullAllBy.js +#USER jessica rw- +#GROUP jessica rw- +#other r-- + +FILE_REGEX="^#[[:space:]]+file:[[:space:]]+(.*)$" +PERMS_REGEX="USER[[:space:]]+([[:alnum:]]+)[[:space:]]+(([r\-])([w\-])([x\-]))([[:space:]]+(([r\-])([w\-])([x\-])))?" +FILE_UNUSED=0 + +getfacl -p -R -t "$1" | while read LINE ; do + if [[ "$LINE" =~ $FILE_REGEX ]] ; then + FILENAME="${BASH_REMATCH[1]}" + + FILE_UNUSED=1 + fi + + if [[ "$LINE" =~ $PERMS_REGEX ]] ; then + PERMS="$LINE" + PERMS_READ="${BASH_REMATCH[3]}" + PERMS_WRITE="${BASH_REMATCH[4]}" + PERMS_EXEC="${BASH_REMATCH[5]}" + + ACTUAL="${BASH_REMATCH[2]}" + DEFAULTS="${BASH_REMATCH[7]}" + + ACTUAL_OTHER="${ACTUAL//[w]/-}" + + if ((FILE_UNUSED)) ; then + setfacl -m "group::$ACTUAL" "$FILENAME" + setfacl -m "other::$ACTUAL_OTHER" "$FILENAME" + + if [[ ! -z "$DEFAULTS" ]] ; then + DEFAULTS_OTHER="${DEFAULTS//[w]/-}" + setfacl -d -m "group::$DEFAULTS" "$FILENAME" + setfacl -d -m "other::$DEFAULTS_OTHER" "$FILENAME" + fi + fi + fi + +done diff --git a/script/attrsec b/script/attrsec new file mode 100755 index 0000000..d47cb9d --- /dev/null +++ b/script/attrsec @@ -0,0 +1,4 @@ +#! /bin/bash +setfacl -R -d -m group::--- "$1" +setfacl -R -d -m other::--- "$1" +chmod -R go-rwx "$1" diff --git a/script/cmus-hook b/script/cmus-hook new file mode 100755 index 0000000..0d46137 --- /dev/null +++ b/script/cmus-hook @@ -0,0 +1,3 @@ +#! /bin/sh + +cmus_notify "$*" & diff --git a/script/dev-node.sh b/script/dev-node.sh new file mode 100755 index 0000000..a93af09 --- /dev/null +++ b/script/dev-node.sh @@ -0,0 +1,32 @@ +#! /bin/bash + +VENDOR_ID="$(echo "$1" | awk '-F:' '{ print $1 }')" +PRODUCT_ID="$(echo "$1" | awk '-F:' '{ print $2 }')" + +if [ -z "$VENDOR_ID" ] || [ -z "$PRODUCT_ID" ] ; then + >&2 echo "You must specify a device identifier in the format xxxx:yyyy" + exit 1 +fi + +echo "Nodes for $VENDOR_ID:$PRODUCT_ID" + +find /sys/devices -name uevent | { + readarray -t uevents + + for u in "${uevents[@]}"; do + path="${u%/uevent}" + while [ "$path" != "/sys/devices" ] && ! [ -f "$path"/idVendor ]; do + path="${path%/*}" + done + + [ "$path" != "/sys/devices" ] && read readValue < "$path"/idVendor && [ "$readValue" = "$VENDOR_ID" ] && { + if [ -n "$idProduct" ]; then + read readValue < "$path"/idProduct && [ "$readValue" = "$PRODUCT_ID" ] + fi + } && echo "$u" + done +} | { + readarray -t uevents + + [ ${#uevents[@]} -gt 0 ] && sed -n 's,DEVNAME=\(.*\),/dev/\1,p' "${uevents[@]}" +} diff --git a/script/docker.js b/script/docker.js new file mode 100755 index 0000000..d9619a6 --- /dev/null +++ b/script/docker.js @@ -0,0 +1,167 @@ +#! /usr/bin/env node +const promisify = require('util').promisify; +const childProcess = require('child_process'); +const execFile = promisify(childProcess.execFile); +const spawn = require('child_pty').spawn; + +let pullStarted = false; +let pullEnded = false; + +const oldTitlePromise = + execFile('tmux', ['display', '-pt', '?', '#{pane_title}'], { + windowsHide: true, + }).catch(() => ({ stdout: '', stderr: '' })); + +const whale = '\u{1f433}'; + +const setTitle = async (title) => { + const oldTitle = await oldTitlePromise; + const pre = oldTitle.stdout.split(whale)[0]; + let newTitle = oldTitle.stdout; + if(title) { + newTitle = pre + whale + title; + } + process.stdout.write('\x1b]2;' + newTitle + '\x1b\\'); +}; + +const progress = {}; +let lastHash = ''; +let averageTotal = 0; +const handle = async (data) => { + const strData = data.toString(); + + process.stdout.write(strData.replace(/\r\n?/g, '\n')); + + if(pullStarted && pullEnded) { + return; + } + + for(const line of strData.split(/[\r\n]+/g)) { + if(!pullStarted) { + if (!/^.*:\s*Pulling\s+from\s+\S+\s*$/i.test(line)) { + continue; + } + + pullStarted = true; + + setTitle('pull'); + + continue; + } + else if(!pullEnded) { + if(/^\s*Status:\s+Downloaded\s+newer\s+image\s+for/i.test(line)) { + pullEnded = true; + + setTitle('pulled'); + + setTitle(); + + break; + } + } + + let match; + if(match = /([0-9a-f]+):/ig.exec(line)) { + lastHash = match[1] || lastHash; + } + + if(!lastHash) { + continue; + } + + if(match = /(Pull\s+complete|Already\s+exists|Pulling\s+fs\s+layer|Downloading\s+\[([=>\s]+)\]\s+([0-9\.]+)\w+\/([0-9\.]+)\w+)/ig.exec(line)) { + const eventType = match[1]; + const bar = match[2]; + const unit = match[3]; + const total = match[4]; + + if(eventType == 'Already exists' || eventType == 'Pull complete') { + const oldHash = progress[lastHash] || {}; + progress[lastHash] = { + unit: oldHash.total, + total: oldHash.total, + } + } + else if(eventType == 'Pulling fs layer') { + progress[lastHash] = { + unit: 0, + total: averageTotal, + } + } + else if(bar && unit && total) { + progress[lastHash] = { + unit: parseFloat(unit), + total: parseFloat(total), + }; + } + + let units = 0; + let totals = 0; + for(const p in progress) { + const item = progress[p]; + units += item.unit; + totals += item.total; + } + + debugger; + + averageTotal = totals / Object.keys(progress).length; + + setTitle(((units / totals).toFixed(2) * 100) + '%'); + } + } +}; + +let args = [...process.argv]; +const debug = args.includes('--debug'); + +const main = async() => { + args.shift(); + args.shift(); + + if(debug) { + args.shift(); + + try { + await execFile('docker', ['rmi', args[0]], { + windowsHide: true, + }); + } + catch(e) { + console.error(e); + // Image already gone? + } + + args = ['run', '-it', '--rm', ...args]; + } + + const commandName = args.filter(x => x && !x.startsWith("-")); + + /* Output sample for pull + alpine: Pulling from library/node + 6c40cc604d8e: Already exists + bf8900ab0b62: Downloading [=> ] 440kB/21.57MB + 287f798ae2cd: Downloading [===============> ] 423.6kB/1.332MB + */ + + const docker = spawn('docker', args, { + columns: 200, + rows: 1, + name: 'xterm', + cwd: process.cwd(), + }); + + !debug && process.stdin.setRawMode(true); + process.stdin.pipe(docker.stdin); + + docker.stdout.on('data', data => handle(data).catch(e => debug && console.error(e))); + + docker.on('close', () => process.exit(0)); +}; + +main() + .then(() => {}) + .catch(e => { + debug && console.error(e); + process.exit(1); + }); diff --git a/script/flickr-wallpaper.py b/script/flickr-wallpaper.py new file mode 100755 index 0000000..3848141 --- /dev/null +++ b/script/flickr-wallpaper.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3 +"""Usage: python flickr-wallpaper.py CONFIG_PATH + +ARGUMENTS: + -c or --config : path to config file ('./config') + +Config File must have the following format: + groups = Comma-separated list of Flickr Group IDs (ex. 796617@N22) + image_root = PATH to where downloaded files should go (ex. ~/wallpapers) + api_key = API KEY from Flickr + +""" + +import sys +import urllib.request, urllib.parse, urllib.error +import hashlib +import os +import string +from urllib.parse import urlencode +from urllib.request import urlopen +from xml.dom import minidom +from pprint import pprint +from configobj import ConfigObj +from time import time +from datetime import datetime + +HOST = 'http://flickr.com' +API = '/services/rest' +AUTH = False +debug = False + +CONFIG_FILENAME = '' +API_KEY = '' + +def main(*argv): + from getopt import getopt, GetoptError + + global API_KEY + global CONFIG_FILENAME + + try: + (opts, args) = getopt(argv[1:],\ + 'c:',\ + ['config']) + except GetoptError as e: + print(e) + print(__doc__) + return 1 + + for o, a in opts: + if o in ('-c' , '--config'): + CONFIG_FILENAME = a + else: + print("Unknown argument: %s" % o) + print(__doc__) + return 1 + + if (CONFIG_FILENAME == ''): + CONFIG_FILENAME = '~/.flickr-wallpaper-config' + + CONFIG_FILENAME = os.path.expandvars(CONFIG_FILENAME) + CONFIG_FILENAME = os.path.expanduser(CONFIG_FILENAME) + print('Using Config file: %s' % CONFIG_FILENAME) + + API_KEY = get_api_key() + if (API_KEY == ''): + print("Missing API KEY, must have a line in config file for Flickr API Key, ex. api_key = dddddddd") + print(__doc__) + return 1 + + image_root = get_image_root() + if (image_root == ''): + print("Missing image_root, must have a line in config file for image root, ex. image_root = /path/to/download") + print(__doc__) + return 1 + + if not os.path.exists(image_root): + print('Image root path not found, creating path: ' + image_root) + os.makedirs(image_root) + + for groupid in get_groups(): + min_upload_date = get_min_upload_date(groupid) + download_photos_from_group(image_root, groupid, min_upload_date) + set_min_upload_date(groupid); + +def photos_search(user_id='', auth=False, tags='', tag_mode='', text='',\ + min_upload_date='', max_upload_date='',\ + min_taken_date='', max_taken_date='', \ + license='', per_page='', page='', sort='',\ + safe_search='', content_type='', + extras='', group_id=''): + """Returns a list of Photo objects. + + If auth=True then will auth the user. Can see private etc + """ + method = 'flickr.photos.search' + + data = _doget(method, auth=auth, user_id=user_id, tags=tags, text=text,\ + min_upload_date=min_upload_date,\ + max_upload_date=max_upload_date, \ + min_taken_date=min_taken_date, \ + max_taken_date=max_taken_date, \ + license=license, per_page=per_page,\ + page=page, sort=sort, safe_search=safe_search, \ + content_type=content_type, \ + extras=extras, group_id=group_id, \ + tag_mode=tag_mode) + + return data + +def _doget(method, auth=False, **params): + #uncomment to check you aren't killing the flickr server + #print "***** do get %s" % method + + params = _prepare_params(params) + url = '%s%s/?api_key=%s&method=%s&%s%s'% \ + (HOST, API, API_KEY, method, urlencode(params), + _get_auth_url_suffix(method, auth, params)) + + #another useful debug print statement + if (debug): print("_doget", url) + + return minidom.parse(urlopen(url)) + +def _prepare_params(params): + """Convert lists to strings with ',' between items.""" + for (key, value) in list(params.items()): + if isinstance(value, list): + params[key] = ','.join([item for item in value]) + return params + +def _get_auth_url_suffix(method, auth, params): + """Figure out whether we want to authorize, and if so, construct a suitable + URL suffix to pass to the Flickr API.""" + authentication = False + + # auth may be passed in via the API, AUTH may be set globally (in the same + # manner as API_KEY, etc). We do a few more checks than may seem necessary + # because we allow the 'auth' parameter to actually contain the + # authentication token, not just True/False. + if auth or AUTH: + token = userToken() + authentication = True; + elif auth != False: + token = auth; + authentication = True; + elif AUTH != False: + token = AUTH; + authentication = True; + + # If we're not authenticating, no suffix is required. + if not authentication: + return '' + + full_params = params + full_params['method'] = method + + return '&auth_token=%s&api_sig=%s' % (token, _get_api_sig(full_params) ) + +def build_photo(photo): + url = photo.getAttribute('url_o') + height = photo.getAttribute('height_o') + width = photo.getAttribute('width_o') + title = photo.getAttribute('title') + id = photo.getAttribute('id') + return (url, height, width, title, id) + +def get_min_upload_date(groupid): + """Figure out the last time this script was run, so we only get recent pictures""" + if (os.path.exists(CONFIG_FILENAME)): + config = ConfigObj(CONFIG_FILENAME) + try: + return config[groupid]['min_upload_date'] + except KeyError: + return '0' + else: + return '0' + +def set_min_upload_date(groupid): + config = ConfigObj(CONFIG_FILENAME) + config[groupid] = {} + config[groupid]['min_upload_date'] = time() + config.write() + +def get_groups(): + config = ConfigObj(CONFIG_FILENAME) + return config['groups'] + +def sanitize_filename(filename): + import unicodedata + validFilenameChars = "-_.() %s%s" % (string.ascii_letters, string.digits) + cleanedFilename = unicodedata.normalize('NFKD', filename).encode('ASCII', 'ignore') + return ''.join(c for c in cleanedFilename if c in validFilenameChars) + +def download_photos_from_group(image_root, groupid, min_upload_date): + print('Finding pictures for group: ' + groupid + ' since: ' + datetime.fromtimestamp(float(min_upload_date)).strftime("%Y-%m-%d %H:%M:%S")) + photos = photos_search(group_id=groupid, min_upload_date=min_upload_date, extras='url_o, original_format') + + for photo in photos.getElementsByTagName('photo'): + (url, height, width, title, id) = build_photo(photo) + if (url != '' and height != '' and int(height) > 900): + try: + image = urlopen(url) + picture = image.read() + filename = os.path.join(image_root, id + '-' + sanitize_filename(string.replace(title, ' ', '-')) + url[-4:]) + if not os.path.exists(filename): + fout = open(filename, 'wb') + fout.write(picture) + fout.close() + print('Saved ' + filename) + else: + print('Skipped ' + filename) + except IOError: + print('Error on url: ' + url + ', skipping') + +def get_image_root(): + config = ConfigObj(CONFIG_FILENAME) + return config['image_root'] + +def get_api_key(): + config = ConfigObj(CONFIG_FILENAME) + return config['api_key'] + +if __name__ == '__main__': + sys.exit(main(*sys.argv)) diff --git a/script/git-walk b/script/git-walk new file mode 100755 index 0000000..cf65839 --- /dev/null +++ b/script/git-walk @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +# Walks up and down revisions in a git repo. +# Usage: +# git walk next +# git walk prev +case ARGV[0] +when "next" + rev_list = `git rev-list --children --all` + refs = rev_list.scan(/[a-z0-9]{40}(?= )/) + refs.unshift(rev_list[/[a-z0-9]{40}/]) + refs.reverse! + + head = `git rev-parse HEAD`.chomp + ref_for_next_commit = refs[refs.index(head) + 1] + + if ref_for_next_commit + puts `git checkout #{ref_for_next_commit}` + else + puts "You're already on the latest commit." + end +when "prev" + puts `git checkout HEAD^` +else + puts "Usage: git-walk next|prev" +end diff --git a/script/gtk-theme-toggler b/script/gtk-theme-toggler new file mode 100755 index 0000000..1523c18 --- /dev/null +++ b/script/gtk-theme-toggler @@ -0,0 +1,8 @@ +#! /bin/bash + +function tog () { + sed -i 's/gtk-theme-name=.*/gtk-theme-name="'"$1"'"/g' "$HOME/.gtkrc-2.0" + sed -i 's/gtk-theme-name=.*/gtk-theme-name='"$1"'/g' "$HOME/.config/gtk-3.0/settings.ini" +} + +tog "$1" diff --git a/script/kexec-now b/script/kexec-now new file mode 100755 index 0000000..c8afc7b --- /dev/null +++ b/script/kexec-now @@ -0,0 +1,3 @@ +#! /bin/sh +kexec -l /boot/vmlinuz-$(uname -r) --initrd=/boot/initrd.img-$(uname -r) --reuse-cmdline +systemctl kexec diff --git a/script/markdown-toc.rb b/script/markdown-toc.rb new file mode 100755 index 0000000..1081ca4 --- /dev/null +++ b/script/markdown-toc.rb @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby + +require 'uri' + +fileName = ARGV[0] +fileName = "README.md" if !fileName + +File.open(fileName, 'r') do |f| + inside_code_snippet = false + f.each_line do |line| + forbidden_words = ['Table of contents', 'define', 'pragma'] + inside_code_snippet = !inside_code_snippet if line.start_with?('```') + next if !line.start_with?("#") || forbidden_words.any? { |w| line =~ /#{w}/ } || inside_code_snippet + + title = line.gsub("#", "").strip + href = URI::encode title.gsub(" ", "-").downcase + puts " " * (line.count("#")-1) + "* [#{title}](\##{href})" + end +end diff --git a/script/openport.js b/script/openport.js new file mode 100755 index 0000000..651553c --- /dev/null +++ b/script/openport.js @@ -0,0 +1,12 @@ +#! /usr/bin/env node +const openport = require('openport'); + +openport.find({ startingPort: 1024, endingPort: 60000 }, (err, port) => { + if(err) { + process.exit(1); + } + + console.log(port); + + process.exit(0); +}); diff --git a/script/package.json b/script/package.json new file mode 100644 index 0000000..c44ead1 --- /dev/null +++ b/script/package.json @@ -0,0 +1,17 @@ +{ + "name": "dotfiles-script", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "lint": "eslint .", + "debug:docker": "nodemon --inspect-brk -- ./docker.js --debug" + }, + "dependencies": { + "openport": "^0.0.6" + }, + "devDependencies": { + "eslint": "^7.8.1", + "nodemon": "^2.0.4" + } +} diff --git a/script/pnpm-lock.yaml b/script/pnpm-lock.yaml new file mode 100644 index 0000000..608268e --- /dev/null +++ b/script/pnpm-lock.yaml @@ -0,0 +1,1434 @@ +dependencies: + openport: 0.0.6 +devDependencies: + eslint: 7.8.1 + nodemon: 2.0.4 +lockfileVersion: 5.1 +packages: + /@babel/code-frame/7.10.4: + dependencies: + '@babel/highlight': 7.10.4 + dev: true + resolution: + integrity: sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + /@babel/helper-validator-identifier/7.10.4: + dev: true + resolution: + integrity: sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + /@babel/highlight/7.10.4: + dependencies: + '@babel/helper-validator-identifier': 7.10.4 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + resolution: + integrity: sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + /@eslint/eslintrc/0.1.3: + dependencies: + ajv: 6.12.4 + debug: 4.1.1 + espree: 7.3.0 + globals: 12.4.0 + ignore: 4.0.6 + import-fresh: 3.2.1 + js-yaml: 3.14.0 + lodash: 4.17.20 + minimatch: 3.0.4 + strip-json-comments: 3.1.1 + dev: true + engines: + node: ^10.12.0 || >=12.0.0 + resolution: + integrity: sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA== + /@sindresorhus/is/0.14.0: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + /@szmarczak/http-timer/1.1.2: + dependencies: + defer-to-connect: 1.1.3 + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + /@types/color-name/1.1.1: + dev: true + resolution: + integrity: sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + /abbrev/1.1.1: + dev: true + resolution: + integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + /acorn-jsx/5.2.0_acorn@7.4.0: + dependencies: + acorn: 7.4.0 + dev: true + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 + resolution: + integrity: sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== + /acorn/7.4.0: + dev: true + engines: + node: '>=0.4.0' + hasBin: true + resolution: + integrity: sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== + /ajv/6.12.4: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.0 + dev: true + resolution: + integrity: sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== + /ansi-align/3.0.0: + dependencies: + string-width: 3.1.0 + dev: true + resolution: + integrity: sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + /ansi-colors/4.1.1: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + /ansi-regex/4.1.0: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + /ansi-regex/5.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + /ansi-styles/3.2.1: + dependencies: + color-convert: 1.9.3 + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + /ansi-styles/4.2.1: + dependencies: + '@types/color-name': 1.1.1 + color-convert: 2.0.1 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + /anymatch/3.1.1: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.2.2 + dev: true + engines: + node: '>= 8' + resolution: + integrity: sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + /argparse/1.0.10: + dependencies: + sprintf-js: 1.0.3 + dev: true + resolution: + integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + /astral-regex/1.0.0: + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + /balanced-match/1.0.0: + dev: true + resolution: + integrity: sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + /binary-extensions/2.1.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + /boxen/4.2.0: + dependencies: + ansi-align: 3.0.0 + camelcase: 5.3.1 + chalk: 3.0.0 + cli-boxes: 2.2.1 + string-width: 4.2.0 + term-size: 2.2.0 + type-fest: 0.8.1 + widest-line: 3.1.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== + /brace-expansion/1.1.11: + dependencies: + balanced-match: 1.0.0 + concat-map: 0.0.1 + dev: true + resolution: + integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + /braces/3.0.2: + dependencies: + fill-range: 7.0.1 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + /cacheable-request/6.1.0: + dependencies: + clone-response: 1.0.2 + get-stream: 5.2.0 + http-cache-semantics: 4.1.0 + keyv: 3.1.0 + lowercase-keys: 2.0.0 + normalize-url: 4.5.0 + responselike: 1.0.2 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + /callsites/3.1.0: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + /camelcase/5.3.1: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + /chalk/2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + /chalk/3.0.0: + dependencies: + ansi-styles: 4.2.1 + supports-color: 7.2.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + /chalk/4.1.0: + dependencies: + ansi-styles: 4.2.1 + supports-color: 7.2.0 + dev: true + engines: + node: '>=10' + resolution: + integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + /chokidar/3.4.2: + dependencies: + anymatch: 3.1.1 + braces: 3.0.2 + glob-parent: 5.1.1 + is-binary-path: 2.1.0 + is-glob: 4.0.1 + normalize-path: 3.0.0 + readdirp: 3.4.0 + dev: true + engines: + node: '>= 8.10.0' + optionalDependencies: + fsevents: 2.1.3 + resolution: + integrity: sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== + /ci-info/2.0.0: + dev: true + resolution: + integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + /cli-boxes/2.2.1: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + /clone-response/1.0.2: + dependencies: + mimic-response: 1.0.1 + dev: true + resolution: + integrity: sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + /color-convert/1.9.3: + dependencies: + color-name: 1.1.3 + dev: true + resolution: + integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + /color-convert/2.0.1: + dependencies: + color-name: 1.1.4 + dev: true + engines: + node: '>=7.0.0' + resolution: + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + /color-name/1.1.3: + dev: true + resolution: + integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + /color-name/1.1.4: + dev: true + resolution: + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + /concat-map/0.0.1: + dev: true + resolution: + integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + /configstore/5.0.1: + dependencies: + dot-prop: 5.2.0 + graceful-fs: 4.2.4 + make-dir: 3.1.0 + unique-string: 2.0.0 + write-file-atomic: 3.0.3 + xdg-basedir: 4.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + /cross-spawn/7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + engines: + node: '>= 8' + resolution: + integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + /crypto-random-string/2.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + /debug/2.6.9: + dependencies: + ms: 2.0.0 + dev: true + resolution: + integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + /debug/3.2.6: + dependencies: + ms: 2.1.2 + dev: true + resolution: + integrity: sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + /debug/4.1.1: + dependencies: + ms: 2.1.2 + dev: true + resolution: + integrity: sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + /decompress-response/3.3.0: + dependencies: + mimic-response: 1.0.1 + dev: true + engines: + node: '>=4' + resolution: + integrity: sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + /deep-extend/0.6.0: + dev: true + engines: + node: '>=4.0.0' + resolution: + integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + /deep-is/0.1.3: + dev: true + resolution: + integrity: sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + /defer-to-connect/1.1.3: + dev: true + resolution: + integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + /doctrine/3.0.0: + dependencies: + esutils: 2.0.3 + dev: true + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + /dot-prop/5.2.0: + dependencies: + is-obj: 2.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== + /duplexer3/0.1.4: + dev: true + resolution: + integrity: sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + /emoji-regex/7.0.3: + dev: true + resolution: + integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + /emoji-regex/8.0.0: + dev: true + resolution: + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + /end-of-stream/1.4.4: + dependencies: + once: 1.4.0 + dev: true + resolution: + integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + /enquirer/2.3.6: + dependencies: + ansi-colors: 4.1.1 + dev: true + engines: + node: '>=8.6' + resolution: + integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + /escape-goat/2.1.1: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + /escape-string-regexp/1.0.5: + dev: true + engines: + node: '>=0.8.0' + resolution: + integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + /eslint-scope/5.1.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + engines: + node: '>=8.0.0' + resolution: + integrity: sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== + /eslint-utils/2.1.0: + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + /eslint-visitor-keys/1.3.0: + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + /eslint/7.8.1: + dependencies: + '@babel/code-frame': 7.10.4 + '@eslint/eslintrc': 0.1.3 + ajv: 6.12.4 + chalk: 4.1.0 + cross-spawn: 7.0.3 + debug: 4.1.1 + doctrine: 3.0.0 + enquirer: 2.3.6 + eslint-scope: 5.1.0 + eslint-utils: 2.1.0 + eslint-visitor-keys: 1.3.0 + espree: 7.3.0 + esquery: 1.3.1 + esutils: 2.0.3 + file-entry-cache: 5.0.1 + functional-red-black-tree: 1.0.1 + glob-parent: 5.1.1 + globals: 12.4.0 + ignore: 4.0.6 + import-fresh: 3.2.1 + imurmurhash: 0.1.4 + is-glob: 4.0.1 + js-yaml: 3.14.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash: 4.17.20 + minimatch: 3.0.4 + natural-compare: 1.4.0 + optionator: 0.9.1 + progress: 2.0.3 + regexpp: 3.1.0 + semver: 7.3.2 + strip-ansi: 6.0.0 + strip-json-comments: 3.1.1 + table: 5.4.6 + text-table: 0.2.0 + v8-compile-cache: 2.1.1 + dev: true + engines: + node: ^10.12.0 || >=12.0.0 + hasBin: true + resolution: + integrity: sha512-/2rX2pfhyUG0y+A123d0ccXtMm7DV7sH1m3lk9nk2DZ2LReq39FXHueR9xZwshE5MdfSf0xunSaMWRqyIA6M1w== + /espree/7.3.0: + dependencies: + acorn: 7.4.0 + acorn-jsx: 5.2.0_acorn@7.4.0 + eslint-visitor-keys: 1.3.0 + dev: true + engines: + node: ^10.12.0 || >=12.0.0 + resolution: + integrity: sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== + /esprima/4.0.1: + dev: true + engines: + node: '>=4' + hasBin: true + resolution: + integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + /esquery/1.3.1: + dependencies: + estraverse: 5.2.0 + dev: true + engines: + node: '>=0.10' + resolution: + integrity: sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + /esrecurse/4.3.0: + dependencies: + estraverse: 5.2.0 + dev: true + engines: + node: '>=4.0' + resolution: + integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + /estraverse/4.3.0: + dev: true + engines: + node: '>=4.0' + resolution: + integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + /estraverse/5.2.0: + dev: true + engines: + node: '>=4.0' + resolution: + integrity: sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + /esutils/2.0.3: + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + /fast-deep-equal/3.1.3: + dev: true + resolution: + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + /fast-json-stable-stringify/2.1.0: + dev: true + resolution: + integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + /fast-levenshtein/2.0.6: + dev: true + resolution: + integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + /file-entry-cache/5.0.1: + dependencies: + flat-cache: 2.0.1 + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + /fill-range/7.0.1: + dependencies: + to-regex-range: 5.0.1 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + /flat-cache/2.0.1: + dependencies: + flatted: 2.0.2 + rimraf: 2.6.3 + write: 1.0.3 + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + /flatted/2.0.2: + dev: true + resolution: + integrity: sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== + /fs.realpath/1.0.0: + dev: true + resolution: + integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + /fsevents/2.1.3: + dev: true + engines: + node: ^8.16.0 || ^10.6.0 || >=11.0.0 + optional: true + os: + - darwin + resolution: + integrity: sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + /functional-red-black-tree/1.0.1: + dev: true + resolution: + integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + /get-stream/4.1.0: + dependencies: + pump: 3.0.0 + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + /get-stream/5.2.0: + dependencies: + pump: 3.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + /glob-parent/5.1.1: + dependencies: + is-glob: 4.0.1 + dev: true + engines: + node: '>= 6' + resolution: + integrity: sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + /glob/7.1.6: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + resolution: + integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + /global-dirs/2.0.1: + dependencies: + ini: 1.3.5 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A== + /globals/12.4.0: + dependencies: + type-fest: 0.8.1 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + /got/9.6.0: + dependencies: + '@sindresorhus/is': 0.14.0 + '@szmarczak/http-timer': 1.1.2 + cacheable-request: 6.1.0 + decompress-response: 3.3.0 + duplexer3: 0.1.4 + get-stream: 4.1.0 + lowercase-keys: 1.0.1 + mimic-response: 1.0.1 + p-cancelable: 1.1.0 + to-readable-stream: 1.0.0 + url-parse-lax: 3.0.0 + dev: true + engines: + node: '>=8.6' + resolution: + integrity: sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + /graceful-fs/4.2.4: + dev: true + resolution: + integrity: sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + /has-flag/3.0.0: + dev: true + engines: + node: '>=4' + resolution: + integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + /has-flag/4.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + /has-yarn/2.1.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + /http-cache-semantics/4.1.0: + dev: true + resolution: + integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + /ignore-by-default/1.0.1: + dev: true + resolution: + integrity: sha1-SMptcvbGo68Aqa1K5odr44ieKwk= + /ignore/4.0.6: + dev: true + engines: + node: '>= 4' + resolution: + integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + /import-fresh/3.2.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + /import-lazy/2.1.0: + dev: true + engines: + node: '>=4' + resolution: + integrity: sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + /imurmurhash/0.1.4: + dev: true + engines: + node: '>=0.8.19' + resolution: + integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o= + /inflight/1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + resolution: + integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + /inherits/2.0.4: + dev: true + resolution: + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + /ini/1.3.5: + dev: true + resolution: + integrity: sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + /is-binary-path/2.1.0: + dependencies: + binary-extensions: 2.1.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + /is-ci/2.0.0: + dependencies: + ci-info: 2.0.0 + dev: true + hasBin: true + resolution: + integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + /is-extglob/2.1.1: + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + /is-fullwidth-code-point/2.0.0: + dev: true + engines: + node: '>=4' + resolution: + integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + /is-fullwidth-code-point/3.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + /is-glob/4.0.1: + dependencies: + is-extglob: 2.1.1 + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + /is-installed-globally/0.3.2: + dependencies: + global-dirs: 2.0.1 + is-path-inside: 3.0.2 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== + /is-npm/4.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== + /is-number/7.0.0: + dev: true + engines: + node: '>=0.12.0' + resolution: + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + /is-obj/2.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + /is-path-inside/3.0.2: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== + /is-typedarray/1.0.0: + dev: true + resolution: + integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + /is-yarn-global/0.3.0: + dev: true + resolution: + integrity: sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + /isexe/2.0.0: + dev: true + resolution: + integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + /js-tokens/4.0.0: + dev: true + resolution: + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + /js-yaml/3.14.0: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + hasBin: true + resolution: + integrity: sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + /json-buffer/3.0.0: + dev: true + resolution: + integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + /json-schema-traverse/0.4.1: + dev: true + resolution: + integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + /json-stable-stringify-without-jsonify/1.0.1: + dev: true + resolution: + integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + /keyv/3.1.0: + dependencies: + json-buffer: 3.0.0 + dev: true + resolution: + integrity: sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + /latest-version/5.1.0: + dependencies: + package-json: 6.5.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + /levn/0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + /lodash/4.17.20: + dev: true + resolution: + integrity: sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + /lowercase-keys/1.0.1: + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + /lowercase-keys/2.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + /make-dir/3.1.0: + dependencies: + semver: 6.3.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + /mimic-response/1.0.1: + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + /minimatch/3.0.4: + dependencies: + brace-expansion: 1.1.11 + dev: true + resolution: + integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + /minimist/1.2.5: + dev: true + resolution: + integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + /mkdirp/0.5.5: + dependencies: + minimist: 1.2.5 + dev: true + hasBin: true + resolution: + integrity: sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + /ms/2.0.0: + dev: true + resolution: + integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + /ms/2.1.2: + dev: true + resolution: + integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + /natural-compare/1.4.0: + dev: true + resolution: + integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + /nodemon/2.0.4: + dependencies: + chokidar: 3.4.2 + debug: 3.2.6 + ignore-by-default: 1.0.1 + minimatch: 3.0.4 + pstree.remy: 1.1.8 + semver: 5.7.1 + supports-color: 5.5.0 + touch: 3.1.0 + undefsafe: 2.0.3 + update-notifier: 4.1.1 + dev: true + engines: + node: '>=8.10.0' + hasBin: true + requiresBuild: true + resolution: + integrity: sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ== + /nopt/1.0.10: + dependencies: + abbrev: 1.1.1 + dev: true + hasBin: true + resolution: + integrity: sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + /normalize-path/3.0.0: + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + /normalize-url/4.5.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== + /once/1.4.0: + dependencies: + wrappy: 1.0.2 + dev: true + resolution: + integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + /openport/0.0.6: + deprecated: Use portfinder + dev: false + engines: + node: '>=0.6.0' + resolution: + integrity: sha512-Dwd5F2mT0vrEqKLcohOdSRYNusFZs+gA8clYGOUmaLZh+lfh8+wKvCbBFrYIXUcuRke1KLQQuqj3zaHgYdNxqA== + /optionator/0.9.1: + dependencies: + deep-is: 0.1.3 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.3 + dev: true + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + /p-cancelable/1.1.0: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + /package-json/6.5.0: + dependencies: + got: 9.6.0 + registry-auth-token: 4.2.0 + registry-url: 5.1.0 + semver: 6.3.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + /parent-module/1.0.1: + dependencies: + callsites: 3.1.0 + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + /path-is-absolute/1.0.1: + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + /path-key/3.1.1: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + /picomatch/2.2.2: + dev: true + engines: + node: '>=8.6' + resolution: + integrity: sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + /prelude-ls/1.2.1: + dev: true + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + /prepend-http/2.0.0: + dev: true + engines: + node: '>=4' + resolution: + integrity: sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + /progress/2.0.3: + dev: true + engines: + node: '>=0.4.0' + resolution: + integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + /pstree.remy/1.1.8: + dev: true + resolution: + integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + /pump/3.0.0: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + resolution: + integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + /punycode/2.1.1: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + /pupa/2.0.1: + dependencies: + escape-goat: 2.1.1 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA== + /rc/1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.5 + minimist: 1.2.5 + strip-json-comments: 2.0.1 + dev: true + hasBin: true + resolution: + integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + /readdirp/3.4.0: + dependencies: + picomatch: 2.2.2 + dev: true + engines: + node: '>=8.10.0' + resolution: + integrity: sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== + /regexpp/3.1.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + /registry-auth-token/4.2.0: + dependencies: + rc: 1.2.8 + dev: true + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w== + /registry-url/5.1.0: + dependencies: + rc: 1.2.8 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + /resolve-from/4.0.0: + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + /responselike/1.0.2: + dependencies: + lowercase-keys: 1.0.1 + dev: true + resolution: + integrity: sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + /rimraf/2.6.3: + dependencies: + glob: 7.1.6 + dev: true + hasBin: true + resolution: + integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + /semver-diff/3.1.1: + dependencies: + semver: 6.3.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + /semver/5.7.1: + dev: true + hasBin: true + resolution: + integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + /semver/6.3.0: + dev: true + hasBin: true + resolution: + integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + /semver/7.3.2: + dev: true + engines: + node: '>=10' + hasBin: true + resolution: + integrity: sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + /shebang-command/2.0.0: + dependencies: + shebang-regex: 3.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + /shebang-regex/3.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + /signal-exit/3.0.3: + dev: true + resolution: + integrity: sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + /slice-ansi/2.1.0: + dependencies: + ansi-styles: 3.2.1 + astral-regex: 1.0.0 + is-fullwidth-code-point: 2.0.0 + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + /sprintf-js/1.0.3: + dev: true + resolution: + integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + /string-width/3.1.0: + dependencies: + emoji-regex: 7.0.3 + is-fullwidth-code-point: 2.0.0 + strip-ansi: 5.2.0 + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + /string-width/4.2.0: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + /strip-ansi/5.2.0: + dependencies: + ansi-regex: 4.1.0 + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + /strip-ansi/6.0.0: + dependencies: + ansi-regex: 5.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + /strip-json-comments/2.0.1: + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo= + /strip-json-comments/3.1.1: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + /supports-color/5.5.0: + dependencies: + has-flag: 3.0.0 + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + /supports-color/7.2.0: + dependencies: + has-flag: 4.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + /table/5.4.6: + dependencies: + ajv: 6.12.4 + lodash: 4.17.20 + slice-ansi: 2.1.0 + string-width: 3.1.0 + dev: true + engines: + node: '>=6.0.0' + resolution: + integrity: sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + /term-size/2.2.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== + /text-table/0.2.0: + dev: true + resolution: + integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + /to-readable-stream/1.0.0: + dev: true + engines: + node: '>=6' + resolution: + integrity: sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + /to-regex-range/5.0.1: + dependencies: + is-number: 7.0.0 + dev: true + engines: + node: '>=8.0' + resolution: + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + /touch/3.1.0: + dependencies: + nopt: 1.0.10 + dev: true + hasBin: true + resolution: + integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== + /type-check/0.4.0: + dependencies: + prelude-ls: 1.2.1 + dev: true + engines: + node: '>= 0.8.0' + resolution: + integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + /type-fest/0.8.1: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + /typedarray-to-buffer/3.1.5: + dependencies: + is-typedarray: 1.0.0 + dev: true + resolution: + integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + /undefsafe/2.0.3: + dependencies: + debug: 2.6.9 + dev: true + resolution: + integrity: sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A== + /unique-string/2.0.0: + dependencies: + crypto-random-string: 2.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + /update-notifier/4.1.1: + dependencies: + boxen: 4.2.0 + chalk: 3.0.0 + configstore: 5.0.1 + has-yarn: 2.1.0 + import-lazy: 2.1.0 + is-ci: 2.0.0 + is-installed-globally: 0.3.2 + is-npm: 4.0.0 + is-yarn-global: 0.3.0 + latest-version: 5.1.0 + pupa: 2.0.1 + semver-diff: 3.1.1 + xdg-basedir: 4.0.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-9y+Kds0+LoLG6yN802wVXoIfxYEwh3FlZwzMwpCZp62S2i1/Jzeqb9Eeeju3NSHccGGasfGlK5/vEHbAifYRDg== + /uri-js/4.4.0: + dependencies: + punycode: 2.1.1 + dev: true + resolution: + integrity: sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + /url-parse-lax/3.0.0: + dependencies: + prepend-http: 2.0.0 + dev: true + engines: + node: '>=4' + resolution: + integrity: sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + /v8-compile-cache/2.1.1: + dev: true + resolution: + integrity: sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== + /which/2.0.2: + dependencies: + isexe: 2.0.0 + dev: true + engines: + node: '>= 8' + hasBin: true + resolution: + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + /widest-line/3.1.0: + dependencies: + string-width: 4.2.0 + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + /word-wrap/1.2.3: + dev: true + engines: + node: '>=0.10.0' + resolution: + integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + /wrappy/1.0.2: + dev: true + resolution: + integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + /write-file-atomic/3.0.3: + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.3 + typedarray-to-buffer: 3.1.5 + dev: true + resolution: + integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + /write/1.0.3: + dependencies: + mkdirp: 0.5.5 + dev: true + engines: + node: '>=4' + resolution: + integrity: sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + /xdg-basedir/4.0.0: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== +specifiers: + eslint: ^7.8.1 + nodemon: ^2.0.4 + openport: ^0.0.6 diff --git a/script/svn-diffwrap b/script/svn-diffwrap new file mode 100755 index 0000000..971065c --- /dev/null +++ b/script/svn-diffwrap @@ -0,0 +1,16 @@ +#!/bin/sh + +# Configure your favorite diff program here. +DIFF="/usr/bin/vimdiff" + +# Subversion provides the paths we need as the sixth and seventh +# parameters. +LEFT=${6} +RIGHT=${7} + +# Call the diff command (change the following line to make sense for +# your merge program). +$DIFF $LEFT $RIGHT + +# Return an errorcode of 0 if no differences were detected, 1 if some were. +# Any other errorcode will be treated as fatal. diff --git a/script/unfuckusb.sh b/script/unfuckusb.sh new file mode 100755 index 0000000..a392f5a --- /dev/null +++ b/script/unfuckusb.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Script to reset all local xHCI (USB) controllers +# Based on: http://billauer.co.il/blog/2013/02/usb-reset-ehci-uhci-linux/ + +if [[ ${EUID} != 0 ]]; then + echo This must be run as root! + exit 1 +fi + +for xhci in /sys/bus/pci/drivers/?hci_hcd; do + if ! cd ${xhci}; then + echo "Weird error. Failed to change directory to ${xhci}." + exit 1 + fi + echo "Resetting devices from ${xhci}..." + for i in ????:??:??.?; do + echo -n "${i}" > unbind + echo -n "${i}" > bind + done +done diff --git a/script/vimcat b/script/vimcat new file mode 100755 index 0000000..c64967c --- /dev/null +++ b/script/vimcat @@ -0,0 +1,2 @@ +#! /bin/bash +"$HOME/.vim/plugged/vimcat/vimcat" "$@" diff --git a/setup/setup.sh b/setup/setup.sh new file mode 100755 index 0000000..92db98a --- /dev/null +++ b/setup/setup.sh @@ -0,0 +1,178 @@ +#! /bin/bash +set -e + +which gls 2>/dev/null && IS_BREW=1 || IS_BREW=0 + +IS_DARWIN=$((0)) +IS_LINUX=$((0)) +IS_WINDOWS=$((0)) +LINKS_ONLY=$((0)) +case "$OSTYPE" in + linux-*) IS_LINUX=$((1)) ;; + darwin*) IS_DARWIN=$((1)) ;; + *) IS_WINDOWS=$((1)) ;; +esac + +USE_NPM=$((1)) +while [ -n "$1" ] ; do + case "$1" in + --skip-npm) USE_NPM=$((0)) ;; + --links-only) LINKS_ONLY=$((1)) ;; + esac + shift +done + +curlorwget () { + curl -sL "$@" | wget -qO- "$@" +} + +setuplink () { + local SRCPATH="$1" + local DEST="$2" + + if [ -f "$DEST" ] ; then + mv -v "$DEST" "$DEST.bak" || echo "$DEST already exists." + fi + + if [ ! -e "$DEST" ] ; then + local MDIR + if ((IS_WINDOWS)) ; then + echo "$DEST -> $SRCPATH" + if [ -d "$each" ] ; then + MDIR="/d" + else + MDIR="" + fi + # Also, screw any version of Windows other than 10. + powershell.exe -Command New-Item -ItemType SymbolicLink -Path "$(cygpath -w "$DEST")" -Value "$(cygpath -w "$SRCPATH")" + else + ln -v -s "$SRCPATH" "$DEST" + fi + fi +} + +setuplinks () { + local SRC="$1" + local DESTBASE="$2" + + local SRCPATH + find "$SRC" -maxdepth 1 -not -iname setup -not -iname .. -not -iname . -not -iname .git -not -iname .config -not -iname xfce4 -not -iname '.tern-*' | while read SRCPATH ; do + local DEST="$DESTBASE/$(basename "$SRCPATH")" + setuplink "$SRCPATH" "$DEST" + done +} + +ADDG= +((IS_BREW)) && ADDG="g" + +CURDIR="$(dirname $(${ADDG}readlink -f "$0"))" +CACHEDIR="$HOME/.cache/dotfiles" + +which pacman 2>&1 >/dev/null && IS_PACMAN=1 || IS_PACMAN=0 +which apt 2>&1 >/dev/null && IS_SUPERCOW=1 || IS_SUPERCOW=0 +IS_SUPERCOW=$((!IS_BREW && IS_SUPERCOW)) + +mkdir -p "$CACHEDIR" + +# This will probably get annoying... +setuplinks "$CURDIR/.." "$HOME" + +# We don't want to include this whole folder because lots of apps live here. Need some control... +setuplinks "$CURDIR/../.config" "$HOME/.config" + +mkdir -p "$HOME/.config/xfce4" +setuplinks "$CURDIR/../.config/xfce4" "$HOME/.config/xfce4" + +mkdir -p "$HOME/.config/dark-mode-notify" +setuplinks "$CURDIR/../.config/dark-mode-notify" "$HOME/.config/dark-mode-notify" + +setuplink "$CURDIR/../.vim" "$HOME/vimfiles" + +setuplink "$CURDIR/../.nvim" "$HOME/.config/nvim" + +mkdir -p "$HOME/.bashrc.local.d" + +((LINKS_ONLY)) && exit 0 + +if ((IS_WINDOWS)) ; then + # Git Bash: 'msys' + choco upgrade python nodejs neovim + ((USE_NPM)) && npm install -g pnpm + ((USE_NPM)) && pnpm add -g tern +else + if ((IS_PACMAN)) ; then + # pstree untested + # silversearcher-ag untested + sudo pacman -S python-pip python2-pip vim ruby pstree silversearcher-ag neovim + yay direnv + elif ((IS_SUPERCOW)) ; then + echo "USING APT" + + wget -qO - https://gitlab.com/paulcarroty/vscodium-deb-rpm-repo/raw/master/pub.gpg | gpg --dearmor | sudo dd of=/etc/apt/trusted.gpg.d/vscodium.gpg + echo 'deb https://paulcarroty.gitlab.io/vscodium-deb-rpm-repo/debs/ vscodium main' | sudo tee --append /etc/apt/sources.list.d/vscodium.list + + curl -fsSL https://deb.nodesource.com/setup_19.x | sudo -E bash - + + sudo apt update + sudo apt install blueman network-manager-gnome python3-pip python3-configobj fonts-powerline direnv vim-nox ruby silversearcher-ag nodejs jq codium pasystray gxkb rofi xdotool x11-xserver-utils indent libanyevent-i3-perl feh tk i3lock xautolock fonts-noto fonts-material-design-icons-iconfont fonts-materialdesignicons-webfont polybar fonts-font-awesome i3 curl playerctl xfce4-screenshooter imagemagick diodon fcitx-bin fcitx-mozc fcitx-imlist + + curlorwget https://releases.hyper.is/download/deb > "$CACHEDIR/hyper.deb" + sudo dpkg -i "$CACHEDIR/hyper.deb" || sudo apt install -f + + curlorwget http://cloudfront.debian.net/debian/pool/main/f/fonts-noto-color-emoji/fonts-noto-color-emoji_0~20200916-1_all.deb > "$CACHEDIR/noto-emoji.deb" + sudo dpkg -i "$CACHEDIR/noto-emoji.deb" + sudo apt install -f + elif ((IS_BREW)) ; then + brew install ipython direnv ruby vim nodejs pstree bash-completion ag neovim pyenv jq coreutils findutils fzf + fi + + ((USE_NPM && !IS_BREW)) && sudo npm install -g pnpm + ((USE_NPM && !IS_BREW)) && sudo pnpm add -g tern +fi + +vim '+PlugInstall' '+qall!' + +if ((!IS_BREW)) ; then + # Find package.jsons and reinstall all node packages + find "$CURDIR" -iname package.json | while read FILENAME ; do + PACKAGEDIR="$(dirname "$FILENAME")" + if [[ -e "$PACKAGEDIR/node_modules" ]] ; then + continue + fi + + ( + cd "$PACKAGEDIR" + yarn install + ) + done + + # For neovim + pyenv update + + pyenv install 2.7.11 + pyenv install 3.4.4 + + pyenv virtualenv 2.7.11 neovim2 + pyenv virtualenv 3.4.4 neovim3 + + pyenv activate neovim2 + pip install neovim + PYPATH2=$(pyenv which python) + + pyenv activate neovim3 + pip install neovim + PYPATH3=$(pyenv which python) + + pip3 install --upgrade --user i3-workspace-names-daemon + + pip3 install --upgrade --user neovim + pip install --upgrade --user neovim websocket-client sexpdata + + echo "$PYPATH2" + echo "$PYPATH3" + + curl https://sdk.cloud.google.com | bash +else + cd $HOME/.vim/plugged/dark-mode-notify + sudo make install +fi diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..8ff398f --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +