-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspecify.el
126 lines (98 loc) · 4.06 KB
/
specify.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
;; -*-lexical-binding: t -*-
(require 'url)
(require 'json)
(defvar specify/http-status-line
"^HTTP/1\\.[01] \\([0-9]+\\) \\(.+\\)$")
(defvar specify/http-header-line
"^\\([^:]+\\): \\(.+\\)$")
(defun specify/status-success-p (status)
(let ((code (car status)))
(and (>= code 200) (< code 300))))
(defun specify/parse-status-line ()
(if (not (looking-at specify/http-status-line))
(message "bad http-status-line: %s"
(buffer-substring (point) (line-end-position)))
(progn
(forward-line)
(list (string-to-number (match-string 1)) (match-string 2)))))
(defun specify/parse-headers (&optional headers)
(cond ((looking-at "^\r?$") headers)
((looking-at specify/http-header-line)
(forward-line)
(let ((key (match-string 1))
(value (match-string 2)))
(when (string-match "[ \r]+$" value)
(setq value (replace-match "" t t value)))
(specify/parse-headers (cons (cons key value) headers))))
(t (error "bad http header: %s"
(buffer-substring (point) (line-end-position))))))
(defun specify/get (url)
(let ((buffer (url-retrieve-synchronously url)))
(specify/process-response url buffer)))
(defun specify/process-response (url buffer)
(with-current-buffer buffer
(unwind-protect
(progn
(goto-char (point-min))
(list url
(specify/parse-status-line)
(specify/parse-headers)
(let ((json-object-type 'hash-table))
(condition-case nil (json-read) (end-of-file nil)))))
(kill-buffer buffer))))
(defun specify/put (url data)
(let* ((url-request-method "PUT")
(url-request-extra-headers '(("Content-Type" . "application/json")))
(url-request-data (json-encode data))
(buffer (url-retrieve-synchronously url)))
(specify/process-response url buffer)))
(defvar specify/server-hist nil)
(defun specify (host)
(interactive (list (read-string "Specify server: " nil 'specify/server-hist)))
(apply 'specify/login (specify/get (concat "http://" host "/context/login/"))))
(defvar specify/username-hist nil)
(defvar specify/collection-hist nil)
(defvar specify/login-data nil)
(defun specify/login (url status headers data)
(setq specify/login-data (copy-hash-table data))
(puthash "username"
(read-from-minibuffer "Username: "
nil nil nil
'specify/username-hist)
data)
(puthash "password" (read-passwd "Password: ") data)
(let ((collections (gethash "collections" data))
(completion-ignore-case t))
(puthash "collection"
(gethash (completing-read "Collection: "
collections
nil t nil
'specify/collection-hist)
collections)
data))
(apply 'specify/complete-login (specify/put url data)))
(defvar specify/api-url nil)
(defun specify/complete-login (url status headers data)
(setq specify/api-url
(replace-regexp-in-string "/context/login/" "/api/specify/" url)))
(defun specify-logout ()
(interactive)
(if (not specify/api-url) (error "Not logged in."))
(let ((url (replace-regexp-in-string "/api/specify/" "/context/login/" specify/api-url))
(data (copy-hash-table specify/login-data)))
(puthash "username" nil data)
(apply 'specify/logout-complete (specify/put url data))))
(defun specify/logout-complete (url status headers data)
(if (not (specify/status-success-p status)) (error "Logout failed."))
(setq specify/api-url nil)
(message "Logged out."))
(defvar specify/get-uri-hist nil)
(defun specify-get (uri)
(interactive (list (read-string "URI: " nil 'specify/get-uri-hist)))
(if (not specify/api-url) (error "Not logged in.")
(apply 'specify/show-result (specify/get (concat specify/api-url uri)))))
(defun specify/show-result (url status headers data)
(with-output-to-temp-buffer url
(print status)
(print data)))
(provide 'specify)