summaryrefslogtreecommitdiff
path: root/modules/restclient-config.el
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