basic UI and gradient formatting works

This commit is contained in:
Pavel Korytov 2023-07-21 22:32:56 +03:00
parent eb240166ac
commit f60e6c047b
4 changed files with 115 additions and 25 deletions

View file

@ -68,7 +68,7 @@ QUERY is a form as defined by `biome-query-current'."
(cons (cons
(car item) (car item)
(cond (cond
((listp (cdr item)) (mapconcat #'identity (cdr item) ",")) ((listp (cdr item)) (mapconcat #'identity (reverse (cdr item)) ","))
(t (cdr item))))))) (t (cdr item)))))))
(alist-get :params query))) (alist-get :params query)))
@ -114,7 +114,7 @@ QUERY is a form as defined by `biome-query-current'."
"Get data from Open Meteo API. "Get data from Open Meteo API.
QUERY is a form as defined by `biome-query-current'. CALLBACK is QUERY is a form as defined by `biome-query-current'. CALLBACK is
called with the data as its only argument." called with QUERY and the data returned by the API as arguments."
(let ((url (alist-get (alist-get :name query) (let ((url (alist-get (alist-get :name query)
biome-api-urls nil nil #'equal))) biome-api-urls nil nil #'equal)))
(request url (request url
@ -123,7 +123,7 @@ called with the data as its only argument."
:parser #'json-read :parser #'json-read
:success (cl-function :success (cl-function
(lambda (&key data &allow-other-keys) (lambda (&key data &allow-other-keys)
(funcall callback data))) (funcall callback (copy-tree query) data)))
:error :error
(cl-function (lambda (&key error-thrown response &allow-other-keys) (cl-function (lambda (&key error-thrown response &allow-other-keys)
(biome-api--show-error error-thrown response)))))) (biome-api--show-error error-thrown response))))))

View file

@ -26,29 +26,77 @@
;;; Code: ;;; Code:
(require 'cl-lib) (require 'cl-lib)
(require 'biome-query) (require 'ct)
(require 'seq)
(require 'tabulated-list) (require 'tabulated-list)
(require 'biome-query)
(defcustom biome-grid-display-units t (defcustom biome-grid-display-units t
"Display units in the grid." "Display units in the grid."
:type 'boolean :type 'boolean
:group 'biome) :group 'biome)
(defcustom biome-grid-format-units
'(("°C" . (gradient
(-40 . "#ae64a0")
(-30 . "#9488d2")
(-15 . "#90cfd2")
(-5 . "#66adbb")
(5 . "#508c40")
(15 . "#aba10e")
(25 . "#f39506")
(35 . "#bf4112")
(40 . "#8a2b0a"))))
"Format units in the grid."
:group 'biome)
(defvar biome-grid-mode-map
(let ((keymap (make-sparse-keymap)))
(define-key keymap (kbd "q") #'quit-window)
(when (fboundp 'evil-define-key*)
(evil-define-key* 'normal keymap
"q" #'quit-window))
keymap)
"Keymap for `biome-api-error-mode'.")
(define-derived-mode biome-grid-mode tabulated-list-mode "Biome Grid" (define-derived-mode biome-grid-mode tabulated-list-mode "Biome Grid"
"Major mode for displaying biome results." "Major mode for displaying biome results.")
(setq-local truncate-lines t))
(defun biome-grid--format-entries (entries unit) (defun biome-grid--blend-colors (c1 c2 val)
(mapcar "Blend colors C1 and C2 by VAL.
(lambda (entry)
(if (stringp entry)
entry
(prin1-to-string entry)))
entries))
(defun biome-grid--get-width (entries col-name) C1 and C2 are hex RGS strings, VAL is a number between 0 and 1."
(cl-loop for entry in (cons col-name entries) (let ((color1 (ct-get-rgb c1))
maximize (length entry))) (color2 (ct-get-rgb c2)))
(apply #'ct-make-rgb
(cl-loop for v1 in color1
for v2 in color2
collect (+ (* (- 1 val) v1) (* val v2))))))
(defun biome-grid--format-gradient (value def col-width)
(let* ((background-color
(cl-loop for (border1 . color1) in def
for (border2 . color2) in (cdr def)
if (< value border1) return color1
if (and (>= value border1) (<= value border2))
return (biome-grid--blend-colors
color1 color2 (/ (- value border1) (- border2 border1)))
finally return color2))
(foreground-color (if (ct-light-p background-color 65) "#000000" "#ffffff")))
(propertize
(format (format "%%%ds" col-width) value)
'face `(:background ,background-color :foreground ,foreground-color))))
(defun biome-grid--format-entries (entries unit col-width)
(let ((format-def (alist-get unit biome-grid-format-units nil nil #'equal)))
(mapcar
(lambda (entry)
(cond
((stringp entry) entry)
((eq (car-safe format-def) 'gradient)
(biome-grid--format-gradient entry (cdr format-def) col-width))
(t (prin1-to-string entry))))
entries)))
(defun biome-grid--set-list (query results) (defun biome-grid--set-list (query results)
(let* ((group (intern (alist-get :group query))) (let* ((group (intern (alist-get :group query)))
@ -56,13 +104,16 @@
(var-names (biome-query--get-var-names-cache)) (var-names (biome-query--get-var-names-cache))
all-entries columns) all-entries columns)
(cl-loop for (key . values) in (alist-get group results) (cl-loop for (key . values) in (alist-get group results)
for unit = (alist-get key (alist-get group-units results)) for unit = (replace-regexp-in-string
(regexp-quote "%") "%%"
(alist-get key (alist-get group-units results)))
for var-name = (biome-query--get-header (symbol-name key) var-names) for var-name = (biome-query--get-header (symbol-name key) var-names)
for col-name = (if biome-grid-display-units for col-name = (if biome-grid-display-units
(format "%s (%s)" var-name unit) (format "%s (%s)" var-name unit)
var-name) var-name)
for entries = (biome-grid--format-entries values unit) for col-width = (cl-loop for entry in (cons col-name entries)
for col-width = (biome-grid--get-width entries col-name) maximize (+ 0 (length entry)))
for entries = (biome-grid--format-entries values unit col-width)
do (push (list col-name col-width nil) columns) do (push (list col-name col-width nil) columns)
do (push entries all-entries)) do (push entries all-entries))
(setq-local (setq-local
@ -82,11 +133,13 @@
(defun biome-grid (query results) (defun biome-grid (query results)
"Display RESULTS in a grid." "Display RESULTS in a grid."
(setq my/test results)
(let ((buf (generate-new-buffer "*biome-grid*"))) (let ((buf (generate-new-buffer "*biome-grid*")))
(with-current-buffer buf (with-current-buffer buf
(biome-grid--set-list query results) (biome-grid--set-list query results)
(biome-grid-mode)) (biome-grid-mode)
(display-buffer buf #'display-buffer-same-window))) (toggle-truncate-lines 1))
(switch-to-buffer buf)))
(provide 'biome-grid) (provide 'biome-grid)
;;; biome-grid.el ends here ;;; biome-grid.el ends here

View file

@ -54,7 +54,8 @@ value will be inserted."
:group 'biome) :group 'biome)
(defcustom biome-query-coords '(("Helsinki, Finland" 60.16952 24.93545) (defcustom biome-query-coords '(("Helsinki, Finland" 60.16952 24.93545)
("Berlin, Germany" 52.52437 13.41053)) ("Berlin, Germany" 52.52437 13.41053)
("Dubai, UAE" 25.0657 55.17128))
"List of locations with their coordinates. "List of locations with their coordinates.
The format is: (name latitude longitude)." The format is: (name latitude longitude)."
@ -99,6 +100,9 @@ case, the value is a list of variable names available in the group.")
(defvar biome-query--var-names-cache nil (defvar biome-query--var-names-cache nil
"Cache for variable names.") "Cache for variable names.")
(defvar biome-query--callback nil
"Call this with the selected query.")
;; TODO delete this ;; TODO delete this
(setq biome-query--layout-cache (make-hash-table :test 'equal)) (setq biome-query--layout-cache (make-hash-table :test 'equal))
@ -880,6 +884,13 @@ SUFFIXES is a list of suffix definitions."
(:group . ,(caar (biome-query--section-groups biome-query--current-section))) (:group . ,(caar (biome-query--section-groups biome-query--current-section)))
(:params . nil))))) (:params . nil)))))
(defun biome-query--on-return ()
"Process the query made by `biome-query'."
(interactive)
(unless biome-query--callback
(user-error "Biome-query--callback is not set"))
(funcall biome-query--callback biome-query-current))
(transient-define-prefix biome-query--section (section &optional parents) (transient-define-prefix biome-query--section (section &optional parents)
"Render transient for SECTION. "Render transient for SECTION.
@ -897,6 +908,7 @@ SECTION is a form as defined in `biome-api-parse--page'."
(biome-query--section-layout section parents) (biome-query--section-layout section parents)
`(["Actions" `(["Actions"
:class transient-row :class transient-row
("RET" "Run" biome-query--on-return)
("q" "Up" transient-quit-one) ("q" "Up" transient-quit-one)
("Q" "Quit" transient-quit-all) ("Q" "Quit" transient-quit-all)
,(unless parents ,(unless parents
@ -906,7 +918,7 @@ SECTION is a form as defined in `biome-api-parse--page'."
(: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 (callback)
["Open Meteo Data" ["Open Meteo Data"
:setup-children :setup-children
(lambda (_) (lambda (_)
@ -925,7 +937,12 @@ SECTION is a form as defined in `biome-api-parse--page'."
(biome-query--section ',params)) (biome-query--section ',params))
:transient transient--do-replace))))] :transient transient--do-replace))))]
["Actions" ["Actions"
("q" "Quit" transient-quit-one)]) ("q" "Quit" transient-quit-one)]
(interactive (list nil))
(unless callback
(error "Callback is not set. Run M-x `biome' instead"))
(setq biome-query--callback callback)
(transient-setup 'biome-query))
(provide 'biome-query) (provide 'biome-query)
;;; biome-query.el ends here ;;; biome-query.el ends here

View file

@ -5,7 +5,7 @@
;; Author: Korytov Pavel <thexcloud@gmail.com> ;; Author: Korytov Pavel <thexcloud@gmail.com>
;; Maintainer: Korytov Pavel <thexcloud@gmail.com> ;; Maintainer: Korytov Pavel <thexcloud@gmail.com>
;; Version: 0.1.0 ;; Version: 0.1.0
;; Package-Requires: ((emacs "27.1")) ;; Package-Requires: ((emacs "27.1") (transient "0.3.7") (ct "0.2") (request "0.3.3") (compat "29.1.4.1"))
;; Homepage: https://github.com/SqrtMinusOne/biome ;; Homepage: https://github.com/SqrtMinusOne/biome
;; This file is NOT part of GNU Emacs. ;; This file is NOT part of GNU Emacs.
@ -28,9 +28,29 @@
;; TODO ;; TODO
;;; Code: ;;; Code:
(require 'biome-api)
(require 'biome-query)
(require 'biome-grid)
(defgroup biome nil (defgroup biome nil
"Bountiful Interface to Open Meteo for Emacs." "Bountiful Interface to Open Meteo for Emacs."
:group 'applications) :group 'applications)
(defcustom biome-frontend #'biome-grid
"The frontend to use for displaying the data.
This has to be a function that receives two arguments: query (as
defined by `biome-query-current' and the response of the open-meteo
API."
:type 'function
:group 'biome)
(defun biome ()
"Bountiful Interface to Open Meteo for Emacs."
(interactive)
(biome-query
(lambda (query)
(biome-api-get query biome-frontend))))
(provide 'biome) (provide 'biome)
;;; biome.el ends here ;;; biome.el ends here