summaryrefslogtreecommitdiff
path: root/modules/prog-json.el
blob: 6dba6dee8f4199a59193d467c8cc9454a7b0ee13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
;;; prog-json.el --- JSON Editing, Formatting, and jq Integration -*- lexical-binding: t; coding: utf-8; -*-
;; Author: Craig Jennings <c@cjennings.net>

;;; Commentary:
;; JSON editing with tree-sitter highlighting, one-key formatting, and
;; interactive jq queries against the current buffer.
;;
;; Features:
;;   - Tree-sitter: Better syntax highlighting and structural navigation
;;   - Formatting: Pretty-print with sorted keys via C-; f
;;   - jq: Interactive jq REPL against current JSON buffer
;;
;; Workflow:
;;   1. Open .json file → json-ts-mode with tree-sitter highlighting
;;   2. C-; f → Format/pretty-print the buffer
;;   3. C-c C-q → Open jq interactive buffer to query/transform JSON

;;; Code:

(defvar json-ts-mode-map)

;; -------------------------------- JSON Mode ----------------------------------
;; tree-sitter mode for JSON files (built-in, Emacs 29+)
;; NOTE: No :mode directive here — treesit-auto (in prog-general.el) handles
;; the auto-mode-alist mapping and auto-installs the grammar on first use.

(use-package json-ts-mode
  :ensure nil
  :defer t)

;; -------------------------------- Formatting ---------------------------------
;; pretty-print with sorted keys, bound to standard format key

(defun cj/json-format-buffer ()
  "Format the current JSON buffer with sorted keys.
Uses jq if available for reliable formatting, otherwise falls
back to the built-in `json-pretty-print-buffer-ordered'."
  (interactive)
  (if (executable-find "jq")
      (let ((point (point)))
        (shell-command-on-region (point-min) (point-max) "jq --sort-keys ." nil t)
        (goto-char (min point (point-max))))
    (json-pretty-print-buffer-ordered)))

(defun cj/json-setup ()
  "Set up JSON buffer keybindings."
  (local-set-key (kbd "C-; f") #'cj/json-format-buffer))

(add-hook 'json-ts-mode-hook #'cj/json-setup)

;; --------------------------------- jq Mode -----------------------------------
;; interactive jq queries against JSON buffers

(use-package jq-mode
  :defer t
  :bind (:map json-ts-mode-map
              ("C-c C-q" . jq-interactively)))

(provide 'prog-json)
;;; prog-json.el ends here.