mirror of
https://github.com/SqrtMinusOne/biome.git
synced 2025-12-11 14:53:02 +03:00
*: make proper docs
This commit is contained in:
parent
f3717600ec
commit
3c8b1918d0
5 changed files with 176 additions and 56 deletions
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
(require 'browse-url)
|
(require 'browse-url)
|
||||||
|
(require 'dom)
|
||||||
(require 'cl-lib)
|
(require 'cl-lib)
|
||||||
(require 'seq)
|
(require 'seq)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
;; TODO
|
;; Make requests to Open Meteo API.
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
(require 'json)
|
(require 'json)
|
||||||
|
|
@ -46,14 +46,13 @@
|
||||||
"Default URLs for Open Meteo API.")
|
"Default URLs for Open Meteo API.")
|
||||||
|
|
||||||
(defcustom biome-api-urls biome-api--default-urls
|
(defcustom biome-api-urls biome-api--default-urls
|
||||||
"URL of the Open Meteo API."
|
"URLs of the Open Meteo API."
|
||||||
:type `(alist
|
:type `(alist
|
||||||
:key-type string
|
:key-type string
|
||||||
:value-type string
|
:value-type string
|
||||||
:options ,(mapcar #'car biome-api--default-urls))
|
:options ,(mapcar #'car biome-api--default-urls))
|
||||||
:group 'biome)
|
:group 'biome)
|
||||||
|
|
||||||
|
|
||||||
(defun biome-api--get-params (query)
|
(defun biome-api--get-params (query)
|
||||||
"Convert QUERY to a list of parameters for `request'.
|
"Convert QUERY to a list of parameters for `request'.
|
||||||
|
|
||||||
|
|
@ -87,7 +86,7 @@ QUERY is a form as defined by `biome-query-current'."
|
||||||
"Keymap for `biome-api-error-mode'.")
|
"Keymap for `biome-api-error-mode'.")
|
||||||
|
|
||||||
(define-derived-mode biome-api-error-mode text-mode "Lyrics view"
|
(define-derived-mode biome-api-error-mode text-mode "Lyrics view"
|
||||||
"Major mode for viewing open meteo errors.
|
"Major mode for viewing open meteo API errors.
|
||||||
|
|
||||||
\\{biome-api-error-mode-map}"
|
\\{biome-api-error-mode-map}"
|
||||||
(read-only-mode 1))
|
(read-only-mode 1))
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
;; TODO
|
;; Display results of open meteo queries with `tabulated-list'.
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
(require 'cl-lib)
|
(require 'cl-lib)
|
||||||
|
|
@ -38,6 +38,9 @@
|
||||||
:group 'biome)
|
:group 'biome)
|
||||||
|
|
||||||
(defun biome-grid--format-units (format)
|
(defun biome-grid--format-units (format)
|
||||||
|
"Add derived units to FORMAT.
|
||||||
|
|
||||||
|
FORMAT is an expression as defined by `biome-grid-format'."
|
||||||
(nreverse
|
(nreverse
|
||||||
(reduce (lambda (acc def)
|
(reduce (lambda (acc def)
|
||||||
(push def acc)
|
(push def acc)
|
||||||
|
|
@ -278,8 +281,29 @@
|
||||||
(nil "is_day" is-day)
|
(nil "is_day" is-day)
|
||||||
("wmo code" nil wmo-code)
|
("wmo code" nil wmo-code)
|
||||||
("°" nil direction)))
|
("°" nil direction)))
|
||||||
"Format units in the grid."
|
"Format units in the grid.
|
||||||
:group 'biome)
|
|
||||||
|
This is a list with the following keys:
|
||||||
|
- unit;
|
||||||
|
- parameter (regexp);
|
||||||
|
- format defintion.
|
||||||
|
|
||||||
|
The format definition is one of the following:
|
||||||
|
- (gradient (value . color) ...);
|
||||||
|
- `is-day';
|
||||||
|
- `wmo-code';
|
||||||
|
- `direction'."
|
||||||
|
:group 'biome
|
||||||
|
:type '(repeat (list
|
||||||
|
(choice :tag "Unit" (const :tag "No unit" nil) string)
|
||||||
|
(choice :tag "Parameter (regexp)" (const :tag "No parameter" nil) string)
|
||||||
|
(choice
|
||||||
|
(cons (const gradient)
|
||||||
|
(alist :key-type (number :tag "Value")
|
||||||
|
:value-type (string :tag "HEX color")))
|
||||||
|
(const :tag "Is day" is-day)
|
||||||
|
(const :tag "WMO code" wmo-code)
|
||||||
|
(const :tag "Direction" direction)))))
|
||||||
|
|
||||||
(defcustom biome-grid-wmo-codes
|
(defcustom biome-grid-wmo-codes
|
||||||
'((0 "☀️" "Clear sky")
|
'((0 "☀️" "Clear sky")
|
||||||
|
|
@ -312,7 +336,7 @@
|
||||||
(99 "⛈️" "Thunderstorm with hail (heavy)"))
|
(99 "⛈️" "Thunderstorm with hail (heavy)"))
|
||||||
"Descriptions for WMO weather codes.
|
"Descriptions for WMO weather codes.
|
||||||
|
|
||||||
The defaults values are takes from open-meteo docs."
|
The defaults values are taken from open-meteo docs."
|
||||||
:group 'biome
|
:group 'biome
|
||||||
:type '(alist :key-type number :value-type (list string string)))
|
:type '(alist :key-type number :value-type (list string string)))
|
||||||
|
|
||||||
|
|
@ -336,12 +360,13 @@ The defaults values are takes from open-meteo docs."
|
||||||
(360 "↑ N"))
|
(360 "↑ N"))
|
||||||
"Descriptions for directions."
|
"Descriptions for directions."
|
||||||
:group 'biome
|
:group 'biome
|
||||||
:type '(repeat (list number string)))
|
:type '(repeat (list (number :tag "Value (0-360)")
|
||||||
|
(string :tag "Description"))))
|
||||||
|
|
||||||
(defcustom biome-grid-is-day-format '("🌙 night" "☀️ day")
|
(defcustom biome-grid-is-day-format '("🌙 night" "☀️ day")
|
||||||
"Format for is-day values."
|
"Format for is-day values."
|
||||||
:group 'biome
|
:group 'biome
|
||||||
:type '(repeat string))
|
:type '(list (string :tag "Night") (string :tag "Day")))
|
||||||
|
|
||||||
(defcustom biome-grid-wmo-show-emoji t
|
(defcustom biome-grid-wmo-show-emoji t
|
||||||
"Show emoji for WMO weather codes."
|
"Show emoji for WMO weather codes."
|
||||||
|
|
@ -371,6 +396,10 @@ C1 and C2 are hex RGS strings, VAL is a number between 0 and 1."
|
||||||
collect (+ (* (- 1 val) v1) (* val v2))))))
|
collect (+ (* (- 1 val) v1) (* val v2))))))
|
||||||
|
|
||||||
(defun biome-grid--format-gradient (value def col-width)
|
(defun biome-grid--format-gradient (value def col-width)
|
||||||
|
"Format VALUE with gradient DEF.
|
||||||
|
|
||||||
|
DEF is a list of (value . color) pairs. COL-WIDTH is the width of the
|
||||||
|
column."
|
||||||
(setq value (float value))
|
(setq value (float value))
|
||||||
(let* ((background-color
|
(let* ((background-color
|
||||||
(cl-loop for (border1 . color1) in def
|
(cl-loop for (border1 . color1) in def
|
||||||
|
|
@ -388,7 +417,7 @@ C1 and C2 are hex RGS strings, VAL is a number between 0 and 1."
|
||||||
(defun biome-grid--format-wmo-code (value)
|
(defun biome-grid--format-wmo-code (value)
|
||||||
"Format WMO code.
|
"Format WMO code.
|
||||||
|
|
||||||
VALUE is a WMO number."
|
VALUE is a WMO number as defined in `biome-grid-wmo-codes'."
|
||||||
(let ((format (alist-get value biome-grid-wmo-codes)))
|
(let ((format (alist-get value biome-grid-wmo-codes)))
|
||||||
(if format
|
(if format
|
||||||
(if biome-grid-wmo-show-emoji
|
(if biome-grid-wmo-show-emoji
|
||||||
|
|
@ -415,12 +444,21 @@ VALUE is 0 or 1."
|
||||||
(nth value biome-grid-is-day-format))
|
(nth value biome-grid-is-day-format))
|
||||||
|
|
||||||
(defun biome-grid--get-format-def (col-key unit)
|
(defun biome-grid--get-format-def (col-key unit)
|
||||||
|
"Get format definition for COL-KEY and UNIT."
|
||||||
(cl-loop for (unit-def col-key-def format-def) in biome-grid-format
|
(cl-loop for (unit-def col-key-def format-def) in biome-grid-format
|
||||||
if (and (or (null unit-def) (equal unit unit-def))
|
if (and (or (null unit-def) (equal unit unit-def))
|
||||||
(or (null col-key-def) (string-match-p col-key-def (symbol-name col-key))))
|
(or (null col-key-def) (string-match-p col-key-def
|
||||||
|
(symbol-name col-key))))
|
||||||
return format-def))
|
return format-def))
|
||||||
|
|
||||||
(defun biome-grid--prepare-entries (entries col-key unit)
|
(defun biome-grid--prepare-entries (entries col-key unit)
|
||||||
|
"Prepare entries for display.
|
||||||
|
|
||||||
|
This function performs all changes that may affect the width of the
|
||||||
|
column.
|
||||||
|
|
||||||
|
ENTRIES is a list of values. COL-KEY is the column key as given by
|
||||||
|
the API. UNIT is the unit of the column."
|
||||||
(let ((format-def (biome-grid--get-format-def col-key unit)))
|
(let ((format-def (biome-grid--get-format-def col-key unit)))
|
||||||
(mapcar
|
(mapcar
|
||||||
(lambda (entry)
|
(lambda (entry)
|
||||||
|
|
@ -436,6 +474,13 @@ VALUE is 0 or 1."
|
||||||
entries)))
|
entries)))
|
||||||
|
|
||||||
(defun biome-grid--format-entries (entries col-key unit col-width)
|
(defun biome-grid--format-entries (entries col-key unit col-width)
|
||||||
|
"Format entries for display.
|
||||||
|
|
||||||
|
This uses the width COL-WIDTH for each column, therefore it must not change
|
||||||
|
that width.
|
||||||
|
|
||||||
|
ENTRIES is a list of values. COL-KEY is the column key as given by
|
||||||
|
the API. UNIT is the unit of the column."
|
||||||
(let ((format-def (biome-grid--get-format-def col-key unit)))
|
(let ((format-def (biome-grid--get-format-def col-key unit)))
|
||||||
(mapcar
|
(mapcar
|
||||||
(lambda (entry)
|
(lambda (entry)
|
||||||
|
|
@ -448,6 +493,9 @@ VALUE is 0 or 1."
|
||||||
entries)))
|
entries)))
|
||||||
|
|
||||||
(defun biome-grid--get-col-witdh (col-name entries unit)
|
(defun biome-grid--get-col-witdh (col-name entries unit)
|
||||||
|
"Get the width of the column COL-NAME.
|
||||||
|
|
||||||
|
ENTRIES is a list of values. UNIT is the unit of the column."
|
||||||
(let ((col-name-width (length col-name))
|
(let ((col-name-width (length col-name))
|
||||||
(entry-width
|
(entry-width
|
||||||
(or (cl-loop for entry in entries
|
(or (cl-loop for entry in entries
|
||||||
|
|
@ -457,10 +505,15 @@ VALUE is 0 or 1."
|
||||||
;; XXX this is necessary to compensate for emojis of different
|
;; XXX this is necessary to compensate for emojis of different
|
||||||
;; actual width. Forunately this doesn't break the formmating of
|
;; actual width. Forunately this doesn't break the formmating of
|
||||||
;; the grid (hail `tabulated-list', what a pleasant surprise)
|
;; the grid (hail `tabulated-list', what a pleasant surprise)
|
||||||
(cond ((and (equal unit "wmo code") biome-grid-wmo-show-emoji) (max col-name-width (+ 1 entry-width)))
|
(cond ((and (equal unit "wmo code") biome-grid-wmo-show-emoji)
|
||||||
|
(max col-name-width (+ 1 entry-width)))
|
||||||
(t (max col-name-width (+ 1 entry-width))))))
|
(t (max col-name-width (+ 1 entry-width))))))
|
||||||
|
|
||||||
(defun biome-grid--set-list (query results)
|
(defun biome-grid--set-list (query results)
|
||||||
|
"Set the list of the grid for the `biome-grid-mode' buffer.
|
||||||
|
|
||||||
|
QUERY is a form as defined by `biome-query-current'. RESULTS is a
|
||||||
|
response of the API."
|
||||||
(let* ((group (intern (alist-get :group query)))
|
(let* ((group (intern (alist-get :group query)))
|
||||||
(group-units (intern (format "%s_units" (alist-get :group query))))
|
(group-units (intern (format "%s_units" (alist-get :group query))))
|
||||||
(var-names (biome-query--get-var-names-cache))
|
(var-names (biome-query--get-var-names-cache))
|
||||||
|
|
@ -514,6 +567,10 @@ it, in which case it is killed."
|
||||||
(kill-buffer)))
|
(kill-buffer)))
|
||||||
|
|
||||||
(defun biome-grid--update-columns (columns)
|
(defun biome-grid--update-columns (columns)
|
||||||
|
"Update the columns of the grid.
|
||||||
|
|
||||||
|
COLUMNS is a list of column names prefixed with \"--\" (to work with
|
||||||
|
transient switches)."
|
||||||
(interactive (list (transient-args transient-current-command)))
|
(interactive (list (transient-args transient-current-command)))
|
||||||
(setq biome-grid--columns-display
|
(setq biome-grid--columns-display
|
||||||
(cl-loop for (key name _display) in biome-grid--columns-display
|
(cl-loop for (key name _display) in biome-grid--columns-display
|
||||||
|
|
@ -523,7 +580,7 @@ it, in which case it is killed."
|
||||||
(tabulated-list-init-header))
|
(tabulated-list-init-header))
|
||||||
|
|
||||||
(transient-define-prefix biome-grid-columns ()
|
(transient-define-prefix biome-grid-columns ()
|
||||||
"Toggle columns in biome-grid buffer."
|
"Toggle columns in `biome-grid' buffer."
|
||||||
["Toggle columns"
|
["Toggle columns"
|
||||||
:setup-children
|
:setup-children
|
||||||
(lambda (_)
|
(lambda (_)
|
||||||
|
|
@ -558,13 +615,19 @@ it, in which case it is killed."
|
||||||
"Keymap for `biome-grid-mode'.")
|
"Keymap for `biome-grid-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.
|
||||||
|
|
||||||
|
\\{biome-grid-mode-map}")
|
||||||
|
|
||||||
(defun biome-grid (query results)
|
(defun biome-grid (query results)
|
||||||
"Display RESULTS in a grid.
|
"Display RESULTS in a grid.
|
||||||
|
|
||||||
QUERY is a form as defined by `biome-query-current'. RESULTS is a
|
QUERY is a form as defined by `biome-query-current'. RESULTS is a
|
||||||
response of Open Meteo (returned by `biome-api-get'."
|
response of Open Meteo (returned by `biome-api-get'.
|
||||||
|
|
||||||
|
The grid is displayed with `tabulated-list'. It doesn't support
|
||||||
|
displaying more columns than the window width, so there's
|
||||||
|
`biome-grid-columns' to toggle columns."
|
||||||
(let ((buf (generate-new-buffer "*biome-grid*")))
|
(let ((buf (generate-new-buffer "*biome-grid*")))
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(biome-grid-mode)
|
(biome-grid-mode)
|
||||||
|
|
|
||||||
125
biome-query.el
125
biome-query.el
|
|
@ -22,7 +22,12 @@
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
;; TODO
|
;; Query editor for Open Meteo API.
|
||||||
|
;;
|
||||||
|
;; The main entrypoints are:
|
||||||
|
;; - `biome-query' - start a new query.
|
||||||
|
;; - `biome-query--section-open' - start a new query in a section.
|
||||||
|
;; These aren't meant to be used directly by the user.
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
(require 'biome-api-data)
|
(require 'biome-api-data)
|
||||||
|
|
@ -42,7 +47,7 @@
|
||||||
:group 'biome)
|
:group 'biome)
|
||||||
|
|
||||||
(defcustom biome-query-date-format "%A, %x"
|
(defcustom biome-query-date-format "%A, %x"
|
||||||
"Format string for date entries.
|
"Format string for date entries in query buffers.
|
||||||
|
|
||||||
By default \"WEEKDAY, DATE\", where DATE is what Emacs thinks is an
|
By default \"WEEKDAY, DATE\", where DATE is what Emacs thinks is an
|
||||||
appropriate way to format days in your language.
|
appropriate way to format days in your language.
|
||||||
|
|
@ -56,10 +61,13 @@ value will be inserted."
|
||||||
(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))
|
("Dubai, UAE" 25.0657 55.17128))
|
||||||
"List of locations with their coordinates.
|
"List of saved locations with their coordinates.
|
||||||
|
|
||||||
The format is: (name latitude longitude)."
|
The format is: (name latitude longitude)."
|
||||||
:type '(repeat (list string number number))
|
:type '(repeat (list
|
||||||
|
(string :tag "Name")
|
||||||
|
(number :tag "Latitude")
|
||||||
|
(number :tag "Longitude")))
|
||||||
:group 'biome)
|
:group 'biome)
|
||||||
|
|
||||||
(defconst biome-query-groups '("daily" "hourly" "minutely_15" "hourly")
|
(defconst biome-query-groups '("daily" "hourly" "minutely_15" "hourly")
|
||||||
|
|
@ -80,20 +88,18 @@ have to be displayed separately.")
|
||||||
"Items to ignore when generating unique keys.")
|
"Items to ignore when generating unique keys.")
|
||||||
|
|
||||||
(defvar biome-query-current nil
|
(defvar biome-query-current nil
|
||||||
"Current report.
|
"Current query.
|
||||||
|
|
||||||
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.
|
||||||
- `:group' - name of the group (see `biome-query-groups').
|
- `:group' - name of the group (see `biome-query-groups').
|
||||||
- `:params' - alist with parameters, where the key is either nil (for
|
- `:params' - alist with parameters, where the key is either the
|
||||||
global parameters) or the value of `:param' key of the corresponding
|
parameter name (for global variables) or the group name (for grouped
|
||||||
section.
|
variables, e.g. hourly, daily). In the latter case, the value has
|
||||||
|
to be a list of grouped variables names.")
|
||||||
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.")
|
|
||||||
|
|
||||||
(defvar biome-query--current-section nil
|
(defvar biome-query--current-section nil
|
||||||
"Current section.")
|
"Current section definition.")
|
||||||
|
|
||||||
(defvar biome-query--layout-cache (make-hash-table :test 'equal)
|
(defvar biome-query--layout-cache (make-hash-table :test 'equal)
|
||||||
"Cache for dynamic transient layout.")
|
"Cache for dynamic transient layout.")
|
||||||
|
|
@ -104,19 +110,22 @@ case, the value is a list of variable names available in the group.")
|
||||||
(defvar biome-query--callback nil
|
(defvar biome-query--callback nil
|
||||||
"Call this with the selected query.")
|
"Call this with the selected query.")
|
||||||
|
|
||||||
;; TODO delete this
|
|
||||||
(setq biome-query--layout-cache (make-hash-table :test 'equal))
|
|
||||||
|
|
||||||
;; Transient display classes
|
;; Transient display classes
|
||||||
(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.
|
||||||
|
|
||||||
|
This just prints out `biome-query-current' in somewhat readable
|
||||||
|
form.")
|
||||||
|
|
||||||
(cl-defmethod transient-init-value ((_ biome-query--transient-report))
|
(cl-defmethod transient-init-value ((_ biome-query--transient-report))
|
||||||
"A dummy method for `biome-query--transient-report'."
|
"A dummy method for `biome-query--transient-report'."
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
(defun biome-query--update-names-cache (sections cache)
|
(defun biome-query--update-names-cache (sections cache)
|
||||||
|
"Update the variable names cache for SECTIONS.
|
||||||
|
|
||||||
|
CACHE is a hash table. See `biome-query--get-var-names-cache'."
|
||||||
(cl-loop for section in sections
|
(cl-loop for section in sections
|
||||||
do (when-let (fields (alist-get :fields section))
|
do (when-let (fields (alist-get :fields section))
|
||||||
(cl-loop for (api-key . params) in fields
|
(cl-loop for (api-key . params) in fields
|
||||||
|
|
@ -126,6 +135,14 @@ case, the value is a list of variable names available in the group.")
|
||||||
(biome-query--update-names-cache children cache))))
|
(biome-query--update-names-cache children cache))))
|
||||||
|
|
||||||
(defun biome-query--get-var-names-cache ()
|
(defun biome-query--get-var-names-cache ()
|
||||||
|
"Generate variable names cache for the current section.
|
||||||
|
|
||||||
|
The current section is determined by `biome-query-current'. The
|
||||||
|
return value is a hashmap with variable api keys as keys and their
|
||||||
|
names as values.
|
||||||
|
|
||||||
|
This is useful because otherwise it would take a long time to look for
|
||||||
|
disambiguations of parameters in `biome-api-data'."
|
||||||
(let* ((name (alist-get :name biome-query-current))
|
(let* ((name (alist-get :name biome-query-current))
|
||||||
(cache (alist-get name biome-query--var-names-cache
|
(cache (alist-get name biome-query--var-names-cache
|
||||||
nil nil #'equal)))
|
nil nil #'equal)))
|
||||||
|
|
@ -139,12 +156,16 @@ case, the value is a list of variable names available in the group.")
|
||||||
cache))))
|
cache))))
|
||||||
|
|
||||||
(defun biome-query--get-header (key var-names)
|
(defun biome-query--get-header (key var-names)
|
||||||
|
"Generate readable name for KEY with a fallback.
|
||||||
|
|
||||||
|
KEY is the api key of the variable. VAR-NAMES is the output of
|
||||||
|
`biome-query--get-var-names-cache'."
|
||||||
(gethash key var-names
|
(gethash key var-names
|
||||||
(capitalize (replace-regexp-in-string
|
(capitalize (replace-regexp-in-string
|
||||||
(regexp-quote "_") " " key))))
|
(regexp-quote "_") " " key))))
|
||||||
|
|
||||||
(cl-defmethod transient-format ((_ biome-query--transient-report))
|
(cl-defmethod transient-format ((_ biome-query--transient-report))
|
||||||
"Format the current report."
|
"Format the `biome-query-current'."
|
||||||
(let ((group (alist-get :group biome-query-current))
|
(let ((group (alist-get :group biome-query-current))
|
||||||
(var-names (biome-query--get-var-names-cache))
|
(var-names (biome-query--get-var-names-cache))
|
||||||
lat lon group-vars line-vars vars)
|
lat lon group-vars line-vars vars)
|
||||||
|
|
@ -221,14 +242,14 @@ case, the value is a list of variable names available in the group.")
|
||||||
|
|
||||||
(defclass biome-query--transient-path (transient-suffix)
|
(defclass biome-query--transient-path (transient-suffix)
|
||||||
((transient :initform t))
|
((transient :initform t))
|
||||||
"A transient class to display the current path.")
|
"A transient class to display the current path in query.")
|
||||||
|
|
||||||
(cl-defmethod transient-init-value ((_ biome-query--transient-path))
|
(cl-defmethod transient-init-value ((_ biome-query--transient-path))
|
||||||
"A dummy method for `biome-query--transient-report'."
|
"A dummy method for `biome-query--transient-report'."
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
(cl-defmethod transient-format ((_ biome-query--transient-path))
|
(cl-defmethod transient-format ((_ biome-query--transient-path))
|
||||||
"Format the current path."
|
"Format the current path in query."
|
||||||
(let* ((scope (oref (or transient--prefix
|
(let* ((scope (oref (or transient--prefix
|
||||||
transient-current-prefix)
|
transient-current-prefix)
|
||||||
scope))
|
scope))
|
||||||
|
|
@ -298,10 +319,7 @@ OBJ is an instance of `biome-query--transient-switch-variable'."
|
||||||
new-value))
|
new-value))
|
||||||
|
|
||||||
(cl-defmethod transient-format ((obj biome-query--transient-switch-variable))
|
(cl-defmethod transient-format ((obj biome-query--transient-switch-variable))
|
||||||
"Return a string generated using OBJ's `format'.
|
"Format the variable switch OBJ."
|
||||||
%k is formatted using `transient-format-key'.
|
|
||||||
%d is formatted using `transient-format-description'.
|
|
||||||
%v is formatted using `transient-format-value'."
|
|
||||||
(concat
|
(concat
|
||||||
" "
|
" "
|
||||||
(string-pad (transient-format-key obj) 6)
|
(string-pad (transient-format-key obj) 6)
|
||||||
|
|
@ -311,12 +329,14 @@ OBJ is an instance of `biome-query--transient-switch-variable'."
|
||||||
|
|
||||||
(defclass biome-query--transient-variable (transient-variable)
|
(defclass biome-query--transient-variable (transient-variable)
|
||||||
((api-key :initarg :api-key))
|
((api-key :initarg :api-key))
|
||||||
"A transient class to display a variable.")
|
"A transient class to work with query variables.
|
||||||
|
|
||||||
|
This is mostly used to interact with `biome-query-current'.")
|
||||||
|
|
||||||
(cl-defmethod transient-infix-set ((obj biome-query--transient-variable) value)
|
(cl-defmethod transient-infix-set ((obj biome-query--transient-variable) value)
|
||||||
"Set the value of OBJ to VALUE.
|
"Set the value of OBJ to VALUE.
|
||||||
|
|
||||||
OBJ is an instance of `biome-query--transient-date-variable'."
|
This also updates `biome-query-current' with the new value."
|
||||||
(if value
|
(if value
|
||||||
(setf
|
(setf
|
||||||
(alist-get (oref obj api-key) (alist-get :params biome-query-current)
|
(alist-get (oref obj api-key) (alist-get :params biome-query-current)
|
||||||
|
|
@ -347,9 +367,15 @@ OBJ is an instance of `biome-query--transient-select-variable'."
|
||||||
(propertize "unset" 'face 'transient-inactive-value))))
|
(propertize "unset" 'face 'transient-inactive-value))))
|
||||||
|
|
||||||
(defclass biome-query--transient-date-variable (biome-query--transient-variable) ()
|
(defclass biome-query--transient-date-variable (biome-query--transient-variable) ()
|
||||||
"A transient class to display a date variable.")
|
"A transient class to work with a date variable.
|
||||||
|
|
||||||
|
The variable is read via `org-read-date' and stored as a UNIX
|
||||||
|
timestamp.")
|
||||||
|
|
||||||
(cl-defmethod transient-infix-read ((obj biome-query--transient-date-variable))
|
(cl-defmethod transient-infix-read ((obj biome-query--transient-date-variable))
|
||||||
|
"Read a date from the user with `org-read-date'.
|
||||||
|
|
||||||
|
OBJ is an instance of `biome-query--transient-date-variable'."
|
||||||
(unless (oref obj value)
|
(unless (oref obj value)
|
||||||
(let ((org-read-date-force-compatible-dates nil))
|
(let ((org-read-date-force-compatible-dates nil))
|
||||||
(time-convert
|
(time-convert
|
||||||
|
|
@ -364,7 +390,6 @@ OBJ is an instance of `biome-query--transient-date-variable'."
|
||||||
(if value
|
(if value
|
||||||
(propertize
|
(propertize
|
||||||
(format-time-string
|
(format-time-string
|
||||||
;; TODO fix
|
|
||||||
biome-query-date-format
|
biome-query-date-format
|
||||||
(seconds-to-time
|
(seconds-to-time
|
||||||
value))
|
value))
|
||||||
|
|
@ -372,9 +397,16 @@ OBJ is an instance of `biome-query--transient-date-variable'."
|
||||||
(propertize "unset" 'face 'transient-inactive-value))))
|
(propertize "unset" 'face 'transient-inactive-value))))
|
||||||
|
|
||||||
(defclass biome-query--transient-select-variable (biome-query--transient-variable)
|
(defclass biome-query--transient-select-variable (biome-query--transient-variable)
|
||||||
((options :initarg :options)))
|
((options :initarg :options))
|
||||||
|
"A transient class to display a select variable.
|
||||||
|
|
||||||
|
`:options' is an alist of the form ((KEY . DESCRIPTION) ...). If the
|
||||||
|
number of options is more than
|
||||||
|
`biome-query-completing-read-threshold', the user is prompted via
|
||||||
|
`completing-read'. Otherwise, it just switches to the next option.")
|
||||||
|
|
||||||
(cl-defmethod transient-infix-value ((obj biome-query--transient-select-variable))
|
(cl-defmethod transient-infix-value ((obj biome-query--transient-select-variable))
|
||||||
|
"Return the value of OBJ."
|
||||||
(oref obj value))
|
(oref obj value))
|
||||||
|
|
||||||
(cl-defmethod transient-format-value ((obj biome-query--transient-select-variable))
|
(cl-defmethod transient-format-value ((obj biome-query--transient-select-variable))
|
||||||
|
|
@ -417,7 +449,7 @@ OBJ is an instance of `biome-query--transient-date-variable'."
|
||||||
((min :initarg :min :initform nil)
|
((min :initarg :min :initform nil)
|
||||||
(max :initarg :max :initform nil)
|
(max :initarg :max :initform nil)
|
||||||
(integer :initarg :integer :initform nil))
|
(integer :initarg :integer :initform nil))
|
||||||
"A transient class to display a number variable.")
|
"A transient class to work with a number variable.")
|
||||||
|
|
||||||
(cl-defmethod transient-infix-read ((obj biome-query--transient-number-variable))
|
(cl-defmethod transient-infix-read ((obj biome-query--transient-number-variable))
|
||||||
"Read the value of OBJ."
|
"Read the value of OBJ."
|
||||||
|
|
@ -475,7 +507,7 @@ OBJ is an instance of `biome-query--transient-date-variable'."
|
||||||
(propertize "unset" 'face 'transient-inactive-value))))
|
(propertize "unset" 'face 'transient-inactive-value))))
|
||||||
|
|
||||||
(defclass biome-query--transient-timezone-variable (biome-query--transient-variable) ()
|
(defclass biome-query--transient-timezone-variable (biome-query--transient-variable) ()
|
||||||
"A transient class to display a timezone variable.")
|
"A transient class to work with a timezone variable.")
|
||||||
|
|
||||||
(cl-defmethod transient-infix-read ((obj biome-query--transient-timezone-variable))
|
(cl-defmethod transient-infix-read ((obj biome-query--transient-timezone-variable))
|
||||||
"Read the value of OBJ."
|
"Read the value of OBJ."
|
||||||
|
|
@ -483,7 +515,9 @@ OBJ is an instance of `biome-query--transient-date-variable'."
|
||||||
nil t (oref obj value)))
|
nil t (oref obj value)))
|
||||||
|
|
||||||
(defclass biome-query--transient-coords (biome-query--transient-variable) ()
|
(defclass biome-query--transient-coords (biome-query--transient-variable) ()
|
||||||
"A transient class for a coordinate switcher.")
|
"A transient class for a coordinate switcher.
|
||||||
|
|
||||||
|
The source of possible coordinates is `biome-query-coords'.")
|
||||||
|
|
||||||
(cl-defmethod transient-init-value ((obj biome-query--transient-coords))
|
(cl-defmethod transient-init-value ((obj biome-query--transient-coords))
|
||||||
"Initialize the value of OBJ."
|
"Initialize the value of OBJ."
|
||||||
|
|
@ -535,15 +569,19 @@ OBJ is an instance of `biome-query--transient-date-variable'."
|
||||||
"A transient class to switch between groups of a query.")
|
"A transient class to switch between groups of a query.")
|
||||||
|
|
||||||
(cl-defmethod transient-infix-value ((obj biome-query--transient-group-switch))
|
(cl-defmethod transient-infix-value ((obj biome-query--transient-group-switch))
|
||||||
|
"Return the value of OBJ."
|
||||||
(oref obj value))
|
(oref obj value))
|
||||||
|
|
||||||
(cl-defmethod transient-init-value ((obj biome-query--transient-group-switch))
|
(cl-defmethod transient-init-value ((obj biome-query--transient-group-switch))
|
||||||
|
"Initialize the value of OBJ."
|
||||||
(let ((groups (biome-query--section-groups biome-query--current-section)))
|
(let ((groups (biome-query--section-groups biome-query--current-section)))
|
||||||
(oset obj options groups)
|
(oset obj options groups)
|
||||||
(oset obj value (alist-get :group biome-query-current))))
|
(oset obj value (alist-get :group biome-query-current))))
|
||||||
|
|
||||||
(cl-defmethod transient-infix-read ((obj biome-query--transient-group-switch))
|
(cl-defmethod transient-infix-read ((obj biome-query--transient-group-switch))
|
||||||
"Read the value of OBJ."
|
"Switch to the next group.
|
||||||
|
|
||||||
|
OBJ is an instance of `biome-query--transient-group-switch'."
|
||||||
(let* ((options (mapcar
|
(let* ((options (mapcar
|
||||||
(lambda (c) (cons (cdr c) (car c)))
|
(lambda (c) (cons (cdr c) (car c)))
|
||||||
(oref obj options)))
|
(oref obj options)))
|
||||||
|
|
@ -591,7 +629,7 @@ number of symbols from the start of the corresponding word.
|
||||||
SEQ-LENGTHS is a list of possible values of IT - if it's 2, then
|
SEQ-LENGTHS is a list of possible values of IT - if it's 2, then
|
||||||
the item is a number that can only be taken as a whole, otherwise
|
the item is a number that can only be taken as a whole, otherwise
|
||||||
it's the length of the word."
|
it's the length of the word."
|
||||||
;; TODO better weight function
|
;; TODO better weight function?
|
||||||
(cl-loop for take in it
|
(cl-loop for take in it
|
||||||
for length in seq-lengths
|
for length in seq-lengths
|
||||||
if (= 2 length) sum 1
|
if (= 2 length) sum 1
|
||||||
|
|
@ -601,7 +639,7 @@ it's the length of the word."
|
||||||
"Generate unique key candidates for NAME.
|
"Generate unique key candidates for NAME.
|
||||||
|
|
||||||
The algorithm is as follows: NAME is split into words, each word
|
The algorithm is as follows: NAME is split into words, each word
|
||||||
produces a list of all its prefixes. E.g. \"hello\" produces \"\",
|
produces a list of all its prefixes. E.g. \"hello\" produces \"\",
|
||||||
\"h\", \"he\", \"hel\", etc. Numbers are takes as a whole,
|
\"h\", \"he\", \"hel\", etc. Numbers are takes as a whole,
|
||||||
e.g. \"100\" produces just \"\" and \"100\".
|
e.g. \"100\" produces just \"\" and \"100\".
|
||||||
|
|
||||||
|
|
@ -639,8 +677,6 @@ at 3."
|
||||||
(reverse sequences)
|
(reverse sequences)
|
||||||
(reduce #'biome-query--cartesian-product)
|
(reduce #'biome-query--cartesian-product)
|
||||||
(mapcar (lambda (it) (if (listp it) (nreverse it) (list it))))
|
(mapcar (lambda (it) (if (listp it) (nreverse it) (list it))))
|
||||||
;; TODO delete comment
|
|
||||||
;; ((lambda (kek) (message "Sorting %s" (length kek)) kek))
|
|
||||||
;; XXX this seems to be just a bit faster than `seq-sort-by'.
|
;; XXX this seems to be just a bit faster than `seq-sort-by'.
|
||||||
(mapcar (lambda (it)
|
(mapcar (lambda (it)
|
||||||
(cons (biome-query--unique-key-weight it seq-lengths) it)))
|
(cons (biome-query--unique-key-weight it seq-lengths) it)))
|
||||||
|
|
@ -706,6 +742,9 @@ exclude from the result."
|
||||||
(defun biome--query-section-fields-define-infixes (fields keys param infix-name)
|
(defun biome--query-section-fields-define-infixes (fields keys param infix-name)
|
||||||
"Define infixes for FIELDS.
|
"Define infixes for FIELDS.
|
||||||
|
|
||||||
|
I wish it were possible to avoid that... Maybe I just didn't find the
|
||||||
|
correct way.
|
||||||
|
|
||||||
PARAM is the value of `:param' of the section. INFIX-NAME is the
|
PARAM is the value of `:param' of the section. INFIX-NAME is the
|
||||||
prefix for infix names. KEYS is a hash table mapping field names
|
prefix for infix names. KEYS is a hash table mapping field names
|
||||||
to keys."
|
to keys."
|
||||||
|
|
@ -761,7 +800,7 @@ to keys."
|
||||||
:argument ,name))))))
|
:argument ,name))))))
|
||||||
|
|
||||||
(defun biome-query--section-fields-children (fields keys parents cache-key)
|
(defun biome-query--section-fields-children (fields keys parents cache-key)
|
||||||
"Get transient laoyut for FIELDS.
|
"Get transient layout 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'. PARENTS is a list
|
KEYS is the result of `biome-query--unique-keys'. PARENTS is a list
|
||||||
|
|
@ -822,9 +861,14 @@ list of parent sections."
|
||||||
sections)])))
|
sections)])))
|
||||||
|
|
||||||
(defmacro biome-query--with-layout-cache (cache-key &rest body)
|
(defmacro biome-query--with-layout-cache (cache-key &rest body)
|
||||||
"Cache layout for CACHE-KEY.
|
"Cache layout for CACHE-KEY in `biome-query--layout-cache'.
|
||||||
|
|
||||||
BODY is the body of the macro."
|
BODY is the body of the macro that returns the layout. The resulting
|
||||||
|
expression either returns the cached layout or evaluates BODY, caches
|
||||||
|
the result and returns it.
|
||||||
|
|
||||||
|
This is necessary mostly because `biome-query--unique-keys' is
|
||||||
|
sometimes a bit slow."
|
||||||
(declare (indent 1))
|
(declare (indent 1))
|
||||||
`(let ((layout (gethash ,cache-key biome-query--layout-cache)))
|
`(let ((layout (gethash ,cache-key biome-query--layout-cache)))
|
||||||
(if layout
|
(if layout
|
||||||
|
|
@ -878,6 +922,7 @@ SUFFIXES is a list of suffix definitions."
|
||||||
collect (cons group (alist-get :name child))))
|
collect (cons group (alist-get :name child))))
|
||||||
|
|
||||||
(defun biome-query--reset-report ()
|
(defun biome-query--reset-report ()
|
||||||
|
"Reset the current query to the current section."
|
||||||
(interactive)
|
(interactive)
|
||||||
(setq biome-query-current
|
(setq biome-query-current
|
||||||
(copy-tree
|
(copy-tree
|
||||||
|
|
@ -893,6 +938,7 @@ SUFFIXES is a list of suffix definitions."
|
||||||
(funcall biome-query--callback biome-query-current))
|
(funcall biome-query--callback biome-query-current))
|
||||||
|
|
||||||
(defun biome-query--generate-preset ()
|
(defun biome-query--generate-preset ()
|
||||||
|
"Generate a preset for the current query."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let ((buf (generate-new-buffer "*biome-preset*")))
|
(let ((buf (generate-new-buffer "*biome-preset*")))
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
|
|
@ -931,6 +977,7 @@ SECTION is a form as defined in `biome-api-parse--page'."
|
||||||
(put 'biome-query-section 'transient--layout nil)))
|
(put 'biome-query-section 'transient--layout nil)))
|
||||||
|
|
||||||
(defun biome-query--section-open (name)
|
(defun biome-query--section-open (name)
|
||||||
|
"Open section NAME in `biome-query--section'."
|
||||||
(let ((params (alist-get name biome-api-data nil nil #'equal)))
|
(let ((params (alist-get name biome-api-data nil nil #'equal)))
|
||||||
(unless params
|
(unless params
|
||||||
(error "No such section: %s" name))
|
(error "No such section: %s" name))
|
||||||
|
|
|
||||||
12
biome.el
12
biome.el
|
|
@ -25,7 +25,17 @@
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
;; TODO
|
;; Interface to Open Meteo <https://open-meteo.com> for Emacs. The
|
||||||
|
;; API provides weather forecasts, historical weather data, climate
|
||||||
|
;; change projections, and more.
|
||||||
|
;;
|
||||||
|
;; The API is free for non-commercial use if you make less than 10000
|
||||||
|
;; requests per day.
|
||||||
|
;;
|
||||||
|
;; The package has two main entrypoints: `biome' and `biome-resume'. The
|
||||||
|
;; former starts a new query, the latter resumes the last query.
|
||||||
|
;;
|
||||||
|
;; Also check out the README at <https://github.com/SqrtMinusOne/biome>.
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
(require 'biome-api)
|
(require 'biome-api)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue