;;; uiua-input-gen.el --- Regenerate uiua-input.el from upstream primitives  -*- lexical-binding:t -*-

;; SPDX-License-Identifier: GPL-3.0-or-later
;; URL: https://github.com/crmsnbleyd/uiua-mode

;;; Commentary:
;; Maintenance script — not part of the runtime package.
;;
;; Run interactively:   M-x uiua-generate-input-method
;; Run from a shell:
;;   emacs --batch --script uiua-input-gen.el
;;
;; Fetches site/primitives.json from the official Uiua repository,
;; extracts every primitive that has a non-ASCII Unicode glyph, and
;; writes a ready-to-commit uiua-input.el in the same directory.
;;
;; Commit the resulting uiua-input.el so that end users never need
;; network access; they simply load the committed file.

;;; Code:
(require 'url)
(require 'json)

(defconst uiua-input-gen--source-url
  "https://raw.githubusercontent.com/uiua-lang/uiua/main/site/primitives.json"
  "URL of the Uiua primitive JSON data.")

(defconst uiua-input-gen--output-file
  (expand-file-name "uiua-input.el"
                    (file-name-directory (or load-file-name buffer-file-name)))
  "Path to the generated uiua-input.el, co-located with this script.")

(defun uiua-input-gen--fetch-primitives ()
  "Return an alist of (quail-key . glyph-string) for all non-ASCII Uiua glyphs.
Fetches `uiua-input-gen--source-url' synchronously.
Multi-word names (e.g. \"absolute value\") have spaces replaced by hyphens."
  (let ((buf (url-retrieve-synchronously uiua-input-gen--source-url t))
        result)
    (unless buf
      (error "Failed to fetch %s" uiua-input-gen--source-url))
    (with-current-buffer buf
      ;; url-retrieve-synchronously delivers a unibyte buffer with raw UTF-8.
      ;; Decode before passing to the JSON parser.
      (set-buffer-multibyte t)
      (decode-coding-region (point-min) (point-max) 'utf-8)
      (goto-char (point-min))
      (re-search-forward "\r?\n\r?\n" nil t)   ; skip HTTP headers
      (let ((json-object-type 'alist)
            (json-array-type  'list)
            (json-key-type    'string))
        (dolist (entry (json-read))
          (let* ((name  (car entry))
                 (props (cdr entry))
                 (glyph (cdr (assoc "glyph" props))))
            (when (and glyph
                       (stringp glyph)
                       (= (length glyph) 1)
                       (> (aref glyph 0) 127))
              (push (cons (replace-regexp-in-string " " "-" name) glyph)
                    result)))))
      (kill-buffer buf))
    (nreverse result)))

;;;###autoload
(defun uiua-generate-input-method ()
  "Regenerate uiua-input.el from the official Uiua primitives.json.
Writes the file to `uiua-input-gen--output-file'.  Commit the result
so that end users get the input method without a network call."
  (interactive)
  (message "Fetching Uiua primitives from %s ..." uiua-input-gen--source-url)
  (let ((pairs (uiua-input-gen--fetch-primitives)))
    (unless pairs
      (error "No non-ASCII primitives found; check network or source URL"))
    (with-temp-file uiua-input-gen--output-file
      (set-buffer-file-coding-system 'utf-8)
      (insert ";;; uiua-input.el --- Quail input method for Uiua glyphs  \
-*- coding:utf-8; lexical-binding:t -*-\n")
      (insert ";;\n")
      (insert ";; SPDX-License-Identifier: GPL-3.0-or-later\n")
      (insert ";; URL: https://github.com/crmsnbleyd/uiua-mode\n")
      (insert ";;\n")
      (insert ";; Auto-generated by uiua-input-gen.el — do not edit by hand.\n")
      (insert ";; Regenerate with:  emacs --batch --script uiua-input-gen.el\n")
      (insert ";;\n")
      (insert ";;; Code:\n")
      (insert "(require 'quail)\n\n")
      ;; quail-define-package positional args:
      ;;   name language title guidance docstring
      ;;   translation-keys forget-last-selection deterministic kbd-translate
      ;;   show-layout create-decode-map maximum-shortest overlay-plist
      ;;   update-translation-function conversion-keys simple
      ;;
      ;; simple=t: each key has exactly one translation, inserted immediately.
      (insert "(quail-define-package\n")
      (insert " \"uiua\" \"UTF-8\" \"Uiua\" t\n")
      (insert " \"Input method for Uiua Unicode glyphs.\n")
      (insert "Activate:  M-x set-input-method RET uiua RET\n")
      (insert "Type \\\\NAME to insert the glyph; use hyphens for multi-word names.\n")
      (insert "Examples:  \\\\not \\to ¬   \\\\fork \\to ⊃   \
\\\\absolute-value \\to ⌵\"\n")
      (insert " nil t nil nil nil nil nil nil nil nil t)\n\n")
      (insert "(quail-define-rules\n")
      ;; \"\\\\NAME\" in the source = the key string \NAME that the user types.
      ;; ?GLYPH is a character literal, matching Emacs built-in Quail style.
      ;; The closing ) goes on the last rule line (package-lint requirement).
      (let ((last (car (last pairs))))
        (dolist (pair (butlast pairs))
          (insert (format " (\"\\\\%s\" ?%s)\n" (car pair) (cdr pair))))
        (insert (format " (\"\\\\%s\" ?%s))\n\n" (car last) (cdr last))))
      ;; Plain alist for completion backends (e.g. corfu via capf).
      (insert "(defconst uiua--name-glyph-alist\n  '(\n")
      (let ((last (car (last pairs))))
        (dolist (pair (butlast pairs))
          (insert (format "   (%S . %S)\n" (car pair) (cdr pair))))
        (insert (format "   (%S . %S))\n" (car last) (cdr last))))
      (insert "  \"Alist mapping Uiua primitive names to their Unicode glyphs.\")\n\n")
      (insert "(provide 'uiua-input)\n")
      (insert ";;; uiua-input.el ends here\n"))
    (message "Wrote %d rules to %s" (length pairs) uiua-input-gen--output-file)))

;; When run as a batch script, generate immediately.
(when noninteractive
  (uiua-generate-input-method))

(provide 'uiua-input-gen)
;;; uiua-input-gen.el ends here
