Personal emacs config
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
3.0 KiB

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