mirror of
https://github.com/SqrtMinusOne/sqrtminusone.github.io.git
synced 2025-12-10 15:53:03 +03:00
226 lines
21 KiB
HTML
226 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html lang=""><head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
|
|
<title>BIOME - Bountiful Interface to Open Meteo for Emacs</title>
|
|
<meta name="description" content="Freedom is a state of mind">
|
|
<meta name="author" content='SqrtMinusOne'>
|
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous">
|
|
|
|
|
|
<link rel="stylesheet" href="/sass/researcher.min.css">
|
|
|
|
|
|
<link rel="icon" type="image/ico" href="https://sqrtminusone.xyz/favicon.ico">
|
|
|
|
|
|
<script defer data-domain="sqrtminusone.xyz" src="https://plausible.sqrtminusone.xyz/js/plausible.js"></script>
|
|
|
|
</head>
|
|
|
|
<body><div class="container mt-5">
|
|
<nav class="navbar navbar-expand-sm flex-column flex-sm-row text-nowrap p-0">
|
|
<a class="navbar-brand mx-0 mr-sm-auto" href="https://sqrtminusone.xyz/" title="SqrtMinusOne">
|
|
|
|
SqrtMinusOne
|
|
</a>
|
|
<div class="navbar-nav flex-row flex-wrap justify-content-center">
|
|
|
|
|
|
|
|
<a class="nav-item nav-link" href="/" title="Index">
|
|
Index
|
|
</a>
|
|
|
|
<span class="nav-item navbar-text mx-1">/</span>
|
|
|
|
|
|
<a class="nav-item nav-link" href="/posts/" title="Posts">
|
|
Posts
|
|
</a>
|
|
|
|
<span class="nav-item navbar-text mx-1">/</span>
|
|
|
|
|
|
<a class="nav-item nav-link" href="/configs/readme" title="Configs">
|
|
Configs
|
|
</a>
|
|
|
|
<span class="nav-item navbar-text mx-1">/</span>
|
|
|
|
|
|
<a class="nav-item nav-link" href="/emacs-packages/" title="Emacs packages">
|
|
Emacs packages
|
|
</a>
|
|
|
|
|
|
|
|
</div>
|
|
</nav>
|
|
</div>
|
|
<hr>
|
|
<div id="content">
|
|
<script defer language="javascript" type="text/javascript" src="/js/dynamic-toc.js"></script>
|
|
<div class="root">
|
|
<h1 id="title-small-screen">
|
|
BIOME - Bountiful Interface to Open Meteo for Emacs
|
|
|
|
<iframe src="https://ghbtns.com/github-btn.html?user=SqrtMinusOne&repo=biome&type=star&count=true" frameborder="0" scrolling="0" width="150" height="20" title="GitHub"></iframe>
|
|
|
|
</h1>
|
|
<div class="container" id="actual-content">
|
|
<h1 id="title-large-screen" class="dotfiles-title">
|
|
BIOME - Bountiful Interface to Open Meteo for Emacs
|
|
|
|
<iframe src="https://ghbtns.com/github-btn.html?user=SqrtMinusOne&repo=biome&type=star&count=true" frameborder="0" scrolling="0" width="150" height="20" title="GitHub"></iframe>
|
|
|
|
</h1>
|
|
<figure><a href="https://melpa.org/#/biome"><img src="https://melpa.org/packages/biome-badge.svg"></a>
|
|
</figure>
|
|
|
|
<p>Interface to <a href="https://open-meteo.com/">Open Meteo</a> for Emacs. The service provides weather forecasts, historical weather data, climate change projections, and more.</p>
|
|
<p>The service is AGPL-licensed; the hosted API is free for non-commercial use if you make less than 10000 requests per day.</p>
|
|
<figure><img src="/biome-img/report.png">
|
|
</figure>
|
|
|
|
<h2 id="installation">Installation</h2>
|
|
<p>The package is available on MELPA. Install it however you normally install packages, I prefer <a href="https://github.com/jwiegley/use-package">use-package</a> and <a href="https://github.com/radian-software/straight.el">straight.el</a>:</p>
|
|
<div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">use-package</span> <span style="color:#19177c">biome</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#008000">:straight</span> <span style="color:#800">t</span>)
|
|
</span></span></code></pre></div><p>Or clone the repository, add it to <code>load-path</code>, and <code>require</code> the package.</p>
|
|
<h3 id="issues-with-termux">Issues with termux?</h3>
|
|
<p>I’ve been trying to run this package on termux and had some issues.</p>
|
|
<p>First, for some reason <code>request.el</code> throws a successfully parsed response as an error. Use this as a workaround:</p>
|
|
<div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">setq</span> <span style="color:#19177c">biome-api-try-parse-error-as-response</span> <span style="color:#800">t</span>)
|
|
</span></span></code></pre></div><p>Second, somehow <code><tab></code> is not the same as <code><TAB></code>. The following might be necessary:</p>
|
|
<div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">setq</span> <span style="color:#19177c">biome-query-tab-key</span> <span style="color:#ba2121">"<TAB>"</span>)
|
|
</span></span></code></pre></div><p>Be sure to add that before the package initialization.</p>
|
|
<h2 id="usage">Usage</h2>
|
|
<p>The main entry point is <code>M-x biome</code>. Each item under “Open Meteo Data” corresponds to a particular endpoint of the service. For instance, <code>M-x biome ww</code> is a generic weather forecast. Check out the <a href="https://open-meteo.com/en/docs">API docs</a> for more detailed descriptions.</p>
|
|
<figure><img src="/biome-img/root.png">
|
|
</figure>
|
|
|
|
<p>Each of these items opens a query interface. A query consists of “global” variables, such as location, units, etc., and “group variables”. Groups are usually “hourly” and “daily”.</p>
|
|
<figure><img src="/biome-img/query.png">
|
|
</figure>
|
|
|
|
<p>Global variables must always include a location (section “Select Coordinates or City”). To enter a location, you can either enter latitude and longitude (Open Meteo has an <a href="https://open-meteo.com/en/docs/geocoding-api">API for those</a> as well) or select a location from <code>biome-query-coords</code>. Example configuration:</p>
|
|
<div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">setq</span> <span style="color:#19177c">biome-query-coords</span>
|
|
</span></span><span style="display:flex;"><span> <span style="color:#666">'</span>((<span style="color:#ba2121">"Helsinki, Finland"</span> <span style="color:#666">60.16952</span> <span style="color:#666">24.93545</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"Berlin, Germany"</span> <span style="color:#666">52.52437</span> <span style="color:#666">13.41053</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"Dubai, UAE"</span> <span style="color:#666">25.0657</span> <span style="color:#666">55.17128</span>)))
|
|
</span></span></code></pre></div><p>A timezone (“Settings” > “Timezone”) may not be required, but be sure to set it because <strong>the default one is UTC+0</strong>.</p>
|
|
<p>The current group is switched with <code><tab></code>. Each group’s section has a set of variables that can be toggled on and off, such as temperature, precipitation, etc. Check out the <a href="https://open-meteo.com/en/docs">API docs</a> if you’re interested in the meaning of more esoteric ones.</p>
|
|
<p>Press <code>RET</code> after you’ve configured the query to call the API. If something goes wrong, it will output an error, such as:</p>
|
|
<div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Open Meteo has returned an error.
|
|
</span></span><span style="display:flex;"><span>Error: (error http 400)
|
|
</span></span><span style="display:flex;"><span>Reason: Timezone is required
|
|
</span></span></code></pre></div><p>Or it will open the results table (the first screenshot).</p>
|
|
<p><code>tabulated-list</code> doesn’t support horizontal scrolling, so press <code>c</code> to toggle columns’ visibility.</p>
|
|
<figure><img src="/biome-img/columns.png">
|
|
</figure>
|
|
|
|
<p>Press <code>c</code> or invoke <code>M-x biome-grid-export-csv</code> to export the results in CSV format.</p>
|
|
<h2 id="more-configuration">More configuration</h2>
|
|
<p>To save a query for later, press <code>P</code> in the root of the query interface. This will generate a definition like this:</p>
|
|
<div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#19177c">biome-def-preset</span> <span style="color:#19177c">biome-query-preset-177</span>
|
|
</span></span><span style="display:flex;"><span> ((<span style="color:#008000">:name</span> <span style="color:#666">.</span> <span style="color:#ba2121">"Weather Forecast"</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#008000">:group</span> <span style="color:#666">.</span> <span style="color:#ba2121">"hourly"</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#008000">:params</span>
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"hourly"</span> <span style="color:#ba2121">"windgusts_10m"</span> <span style="color:#ba2121">"windspeed_10m"</span> <span style="color:#ba2121">"cloudcover"</span> <span style="color:#ba2121">"surface_pressure"</span> <span style="color:#ba2121">"weathercode"</span> <span style="color:#ba2121">"snowfall"</span> <span style="color:#ba2121">"showers"</span> <span style="color:#ba2121">"rain"</span> <span style="color:#ba2121">"relativehumidity_2m"</span> <span style="color:#ba2121">"temperature_2m"</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"longitude"</span> <span style="color:#666">.</span> <span style="color:#666">24.93545</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"latitude"</span> <span style="color:#666">.</span> <span style="color:#666">60.16952</span>))))
|
|
</span></span></code></pre></div><p>Add this somewhere in your config after the package is loaded, e.g., in the <code>:config</code> section of the <code>use-package</code> form or wrapped in <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Hooks-for-Loading.html#index-with_002deval_002dafter_002dload">with-eval-after-load</a>. Running <code>M-x biome-query-preset-177</code> will create a query interface with this preset.</p>
|
|
<p>Alternatively, use the <code>add-to-list</code> form (generated below the <code>biome-def-preset</code> form). Presets added that way will show up in <code>M-x biome-presets</code> or “Presets” in <code>M-x biome</code>.</p>
|
|
<p>Table formatting can be configured with <code>biome-grid-format</code>; check the docstring for more information. For instance, if you want to disable all gradients:</p>
|
|
<div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">setq</span> <span style="color:#19177c">biome-grid-format</span> (<span style="color:#19177c">seq-filter</span> (<span style="color:#008000">lambda</span> (<span style="color:#19177c">f</span>) (<span style="color:#19177c">not</span> (<span style="color:#00f">eq</span> (<span style="color:#00f">car-safe</span> (<span style="color:#00f">nth</span> <span style="color:#666">2</span> <span style="color:#19177c">f</span>))
|
|
</span></span><span style="display:flex;"><span> <span style="color:#19177c">'gradient</span>)))
|
|
</span></span><span style="display:flex;"><span> <span style="color:#19177c">biome-grid-format</span>))
|
|
</span></span></code></pre></div><p>Turn off highlighting of the current hour or day as follows:</p>
|
|
<div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#008000">setq</span> <span style="color:#19177c">biome-grid-highlight-current</span> <span style="color:#800">nil</span>)
|
|
</span></span></code></pre></div><h2 id="composite-queries">Composite queries</h2>
|
|
<p>The package also allows executing multiple queries at once to join their results. This can be useful for comparing weather in different locations or for viewing different reports about the same location.</p>
|
|
<p>Run <code>M-x biome-multi</code> to invoke the-multi query dialog.</p>
|
|
<figure><img src="/biome-img/multi.png">
|
|
</figure>
|
|
|
|
<p>(<em>yes, I’ve switched to a light theme since the time of the previous screenshot</em>)</p>
|
|
<p>Pressing <code>a</code> invokes the standard query dialog, where pressing <code>RET</code> returns to the root dialog, adding the query to the list. Pressing <code>RET</code> in the root dialog executes the queries in the list.</p>
|
|
<p>Queries are executed concurrently. The results are shown if all queries have been successfully completed.</p>
|
|
<p><code>P</code> generates a preset defintion for the current query:</p>
|
|
<div class="highlight"><pre tabindex="0" style=";-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span style="display:flex;"><span>(<span style="color:#19177c">biome-def-multi-preset</span> <span style="color:#19177c">biome-query-preset-601</span>
|
|
</span></span><span style="display:flex;"><span> (((<span style="color:#008000">:name</span> <span style="color:#666">.</span> <span style="color:#ba2121">"Air Quality"</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#008000">:group</span> <span style="color:#666">.</span> <span style="color:#ba2121">"hourly"</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#008000">:params</span>
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"hourly"</span> <span style="color:#ba2121">"uv_index"</span> <span style="color:#ba2121">"european_aqi"</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"longitude"</span> <span style="color:#666">.</span> <span style="color:#666">24.93545</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"latitude"</span> <span style="color:#666">.</span> <span style="color:#666">60.16952</span>)))
|
|
</span></span><span style="display:flex;"><span> ((<span style="color:#008000">:name</span> <span style="color:#666">.</span> <span style="color:#ba2121">"Weather Forecast"</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#008000">:group</span> <span style="color:#666">.</span> <span style="color:#ba2121">"hourly"</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#008000">:params</span>
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"hourly"</span> <span style="color:#ba2121">"weathercode"</span> <span style="color:#ba2121">"snowfall"</span> <span style="color:#ba2121">"showers"</span> <span style="color:#ba2121">"rain"</span> <span style="color:#ba2121">"temperature_2m"</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"longitude"</span> <span style="color:#666">.</span> <span style="color:#666">24.93545</span>)
|
|
</span></span><span style="display:flex;"><span> (<span style="color:#ba2121">"latitude"</span> <span style="color:#666">.</span> <span style="color:#666">60.16952</span>)))))
|
|
</span></span></code></pre></div><p>Just note that the macro is called <code>biome-def-multi-preset</code>.</p>
|
|
<h2 id="implementation-notes">Implementation notes</h2>
|
|
<p>This isn’t the most complicated thing I’ve done, but it’s probably the most over-engineered one.</p>
|
|
<p>As you may have guessed, the interfaces mirror the <a href="https://open-meteo.com/en/docs">API docs</a>. I’ve implemented <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Parsing-HTML_002fXML.html">parsing of these HTMLs</a> in <code>biome-api-parse--generate</code>, which generates the value of <code>biome-api-data</code>. Initially, it downloaded the HTML pages by itself, but - imagine that - the website was migrated to Svelte after I implemented maybe 80% of the parsing logic, and the Svelte version populates the accordions via JavaScript. So, as of now, the function requires opening the website in the browser, manually toggling all the accordions, and copying the HTML from DevTools. Fortunately, the parsing is a one-off operation.</p>
|
|
<p>Then, the interface… I like <a href="https://github.com/magit/transient/">transient.el</a>, so I wanted to make the interface generated dynamically from <code>biome-api-data</code>, which turned out harder than I expected. I probably should’ve just used <a href="https://www.gnu.org/software/emacs/manual/html_mono/widget.html">widget.el</a>.</p>
|
|
<p>Generating sensible keys was a challenge. I’ve made an algorithm in <code>biome-query--unique-keys</code> that sort of works well.</p>
|
|
<p>And as for populating transient prefixes, I tried to use <code>:setup-children</code> in a few places, but it’s not general enough, namely, it doesn’t seem to support specifying <code>:class</code> for child groups… So I ended up overriding <code>transient--layout</code> in the prefix setup. This doesn’t seem to have any undesirable side effects.</p>
|
|
<p>Also, the only way I found to use custom infix classes in these dynamic definitions was to eval <code>transient-define-infix</code> for each required place. Unfortunately, that adds a lot of stuff to the interactive functions namespace.</p>
|
|
<p>Getting to the results display, Lars Ingebrigtsen’s <a href="https://lars.ingebrigtsen.no/2022/04/13/more-vtable-fun/">vtable</a> comes only in Emacs 29, so I used <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Tabulated-List-Mode.html">tabulated-list</a>. The only disadvantage of the latter is the lack of horizontal scroll support, which can be worked around by hiding columns with <code>biome-grid-columns</code>.</p>
|
|
<p>Most variables are formatted with a gradient, colors for which were mostly inspired by <a href="https://www.windy.com/">Windy</a>. Formatting for things like air quality variables is probably all over the place, so take the red color with a grain of salt.</p>
|
|
|
|
</div>
|
|
<div class="table-of-contents">
|
|
<div class="table-of-contents-text">
|
|
<b><a href="#">Table of Contents</a></b>
|
|
<nav id="TableOfContents">
|
|
<ul>
|
|
<li><a href="#installation">Installation</a>
|
|
<ul>
|
|
<li><a href="#issues-with-termux">Issues with termux?</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#usage">Usage</a></li>
|
|
<li><a href="#more-configuration">More configuration</a></li>
|
|
<li><a href="#composite-queries">Composite queries</a></li>
|
|
<li><a href="#implementation-notes">Implementation notes</a></li>
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
<a id="unhide-all-button" class="hidden"><Expand></a>
|
|
<a id="hide-all-button" class="hidden"><Collapse></a>
|
|
</div>
|
|
</div>
|
|
|
|
</div><div id="footer" class="mb-5">
|
|
<hr>
|
|
<div class="container text-center">
|
|
|
|
</div>
|
|
|
|
<div class="container text-center">
|
|
|
|
|
|
<a href="https://creativecommons.org/licenses/by/4.0/legalcode" title="Licensed under CC-BY 4.0"><small>Licensed under CC-BY 4.0</small></a>
|
|
|
|
|
|
|
|
|
|
|
<a href="https://plausible.io/" title="Uses Plausible Analytics"><small>Uses Plausible Analytics</small></a>
|
|
|
|
|
|
<br>
|
|
|
|
<a href="https://sqrtminusone.xyz/" title="Pavel Korytov, 2024"><small>Pavel Korytov, 2024</small></a>
|
|
</div>
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|