diff --git a/.gitignore b/.gitignore index 518d7e9..d4470f3 100644 --- a/.gitignore +++ b/.gitignore @@ -19,10 +19,6 @@ transient/ url/ .org-id-locations bookmarks -request/ - -# Weather forecast -forecast # Custom file custom.el diff --git a/screens/dashboard.el b/screens/dashboard.el index 8f53fd3..22d9320 100644 --- a/screens/dashboard.el +++ b/screens/dashboard.el @@ -113,7 +113,7 @@ ("RSS" elfeed "r") ("Terminal" theurgy-bottom-shell "t") ("Gomuks" theurgy-gomuks-workspace "G") - ("Weather" theurgy-weather "w"))))) + ("Weather" theurgy-show-weather "w"))))) :align center :width 20)) (grid-make-box `(:content ,(concat @@ -144,7 +144,7 @@ (grid-make-column (list (grid-make-box `(:content ,(concat (enlight-menu '(("Userland" - ("Weather" theurgy-weather "w") + ("Dired" (dired "~") "d") ("RSS" elfeed "r") ("Terminal" theurgy-bottom-shell "t") )))) diff --git a/shared-packages.el b/shared-packages.el index 9754098..db5e015 100644 --- a/shared-packages.el +++ b/shared-packages.el @@ -39,9 +39,6 @@ ;; Transient (use-package transient) -;; Request is generally useful and a dependency for other packages -(use-package request) - (provide 'shared-packages) ;;; shared-packages.el ends here diff --git a/userland/browser.el b/userland/browser.el index 5a74ff0..d962fe9 100644 --- a/userland/browser.el +++ b/userland/browser.el @@ -22,10 +22,37 @@ ;;; Code: -(defun rename-eww-hook () - "Rename eww browser's buffer so sites open in new page." - (rename-buffer "eww" t)) -(add-hook 'eww-mode-hook #'rename-eww-hook) +(defcustom theurgy-city + "Perth" + "The city used for fetching weather from wttr.in." + :type 'string + :group 'theurgy + :group 'theurgy-weather) + +(defun theurgy-eww-rename-buffer () + "Rename the eww buffer intelligently." + (when (eq major-mode 'eww-mode) + (let ((url (plist-get eww-data :url))) + (cond + ((string-match-p "wttr.in" url) "*weather*") + (t "*eww*"))))) + +(setq eww-auto-rename-buffer #'theurgy-eww-rename-buffer) + +(defun theurgy-show-weather () + "Show wttr.in in an eww buffer." + (interactive) + (if (get-buffer "*weather*") + (switch-to-buffer "*weather*") + (eww (concat "wttr.in/" theurgy-city "?0")))) + +(unless (equal system-type 'android) + (add-to-list 'display-buffer-alist + '("\\*weather\\*" + (display-buffer-in-side-window) + (side . left) + (slot . 4) + (window-width . 0.15)))) (provide 'browser) diff --git a/userland/weather.el b/userland/weather.el deleted file mode 100644 index 5833d99..0000000 --- a/userland/weather.el +++ /dev/null @@ -1,162 +0,0 @@ -;;; weather.el --- Fetch and display the weather from bom.gov.au -*- lexical-binding: t -*- - - -;; This file is not part of GNU Emacs - -;; This program is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - - -;;; Commentary: - -;; Reverse-engineered API docs are available here https://trickypr.github.io/bom-weather-docs/ -;; This code depends on request.el - -;;; Code: - -(defcustom theurgy-geohash - "" - "The geohash used for fetching forecast data from BOM. You can manually find this by going to https://api.weather.bom.gov.au/v1/locations?search=, or you can get a nicer interface for it with \\[theurgy-weather-find-geohash]." - :type 'string - :group 'theurgy - :group 'theurgy-weather) - -(defvar bom-api "https://api.weather.bom.gov.au/v1/") - -(defun theurgy-weather-find-geohash (search-term) - "Search for SEARCH-TERM and then return possible geohash candidates." - (interactive "sSearch term (Suburb or Postcode): ") - (when (> 4 (length search-term)) - (error "Search term must be greater than 3 characters (don't ask me)")) - (request (concat bom-api "locations?search=" search-term) - :parser 'json-read - :success (cl-function - (lambda (&key data &allow-other-keys) - (let* ((res (cdr (assoc 'data data))) - (candidates (mapcar (lambda (alst) - (cons (concat - (cdr (assoc 'name alst)) ", " - (cdr (assoc 'state alst)) ", " - (cdr (assoc 'postcode alst))) - (cdr (assoc 'geohash alst)))) - res))) - (customize-set-variable 'theurgy-geohash (cdr (assoc (completing-read "Select Location: " candidates) candidates)))))))) - -(defvar forecast-timer nil) -(defvar forecast-location "forecast") ;; The location of the cached forecast, related to the emacs user directory - -(defun theurgy-weather-fetch-forecast () - "Fetch and save the weather forecast." - (interactive) - (request - (concat bom-api "locations/" theurgy-geohash "/forecasts/daily") - :parser 'json-read - :success (cl-function - (lambda (&key data &allow-other-keys) - (save-excursion - (find-file (concat user-emacs-directory forecast-location)) - (delete-region (point-min) (point-max)) - (insert (format "%S" (mapcar (lambda (alst) - (cons (let ((d (parse-time-string (cdr (assoc 'date alst))))) - (list (nth 3 d) (nth 4 d) (nth 5 d))) - (assq-delete-all 'date alst))) - (cdr (assoc 'data data))))) - (save-buffer) - (kill-buffer)))))) - -(defun current-date () - "Get the current date as a list." - (let ((d (decode-time (current-time)))) - (list (nth 3 d) (nth 4 d) (nth 5 d)))) - -(defun today+ (days) - "Date list for today + DAYS." - (let* ((sec (+ (* days 86400) (time-convert (current-time) 'integer))) - (d (decode-time sec))) - (list (nth 3 d) (nth 4 d) (nth 5 d)))) - -(defun prompt-date () - "Prompt the user for a date." - (let ((d (parse-time-string (org-read-date)))) - (list (nth 3 d) (nth 4 d) (nth 5 d)))) - -(defun theurgy-weather-get-for-date (date) - "Get weather for a particular DATE." - (let* ((forecast-data (read (with-temp-buffer - (insert-file-contents (concat user-emacs-directory forecast-location)) - (buffer-string)))) - (day (assoc date - forecast-data))) - day)) - -(defun theurgy-quick-forecast (date) - "Quick forecast for DATE." - (let ((forecast (theurgy-weather-get-for-date date))) - (message (format "%s - %s degrees. %s" - (cdr (assoc 'temp_min forecast)) - (cdr (assoc 'temp_max forecast)) - (cdr (assoc 'short_text forecast)))))) - -(defun theurgy-weather-quick () - "Show the forecast as a message." - (interactive) - (theurgy-quick-forecast (prompt-date))) - -(defun theurgy-start-forecast-timer () - "Start the timer for periodically retrieving the weather forecast." - (interactive) - (theurgy-weather-fetch-forecast) - (unless forecast-timer - (when (timerp forecast-timer) - (cancel-timer forecast-timer)) - (setq forecast-timer (run-at-time t (* 60 30) (theurgy-weather-fetch-forecast))))) - -(theurgy-start-forecast-timer) - -(defun theurgy-weather-insert-forecast (fc) - "Insert provided forecast FC in the current buffer, as org markup." - (let ((date (car fc))) - (insert (format "* %s/%s/%s - %s\n" (nth 0 date) (nth 1 date) (nth 2 date) (cdr (assoc 'short_text fc)))) - (insert (format "%s\n" (cdr (assoc 'extended_text fc)))) - (insert (format "- %s-%s°C\n" - (cdr (assoc 'temp_min fc)) - (cdr (assoc 'temp_max fc)))) - (insert (format "- %s%% Chance of Rain (%s-%smm)\n" - (cdr (assoc 'chance (assoc 'rain fc))) - (cdr (assoc 'lower_range (assoc 'amount (assoc 'rain fc)))) - (cdr (assoc 'upper_range (assoc 'amount (assoc 'rain fc)))))) - (insert (format "- %s UV\n" - (cdr (assoc 'category (assoc 'uv fc))))) - (insert (format "- %s Fire Danger\n" - (cdr (assoc 'fire_danger fc)))) - (insert "\n"))) - -(defun theurgy-weather () - "Show weather information in a new buffer." - (interactive) - (let ((buf (generate-new-buffer "*Weather*"))) - (with-current-buffer buf - (delete-region (point-min) (point-max)) - (org-mode) - (let* ((today (theurgy-weather-get-for-date (current-date))) - (tomorrow (theurgy-weather-get-for-date (today+ 1))) - (after-tomorrow (theurgy-weather-get-for-date (today+ 2)))) - (theurgy-weather-insert-forecast today) - (theurgy-weather-insert-forecast tomorrow) - (theurgy-weather-insert-forecast after-tomorrow)) - (setq buffer-read-only t)) - (switch-to-buffer buf))) - -(provide 'weather) - -;;; weather.el ends here