Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/emacs-codepad/codepad.el
989 views
1
;; codepad.el --- Emacs integration for codepad.org
2
;;
3
;; Author: RĂ¼diger Sonderfeld <[email protected]>
4
;; Contributors: Thomas Weidner <[email protected]>
5
;; Website: http://github.com/ruediger/emacs-codepad
6
;; Created: <2009-11-29>
7
;; Keywords: codepad paste pastie pastebin
8
;;
9
;; This code is inspired by gist.el (written by Christian Neukirchen et.al.)
10
;; see http://github.com/defunkt/gist.el/blob/master/gist.el
11
;;
12
;; This file is NOT part of GNU Emacs.
13
;;
14
;; This is free software; you can redistribute it and/or modify it under
15
;; the terms of the GNU General Public License as published by the Free
16
;; Software Foundation; either version 2, or (at your option) any later
17
;; version.
18
;;
19
;; This is distributed in the hope that it will be useful, but WITHOUT
20
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22
;; for more details.
23
;;
24
;; You should have received a copy of the GNU General Public License
25
;; along with GNU Emacs; see the file COPYING. If not, write to the
26
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27
;; MA 02111-1307, USA.
28
29
;;; Commentary:
30
31
;; This code can be used to paste code to codepad.org.
32
33
;; codepad-paste-region pastes a region to codepad.org. The URL is printed
34
;; and if codepad-view is T opened in the browser.
35
;;
36
;; codepad-paste-buffer pastes the whole buffer.
37
38
;; TODO:
39
40
;; * fetch Output from codepad.org (if run is True)
41
;; * support projects (http://project.codepad.org)
42
;; * support user accounts
43
44
;;; Code:
45
46
(require 'cl)
47
(require 'url-http)
48
49
(defconst +codepad-url+ "http://codepad.org"
50
"Url to codepad.org.")
51
52
(defconst +codepad-lang+ '((c-mode . "C")
53
(c++-mode . "C++")
54
(d-mode . "D")
55
(haskell-mode . "Haskell")
56
(lua-mode . "Lua")
57
(ocaml-mode . "OCaml")
58
(php-mode . "PHP")
59
(perl-mode . "Perl")
60
(python-mode . "Python")
61
(ruby-mode . "Ruby")
62
(scheme-mode . "Scheme")
63
(tcl-mode . "Tcl"))
64
"Association of major-modes to language names used by codepad.org.")
65
66
(defconst +codepad-default-lang+ "Plain Text"
67
"Language if `major-mode' is not supported by codepad.org.")
68
69
(defgroup codepad nil
70
"Codepad paste support"
71
:prefix "codepad-"
72
:tag "Codepad"
73
:group 'external
74
:link '(url-link "http://github.com/ruediger/emacs-codepad"))
75
76
(defcustom codepad-private 'ask
77
"Private pastes?"
78
:group 'codepad
79
:type '(radio
80
(const :tag "Always ask" :value ask)
81
(const :tag "Check prefix" :value prefix)
82
(const :tag "No" :value no)
83
(const :tag "Yes" :value yes)))
84
85
(defcustom codepad-run 'yes
86
"Run pastes?"
87
:group 'codepad
88
:type '(radio
89
(const :tag "Always ask" :value ask)
90
(const :tag "Check prefix" :value prefix)
91
(const :tag "No" :value no)
92
(const :tag "Yes" :value yes)))
93
94
(defcustom codepad-view t
95
"View paste in browser?"
96
:group 'codepad
97
:type 'boolean)
98
99
(defcustom codepad-autoset-mode t
100
"Try to determine and set mode for fetched code?"
101
:group 'codepad
102
:type 'boolean)
103
104
(defcustom codepad-autofork t
105
"Create new pastes as a fork of `codepad-id'?"
106
:group 'codepad
107
:type 'boolean)
108
109
(defcustom codepad-use-x-clipboard t
110
"Copy URL also to the X clipboard?"
111
:group 'codepad
112
:type 'boolean)
113
114
(defvar codepad-id nil "ID on Codepad or nil. Buffer local.")
115
116
(defun codepad-read-p (prompt &optional default)
117
"Read true (t,y,true,yes) or false (nil,false,no) from the minibuffer.
118
Uses PROMPT as prompt and DEFAULT is the default value."
119
(let ((val (downcase (read-string (concat prompt " (default "
120
(if default "Yes" "No") "): ")))))
121
(cond
122
((string= val "") default)
123
((member val '("t" "y" "true" "yes")) t)
124
((member val '("nil" "f" "n" "false" "no")) nil)
125
(t (message "Wrong input '%s'! Please enter either Yes or No" val)
126
(codepad-read-p prompt default)))))
127
128
(defun codepad-interactive-option (var prompt)
129
"Handle interactive option for VAR. Use PROMPT if user is asked."
130
(case var
131
((ask) (codepad-read-p prompt))
132
((no) nil)
133
((yes) t)
134
((prefix) current-prefix-arg)
135
(t var)))
136
137
(defun codepad-true-or-false (val)
138
"Convert VAL into a string True or False."
139
(if val
140
"True"
141
"False"))
142
143
(defun codepad-url-encode (string)
144
"Encode STRING. Like `url-hexify-string' but space is turned into +."
145
(replace-regexp-in-string "%20" "+" (url-hexify-string string)))
146
147
;; copied from gist.el
148
(defun codepad-make-query-string (params)
149
"Return a query string constructed from PARAMS.
150
PARAMS should be a list with elements of the form (KEY . VALUE). KEY and VALUE
151
should both be strings."
152
(mapconcat
153
(lambda (param)
154
(concat (codepad-url-encode (car param)) "="
155
(codepad-url-encode (cdr param))))
156
params "&"))
157
158
;;;###autoload
159
(defun* codepad-paste-region (begin end
160
&optional (private 'check-custom)
161
(fork 'check-custom)
162
callback cbargs)
163
"Paste region to codepad.org.
164
If PRIVATE is set the pase will be private.
165
If FORK is set to an id the paste will be created as a fork of this paste.
166
If FORK is set to 'auto (or to check-custom and codepad-autofork is t) it
167
will fork the paste in `codepad-id'.
168
Call CALLBACK as (apply CALLBACK URL ERR-P CBARGS) where ERR-P is nil and
169
URL is the resulted url in the case of success or ERR is an error descriptor."
170
(interactive "r")
171
(let* ((codepad-url (cond
172
((and
173
(or (eql fork 'auto)
174
(and (eql fork 'check-custom)
175
codepad-autofork))
176
(stringp codepad-id))
177
(format "%s/%s/fork" +codepad-url+ codepad-id))
178
((stringp fork)
179
(format "%s/%s/fork" +codepad-url+ fork))
180
(t +codepad-url+)))
181
(private (codepad-interactive-option (if (eql private 'check-custom)
182
codepad-private
183
private)
184
"Private Paste?"))
185
(lang (or (cdr (assoc major-mode +codepad-lang+))
186
+codepad-default-lang+))
187
(run (codepad-interactive-option codepad-run "Run Paste?"))
188
(url-max-redirections 0)
189
(url-request-method "POST")
190
(url-request-extra-headers
191
'(("Content-type" . "application/x-www-form-urlencoded")))
192
(url-request-data
193
(codepad-make-query-string
194
`(("submit" . "Submit")
195
("private" . ,(codepad-true-or-false private))
196
("run" . ,(codepad-true-or-false run))
197
("lang" . ,lang)
198
("code" . ,(buffer-substring begin end))))))
199
(url-retrieve codepad-url
200
(lambda (status callback cbargs)
201
(let ((url (plist-get status :redirect))
202
(err (plist-get status :error)))
203
(when callback
204
(apply callback url err cbargs))
205
(when err
206
(signal (car err) (cdr err)))
207
(message "Paste created: %s" url)
208
(when codepad-view (browse-url url))
209
(let ((x-select-enable-clipboard
210
(or codepad-use-x-clipboard
211
x-select-enable-clipboard)))
212
(kill-new url))
213
(kill-buffer (current-buffer))
214
url))
215
(list callback cbargs))))
216
217
;;;###autoload
218
(defun* codepad-paste-buffer (&optional
219
(private 'check-custom)
220
(fork 'check-custom)
221
callback cbargs)
222
"Paste buffer to codepad.org. See `codepad-paste-region'."
223
(interactive)
224
(codepad-paste-region (point-min) (point-max) private callback cbargs))
225
226
(defconst +codepad-mime-to-mode+ '(("c++src" . c++-mode)
227
("csrc" . c-mode)
228
("dsrc" . d-mode)
229
("haskell" . haskell-mode)
230
("lua" . lua-mode)
231
("ocaml" . ocaml-mode)
232
("php" . php-mode)
233
("perl" . perl-mode)
234
("python" . python-mode)
235
("ruby" . ruby-mode)
236
("scheme" . scheme-mode)
237
("tcl" . tcl-mode))
238
"MIME text/x-... to emacs mode.")
239
240
;; stuff from url-http.el
241
(defvar url-http-content-type)
242
(defvar url-http-end-of-headers)
243
244
;;;###autoload
245
(defun codepad-fetch-code (id &optional buffer-name)
246
"Fetch code from codepad.org.
247
Argument ID is the codepad id and
248
optional argument is the BUFFER-NAME where to write."
249
(interactive "sCodepad ID: ")
250
(let* ((just-id (replace-regexp-in-string "^.*/" "" id)) ; strip http://...
251
(buffer-name (or buffer-name (format "*codepad %s*" just-id)))
252
(url (concat +codepad-url+ "/" just-id "/raw"))
253
(buffer (get-buffer buffer-name)))
254
(if (bufferp buffer)
255
(pop-to-buffer buffer)
256
257
(message "Fetching %s from Codepad" just-id)
258
(url-retrieve url
259
(lambda (status buffer-name just-id)
260
(let ((err (plist-get status :error)))
261
(when err
262
(signal (car err) (cdr err))))
263
(rename-buffer buffer-name t)
264
265
;; set codepad-id to the id
266
(make-local-variable 'codepad-id)
267
(setq codepad-id just-id)
268
269
;; Delete Headers
270
(delete-region (point-min) url-http-end-of-headers)
271
272
;; Determine and set mode
273
(if (and codepad-autoset-mode
274
url-http-content-type
275
(string-match "text/x-\\([^;[:space:]]*\\)"
276
url-http-content-type))
277
(let ((mode
278
(cdr (assoc
279
(match-string 1 url-http-content-type)
280
+codepad-mime-to-mode+))))
281
(if mode
282
(funcall mode)
283
(fundamental-mode)))
284
(fundamental-mode))
285
(set-buffer-modified-p nil)
286
(pop-to-buffer (current-buffer)))
287
(list buffer-name just-id)))))
288
289
(provide 'codepad)
290
;;; codepad.el ends here
291
292