From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eshel Yaron Newsgroups: gmane.emacs.help Subject: Re: Package critique: modeline for air quality information Date: Fri, 01 Sep 2023 11:38:27 +0200 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="8195"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: help-gnu-emacs@gnu.org To: John Haman Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Fri Sep 01 12:36:17 2023 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qc1Vg-0001wg-Uz for geh-help-gnu-emacs@m.gmane-mx.org; Fri, 01 Sep 2023 12:36:17 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qc1VC-0005Tw-NB; Fri, 01 Sep 2023 06:35:46 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qc0bq-0006v0-JV for help-gnu-emacs@gnu.org; Fri, 01 Sep 2023 05:38:36 -0400 Original-Received: from mail.eshelyaron.com ([107.175.124.16] helo=eshelyaron.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qc0bn-0001qY-Ph for help-gnu-emacs@gnu.org; Fri, 01 Sep 2023 05:38:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eshelyaron.com; s=mail; t=1693561111; bh=Sj2i3AgiU1pvUegVed+gxkDW6Xc1lGxUvU1FJ29CUe0=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=qyn9hcTrAImi8C69QfjuTZ4Eli1sx5z1xHIogkPbxUyYJdD7vDnrQLGme+H7Y9wN7 fk93AceE42k2XjsIQ2rw6gZsdz4OtphLFGr6nQBy9KO6lHzE6R1zM9mdtW6Mxbpi49 OZQAdeSeyRxoQ4pwKAQ/EhKfjyT6nNrDJ9fh2fKfMzHBB7GS23OnuuDCDpsDSY1/fq NCxznAwtiK//ncfnLPB05lWOx6WYoYmqvfPPYAz6oIwa0ikse0Ah8J6ugimxQI4HY8 rFgtJKQeB85lZZB5p+TdRBqcm3bfiglRsD/KrJxt/O5aYxFcxcivHgmD/L8AgvGnvi DPE9Ez/GRDveA== In-Reply-To: (John Haman's message of "Thu, 31 Aug 2023 21:58:02 -0400") Received-SPF: pass client-ip=107.175.124.16; envelope-from=me@eshelyaron.com; helo=eshelyaron.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 01 Sep 2023 06:35:43 -0400 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.help:145048 Archived-At: Hello John, John Haman writes: > I wrote a package that adds local air quality statistics to the > mode-line. Cool! > > https://github.com/jthaman/air-quality/blob/main/air-quality.el > > If you are so inclined, I'd like some thoughts on the code. It's > short, but I'm trying to get better at Emacs Lisp (at least this week, > while I'm on vacation...) > My suggestion would be to set this up as a global minor mode. Also, you may want to define your "public variables" as user options, so they can be customized with `M-x customize` and friends. Something along the lines of: diff --git a/air-quality.el b/air-quality.el index 1781515..533ce1b 100644 --- a/air-quality.el +++ b/air-quality.el @@ -6,7 +6,7 @@ ;;; air-quality.el --- Air quality modeline indicator and r= eporting tool -*- le ;; URL: https://github.com/jthaman/air-quality ;; Version: 0.1 ;; Package-Requires: ((emacs "27.1")) -;; Keywords: bling +;; Keywords: convenience =20 ;; 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 @@ -21,35 +21,44 @@ ;;; air-quality.el --- Air quality modeline indicator a= nd reporting tool -*- le ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . =20 -;;; Package Imports -(require 'url) -(require 'json) -(require 'cl-lib) - - ;;; Commentary: + ;; Add information about local air quality to the modeline. Air Quality ;; information is downloaded from the Open Weather Map Air Pollution API. =20 - ;;; Code: =20 +;;;; Package Imports + +(require 'url) +(require 'json) +(require 'cl-lib) + +;;;; User options =20 -;;; Public Variables -(defvar air-quality-open-weather-api-key nil - "A string. API key for Open Weather Map.") +(defgroup air-quality nil + "Air quality mode-line indicator." + :group 'mode-line) + +(defcustom air-quality-open-weather-api-key nil + "API key for Open Weather Map." + :type '(choice (const :tag "Unset" nil) + (string :tag "Your API key"))) =20 (defvar air-quality-refresh-interval 60 + ;; XXX - turn into a defcustom "An integer. Number of minutes between refreshes of air quality informat= ion.") =20 (defvar air-quality-latitude nil + ;; XXX - likewise "A float. Your latitude.") =20 (defvar air-quality-longitude nil + ;; XXX - likewise "A float. Your longitude.") =20 +;;;; Private Variables =20 -;;; Private Variables (defvar air-quality--timer nil) =20 (defvar air-quality--co nil "Carbon Monoxide level (micrograms per cubic-m= eter).") @@ -62,30 +71,44 @@ (defvar air-quality--pm10 nil "PM 10 level (micrograms = per cubic-meter).") (defvar air-quality--nh3 nil "Ammonia level (micrograms per cubic-meter).") (defvar air-quality--level nil "Overall Air Quality (AQI).") =20 -(defun air-quality--make-forecast-call (key lat lon) - "Create an API request for the future forecast of Air Quality informatio= n from Open Weather Map." - (concat "http://api.openweathermap.org/data/2.5/air_pollution/forecast?l= at=3D" - (number-to-string lat) - "&lon=3D" - (number-to-string lon) - "&appid=3D" - key)) - -(defun air-quality--make-api-call (key lat lon) - "Create an API request to Open Weather Map." - (concat "http://api.openweathermap.org/data/2.5/air_pollution?lat=3D" - (number-to-string lat) - "&lon=3D" - (number-to-string lon) - "&appid=3D" - key)) - -(defvar air-quality--index-alist '((1 . "Good") - (2 . "Fair") - (3 . "Moderate") - (4 . "Poor") - (5 . "Very Poor"))) - +(defun air-quality--make-api-call (key latitude longitude) + "Return Open Weather Map URL for LATITUDE and LONGITUDE with API key KEY= ." + (url-parse-make-urlobj + "https" nil nil "api.openweathermap.org" nil + (concat "/data/2.5/air_pollution/?" + (url-build-query-string `(("lat" ,latitude) + ("lon" ,longitude) + ("appid" ,key)))))) + +(defconst air-quality--index-alist '((1 . "Good") + (2 . "Fair") + (3 . "Moderate") + (4 . "Poor") + (5 . "Very Poor"))) + +(defvar air-quality-indicator + '(:eval + (propertize (concat " " (alist-get air-quality--level + air-quality--index-alist)) + 'face 'mode-line-buffer-id + 'help-echo (format "Carbon Monoxide: %d =C2=B5g/m=C2=B3 +Nitrogen Oxide: %d =C2=B5g/m=C2=B3 +Nitrogen Dioxide: %d =C2=B5g/m=C2=B3 +Ozone: %d =C2=B5g/m=C2=B3 +Sulfur Dioxide: %d =C2=B5g/m=C2=B3 +PM 2.5: %d =C2=B5g/m=C2=B3 +PM 10: %d =C2=B5g/m=C2=B3 +Ammonia: %d =C2=B5g/m=C2=B3" + air-quality--co + air-quality--no + air-quality--no2 + air-quality--o3 + air-quality--so2 + air-quality--pm2_5 + air-quality--pm10 + air-quality--nh3) + 'mouse-face 'mode-line-highlight))) +(put 'air-quality-indicator 'risky-local-variable t) =20 (defun air-quality--get-update () "Query Open Weather for air quality information." @@ -93,7 +116,7 @@ (defun air-quality--get-update () (air-quality--make-api-call air-quality-open-weather-api-key air-quality-latitude air-quality-longitude) - (lambda (events) + (lambda (_events) (goto-char url-http-end-of-headers) (let ((json-object-type 'plist) (json-key-type 'symbol) @@ -108,57 +131,24 @@ (defun air-quality--get-update () (setq air-quality--pm2_5 (plist-get components 'pm2_5)) (setq air-quality--pm10 (plist-get components 'pm10)) (setq air-quality--nh3 (plist-get components 'nh3)) - (setq air-quality--level (cadadr (aref (plist-get result 'list) 0= ))) - (air-quality--set-indicator) - (run-with-idle-timer 1 nil #'air-quality--append-modeline) - ))))) - -(defun air-quality--set-indicator () - (defvar-local air-quality-indicator - (list (propertize (concat " " (alist-get air-quality--level air-qua= lity--index-alist)) - 'face 'mode-line-buffer-id - 'help-echo (purecopy (format "Carbon Monoxide: %d = =C2=B5g/m=C2=B3 -Nitrogen Oxide: %d =C2=B5g/m=C2=B3 -Nitrogen Dioxide: %d =C2=B5g/m=C2=B3 -Ozone: %d =C2=B5g/m=C2=B3 -Sulfur Dioxide: %d =C2=B5g/m=C2=B3 -PM 2.5: %d =C2=B5g/m=C2=B3 -PM 10: %d =C2=B5g/m=C2=B3 -Ammonia: %d =C2=B5g/m=C2=B3" - air-quality--co - air-quality--no - air-quality--no2 - air-quality--o3 - air-quality--so2 - air-quality--pm2_5 - air-quality--pm10 - air-quality--nh3)) - 'mouse-face 'mode-line-highlight - ))) - (put 'air-quality-indicator 'risky-local-variable t)) - - -(defun air-quality--append-modeline () - (unless (cl-find '(:eval air-quality-indicator) mode-line-format :test '= equal) - (setq-default mode-line-format - (reverse (append '((:eval air-quality-indicator)) (rever= se mode-line-format)))))) + (setq air-quality--level (cadadr (aref (plist-get result 'list) 0= )))))))) =20 ;;;###autoload -(defun air-quality-setup-modeline () - - ;; This could be better... - ;; if no timer, start one - (if (null air-quality--timer) - (setq air-quality--timer - (run-with-timer 0 (* 60 air-quality-refresh-interval) #'air-qu= ality--get-update)) - ;; otherwise, cancel the timer and start one - (progn - (cancel-timer air-quality--timer) - (setq air-quality--timer - (run-with-timer 0 (* 60 air-quality-refresh-interval) #'air-qu= ality--get-update)) - ))) - +(define-minor-mode air-quality-mode + "Minor mode for displaying air quality information in the mode line." + :group 'air-quality + :global t + (if air-quality-mode + (progn + ;; XXX - check that air-quality-open-weather-api-key, + ;; air-quality-latitude and air-quality-longitude are set + (add-to-list 'mode-line-misc-info 'air-quality-indicator t ) + (setq air-quality--timer + (run-with-timer 0 (* 60 air-quality-refresh-interval) + #'air-quality--get-update))) + (setq mode-line-misc-info (delq 'air-quality-indicator mode-line-misc-= info)) + (cancel-timer air-quality--timer)) + (force-mode-line-update)) =20 (provide 'air-quality) - ;;; air-quality.el ends here > -- > Dr. John Haman > Maryland, USA