emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/plz-see bdcc265ce9 01/10: Initial commit


From: ELPA Syncer
Subject: [elpa] externals/plz-see bdcc265ce9 01/10: Initial commit
Date: Wed, 1 Nov 2023 18:58:45 -0400 (EDT)

branch: externals/plz-see
commit bdcc265ce99601bdb411b2b00fb2d778429d7c3b
Author: Augusto Stoffel <arstoffel@gmail.com>
Commit: Augusto Stoffel <arstoffel@gmail.com>

    Initial commit
---
 plzi.el | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 240 insertions(+)

diff --git a/plzi.el b/plzi.el
new file mode 100644
index 0000000000..818a61ccc7
--- /dev/null
+++ b/plzi.el
@@ -0,0 +1,240 @@
+;;; plzi.el --- Interactive HTTP client              -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2023  Augusto Stoffel
+
+;; Author: Augusto Stoffel <arstoffel@gmail.com>
+;; Keywords: comm, network, http
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; 
+
+;;; Code:
+
+(require 'json)
+(require 'plz)
+
+;;; User options and variables
+
+(defgroup plzi nil
+  "Interactive HTTP client."
+  :group 'plz
+  :link '(url-link "https://github.com/astoff/plzi.el";))
+
+(defcustom plzi-base-url nil
+  "Prefix to add to the URL argument of `plzi', if relative.
+Here \"relative\" means, paradoxically, that the URL in question
+starts with '/'."
+  :local t
+  :type '(choice string (const :tag "None" nil))
+  :safe #'stringp)
+
+(defcustom plzi-base-headers nil
+  "List of headers to add to all requests.
+Entries of this alist are ignored if the same header is given
+explicitly in the HEADERS argument of `plzi'."
+  :local t
+  :type '(alist :key-type string :value-type string)
+  :safe #'listp)
+
+(defcustom plzi-keep-buffers 10
+  "How many response buffers to keep.
+If nil, never delete old response buffers."
+  :type '(choice natnum (const :tag "Keep all" nil)))
+
+(defcustom plzi-display-action nil
+  "The ACTION argument `plzi' passes to `display-buffer'."
+  :type 'sexp)
+
+(defcustom plzi-header-line-format
+  (let ((headers '(plzi-header-line-status
+                   plzi-header-line-content-type
+                   plzi-header-line-content-length
+                   plzi-header-line-show-headers)))
+    (dolist (sym headers)
+      (put sym 'risky-local-variable t))
+    (cons "" headers))
+  "Header line format for plzi result buffers."
+  :type 'sexp)
+
+(defcustom plzi-headers-buffer nil
+  "Buffer used to display request headers.
+This can be nil to add the headers to the response buffer itself,
+or a buffer name to use a separate buffer."
+  :type 'sexp)
+
+(defface plzi-header '((t :inherit font-lock-comment-face))
+  "Face added by `plzi-insert-headers' to response headers.")
+
+(defcustom plzi-content-type-alist
+  `(("\\`text/html" . html-mode)
+    ("\\`\\(application\\|text\\)/xml" . xml-mode)
+    ("\\`application/xhtml\\+xml" . xml-mode)
+    ("\\`application/json" . ,(lambda ()
+                                (json-pretty-print-buffer)
+                                (js-json-mode)))
+    ("\\`application/javascript" . js-mode)
+    ("\\`application/css" . css-mode)
+    ("\\`text/plain" . text-mode)
+    ("\\`application/pdf" . doc-view-mode)
+    ("\\`image/" . image-mode))
+  "Alist mapping content types to rendering functions."
+  :type '(alist :key-type regexp
+                :value-type function))
+
+(defvar-local plzi-response nil
+  "Store the `plz-response' object in a plzi buffer.")
+
+(defvar plzi--buffers '(0 . nil)
+  "List of buffers generated by `plzi'.
+The car is the number of buffers created so far.")
+
+;;; Response buffer header line
+
+(defvar plzi-header-line-status
+  '(:eval
+    (setq-local plzi-header-line-status
+                (format "HTTP/%s %s"
+                        (plz-response-version plzi-response)
+                        (let ((status (plz-response-status plzi-response)))
+                          (propertize (number-to-string status)
+                                      'face (if (<= 200 status 299) 'success 
'error)))))))
+
+(defvar plzi-header-line-content-type
+  '(:eval
+    (setq-local plzi-header-line-content-type
+                (format " | %s"
+                        (alist-get 'content-type
+                                   (plz-response-headers plzi-response))))))
+
+(defvar plzi-header-line-content-length
+  '(:eval
+    (setq-local plzi-header-line-content-length
+                (format " | %s bytes"
+                        (alist-get 'content-length
+                                   (plz-response-headers plzi-response))))))
+
+(defvar plzi-header-line-show-headers
+  '(:eval
+    (setq-local plzi-header-line-show
+                (format " | %s"
+                        (buttonize "show headers"
+                                   (lambda (buffer)
+                                     (with-selected-window (get-buffer-window 
buffer)
+                                       (plzi-insert-headers)))
+                                   (current-buffer))))))
+
+;;; Response buffer construction
+
+(defun plzi--prepare-buffer (response)
+  (let* ((buffer (generate-new-buffer
+                  (format "*plzi-%s*" (cl-incf (car plzi--buffers)))))
+         (error (and (plz-error-p response) response))
+         (response (if error (plz-error-response error) response))
+         (headers (plz-response-headers response))
+         (mode (alist-get (alist-get 'content-type headers)
+                          plzi-content-type-alist
+                          nil nil #'string-match-p))
+         (body (plz-response-body response)))
+    (with-current-buffer buffer
+      (save-excursion
+        (insert body)
+        (when mode (funcall mode)))
+      (setq-local plzi-response response)
+      (setq header-line-format plzi-header-line-format)
+      (push buffer (cdr plzi--buffers))
+      (when-let ((oldbufs (and plzi-keep-buffers
+                               (seq-drop (cdr plzi--buffers)
+                                         (1- plzi-keep-buffers)))))
+        (dolist (b (cdr oldbufs))
+          (kill-buffer b))
+        (setf (cdr oldbufs) nil))
+      buffer)))
+
+(defun plzi--continue (as continue)
+  (lambda (response)
+    (if-let ((curl-error (and (plz-error-p response)
+                              (plz-error-curl-error response))))
+        (message "curl error %s: %s" (car curl-error) (cdr curl-error))
+      (let ((buffer (plzi--prepare-buffer response)))
+        (display-buffer buffer plzi-display-action)
+        (when continue
+          (funcall continue
+                   (pcase-exhaustive as
+                     ('response response)
+                     ('buffer buffer)
+                     ((or 'binary 'string 'file `(file ,_))
+                      (user-error "plzi does not accept :as %s" as))
+                     ((pred functionp)
+                      (with-temp-buffer
+                        (insert (plz-response-body response))
+                        (goto-char (point-min))
+                        (funcall as))))))))))
+
+;;; User commands
+
+(defun plzi-kill-old-buffers (n)
+  "Kill all but the N most recent plzi buffers.
+Interactively, N is the prefix argument."
+  (interactive "p")
+  (let ((buffers (seq-drop plzi--buffers n)))
+    (dolist (buffer (cdr buffers))
+      (kill-buffer buffer))
+    (setf (cdr buffers) nil)))
+
+(defun plzi-insert-headers ()
+  "Insert response headers into `plzi-headers-buffer'."
+  (interactive)
+  (let ((headers (plz-response-headers plzi-response))
+        (hbuffer (when plzi-headers-buffer
+                    (get-buffer-create plzi-headers-buffer))))
+    (with-current-buffer (or hbuffer (current-buffer))
+      (let ((inhibit-read-only t))
+        (save-excursion
+          (goto-char (point-min))
+          (pcase-dolist (`(,k . ,v) headers)
+            (insert (format "%s: %s\n" k v)))
+          (insert ?\n)
+          (add-text-properties (point-min) (point)
+                               '(face plzi-header
+                                 font-lock-face plzi-header
+                                 fontified t)))))
+    (if hbuffer
+        (display-buffer hbuffer)
+      (setq-local plzi-header-line-show-headers nil))))
+
+;;;###autoload
+(cl-defun plzi (method
+                url
+                &rest rest
+                &key headers then else as
+                &allow-other-keys)
+  (interactive `(get ,(read-from-minibuffer "Make GET request: ")))
+  (when (and plzi-base-url
+             (string-prefix-p "/" url))
+    (setq url (concat plzi-base-url url)))
+  (dolist (h plzi-base-headers)
+    (unless (assoc (car h) headers)
+      (push h headers)))
+  (apply #'plz method url
+         :headers headers
+         :as 'response
+         :then (plzi--continue as then)
+         :else (plzi--continue as else)
+         rest))
+
+(provide 'plzi)
+;;; plzi.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]