I have some JSON files and I'm writing a mode that allows editing a single property of the JSON object independently from the rest. For example:
foo.json:
{
"creation_timestamp": "1411210038.000000",
"description": "lorem ipsum.\ndolor sit amet.",
"version": 4
}
Opening foo.json results in this buffer:
lorem ipsum.
dolor sit amet.
Changing the first line to "foo bar" and saving the file results in a foo.json
with only the description
field updated:
{
"creation_timestamp": "1411210038.000000",
"description": "foo bar.\ndolor sit amet.",
"version": 4
}
What's the best strategy for this? My current attempt is so:
- open the JSON file with find-file
- create an invisible overlay from point-min to point-max
- parse json
- insert the value of the
description
property at point-min, creating a "view" - add a local-write-file hook and an after-save hook
The local-write-file
hook kills the "view", updates the json in the overlay, and saves the file. The after-save
hook recreates the "view" so the user can keep editing.
This is long-winded and brittle. Is there a better way of working with data where the screen representation should be different than the disk representation?
Is your use case really as simple as the scenario you describe (not the solution outline, but the problem/use case)?
If so, your solution sounds like overkill. If the use case is as simple as editing the value of a particular key, I would probably do this:
Display the content of that field (value corresponding to the key) in a temporary buffer, for editing.
Bind a key (e.g.,
C-c C-c
) to save the edited value back to the file.I do that in Bookmark+ for editing a bookmark's tags, for instance (and also for editing all of a bookmark's fields, using a different command). The command to edit the tags is
bmkp-edit-tags
. The command (bound toC-c C-c
in the edit buffer) isbmkp-edit-tags-send
. The code is here, in context. Here it is, out of context:The most relevant bits are these:
Define a command to initiate editing and a command to end it and save the changes.
Provide an edit buffer using
bmkp-with-output-to-plain-temp-buffer
(essentiallywith-output-to-temp-buffer
, but that macro in some Emacs versions also adds Help mode stuff not needed here).Put the edit buffer in a simple minor mode that binds
C-c C-c
to the save-and-exit command.Fill the edit buffer with the text to be edited. Pop to the buffer, for editing.
In the save-and-exit command (
bmkp-edit-tags-send
), update the original data, replacing the relevant field contents with the edit-buffer contents. Save the updated data. Return to the original buffer.You can define your own encoding and decoding in
format-alist
for that purpose. Your example could be implemented in the following way:Actually, one can also interpret this as a more general problem. Load a file into a hidden buffer. Use another visible buffer to edit its transformed content. At saving the visible buffer actually transform the content back to the original format and save the hidden buffer.
I do not have the time right now to implement the general case as described above. The following code roughly covers your special case. (Note, that it is a fast hack for demonstration purposes only.)