git.fiddlerwoaroof.com
Browse code

feat(emacs): add nicer json navigator

Edward authored on 24/12/2021 11:04:21
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,116 @@
1
+;;; fwoar-json-navigator.el --- more functional utilities for emacs -*- lexical-binding: t; -*-
2
+
3
+;; Copyright (C) 2020 Edward Langley
4
+
5
+;; Author: Edward Langley <fwoar@elangley.org>
6
+;; Version: 0.0.1
7
+;; Keywords: json,navigator
8
+;; URL: https://fwoar.co
9
+
10
+;; This program is free software; you can redistribute it and/or modify
11
+;; it under the terms of the GNU General Public License as published by
12
+;; the Free Software Foundation, either version 3 of the License, or
13
+;; (at your option) any later version.
14
+
15
+;; This program is distributed in the hope that it will be useful,
16
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
+;; GNU General Public License for more details.
19
+
20
+;; You should have received a copy of the GNU General Public License
21
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
+
23
+;;; Commentary:
24
+
25
+;; simple attempts to navigate json
26
+
27
+;;; Code:
28
+
29
+(defvar-local fwoar/json-nav--data nil)
30
+(defvar-local fwoar/json-nav--path nil)
31
+
32
+(defun fwoar/json--ensure-data ()
33
+  (unless fwoar/json-nav--data
34
+    (save-excursion
35
+      (goto-char (point-min))
36
+      (setq-local fwoar/json-nav--data (json-parse-buffer :null-object nil))))
37
+  (values))
38
+
39
+(defun fwoar/json-nav--pierce-vectors (fun it)
40
+  (cl-typecase it
41
+    (vector (map 'vector
42
+                 (lambda (next)
43
+                   (fwoar/json-nav--pierce-vectors fun next))
44
+                 it))
45
+    (t (funcall fun it))))
46
+
47
+(defun fwoar/json-nav--get-path (data path)
48
+  (cl-loop with cur = data for key in path
49
+           do
50
+           (setf cur
51
+                 (cl-etypecase cur
52
+                   (vector
53
+                    (fwoar/json-nav--pierce-vectors (fwoar/key key)
54
+                                                    cur))
55
+                   (hash-table
56
+                    (funcall (fwoar/key key)
57
+                             cur))
58
+                   (null ())))
59
+           finally (return cur)))
60
+
61
+(cl-defmacro fwoar/json-nav--with-collector ((c) &body body)
62
+  (declare (indent 1))
63
+  (let ((v (gensym "v")))
64
+    `(let ((,v ()))
65
+       (cl-flet ((,c (it) (push it ,v)))
66
+         ,@body
67
+         (nreverse ,v)))))
68
+
69
+(defun fwoar/json-nav--get-keys ()
70
+  (fwoar/json--ensure-data)
71
+  (let ((data (fwoar/json-nav--get-path fwoar/json-nav--data
72
+                                        (reverse fwoar/json-nav--path))))
73
+    (sort (cl-etypecase data
74
+            (hash-table (hash-table-keys data))
75
+            (vector (remove-duplicates (sort (fwoar/json-nav--with-collector (c)
76
+                                               (fwoar/json-nav--pierce-vectors
77
+                                                (lambda (next)
78
+                                                  (when next
79
+                                                    (map nil #'c
80
+                                                         (hash-table-keys next))))
81
+                                                data))
82
+                                             'string<)
83
+                                       :test 'equal)))
84
+          'string<)))
85
+
86
+(defun fwoar/dive (s)
87
+  (interactive (list (completing-read "key? "
88
+                                      (fwoar/json-nav--get-keys))))
89
+  (fwoar/json--ensure-data)
90
+  (let* ((path (cons s fwoar/json-nav--path))
91
+         (data fwoar/json-nav--data))
92
+    (with-current-buffer (switch-to-buffer-other-window
93
+                          (format "*test-buffer: %s*"
94
+                                  (s-join "/" (reverse path))))
95
+      (json-mode)
96
+      (setq-local fwoar/json-nav--data data
97
+                  fwoar/json-nav--path path)
98
+      (setf (buffer-string)
99
+            (json-serialize (fwoar/json-nav--get-path fwoar/json-nav--data
100
+                                                      (reverse path))
101
+                            :null-object nil))
102
+      (json-pretty-print-buffer)
103
+      (goto-char (point-min))))
104
+  (goto-char (point-min)))
105
+
106
+(defun fwoar/return ()
107
+  (interactive)
108
+  (fwoar/json--ensure-data)
109
+  (let ((prev-buffer (format "*test-buffer: %s*"
110
+                             (s-join "/" (reverse (cdr fwoar/json-nav--path))))))
111
+    (kill-buffer)
112
+    (switch-to-buffer-other-window prev-buffer))
113
+  (point-min))
114
+
115
+(provide 'fwoar-json-navigator)
116
+;;; fwoar-json-navigator.el ends here