##GithubGistClient
GithubGistClient
is a Mathematica client for Githib gists, which uses the Github gist API to manipulate gists from within Mathematica
(* Mathematica Package *) | |
BeginPackage["GithubGistClient`"] | |
(* Exported symbols added here with SymbolName::usage *) | |
(* TODO: | |
1. Make this OO | |
2. Get rid of curl | |
3. Refine the API | |
*) | |
$curl; | |
$userpswd; | |
getGist; | |
GistObject; | |
getBriefVersionInfo; | |
getVersionCommitDate; | |
getVersionURL; | |
getGistComments; | |
getGistCommentsURL; | |
getGistCreationTime; | |
getGistID; | |
getGistHtmlURL; | |
getGistURL; | |
getGistUpdateTime; | |
getGistFilesInfo; | |
getGistFileKeyName; | |
getGistFileNames; | |
getGistFileInfo; | |
getGistFileContent; | |
getGistFileName; | |
getGistFileRawURL; | |
getGistFileType; | |
makeFileEditInfo; | |
FileEditInfo; | |
makeFileDeleteInfo; | |
makeGistEditInfo; | |
editGist; | |
makeFileCreateInfo; | |
FileCreateInfo; | |
makeGistCreateInfo; | |
createGist; | |
deleteGist; | |
listUserGists; | |
Begin["`Private`"] (* Begin Private Context *) | |
Needs["ResourceLocator`"]; | |
$curl := Throw[$Failed, "curl_path_not_set"]; | |
$userpswd := Throw[$Failed, "user_and_pswd_not_set"]; | |
$temporaryDirectory = ApplicationDataUserDirectory["GithubGistClient"]; | |
ClearAll[fullName]; | |
fullName[name_] := FileNameJoin[{$temporaryDirectory , name}]; | |
stringify[s_String] := StringJoin["\"", s, "\""]; | |
auth[] := " --user " <> $userpswd; | |
ClearAll[LetL]; | |
SetAttributes[LetL, HoldAll]; | |
SyntaxInformation[LetL] = {"ArgumentsPattern" -> {_, _}, | |
"LocalVariables" -> {"Solve", {1, Infinity}}}; | |
LetL /: Verbatim[SetDelayed][lhs_, rhs : HoldPattern[LetL[{__}, _]]] := | |
Block[{With}, Attributes[With] = {HoldAll}; | |
lhs := Evaluate[rhs]]; | |
LetL[{}, expr_] := expr; | |
LetL[{head_}, expr_] := With[{head}, expr]; | |
LetL[{head_, tail__}, expr_] := | |
Block[{With}, Attributes[With] = {HoldAll}; | |
With[{head}, Evaluate[LetL[{tail}, expr]]]]; | |
Clear[makeTemporaryJSONFile]; | |
makeTemporaryJSONFile[name_String, content_] := | |
Export[name, content, "JSON"] | |
Clear[getGistScript]; | |
getGistScript[gistID_String, tempfile_String, isAuth_: False] := | |
stringify@StringJoin[ | |
stringify@$curl, | |
" -k -v ", | |
If[isAuth, auth[], Sequence @@ {}], | |
" -X GET https://api.github.com/gists/", | |
gistID, | |
" -o ", | |
stringify@tempfile]; | |
ClearAll[getGist]; | |
getGist[gistID_String, isAuth_: False] := | |
Module[{tempFile = fullName["result.txt"]}, | |
If[FileExistsQ[tempFile], DeleteFile[tempFile]]; | |
If[Run[getGistScript[gistID, tempFile, False]] != 0 || !FileExistsQ[tempFile], | |
Return[$Failed] | |
]; | |
GistObject@Import[tempFile, "JSON"]] | |
ClearAll[GistObject]; | |
GistObject[gist_][prop_] := OptionValue[gist, prop]; | |
ClearAll[getBriefVersionInfo]; | |
getBriefVersionInfo[gist_GistObject] := | |
FilterRules[#, "committed_at" | "url" | "version" -> _] & /@ | |
gist["history"] | |
ClearAll[getVersionCommitDate, getVersionURL] | |
getVersionCommitDate[versionData_List] := | |
"committed_at" /. versionData; | |
getVersionURL[versionData_List] := | |
"url" /. versionData; | |
ClearAll[getGistComments, getGistCommentsURL, getGistCreationTime, | |
getGistID, getGistHtmlURL, getGistURL, getGistUpdateTime]; | |
getGistID[gist_GistObject] := gist["id"]; | |
getGistHtmlURL[gist_GistObject] := gist["html_url"]; | |
getGistURL[gist_GistObject] := gist["url"]; | |
getGistUpdateTime[gist_GistObject] := DateList@gist["updated_at"]; | |
getGistComments[gist_GistObject] := gist["comments"]; | |
getGistCommentsURL[gist_GistObject] := gist["comments_url"]; | |
getGistCreationTime[gist_GistObject] := gist["created_at"]; | |
getGistDescription[gist_GistObject] := gist["description"]; | |
ClearAll[getGistFilesInfo]; | |
getGistFilesInfo[gist_GistObject] := gist["files"]; | |
ClearAll[getGistFileKeyName]; | |
getGistFileKeyName[name_ -> _] := name; | |
ClearAll[getGistFileNames]; | |
getGistFileNames[gist_GistObject] := | |
Map[getGistFileKeyName, getGistFilesInfo[gist]]; | |
Clear[getGistFileInfo]; | |
getGistFileInfo[name_, gist_GistObject] := | |
getGistFileInfo[name, getGistFilesInfo[gist]]; | |
getGistFileInfo[name_, filesInfo_] := | |
name /. filesInfo; | |
ClearAll[getGistFileContent, getGistFileName, getGistFileRawURL, | |
getGistFileType]; | |
getGistFileContent[name_, gist_GistObject] := | |
"content" /. getGistFileInfo[name, gist]; | |
getGistFileName[name_, gist_GistObject] := | |
"filename" /. getGistFileInfo[name, gist]; | |
getGistFileRawURL[name_, gist_GistObject] := | |
"raw_url" /. getGistFileInfo[name, gist]; | |
getGistFileType[name_, gist_GistObject] := | |
"type" /. getGistFileInfo[name, gist]; | |
ClearAll[makeFileEditInfo] | |
makeFileEditInfo[name_, Automatic, Automatic] := Sequence[] | |
makeFileEditInfo[name_String, newContent_, newName_: Automatic] := | |
With[{ | |
rules = | |
MapThread[ | |
If[#1 === Automatic, Sequence @@ {}, #2 -> #1] &, | |
{{newContent, newName}, {"content", "filename"}} | |
]}, | |
FileEditInfo[name -> rules] | |
]; | |
Clear[makeFileDeleteInfo]; | |
makeFileDeleteInfo[name_String] := FileEditInfo[name -> Null]; | |
ClearAll[makeGistEditInfo]; | |
makeGistEditInfo[fileEdits : {___FileEditInfo}, | |
newDescription_: Automatic] := | |
With[{ | |
desc = | |
If[#1 === Automatic, Sequence @@ {}, #2 -> #1] &[newDescription, | |
"description"], | |
files = fileEdits /. FileEditInfo[info_] :> info | |
}, | |
{ | |
desc, | |
If[files =!= {}, "files" -> files, Sequence @@ {}] | |
} | |
]; | |
makeGistEditInfo[fileEdits : {(_String -> _String) ...}, | |
fileRenamings : {(_String -> _String) ...}, | |
fileRemovals : {___String}, newDescription_: Automatic] := | |
makeGistEditInfo[ | |
Join[ | |
Map[makeFileEditInfo[#, # /. fileEdits /. # -> Automatic, # /. | |
fileRenamings /. # -> Automatic] &, | |
Union[fileEdits[[All, 1]], fileRenamings[[All, 1]]] | |
], | |
Map[makeFileDeleteInfo, fileRemovals] | |
], | |
newDescription | |
]; | |
makeGistEditInfo[___] := throwError[makeGistEditInfo]; | |
Clear[editGistScript]; | |
editGistScript[gistID_String, tempfile_String, jsonFile_String, | |
isAuth_: True] := | |
stringify@StringJoin[ | |
stringify@$curl, | |
" -k -v ", | |
If[isAuth, auth[], Sequence @@ {}], | |
" -X PATCH https://api.github.com/gists/", | |
gistID, | |
" --data ", | |
"@", | |
stringify@jsonFile, | |
" -o ", | |
stringify@tempfile]; | |
ClearAll[editGist]; | |
editGist[gistID_String, newContent_] := | |
Module[{tempFile = fullName["temp.txt"], | |
jsonFile = fullName["gistedit.json"]}, | |
If[FileExistsQ[#], DeleteFile[#]] & /@ {tempFile, jsonFile}; | |
If[makeTemporaryJSONFile[jsonFile, newContent] === $Failed, | |
Return[$Failed]]; | |
If[Run[editGistScript[gistID, tempFile, jsonFile]] != 0 || !FileExistsQ[tempFile], | |
Return[$Failed] | |
]; | |
GistObject@Import[tempFile, "JSON"]] | |
ClearAll[makeFileCreateInfo] | |
makeFileCreateInfo[name_String, content_] := | |
FileCreateInfo[name -> {"content" -> content}]; | |
ClearAll[makeGistCreateInfo]; | |
makeGistCreateInfo[files : {__FileCreateInfo}, | |
description_: Automatic] := | |
{ | |
If[# === Automatic, Sequence @@ {}, "description" -> #] &[ | |
description], | |
"public" -> True, | |
"files" -> (files /. FileCreateInfo[x_] :> x) | |
}; | |
Clear[createGistScript]; | |
createGistScript[tempfile_String, jsonFile_String, isAuth_: True] := | |
stringify@StringJoin[ | |
stringify@$curl, | |
" -k -v ", | |
If[isAuth, auth[], Sequence @@ {}], | |
" -X POST https://api.github.com/gists", | |
" --data ", | |
"@", | |
stringify@jsonFile, | |
" -o ", | |
stringify@tempfile]; | |
ClearAll[createGist]; | |
createGist[content_] := | |
Module[{tempFile = fullName["temp.txt"], | |
jsonFile = fullName["gistcreate.json"]}, | |
If[FileExistsQ[#], DeleteFile[#]] & /@ {tempFile, jsonFile}; | |
If[makeTemporaryJSONFile[jsonFile, content] === $Failed, | |
Return[$Failed]]; | |
If[Run[createGistScript[tempFile, jsonFile]] != 0 || !FileExistsQ[tempFile], | |
Return[$Failed] | |
]; | |
GistObject@Import[tempFile, "JSON"]] | |
Clear[deleteGistScript]; | |
deleteGistScript[gistID_String, tempfile_String, isAuth_: True] := | |
stringify@StringJoin[ | |
stringify@$curl, | |
" -k -v ", | |
If[isAuth, auth[], Sequence @@ {}], | |
" -X DELETE https://api.github.com/gists/", | |
gistID, | |
" 2> ", | |
stringify@tempfile]; | |
ClearAll[deleteGist]; | |
deleteGist[gistID_String] := | |
Module[{tempFile = fullName["temp.txt"]}, | |
If[FileExistsQ[tempFile], DeleteFile[tempFile]]; | |
If[Run[deleteGistScript[gistID, tempFile, True]] != 0 || !FileExistsQ[tempFile], | |
Return[$Failed] | |
]; | |
(*Import[tempFile,"Text"]*) | |
If[getGist[gistID] =!= GistObject[{"message" -> "Not Found"}], | |
Return[$Failed] | |
]]; | |
ClearAll[listUserGistsScript]; | |
listUserGistsScript[user_String, tempfile_String, | |
since : (_String | Automatic) : Automatic] := | |
stringify@StringJoin[ | |
stringify@$curl, | |
" -k -v ", | |
auth[], | |
" -X GET https://api.github.com/users/", | |
user, | |
"/gists", | |
" -o ", | |
stringify@tempfile]; | |
ClearAll[listUserGists]; | |
listUserGists[user_String, | |
since : (_String | Automatic) : Automatic] := | |
Module[{tempFile = fullName["result.txt"]}, | |
If[FileExistsQ[tempFile], DeleteFile[tempFile]]; | |
If[Run[listUserGistsScript[user, tempFile, since]] != 0 || !FileExistsQ[tempFile], | |
Return[$Failed] | |
]; | |
GistObject /@ Import[tempFile, "JSON"]] | |
End[] (* End Private Context *) | |
EndPackage[] |
{ | |
"author"-> | |
{ | |
"name" -> "lshifr", | |
"email" -> "lshifr@gmail.com", | |
"url" -> "http://www.mathprogramming-intro.org" | |
}, | |
"name" -> "GithubGistClient", | |
"mathematica_version" -> "8.0+", | |
"description" -> "A Mathematica client for Github gists", | |
"url" -> "https://gist.github.com/4267071" | |
} |