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.

94 lines
3.0 KiB

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