ljos / jq-mode

Emacs major mode for editing jq queries.
GNU General Public License v3.0
110 stars 12 forks source link

Enhancement: support yaml using yq #31

Closed chasecaleb closed 2 years ago

chasecaleb commented 2 years ago

Hi,

What do you think about adding yaml support using https://github.com/kislyuk/yq ? Since it's a wrapper around jq it uses the same filter language, so it wouldn't take a lot of work to support in your project.

I deal with yaml all day long as an SRE in Kubernetes land, so it would be excellent to have a yq babel source block and a yq-interactively function.

*Note: there are unfortunately two different projects named yq, don't mix them up. The other one (written in go) doesn't use jq and has significant breakage between major versions... I think it would be a much bigger headache to integrate with.

ljos commented 2 years ago

I added a configuration so that you can change the font lock mode used by jq-interactively. This means that you can change the command to run jq to yq, set any flags you need, and then also change the font locking mode from json mode to yaml mode.

It might not be fully satisfactory as maybe some of those variables need to be buffer local or something so that you can have jq-interactively run both with yaml and json without having to change configuration.

ljos commented 2 years ago

For babel source blocks you can add the configuration to the top of the block or file.

chasecaleb commented 2 years ago

Nice! I'm working on adding a yq babel executor and a yq-interactively function to enhance this. I have it mostly working but could use some help if possible. In return I can make a PR once finished, or you're free to take this and finish implementing it yourself if you'd prefer. Interested?

Here's what I have so far:


Babel

(defun org-babel-execute:yq (body params)
  "Like `org-babel-execute:jq', but for yaml with yq."
  (let* ((org-babel-jq-command "yq"))
    (org-babel-execute:jq body params)))

(add-to-list 'org-src-lang-modes '("yq" . "jq"))

Example usage:

#+name: test-yaml
#+begin_example yaml
  name: foo
  args:
    - abc
    - def
#+end_example

#+begin_src yq :stdin test-yaml :results verbatim :cmd-line --yaml-output :wrap example yaml
  .args
#+end_src

#+RESULTS:
#+begin_example yaml
- abc
- def
#+end_example

Issues:

  1. I have to add :results verbatim, otherwise I get a "Invalid number format: 1" error. So should we set that by default in org-babel-execute:yq?
  2. I think people will almost always want :cmd-line --yaml-output, since they're working with yaml as input. Do you think that should be set by default? It could be disabled with a :yaml-output no param if so. I'm ambivalent, up to you.

Interactive

(defun yq-interactively (beg end)
  "Like `jq-interactively', but for yaml with yq."
  (interactive ; Interactive signature copied from `jq-interactively'.
   (if (region-active-p)
       (list (region-beginning)
             (region-end))
     (list (point-min)
           (point-max))))
  (let ((jq-interactive-command "yq")
        (jq-interactive-default-prompt "yq: ")
        (jq-interactive-default-options (concat "--yaml-output " jq-interactive-default-options)))
    (jq-interactively beg end)))

Issues:

  1. If you want to merge this we'll want to add yq-interactive-command and yq-interactive-default-options defcustoms, but that's straightforward.
  2. For some reason the interactive output adds a line at the end with .... This doesn't happen if I omit the --yaml-output option, but of course then it outputs json which doesn't seem like a good idea. I couldn't figure out where this extra line is coming from, but yq doesn't do this on the command line so maybe it's somewhere in your interactive code? I got lost trying to figure this out.
chasecaleb commented 2 years ago

Okay, weirdly enough I get the extra line of ellipsis with a babel block too sometimes. I have no idea what's going on with it:

#+name: foo-yaml
#+begin_src yaml :results silent
  name: foo
#+end_src

#+begin_src yq :stdin foo-yaml :cmd-line --yaml-output :results verbatim
  .name
#+end_src

#+RESULTS:
: foo
: ...
chasecaleb commented 2 years ago

@ljos Just in case you didn't see the above ^