dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

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