s/plist/plisty to make it clear it's not a builtin lib

This commit is contained in:
Chris Barrett
2022-08-17 00:05:10 +12:00
parent 8cf0527beb
commit 6c3fac3f6a
5 changed files with 46 additions and 45 deletions

View File

@@ -97,7 +97,7 @@
(require 'dash)
(require 'org-tags-filter)
(require 'plist)
(require 'plisty)
(cl-eval-when (compile)
(require 'org)
@@ -121,7 +121,7 @@ their blocks updated automatically."
(plist-define org-roam-dblocks-args
(plisty-define org-roam-dblocks-args
:optional (:id :match :tags
:name :indentation-column :content))

View File

@@ -34,8 +34,9 @@
(require 'dash)
(require 'org-roam-review)
(require 'plisty)
(plist-define org-roam-links-graph
(plisty-define org-roam-links-graph
:required (:nodes :tree))
(defun org-roam-links--forward-links (node)

View File

@@ -61,6 +61,7 @@
(require 'org-drill)
(require 'org-roam-node)
(require 'org-roam-dailies)
(require 'plisty)
(require 'ts)
(defgroup org-roam-review nil
@@ -363,7 +364,7 @@ When called with a `C-u' prefix arg, clear the current filter."
(insert (or placeholder org-roam-review-default-placeholder))
(newline)))
(plist-define org-roam-review-render-args
(plisty-define org-roam-review-render-args
:optional (:group-on :nodes :placeholder :sort)
:required (:root-section))

View File

@@ -25,9 +25,9 @@
;;; Code:
(require 'dash)
(require 'plist)
(require 'plisty)
(plist-define org-tags-filter
(plisty-define org-tags-filter
:optional (:required :forbidden))
(defun org-tags-filter-parse (input)

View File

@@ -1,4 +1,4 @@
;;; plist.el --- Utilities for working with plists -*- lexical-binding: t; -*-
;;; plisty.el --- Utilities for working with plists -*- lexical-binding: t; -*-
;; Copyright (C) 2022 Chris Barrett
@@ -25,8 +25,7 @@
;;; Commentary:
;; Dinky little utilitity library for parsing plists around with basic
;; structural validation.
;; Dinky little utilitity library for defining simple schemas for plists.
;;; Code:
@@ -35,74 +34,74 @@
(require 'subr-x)
(require 'ht)
(defun plist-keys (plist)
(defun plisty-keys (plist)
(seq-map #'car (seq-partition plist 2)))
(defun plist-pick (key-or-keys plist)
(defun plisty-pick (key-or-keys plist)
(let ((keys (flatten-list (list key-or-keys)))
(ht (ht-from-plist plist)))
(ht-reject! (lambda (key _v) (not (seq-contains-p keys key)))
ht)
(ht-to-plist ht)))
(defun plist-omit (key-or-keys plist)
(defun plisty-omit (key-or-keys plist)
(let ((keys (flatten-list (list key-or-keys)))
(ht (ht-from-plist plist)))
(ht-reject! (lambda (key _v) (seq-contains-p keys key))
ht)
(ht-to-plist ht)))
(defun plist-map-keys (fn plist)
(defun plisty-map-keys (fn plist)
(let ((pairs (ht-map (lambda (k v)
(list (funcall fn k) v))
(ht-from-plist plist))))
(apply 'append pairs)))
(defun plist-merge (p1 p2)
(defun plisty-merge (p1 p2)
"Merge two plists, such that keys in P2 override duplicates in P1."
(let* ((h1 (ht-from-plist p1))
(h2 (ht-from-plist p2))
(merged (ht-merge h1 h2)))
(ht-to-plist merged)))
(defun plist-p (obj)
(defun plisty-p (obj)
"Return t if OBJ is a list and appears to be a plist with keyword keys."
(and (listp obj)
(cl-evenp (length obj))
(seq-every-p #'keywordp (plist-keys obj))))
(seq-every-p #'keywordp (plisty-keys obj))))
(defun plist-equal (p1 p2)
(defun plisty-equal (p1 p2)
"Test whether two plists P1 & P2 are structurally equal.
Values are compared using `equal', except directly nested plists,
which are compared using `plist-equal' recursively."
(cl-assert (plist-p p1) t)
(cl-assert (plist-p p2) t)
(cl-assert (plisty-p p1) t)
(cl-assert (plisty-p p2) t)
(catch 'not-equal
(when (equal (length p1) (length p2))
(dolist (key (plist-keys p1))
(dolist (key (plisty-keys p1))
(let ((v1 (plist-get p1 key))
(v2 (plist-get p2 key)))
(cond
((equal v1 v2))
((and (plist-p v1) (plist-p v2) (plist-equal v1 v2)))
((and (plisty-p v1) (plisty-p v2) (plisty-equal v1 v2)))
(t
(throw 'not-equal nil)))))
t)))
(defun plist--pred-name-for-type (type)
(defun plisty--pred-name-for-type (type)
(intern (format "%s-p" type)))
(defmacro plist-define-predicate (type required-keys all-keys)
(defmacro plisty-define-predicate (type required-keys all-keys)
(cl-assert (symbolp type))
(cl-assert (listp required-keys))
(cl-assert (seq-every-p #'keywordp required-keys))
(cl-assert (seq-every-p #'keywordp all-keys))
`(defun ,(plist--pred-name-for-type type) (value &optional strict)
`(defun ,(plisty--pred-name-for-type type) (value &optional strict)
(when (listp value)
(let ((required-keys ',required-keys)
(all-keys ',all-keys))
(let ((keys (plist-keys value)))
(let ((keys (plisty-keys value)))
(and (null (seq-difference required-keys keys))
(seq-every-p (lambda (key)
(plist-get value key))
@@ -111,19 +110,19 @@ which are compared using `plist-equal' recursively."
(null (seq-difference keys all-keys))
t)))))))
(defun plist--validator-for-type (type)
(defun plisty--validator-for-type (type)
(intern (format "%s-assert" type)))
(defmacro plist-define-validator (type required-keys all-keys)
(defmacro plisty-define-validator (type required-keys all-keys)
(cl-assert (symbolp type))
(cl-assert (listp required-keys))
(cl-assert (seq-every-p #'keywordp required-keys))
(cl-assert (seq-every-p #'keywordp all-keys))
`(defsubst ,(plist--validator-for-type type) (value &optional strict)
`(defsubst ,(plisty--validator-for-type type) (value &optional strict)
(cl-assert (listp value) t "Expected a plist" )
(let ((required-keys ',required-keys)
(all-keys ',all-keys)
(keys (plist-keys value)))
(keys (plisty-keys value)))
(cl-assert (null (seq-difference required-keys keys)) t "Missing required keys: %s" (seq-difference required-keys keys))
(cl-assert (seq-every-p (lambda (key)
(plist-get value key))
@@ -137,20 +136,20 @@ which are compared using `plist-equal' recursively."
"Unexpected additional keys: %s"
(seq-difference keys all-keys))))))
(defun plist--pred-accessor-name (type keyword)
(defun plisty--pred-accessor-name (type keyword)
(intern (format "%s-%s" type (string-remove-prefix ":" (symbol-name keyword)))))
(defmacro plist-define-getter (type key)
(defmacro plisty-define-getter (type key)
(cl-assert (symbolp type))
(cl-assert (keywordp key))
(let ((validator (plist--validator-for-type type)))
`(defun ,(plist--pred-accessor-name type key) (,type)
(let ((validator (plisty--validator-for-type type)))
`(defun ,(plisty--pred-accessor-name type key) (,type)
,(format "Lookup `%s' in a plist of type `%s'." key type)
(when (fboundp ',validator)
(,validator ,type))
(plist-get ,type ,key))))
(defun plist--format-create-fn-arglist (required optional)
(defun plisty--format-create-fn-arglist (required optional)
(if (or required optional)
(format "\n\n\(fn &key %s)"
(string-join (append (seq-map (lambda (it) (upcase (string-remove-prefix ":" (symbol-name it)))) required)
@@ -158,17 +157,17 @@ which are compared using `plist-equal' recursively."
" "))
""))
(defmacro plist-define-create (type required optional)
(defmacro plisty-define-create (type required optional)
(cl-assert (symbolp type))
(cl-assert (listp required))
(cl-assert (listp optional))
`(defun ,(intern (format "%s-create" type)) (&rest attrs)
,(format "Construct a value of type `%s'.%s"
type (plist--format-create-fn-arglist required optional))
(,(plist--validator-for-type type) attrs)
(plist-pick ',(-union required optional) attrs)))
type (plisty--format-create-fn-arglist required optional))
(,(plisty--validator-for-type type) attrs)
(plisty-pick ',(-union required optional) attrs)))
(cl-defmacro plist-define (type &key required optional)
(cl-defmacro plisty-define (type &key required optional)
(declare (indent 1))
(cl-assert (symbolp type))
(cl-assert (listp required))
@@ -176,12 +175,12 @@ which are compared using `plist-equal' recursively."
(cl-assert (null (seq-intersection required optional)))
(let ((keys (-union required optional)))
`(progn
(plist-define-predicate ,type ,required ,keys)
(plist-define-validator ,type ,required ,keys)
(plist-define-create ,type ,required ,optional)
,@(seq-map (lambda (it) `(plist-define-getter ,type ,it))
(plisty-define-predicate ,type ,required ,keys)
(plisty-define-validator ,type ,required ,keys)
(plisty-define-create ,type ,required ,optional)
,@(seq-map (lambda (it) `(plisty-define-getter ,type ,it))
keys))))
(provide 'plist)
(provide 'plisty)
;;; plist.el ends here
;;; plisty.el ends here