#
# Note: this may contain Windows line endings. If you're going to use it in Linux then you'll need
# to remove those with: `sed -i 's/\r//' <file>` or with `dos2unix`.
#

if which tput >/dev/null 2>&1; then
    ncolors=$(tput colors)
fi
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
    RED="$(tput setaf 1)"
    GREEN="$(tput setaf 2)"
    YELLOW="$(tput setaf 3)"
    BLUE="$(tput setaf 4)"
    MAGENTA="$(tput setaf 5)"
    CYAN="$(tput setaf 6)"
    BOLD="$(tput bold)"
    NORMAL="$(tput sgr0)"
else
    RED=""
    GREEN=""
    YELLOW=""
    BLUE=""
    MAGENTA=""
    CYAN=""
    BOLD=""
    NORMAL=""
fi

platform=`uname`

####################################################################################################
# Helper Functions
####################################################################################################

error() {
    printf "${BOLD}${RED}$1${NORMAL}\n"
}

reload() {
    test -f ~/.env.loader && . ~/.env.loader
}

update-shell() {
    if [[ '${platform,,}' == *'ming'* ]]; then
        pacman -Syu
        printf "\n${BOLD}${YELLOW}Close this shell, open a new one, and then run 'pacman -Su'${NORMAL}\n"
    fi
}

# Will return a symlink path in its expanded form. If the path's root is the
# home directory symbol "~" then it'll be replaced by the full home path.
expand_path() {
    local ret="$1"

    IFS="/" read -ra parts <<< "$ret"
    if [[ "${parts[0]}" == "~" ]]; then
        ret="$HOME"
        for ((i=1; i < ${#parts[@]}; i++))
        do
            ret="$ret/${parts[$i]}"
        done
    fi
    ret=$(readlink -m "$ret")
    echo $ret
}
is_absolute_unix_path() {
    if [[ $1 =~ ^/ ]]; then echo 1; else echo 0; fi
}

is_windows_path() {
    if [[ ! $1 =~ \/+ ]]; then echo 1; else echo 0; fi
}

# Returns a Unix path with spaces escaped with a '\'.
escape_unix_path() {
    ret="$1"
    ret="${ret/ /\\ }"
    echo "$ret"
}

# Returned value does not have a trailing '\'.
unix_to_windows_path() {
    ret="$1"
    if [[ $(is_windows_path "$ret") -eq 0 ]]; then
        if [[ $(is_absolute_unix_path "$ret") -eq 1 ]]; then
            ret="${ret/\//}"
            # Fix the drive name, e.g. c\foo becomes c:\foo
            ret=$(sed 's,\([a-zA-Z]*\),\1:,' <<< "$ret")
        fi
        ret="${ret////\\}"    # Replace Unix slashes.
        ret="${ret//\\\(/\(}" # Remove backslash before (.
        ret="${ret//\\\)/\)}" # Remove backslash before ).
    fi

    # Strip trailing slashes.
    shopt -s extglob
    ret=$(echo "${ret%%+(\\)}")

    echo $ret
}

remove_windows_file() {
    local path=$(expand_path "$1")
    if [[ -f "$path" || -d "$path" ]]; then
        local dest=$(unix_to_windows_path "$path")
        recycle-bin.exe $dest
    else
        echo "'$path' does not exist!"
    fi
}

open_explorer_here() {
    local path_expanded=$(expand_path "$1")
    if [[ -d $path_expanded ]]; then
        local path=$(unix_to_windows_path "$path_expanded")
        explorer.exe "$path"
    else
        echo "Folder no longer exists"
    fi
}

##################
# Building code
##################

# Dev build
b() {
  test -f build && ./build $@ ; test -f build.sh && ./build.sh $@ ; test -f build.jai && ./build.jai $@
}

# fast dev build
bf() {
  test -f build && ./build $@ -fast ; test -f build.sh && ./build.sh $@ -fast ; test -f build.jai && ./build.jai $@
}

# Optimized dev build
bb() {
  test -f build && ./build $@ -o 1 ; test -f build.sh && ./build.sh $@ -o 1 ; test -f build.jai && ./build.jai -release $@
}

# Production build
bp() {
  test -f build && ./build $@ -p p ; test -f build.sh && ./build.sh $@ -p p ; test -f build.jai && ./build.jai -release $@ - -prod
}

# Profiling build
bpf() {
  test -f build && ./build $@ -p pf ; test -f build.sh && ./build.sh $@ -p pf
}

# GPU profiling build
bgpf() {
  test -f build && ./build $@ -p gpu ; test -f build.sh && ./build.sh $@ -p gpu
}

# Run build
r() {
  test -f run && ./run $@ ; test -f run.sh && ./run.sh $@
}

# Build then run
br() {
  b $@ ; r
}

####################################################################################################

if [[ $platform == 'Darwin' ]]; then
  alias trash='rmtrash'
  alias tt='rmtrash'

elif [[ "${platform,,}" == *'ming'* ]]; then # convert to lowercase then compare with wildcard
  #alias rm='echo "use trash command instead!"'
  #alias rmr='echo "use trash command instead!"'
  alias trash='remove_windows_file'
  alias tt='remove_windows_file'
  alias cgrep='cgrep.exe'
fi

alias cd-='echo "Use c- instead"'
alias ..='cd ../'
alias ...='cd ../..'
alias cd..='cd ..'
alias cd...='cd ../..'
alias cd....='cd ../../..'
alias cd.....='cd ../../../..'

alias ls='ls -F --color'
alias l='ls -lh'
alias ll='ls -lha'

alias aliases='vim ~/.aliases'
alias al='aliases'

if [[ "${platform,,}" == *'ming'* ]]; then
    _checksum() {
        local algo="$1"
        local file="$2"
        certutil -hashfile $file $algo
    }
    alias checksum='certutil -hashfile'
    alias checksum-md5='_checksum MD5'
    alias checksum-sha1='_checksum SHA1'
    alias checksum-sha256='_checksum SHA256'
    alias checksum-sha512='_checksum SHA512'
fi

check_signature() {
    local algo="$1"
    local hashes_file="$2"
    local pem_file="$3"
    local sig_file="$4"

    if [[ $hashes_file == "" || $pem_file == "" || $sig_file == "" ]]; then
        error "Usage: <hashes file (e.g. sha512 hashes)> <pem file> <sig file>"
        return
    fi

    openssl dgst -$algo -verify $pem_file -signature $sig_file $hashes_file
}
alias check-signature256='check_signature sha256 '

alias cr='RUSTFLAGS="$RUSTFLAGS -A unused_variables -A dead_code -A unused_parens" cargo run'
alias crr='cargo run --release'
alias cb='RUSTFLAGS="$RUSTFLAGS -A unused_variables -A dead_code -A unused_parens" cargo build'
alias cbr='cargo build --release'
alias clrtmp='trash ~/tmp/*.bak && trash ~/tmp/*.swp'
alias clrtemp='clrtmp'
alias clipboard='xclip -selection c'
# Cloc alias may be overridden by a private alias
alias cloc='cloc --no3 --by-file-by-lang --skip-win-hidden'
alias cls=clear
alias cpr='cp -r'
alias dc='gdc'
alias duh='du -csh'
alias e='open_explorer_here "$PWD"'
alias exp='echo "Use e instead."'
alias f='fg'
alias hist='history'
alias histroy='history'
alias irb='irb --readline -r irb/completion'
alias lcc='lein clean'
alias lca='lein cljsbuild auto dev'
alias ldi='lein deps install'
alias lsd='lein start-dev'
alias moon='curl wttr.in/moon -A "curl"'
alias reguard='killall -9 ruby ; guard'
alias rb='rbenv'
alias rbg='rbenv gemset active'
alias rbp='cd $RBENV_PATH/versions/$(rbenv version | sed -e "s/ (set.*$//")'
alias rbl='cd $RBENV_PATH/versions/$(rbenv version | sed -e "s/ (set.*$//")/lib/ruby'
alias rc='rclone'
alias rcc='rclone copy'
alias restart='sudo shutdown now -r'
alias rl='reload'
alias rmr='rm -r'
alias rmrf='rm -rf'
alias s='cd ~/.ssh'
alias sc='vim ~/.ssh/config'
alias shutdown='sudo shutdown now'
alias t='tree'
alias tag='ctags -R .'
alias v='vim'
alias vi='vim'
alias vh='vagrant halt'
alias vs='vagrant ssh'
alias vu='vagrant up'
alias vimrc='vim ~/.vimrc'
alias weather='curl wttr.in/toronto -A "curl"'

####################################################################################################
# Grep
####################################################################################################

custom_grep() {
    local term="$1"
    shift 1
    local include_list=("$@")
    local include_arg=""
    if [[ $include_list != "" ]]; then
        # We're looping like this instead of for var in "$@", because that way of looping is affecting
        # my shell environment. Very strange!
        for i in "${include_list[@]}"; do
            include_arg+="--include=\*${i} "
        done
    fi
    eval grep -nri --color=auto $include_arg --exclude=tags --exclude=newtags --exclude-dir=.git \"$term\"
}

# Search c/cpp/txt files. Only supports a single search term arg or a quoted search term.
grep_dev() {
    custom_grep "$@" .h .c .cpp .inc .def .txt .md
}

# Search c/cpp files. Only supports a single search term arg or a quoted search term.
grep_c() {
    custom_grep "$@" .h .c .cpp .inc .def
}

# Search txt/md files. Only supports a single search term arg or a quoted search term.
grep_txt() {
    custom_grep "$@" .txt .md
}

alias grepp='grep -n --color=auto --exclude=tags --exclude=newtags --exclude-dir=.git '
alias grep-c='grep_c '
alias grep-txt='grep_txt'
alias grep-dev='grep_dev'

####################################################################################################
# Downloading Vids and Audio
####################################################################################################

COMPRESSION_ON=1
COMPRESSION_OFF=0

SHORTNAME_ON=1
SHORTNAME_OFF=0

TRANSCRIBE_ON=1
TRANSCRIBE_OFF=0

make_vid_dir_and_cd_into() {
    local url="$1"
    local dir_name="$2"
    shift 2
    local opts="$@"

    if [[ $dir_name == "" ]]; then
        # @note If the filename contains symbols that are incompatible with
        # Windows' directory names then add --restrict-filenames to the command.

        dir_name=$(yt-dlp.exe --get-filename -o "%(upload_date>%Y-%m-%d)s - %(title)s" $opts $url)

        if [[ $dir_name == "" ]]; then
            return 1
        fi
    fi

    printf "${BOLD}Creating directory ${YELLOW}'$dir_name'${NORMAL}\n"
    mkdir "$dir_name" 2>/dev/null
    cd "$dir_name"

    error=$?
    if [[ ! $error -eq 0 ]]; then
        error "Error: failed to create directory. Aborting."
        return 1
    fi

    return 0
}

function my_transcribe_video() {
    file="$1"
    output="$2"
    include_small=$3
    if [[ $file == "" ]]; then
        error "Usage: <input video> <optional output name>"
        return
    fi
    if [[ $output == "" ]]; then
        output="${1%.*}"  # just use the input name without the extension.
    fi
    # Tiny is fast and semi-accurate, so whatever.
    # Base is pretty good overall. It has good punctuation inserting and
    # catches most words. Small and medium can do better word detection at
    # times, but suffer from bad punctuation. Medium is particularly bad and
    # not adding commas and periods.
    if [[ $include_small -eq 1 ]]; then
        transcribe-video "$file" "$output" tiny base small
    else
        transcribe-video "$file" "$output" tiny base
    fi
}

function my_transcribe_video_all_models() {
    file="$1"
    output="$2"
    if [[ $file == "" ]]; then
        error "Usage: <input video> <optional output name>"
        return
    fi
    if [[ $output == "" ]]; then
        output="${1%.*}"   # just use the input name without the extension.
    fi
    transcribe-video "$file" "$output" tiny base small medium
}


# Download YouTube videos. Note that yt-dlp downloads a lot faster than streamlink.
download_youtube_vid() {
    local format="$1"
    local shortname="$2"
    local transcribe="$3"

    local make_folder="$4"
    local url="$5"
    shift 5
    local opts="$@"

    if [[ $url == "" ]]; then
        error "Usage: <make folder?> <url> <optional args>"
        return
    fi

    if [[ $shortname == "1" || $transcribe == "1" ]]; then
        printf "${BOLD}Downloading Youtube vid "
        if [[ $shortname == "1" ]];  then printf "| ${YELLOW}using short name${NORMAL}${BOLD} "; fi
        if [[ $transcribe == "1" ]]; then printf "| ${YELLOW}audio transcription on${NORMAL}${BOLD} "; fi
        printf "\n\n${NORMAL}"
    else
        printf "${BOLD}Downloading Youtube vid\n\n${NORMAL}"
    fi

    if [[ $format == "" ]]; then
        printf "${BOLD}No format given; using best available.${NORMAL}\n"
        # Download best mp4 video.
        format="bv*[ext=mp4]+ba[ext=m4a]"
    fi

    # We're assuming we'll always have an mp4 video only and audio track to merge.
    opts+=" --merge-output-format mp4 --write-subs --sub-lang en --embed-subs"

    if [[ $make_folder == "1" ]]; then
        make_vid_dir_and_cd_into $url ""
        if [[ $? -ne 0 ]]; then
            return
        fi
    fi

    if [[ $shortname == "0" ]]; then
        local name_format="%(upload_date>%Y-%m-%d)s-%(title)s-yt-%(id)s"
    else
        local name_format="%(upload_date>%Y-%m-%d)s-shortname-yt-%(id)s"
    fi

    # Get the video filename.
    local filename=$(yt-dlp.exe --get-filename -f $format -o "$name_format.%(ext)s" $opts $url)
    printf "filename: $filename\n"

    # Download
    local cmd="yt-dlp.exe -f $format -o \"$filename\" $opts $url"
    eval $cmd   # Need to eval in order to preserve the quotes wrapping the filename format string.
    error=$?

    if [[ $error -ne 0 ]]; then
        error "Error: Failed to download '$url'"
        if [[ $make_folder == "1" ]]; then cd ..; fi
        return
    fi

    # Removing any trailing subtitle files
    rm *.vtt *.srt 2>/dev/null

    if [[ $transcribe == "1" ]]; then
        my_transcribe_video "$filename"
    fi

    if [[ $make_folder == "1" ]]; then cd ..; fi

    printf "${BOLD}Finished downloading ${YELLOW}$filename${NORMAL}\n"
}

download_youtube_playlist() {
    local format="$1"
    local url="$2"
    local dir_name="$3"
    shift 3
    local opts="$@"

    if [[ $url == "" ]]; then
        error "Usage: <url> <directory name (optional)> <optional args>"
        return
    fi

    printf "${BOLD}Downloading Youtube playlist\n\n${NORMAL}"

    if [[ $format == "" ]]; then
        printf "${BOLD}No format given; using best available.${NORMAL}\n"
        # Download best mp4 video and best m4a audio, then merge.
        format="bv*[ext=mp4]+ba[ext=m4a]"
        opts+=" --merge-output-format mp4"
    fi

    opts+=" --write-sub --sub-lang en --embed-subs"

    if [[ $dir_name != "" ]]; then
        make_vid_dir_and_cd_into $url "$dir_name"
        if [[ $? -ne 0 ]]; then
            return
        fi
    fi

    local cmd="yt-dlp.exe -f $format -o \"v%(playlist_index)03d--%(upload_date>%Y-%m-%d)s-%(title)s-yt-%(id)s.%(ext)s\" $opts $url"
    eval $cmd   # Need to eval in order to preserve the quotes wrapping the filename format string.

    # Removing any trailing subtitle files
    rm *.vtt *.srt 2>/dev/null

    if [[ $dir_name == "1" ]]; then cd ..; fi

    printf "${BOLD}Finished downloading the playlist\n${NORMAL}"
}

download_youtube_playlist_list() {
    local url="$1"
    local output_name="$2"
    shift 2
    local opts="$@"

    if [[ $url == "" || $output_name == "" ]]; then
        error "Usage: <url> <output name> <optional args>"
        return
    fi

    printf "${BOLD}Downloading Youtube playlist video list\n\n${NORMAL}"

    local cmd="yt-dlp.exe --ignore-errors -O \"%(playlist_index)s-%(title)s--%(id)s\" --skip-download $opts $url"
    eval $cmd  1>"${output_name}.txt"  # Need to eval in order to preserve the quotes wrapping the filename format string.

    printf "${BOLD}Finished downloading the playlist video list\n${NORMAL}"
}

download_youtube_uploads_list() {
    local include_descriptions="$1"

    local url="$2"
    local output_name="$3"
    shift 3
    local opts="$@"

    if [[ $url == "" || $output_name == "" ]]; then
        error "Usage: <url> <output name> <optional args>"
        return
    fi

    local cmd=""

    if [[ $include_descriptions == "1" ]]; then
        printf "${BOLD}Downloading Youtube uploads list with descriptions\n\n${NORMAL}"
        cmd="yt-dlp.exe --ignore-errors -O \"@@@ %(video_autonumber)s-%(upload_date>%Y-%m-%d)s--%(title)s--%(id)s\" --skip-download --get-description $opts $url"
    else
        printf "${BOLD}Downloading Youtube uploads list\n\n${NORMAL}"
        cmd="yt-dlp.exe --ignore-errors -O \"%(video_autonumber)s-%(upload_date>%Y-%m-%d)s--%(title)s--%(id)s\" --skip-download $opts $url"
    fi

    eval $cmd  1>"${output_name}.txt"  # Need to eval in order to preserve the quotes wrapping the filename format string.

    printf "${BOLD}Finished downloading the upload list\n${NORMAL}"
}

function download_youtube_audio() {
    if [[ $1 == "" ]]; then
        error "Usage: <url>"
        return
    fi
    yt-dlp.exe -f "140" "$1"
}

# Download Twitch chat transcript
actually_download_twitch_chat() {
    local url="$1"
    local filename="$2"

    rechat.exe -d $url "$filename.json"
    if [[ -f "$filename.json" ]]; then
        rechat.exe -p "$filename.json" "$filename.txt" -b -o
        rm "$filename.json"
    else
        error "Video doesn't have a chat transcript."
    fi

    printf "${BOLD}Finished downloading ${YELLOW}$filename${NORMAL}\n"
}

download_twitch_chat() {
    local make_folder="$1"
    local url="$2"
    shift 2
    local opts="$@"

    if [[ $url == "" ]]; then
        error "Usage: <url>"
        return
    fi

    if [[ $make_folder == "1" ]]; then
        make_vid_dir_and_cd_into $url "" $opts
        if [[ $? -ne 0 ]]; then
            return
        fi
    fi

    actually_download_twitch_chat $url "$(yt-dlp.exe --get-filename -o "%(upload_date>%Y-%m-%d)s-%(title)s-tw-%(id)s.chat" $opts $url)"

    if [[ $make_folder == "1" ]]; then cd ..; fi
}

# Download Twitch videos, both VODs and live streams. Pass a Twitch account URL to download a live stream.
# The live stream filename will not contain the stream title, so you'll need to modify it afterwards.
#
# If you want to download subcriber-only vids then first extract your Twitch
# cookies to a file (can use cookies.txt add-on from Lennon Hill) and then pass it as an option,
# using the full path to the cookies file, e.g.
#   `tw-1080p60 <url> --cookies /c/<cookie_path>/twitch_cookies.txt`
#
# To extract a portion of a video, you have to first download the entire file and then use the
# `trim-video` or `compress-video-and-trim` scripts.
#
download_twitch_vid() {
    local format="$1"
    local shortname="$2"
    local compress="$3"
    local transcribe="$4"
    local make_folder="$5"
    local url="$6"
    shift 6
    local opts="$@"

    if [[ $url == "" ]]; then
        error "Usage: <make folder?> <url> <optional args>"
        return
    fi

    # We use yt-dlp to get the filename and then use streamlink to download it (the latter is a lot faster).
    # It's a two step process because streamlink cannot pass the formatted filename to ffmpeg.
    # We fallback to yt-dlp when it's a subscriber VOD because we don't have an easy way to access it with streamlink.

    local subscriber_vod=0
    local split_opts=($opts)
    if [[ ${split_opts[0]} == "--cookies" ]]; then
        subscriber_vod=1
        printf "${BOLD}Subscriber VOD. Will use yt-dlp to download.${NORMAL}\n"
    fi

    if [[ $shortname == "1" || $compress == "1" || $transcribe == "1" ]]; then
        printf "${BOLD}Downloading Twitch vid "
        if [[ $shortname == "1" ]];  then printf "| ${YELLOW}using short name${NORMAL}${BOLD} "; fi
        if [[ $compress == "1" ]];   then printf "| ${YELLOW}compression on${NORMAL}${BOLD} "; fi
        if [[ $transcribe == "1" ]]; then printf "| ${YELLOW}audio transcription on${NORMAL}${BOLD} "; fi
        printf "\n\n${NORMAL}"
    else
        printf "${BOLD}Downloading Twitch vid\n\n${NORMAL}"
    fi

    local yt_dlp_format=""
    local streamlink_format=""

    if [[ $format == "" ]]; then
        # Twitch only supplies pre-merged mp4s so we can ask for the best format and not worry about anything else.
        printf "${BOLD}No format given; using best available.${NORMAL}\n"
        yt_dlp_format="b"
        streamlink_format="best"
    else
        yt_dlp_format="$format"
        streamlink_format="$format"
    fi

    if [[ $make_folder == "1" ]]; then
        make_vid_dir_and_cd_into $url "" $opts
        if [[ $? -ne 0 ]]; then
            return
        fi
    fi

    if [[ $shortname == "0" ]]; then
        local name_format="%(upload_date>%Y-%m-%d)s-%(title)s-tw-%(id)s"
    else
        local name_format="%(upload_date>%Y-%m-%d)s-shortname-tw-%(id)s"
    fi

    # Download Twitch chat transcript
    actually_download_twitch_chat $url "$(yt-dlp.exe --get-filename -o "$name_format" $opts $url)"

    # Get the video filename.
    local filename=$(yt-dlp.exe --get-filename -f $yt_dlp_format -o "$name_format.%(ext)s" $opts $url)

    # Download
    if [[ $subscriber_vod == "0" ]]; then
        local cmd="streamlink.exe --twitch-low-latency --twitch-disable-ads --twitch-disable-hosting --force --force-progress $opts $url $streamlink_format -O | ffmpeg -i pipe:0 -c copy \"$filename\""
    else
        local cmd="yt-dlp.exe -f $yt_dlp_format -o \"$filename\" $opts $url"
    fi

    printf "${YELLOW}${BOLD}Downloading video\n${NORMAL}"

    eval $cmd  # Need to eval in order to preserve the quotes wrapping the filename format string.
    error=$?

    if [[ $error -ne 0 ]]; then
        error "Error: Failed to download '$url'"
        if [[ $make_folder == "1" ]]; then cd ..; fi
        return
    fi

    if [[ $compress == "1" ]]; then
        local temp_name="temp_${RANDOM}"
        # 0=cpu, 1=gpu
        compress-video "$filename" "$temp_name" 0
        extension="${filename##*.}"
        mv "$filename" "orig_$filename"
        mv $temp_name.$extension "$filename"
        printf "${BOLD}Make sure to delete the original video file\n${NORMAL}"
    fi

    if [[ $transcribe == "1" ]]; then
        my_transcribe_video "$filename"
    fi

    if [[ $make_folder == "1" ]]; then cd ..; fi

    printf "${BOLD}Finished downloading ${YELLOW}$filename${NORMAL}\n"
}

# Download Vimeo videos.
# Can download an embedded vid. You might need to save the site cookies if the vid is behind a paywall.
# e.g.  --cookies cookies.txt --referer https://gillyandkeeves.tv https://player.vimeo.com/video/756941969
# The vid ID can be found by looking at the embed's iframe src attribute.
download_vimeo_vid() {
    local shortname="$1"
    local compress="$2"
    local transcribe="$3"
    local format="$4"
    local make_folder="$5"
    local url="$6"
    shift 5
    local opts="$@"

    if [[ $format == "" || $url == "" ]]; then
        error "Usage: <format> <make folder?> <url> <optional args>"
        return
    fi

    if [[ $shortname == "1" || $compress == "1" || $transcribe == "1" ]]; then
        printf "${BOLD}Downloading Vimeo vid "
        if [[ $shortname == "1" ]];  then printf "| ${YELLOW}using short name${NORMAL}${BOLD} "; fi
        if [[ $compress == "1" ]];   then printf "| ${YELLOW}compression on${NORMAL}${BOLD} "; fi
        if [[ $transcribe == "1" ]]; then printf "| ${YELLOW}audio transcription on${NORMAL}${BOLD} "; fi
        printf "\n\n${NORMAL}"
    else
        printf "${BOLD}Downloading Vimeo vid\n\n${NORMAL}"
    fi

    if [[ $make_folder == "1" ]]; then
        make_vid_dir_and_cd_into $url "" $opts
        if [[ $? -ne 0 ]]; then
            return
        fi
    fi

    if [[ $shortname == "0" ]]; then
        local name_format="%(upload_date>%Y-%m-%d)s-%(title)s-vimeo-%(id)s"
    else
        local name_format="%(upload_date>%Y-%m-%d)s-shortname-vimeo-%(id)s"
    fi

    # Download the video.
    local filename=$(yt-dlp.exe --get-filename -f $format -o "$name_format.%(ext)s" $opts $url)

    local cmd="yt-dlp.exe -f $format -o \"$filename\" $opts $url"
    eval $cmd   # Need to eval in order to preserve the quotes wrapping the filename format string.

    error=$?
    if [[ $error -eq 0 ]]; then
        if [[ $compress == "1" ]]; then
            local temp_name="temp_${RANDOM}"
            # 0=cpu, 1=gpu
            compress-video "$filename" "$temp_name" 0
            extension="${filename##*.}"
            mv "$filename" "orig_$filename"
            mv $temp_name.$extension "$filename"
            printf "${BOLD}Make sure to delete the original video file${NORMAL}\n"
        fi
    else
        error "Error: Failed to download '$url'"
        if [[ $make_folder == "1" ]]; then cd ..; fi
        return
    fi

    if [[ $transcribe == "1" ]]; then
        my_transcribe_video "$filename"
    fi

    if [[ $make_folder == "1" ]]; then cd ..; fi

    printf "${BOLD}Finished downloading ${YELLOW}$filename${NORMAL}\n"
}

# Download Twitter videos.
download_twitter_vid() {
    local format="$1"
    local make_folder="$2"
    local url="$3"
    local vid_name="$4"

    if [[ $url == "" ]]; then
        error "Usage: <make folder?> <url> <optional filename> <optional args>"
        return
    fi

    printf "${BOLD}Downloading Twitter vid.${NORMAL}\n"

    if [[ $vid_name == "" ]]; then
        local name_format="%(upload_date>%Y-%m-%d)s-%(title)s-twitter-%(id)s"
        local opts=""
    else
        local name_format="%(upload_date>%Y-%m-%d)s-${vid_name}-twitter-%(id)s"
        shift 4
        local opts="$@"
    fi

    if [[ $make_folder == "1" ]]; then
        make_vid_dir_and_cd_into $url $vid_name $opts
        if [[ $? -ne 0 ]]; then
            return
        fi
    fi

    if [[ $format == "" ]]; then
        printf "${BOLD}No format given; using best available.${NORMAL}\n"
        format="b"
    fi

    # Download the video.
    local filename=$(yt-dlp.exe --get-filename -f $format -o "$name_format.%(ext)s" $opts $url)

    local cmd="yt-dlp.exe -f $format -o \"$filename\" $opts $url"
    eval $cmd   # Need to eval in order to preserve the quotes wrapping the filename format string.

    error=$?
    if [[ $error -eq 1 ]]; then
        error "Error: Failed to download '$url'"
    fi

    if [[ $make_folder == "1" ]]; then cd ..; fi

    printf "${BOLD}Finished downloading ${YELLOW}$filename${NORMAL}\n"
}

# Download Instagram videos.
download_instagram_vid() {
    local transcribe="$1"

    local make_folder="$2"
    local url="$3"
    local vid_name="$4"

    if [[ $url == "" ]]; then
        error "Usage: <make folder?> <url> <optional filename> <optional args>"
        return
    fi

    printf "${BOLD}Downloading Instagram vid.${NORMAL}\n"

    if [[ $vid_name == "" ]]; then
        local name_format="%(upload_date>%Y-%m-%d)s-%(title)s-ig-%(id)s"
        local opts=""
    else
        local name_format="%(upload_date>%Y-%m-%d)s-${vid_name}-ig-%(id)s"
        shift 4
        local opts="$@"
    fi

    if [[ $make_folder == "1" ]]; then
        make_vid_dir_and_cd_into $url $vid_name $opts
        if [[ $? -ne 0 ]]; then
            return
        fi
    fi

    format="b" # best available

    # Download the video.
    local filename=$(yt-dlp.exe --get-filename -f $format -o "$name_format.%(ext)s" $opts $url)

    local cmd="yt-dlp.exe -f $format -o \"$filename\" $opts $url"
    eval $cmd   # Need to eval in order to preserve the quotes wrapping the filename format string.

    error=$?
    if [[ $error -eq 1 ]]; then
        error "Error: Failed to download '$url'"
        if [[ $make_folder == "1" ]]; then cd ..; fi
        return
    fi

    if [[ $transcribe == "1" ]]; then
        transcribe "$filename"
    fi

    if [[ $make_folder == "1" ]]; then cd ..; fi

    printf "${BOLD}Finished downloading ${YELLOW}$filename${NORMAL}\n"
}

# Download MP4 video.
download_mp4() {
    local url="$1"
    local filename="$2"

    if [[ $url == "" || $filename == "" ]]; then
        error "Usage: <url> <filename>"
        return
    fi

    temp_name="temp_${RANDOM}.mp4"

    printf "${BOLD}Downloading: ${YELLOW}$filename${NORMAL}\n"
    curl "$url" -o $temp_name

    if [[ $? -ne 0 ]]; then
        error "Error: failed to download."
        return
    fi

    mv $temp_name "$filename.mp4"
}

# Download from m3u8 stream to mp4.
download_from_m3u8() {
    local m3u8_path="$1"
    local filename="$2"

    if [[ $m3u8_path == "" || $filename == "" ]]; then
        error "Usage: <m3u8 path> <filename>"
        return
    fi

    printf "${BOLD}Downloading: ${YELLOW}$filename${NORMAL}\n"
    ffmpeg.exe -protocol_whitelist file,https,crypto,tls,tcp -i $m3u8_path -acodec copy -vcodec copy "${filename}.mp4"

    if [[ $? -ne 0 ]]; then
        error "Error: failed to download."
        return
    fi

    printf "${BOLD}Finished downloading ${YELLOW}$filename${NORMAL}\n"
}


#-------------------------------------------------
# YouTube Vid DL
#-------------------------------------------------
alias yt-list='download_youtube_uploads_list 0 '
alias yt-list-desc='download_youtube_uploads_list 1 '

alias yt='download_youtube_vid                  ""        $SHORTNAME_OFF $TRANSCRIBE_OFF'
alias yt-shortname='download_youtube_vid        ""        $SHORTNAME_ON  $TRANSCRIBE_OFF'
alias yt-1080='download_youtube_vid             "137+140" $SHORTNAME_OFF $TRANSCRIBE_OFF'
alias yt-1080-shortname='download_youtube_vid   "137+140" $SHORTNAME_ON  $TRANSCRIBE_OFF'
alias yt-720='download_youtube_vid              "136+140" $SHORTNAME_OFF $TRANSCRIBE_OFF'
alias yt-720-shortname='download_youtube_vid    "136+140" $SHORTNAME_ON  $TRANSCRIBE_OFF'
#TRANSCRIPTION ON
alias ytt='download_youtube_vid                 ""        $SHORTNAME_OFF $TRANSCRIBE_ON'
alias yt-shortname-t='download_youtube_vid      ""        $SHORTNAME_ON  $TRANSCRIBE_ON'
alias yt-1080-t='download_youtube_vid           "137+140" $SHORTNAME_OFF $TRANSCRIBE_ON'
alias yt-1080-shortname-t='download_youtube_vid "137+140" $SHORTNAME_ON  $TRANSCRIBE_ON'
alias yt-720-t='download_youtube_vid            "136+140" $SHORTNAME_OFF $TRANSCRIBE_ON'
alias yt-720-shortname-t='download_youtube_vid  "136+140" $SHORTNAME_ON  $TRANSCRIBE_ON'
#---------------------------
alias yt-playlist='download_youtube_playlist      ""'
alias yt-playlist-list='download_youtube_playlist_list '
alias yt-playlist-1080='download_youtube_playlist "137+140"'
alias yt-playlist-720='download_youtube_playlist  "136+140"'
alias yt-playlist-tiny='download_youtube_playlist "160+140"'
alias yt-audio='download_youtube_audio'

#-------------------------------------------------
# Twitch Vid DL
#-------------------------------------------------
alias tw-chat='download_twitch_chat'

alias tw='download_twitch_vid                                ""        $SHORTNAME_OFF $COMPRESSION_OFF $TRANSCRIBE_OFF'
alias tw-compressed='download_twitch_vid                     ""        $SHORTNAME_OFF $COMPRESSION_ON  $TRANSCRIBE_OFF'
alias tw-shortname='download_twitch_vid                      ""        $SHORTNAME_ON  $COMPRESSION_OFF $TRANSCRIBE_OFF'
alias tw-shortname-compressed='download_twitch_vid           ""        $SHORTNAME_ON  $COMPRESSION_ON  $TRANSCRIBE_OFF'
alias tw-source='download_twitch_vid                         "Source"  $SHORTNAME_OFF $COMPRESSION_ON  $TRANSCRIBE_OFF'
alias tw-custom='download_twitch_vid '
#TRANSCRIPTION ON
alias twt='download_twitch_vid                               ""        $SHORTNAME_OFF $COMPRESSION_OFF $TRANSCRIBE_ON'
alias tw-compressed-t='download_twitch_vid                   ""        $SHORTNAME_OFF $COMPRESSION_ON  $TRANSCRIBE_ON'
alias tw-shortname-t='download_twitch_vid                    ""        $SHORTNAME_ON  $COMPRESSION_OFF $TRANSCRIBE_ON'
alias tw-shortname-compressed-t='download_twitch_vid         ""        $SHORTNAME_ON  $COMPRESSION_ON  $TRANSCRIBE_ON'
alias tw-source-t='download_twitch_vid "Source"              "Source"  $SHORTNAME_OFF $COMPRESSION_ON  $TRANSCRIBE_ON'

#1080p
alias tw-1080='download_twitch_vid                           "1080"    $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080-compressed='download_twitch_vid                "1080"    $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080-shortname='download_twitch_vid                 "1080"    $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080-shortname-compressed='download_twitch_vid      "1080"    $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
#TRANSCRIPTION ON
alias tw-1080-t='download_twitch_vid                         "1080"    $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080-compressed-t='download_twitch_vid              "1080"    $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080-shortname-t='download_twitch_vid               "1080"    $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080-shortname-compressed-t='download_twitch_vid    "1080"    $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'

#1080p60/50
alias tw-1080p60='download_twitch_vid                        "1080p60" $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080p50='download_twitch_vid                        "1080p50" $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080p60-compressed='download_twitch_vid             "1080p60" $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080p50-compressed='download_twitch_vid             "1080p50" $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080p60-shortname='download_twitch_vid              "1080p60" $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080p50-shortname='download_twitch_vid              "1080p50" $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080p60-shortname-compressed='download_twitch_vid   "1080p60" $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-1080p50-shortname-compressed='download_twitch_vid   "1080p50" $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
#TRANSCRIPTION ON
alias tw-1080p60-t='download_twitch_vid                      "1080p60" $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080p50-t='download_twitch_vid                      "1080p50" $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080p60-compressed-t='download_twitch_vid           "1080p60" $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080p50-compressed-t='download_twitch_vid           "1080p50" $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080p60-shortname-t='download_twitch_vid            "1080p60" $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080p50-shortname-t='download_twitch_vid            "1080p50" $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080p60-shortname-compressed-t='download_twitch_vid "1080p60" $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-1080p50-shortname-compressed-t='download_twitch_vid "1080p50" $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'

#720p
alias tw-720='download_twitch_vid                            "720p"    $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-720-compressed='download_twitch_vid                 "720p"    $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-720-shortname='download_twitch_vid                  "720p"    $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-720p60='download_twitch_vid                         "720p60"  $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-720p60-shortname='download_twitch_vid               "720p60"  $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
#TRANSCRIPTION ON
alias tw-720-t='download_twitch_vid                          "720p"    $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-720-compressed-t='download_twitch_vid               "720p"    $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-720-shortname-t='download_twitch_vid                "720p"    $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-720p60-t='download_twitch_vid                       "720p60"  $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-720p60-shortname-t='download_twitch_vid             "720p60"  $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'

#4k
alias tw-4k='download_twitch_vid                             "2160p"   $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-4k-compressed='download_twitch_vid                  "2160p"   $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-4k-shortname='download_twitch_vid                   "2160p"   $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
alias tw-4k-shortname-compressed='download_twitch_vid        "2160p"   $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_OFF'
#TRANSCRIPTION ON
alias tw-4k-t='download_twitch_vid                           "2160p"   $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-4k-compressed-t='download_twitch_vid                "2160p"   $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-4k-shortname-t='download_twitch_vid                 "2160p"   $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'
alias tw-4k-shortname-compressed-t='download_twitch_vi       "2160p"   $SHORTNAME_ON  $COMPRESSION_ON $TRANSCRIBE_ON'


#-------------------------------------------------
# Vimeo Vid DL
#-------------------------------------------------
alias vimeo='download_vimeo_vid              $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias vimeo-t='download_vimeo_vid            $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'
alias vimeo-compressed='download_vimeo_vid   $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_OFF'
alias vimeo-compressed-t='download_vimeo_vid $SHORTNAME_OFF $COMPRESSION_ON $TRANSCRIBE_ON'

#-------------------------------------------------
# Instagram Vid DL
#-------------------------------------------------
alias ig='download_instagram_vid  $TRANSCRIBE_OFF'
alias igt='download_instagram_vid $TRANSCRIBE_ON'

#-------------------------------------------------
# Twitter Vid DL
#-------------------------------------------------
alias twitter='download_twitter_vid "" '

#-------------------------------------------------
# Misc
#-------------------------------------------------
alias download-mp4='download_mp4'
alias download-from-m3u8='download_from_m3u8'

####################################################################################################
# Video Compression
####################################################################################################

function _compress_video_hard() {
    local crf=35
    local name="$1"
    local out="$2"
    if [[ name == "" || out == "" ]]; then
        error "Usage: cmd <source> <dest>"
        return
    fi
    # 0=cpu, 1=gpu
    compress-video-with-crf $crf "$name" "$out" 0
}

alias compress-video-hard='_compress_video_hard'

####################################################################################################
# Git
####################################################################################################

if [[ '${platform,,}' == *'ming'* ]]; then
    # Fix a weird mingw 'not a valid identifierline' error.
    # Got the fix from https://github.com/Alexpux/MSYS2-packages/issues/735#issuecomment-328938800
    alias git="PATH=/usr/bin git"
fi

git_cmd_wrapper() {
    # If no args are provided then run `git status -s`
    if [[ $# > 0 ]]; then
        git $@
    else
        git status -s
    fi
}

git_commit() {
    cmd="git commit -m \"$*\""
    eval "$cmd"
}

# Performs a commit with the nocheckin prehook disabled.
git_commit_nocheckin() {
    cmd="git commit -m \"$*\""
    eval "DISABLE_NOCHECKIN=1 $cmd"
}

git_commit_signed() {
    cmd="git commit -S -m \"$*\""
    eval "$cmd"
}

git_fix_nocheckin() {
    eval "DISABLE_NOCHECKIN=1 git commit --amend -C HEAD"
}

git_branch_name() {
    val=`git branch 2>/dev/null | grep '^*' | colrm 1 2`
    echo "$val"
}

git_nuke() {
    git checkout master && git branch -D $1 && git push origin :$1
}

git_create_stash_patch() {
    stashNum="$1"
    file="stash_$stashNum.patch"
    git stash show "stash@{$stashNum}" -p > $file
    printf "${BOLD}${YELLOW}Created $file for stash@{$stashNum}.${NORMAL}\n"
}

alias am='git commit --amend'
alias ama='git commit --amend -C head --author'
alias ams='git commit -S --amend' # signed
alias ammend='echo "use am instead"'
alias amend='echo "use am instead"'
alias g='git_cmd_wrapper'
alias ga='git add -A'
alias gaa='git add -A; gdcc'
alias gap='git add -Ap'
alias gau='git add --update'
alias gaup='git add --update -p'
alias gb='git branch -v'
alias gbb='git bisect bad'
alias gbd='git branch -D'
alias gbdr='git branch -Dr' # Delete a remote tracking branch; useful when the remote no longer exists and branch pruning isn't removing the lingering tracking branches.
alias gbg='git bisect good'
alias gbl='git branch --all'
alias gblm='git blame -wMC'
alias gbm='git branch -m'
alias gbr='git branch -rv'
alias gc='git commit'
alias gcl='git clone'
alias gcm='git_commit'
alias gcms='git_commit_signed' # signed
alias gcmno='git_commit_nocheckin'
alias gco='git checkout'
alias gco-='git checkout -'
alias gcob='git checkout -b'
alias gcon='vi .git/config'
alias gcp='git cherry-pick'
alias gcpa='git cherry-pick --abort'
alias gcpc='git cherry-pick --continue'
alias gcps='git cherry-pick -n'
alias gd='git diff'
alias gdc='git diff --cached'
alias gdcc='git diff --cached --color-words'
alias gdm='git diff master'
alias gds='git diff --stat=160,120'
alias gf='git fetch'
alias gfa='git fetch --all'
alias gfd='git fetch --prune' # Removes remote branches that don't have a counterpart branch on the remote.
alias gfix='git commit --amend -C HEAD'
alias gfixs='git commit -S -a --amend -C HEAD' # signed
alias gfixno='git_fix_nocheckin'
alias gfo='git fetch origin'
alias gfu='git fetch up'
alias gfm='git fetch origin master'
alias gfup='git fetch upstream'
alias ggrep='git log --all --oneline | grep '
alias gla='git lg --all'
alias gl='git lg -30'
alias gll='git lg'
alias gli='git show --pretty="format:" --name-only'
alias glog='git log'
alias glom='gl origin/master'
alias gm='git merge'
alias gmnff='git merge --no-ff'
alias gmff='git merge --ff-only'
alias gmffm='git merge --ff-only master'
alias gmffs='git merge --ff-only --squash'
alias gmtheirs='git merge -Xtheirs'
alias gp='git push'
alias gpa='git push --all && echo "pushing tags..." && git push --tags'
alias gpaf='git push --all -f && echo "pushing tags..." && git push --tags -f'
alias gpf='git push -f'
alias gpff='git pull --ff-only'
alias gplu='git pull --set-upstream origin HEAD'
alias gplup='git pull upstream master'
alias gpo='git push origin'
alias gpom='git push origin master'
alias gpr='git pull --rebase'
alias gpt='git push --tags'
alias gpu='git push --set-upstream origin HEAD'
alias gr='git reset'
alias gr1='git reset HEAD^1'
alias grb='git rebase --autostash'
alias grba='git rebase --abort'
alias grbc='git rebase --continue'
alias grbs='git rebase --skip'
alias grbi='git rebase -i --autostash'
alias grbm='git rebase master --autostash'
alias grbmi='git rebase master -i --autostash'
alias grbom='git fetch origin master && git rebase origin/master --autostash'
alias grbomi='git fetch origin master && git rebase origin/master -i --autostash'
alias grbum='git fetch upstream master && git rebase upstream/master --autostash'
alias grbumi='git fetch upstream master && git rebase upstream/master -i --autostash'
alias gre='git remote'
alias grea='git remote add'
alias gremo='git remote remove origin; git remote add origin'
alias greao='git remote add origin'
alias gred='git remote remove'
alias gref='git reflog --format="%C(auto)%h %<|(17)%gd %C(cyan)%ci%C(reset) [%gs] %C(yellow)(%s)%C(reset)"'
alias grev='git remote -v'
alias grm='git rm'
alias grmr='git rm -r'
alias grp='git reset -p'
alias gsnapshot='git stash save "snapshot: $(date)" && git stash apply "stash@{0}"'
alias gsh='git show'
alias gshh='git show -w'
alias gs='git stash'
alias gsc='git_create_stash_patch'
alias gsk='git stash -k -u'
alias gssk='git stash save -k -u'
alias gss='git stash save'
alias gsd='git stash drop'
alias gsl='git stash list'
alias gsi='git stash -p'
alias gsp='git stash pop'
alias gsp0='git stash pop stash@{0}'
alias gsp1='git stash pop stash@{1}'
alias gsp2='git stash pop stash@{2}'
alias gsp3='git stash pop stash@{3}'
alias gsp4='git stash pop stash@{4}'
alias gsp5='git stash pop stash@{6}'
alias gsp6='git stash pop stash@{7}'
alias gt='git tag' # Unsigned
alias gta='git tag -a'
alias gtd='git tag -d'
alias gtl='git tag -l'
alias gts='git tag -s' # Signed
alias gx='git reset --hard'
alias gxx='git reset --hard HEAD~1'
alias gxom='git reset --hard origin/master'
alias gstats='echo "Total commits: $(git rev-list HEAD --count)"; echo "\nAuthor breakdown:"; git shortlog | grep -E "^[^ ]"'
alias gwip="git add . && git commit -m \"WIP\""

####################################################################################################
# Elixir
####################################################################################################
alias iex='rlwrap -i -f ~/.iex_history -H ~/.iex_history -s 30000 iex'
alias iexw='rlwrap -i -f ~/.iex_history -H ~/.iex_history -s 30000 iex --werl'
alias ep='iex -S mix phx.server'
alias ei='iex -S mix'
alias er='mix phx.server'
alias et='mix test'

####################################################################################################
# Haxe
####################################################################################################
alias flow='haxelib run flow'
alias snowfall='haxelib run snowfall'

####################################################################################################
# CMake
####################################################################################################
alias cmake-gen='cmake -D CMAKE_CXX_COMPILER="/Library/Developer/CommandLineTools/usr/bin/c++" CMAKE_C_COMPILER="/Library/Developer/CommandLineTools/usr/bin/cc" ..'