From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: taylanbayirli@gmail.com (Taylan Ulrich =?utf-8?Q?Bay=C4=B1rl=C4=B1?= =?utf-8?Q?=2FKammer?=) Newsgroups: gmane.emacs.devel Subject: Re: [PATCH] Add json-sexp-mode. Date: Sun, 18 Oct 2015 00:08:05 +0200 Message-ID: <87pp0dtagq.fsf@T420.taylan> References: <87wpulwje2.fsf@T420.taylan> <8737x9wem9.fsf@T420.taylan> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1445119704 13061 80.91.229.3 (17 Oct 2015 22:08:24 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 17 Oct 2015 22:08:24 +0000 (UTC) Cc: emacs-devel To: Artur Malabarba Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Oct 18 00:08:24 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1ZnZeJ-00075Q-Mq for ged-emacs-devel@m.gmane.org; Sun, 18 Oct 2015 00:08:23 +0200 Original-Received: from localhost ([::1]:59920 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZnZeJ-0005f3-29 for ged-emacs-devel@m.gmane.org; Sat, 17 Oct 2015 18:08:23 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:54396) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZnZe5-0005ey-Vr for emacs-devel@gnu.org; Sat, 17 Oct 2015 18:08:11 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZnZe4-0006P4-IQ for emacs-devel@gnu.org; Sat, 17 Oct 2015 18:08:09 -0400 Original-Received: from mail-wi0-x230.google.com ([2a00:1450:400c:c05::230]:33138) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZnZe4-0006Ou-7m for emacs-devel@gnu.org; Sat, 17 Oct 2015 18:08:08 -0400 Original-Received: by wijp11 with SMTP id p11so52493355wij.0 for ; Sat, 17 Oct 2015 15:08:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version:content-type; bh=ti+akOktfqLrzp22qAP4doweGAdEwW+v0xCX0kZ4Oo8=; b=vOZmDqMGO6h4Smu/wLv9y1o7N1vPUem6r7X37XUUO6V/A/oIK8yqSWJadmy8zDw6uM rs62zlCG1eu8uuwMiwBh41kVqCwWRNKtstzCNJ8IrtPBmAsxnKf7uO/cxTqizubn4WcH E08pST1k8FQV9mq69MF0VJE7fuQ0hwhdJC64ymdbpIe2CAOl7ES28SR9RdRtie5aETQp x0DkAqZzdt+YhqVoD6eg8pfjv4zpX4GEL2rWIQwi8xaJhvvshJY99/vF8PWWK2CycsDm 1mQ7Q5JrQDzbwJK9xWkQD4QnTOrdgJr3yhEzLL6q6mmY8e2l2K74CX9Lf5BcUy+8zPWG y0Aw== X-Received: by 10.194.52.6 with SMTP id p6mr27476048wjo.119.1445119687593; Sat, 17 Oct 2015 15:08:07 -0700 (PDT) Original-Received: from T420.taylan ([2a02:908:c32:4740:221:ccff:fe66:68f0]) by smtp.gmail.com with ESMTPSA id kr10sm30554965wjc.25.2015.10.17.15.08.06 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 17 Oct 2015 15:08:06 -0700 (PDT) In-Reply-To: (Artur Malabarba's message of "Sat, 17 Oct 2015 22:47:16 +0100") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:400c:c05::230 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:191895 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Artur Malabarba writes: > 2015-10-17 19:10 GMT+01:00 Taylan Ulrich Bay=C4=B1rl=C4=B1/Kammer > : >> >> json.el yields Elisp s-expressions though. The closest approximation to >> an "Elisp s-expression editing mode" is emacs-lisp-mode. > > I've got something even better for you then. You can change your mode > to inherit from prog-mode and add this line: > (lisp-mode-variables nil nil 'elisp) > > This should make sure it has all the syntax definitions of > emacs-lisp-mode, without carrying its keybinds, eldoc, completion > functions, xref definitions, search-path, menu-bars, etc, which (IIUC) > wouldn't make sense for this json-sexp-mode. > > Of course, it's up to you. I'm just recommending what I would do. Ooh, thanks, that seems to be a good way to do it. (Some people might have to add paredit-mode to json-sexp-mode-hook when previously emacs-lisp-mode-hook would enable it for them, but that should be fine. I personally enable Paredit in prog-mode-hook.) Here's the updated patch. --=-=-= Content-Type: text/x-diff; charset=utf-8 Content-Disposition: inline; filename=0001-Add-json-sexp-mode.patch Content-Transfer-Encoding: quoted-printable >From ff35fbca2ff8b818ce47efe2bb1d07f5f70a6051 Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?Taylan=3D20Ulrich=3D20Bay=3DC4=3DB1rl=3DC4=3DB1/Kammer?=3D Date: Sat, 17 Oct 2015 17:15:23 +0200 Subject: [PATCH 1/2] Add json-sexp-mode. --- packages/json-sexp-mode/json-sexp-mode.el | 110 ++++++++++++++++++++++++++= ++++ 1 file changed, 110 insertions(+) create mode 100644 packages/json-sexp-mode/json-sexp-mode.el diff --git a/packages/json-sexp-mode/json-sexp-mode.el b/packages/json-sexp= -mode/json-sexp-mode.el new file mode 100644 index 0000000..689ba8c --- /dev/null +++ b/packages/json-sexp-mode/json-sexp-mode.el @@ -0,0 +1,110 @@ +;;; json-sexp-mode.el --- Edit JSON in s-expression form. + +;; Copyright (C) 2015 Free Software Foundation, Inc. + +;; Author: Taylan Ulrich Bay=C4=B1rl=C4=B1/Kammer +;; Keywords: data, files + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Activating `json-sexp-mode' will turn the JSON value in the buffer into= an +;; s-expression, and arrange for it to be transparently converted back int= o a +;; (pretty-printed) JSON value whenever the buffer is saved. Adding +;; `json-sexp-mode' to `auto-mode-alist' can provide a fully transparent +;; experience for editing JSON files as s-expressions. +;; +;; The symbol `false' is used to represent JSON's false value, because nil +;; stands for an empty object. (However, t is used for JSON's true value.) +;; +;; +;; The following commands can be used to manually convert a region or whole +;; buffer from a JSON value to an s-expression and from an s-expression to= a +;; JSON value: +;; +;; `json-sexp-convert-region-to-sexp' +;; `json-sexp-convert-region-to-json' +;; `json-sexp-convert-buffer-to-sexp' +;; `json-sexp-convert-buffer-to-json' + +;;; Code: +(require 'json) + +(defun json-sexp-convert-region-to-sexp (start end) + "Convert region from JSON to sexps." + (interactive "r") + (unless (=3D start end) + (let ((data (let ((json-object-type 'alist) + (json-false 'false) + (json-null 'null)) + (json-read-from-string (buffer-substring start end)))) + (point (point))) + (delete-region start end) + (goto-char start) + (insert (pp-to-string data)) + ;; Only an approximation of our position in the JSON. + (goto-char point)))) + +(defun json-sexp-convert-region-to-json (start end) + "Convert region from sexps to JSON." + (interactive "r") + (unless (=3D start end) + (let ((data (car (read-from-string (buffer-substring start end)))) + (point (point))) + (delete-region start end) + (goto-char start) + (insert (let ((json-encoding-pretty-print t) + (json-false 'false) + (json-null 'null) + (json-nil 'object)) + (json-encode data))) + ;; Only an approximation of our position in the s-expression. + (goto-char point)))) + +(defun json-sexp-convert-buffer-to-sexp () + "Convert buffer from JSON to sexps." + (interactive) + (json-sexp-convert-region-to-sexp (point-min) (point-max))) + +(defun json-sexp-convert-buffer-to-json () + "Convert buffer from sexps to JSON." + (interactive) + (json-sexp-convert-region-to-json (point-min) (point-max))) + +(defvar json-sexp--saved-point nil) + +(define-derived-mode json-sexp-mode prog-mode "JSON-sexp" + "Major mode for editing JSON in s-expression form. +The buffer-contents, which must be JSON, are transformed to +s-expressions when this mode is started, and transformed back +temporarily to JSON whenever the buffer is saved." + (lisp-mode-variables nil nil 'elisp) + (let ((was-modified (buffer-modified-p))) + (json-sexp-convert-buffer-to-sexp) + (set-buffer-modified-p was-modified)) + (add-hook 'before-save-hook 'json-sexp--before-save nil t) + (add-hook 'after-save-hook 'json-sexp--after-save nil t)) + +(defun json-sexp--before-save () + (setq json-sexp--saved-point (point)) + (json-sexp-convert-buffer-to-json)) + +(defun json-sexp--after-save () + (json-sexp-convert-buffer-to-sexp) + (set-buffer-modified-p nil) + (goto-char json-sexp--saved-point)) + +(provide 'json-sexp-mode) +;;; json-sexp-mode.el ends here --=20 2.5.0 --=-=-=--