I want to read config in YAML with elisp code. Searched but didn't find ready-to-use parser in elisp. Did I miss something useful?
Three years later, we have dynamic modules, and emacs-libyaml looks pretty interesting. It uses the dynamic module system to expose the C bindings of libyaml in Elisp. I would expect the performance to be fantastic, although I haven't tested it.
Six months later, it appears that the answer is "there exists no solid easily-available elisp YAML parser."
If you really want to read a YAML document in elisp and turn it into something that elisp can interact with, you're going to have to put in some gnarly work. The EmacsWiki YAML page hasn't got much for you, and the canonical YAML mode has syntax hints, but no actual parser. Fortunately someone has implemented a YAML-parsing web-app that takes YAML and outputs JSON or Python - you could try to get a look under the hood of that and-or use it to check any YAML parser you may write yourself.
Good luck.
And some months later: I wanted it, so here's how to do it with some help from python:
(defun yaml-parse ()
"yaml to json to a hashmap of current buffer, with python.
There is no yaml parser in elisp.
You need pyYaml and some yaml datatypes like dates are not supported by json."
(interactive)
(let ((json-object-type 'hash-table))
(setq myyaml (json-read-from-string (shell-command-to-string (concat "python -c 'import sys, yaml, json; json.dump(yaml.load(sys.stdin), sys.stdout, indent=4)' < " (buffer-file-name))))))
;; code here
)
It turns the yaml of the current buffer into an elisp hashmap, with the help of json.el
.
You need python's pyyaml: pip install PyYaml
.
Three more years later, I'm happy to say that there is now a YAML parser written in Elisp: https://melpa.org/#/yaml
It's API is similar to that of json-parse-string
in that you can specify it's object and list type. The following is an example of its usage:
(yaml-parse-string "
-
\"flow in block\"
- >
Block scalar
- !!map # Block collection
foo : bar" :object-type 'alist)
;; => ["flow in block" "Block scalar\n" (("foo" . "bar"))]
To improve on Ehvince answer using python, a more generic way that allows parsing string, buffers and files:
(defun yaml-parse (string)
"yaml STRING to json to a hashmap of current buffer, with python."
(interactive)
(with-temp-buffer
(insert string)
(when (zerop (call-process-region (point-min) (point-max) "python" t t nil "-c" "import sys, yaml, json; json.dump(yaml.load(sys.stdin), sys.stdout)"))
(goto-char (point-min))
(json-read))))
(defun yaml-parse-buffer (&optional buffer)
"Parse yaml BUFFER."
(with-current-buffer (or buffer (current-buffer))
(yaml-parse (buffer-substring-no-properties (point-min) (point-max)))))
(defun yaml-parse-file (file)
"Parse yaml FILE."
(with-temp-buffer
(insert-file-contents-literally file)
(yaml-parse (buffer-substring-no-properties (point-min) (point-max)))))
You can use the json-* variables to control type mappings.
edit: Added yaml-parse-file
© 2022 - 2024 — McMap. All rights reserved.
read
. – Dvinapymacs
. – Thankyou