diff options
| -rwxr-xr-x | gist | 76 |
1 files changed, 58 insertions, 18 deletions
| @@ -6,7 +6,7 @@ | |||
| 6 | # | 6 | # |
| 7 | # | 7 | # |
| 8 | # This script host your gists as local cloned git repo | 8 | # This script host your gists as local cloned git repo |
| 9 | # It works under GNU with jq and curl, both are easy to get in most cases | 9 | # It works under GNU curl, which is easy to get in most cases |
| 10 | # | 10 | # |
| 11 | # Use the following commands to manage your gists: | 11 | # Use the following commands to manage your gists: |
| 12 | # | 12 | # |
| @@ -46,13 +46,12 @@ | |||
| 46 | # It is your business to do git commit and git push | 46 | # It is your business to do git commit and git push |
| 47 | # | 47 | # |
| 48 | # * configuration | 48 | # * configuration |
| 49 | # gist (config | c) [token <value>] [user <value>] [folder <value>] | 49 | # gist (config | c) [token <value>] [user <value>] [folder <value>] [auto-sync false] |
| 50 | # | 50 | # |
| 51 | # * show this help message | 51 | # * show this help message |
| 52 | # gist (help | h) | 52 | # gist (help | h) |
| 53 | 53 | ||
| 54 | # TODO error handling, unit test | 54 | # TODO error handling, unit test |
| 55 | # TODO parallel branch works with json parsing on python | ||
| 56 | # TODO parallel branch works with wget and other stuff | 55 | # TODO parallel branch works with wget and other stuff |
| 57 | # TODO completion | 56 | # TODO completion |
| 58 | # TODO grep mode for description, file content | 57 | # TODO grep mode for description, file content |
| @@ -62,6 +61,12 @@ config=~/.config/gistrc | |||
| 62 | set -eo pipefail | 61 | set -eo pipefail |
| 63 | [ "$TRACE" ] && set -x | 62 | [ "$TRACE" ] && set -x |
| 64 | 63 | ||
| 64 | ## parse JSON from STDIN with string of commands | ||
| 65 | AccessJsonElement() { | ||
| 66 | PYTHONIOENCODING=utf-8 python -c "from __future__ import print_function; import sys, json; raw = json.load(sys.stdin); $1" | ||
| 67 | return "$?" | ||
| 68 | } | ||
| 69 | |||
| 65 | _auth() { | 70 | _auth() { |
| 66 | echo 'Hi fellow! To access your gists, I need your Github username and a personal token with scope which allows "gist"!' | 71 | echo 'Hi fellow! To access your gists, I need your Github username and a personal token with scope which allows "gist"!' |
| 67 | read -p "Github username: " user < /dev/tty | 72 | read -p "Github username: " user < /dev/tty |
| @@ -146,12 +151,24 @@ _update() { | |||
| 146 | if [[ $auto_sync != "false" ]]; then (_sync_repos $1 > /dev/null 2>&1 &); fi | 151 | if [[ $auto_sync != "false" ]]; then (_sync_repos $1 > /dev/null 2>&1 &); fi |
| 147 | } | 152 | } |
| 148 | 153 | ||
| 154 | # equal to: jq '.[] | "\(.html_url) \([.files[] | .raw_url]) \(.files | keys | length) \(.comments) \(.description)"' | ||
| 155 | _handle_gists() { | ||
| 156 | echo ' | ||
| 157 | for gist in raw: | ||
| 158 | print(gist["html_url"], end=" ") | ||
| 159 | print([file["raw_url"] for file in gist["files"].values()], end=" ") | ||
| 160 | print(len(gist["files"]), end=" ") | ||
| 161 | print(gist["comments"], end=" ") | ||
| 162 | print(gist["description"]) | ||
| 163 | ' | ||
| 164 | } | ||
| 165 | |||
| 149 | # TODO check if a user create a very first gist | 166 | # TODO check if a user create a very first gist |
| 150 | _parse_response() { | 167 | _parse_response() { |
| 151 | jq '.[] | "\(.html_url) \([.files[] | .raw_url]) \(.files | keys | length) \(.comments) \(.description)"' \ | 168 | AccessJsonElement "$(_handle_gists)" \ |
| 152 | | tac \ | 169 | | tac | sed 's/, /,/g'\ |
| 153 | | while read link file_url_array file_num comment_num description; do | 170 | | while read link file_url_array file_num comment_num description; do |
| 154 | local blob_code=$(echo $file_url_array | jq -r '.[]' | sed -E 's#.*raw/(.*)/.*#\1#' | sort | cut -c -7 | paste -sd '-') | 171 | local blob_code=$(echo $file_url_array | tr ',' '\n' | sed -E 's#.*raw/(.*)/.*#\1#' | sort | cut -c -7 | paste -sd '-') |
| 155 | echo $link $blob_code $file_num $comment_num $description | tr -d '"' | 172 | echo $link $blob_code $file_num $comment_num $description | tr -d '"' |
| 156 | done | 173 | done |
| 157 | } | 174 | } |
| @@ -163,7 +180,7 @@ _sync_repos() { | |||
| 163 | # clone repos which are not in the local | 180 | # clone repos which are not in the local |
| 164 | comm -13 <(find $folder -maxdepth 1 -type d | sed '1d; s#.*/##' | sort) \ | 181 | comm -13 <(find $folder -maxdepth 1 -type d | sed '1d; s#.*/##' | sort) \ |
| 165 | <(cat $list_file | cut -d' ' -f2 | sed 's#.*/##' | sort) \ | 182 | <(cat $list_file | cut -d' ' -f2 | sed 's#.*/##' | sort) \ |
| 166 | | xargs -I{} git clone git@github.com:{}.git $folder/{} | 183 | | xargs -I{} --max-procs 8 git clone git@github.com:{}.git $folder/{} |
| 167 | 184 | ||
| 168 | # pull if remote repo has different blob objects | 185 | # pull if remote repo has different blob objects |
| 169 | cat $index | cut -d' ' -f2,3 \ | 186 | cat $index | cut -d' ' -f2,3 \ |
| @@ -178,8 +195,9 @@ _sync_repos() { | |||
| 178 | echo Everything is fine! | 195 | echo Everything is fine! |
| 179 | } | 196 | } |
| 180 | 197 | ||
| 198 | # get gist id from index files | ||
| 181 | _gist_id() { | 199 | _gist_id() { |
| 182 | GIST_ID=$(cat $index $starred 2> /dev/null | sed -n "/^$1 / p" | cut -d' ' -f2 | sed -E 's#.*/##') | 200 | GIST_ID=$( (grep -hs '' $index $starred || true) | sed -n "/^$1 / p" | cut -d' ' -f2 | sed -E 's#.*/##') |
| 183 | if [[ -z "$GIST_ID" ]]; then | 201 | if [[ -z "$GIST_ID" ]]; then |
| 184 | echo -e "Not a valid index: \e[31m$1\e[0m" | 202 | echo -e "Not a valid index: \e[31m$1\e[0m" |
| 185 | echo Use the index number in the first column instead: | 203 | echo Use the index number in the first column instead: |
| @@ -223,16 +241,43 @@ _clean_repos() { | |||
| 223 | done | 241 | done |
| 224 | } | 242 | } |
| 225 | 243 | ||
| 244 | _handle_gist() { | ||
| 245 | echo ' | ||
| 246 | print("site:", raw["html_url"]) | ||
| 247 | print("description:", raw["description"]) | ||
| 248 | print("public:", raw["public"]) | ||
| 249 | print("API:", raw["url"]) | ||
| 250 | print("created_at:", raw["created_at"]) | ||
| 251 | print("updated_at:", raw["updated_at"]) | ||
| 252 | print("files:") | ||
| 253 | for file in raw["files"].keys(): | ||
| 254 | print(" ", file) | ||
| 255 | ' | ||
| 256 | } | ||
| 257 | |||
| 258 | # equal to jq '.[] | {user: .user.login, created_at: .created_at, updated_at: .updated_at, body: .body}' | ||
| 259 | _handle_comment() { | ||
| 260 | echo ' | ||
| 261 | for comment in raw: | ||
| 262 | print() | ||
| 263 | print("|", "user:", comment["user"]["login"]) | ||
| 264 | print("|", "created_at:", comment["created_at"]) | ||
| 265 | print("|", "updated_at:", comment["updated_at"]) | ||
| 266 | print("|", comment["body"]) | ||
| 267 | ' | ||
| 268 | } | ||
| 269 | |||
| 226 | # TODO format with simple text | 270 | # TODO format with simple text |
| 227 | _show_detail() { | 271 | _show_detail() { |
| 228 | _gist_id $1 | 272 | _gist_id $1 |
| 229 | curl -s $github_api/gists/$GIST_ID \ | 273 | curl -s $github_api/gists/$GIST_ID \ |
| 230 | | jq '{site: .html_url, description: .description, public: .public, API: .url, created_at: .created_at, updated_at: .updated_at, files: (.files | keys)}' | 274 | | AccessJsonElement "$(_handle_gist)" |
| 231 | 275 | ||
| 232 | curl -s $github_api/gists/$GIST_ID/comments \ | 276 | curl -s $github_api/gists/$GIST_ID/comments \ |
| 233 | | jq '.[] | {user: .user.login, created_at: .created_at, updated_at: .updated_at, body: .body}' | 277 | | AccessJsonElement "$(_handle_comment)" |
| 234 | } | 278 | } |
| 235 | 279 | ||
| 280 | # FIXME put file before parameters | ||
| 236 | _set_gist() { | 281 | _set_gist() { |
| 237 | while [[ "$1" =~ ^- && "$1" != "--" ]]; do case $1 in | 282 | while [[ "$1" =~ ^- && "$1" != "--" ]]; do case $1 in |
| 238 | -d | --desc) | 283 | -d | --desc) |
| @@ -266,14 +311,9 @@ _create_gist() { | |||
| 266 | [[ -z "$description" ]] && read -p 'Type description: ' description < /dev/tty | 311 | [[ -z "$description" ]] && read -p 'Type description: ' description < /dev/tty |
| 267 | 312 | ||
| 268 | for file in $files; do | 313 | for file in $files; do |
| 269 | FILE=$(basename $file) | 314 | echo "\"$(basename $file)\": {\"content\": \"$(sed '$ !s/$/\\n/' $file)\"}," |
| 270 | jq --arg FILE "$FILE" '. as $content | { ($FILE): {content: $content} }' -Rs $file | 315 | done | tr -d '\n' | sed 's/^/{/; s/,$/}/' \ |
| 271 | done \ | 316 | | echo "{ \"public\": true, \"files\": $(cat -), \"description\": \"$description\"}" \ |
| 272 | | jq --slurp --arg DESC "$description" '{ | ||
| 273 | public: true, | ||
| 274 | files: add, | ||
| 275 | description: ($DESC) | ||
| 276 | }' \ | ||
| 277 | | curl -s -H "$auth_header" --data @- $github_api/gists \ | 317 | | curl -s -H "$auth_header" --data @- $github_api/gists \ |
| 278 | | sed '1 s/^/[/; $ s/$/]/' \ | 318 | | sed '1 s/^/[/; $ s/$/]/' \ |
| 279 | | _parse_response \ | 319 | | _parse_response \ |