From bb5cbdd33dd2b4268012011cfaeff34fd7d5c198 Mon Sep 17 00:00:00 2001 From: Levi Olson Date: Mon, 26 Jul 2021 10:28:21 -0500 Subject: [PATCH] Remove local vs-restclient work --- custom/leo-restclient.el | 791 --------------------------------------- 1 file changed, 791 deletions(-) delete mode 100644 custom/leo-restclient.el diff --git a/custom/leo-restclient.el b/custom/leo-restclient.el deleted file mode 100644 index e76c1de..0000000 --- a/custom/leo-restclient.el +++ /dev/null @@ -1,791 +0,0 @@ -;;; custom/leo-restclient.el -*- lexical-binding: t; -*- - -;;; leo/restclient.el --- An interactive HTTP client for Emacs -;; -;; Public domain. - -;; Author: Pavel Kurnosov -;; Maintainer: Pavel Kurnosov -;; Created: 01 Apr 2012 -;; Keywords: http - -;; This file is not part of GNU Emacs. -;; This file is public domain software. Do what you want. - -;;; Commentary: -;; -;; This is a tool to manually explore and test HTTP REST -;; webservices. Runs queries from a plain-text query sheet, displays -;; results as a pretty-printed XML, JSON and even images. - -;;; Code: -;; -(require 'url) -(require 'json) -(require 'outline) -(eval-when-compile (require 'subr-x)) -(eval-when-compile (require 'cl)) - -(defgroup leo/restclient nil - "An interactive HTTP client for Emacs." - :group 'tools) - -(defcustom leo/restclient-log-request t - "Log leo/restclient requests to *Messages*." - :group 'leo/restclient - :type 'boolean) - -(defcustom leo/restclient-same-buffer-response t - "Re-use same buffer for responses or create a new one each time." - :group 'leo/restclient - :type 'boolean) - -(defcustom leo/restclient-same-buffer-response-name "*HTTP Response*" - "Name for response buffer." - :group 'leo/restclient - :type 'string) - -(defcustom leo/restclient-info-buffer-name "*Leo/Restclient Info*" - "Name for info buffer." - :group 'leo/restclient - :type 'string) - -(defcustom leo/restclient-inhibit-cookies nil - "Inhibit leo/restclient from sending cookies implicitly." - :group 'leo/restclient - :type 'boolean) - -(defcustom leo/restclient-content-type-modes '(("text/xml" . xml-mode) - ("text/plain" . text-mode) - ("application/xml" . xml-mode) - ("application/json" . js-mode) - ("image/png" . image-mode) - ("image/jpeg" . image-mode) - ("image/jpg" . image-mode) - ("image/gif" . image-mode) - ("text/html" . html-mode)) - "An association list mapping content types to buffer modes" - :group 'leo/restclient - :type '(alist :key-type string :value-type symbol)) - -(defgroup leo/restclient-faces nil - "Faces used in Leo/Restclient Mode" - :group 'leo/restclient - :group 'faces) - -(defface leo/restclient-variable-name-face - '((t (:inherit font-lock-preprocessor-face))) - "Face for variable name." - :group 'leo/restclient-faces) - -(defface leo/restclient-variable-string-face - '((t (:inherit font-lock-string-face))) - "Face for variable value (string)." - :group 'leo/restclient-faces) - -(defface leo/restclient-variable-elisp-face - '((t (:inherit font-lock-function-name-face))) - "Face for variable value (Emacs lisp)." - :group 'leo/restclient-faces) - -(defface leo/restclient-variable-multiline-face - '((t (:inherit font-lock-doc-face))) - "Face for multi-line variable value marker." - :group 'leo/restclient-faces) - -(defface leo/restclient-variable-usage-face - '((t (:inherit leo/restclient-variable-name-face))) - "Face for variable usage (only used when headers/body is represented as a single variable, not highlighted when variable appears in the middle of other text)." - :group 'leo/restclient-faces) - -(defface leo/restclient-method-face - '((t (:inherit font-lock-keyword-face))) - "Face for HTTP method." - :group 'leo/restclient-faces) - -(defface leo/restclient-url-face - '((t (:inherit font-lock-function-name-face))) - "Face for variable value (Emacs lisp)." - :group 'leo/restclient-faces) - -(defface leo/restclient-file-upload-face - '((t (:inherit leo/restclient-variable-multiline-face))) - "Face for highlighting upload file paths." - :group 'leo/restclient-faces) - -(defface leo/restclient-header-name-face - '((t (:inherit font-lock-variable-name-face))) - "Face for HTTP header name." - :group 'leo/restclient-faces) - -(defface leo/restclient-header-value-face - '((t (:inherit font-lock-string-face))) - "Face for HTTP header value." - :group 'leo/restclient-faces) - -(defface leo/restclient-request-hook-face - '((t (:inherit font-lock-preprocessor-face))) - "Face for single request hook indicator." - :group 'leo/restclient-faces) - -(defface leo/restclient-request-hook-name-face - '((t (:inherit font-lock-function-name-face))) - "Face for single request hook type names." - :group 'leo/restclient-faces) - -(defface leo/restclient-request-hook-args-face - '((t (:inherit font-lock-string-face))) - "Face for single request hook type arguments." - :group 'leo/restclient-faces) - - -(defvar leo/restclient-within-call nil) - -(defvar leo/restclient-request-time-start nil) -(defvar leo/restclient-request-time-end nil) - -(defvar leo/restclient-var-overrides nil - "An alist of vars that will override any set in the file, - also where dynamic vars set on callbacks are stored.") - -(defvar leo/restclient-result-handlers '() - "A registry of available completion hooks. - Stored as an alist of name -> (hook-creation-func . description)") - -(defvar leo/restclient-curr-request-functions nil - "A list of functions to run once when the next request is loaded") - -(defvar leo/restclient-response-loaded-hook nil - "Hook run after response buffer is formatted.") - -(defvar leo/restclient-http-do-hook nil - "Hook to run before making request.") - -(defvar leo/restclient-response-received-hook nil - "Hook run after data is loaded into response buffer.") - -(defcustom leo/restclient-vars-max-passes 10 - "Maximum number of recursive variable references. This is to prevent hanging if two variables reference each other directly or indirectly." - :group 'leo/restclient - :type 'integer) - -(defconst leo/restclient-comment-separator "#") -(defconst leo/restclient-comment-start-regexp (concat "^" leo/restclient-comment-separator)) -(defconst leo/restclient-comment-not-regexp (concat "^[^" leo/restclient-comment-separator "]")) -(defconst leo/restclient-empty-line-regexp "^\\s-*$") - -(defconst leo/restclient-method-url-regexp - "^\\(GET\\|POST\\|DELETE\\|PUT\\|HEAD\\|OPTIONS\\|PATCH\\) \\(.*\\)$") - -(defconst leo/restclient-header-regexp - "^\\([^](),/:;@[\\{}= \t]+\\): \\(.*\\)$") - -(defconst leo/restclient-use-var-regexp - "^\\(:[^: \n]+\\)$") - -(defconst leo/restclient-var-regexp - (concat "^\\(:[^:= ]+\\)[ \t]*\\(:?\\)=[ \t]*\\(<<[ \t]*\n\\(\\(.*\n\\)*?\\)" leo/restclient-comment-separator "\\|\\([^<].*\\)$\\)")) - -(defconst leo/restclient-svar-regexp - "^\\(:[^:= ]+\\)[ \t]*=[ \t]*\\(.+?\\)$") - -(defconst leo/restclient-evar-regexp - "^\\(:[^: ]+\\)[ \t]*:=[ \t]*\\(.+?\\)$") - -(defconst leo/restclient-mvar-regexp - "^\\(:[^: ]+\\)[ \t]*:?=[ \t]*\\(<<\\)[ \t]*$") - -(defconst leo/restclient-file-regexp - "^<[ \t]*\\([^<>\n\r]+\\)[ \t]*$") - -(defconst leo/restclient-content-type-regexp - "^Content-[Tt]ype: \\(\\w+\\)/\\(?:[^\\+\r\n]*\\+\\)*\\([^;\r\n]+\\)") - -(defconst leo/restclient-response-hook-regexp - "^\\(->\\) \\([^[:space:]]+\\) +\\(.*\\)$") - -;; The following disables the interactive request for user name and -;; password should an API call encounter a permission-denied response. -;; This API is meant to be usable without constant asking for username -;; and password. -(defadvice url-http-handle-authentication (around leo/restclient-fix) - (if leo/restclient-within-call - (setq ad-return-value t) - ad-do-it)) -(ad-activate 'url-http-handle-authentication) - -(defadvice url-cache-extract (around leo/restclient-fix-2) - (unless leo/restclient-within-call - ad-do-it)) -(ad-activate 'url-cache-extract) - -(defadvice url-http-user-agent-string (around leo/restclient-fix-3) - (if leo/restclient-within-call - (setq ad-return-value nil) - ad-do-it)) -(ad-activate 'url-http-user-agent-string) - -(defun leo/restclient-http-do (method url headers entity &rest handle-args) - "Send ENTITY and HEADERS to URL as a METHOD request." - (if leo/restclient-log-request - (message "HTTP %s %s Headers:[%s] Body:[%s]" method url headers entity)) - (let ((url-request-method (encode-coding-string method 'us-ascii)) - (url-request-extra-headers '()) - (url-request-data (encode-coding-string entity 'utf-8)) - (url-mime-charset-string (url-mime-charset-string)) - (url-mime-language-string nil) - (url-mime-encoding-string nil) - (url-mime-accept-string nil) - (url-personal-mail-address nil)) - - (dolist (header headers) - (let* ((mapped (assoc-string (downcase (car header)) - '(("from" . url-personal-mail-address) - ("accept-encoding" . url-mime-encoding-string) - ("accept-charset" . url-mime-charset-string) - ("accept-language" . url-mime-language-string) - ("accept" . url-mime-accept-string))))) - - (if mapped - (set (cdr mapped) (encode-coding-string (cdr header) 'us-ascii)) - (let* ((hkey (encode-coding-string (car header) 'us-ascii)) - (hvalue (encode-coding-string (cdr header) 'us-ascii))) - (setq url-request-extra-headers (cons (cons hkey hvalue) url-request-extra-headers)))))) - - (setq leo/restclient-within-call t) - (setq leo/restclient-request-time-start (current-time)) - (run-hooks 'leo/restclient-http-do-hook) - (url-retrieve url 'leo/restclient-http-handle-response - (append (list method url (if leo/restclient-same-buffer-response - leo/restclient-same-buffer-response-name - (format "*HTTP %s %s*" method url))) handle-args) nil leo/restclient-inhibit-cookies))) - -(defun leo/restclient-prettify-response (method url) - (save-excursion - (let ((start (point)) (guessed-mode) (end-of-headers)) - (while (and (not (looking-at leo/restclient-empty-line-regexp)) - (eq (progn - (when (looking-at leo/restclient-content-type-regexp) - (setq guessed-mode - (cdr (assoc-string (concat - (match-string-no-properties 1) - "/" - (match-string-no-properties 2)) - leo/restclient-content-type-modes - t)))) - (forward-line)) 0))) - (setq end-of-headers (point)) - (while (and (looking-at leo/restclient-empty-line-regexp) - (eq (forward-line) 0))) - (unless guessed-mode - (setq guessed-mode - (or (assoc-default nil - ;; magic mode matches - '(("<\\?xml " . xml-mode) - ("{\\s-*\"" . js-mode)) - (lambda (re _dummy) - (looking-at re))) 'js-mode))) - (let ((headers (buffer-substring-no-properties start end-of-headers))) - (when guessed-mode - (delete-region start (point)) - (unless (eq guessed-mode 'image-mode) - (apply guessed-mode '()) - (if (fboundp 'font-lock-flush) - (font-lock-flush) - (with-no-warnings - (font-lock-fontify-buffer)))) - - (cond - ((eq guessed-mode 'xml-mode) - (goto-char (point-min)) - (while (search-forward-regexp "\>[ \\t]*\<" nil t) - (backward-char) (insert "\n")) - (indent-region (point-min) (point-max))) - - ((eq guessed-mode 'image-mode) - (let* ((img (buffer-string))) - (delete-region (point-min) (point-max)) - (fundamental-mode) - (insert-image (create-image img nil t)))) - - ((eq guessed-mode 'js-mode) - (let ((json-special-chars (remq (assoc ?/ json-special-chars) json-special-chars)) - ;; Emacs 27 json.el uses `replace-buffer-contents' for - ;; pretty-printing which is great because it keeps point and - ;; markers intact but can be very slow with huge minimalized - ;; JSON. We don't need that here. - (json-pretty-print-max-secs 0)) - (ignore-errors (json-pretty-print-buffer))) - (leo/restclient-prettify-json-unicode))) - - (goto-char (point-max)) - (or (eq (point) (point-min)) (insert "\n")) - (let ((hstart (point))) - (insert method " " url "\n" headers) - (insert (format "Request duration: %fs\n" (float-time (time-subtract leo/restclient-request-time-end leo/restclient-request-time-start)))) - (unless (member guessed-mode '(image-mode text-mode)) - (comment-region hstart (point))))))))) - -(defun leo/restclient-prettify-json-unicode () - (save-excursion - (goto-char (point-min)) - (while (re-search-forward "\\\\[Uu]\\([0-9a-fA-F]\\{4\\}\\)" nil t) - (replace-match (char-to-string (decode-char 'ucs (string-to-number (match-string 1) 16))) t nil)))) - -(defun leo/restclient-http-handle-response (status method url bufname raw stay-in-window) - "Switch to the buffer returned by `url-retreive'. -The buffer contains the raw HTTP response sent by the server." - (setq leo/restclient-within-call nil) - (setq leo/restclient-request-time-end (current-time)) - (if (= (point-min) (point-max)) - (signal (car (plist-get status :error)) (cdr (plist-get status :error))) - (when (buffer-live-p (current-buffer)) - (with-current-buffer (leo/restclient-decode-response - (current-buffer) - bufname - leo/restclient-same-buffer-response) - (run-hooks 'leo/restclient-response-received-hook) - (unless raw - (leo/restclient-prettify-response method url)) - (buffer-enable-undo) - (leo/restclient-response-mode) - (run-hooks 'leo/restclient-response-loaded-hook) - (if stay-in-window - (display-buffer (current-buffer) t) - (switch-to-buffer-other-window (current-buffer))))))) - -(defun leo/restclient-decode-response (raw-http-response-buffer target-buffer-name same-name) - "Decode the HTTP response using the charset (encoding) specified in the Content-Type header. If no charset is specified, default to UTF-8." - (let* ((charset-regexp "^Content-Type.*charset=\\([-A-Za-z0-9]+\\)") - (image? (save-excursion - (search-forward-regexp "^Content-Type.*[Ii]mage" nil t))) - (encoding (if (save-excursion - (search-forward-regexp charset-regexp nil t)) - (intern (downcase (match-string 1))) - 'utf-8))) - (if image? - ;; Dont' attempt to decode. Instead, just switch to the raw HTTP response buffer and - ;; rename it to target-buffer-name. - (with-current-buffer raw-http-response-buffer - ;; We have to kill the target buffer if it exists, or `rename-buffer' - ;; will raise an error. - (when (get-buffer target-buffer-name) - (kill-buffer target-buffer-name)) - (rename-buffer target-buffer-name) - raw-http-response-buffer) - ;; Else, switch to the new, empty buffer that will contain the decoded HTTP - ;; response. Set its encoding, copy the content from the unencoded - ;; HTTP response buffer and decode. - (let ((decoded-http-response-buffer - (get-buffer-create - (if same-name target-buffer-name (generate-new-buffer-name target-buffer-name))))) - (with-current-buffer decoded-http-response-buffer - (setq buffer-file-coding-system encoding) - (save-excursion - (erase-buffer) - (insert-buffer-substring raw-http-response-buffer)) - (kill-buffer raw-http-response-buffer) - (condition-case nil - (decode-coding-region (point-min) (point-max) encoding) - (error - (message (concat "Error when trying to decode http response with encoding: " - (symbol-name encoding))))) - decoded-http-response-buffer))))) - -(defun leo/restclient-current-min () - (save-excursion - (beginning-of-line) - (if (looking-at leo/restclient-comment-start-regexp) - (if (re-search-forward leo/restclient-comment-not-regexp (point-max) t) - (point-at-bol) (point-max)) - (if (re-search-backward leo/restclient-comment-start-regexp (point-min) t) - (point-at-bol 2) - (point-min))))) - -(defun leo/restclient-current-max () - (save-excursion - (if (re-search-forward leo/restclient-comment-start-regexp (point-max) t) - (max (- (point-at-bol) 1) 1) - (progn (goto-char (point-max)) - (if (looking-at "^$") (- (point) 1) (point)))))) - -(defun leo/restclient-replace-all-in-string (replacements string) - (if replacements - (let ((current string) - (pass leo/restclient-vars-max-passes) - (continue t)) - (while (and continue (> pass 0)) - (setq pass (- pass 1)) - (setq current (replace-regexp-in-string (regexp-opt (mapcar 'car replacements)) - (lambda (key) - (setq continue t) - (cdr (assoc key replacements))) - current t t))) - current) - string)) - -(defun leo/restclient-replace-all-in-header (replacements header) - (cons (car header) - (leo/restclient-replace-all-in-string replacements (cdr header)))) - -(defun leo/restclient-chop (text) - (if text (replace-regexp-in-string "\n$" "" text) nil)) - -(defun leo/restclient-find-vars-before-point () - (let ((vars nil) - (bound (point))) - (save-excursion - (goto-char (point-min)) - (while (search-forward-regexp leo/restclient-var-regexp bound t) - (let ((name (match-string-no-properties 1)) - (should-eval (> (length (match-string 2)) 0)) - (value (or (leo/restclient-chop (match-string-no-properties 4)) (match-string-no-properties 3)))) - (setq vars (cons (cons name (if should-eval (leo/restclient-eval-var value) value)) vars)))) - (append leo/restclient-var-overrides vars)))) - -(defun leo/restclient-eval-var (string) - (with-output-to-string (princ (eval (read string))))) - -(defun leo/restclient-make-header (&optional string) - (cons (match-string-no-properties 1 string) - (match-string-no-properties 2 string))) - -(defun leo/restclient-parse-headers (string) - (let ((start 0) - (headers '())) - (while (string-match leo/restclient-header-regexp string start) - (setq headers (cons (leo/restclient-make-header string) headers) - start (match-end 0))) - headers)) - -(defun leo/restclient-read-file (path) - (with-temp-buffer - (insert-file-contents path) - (buffer-string))) - -(defun leo/restclient-parse-body (entity vars) - (if (= 0 (or (string-match leo/restclient-file-regexp entity) 1)) - (leo/restclient-read-file (match-string 1 entity)) - (leo/restclient-replace-all-in-string vars entity))) - -(defun leo/restclient-parse-hook (cb-type args-offset args) - (if-let ((handler (assoc cb-type leo/restclient-result-handlers))) - (funcall (cadr handler) args args-offset) - `(lambda () - (message "Unknown leo/restclient hook type %s" ,cb-type)))) - -(defun leo/restclient-register-result-func (name creation-func description) - (let ((new-cell (cons name (cons creation-func description)))) - (setq leo/restclient-result-handlers (cons new-cell leo/restclient-result-handlers)))) - -(defun leo/restclient-remove-var (var-name) - (setq leo/restclient-var-overrides (assoc-delete-all var-name leo/restclient-var-overrides))) - -(defun leo/restclient-set-var (var-name value) - (leo/restclient-remove-var var-name) - (setq leo/restclient-var-overrides (cons (cons var-name value) leo/restclient-var-overrides))) - -(defun leo/restclient-get-var-at-point (var-name buffer-name buffer-pos) - (message (format "getting var %s form %s at %s" var-name buffer-name buffer-pos)) - (let* ((vars-at-point (save-excursion - (switch-to-buffer buffer-name) - (goto-char buffer-pos) - ;; if we're called from a leo/restclient buffer we need to lookup vars before the current hook or evar - ;; outside a leo/restclient buffer only globals are available so moving the point wont matter - (re-search-backward "^:\\|->" (point-min) t) - (leo/restclient-find-vars-before-point)))) - (leo/restclient-replace-all-in-string vars-at-point (cdr (assoc var-name vars-at-point))))) - -(defmacro leo/restclient-get-var (var-name) - (lexical-let ((buf-name (buffer-name (current-buffer))) - (buf-point (point))) - `(leo/restclient-get-var-at-point ,var-name ,buf-name ,buf-point))) - -(defun leo/restclient-single-request-function () - (dolist (f leo/restclient-curr-request-functions) - (ignore-errors - (funcall f))) - (setq leo/restclient-curr-request-functions nil) - (remove-hook 'leo/restclient-response-loaded-hook 'leo/restclient-single-request-function)) - - -(defun leo/restclient-http-parse-current-and-do (func &rest args) - (save-excursion - (goto-char (leo/restclient-current-min)) - (when (re-search-forward leo/restclient-method-url-regexp (point-max) t) - (let ((method (match-string-no-properties 1)) - (url (match-string-no-properties 2)) - (vars (leo/restclient-find-vars-before-point)) - (headers '())) - (forward-line) - (while (cond - ((looking-at leo/restclient-response-hook-regexp) - (when-let (hook-function (leo/restclient-parse-hook (match-string-no-properties 2) - (match-end 2) - (match-string-no-properties 3))) - (push hook-function leo/restclient-curr-request-functions))) - ((and (looking-at leo/restclient-header-regexp) (not (looking-at leo/restclient-empty-line-regexp))) - (setq headers (cons (leo/restclient-replace-all-in-header vars (leo/restclient-make-header)) headers))) - ((looking-at leo/restclient-use-var-regexp) - (setq headers (append headers (leo/restclient-parse-headers (leo/restclient-replace-all-in-string vars (match-string 1))))))) - (forward-line)) - (when (looking-at leo/restclient-empty-line-regexp) - (forward-line)) - (when leo/restclient-curr-request-functions - (add-hook 'leo/restclient-response-loaded-hook 'leo/restclient-single-request-function)) - (let* ((cmax (leo/restclient-current-max)) - (entity (leo/restclient-parse-body (buffer-substring (min (point) cmax) cmax) vars)) - (url (leo/restclient-replace-all-in-string vars url))) - (apply func method url headers entity args)))))) - -(defun leo/restclient-copy-curl-command () - "Formats the request as a curl command and copies the command to the clipboard." - (interactive) - (leo/restclient-http-parse-current-and-do - '(lambda (method url headers entity) - (let ((header-args - (apply 'append - (mapcar (lambda (header) - (list "-H" (format "%s: %s" (car header) (cdr header)))) - headers)))) - (kill-new (concat "curl " - (mapconcat 'shell-quote-argument - (append '("-i") - header-args - (list (concat "-X" method)) - (list url) - (when (> (string-width entity) 0) - (list "-d" entity))) - " ")))) - (message "curl command copied to clipboard.")))) - - -(defun leo/restclient-elisp-result-function (args offset) - (goto-char offset) - (lexical-let ((form (macroexpand-all (read (current-buffer))))) - (lambda () - (eval form)))) - -(leo/restclient-register-result-func - "run-hook" #'leo/restclient-elisp-result-function - "Call the provided (possibly multi-line) elisp when the result - buffer is formatted. Equivalent to a leo/restclient-response-loaded-hook - that only runs for this request. - eg. -> on-response (message \"my hook called\")" ) - -;;;###autoload -(defun leo/restclient-http-send-current (&optional raw stay-in-window) - "Sends current request. -Optional argument RAW don't reformat response if t. -Optional argument STAY-IN-WINDOW do not move focus to response buffer if t." - (interactive) - (leo/restclient-http-parse-current-and-do 'leo/restclient-http-do raw stay-in-window)) - -;;;###autoload -(defun leo/restclient-http-send-current-raw () - "Sends current request and get raw result (no reformatting or syntax highlight of XML, JSON or images)." - (interactive) - (leo/restclient-http-send-current t)) - -;;;###autoload -(defun leo/restclient-http-send-current-stay-in-window () - "Send current request and keep focus in request window." - (interactive) - (leo/restclient-http-send-current nil t)) - -(defun leo/restclient-jump-next () - "Jump to next request in buffer." - (interactive) - (let ((last-min nil)) - (while (not (eq last-min (goto-char (leo/restclient-current-min)))) - (goto-char (leo/restclient-current-min)) - (setq last-min (point)))) - (goto-char (+ (leo/restclient-current-max) 1)) - (goto-char (leo/restclient-current-min))) - -(defun leo/restclient-jump-prev () - "Jump to previous request in buffer." - (interactive) - (let* ((current-min (leo/restclient-current-min)) - (end-of-entity - (save-excursion - (progn (goto-char (leo/restclient-current-min)) - (while (and (or (looking-at "^\s*\\(#.*\\)?$") - (eq (point) current-min)) - (not (eq (point) (point-min)))) - (forward-line -1) - (beginning-of-line)) - (point))))) - (unless (eq (point-min) end-of-entity) - (goto-char end-of-entity) - (goto-char (leo/restclient-current-min))))) - -(defun leo/restclient-mark-current () - "Mark current request." - (interactive) - (goto-char (leo/restclient-current-min)) - (set-mark-command nil) - (goto-char (leo/restclient-current-max)) - (backward-char 1) - (setq deactivate-mark nil)) - -(defun leo/restclient-show-info () - ;; leo/restclient-info-buffer-name - (interactive) - (let ((vars-at-point (leo/restclient-find-vars-before-point))) - (cl-labels ((non-overidden-vars-at-point () - (seq-filter (lambda (v) - (null (assoc (car v) leo/restclient-var-overrides))) - vars-at-point)) - (sanitize-value-cell (var-value) - (replace-regexp-in-string "\n" "|\n| |" - (replace-regexp-in-string "\|" "\\\\vert{}" - (leo/restclient-replace-all-in-string vars-at-point var-value)))) - (var-row (var-name var-value) - (insert "|" var-name "|" (sanitize-value-cell var-value) "|\n")) - (var-table (table-name) - (insert (format "* %s \n|--|\n|Name|Value|\n|---|\n" table-name))) - (var-table-footer () - (insert "|--|\n\n"))) - - (with-current-buffer (get-buffer-create leo/restclient-info-buffer-name) - ;; insert our info - (erase-buffer) - - (insert "\Leo/Restclient Info\ \n\n") - - (var-table "Dynamic Variables") - (dolist (dv leo/restclient-var-overrides) - (var-row (car dv) (cdr dv))) - (var-table-footer) - - ;; (insert ":Info:\n Dynamic vars defined by request hooks or with calls to leo/restclient-set-var\n:END:") - - (var-table "Vars at current position") - (dolist (dv (non-overidden-vars-at-point)) - (var-row (car dv) (cdr dv))) - (var-table-footer) - - - ;; registered callbacks - (var-table "Registered request hook types") - (dolist (handler-name (delete-dups (mapcar 'car leo/restclient-result-handlers))) - (var-row handler-name (cddr (assoc handler-name leo/restclient-result-handlers)))) - (var-table-footer) - - (insert "\n\n'q' to exit\n") - (org-mode) - (org-toggle-pretty-entities) - (org-table-iterate-buffer-tables) - (outline-show-all) - (leo/restclient-response-mode) - (goto-char (point-min)))) - (switch-to-buffer-other-window leo/restclient-info-buffer-name))) - -(defun leo/restclient-narrow-to-current () - "Narrow to region of current request" - (interactive) - (narrow-to-region (leo/restclient-current-min) (leo/restclient-current-max))) - -(defun leo/restclient-toggle-body-visibility () - (interactive) - ;; If we are not on the HTTP call line, don't do anything - (let ((at-header (save-excursion - (beginning-of-line) - (looking-at leo/restclient-method-url-regexp)))) - (when at-header - (save-excursion - (end-of-line) - ;; If the overlays at this point have 'invisible set, toggling - ;; must make the region visible. Else it must hide the region - - ;; This part of code is from org-hide-block-toggle method of - ;; Org mode - (let ((overlays (overlays-at (point)))) - (if (memq t (mapcar - (lambda (o) - (eq (overlay-get o 'invisible) 'outline)) - overlays)) - (outline-flag-region (point) (leo/restclient-current-max) nil) - (outline-flag-region (point) (leo/restclient-current-max) t)))) t))) - -(defun leo/restclient-toggle-body-visibility-or-indent () - (interactive) - (unless (leo/restclient-toggle-body-visibility) - (indent-for-tab-command))) - -(defconst leo/restclient-mode-keywords - (list (list leo/restclient-method-url-regexp '(1 'leo/restclient-method-face) '(2 'leo/restclient-url-face)) - (list leo/restclient-svar-regexp '(1 'leo/restclient-variable-name-face) '(2 'leo/restclient-variable-string-face)) - (list leo/restclient-evar-regexp '(1 'leo/restclient-variable-name-face) '(2 'leo/restclient-variable-elisp-face t)) - (list leo/restclient-mvar-regexp '(1 'leo/restclient-variable-name-face) '(2 'leo/restclient-variable-multiline-face t)) - (list leo/restclient-use-var-regexp '(1 'leo/restclient-variable-usage-face)) - (list leo/restclient-file-regexp '(0 'leo/restclient-file-upload-face)) - (list leo/restclient-header-regexp '(1 'leo/restclient-header-name-face t) '(2 'leo/restclient-header-value-face t)) - (list leo/restclient-response-hook-regexp '(1 ' leo/restclient-request-hook-face t) - '(2 'leo/restclient-request-hook-name-face t) - '(3 'leo/restclient-request-hook-args-face t)))) - -(defconst leo/restclient-mode-syntax-table - (let ((table (make-syntax-table))) - (modify-syntax-entry ?\# "<" table) - (modify-syntax-entry ?\n ">#" table) - table)) - -(defvar leo/restclient-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c C-c") 'leo/restclient-http-send-current) - (define-key map (kbd "C-c C-r") 'leo/restclient-http-send-current-raw) - (define-key map (kbd "C-c C-v") 'leo/restclient-http-send-current-stay-in-window) - (define-key map (kbd "C-c C-n") 'leo/restclient-jump-next) - (define-key map (kbd "C-c C-p") 'leo/restclient-jump-prev) - (define-key map (kbd "C-c C-.") 'leo/restclient-mark-current) - (define-key map (kbd "C-c C-u") 'leo/restclient-copy-curl-command) - (define-key map (kbd "C-c n n") 'leo/restclient-narrow-to-current) - (define-key map (kbd "C-c C-i") 'leo/restclient-show-info) - map) - "Keymap for leo/restclient-mode.") - -(define-minor-mode leo/restclient-outline-mode - "Minor mode to allow show/hide of request bodies by TAB." - :init-value nil - :lighter nil - :keymap '(("\t" . leo/restclient-toggle-body-visibility-or-indent) - ("\C-c\C-a" . leo/restclient-toggle-body-visibility-or-indent)) - :group 'leo/restclient) - -(define-minor-mode leo/restclient-response-mode - "Minor mode to allow additional keybindings in leo/restclient response buffer." - :init-value nil - :lighter nil - :keymap '(("q" . (lambda () - (interactive) - (quit-window (get-buffer-window (current-buffer)))))) - :group 'leo/restclient) - -;;;###autoload -(define-derived-mode leo/restclient-mode fundamental-mode "REST Client" - "Turn on leo/restclient mode." - (set (make-local-variable 'comment-start) "# ") - (set (make-local-variable 'comment-start-skip) "# *") - (set (make-local-variable 'comment-column) 48) - - (set (make-local-variable 'font-lock-defaults) '(leo/restclient-mode-keywords)) - ;; We use outline-mode's method outline-flag-region to hide/show the - ;; body. As a part of it, it sets 'invisibility text property to - ;; 'outline. To get ellipsis, we need 'outline to be in - ;; buffer-invisibility-spec - (add-to-invisibility-spec '(outline . t))) - -(add-hook 'leo/restclient-mode-hook 'leo/restclient-outline-mode) - -(provide 'leo/restclient) - -;; (eval-after-load 'helm -;; '(ignore-errors (require 'leo/restclient-helm))) - -;; (eval-after-load 'jq-mode -;; '(ignore-errors (require 'leo/restclient-jq))) - -(provide 'leo/restclient) -;;; leo/restclient.el ends here