Skip to content

Instantly share code, notes, and snippets.

@brianm

brianm/gist.el

Created Oct 25, 2008
Embed
What would you like to do?
;; gist.el --- Emacs integration for gist.github.com
;; Copyright (C) 2008 Christian Neukirchen <purl.org/net/chneukirchen>
;; Copyright (C) 2008 Chris Wanstrath <chris@ozmm.org>
;; Copyright (C) 2008 Will Farrington <wcfarrington@gmail.com>
;; Licensed under the same terms as Emacs.
;; Version: 0.3.1
;; 26aug2008 +wfarr+
;; 25aug2008 +defunkt+
;; 21jul2008 +chris+
;; Ideas: fork
(defvar github-username "")
(defvar github-api-key "")
(defvar gist-supported-modes-alist '((action-script-mode . "as")
(c-mode . "c")
(c++-mode . "cpp")
(common-lisp-mode . "el")
(css-mode . "css")
(diff-mode . "diff")
(emacs-lisp-mode . "el")
(erlang-mode . "erl")
(haskell-mode . "hs")
(html-mode . "html")
(io-mode . "io")
(java-mode . "java")
(javascript-mode . "js")
(jde-mode . "java")
(js2-mode . "js")
(lua-mode . "lua")
(ocaml-mode . "ml")
(objective-c-mode . "m")
(perl-mode "pl")
(php-mode . "php")
(python-mode . "sc")
(ruby-mode . "rbx")
(text-mode . "txt")
(sql-mode . "sql")
(scheme-mode . "scm")
(smalltalk-mode . "st")
(sh-mode . "sh")
(tcl-mode . "tcl")
(tex-mode . "tex")
(xml-mode . "xml")))
;;;###autoload
(defun gist-region (begin end &optional private)
"Post the current region as a new paste at gist.github.com
Copies the URL into the kill ring."
(interactive "r")
(let* ((file (or (buffer-file-name) (buffer-name)))
(name (file-name-nondirectory file))
(ext (or (cdr (assoc major-mode gist-supported-modes-alist))
(file-name-extension file)
"txt"))
(output (generate-new-buffer " *gist*"))
(login (github-auth-string))
(do-private (if private "-F private=1" "")))
(shell-command-on-region
begin end
(format (concat "curl -sS "
"%s "
"-F 'file_ext[gistfile1]=.%s' "
"-F 'file_name[gistfile1]=%s' "
"-F 'file_contents[gistfile1]=<-' "
"%s "
"http://gist.github.com/gists") login ext name do-private)
output)
(with-current-buffer output
(re-search-backward "href=\"\\(.*\\)\"")
; (re-search-backward ".*")
(message "Paste created: %s" (match-string 1))
(kill-new (match-string 1)))
(kill-buffer output)))
;;;###autoload
(defun gist-region-private (begin end)
"Post the current region as a new private paste at gist.github.com
Copies the URL into the kill ring."
(interactive "r")
(gist-region begin end t))
(defun github-raw-auth-string (user token)
"Given a username and API token, returns a curl-friendly string."
(if (and (> (length user) 0) (> (length token) 0))
(format "-F 'login=%s' -F 'token=%s'" user token)))
(defun github-config (key)
"Returns a GitHub specific value from the global Git config."
(let ((strip (lambda (string)
(if (> (length string) 0)
(substring string 0 (- (length string) 1))))))
(funcall strip (shell-command-to-string
(concat "git config --global github." key)))))
(defun github-set-config (key value)
"Sets a GitHub specific value to the global Git config."
(shell-command-to-string (format "git config --global github.%s %s" key value)))
(defun github-auth-string ()
"Returns a curl-friendly GitHub auth string.
Searches for a GitHub username and token in the global git config.
If nothing is found, prompts for the info then sets it to the git config."
(interactive)
(let* ((user (github-config "user"))
(token (github-config "token"))
(auth-string (github-raw-auth-string user token)))
(if (> (length auth-string) 0)
auth-string
(cond
((not user)
(setq user (read-string "GitHub username: "))
(github-set-config "user" user)))
(cond
((not token)
(setq token (read-string "GitHub API token: "))
(github-set-config "token" token)))
(github-raw-auth-string user token))))
;;;###autoload
(defun gist-buffer ()
"Post the current buffer as a new paste at gist.github.com.
Copies the URL into the kill ring."
(interactive)
(gist-region (point-min) (point-max)))
;;;###autoload
(defun gist-buffer-private ()
"Post the current buffer as a new private paste at gist.github.com.
Copies the URL into the kill ring."
(interactive)
(gist-region-private (point-min) (point-max)))
;;;###autoload
(defun gist-region-or-buffer ()
"Post either the current region, or if mark is not set, the current buffer as a new paste at gist.github.com
Copies the URL into the kill ring."
(interactive)
(condition-case nil
(gist-region (point) (mark))
(mark-inactive (gist-buffer))))
;;;###autoload
(defun gist-region-or-buffer-private ()
"Post either the current region, or if mark is not set, the current buffer as a new private paste at gist.github.com
Copies the URL into the kill ring."
(interactive)
(condition-case nil
(gist-region-private (point) (mark))
(mark-inactive (gist-buffer-private))))
(defvar gist-fetch-url "http://gist.github.com/%d.txt"
"Raw Gist content URL format")
;;;###autoload
(defun gist-fetch (id)
"Fetches a Gist and inserts it into a new buffer
If the Gist already exists in a buffer, switches to it"
(interactive "nGist ID: ")
(let* ((gist-buffer-name (format "*gist %d*" id))
(gist-buffer (get-buffer gist-buffer-name)))
(if (bufferp gist-buffer)
(switch-to-buffer-other-window gist-buffer)
(progn
(message "Fetching Gist %d..." id)
(setq gist-buffer
(url-retrieve-synchronously (format gist-fetch-url id)))
(with-current-buffer gist-buffer
(rename-buffer gist-buffer-name t)
(beginning-of-buffer)
(search-forward-regexp "\n\n")
(delete-region (point-min) (point))
(set-buffer-modified-p nil))
(switch-to-buffer-other-window gist-buffer)))))
(provide 'gist)
;;; gist.el ends here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment