├── LICENSE ├── README.md └── brew-up.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 kanako 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # brew-up 2 | 3 | A script for homebrew to interactive upgrade outdated casks and outdated 4 | 5 | ## Install 6 | ```sh 7 | brew tap mkanako/tap 8 | brew install mkanako/tap/brew-up 9 | ``` 10 | 11 | ## Usage 12 | Execute `brew-up`, it will run `brew update` first, then list the outdated casks and outdated with an interactive UI. 13 | 14 | With argument `-s` can skip run `brew update`. 15 | 16 | ## ScreenShot 17 | ![ScreenShot](https://user-images.githubusercontent.com/4190346/101786544-0354dd00-3b39-11eb-934e-3e96804ef8d0.png) -------------------------------------------------------------------------------- /brew-up.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function prompt_checkbox() { 4 | # little helpers for terminal print control and key input 5 | ESC=$(printf "\033") 6 | cursor_blink_on() { printf "$ESC[?25h"; } 7 | cursor_blink_off() { printf "$ESC[?25l"; } 8 | cursor_to() { printf "$ESC[$1;${2:-1}H"; } 9 | print_inactive() { printf "$2 $1"; } 10 | print_active() { printf "$2 $ESC[7m$1$ESC[27m"; } 11 | get_cursor_row() { 12 | IFS=';' read -sdR -p $'\E[6n' ROW COL 13 | echo ${ROW#*[} 14 | } 15 | print_separator() { 16 | local title=$1 17 | local len=$2 18 | local line=$(printf "%$((($len - ${#title}) / 2))s" | tr ' ' '-') 19 | printf "$ESC[38;5;245m$line $title $line$ESC[m" 20 | } 21 | is_separator() { 22 | if [[ ${1:0:1} == '|' && ${1: -1} == '|' ]]; then 23 | return 0 24 | else 25 | return 1 26 | fi 27 | } 28 | key_input() { 29 | local key 30 | IFS= read -rsn1 key 2>/dev/null >&2 31 | if [[ $key = "" ]]; then echo enter; fi 32 | if [[ $key = $'\x20' ]]; then echo space; fi 33 | if [[ $key = $'\x1b' ]]; then 34 | read -rsn2 key 35 | if [[ $key = [A ]]; then echo up; fi 36 | if [[ $key = [B ]]; then echo down; fi 37 | fi 38 | } 39 | toggle_option() { 40 | local arr_name=$1 41 | eval "local arr=(\"\${${arr_name}[@]}\")" 42 | local option=$2 43 | if [[ ${arr[option]} == true ]]; then 44 | arr[option]= 45 | else 46 | arr[option]=true 47 | fi 48 | eval $arr_name='("${arr[@]}")' 49 | } 50 | 51 | local retval=$1 52 | local options 53 | local defaults 54 | local max_str_len=0 55 | 56 | IFS=';' read -r -a options <<<"$2" 57 | if [[ -z $3 ]]; then 58 | defaults=() 59 | else 60 | IFS=';' read -r -a defaults <<<"$3" 61 | fi 62 | local selected=() 63 | 64 | for ((i = 0; i < ${#options[@]}; i++)); do 65 | selected+=("${defaults[i]}") 66 | printf "\n" 67 | if [ ${#options[$i]} -gt $max_str_len ]; then 68 | max_str_len=${#options[$i]} 69 | fi 70 | done 71 | 72 | # determine current screen position for overwriting the options 73 | local lastrow=$(get_cursor_row) 74 | local startrow=$(($lastrow - ${#options[@]})) 75 | 76 | # ensure cursor and input echoing back on upon a ctrl+c during read -s 77 | trap "cursor_blink_on; stty echo; printf '\n'; exit" 2 78 | cursor_blink_off 79 | 80 | local active=0 81 | while true; do 82 | # print options by overwriting the last lines 83 | local idx=0 84 | for option in "${options[@]}"; do 85 | local prefix="◯" 86 | if [[ ${selected[idx]} == true ]]; then 87 | prefix="◉" 88 | fi 89 | 90 | cursor_to $(($startrow + $idx)) 91 | if is_separator $option; then 92 | print_separator ${option:1:(${#option} - 2)} $max_str_len 93 | else 94 | if [ $idx -eq $active ]; then 95 | print_active "$option" "$prefix" 96 | else 97 | print_inactive "$option" "$prefix" 98 | fi 99 | fi 100 | ((idx++)) 101 | done 102 | 103 | # user key control 104 | case $(key_input) in 105 | space) toggle_option selected $active ;; 106 | enter) break ;; 107 | up) 108 | ((active--)) 109 | if [ $active -lt 0 ]; then active=$((${#options[@]} - 1)); fi 110 | if is_separator ${options[$active]}; then ((active--)); fi 111 | ;; 112 | down) 113 | ((active++)) 114 | if is_separator ${options[$active]}; then ((active++)); fi 115 | if [ $active -ge ${#options[@]} ]; then active=0; fi 116 | ;; 117 | esac 118 | done 119 | 120 | # cursor position back to normal 121 | cursor_to $lastrow 122 | printf "\n" 123 | cursor_blink_on 124 | eval $retval='("${selected[@]}")' 125 | } 126 | 127 | function split() { 128 | local string=$1 129 | local output=$2 130 | local delimiter=$3 131 | local oldIFS=$IFS 132 | if [[ -z "$delimiter" ]]; then 133 | delimiter=$'\n' 134 | fi 135 | IFS=$delimiter 136 | eval $output='($string)' 137 | IFS=$oldIFS 138 | } 139 | 140 | set -o errexit 141 | set -o pipefail 142 | 143 | if [[ $1 == '-h' ]]; then 144 | echo "usage: brew-up [-s]" 145 | exit 146 | fi 147 | if [[ $1 != '-s' ]]; then 148 | brew update 149 | fi 150 | 151 | outdated=$(brew outdated -v --formula) 152 | outdated_cask=$(brew outdated --cask --greedy --verbose) 153 | 154 | if [[ -z ${outdated} && -z ${outdated_cask} ]]; then 155 | exit 156 | fi 157 | 158 | options=() 159 | formulae_len=0 160 | 161 | if [[ ! -z ${outdated} ]]; then 162 | split "${outdated[*]//