mirror of
https://github.com/SqrtMinusOne/biome.git
synced 2025-12-11 14:53:02 +03:00
biome-query: infix spam :'-(
This commit is contained in:
parent
648cb287f6
commit
1bc7a354ee
1 changed files with 169 additions and 37 deletions
206
biome-query.el
206
biome-query.el
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
(require 'biome-api-data)
|
(require 'biome-api-data)
|
||||||
|
(require 'font-lock)
|
||||||
(require 'compat)
|
(require 'compat)
|
||||||
(require 'transient)
|
(require 'transient)
|
||||||
|
|
||||||
|
|
@ -51,12 +52,17 @@ have to be displayed separately.")
|
||||||
It is an alist with the following keys:
|
It is an alist with the following keys:
|
||||||
- `:name' - name of the root section.
|
- `:name' - name of the root section.
|
||||||
- `:kind' - name of the group (see `biome-query-groups').
|
- `:kind' - name of the group (see `biome-query-groups').
|
||||||
- `:parameters' - alist with parameters, where the key is either nil
|
- `:params' - alist with parameters, where the key is either nil (for
|
||||||
(for global parameters) or the value of `:param' key of the
|
global parameters) or the value of `:param' key of the corresponding
|
||||||
corresponding section.
|
section.
|
||||||
In the former case, the value is an alist with values; in the latter
|
In the former case, the value is an alist with values; in the latter
|
||||||
case, the value is a list of variable names available in the group.")
|
case, the value is a list of variable names available in the group.")
|
||||||
|
|
||||||
|
(defvar biome-query--layout-cache (make-hash-table :test 'equal)
|
||||||
|
"Cache for dynamic transient layout.")
|
||||||
|
|
||||||
|
(setq biome-query--layout-cache (make-hash-table :test 'equal))
|
||||||
|
|
||||||
(defclass biome-query--transient-report (transient-suffix)
|
(defclass biome-query--transient-report (transient-suffix)
|
||||||
((transient :initform t))
|
((transient :initform t))
|
||||||
"A transient class to display the current report.")
|
"A transient class to display the current report.")
|
||||||
|
|
@ -73,6 +79,89 @@ It is an alist with the following keys:
|
||||||
:class 'biome-query--transient-report
|
:class 'biome-query--transient-report
|
||||||
:key "~~1")
|
:key "~~1")
|
||||||
|
|
||||||
|
(defclass biome-query--transient-path (transient-suffix)
|
||||||
|
((transient :initform t))
|
||||||
|
"A transient class to display the current path.")
|
||||||
|
|
||||||
|
(cl-defmethod transient-init-value ((_ biome-query--transient-path))
|
||||||
|
"A dummy method for `biome-query--transient-report'."
|
||||||
|
nil)
|
||||||
|
|
||||||
|
(cl-defmethod transient-format ((_ biome-query--transient-path))
|
||||||
|
"Format the current path."
|
||||||
|
(let* ((scope (oref (or transient--prefix
|
||||||
|
transient-current-prefix)
|
||||||
|
scope))
|
||||||
|
(parents (alist-get :parents scope))
|
||||||
|
(section (alist-get :section scope)))
|
||||||
|
(concat
|
||||||
|
(cl-loop for parent in (reverse parents)
|
||||||
|
concat (propertize
|
||||||
|
(alist-get :name parent)
|
||||||
|
'face 'font-lock-variable-name-face)
|
||||||
|
concat " > ")
|
||||||
|
(propertize
|
||||||
|
(alist-get :name section)
|
||||||
|
'face 'transient-heading))))
|
||||||
|
|
||||||
|
(transient-define-infix biome-query--transient-path-infix ()
|
||||||
|
:class 'biome-query--transient-path
|
||||||
|
:key "~~1")
|
||||||
|
|
||||||
|
(defclass biome-query--transient-switch-variable (transient-argument)
|
||||||
|
((name :initarg :name)
|
||||||
|
(param :initarg :param :initform nil))
|
||||||
|
"A transient class to display a switch.")
|
||||||
|
|
||||||
|
(cl-defmethod transient-init-value ((obj biome-query--transient-switch-variable))
|
||||||
|
(oset obj value
|
||||||
|
(not
|
||||||
|
(null
|
||||||
|
(member
|
||||||
|
(oref obj name)
|
||||||
|
(if-let ((param (oref obj param)))
|
||||||
|
(cdr
|
||||||
|
(assoc
|
||||||
|
param
|
||||||
|
(alist-get :params biome-query-current)))
|
||||||
|
(alist-get :params biome-query-current)))))))
|
||||||
|
|
||||||
|
(defmacro biome-query--update-list (item list-place add)
|
||||||
|
`(setf ,list-place
|
||||||
|
(if ,add
|
||||||
|
(cons ,item ,list-place)
|
||||||
|
(delete ,item ,list-place))))
|
||||||
|
|
||||||
|
(cl-defmethod transient-infix-read ((obj biome-query--transient-switch-variable))
|
||||||
|
"Toggle the switch on or off."
|
||||||
|
(setq my/test obj)
|
||||||
|
(let ((new-value (not (oref obj value)))
|
||||||
|
(param (oref obj param))
|
||||||
|
(name (oref obj name)))
|
||||||
|
(if param
|
||||||
|
(biome-query--update-list
|
||||||
|
name (alist-get param (alist-get :params biome-query-current) nil nil #'equal)
|
||||||
|
new-value)
|
||||||
|
(biome-query--update-list
|
||||||
|
name (alist-get :params biome-query-current nil nil #'equal)
|
||||||
|
new-value))
|
||||||
|
new-value))
|
||||||
|
|
||||||
|
(cl-defmethod transient-format ((obj biome-query--transient-switch-variable))
|
||||||
|
"Return a string generated using OBJ's `format'.
|
||||||
|
%k is formatted using `transient-format-key'.
|
||||||
|
%d is formatted using `transient-format-description'.
|
||||||
|
%v is formatted using `transient-format-value'."
|
||||||
|
(concat
|
||||||
|
(string-pad (transient-format-key obj) 6)
|
||||||
|
(transient-format-description obj)
|
||||||
|
(when (oref obj value)
|
||||||
|
(propertize " (+)" 'face 'transient-argument))))
|
||||||
|
|
||||||
|
(transient-define-infix biome-query--transient-switch-variable-infix ()
|
||||||
|
:class 'biome-query--transient-switch-variable
|
||||||
|
:key "~~1")
|
||||||
|
|
||||||
(defun biome-query--cartesian-product (a b)
|
(defun biome-query--cartesian-product (a b)
|
||||||
"Compute the Cartesian product of A and B."
|
"Compute the Cartesian product of A and B."
|
||||||
(mapcan
|
(mapcan
|
||||||
|
|
@ -159,28 +248,51 @@ NAMES is a list of strings."
|
||||||
do (puthash name key keys-by-name)))
|
do (puthash name key keys-by-name)))
|
||||||
keys-by-name))
|
keys-by-name))
|
||||||
|
|
||||||
(defun biome-query--section-fields-children (fields keys)
|
(defun biome-query--section-fields-children (fields keys parents cache-key)
|
||||||
"Get transient laoyut for FIELDS.
|
"Get transient laoyut for FIELDS.
|
||||||
|
|
||||||
FIELDS is a list of fields as defined in `biome-api-parse--page'.
|
FIELDS is a list of fields as defined in `biome-api-parse--page'.
|
||||||
KEYS is the result of `biome-query--unique-keys'."
|
KEYS is the result of `biome-query--unique-keys'. PARENTS is a list
|
||||||
|
of parent sections."
|
||||||
(when fields
|
(when fields
|
||||||
`(["Fields"
|
(let ((param (seq-some (lambda (s) (alist-get :param s)) parents))
|
||||||
:class transient-columns
|
(infix-name (concat "biome-query--transient-" cache-key "-")))
|
||||||
,@(thread-last
|
(cl-loop
|
||||||
fields
|
for field in fields
|
||||||
(seq-map-indexed
|
for field-api-key = (car field)
|
||||||
(lambda (field idx) (cons field (/ idx biome-query-max-fields-in-row))))
|
for name = (alist-get :name (cdr field))
|
||||||
(seq-group-by #'cdr)
|
for key = (gethash name keys)
|
||||||
(mapcar (lambda (group)
|
for type = (alist-get :type (cdr field))
|
||||||
(apply #'vector
|
for infix-symbol = (intern (concat infix-name field-api-key))
|
||||||
(mapcar
|
do (eval (pcase type
|
||||||
(lambda (el)
|
('checkbox
|
||||||
(let* ((field (car el))
|
`(transient-define-infix ,infix-symbol ()
|
||||||
(name (alist-get :name (cdr field))))
|
:class 'biome-query--transient-switch-variable
|
||||||
;; TODO
|
:key ,key
|
||||||
(list (gethash name keys) name #'transient-quit-one)))
|
:description ,name
|
||||||
(cdr group))))))])))
|
:argument ,name
|
||||||
|
:name ,name
|
||||||
|
:param ,param))
|
||||||
|
(_
|
||||||
|
`(transient-define-infix ,infix-symbol ()
|
||||||
|
:key ,key
|
||||||
|
:name ,name)))))
|
||||||
|
`(["Fields"
|
||||||
|
:class transient-columns
|
||||||
|
,@(thread-last
|
||||||
|
fields
|
||||||
|
(seq-map-indexed
|
||||||
|
(lambda (field idx) (cons field (/ idx biome-query-max-fields-in-row))))
|
||||||
|
(seq-group-by #'cdr)
|
||||||
|
(mapcar
|
||||||
|
(lambda (group)
|
||||||
|
(apply
|
||||||
|
#'vector
|
||||||
|
(mapcar
|
||||||
|
(lambda (el)
|
||||||
|
(let* ((field-api-key (caar el)))
|
||||||
|
(list (intern (concat infix-name field-api-key)))))
|
||||||
|
(cdr group))))))]))))
|
||||||
|
|
||||||
(defun biome-query--section-sections-children (sections keys parents)
|
(defun biome-query--section-sections-children (sections keys parents)
|
||||||
"Get transient layout for SECTIONS.
|
"Get transient layout for SECTIONS.
|
||||||
|
|
@ -201,21 +313,43 @@ list of parent sections."
|
||||||
:transient transient--do-replace))
|
:transient transient--do-replace))
|
||||||
sections)])))
|
sections)])))
|
||||||
|
|
||||||
|
(defmacro biome-query--with-layout-cache (cache-key &rest body)
|
||||||
|
"Cache layout for CACHE-KEY.
|
||||||
|
|
||||||
|
BODY is the body of the macro."
|
||||||
|
(declare (indent 1))
|
||||||
|
`(let ((layout (gethash ,cache-key biome-query--layout-cache)))
|
||||||
|
(if layout
|
||||||
|
layout
|
||||||
|
(let* ((cache-key ,cache-key)
|
||||||
|
(layout (progn ,@body)))
|
||||||
|
(puthash ,cache-key layout biome-query--layout-cache)
|
||||||
|
layout))))
|
||||||
|
|
||||||
(defun biome-query--section-layout (section parents)
|
(defun biome-query--section-layout (section parents)
|
||||||
"Get transient layout for SECTION.
|
"Get transient layout for SECTION.
|
||||||
|
|
||||||
SECTION is a form as defined by `biome-api-parse--page'. PARENTS
|
SECTION is a form as defined by `biome-api-parse--page'. PARENTS
|
||||||
is a list of parent sections."
|
is a list of parent sections."
|
||||||
(let* ((sections (or (alist-get :children section)
|
(biome-query--with-layout-cache
|
||||||
(alist-get :sections section)))
|
(string-join
|
||||||
(fields (alist-get :fields section))
|
(mapcar
|
||||||
(keys (biome-query--unique-keys
|
(lambda (s) (string-replace " " "-" s))
|
||||||
(append
|
(cons
|
||||||
(mapcar (lambda (s) (alist-get :name s)) sections)
|
(alist-get :name section)
|
||||||
(mapcar (lambda (s) (alist-get :name (cdr s))) fields)))))
|
(mapcar (lambda (s) (alist-get :name s)) parents)))
|
||||||
(append
|
"-")
|
||||||
(biome-query--section-fields-children fields keys)
|
(let* ((sections (or (alist-get :children section)
|
||||||
(biome-query--section-sections-children sections keys (cons section parents)))))
|
(alist-get :sections section)))
|
||||||
|
(fields (alist-get :fields section))
|
||||||
|
(keys (biome-query--unique-keys
|
||||||
|
(append
|
||||||
|
(mapcar (lambda (s) (alist-get :name s)) sections)
|
||||||
|
(mapcar (lambda (s) (alist-get :name (cdr s))) fields))))
|
||||||
|
(parents (cons section parents)))
|
||||||
|
(append
|
||||||
|
(biome-query--section-fields-children fields keys parents cache-key)
|
||||||
|
(biome-query--section-sections-children sections keys parents)))))
|
||||||
|
|
||||||
(defun biome-query--transient-prepare-layout (name suffixes)
|
(defun biome-query--transient-prepare-layout (name suffixes)
|
||||||
"Prepare dynamic transient layout for NAME.
|
"Prepare dynamic transient layout for NAME.
|
||||||
|
|
@ -234,13 +368,11 @@ SECTION is a form as defined in `biome-api-parse--page'."
|
||||||
(interactive (list nil))
|
(interactive (list nil))
|
||||||
(unwind-protect
|
(unwind-protect
|
||||||
(progn
|
(progn
|
||||||
(setq my/test section)
|
|
||||||
(biome-query--prepare-layout
|
(biome-query--prepare-layout
|
||||||
'biome-query--section
|
'biome-query--section
|
||||||
(append
|
(append
|
||||||
'([:description
|
'([(biome-query--transient-path-infix)])
|
||||||
(lambda () (alist-get :name (car (oref transient--prefix scope))))
|
'([(biome-query--transient-report-infix)])
|
||||||
(biome-query--transient-report-infix)])
|
|
||||||
(biome-query--section-layout section parents)
|
(biome-query--section-layout section parents)
|
||||||
'(["Actions"
|
'(["Actions"
|
||||||
:class transient-row
|
:class transient-row
|
||||||
|
|
@ -249,7 +381,7 @@ SECTION is a form as defined in `biome-api-parse--page'."
|
||||||
(transient-setup 'biome-query--section nil nil :scope
|
(transient-setup 'biome-query--section nil nil :scope
|
||||||
`((:section . ,section)
|
`((:section . ,section)
|
||||||
(:parents . ,parents))))
|
(:parents . ,parents))))
|
||||||
(put 'biome-query-section 'transient--layout nil)))
|
(put 'biome-query-section 'transient--layout nil)))
|
||||||
|
|
||||||
(transient-define-prefix biome-query ()
|
(transient-define-prefix biome-query ()
|
||||||
["Open Meteo Data"
|
["Open Meteo Data"
|
||||||
|
|
@ -268,7 +400,7 @@ SECTION is a form as defined in `biome-api-parse--page'."
|
||||||
(setq biome-query-current
|
(setq biome-query-current
|
||||||
'((:name . ,name)
|
'((:name . ,name)
|
||||||
(:kind . nil)
|
(:kind . nil)
|
||||||
(:parameters . nil))))
|
(:params . nil))))
|
||||||
(biome-query--section ',params))
|
(biome-query--section ',params))
|
||||||
:transient transient--do-replace))))]
|
:transient transient--do-replace))))]
|
||||||
["Actions"
|
["Actions"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue