-
Notifications
You must be signed in to change notification settings - Fork 51
/
lui-autopaste.el
149 lines (125 loc) · 5.76 KB
/
lui-autopaste.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
;;; lui-autopaste.el --- Extension for lui for long text input
;; Copyright (C) 2012 Jorgen Schaefer <[email protected]>
;; Author: Jorgen Schaefer <[email protected]>
;; This file is part of Lui.
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License
;; as published by the Free Software Foundation; either version 3
;; of the License, or (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This extension for lui will intercept long input and replace it by
;; an URL to a paste service.
;; What is considered "long" is defined by `lui-autopaste-lines'. You
;; can configure which paste service to use by changing
;; `lui-autopaste-function'.
;; Run `enable-lui-autopaste' to enable this.
;;; Code:
(require 'mm-url)
(defgroup lui-autopaste nil
"The Lui autopaste extension."
:prefix "lui-autopaste-"
:group 'lui)
(defcustom lui-autopaste-lines 3
"Starting at this number of lines, Lui will ask to paste the input."
:type 'integer
:group 'lui-autopaste)
(defcustom lui-autopaste-function 'lui-autopaste-service-0x0.st
"Which paste service to use.
This function will be called with some text as its only argument,
and is expected to return an URL to view the contents."
:type '(choice (const :tag "0x0.st" lui-autopaste-service-0x0.st)
(const :tag "ix.io" lui-autopaste-service-ixio)
(const :tag "paste.rs" lui-autopaste-service-paste.rs))
:group 'lui-autopaste)
;;;###autoload
(defun enable-lui-autopaste ()
"Enable the lui autopaste feature.
If you enter more than `lui-autopaste-lines' at once, Lui will
ask if you would prefer to use a paste service instead. If you
agree, Lui will paste your input to `lui-autopaste-function' and
replace it with the resulting URL."
(interactive)
(add-hook 'lui-pre-input-hook 'lui-autopaste))
;;;###autoload
(defun disable-lui-autopaste ()
"Disable the lui autopaste feature."
(interactive)
(remove-hook 'lui-pre-input-hook 'lui-autopaste))
(defun lui-autopaste ()
"Check if the lui input is too large. If so, paste it instead."
(when (and (>= (count-lines (point-min) (point-max))
lui-autopaste-lines)
(y-or-n-p "That's pretty long, would you like to use a paste service instead? "))
(let ((url (funcall lui-autopaste-function
(buffer-substring (point-min)
(point-max)))))
(delete-region (point-min) (point-max))
(insert url))))
(defun lui-autopaste-service-ixio (text)
"Paste TEXT to ix.io and return the paste url."
(let ((url-request-method "POST")
(url-request-extra-headers
'(("Content-Type" . "application/x-www-form-urlencoded")))
(url-request-data (format "f:1=%s" (url-hexify-string text)))
(url-http-attempt-keepalives nil))
(let ((buf (url-retrieve-synchronously "https://ix.io/")))
(unwind-protect
(with-current-buffer buf
(goto-char (point-min))
(if (re-search-forward "\n\n" nil t)
(buffer-substring (point) (line-end-position))
(error "Error during pasting to ix.io")))
(kill-buffer buf)))))
(defun lui-autopaste-service-0x0.st (text)
"Paste TEXT to 0x0.st and return the paste url."
(let* ((url-request-method "POST")
;; HACK: 0x0.st cannot parse the boundary generated by
;; `mml-make-boundary', so let's generate one like curl
(random-bytes (mapcar (lambda (_) (random 256))
(number-sequence 1 16)))
(random-bytes (base64-encode-string
(apply #'unibyte-string random-bytes)))
(random-bytes (replace-regexp-in-string "[/+=]" "" random-bytes))
(form-boundary (concat (make-string (- 46 (length random-bytes)) ?-)
random-bytes))
(url-request-extra-headers
`(("Content-Type" . ,(concat "multipart/form-data; boundary="
form-boundary))))
(url-request-data
(mm-url-encode-multipart-form-data
`(("file" . (("content-type" . "text/plain")
;; HACK: if this is unset, we get filename=nil
("filename" . "bogus.txt")
("filedata" . ,text))))
form-boundary))
(url-http-attempt-keepalives nil))
(let ((buf (url-retrieve-synchronously "https://0x0.st/")))
(unwind-protect
(with-current-buffer buf
(goto-char (point-min))
(if (re-search-forward "\n\n" nil t)
(buffer-substring (point) (line-end-position))
(error "Error during pasting to 0x0.st")))
(kill-buffer buf)))))
(defun lui-autopaste-service-paste.rs (text)
"Paste TEXT to 0x0.st and return the paste url."
(let* ((url-request-method "POST")
(url-request-extra-headers `(("Content-Type" . "text/plain")))
(url-request-data text)
(url-http-attempt-keepalives nil))
(let ((buf (url-retrieve-synchronously "https://paste.rs/")))
(unwind-protect
(with-current-buffer buf
(goto-char (point-min))
(if (re-search-forward "\n\n" nil t)
(buffer-substring (point) (line-end-position))
(error "Error during pasting to paste.rs")))
(kill-buffer buf)))))
(provide 'lui-autopaste)
;;; lui-autopaste.el ends here