tagger (3725B)
1 #!/usr/bin/env sh 2 # disable warnings about variables are declared indirectly 3 # shellcheck disable=SC2154 4 5 ## tagger - simple tagging system for any types of files 6 7 # Developer notes 8 # - 'tagger alias folder' for output alias and completion commands 9 # - add '_tagger_completion name folder` for aliases completion 10 # - check command for test tagger folder correctnes 11 # - you can make completition as separate task, maybe? 12 # so you can get arguments and decide wath to complete 13 14 set -e 15 16 # Error handling and checks 17 err () { 18 echo "$@" >&2 19 exit 20 } 21 22 check () { 23 name="$1" 24 value="$2" 25 desc="$3" 26 27 pexist "$value" "$desc" 28 shift 3 29 30 for chk in "$@" 31 do 32 "$chk" "$value" "$desc" 33 done 34 35 [ -n "$name" ] && eval "$name=$value" 36 } 37 38 check_all () { 39 name="$1" 40 vars="$2" 41 desc="$3" 42 43 pexist "$vars" "$desc" 44 shift 3 45 46 for chk in "$@" 47 do 48 for var in $vars 49 do 50 "$chk" "$var" "$desc" 51 done 52 done 53 54 [ -n "$name" ] && eval "$name=\"$vars\"" 55 } 56 57 pexist () { 58 [ -z "$1" ] && 59 err "$2 should be specified" 60 } 61 62 pnotagger () { 63 [ -d "$BASE" ] && 64 err "$2 is already contain tagger: $1" 65 } 66 67 pfile () { 68 [ ! -f "$1" ] && 69 err "$2 should exist and be a file: $1" 70 } 71 72 pdir () { 73 [ ! -d "$1" ] && 74 err "$2 should exist and be a directory: $1" 75 } 76 77 ptagged () { 78 [ ! -f "$BASE/$1" ] && 79 err "$2 should be added before: $1" 80 } 81 82 ptag () { 83 [ ! -d "$BASE/../$1" ] && 84 err "$2 should exist: $1" 85 } 86 87 pbase () { 88 [ ! -d "$BASE" ] && 89 err "$2 should be initialized by tagger: $1" 90 } 91 92 # Script logic 93 94 ## 95 ## Usage: 96 ## 97 ## Common pattern is: 98 ## tagger _folder_ command [arguments ...] 99 ## 100 print_help () { 101 awk '/^##/{print substr($0, 4);}' "$SCRIPT" 102 exit 103 } 104 105 ## tagger _folder_ init 106 ## create new folder structure, for 107 ## keeping files and tags 108 ## 109 init_tagger () { 110 check "" "$1" folder pnotagger 111 112 mkdir -p "$BASE" 113 } 114 115 ## tagger _folder_ add [_file_ ...] 116 ## move file to tagger in tagger folder 117 ## 118 add_file () { 119 check "" "$1" "tagger folder" pdir pbase 120 #check file "$3" file pfile 121 shift 2 122 check_all files "$*" files pfile 123 124 mv "$files" "$BASE" 125 } 126 127 ## tagger _folder_ tag _file_ _tag_ 128 ## add tag to file from tagger folder 129 ## 130 tag_file () { 131 check folder "$1" "tagger folder" pdir pbase 132 check file "$3" file ptagged 133 check tag "$4" tag 134 135 tag_folder="$folder/$tag" 136 mkdir -p "$tag_folder" 137 ln -s "../.base/$file" "$tag_folder" 138 } 139 140 ## tagger _folder_ untag _file_ _tag_ 141 ## remove tag from file in tagger folder 142 ## 143 untag_file () { 144 check folder "$1" "tagger folder" pdir pbase 145 check file "$3" file ptagged 146 check tag "$4" tag ptag 147 148 tag_folder="$folder/$tag" 149 rm -f "$tag_folder/$file" 150 } 151 152 ## tagger _folder_ ls 153 ## list all files under tagger folder 154 ## 155 list () { 156 check "" "$1" "tagger folder" pdir pbase 157 ls -1 "$BASE" 158 } 159 160 ## tagger _folder_ path _file_ 161 ## get path for tagged file 162 ## 163 path () { 164 check "" "$1" "tagger folder" pdir pbase 165 check file "$3" file ptagged 166 167 echo "$BASE/$file" 168 } 169 170 ## tagger _folder_ rm _file_ 171 ## remove file from tagger 172 ## 173 remove () { 174 check "" "$1" "tagger folder" pdir pbase 175 check file "$3" file ptagged 176 177 rm -f "$BASE"/../*/"$file" 178 rm "$BASE/$file" 179 } 180 181 # Process arguments 182 183 SCRIPT=$(dirname "$0")/tagger 184 [ "$#" -lt 2 ] && print_help 185 186 BASE="$1/.base" 187 COMMAND="$2" 188 189 case "$COMMAND" in 190 init) init_tagger "$@" ;; 191 add) add_file "$@" ;; 192 tag) tag_file "$@" ;; 193 untag) untag_file "$@" ;; 194 ls) list "$@" ;; 195 path) path "$@" ;; 196 rm) remove "$@" ;; 197 *) err "Unknown command $COMMAND" ;; 198 esac