diff options
| author | Ryan Crum | 2012-12-14 09:57:37 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2012-12-14 09:57:37 -0500 |
| commit | d72e9e922fb914a946e104ad2128f57c983ab75d (patch) | |
| tree | 28033212d18d659b1f7f16cee58dfd6482041bab /lisp | |
| parent | 5c207910c4899af1c547b0e508692d846c145d48 (diff) | |
| download | emacs-d72e9e922fb914a946e104ad2128f57c983ab75d.tar.gz emacs-d72e9e922fb914a946e104ad2128f57c983ab75d.zip | |
* lisp/json.el: Add pretty-print option.
(json-encoding-separator, json-encoding-default-indentation)
(json--encoding-current-indentation, json-encoding-pretty-print)
(json-encoding-lisp-style-closings): New vars.
(json--with-indentation): New macro.
(json-encode-hash-table, json-encode-alist, json-encode-plist)
(json-encode-array): Use it to obey json-encoding-pretty-print.
(json-pretty-print-buffer, json-pretty-print): New commands.
Fixes: debbugs:12634
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 11 | ||||
| -rw-r--r-- | lisp/json.el | 136 |
2 files changed, 122 insertions, 25 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8df55eaa108..97b3a6608ad 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2012-12-14 Ryan Crum <ryan.crum@eleostech.com> | ||
| 2 | |||
| 3 | * json.el: Add pretty-print option (bug#12634). | ||
| 4 | (json-encoding-separator, json-encoding-default-indentation) | ||
| 5 | (json--encoding-current-indentation, json-encoding-pretty-print) | ||
| 6 | (json-encoding-lisp-style-closings): New vars. | ||
| 7 | (json--with-indentation): New macro. | ||
| 8 | (json-encode-hash-table, json-encode-alist, json-encode-plist) | ||
| 9 | (json-encode-array): Use it to obey json-encoding-pretty-print. | ||
| 10 | (json-pretty-print-buffer, json-pretty-print): New commands. | ||
| 11 | |||
| 1 | 2012-12-14 Dmitry Gutov <dgutov@yandex.ru> | 12 | 2012-12-14 Dmitry Gutov <dgutov@yandex.ru> |
| 2 | 13 | ||
| 3 | * progmodes/ruby-mode.el (ruby-syntax-propertize-function): | 14 | * progmodes/ruby-mode.el (ruby-syntax-propertize-function): |
diff --git a/lisp/json.el b/lisp/json.el index b1ea03120dc..0927625de9f 100644 --- a/lisp/json.el +++ b/lisp/json.el | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | ;; Copyright (C) 2006-2012 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2006-2012 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Edward O'Connor <ted@oconnor.cx> | 5 | ;; Author: Edward O'Connor <ted@oconnor.cx> |
| 6 | ;; Version: 1.3 | 6 | ;; Version: 1.4 |
| 7 | ;; Keywords: convenience | 7 | ;; Keywords: convenience |
| 8 | 8 | ||
| 9 | ;; This file is part of GNU Emacs. | 9 | ;; This file is part of GNU Emacs. |
| @@ -48,6 +48,7 @@ | |||
| 48 | ;; 2006-12-29 - XEmacs support, from Aidan Kehoe <kehoea@parhasard.net>. | 48 | ;; 2006-12-29 - XEmacs support, from Aidan Kehoe <kehoea@parhasard.net>. |
| 49 | ;; 2008-02-21 - Installed in GNU Emacs. | 49 | ;; 2008-02-21 - Installed in GNU Emacs. |
| 50 | ;; 2011-10-17 - Patch `json-alist-p' and `json-plist-p' to avoid recursion -tzz | 50 | ;; 2011-10-17 - Patch `json-alist-p' and `json-plist-p' to avoid recursion -tzz |
| 51 | ;; 2012-10-25 - Added pretty-printed reformatting -Ryan Crum (ryan@ryancrum.org) | ||
| 51 | 52 | ||
| 52 | ;;; Code: | 53 | ;;; Code: |
| 53 | 54 | ||
| @@ -98,6 +99,24 @@ If this has the same value as `json-false', you might not be able to | |||
| 98 | tell the difference between `false' and `null'. Consider let-binding | 99 | tell the difference between `false' and `null'. Consider let-binding |
| 99 | this around your call to `json-read' instead of `setq'ing it.") | 100 | this around your call to `json-read' instead of `setq'ing it.") |
| 100 | 101 | ||
| 102 | (defvar json-encoding-separator "," | ||
| 103 | "Value to use as an element seperator when encoding.") | ||
| 104 | |||
| 105 | (defvar json-encoding-default-indentation " " | ||
| 106 | "The default indentation level for encoding. | ||
| 107 | Used only when `json-encoding-pretty-print' is non-nil.") | ||
| 108 | |||
| 109 | (defvar json--encoding-current-indentation "\n" | ||
| 110 | "Internally used to keep track of the current indentation level of encoding. | ||
| 111 | Used only when `json-encoding-pretty-print' is non-nil.") | ||
| 112 | |||
| 113 | (defvar json-encoding-pretty-print nil | ||
| 114 | "If non-nil, then the output of `json-encode' will be pretty-printed.") | ||
| 115 | |||
| 116 | (defvar json-encoding-lisp-style-closings nil | ||
| 117 | "If non-nil, ] and } closings will be formatted lisp-style, | ||
| 118 | without indentation.") | ||
| 119 | |||
| 101 | 120 | ||
| 102 | 121 | ||
| 103 | ;;; Utilities | 122 | ;;; Utilities |
| @@ -123,6 +142,14 @@ this around your call to `json-read' instead of `setq'ing it.") | |||
| 123 | 'not-plist))) | 142 | 'not-plist))) |
| 124 | (null list)) | 143 | (null list)) |
| 125 | 144 | ||
| 145 | (defmacro json--with-indentation (body) | ||
| 146 | `(let ((json--encoding-current-indentation | ||
| 147 | (if json-encoding-pretty-print | ||
| 148 | (concat json--encoding-current-indentation | ||
| 149 | json-encoding-default-indentation) | ||
| 150 | ""))) | ||
| 151 | ,body)) | ||
| 152 | |||
| 126 | ;; Reader utilities | 153 | ;; Reader utilities |
| 127 | 154 | ||
| 128 | (defsubst json-advance (&optional n) | 155 | (defsubst json-advance (&optional n) |
| @@ -401,41 +428,70 @@ Please see the documentation of `json-object-type' and `json-key-type'." | |||
| 401 | 428 | ||
| 402 | (defun json-encode-hash-table (hash-table) | 429 | (defun json-encode-hash-table (hash-table) |
| 403 | "Return a JSON representation of HASH-TABLE." | 430 | "Return a JSON representation of HASH-TABLE." |
| 404 | (format "{%s}" | 431 | (format "{%s%s}" |
| 405 | (json-join | 432 | (json-join |
| 406 | (let (r) | 433 | (let (r) |
| 407 | (maphash | 434 | (json--with-indentation |
| 408 | (lambda (k v) | 435 | (maphash |
| 409 | (push (format "%s:%s" | 436 | (lambda (k v) |
| 410 | (json-encode-key k) | 437 | (push (format |
| 411 | (json-encode v)) | 438 | (if json-encoding-pretty-print |
| 412 | r)) | 439 | "%s%s: %s" |
| 413 | hash-table) | 440 | "%s%s:%s") |
| 441 | json--encoding-current-indentation | ||
| 442 | (json-encode-key k) | ||
| 443 | (json-encode v)) | ||
| 444 | r)) | ||
| 445 | hash-table)) | ||
| 414 | r) | 446 | r) |
| 415 | ", "))) | 447 | json-encoding-separator) |
| 448 | (if (or (not json-encoding-pretty-print) | ||
| 449 | json-encoding-lisp-style-closings) | ||
| 450 | "" | ||
| 451 | json--encoding-current-indentation))) | ||
| 416 | 452 | ||
| 417 | ;; List encoding (including alists and plists) | 453 | ;; List encoding (including alists and plists) |
| 418 | 454 | ||
| 419 | (defun json-encode-alist (alist) | 455 | (defun json-encode-alist (alist) |
| 420 | "Return a JSON representation of ALIST." | 456 | "Return a JSON representation of ALIST." |
| 421 | (format "{%s}" | 457 | (format "{%s%s}" |
| 422 | (json-join (mapcar (lambda (cons) | 458 | (json-join |
| 423 | (format "%s:%s" | 459 | (json--with-indentation |
| 424 | (json-encode-key (car cons)) | 460 | (mapcar (lambda (cons) |
| 425 | (json-encode (cdr cons)))) | 461 | (format (if json-encoding-pretty-print |
| 426 | alist) | 462 | "%s%s: %s" |
| 427 | ", "))) | 463 | "%s%s:%s") |
| 464 | json--encoding-current-indentation | ||
| 465 | (json-encode-key (car cons)) | ||
| 466 | (json-encode (cdr cons)))) | ||
| 467 | alist)) | ||
| 468 | json-encoding-separator) | ||
| 469 | (if (or (not json-encoding-pretty-print) | ||
| 470 | json-encoding-lisp-style-closings) | ||
| 471 | "" | ||
| 472 | json--encoding-current-indentation))) | ||
| 428 | 473 | ||
| 429 | (defun json-encode-plist (plist) | 474 | (defun json-encode-plist (plist) |
| 430 | "Return a JSON representation of PLIST." | 475 | "Return a JSON representation of PLIST." |
| 431 | (let (result) | 476 | (let (result) |
| 432 | (while plist | 477 | (json--with-indentation |
| 433 | (push (concat (json-encode-key (car plist)) | 478 | (while plist |
| 434 | ":" | 479 | (push (concat |
| 435 | (json-encode (cadr plist))) | 480 | json--encoding-current-indentation |
| 436 | result) | 481 | (json-encode-key (car plist)) |
| 437 | (setq plist (cddr plist))) | 482 | (if json-encoding-pretty-print |
| 438 | (concat "{" (json-join (nreverse result) ", ") "}"))) | 483 | ": " |
| 484 | ":") | ||
| 485 | (json-encode (cadr plist))) | ||
| 486 | result) | ||
| 487 | (setq plist (cddr plist)))) | ||
| 488 | (concat "{" | ||
| 489 | (json-join (nreverse result) json-encoding-separator) | ||
| 490 | (if (and json-encoding-pretty-print | ||
| 491 | (not json-encoding-lisp-style-closings)) | ||
| 492 | json--encoding-current-indentation | ||
| 493 | "") | ||
| 494 | "}"))) | ||
| 439 | 495 | ||
| 440 | (defun json-encode-list (list) | 496 | (defun json-encode-list (list) |
| 441 | "Return a JSON representation of LIST. | 497 | "Return a JSON representation of LIST. |
| @@ -474,7 +530,22 @@ become JSON objects." | |||
| 474 | 530 | ||
| 475 | (defun json-encode-array (array) | 531 | (defun json-encode-array (array) |
| 476 | "Return a JSON representation of ARRAY." | 532 | "Return a JSON representation of ARRAY." |
| 477 | (concat "[" (mapconcat 'json-encode array ", ") "]")) | 533 | (if (and json-encoding-pretty-print |
| 534 | (> (length array) 0)) | ||
| 535 | (concat | ||
| 536 | (json--with-indentation | ||
| 537 | (concat (format "[%s" json--encoding-current-indentation) | ||
| 538 | (json-join (mapcar 'json-encode array) | ||
| 539 | (format "%s%s" | ||
| 540 | json-encoding-separator | ||
| 541 | json--encoding-current-indentation)))) | ||
| 542 | (format "%s]" | ||
| 543 | (if json-encoding-lisp-style-closings | ||
| 544 | "" | ||
| 545 | json--encoding-current-indentation))) | ||
| 546 | (concat "[" | ||
| 547 | (mapconcat 'json-encode array json-encoding-separator) | ||
| 548 | "]"))) | ||
| 478 | 549 | ||
| 479 | 550 | ||
| 480 | 551 | ||
| @@ -541,6 +612,21 @@ Advances point just past JSON object." | |||
| 541 | ((listp object) (json-encode-list object)) | 612 | ((listp object) (json-encode-list object)) |
| 542 | (t (signal 'json-error (list object))))) | 613 | (t (signal 'json-error (list object))))) |
| 543 | 614 | ||
| 615 | ;; Pretty printing | ||
| 616 | |||
| 617 | (defun json-pretty-print-buffer () | ||
| 618 | "Pretty-print current buffer." | ||
| 619 | (interactive) | ||
| 620 | (json-pretty-print (point-min) (point-max))) | ||
| 621 | |||
| 622 | (defun json-pretty-print (begin end) | ||
| 623 | "Pretty-print selected region." | ||
| 624 | (interactive "r") | ||
| 625 | (atomic-change-group | ||
| 626 | (let ((json-encoding-pretty-print t) | ||
| 627 | (txt (delete-and-extract-region begin end))) | ||
| 628 | (insert (json-encode (json-read-from-string txt)))))) | ||
| 629 | |||
| 544 | (provide 'json) | 630 | (provide 'json) |
| 545 | 631 | ||
| 546 | ;;; json.el ends here | 632 | ;;; json.el ends here |