json-emacs/json-mode

How to add a comment feature to json-mode?

Closed this issue · 8 comments

I am trying to add a comment feature to the JSON format. Although the regular JSON format does not accept comments, I have written a Perl script that can parse such a file. A comment starts with the # sign as in Shell scripts. What I would like to achieve, is to add syntax highlighting for comments in Emacs, while still using the nice highlighting features of your Emacs json-mode. However, this is complicated by the fact that json-mode does not use syntax highlighting for regular strings, instead it uses font-lock keywords. I think I understand why this is done: the ordinary (built-in) syntax highlighting for strings cannot differentiate between key strings and value strings, so you chose to use font-lock keywords instead? See this question at emacs.stackexchange.com for more information about the problem:

http://emacs.stackexchange.com/questions/9840/how-to-use-font-lock-to-highlight-end-of-line-comments

Any suggestions on how to achieve this (preferably using syntax highlighting and not font lock keywords)?

I'm doing something similar to support // end of line comments (which is very common in the Node world of configs) using the following:

(defconst json-mode-comments-re (rx (group "//" (zero-or-more nonl) line-end)))
(push (list json-mode-comments-re 1 font-lock-comment-face) json-font-lock-keywords-1)

I imagine you could do the same using "#" instead of "//". Unfortunately this doesn't work for multi-line comments (which in my case would be of the /* ... */ form.

It would be great if there could be a native means of specifying this. Perhaps a couple of functions json-mode-set-hash-comment-style,json-mode-set-js-comment-style, json-mode-disable-comments that would modify json-font-lock-keywords-1 (after setting it buffer-local)? It would be nicer to just have a json-mode-comment-style with options 'hash, 'js and nil, but I'm not sure how that would flow into the keyword-style fontification.

Although the regular JSON format does not accept comments, I have written a Perl script that can parse such a file.

I would hesitate to add support for comments in json-mode for this reason. Because at that point, it's not valid json anymore and so we'll potentially introduce interop problems (with other packages that expect json-mode to indicate valid json).

I think the best option here would be to create a new mode, like cjson-mode for example, and use a defined set of rules that others can follow (eg. https://www.npmjs.com/package/cjson)

Fuco1 commented

@joshwnj do you know of some modes that actually assume that json-mode = valid json?

I would also like to have comment support using the syntax properties as usual in Emacs. If we really want strictly valid json we could add a strict mode or something to strip the comments.

I would like to change restclient package to use json-mode instead of js-mode but it prints headers as comments and so in json-mode the buffer gets unusable :/

@Fuco1 could you please paste some example output that you're trying to use? That will be helpful in finding a good solution here.

Fuco1 commented

restclient formats the output like so

{
    "error": "Data not available"
}
// HTTP/1.1 404 Not Found
// Cache-Control: private
// Content-Type: application/json; charset=UTF-8
// Referrer-Policy: no-referrer
// Content-Length: 31
// Date: Mon, 01 May 2017 08:57:14 GMT

So for me it would be sufficient to mark as comment everything after the first valid json form. I'm not sure if the intent ever was to have more than one anyway.

I think it might be a nice thing at some point to have a setting to enable comments, but for now I'm utilizing this function from this emacs init file - https://github.com/jordonbiondo/.emacs.d/blob/master/init.el#L884. Does the job well enough when everything is returned 200 OK.

Alright! An update, here's my solution. I took the comment face provided by @felipeochoa here and applied it to json-mode. Then, in my restclient use-package setup, I made sure to enable json-mode and disable Flycheck.

;; REST Client inside Emacs
(use-package restclient
  :mode ("\\.http\\'" . restclient-mode)
  :config
  (add-hook 'restclient-response-loaded-hook
            (defun mad/js-to-cjson-mode ()
              (when (equal major-mode 'js-mode)
                (json-mode)
                ;; Disable Flycheck so comments don't set off alarms
                (flycheck-mode -1)))))

This is a very specific solution for REST client, but it works for me 😄. I do agree with @joshwnj that if actual "commented json" is supposed to be valid, it should probably be its own mode.

taku0 commented

Now jsonc-mode is available.