From 456d5d41eeca37a595980ec3ba8e9411e0dfb63b Mon Sep 17 00:00:00 2001 From: typebrook Date: Mon, 20 Jan 2020 11:53:00 +0800 Subject: update --- gist | 221 +++++++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 149 insertions(+), 72 deletions(-) diff --git a/gist b/gist index 9a869f9..55c9ab8 100755 --- a/gist +++ b/gist @@ -5,7 +5,7 @@ # https://gist.github.com/typebrook/b0d2e7e67aa50298fdf8111ae7466b56 # # -# This script host your gists as local Github repo +# This script host your gists as local cloned git repo # It works under GNU with jq and curl, both are easy to get in most cases # # Use the following commands to manage your gists: @@ -18,31 +18,42 @@ # # * clone gist repos which are not in local # * pull master branch if a local repo is behind its remote -# gist [sync | s] +# gist (sync | S) # # * Go to local gist repo -# gist +# . gist # -# * create a new gist with a file and description -# gist [create | c] "" +# * create a new gist with files +# gist (new | n) [-d | --desc ""] ... +# +# * create a new gist with STDIN +# gist (new | n) [-d | --desc ""] [-f | --file ] < # # * show the detail of a gist -# gist [detail | d] +# gist (detail | d) # # * edit a gist description -# gist [edit | e] +# gist (edit | e) # # * delete a gist -# gist [delete | D] +# gist (delete | D) ... # # * clean removed gists in local -# gist [clean | C] - +# gist (clean | C) +# +# * update a gist +# Since now a gist is a local cloned repo +# It is your business to do git commit and git push +# # * show this help message -# gist [help | h] +# gist (help | h) # define your environmemnts here -# TODO support auth prompt +# TODO support auth prompt, remove personal info here +# TODO error handling, unit test +# TODO parallel branch works with json parsing on python +# TODO parallel branch works with wget and other stuff +# completion #------------------- github_api_token=$(cat $SETTING_DIR/tokens/github) user=typebrook @@ -53,32 +64,68 @@ github_api=https://api.github.com auth_header="Authorization: token $github_api_token" mkdir -p $folder index=$folder/index +starred=$folder/starred # Validate settings. [ "$TRACE" ] && set -x # Show the list of gist, but not updated time +# TODO show git status outdated _show_list() { - cat $index | cut -d' ' -f1-2,4- + if [[ ! -e $1 ]]; then + echo No local file found for last update + echo Please run command: + echo " gist update" + exit 0 + fi + cat $1 |\ + while read line_num link file_url_array file_num extra description; do + repo=$folder/$(echo $link | sed 's#.*/##') + + # if repo is not yet cloned, show green message "Sync Now" + cd $repo 2>/dev/null || extra="\e[32m[Sync Now]\e[0m" + # if there are some changes in git index or working directory, show blue message "working" + [[ -n $(git status --short) ]] 2>/dev/null && extra="\e[36m[working]\e[0m" + # if there is a commit not yet push, show red message "ahead" + [[ -n $(git cherry) ]] 2>/dev/null && extra="\e[31m[ahead]\e[0m" + + echo -e $line_num $link $file_num $extra $(echo $description | cut -c -60) + done } # get the list of gists # TODO support secret gist _update() { - curl -s -H "$auth_header" $github_api/users/$user/gists |\ + echo "fetching from api.github.com..." + echo + list_file=$index + route="users/$user/gists" + mark="" + [[ "$1" =~ ^(star|s)$ ]] && list_file=$starred && route="gists/starred" && mark="s" + + curl -s -H "$auth_header" $github_api/$route |\ + _parse_response | nl -s' ' | sed -E "s/^ */$mark/" > $list_file && \ + _show_list $list_file + (_sync_repos $1 > /dev/null 2>&1 &) +} + +# TODO check if a user create a very first gist +_parse_response() { jq '.[] | "\(.html_url) \([.files[] | .raw_url]) \(.files | keys | length) \(.comments) \(.description)"' |\ - tac | nl |\ - while read line_num link file_url_array file_num comment_num description; do - blob_code=$(echo $file_url_array | jq -r '.[]' | sed -r 's#.*raw/(.*)/.*#\1#' | sort | cut -c -7 | paste -sd '-') - echo $line_num $link $blob_code $file_num $comment_num $(echo $description | cut -c -70) | tr -d '"' - done > $index && \ - _show_list + tac |\ + while read link file_url_array file_num comment_num description; do + blob_code=$(echo $file_url_array | jq -r '.[]' | sed -E 's#.*raw/(.*)/.*#\1#' | sort | cut -c -7 | paste -sd '-') + echo $link $blob_code $file_num $comment_num $description | tr -d '"' + done } _sync_repos() { + list_file=$index + [[ "$1" == "--star" ]] && list_file=$starred && route="gists/starred" + # clone repos which are not in the local comm -13 <(find $folder -maxdepth 1 -type d | sed '1d; s#.*/##' | sort) \ - <(cat $index | cut -d' ' -f2 | sed 's#.*/##' | sort) |\ + <(cat $list_file | cut -d' ' -f2 | sed 's#.*/##' | sort) |\ xargs -I{} git clone git@github.com:{}.git $folder/{} # pull if remote repo has different blob objects @@ -96,27 +143,32 @@ _sync_repos() { } _gist_id() { - cat $index | sed -n "$1"p | cut -d' ' -f2 | sed -r 's#.*/##' -} - -_goto_gist() { - gist_num=$(wc -l $index | cut -d' ' -f1) - if [[ ! "$1" =~ [0-9]+ ]] || (( $1 > $gist_num )); then - echo Not a valid gist number: $1 - echo Use the number in the first column instead: + GIST_ID=$(cat $index $starred | sed -n "/^$1 / p" | cut -d' ' -f2 | sed -E 's#.*/##') + if [[ -z $GIST_ID ]]; then + echo -e "Not a valid index: \e[31m$1\e[0m" + echo Use the index number in the first column instead: echo - _show_list - return 0 + _show_list "$index $starred" + exit 1 fi +} - GIST_ID=$(_gist_id $1) +# FIXME error handling +_goto_gist() { + _gist_id $1 echo This gist is at $folder/$GIST_ID - cd $folder/$GIST_ID && tig --all 2> /dev/null + echo -e "You can run the following command to jump to this directory: \n" + echo -e " \e[32m. gist $1\e[0m" + echo + cd $folder/$GIST_ID && ls && tig --all 2> /dev/null } _delete_gist() { - GIST_ID=$(_gist_id $1) - curl -X DELETE -s -H "$auth_header" $github_api/gists/$GIST_ID && \ + for i in "$@"; do + _gist_id "$i" + curl -X DELETE -s -H "$auth_header" $github_api/gists/$GIST_ID && \ + echo "$i" deleted + done _update } @@ -129,78 +181,103 @@ _clean_repos() { done } -# TODO star count +# TODO format with simple text _show_detail() { - GIST_ID=$(_gist_id $1) + _gist_id $1 curl -s -H "$auth_header" $github_api/gists/$GIST_ID |\ - jq '{site: .html_url, description: .description, API: .url, created_at: .created_at, updated_at: .updated_at, files: (.files | keys)}' + jq '{site: .html_url, description: .description, public: .public, API: .url, created_at: .created_at, updated_at: .updated_at, files: (.files | keys)}' curl -s -H "$auth_header" $github_api/gists/$GIST_ID/comments |\ jq '.[] | {user: .user.login, created_at: .created_at, updated_at: .updated_at, body: .body}' } +_new_file() { + [[ -t 0 ]] && echo "Type a gist. to cancel, when done" > /dev/tty + tmp_file=$(mktemp) + cat > $tmp_file + echo + [[ -z "$1" ]] && echo -en '\nType file name: ' > /dev/tty && read filename + mv $tmp_file /tmp/$filename + echo /tmp/$filename +} + +_set_gist() { + while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in + -d | --desc) + description="$2" + shift; shift;; + -f | --file) + filename="$2" + shift; shift;; + esac + done + if [[ "$1" == '--' ]]; then shift; fi + files=$@ +} + # create a new gist with files +# FIXME error handling if gist is not created _create_gist() { - echo -n 'description: ' - read DESC + _set_gist "$@" + [[ -z $files ]] && files=$(_new_file $filename) + [[ -z $description ]] && echo -en '\nDescription: ' && read description - echo $@ | tr " " "\n" |\ - while read file; do + for file in $files; do FILE=$(basename $file) jq --arg FILE "$FILE" '. as $content | { ($FILE): {content: $content} }' -Rs $file done |\ - jq --slurp --arg DESC "$DESC" '{ + jq --slurp --arg DESC "$description" '{ public: true, files: add, description: ($DESC) }' |\ - curl -s -H "$auth_header" --data @- $github_api/gists > /dev/null && \ - _update && _sync_repos + curl -H "$auth_header" --data @- $github_api/gists |\ + sed '1 s/^/[/; $ s/$/]/' |\ + _parse_response |\ + sed -E "s/^/$(( $(wc -l $index | cut -d' ' -f1) + 1 )) /" >> $index && \ + echo Gist created + echo + _show_list $index | tail -1 } # update description of a gist _edit_gist() { - GIST_ID=$(_gist_id $1) + _gist_id $1 - jq -n --arg DESC "$2" '{ description: ($DESC) }' |\ + echo -n 'Type new description: ' + read DESC + jq -n --arg DESC "$DESC" '{ description: ($DESC) }' |\ curl -X PATCH -H "$auth_header" --data @- $github_api/gists/$GIST_ID > /dev/null && \ _update } _help_message() { - sed -r -n ' /^$/ q; 8,$ s/^#//p' $0 + sed -E -n ' /^$/ q; 8,$ s/^#//p' $0 } case "$1" in "") - _show_list - ;; - create | c) - shift; - _create_gist $@ - ;; - edit | e) - _edit_gist "$2" "$3" - ;; + _show_list $index ;; + star | s) + _show_list $starred ;; update | u) - _update - ;; - sync | s) - _sync_repos - ;; + _update "$2" ;; + new | n) + shift + _create_gist "$@" ;; + edit | e) + _edit_gist "$2" ;; + sync | S) + _sync_repos ;; detail | d) - _show_detail "$2" - ;; + _show_detail "$2" ;; delete | D) - _delete_gist "$2" - ;; + shift + _delete_gist "$@" ;; clean | C) - _clean_repos - ;; + _clean_repos ;; help | h) - _help_message - ;; + _help_message ;; *) - _goto_gist "$1" - ;; + _goto_gist "$1" ;; esac -- cgit v1.2.3-70-g09d2