blob: 650bb781971e6a08521d2e026c68a723a11e8a2d (
plain)
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
|
;;; restclient-config.el --- REST API Client Configuration -*- lexical-binding: t; coding: utf-8; -*-
;; author: Craig Jennings <c@cjennings.net>
;;; Commentary:
;; Integrates restclient.el for interactive API exploration from within Emacs.
;;
;; Write HTTP requests in plain text buffers, execute with C-c C-c, see
;; results inline. Supports .rest files with variable substitution for
;; reusable API templates.
;;
;; Includes SkyFi satellite imagery API integration with automatic key
;; injection from authinfo.gpg (key never stored on disk).
;;
;; Keybindings (C-; R prefix):
;; - C-; R n : New scratch *restclient* buffer
;; - C-; R o : Open a .rest file (defaults to data/)
;; - C-; R s : Open SkyFi API template
;;; Code:
;; --------------------------------- Constants ---------------------------------
(defvar cj/restclient-data-dir (expand-file-name "data/" user-emacs-directory)
"Directory containing .rest API template files.")
;; -------------------------------- use-package --------------------------------
(use-package restclient
:ensure t
:defer t
:mode ("\\.rest\\'" . restclient-mode))
(use-package restclient-jq
:ensure t
:if (executable-find "jq")
:after restclient)
;; ----------------------------- Private Helpers -------------------------------
(defun cj/restclient--inject-skyfi-key ()
"Replace the :skyfi-key variable line with the real key from authinfo.
Only acts when the buffer is in `restclient-mode', the filename ends
in \"skyfi-api.rest\", and a :skyfi-key line exists. If the auth
lookup returns nil, leaves the buffer unchanged."
(when (and (derived-mode-p 'restclient-mode)
buffer-file-name
(string-match-p "skyfi-api\\.rest\\'" buffer-file-name))
(let ((key (condition-case nil
(cj/skyfi-api-key)
(error nil))))
(when key
(save-excursion
(goto-char (point-min))
(when (re-search-forward "^:skyfi-key = .*$" nil t)
(replace-match (format ":skyfi-key = %s" key))))))))
;; ----------------------------- Public Functions ------------------------------
(defun cj/skyfi-api-key ()
"Fetch SkyFi API key from authinfo.gpg."
(cj/auth-source-secret "app.skyfi.com" "apikey"))
(defun cj/restclient-new-buffer ()
"Open a scratch *restclient* buffer in `restclient-mode'."
(interactive)
(let ((buf (get-buffer-create "*restclient*")))
(switch-to-buffer buf)
(unless (derived-mode-p 'restclient-mode)
(restclient-mode))))
(defun cj/restclient-open-file ()
"Prompt for a .rest file to open, defaulting to the data/ directory."
(interactive)
(let ((file (read-file-name "Open .rest file: " cj/restclient-data-dir nil t nil
(lambda (f)
(or (file-directory-p f)
(string-match-p "\\.rest\\'" f))))))
(find-file file)))
(defun cj/restclient-skyfi-buffer ()
"Open the SkyFi API template file.
Runs the key-injection hook after opening."
(interactive)
(let ((skyfi-file (expand-file-name "skyfi-api.rest" cj/restclient-data-dir)))
(unless (file-exists-p skyfi-file)
(user-error "SkyFi template not found: %s" skyfi-file))
(find-file skyfi-file)
(cj/restclient--inject-skyfi-key)))
;; -------------------------------- Keybindings --------------------------------
(global-set-key (kbd "C-; R n") #'cj/restclient-new-buffer)
(global-set-key (kbd "C-; R o") #'cj/restclient-open-file)
(global-set-key (kbd "C-; R s") #'cj/restclient-skyfi-buffer)
(with-eval-after-load 'which-key
(which-key-add-key-based-replacements
"C-; R" "REST client"
"C-; R n" "new scratch buffer"
"C-; R o" "open .rest file"
"C-; R s" "SkyFi API template"))
(provide 'restclient-config)
;;; restclient-config.el ends here
|