gsexp.el (3075B)
1 ;;; gsexp.el --- GraphQl as S-expressions -*- lexical-binding: t -*- 2 3 ;; Copyright (C) 2016-2022 Jonas Bernoulli 4 5 ;; Author: Jonas Bernoulli <jonas@bernoul.li> 6 ;; Homepage: https://github.com/magit/ghub 7 ;; Keywords: tools 8 ;; SPDX-License-Identifier: GPL-3.0-or-later 9 10 ;; This file is not part of GNU Emacs. 11 12 ;; This file is free software; you can redistribute it and/or modify 13 ;; it under the terms of the GNU General Public License as published by 14 ;; the Free Software Foundation; either version 3, or (at your option) 15 ;; any later version. 16 17 ;; This file is distributed in the hope that it will be useful, 18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 ;; GNU General Public License for more details. 21 22 ;; For a copy of the GPL see https://www.gnu.org/licenses/gpl.txt. 23 24 ;;; Commentary: 25 26 ;; This library encodes S-expressions as GraphQl documents. Currently 27 ;; it is rather incomplete and only intended for use by `ghub-graphql' 28 ;; but I might fill the gaps and add documentation eventually. I am 29 ;; not in a hurry though. 30 31 ;;; Code: 32 33 (require 'cl-lib) 34 35 (defun gsexp-encode (document) 36 (gsexp--pp (gsexp--encode-field document))) 37 38 (defun gsexp--encode-field (field) 39 (cond 40 ((stringp field) 41 field) 42 ((symbolp field) 43 (symbol-name field)) 44 ((listp (car field)) 45 (concat (format "%s: " (caar field)) 46 (gsexp--encode-field (cons (cadar field) 47 (cdr field))))) 48 (t 49 (concat (symbol-name (pop field)) 50 (and (vectorp (car field)) 51 (format " (\n%s)" 52 (mapconcat #'gsexp--encode-argument 53 (append (pop field) nil) 54 ",\n"))) 55 (and field 56 (format " {\n%s\n}" 57 (mapconcat #'gsexp--encode-field field "\n"))))))) 58 59 (cl-defun gsexp--encode-argument ((argument value)) 60 (format "%s: %s" argument (gsexp--encode-value value))) 61 62 (defun gsexp--encode-value (value) 63 (cond 64 ((numberp value) 65 (number-to-string value)) 66 ((symbolp value) ; including variables, enums, booleans and null 67 (symbol-name value)) 68 ((stringp value) 69 (prin1-to-string value)) 70 ((vectorp value) 71 (format "(%s)" (mapconcat #'gsexp--encode-value value ""))) 72 ((listp value) 73 (format "{%s}" (mapconcat 74 (pcase-lambda (`(,name ,value)) 75 (format "%s: %s" name (gsexp--encode-value value))) 76 value ", "))) 77 (t (error "Invalid field value: %S" value)))) 78 79 (defun gsexp--pp (string) 80 (with-temp-buffer 81 (save-excursion 82 (insert string)) 83 (while (< (point) (point-max)) 84 (unless (and (bolp) (eolp)) 85 (save-excursion 86 (let ((level (car (syntax-ppss (point-at-bol))))) 87 (when (looking-at "\\s-*\\s)") 88 (cl-decf level)) 89 (indent-line-to (* 2 level))))) 90 (forward-line 1)) 91 (buffer-string))) 92 93 ;;; _ 94 (provide 'gsexp) 95 ;;; gsexp.el ends here