<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/assets/atom.xsl" type="text/xsl"?><feed
	xmlns="http://www.w3.org/2005/Atom"
	xmlns:thr="http://purl.org/syndication/thread/1.0"
	xml:lang="en-US"
	><title>Sacha Chua - category - org</title>
	<subtitle>Emacs, sketches, and life</subtitle>
	<link rel="self" type="application/atom+xml" href="https://sachachua.com/blog/category/org/feed/atom/index.xml" />
  <link rel="alternate" type="text/html" href="https://sachachua.com/blog/category/org" />
  <id>https://sachachua.com/blog/category/org/feed/atom/index.xml</id>
  <generator uri="https://11ty.dev">11ty</generator>
	<updated>2026-08-29T14:52:30Z</updated>
<entry>
		<title type="html">Carnaval d'Emacs d'août 2026 : la gestion d'information et les graphes de connaissances</title>
		<link rel="alternate" type="text/html" href="https://sachachua.com/blog/2026/08/carnaval-d-emacs-d-aout-la-gestion-d-information-et-les-graphes-de-connaissances/"/>
		<author><name><![CDATA[Sacha Chua]]></name></author>
		<updated>2026-08-29T14:52:30Z</updated>
    <published>2026-08-29T14:52:30Z</published>
    <category term="emacs" />
<category term="french" />
<category term="org" />
		<id>https://sachachua.com/blog/2026/08/carnaval-d-emacs-d-aout-la-gestion-d-information-et-les-graphes-de-connaissances/</id>
		<content type="html"><![CDATA[<div class="update" id="orgcd91b65">
<p>
English: <a href="https://sachachua.com/blog/2026/08/emacs-carnival-aug-2026-information-management-and-knowledge-graphs/">Emacs Carnival Aug 2026: Information management and knowledge graphs</a>
</p>

</div>

<p>
Cet article est inspiré par le <a href="https://www.emacswiki.org/emacs/Carnival">Carnaval d'Emacs</a> sur <a href="https://www.chiply.dev/post-august-emacs-carnival">la recherche de connaissances</a>. Merci à Charlie Holland pour son accueil ! C'est une bonne occasion de réfléchir à la gestion de mes notes, qui est un de mes intérêts forts.
</p>

<p>
<b>Saisir :</b> Je souhaite saisir et publier ce que j'apprends aussitôt que possible parce que ma mémoire n'est pas fiable. Je préfère le format texte brut car il est le plus consultable et le plus archivable à long terme. Je suis loin de mon ordinateur la plupart du temps, donc j'utilise <a href="https://www.orgzlyrevived.com/">Orgzly Revived</a> sur mon téléphone pour saisir des notes courtes dans ma boîte de réception inbox.org ou mon fichier de brouillons posts.org. Une fois que je suis sur mon ordinateur, je développe mes notes en utilisant <a href="https://orgmode.org">Org Mode</a> sur <a href="https://www.gnu.org/savannah-checkouts/gnu/emacs/emacs.html">Emacs</a>. J'utilise <code>org-refile</code> pour déplacer des notes vers d'autres fichiers comme organizer.org. J'utilise <a href="https://sachachua.com/dotemacs#org-files">quelques grands fichiers Org</a>. Pour les tâches répétitives comme <a href="https://sachachua.com/topic/workflows/">mes flux de travail</a>, j'y ajoute des détails autant que possible.
</p>

<p>
<b>Chercher</b> : Pour chercher mes notes publiques, j'utilise souvent Google. Les notes publiques me permettent de les récupérer facilement. Si je publie mes notes, d'autres personnes peuvent en profiter et les enrichir. Forcément, j'ai aussi des notes personnelles. J'utilise <a href="https://orgmode.org/manual/Refile-and-Copy.html">org-refile</a> pour chercher par titres ou <a href="https://github.com/minad/consult">consult-ripgrep</a> pour naviguer dans mes notes privées. J'utilise aussi <code>consult-line</code> et <code>isearch</code> si je veux chercher par mots dans le corps. Ils reposent sur des comparaisons exactes, mais si j'essaie des mots similaires, je ne peux pas trouver ce que je cherche. C'est la raison pour laquelle je m'intéresse au paquet <a href="https://github.com/zkry/p-search">p-search</a> et <a href="https://sachachua.com/dotemacs/index.html#org-mode-vector-search">aux plongements de phrases</a> (embeddings) pour la recherche approximative, mais je n'ai pas encore mis en place un bon flux de travail. Je rêve d'un système pour suggérer automatiquement des liens vers mes autres articles, ma configuration et mes notes privées, ce qui peut me rafraîchir la mémoire sur des choses oubliées. Une vraie évaluation doit attendre d'avoir plus de temps libre.
</p>

<p>
<b>Naviguer</b> : J'utilise <code>C-u org-refile</code> pour naviguer dans mes sous-titres n'importe où dans mes fichiers <code>org-refile-targets</code>. Je relis aussi ma boîte de réception et mes brouillons de temps en temps. J'ai une fonction <a href="https://sachachua.com/dotemacs#embark-11ty">sacha-blog-edit-org</a> qui ouvre le code source Org à partir d'un lien, même s'il est dans mon posts.org ou seulement dans la copie publiée.
</p>

<p>
<b>Lier</b> : Beaucoup de mes idées sont inspirées par des articles d'autres personnes, donc quand je trouve un article intéressant sur mon téléphone, je l'envoie à Orgzly Revived pour l'ajouter à ma boîte de réception. Ça me permet d'inclure le lien ou les liens dans l'article une fois que je réussis finalement à l'écrire et à le publier.
</p>

<p>
J'ai une petite fonction <a href="https://sachachua.com/dotemacs#mastodon-mastodon-el-mention-people-based-on-regexp">sacha-org-contacts-suggest-mentions</a> qui m'aide à notifier l'auteur de l'article précédent et peut-être d'autres personnes qui sont potentiellement intéressées en utilisant mon fichier people.org, où j'ai spécifié des expressions régulières à comparer au texte.
</p>

<p>
Pour m'aider à lier l'article aux autres ressources, j'ai des fonctions pour lier :
</p>
<ul class="org-ul">
<li><a href="https://sachachua.com/dotemacs#linking-to-blog-posts">aux articles sur mon blog</a> avec le genre de lien "blog"</li>
<li><a href="https://sachachua.com/dotemacs#completion-consult-consult-omni-using-web-searches-and-bookmarks-to-quickly-link-placeholders-in-org-mode">aux autres sites automatiquement à partir du texte du lien</a></li>
</ul>
<p>
(Hmm, je peux automatiser les liens vers les autres parties de ma configuration qui définissent les autres fonctions…)
</p>

<p>
Mes pensées sont souvent déconnectées à cause d'un cerveau qui aime sauter d'un sujet à l'autre.​ (Bien évidemment, même avec cet article…) En écrivant un article, j'ajoute de nombreuses idées dans ma boîte de réception. À bien y penser, je pourrais ajouter à Org Mode un genre de lien qui résoudra un vrai lien une fois que l'article lié sera publié, comme les WikiWords, ce qui peut m'aider à les connecter. Je sais qu'il y a des paquets qui offrent cette fonctionnalité.
</p>

<p>
<b>Publier</b> : J'utilise le générateur de site statique <a href="https://www.11ty.dev/">11ty</a> avec <a href="https://github.com/sachac/ox-11ty/blob/master/ox-11ty.el">ox-11ty.el</a>. Une fois que je publie une note, <a href="https://sachachua.com/dotemacs#moving-sacha-org-post-subtree-to-the-11ty-directory">le code source org est aussi copié dans le même répertoire</a>.
</p>
<div id="outline-container-carnaval-d-emacs-d-ao-t-2026-la-gestion-d-information-et-les-graphes-de-connaissances-visualisation-et-exploration" class="outline-3">
<h3 id="carnaval-d-emacs-d-ao-t-2026-la-gestion-d-information-et-les-graphes-de-connaissances-visualisation-et-exploration"><a href="https://sachachua.com/blog/feed/atom/index.xml#carnaval-d-emacs-d-ao-t-2026-la-gestion-d-information-et-les-graphes-de-connaissances-visualisation-et-exploration">Visualisation et exploration</a></h3>
<div class="outline-text-3" id="text-carnaval-d-emacs-d-ao-t-2026-la-gestion-d-information-et-les-graphes-de-connaissances-visualisation-et-exploration">
<p>
J'ai toujours envie de graphes de connaissances comme celui dans <a href="https://www.jerrysbrain.com/">le cerveau de Jerry</a>. Je pense que l'affichage du voisinage autour de l'article actuel est plus utile qu'un aperçu global (comme ceux de ) qui est impressionnant mais un peu trop difficile à utiliser.​
</p>

<p>
J'adore également les grands jardins publics de connaissances comme celui d'<a href="https://andymatuschak.org/">Andy Matuschak</a> même si on n'a pas une véritable carte ou un graphe. La richesse des liens m'encourage à les explorer. Je préfère les liens intégrés plutôt que les listes ou les connexions ​sans explications. Je suis curieuse aussi du projet <a href="https://anagora.org">Anagora</a>, qui essaye de créer un grand réseau de graphes de connaissances personnels et de faciliter le saut de l'un à l'autre par sujet.
</p>

<p>
Mais je ne veux pas investir trop d'efforts pour le faire moi-même. La majorité de mes articles (sauf le bulletin d'information <a href="https://sachachua.com/blog/category/emacs-news">Emacs News</a> et les revues) contiennent peu de liens. Si je reste au niveau des catégories, il y a trop de points près d'Emacs. Je pourrais convertir les sous-catégories dans <a href="https://sachachua.com/topic/">mon catalogue</a> en données pour la visualisation… Quand même, le catalogue aurait bien besoin d'une mise à jour.
</p>

<p>
Il y a d'autres genres de graphes que j'utilise fréquemment. <a href="https://sachachua.com/blog/2025/07/finding-the-shape-of-my-thoughts/">Je dessine souvent pendant que j'écris</a>. Je fais des cartes mentales et des notes dessinées. En fait, c'est plutôt que je jette plusieurs mots sur une page et puis que je les déplace, les connecte, et les range graduellement. Je le fais pour découvrir ce que je veux dire et comment je peux les organiser. De temps en temps, j'inclus des dessins dans les articles ou les publie dans <a href="https://sketches.sachachua.com">mon carnet de croquis public</a>, et c'est une agréable surprise quand un de ces dessins intéresse d'autres personnes.
</p>

<p>
J'accumule beaucoup de brouillons dans mon fichier posts.org, que je synchronise avec mon téléphone via <a href="https://syncthing.net/">Syncthing</a> pour éditer sur Orgzly Revived. De temps en temps, j'utilise <a href="https://sachachua.com/blog/2025/01/treemap-visualization-of-an-org-mode-file/">une carte arborescente</a> (ou treemap) pour visualiser les tailles des brouillons oubliés (et qui sont peut-être presque finalisés, il leur manque seulement une petite révision ou un ajout). (Hmm, je me demande comment je peux ajouter la taille du sous-arbre aux titres d'Org…)
</p>


<figure id="orgbb928c5">
<a href="https://sachachua.com/blog/2026/08/carnaval-d-emacs-d-aout-la-gestion-d-information-et-les-graphes-de-connaissances/webtreemap.html"><img src="https://sachachua.com/blog/2026/08/carnaval-d-emacs-d-aout-la-gestion-d-information-et-les-graphes-de-connaissances/2026-08-29_08-16-41.png" alt="2026-08-29_08-16-41.png"></a>

<figcaption><span class="figure-number">Figure 1: </span>Une capture d'écran de ma carte arborescente pour mon fichier actuel posts.org</figcaption>
</figure>

<p>
En plus, j'apprécie l'analyse des tendances saisonnières ou annuelles dans ma fréquence de publication (qui me rassure sur le fait que les journées chargées de l'été sont normales et je retrouverai bientôt un peu plus de temps libre):
</p>

<details><summary>Tendances mensuelles</summary>
<div class="org-src-container">
<pre class="src src-python"><code><span class="org-keyword">import</span> json
<span class="org-keyword">import</span> seaborn <span class="org-keyword">as</span> sns
<span class="org-keyword">import</span> re
<span class="org-keyword">from</span> collections <span class="org-keyword">import</span> defaultdict
<span class="org-keyword">import</span> requests
<span class="org-keyword">import</span> numpy <span class="org-keyword">as</span> np
<span class="org-keyword">import</span> pandas <span class="org-keyword">as</span> pd
<span class="org-keyword">import</span> matplotlib.pyplot <span class="org-keyword">as</span> plt
<span class="org-keyword">with</span> <span class="org-builtin">open</span>(<span class="org-string">'/home/sacha/proj/static-blog/_site/blog/all/index.json'</span>) <span class="org-keyword">as</span> jsonfile:
    <span class="org-variable-name">posts</span> <span class="org-operator">=</span> json.load(jsonfile)
    jsonfile.close()
<span class="org-variable-name">monthly_counts</span> <span class="org-operator">=</span> defaultdict(<span class="org-keyword">lambda</span>: defaultdict(<span class="org-builtin">int</span>))
<span class="org-keyword">for</span> post <span class="org-keyword">in</span> posts:
    <span class="org-variable-name">title</span> <span class="org-operator">=</span> post.get(<span class="org-string">"title"</span>, <span class="org-string">""</span>)
    <span class="org-variable-name">date_str</span> <span class="org-operator">=</span> post.get(<span class="org-string">"date"</span>, <span class="org-string">""</span>)
    <span class="org-keyword">if</span> re.search(r<span class="org-string">'emacs news'</span>, title, re.IGNORECASE):
        <span class="org-keyword">continue</span>
    <span class="org-keyword">if</span> date_str <span class="org-keyword">and</span> <span class="org-builtin">len</span>(date_str) <span class="org-operator">&gt;=</span> 7:
        <span class="org-variable-name">year</span> <span class="org-operator">=</span> date_str[:4]
        <span class="org-variable-name">month</span> <span class="org-operator">=</span> <span class="org-builtin">int</span>(date_str[5:7])
        monthly_counts[year][month] <span class="org-operator">+=</span> 1
<span class="org-variable-name">months_labels</span> <span class="org-operator">=</span> [<span class="org-string">'Jan'</span>, <span class="org-string">'F&#233;v'</span>, <span class="org-string">'Mar'</span>, <span class="org-string">'Avr'</span>, <span class="org-string">'Mai'</span>, <span class="org-string">'Juin'</span>, <span class="org-string">'Juil'</span>, <span class="org-string">'Ao&#251;t'</span>, <span class="org-string">'Sept'</span>, <span class="org-string">'Oct'</span>, <span class="org-string">'Nov'</span>, <span class="org-string">'D&#233;c'</span>]
<span class="org-variable-name">years</span> <span class="org-operator">=</span> [<span class="org-string">'2022'</span>, <span class="org-string">'2023'</span>, <span class="org-string">'2024'</span>, <span class="org-string">'2025'</span>, <span class="org-string">'2026'</span>]
<span class="org-variable-name">df</span> <span class="org-operator">=</span> pd.DataFrame(index<span class="org-operator">=</span><span class="org-builtin">range</span>(1, 13), data<span class="org-operator">=</span>{<span class="org-string">'Mois'</span>: months_labels})
<span class="org-keyword">for</span> year <span class="org-keyword">in</span> years:
    <span class="org-variable-name">df</span>[year] <span class="org-operator">=</span> [monthly_counts[year][m] <span class="org-keyword">for</span> m <span class="org-keyword">in</span> <span class="org-builtin">range</span>(1, 13)]
df.<span class="org-variable-name">iloc</span>[8:, <span class="org-operator">-</span>1] <span class="org-operator">=</span> <span class="org-constant">None</span>
<span class="org-variable-name">df_long</span> <span class="org-operator">=</span> df.melt(id_vars<span class="org-operator">=</span>[<span class="org-string">'Mois'</span>], value_vars<span class="org-operator">=</span>years, var_name<span class="org-operator">=</span><span class="org-string">'Ann&#233;e'</span>, value_name<span class="org-operator">=</span><span class="org-string">'Compte'</span>)
<span class="org-variable-name">num_old_years</span> <span class="org-operator">=</span> <span class="org-builtin">len</span>(years) <span class="org-operator">-</span> 1
<span class="org-variable-name">gray_shades</span> <span class="org-operator">=</span> np.linspace(0.8, 0.3, num_old_years)  <span class="org-comment-delimiter"># </span><span class="org-comment">0.8 is lighter, 0.3 is darker</span>
<span class="org-variable-name">custom_colors</span> <span class="org-operator">=</span> {year: <span class="org-builtin">str</span>(shade) <span class="org-keyword">for</span> year, shade <span class="org-keyword">in</span> <span class="org-builtin">zip</span>(years[:<span class="org-operator">-</span>1], gray_shades)}
<span class="org-variable-name">custom_colors</span>[<span class="org-string">'2026'</span>] <span class="org-operator">=</span> <span class="org-string">"#000000"</span>  <span class="org-comment-delimiter"># </span><span class="org-comment">Force the current year to pure black</span>
<span class="org-variable-name">widths</span> <span class="org-operator">=</span> {year: 1 <span class="org-keyword">for</span> year <span class="org-keyword">in</span> years}
<span class="org-variable-name">widths</span>[<span class="org-string">'2026'</span>] <span class="org-operator">=</span> 3
plt.figure(figsize<span class="org-operator">=</span>(10, 5))
<span class="org-variable-name">ax</span> <span class="org-operator">=</span> sns.lineplot(data<span class="org-operator">=</span>df_long, hue<span class="org-operator">=</span><span class="org-string">'Ann&#233;e'</span>, x<span class="org-operator">=</span><span class="org-string">'Mois'</span>, y<span class="org-operator">=</span><span class="org-string">'Compte'</span>, size<span class="org-operator">=</span><span class="org-string">'Ann&#233;e'</span>, palette<span class="org-operator">=</span>custom_colors, sizes<span class="org-operator">=</span>widths, sort<span class="org-operator">=</span><span class="org-constant">False</span>)
ax.set_xticks(<span class="org-builtin">range</span>(12))
ax.set_xticklabels(months_labels)
plt.title(<span class="org-string">"Fr&#233;quence mensuelle des articles sur sachachua.com</span><span class="org-constant">\n</span><span class="org-string">(hors Emacs News)"</span>, fontsize<span class="org-operator">=</span>12, fontweight<span class="org-operator">=</span><span class="org-string">'bold'</span>)
plt.xlabel(<span class="org-string">"Mois"</span>, fontsize<span class="org-operator">=</span>10)
plt.ylabel(<span class="org-string">"Nombre d'articles publi&#233;s"</span>, fontsize<span class="org-operator">=</span>10)
plt.grid(<span class="org-constant">True</span>, linestyle<span class="org-operator">=</span><span class="org-string">'&#45;&#45;'</span>, alpha<span class="org-operator">=</span>0.5)
plt.legend(loc<span class="org-operator">=</span><span class="org-string">'upper right'</span>)
plt.tight_layout()
plt.savefig(<span class="org-string">'frequence.svg'</span>)
<span class="org-keyword">return</span> df
</code></pre>
</div>

</details>

<table>


<colgroup>
<col class="org-right">

<col class="org-left">

<col class="org-right">

<col class="org-right">

<col class="org-right">

<col class="org-right">

<col class="org-right">
</colgroup>
<thead>
<tr>
<th scope="col" class="org-right">&nbsp;</th>
<th scope="col" class="org-left">Mois</th>
<th scope="col" class="org-right">2022</th>
<th scope="col" class="org-right">2023</th>
<th scope="col" class="org-right">2024</th>
<th scope="col" class="org-right">2025</th>
<th scope="col" class="org-right">2026</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-right">1</td>
<td class="org-left">Jan</td>
<td class="org-right">6</td>
<td class="org-right">19</td>
<td class="org-right">20</td>
<td class="org-right">23</td>
<td class="org-right">16.0</td>
</tr>

<tr>
<td class="org-right">2</td>
<td class="org-left">Fév</td>
<td class="org-right">0</td>
<td class="org-right">3</td>
<td class="org-right">0</td>
<td class="org-right">10</td>
<td class="org-right">8.0</td>
</tr>

<tr>
<td class="org-right">3</td>
<td class="org-left">Mar</td>
<td class="org-right">0</td>
<td class="org-right">5</td>
<td class="org-right">1</td>
<td class="org-right">24</td>
<td class="org-right">15.0</td>
</tr>

<tr>
<td class="org-right">4</td>
<td class="org-left">Avr</td>
<td class="org-right">0</td>
<td class="org-right">2</td>
<td class="org-right">1</td>
<td class="org-right">14</td>
<td class="org-right">22.0</td>
</tr>

<tr>
<td class="org-right">5</td>
<td class="org-left">Mai</td>
<td class="org-right">0</td>
<td class="org-right">1</td>
<td class="org-right">1</td>
<td class="org-right">9</td>
<td class="org-right">15.0</td>
</tr>

<tr>
<td class="org-right">6</td>
<td class="org-left">Juin</td>
<td class="org-right">0</td>
<td class="org-right">3</td>
<td class="org-right">1</td>
<td class="org-right">9</td>
<td class="org-right">13.0</td>
</tr>

<tr>
<td class="org-right">7</td>
<td class="org-left">Juil</td>
<td class="org-right">1</td>
<td class="org-right">0</td>
<td class="org-right">0</td>
<td class="org-right">6</td>
<td class="org-right">9.0</td>
</tr>

<tr>
<td class="org-right">8</td>
<td class="org-left">Août</td>
<td class="org-right">7</td>
<td class="org-right">2</td>
<td class="org-right">1</td>
<td class="org-right">5</td>
<td class="org-right">11.0</td>
</tr>

<tr>
<td class="org-right">9</td>
<td class="org-left">Sept</td>
<td class="org-right">1</td>
<td class="org-right">8</td>
<td class="org-right">12</td>
<td class="org-right">17</td>
<td class="org-right">nan</td>
</tr>

<tr>
<td class="org-right">10</td>
<td class="org-left">Oct</td>
<td class="org-right">2</td>
<td class="org-right">12</td>
<td class="org-right">29</td>
<td class="org-right">11</td>
<td class="org-right">nan</td>
</tr>

<tr>
<td class="org-right">11</td>
<td class="org-left">Nov</td>
<td class="org-right">5</td>
<td class="org-right">1</td>
<td class="org-right">19</td>
<td class="org-right">8</td>
<td class="org-right">nan</td>
</tr>

<tr>
<td class="org-right">12</td>
<td class="org-left">Déc</td>
<td class="org-right">4</td>
<td class="org-right">15</td>
<td class="org-right">6</td>
<td class="org-right">6</td>
<td class="org-right">nan</td>
</tr>
</tbody>
</table>


<figure id="org162ab78">

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="720pt" height="360pt" viewBox="0 0 720 360" xmlns="http://www.w3.org/2000/svg" version="1.1">
 <metadata>
  <rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
   <cc:Work>
    <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"></dc:type>
    <dc:date>2026-08-30T08:43:07.159204</dc:date>
    <dc:format>image/svg+xml</dc:format>
    <dc:creator>
     <cc:Agent>
      <dc:title>Matplotlib v3.11.0, https://matplotlib.org/</dc:title>
     </cc:Agent>
    </dc:creator>
   </cc:Work>
  </rdf:RDF>
 </metadata>
 <defs>
  <style type="text/css">*{stroke-linejoin: round; stroke-linecap: butt}</style>
 </defs>
 <g id="figure_1">
  <g id="patch_1">
   <path d="M 0 360 
L 720 360 
L 720 0 
L 0 0 
z
" style="fill: #ffffff"></path>
  </g>
  <g id="axes_1">
   <g id="patch_2">
    <path d="M 45.082344 317.555313 
L 709.2 317.555313 
L 709.2 42.726328 
L 45.082344 42.726328 
z
" style="fill: #ffffff"></path>
   </g>
   <g id="FillBetweenPolyCollection_1"></g>
   <g id="FillBetweenPolyCollection_2"></g>
   <g id="FillBetweenPolyCollection_3"></g>
   <g id="FillBetweenPolyCollection_4"></g>
   <g id="FillBetweenPolyCollection_5"></g>
   <g id="matplotlib.axis_1">
    <g id="xtick_1">
     <g id="line2d_1">
      <path d="M 75.26951 317.555313 
L 75.26951 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_2">
      <defs>
       <path id="m77e64fe0b2" d="M 0 0 
L 0 3.5 
" style="stroke: #000000; stroke-width: 0.8"></path>
      </defs>
      <g>
       <use xlink:href="#m77e64fe0b2" x="75.26951" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_1">
      
      <g transform="translate(67.561697 332.152969) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-2d" d="M 628 4666 
L 1259 4666 
L 1259 325 
Q 1259 -519 939 -900 
Q 619 -1281 -91 -1281 
L -331 -1281 
L -331 -750 
L -134 -750 
Q 284 -750 456 -515 
Q 628 -281 628 325 
L 628 4666 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-44" d="M 2194 1759 
Q 1497 1759 1228 1600 
Q 959 1441 959 1056 
Q 959 750 1161 570 
Q 1363 391 1709 391 
Q 2188 391 2477 730 
Q 2766 1069 2766 1631 
L 2766 1759 
L 2194 1759 
z
M 3341 1997 
L 3341 0 
L 2766 0 
L 2766 531 
Q 2569 213 2275 61 
Q 1981 -91 1556 -91 
Q 1019 -91 701 211 
Q 384 513 384 1019 
Q 384 1609 779 1909 
Q 1175 2209 1959 2209 
L 2766 2209 
L 2766 2266 
Q 2766 2663 2505 2880 
Q 2244 3097 1772 3097 
Q 1472 3097 1187 3025 
Q 903 2953 641 2809 
L 641 3341 
Q 956 3463 1253 3523 
Q 1550 3584 1831 3584 
Q 2591 3584 2966 3190 
Q 3341 2797 3341 1997 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-51" d="M 3513 2113 
L 3513 0 
L 2938 0 
L 2938 2094 
Q 2938 2591 2744 2837 
Q 2550 3084 2163 3084 
Q 1697 3084 1428 2787 
Q 1159 2491 1159 1978 
L 1159 0 
L 581 0 
L 581 3500 
L 1159 3500 
L 1159 2956 
Q 1366 3272 1645 3428 
Q 1925 3584 2291 3584 
Q 2894 3584 3203 3211 
Q 3513 2838 3513 2113 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-2d"></use>
       <use xlink:href="#DejaVuSans-44" transform="translate(29.5 0)"></use>
       <use xlink:href="#DejaVuSans-51" transform="translate(90.78125 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_2">
     <g id="line2d_3">
      <path d="M 130.155267 317.555313 
L 130.155267 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_4">
      <g>
       <use xlink:href="#m77e64fe0b2" x="130.155267" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_2">
      
      <g transform="translate(121.516985 332.55375) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-29" d="M 628 4666 
L 3309 4666 
L 3309 4134 
L 1259 4134 
L 1259 2759 
L 3109 2759 
L 3109 2228 
L 1259 2228 
L 1259 0 
L 628 0 
L 628 4666 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-ab" d="M 3597 1894 
L 3597 1613 
L 953 1613 
Q 991 1019 1311 708 
Q 1631 397 2203 397 
Q 2534 397 2845 478 
Q 3156 559 3463 722 
L 3463 178 
Q 3153 47 2828 -22 
Q 2503 -91 2169 -91 
Q 1331 -91 842 396 
Q 353 884 353 1716 
Q 353 2575 817 3079 
Q 1281 3584 2069 3584 
Q 2775 3584 3186 3129 
Q 3597 2675 3597 1894 
z
M 3022 2063 
Q 3016 2534 2758 2815 
Q 2500 3097 2075 3097 
Q 1594 3097 1305 2825 
Q 1016 2553 972 2059 
L 3022 2063 
z
M 2468 5119 
L 3090 5119 
L 2072 3944 
L 1593 3944 
L 2468 5119 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-59" d="M 191 3500 
L 800 3500 
L 1894 563 
L 2988 3500 
L 3597 3500 
L 2284 0 
L 1503 0 
L 191 3500 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-29"></use>
       <use xlink:href="#DejaVuSans-ab" transform="translate(52.046875 0)"></use>
       <use xlink:href="#DejaVuSans-59" transform="translate(113.578125 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_3">
     <g id="line2d_5">
      <path d="M 185.041023 317.555313 
L 185.041023 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_6">
      <g>
       <use xlink:href="#m77e64fe0b2" x="185.041023" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_3">
      
      <g transform="translate(175.60743 332.152969) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-30" d="M 628 4666 
L 1569 4666 
L 2759 1491 
L 3956 4666 
L 4897 4666 
L 4897 0 
L 4281 0 
L 4281 4097 
L 3078 897 
L 2444 897 
L 1241 4097 
L 1241 0 
L 628 0 
L 628 4666 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-55" d="M 2631 2963 
Q 2534 3019 2420 3045 
Q 2306 3072 2169 3072 
Q 1681 3072 1420 2755 
Q 1159 2438 1159 1844 
L 1159 0 
L 581 0 
L 581 3500 
L 1159 3500 
L 1159 2956 
Q 1341 3275 1631 3429 
Q 1922 3584 2338 3584 
Q 2397 3584 2469 3576 
Q 2541 3569 2628 3553 
L 2631 2963 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-30"></use>
       <use xlink:href="#DejaVuSans-44" transform="translate(86.28125 0)"></use>
       <use xlink:href="#DejaVuSans-55" transform="translate(147.5625 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_4">
     <g id="line2d_7">
      <path d="M 239.92678 317.555313 
L 239.92678 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_8">
      <g>
       <use xlink:href="#m77e64fe0b2" x="239.92678" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_4">
      
      <g transform="translate(231.784593 332.152969) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-24" d="M 2188 4044 
L 1331 1722 
L 3047 1722 
L 2188 4044 
z
M 1831 4666 
L 2547 4666 
L 4325 0 
L 3669 0 
L 3244 1197 
L 1141 1197 
L 716 0 
L 50 0 
L 1831 4666 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-24"></use>
       <use xlink:href="#DejaVuSans-59" transform="translate(62.546875 0)"></use>
       <use xlink:href="#DejaVuSans-55" transform="translate(121.734375 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_5">
     <g id="line2d_9">
      <path d="M 294.812537 317.555313 
L 294.812537 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_10">
      <g>
       <use xlink:href="#m77e64fe0b2" x="294.812537" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_5">
      
      <g transform="translate(286.045349 332.15375) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-4c" d="M 603 3500 
L 1178 3500 
L 1178 0 
L 603 0 
L 603 3500 
z
M 603 4863 
L 1178 4863 
L 1178 4134 
L 603 4134 
L 603 4863 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-30"></use>
       <use xlink:href="#DejaVuSans-44" transform="translate(86.28125 0)"></use>
       <use xlink:href="#DejaVuSans-4c" transform="translate(147.5625 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_6">
     <g id="line2d_11">
      <path d="M 349.698294 317.555313 
L 349.698294 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_12">
      <g>
       <use xlink:href="#m77e64fe0b2" x="349.698294" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_6">
      
      <g transform="translate(340.496731 332.15375) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-58" d="M 544 1381 
L 544 3500 
L 1119 3500 
L 1119 1403 
Q 1119 906 1312 657 
Q 1506 409 1894 409 
Q 2359 409 2629 706 
Q 2900 1003 2900 1516 
L 2900 3500 
L 3475 3500 
L 3475 0 
L 2900 0 
L 2900 538 
Q 2691 219 2414 64 
Q 2138 -91 1772 -91 
Q 1169 -91 856 284 
Q 544 659 544 1381 
z
M 1991 3584 
L 1991 3584 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-2d"></use>
       <use xlink:href="#DejaVuSans-58" transform="translate(29.5 0)"></use>
       <use xlink:href="#DejaVuSans-4c" transform="translate(92.875 0)"></use>
       <use xlink:href="#DejaVuSans-51" transform="translate(120.65625 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_7">
     <g id="line2d_13">
      <path d="M 404.58405 317.555313 
L 404.58405 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_14">
      <g>
       <use xlink:href="#m77e64fe0b2" x="404.58405" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_7">
      
      <g transform="translate(397.162175 332.15375) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-4f" d="M 603 4863 
L 1178 4863 
L 1178 0 
L 603 0 
L 603 4863 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-2d"></use>
       <use xlink:href="#DejaVuSans-58" transform="translate(29.5 0)"></use>
       <use xlink:href="#DejaVuSans-4c" transform="translate(92.875 0)"></use>
       <use xlink:href="#DejaVuSans-4f" transform="translate(120.65625 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_8">
     <g id="line2d_15">
      <path d="M 459.469807 317.555313 
L 459.469807 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_16">
      <g>
       <use xlink:href="#m77e64fe0b2" x="459.469807" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_8">
      
      <g transform="translate(447.948713 332.55375) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-52" d="M 1959 3097 
Q 1497 3097 1228 2736 
Q 959 2375 959 1747 
Q 959 1119 1226 758 
Q 1494 397 1959 397 
Q 2419 397 2687 759 
Q 2956 1122 2956 1747 
Q 2956 2369 2687 2733 
Q 2419 3097 1959 3097 
z
M 1959 3584 
Q 2709 3584 3137 3096 
Q 3566 2609 3566 1747 
Q 3566 888 3137 398 
Q 2709 -91 1959 -91 
Q 1206 -91 779 398 
Q 353 888 353 1747 
Q 353 2609 779 3096 
Q 1206 3584 1959 3584 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-bd" d="M 544 1381 
L 544 3500 
L 1119 3500 
L 1119 1403 
Q 1119 906 1312 657 
Q 1506 409 1894 409 
Q 2359 409 2629 706 
Q 2900 1003 2900 1516 
L 2900 3500 
L 3475 3500 
L 3475 0 
L 2900 0 
L 2900 538 
Q 2691 219 2414 64 
Q 2138 -91 1772 -91 
Q 1169 -91 856 284 
Q 544 659 544 1381 
z
M 1991 3584 
L 1991 3584 
z
M 1753 5119 
L 2215 5119 
L 2981 3944 
L 2547 3944 
L 1984 4709 
L 1422 3944 
L 987 3944 
L 1753 5119 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-57" d="M 1172 4494 
L 1172 3500 
L 2356 3500 
L 2356 3053 
L 1172 3053 
L 1172 1153 
Q 1172 725 1289 603 
Q 1406 481 1766 481 
L 2356 481 
L 2356 0 
L 1766 0 
Q 1100 0 847 248 
Q 594 497 594 1153 
L 594 3053 
L 172 3053 
L 172 3500 
L 594 3500 
L 594 4494 
L 1172 4494 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-24"></use>
       <use xlink:href="#DejaVuSans-52" transform="translate(66.65625 0)"></use>
       <use xlink:href="#DejaVuSans-bd" transform="translate(127.84375 0)"></use>
       <use xlink:href="#DejaVuSans-57" transform="translate(191.21875 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_9">
     <g id="line2d_17">
      <path d="M 514.355564 317.555313 
L 514.355564 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_18">
      <g>
       <use xlink:href="#m77e64fe0b2" x="514.355564" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_9">
      
      <g transform="translate(502.970407 332.152969) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-36" d="M 3425 4513 
L 3425 3897 
Q 3066 4069 2747 4153 
Q 2428 4238 2131 4238 
Q 1616 4238 1336 4038 
Q 1056 3838 1056 3469 
Q 1056 3159 1242 3001 
Q 1428 2844 1947 2747 
L 2328 2669 
Q 3034 2534 3370 2195 
Q 3706 1856 3706 1288 
Q 3706 609 3251 259 
Q 2797 -91 1919 -91 
Q 1588 -91 1214 -16 
Q 841 59 441 206 
L 441 856 
Q 825 641 1194 531 
Q 1563 422 1919 422 
Q 2459 422 2753 634 
Q 3047 847 3047 1241 
Q 3047 1584 2836 1778 
Q 2625 1972 2144 2069 
L 1759 2144 
Q 1053 2284 737 2584 
Q 422 2884 422 3419 
Q 422 4038 858 4394 
Q 1294 4750 2059 4750 
Q 2388 4750 2728 4690 
Q 3069 4631 3425 4513 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-48" d="M 3597 1894 
L 3597 1613 
L 953 1613 
Q 991 1019 1311 708 
Q 1631 397 2203 397 
Q 2534 397 2845 478 
Q 3156 559 3463 722 
L 3463 178 
Q 3153 47 2828 -22 
Q 2503 -91 2169 -91 
Q 1331 -91 842 396 
Q 353 884 353 1716 
Q 353 2575 817 3079 
Q 1281 3584 2069 3584 
Q 2775 3584 3186 3129 
Q 3597 2675 3597 1894 
z
M 3022 2063 
Q 3016 2534 2758 2815 
Q 2500 3097 2075 3097 
Q 1594 3097 1305 2825 
Q 1016 2553 972 2059 
L 3022 2063 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-53" d="M 1159 525 
L 1159 -1331 
L 581 -1331 
L 581 3500 
L 1159 3500 
L 1159 2969 
Q 1341 3281 1617 3432 
Q 1894 3584 2278 3584 
Q 2916 3584 3314 3078 
Q 3713 2572 3713 1747 
Q 3713 922 3314 415 
Q 2916 -91 2278 -91 
Q 1894 -91 1617 61 
Q 1341 213 1159 525 
z
M 3116 1747 
Q 3116 2381 2855 2742 
Q 2594 3103 2138 3103 
Q 1681 3103 1420 2742 
Q 1159 2381 1159 1747 
Q 1159 1113 1420 752 
Q 1681 391 2138 391 
Q 2594 391 2855 752 
Q 3116 1113 3116 1747 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-36"></use>
       <use xlink:href="#DejaVuSans-48" transform="translate(63.484375 0)"></use>
       <use xlink:href="#DejaVuSans-53" transform="translate(125.015625 0)"></use>
       <use xlink:href="#DejaVuSans-57" transform="translate(188.5 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_10">
     <g id="line2d_19">
      <path d="M 569.24132 317.555313 
L 569.24132 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_20">
      <g>
       <use xlink:href="#m77e64fe0b2" x="569.24132" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_10">
      
      <g transform="translate(560.596008 332.152969) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-32" d="M 2522 4238 
Q 1834 4238 1429 3725 
Q 1025 3213 1025 2328 
Q 1025 1447 1429 934 
Q 1834 422 2522 422 
Q 3209 422 3611 934 
Q 4013 1447 4013 2328 
Q 4013 3213 3611 3725 
Q 3209 4238 2522 4238 
z
M 2522 4750 
Q 3503 4750 4090 4092 
Q 4678 3434 4678 2328 
Q 4678 1225 4090 567 
Q 3503 -91 2522 -91 
Q 1538 -91 948 565 
Q 359 1222 359 2328 
Q 359 3434 948 4092 
Q 1538 4750 2522 4750 
z
" transform="scale(0.015625)"></path>
        <path id="DejaVuSans-46" d="M 3122 3366 
L 3122 2828 
Q 2878 2963 2633 3030 
Q 2388 3097 2138 3097 
Q 1578 3097 1268 2742 
Q 959 2388 959 1747 
Q 959 1106 1268 751 
Q 1578 397 2138 397 
Q 2388 397 2633 464 
Q 2878 531 3122 666 
L 3122 134 
Q 2881 22 2623 -34 
Q 2366 -91 2075 -91 
Q 1284 -91 818 406 
Q 353 903 353 1747 
Q 353 2603 823 3093 
Q 1294 3584 2113 3584 
Q 2378 3584 2631 3529 
Q 2884 3475 3122 3366 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-32"></use>
       <use xlink:href="#DejaVuSans-46" transform="translate(78.71875 0)"></use>
       <use xlink:href="#DejaVuSans-57" transform="translate(133.703125 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_11">
     <g id="line2d_21">
      <path d="M 624.127077 317.555313 
L 624.127077 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_22">
      <g>
       <use xlink:href="#m77e64fe0b2" x="624.127077" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_11">
      
      <g transform="translate(614.367702 332.152969) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-31" d="M 628 4666 
L 1478 4666 
L 3547 763 
L 3547 4666 
L 4159 4666 
L 4159 0 
L 3309 0 
L 1241 3903 
L 1241 0 
L 628 0 
L 628 4666 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-31"></use>
       <use xlink:href="#DejaVuSans-52" transform="translate(74.8125 0)"></use>
       <use xlink:href="#DejaVuSans-59" transform="translate(136 0)"></use>
      </g>
     </g>
    </g>
    <g id="xtick_12">
     <g id="line2d_23">
      <path d="M 679.012834 317.555313 
L 679.012834 42.726328 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_24">
      <g>
       <use xlink:href="#m77e64fe0b2" x="679.012834" y="317.555313" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_12">
      
      <g transform="translate(669.337053 332.55375) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-27" d="M 1259 4147 
L 1259 519 
L 2022 519 
Q 2988 519 3436 956 
Q 3884 1394 3884 2338 
Q 3884 3275 3436 3711 
Q 2988 4147 2022 4147 
L 1259 4147 
z
M 628 4666 
L 1925 4666 
Q 3281 4666 3915 4102 
Q 4550 3538 4550 2338 
Q 4550 1131 3912 565 
Q 3275 0 1925 0 
L 628 0 
L 628 4666 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-27"></use>
       <use xlink:href="#DejaVuSans-ab" transform="translate(77 0)"></use>
       <use xlink:href="#DejaVuSans-46" transform="translate(138.53125 0)"></use>
      </g>
     </g>
    </g>
    <g id="text_13">
     
     <g transform="translate(365.773984 346.554531) scale(0.1 -0.1)">
      <defs>
       <path id="DejaVuSans-56" d="M 2834 3397 
L 2834 2853 
Q 2591 2978 2328 3040 
Q 2066 3103 1784 3103 
Q 1356 3103 1142 2972 
Q 928 2841 928 2578 
Q 928 2378 1081 2264 
Q 1234 2150 1697 2047 
L 1894 2003 
Q 2506 1872 2764 1633 
Q 3022 1394 3022 966 
Q 3022 478 2636 193 
Q 2250 -91 1575 -91 
Q 1294 -91 989 -36 
Q 684 19 347 128 
L 347 722 
Q 666 556 975 473 
Q 1284 391 1588 391 
Q 1994 391 2212 530 
Q 2431 669 2431 922 
Q 2431 1156 2273 1281 
Q 2116 1406 1581 1522 
L 1381 1569 
Q 847 1681 609 1914 
Q 372 2147 372 2553 
Q 372 3047 722 3315 
Q 1072 3584 1716 3584 
Q 2034 3584 2315 3537 
Q 2597 3491 2834 3397 
z
" transform="scale(0.015625)"></path>
      </defs>
      <use xlink:href="#DejaVuSans-30"></use>
      <use xlink:href="#DejaVuSans-52" transform="translate(86.28125 0)"></use>
      <use xlink:href="#DejaVuSans-4c" transform="translate(147.46875 0)"></use>
      <use xlink:href="#DejaVuSans-56" transform="translate(175.25 0)"></use>
     </g>
    </g>
   </g>
   <g id="matplotlib.axis_2">
    <g id="ytick_1">
     <g id="line2d_25">
      <path d="M 45.082344 305.063086 
L 709.2 305.063086 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_26">
      <defs>
       <path id="me0f1f518fd" d="M 0 0 
L -3.5 0 
" style="stroke: #000000; stroke-width: 0.8"></path>
      </defs>
      <g>
       <use xlink:href="#me0f1f518fd" x="45.082344" y="305.063086" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_14">
      
      <g transform="translate(31.719844 308.861914) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-13" d="M 2034 4250 
Q 1547 4250 1301 3770 
Q 1056 3291 1056 2328 
Q 1056 1369 1301 889 
Q 1547 409 2034 409 
Q 2525 409 2770 889 
Q 3016 1369 3016 2328 
Q 3016 3291 2770 3770 
Q 2525 4250 2034 4250 
z
M 2034 4750 
Q 2819 4750 3233 4129 
Q 3647 3509 3647 2328 
Q 3647 1150 3233 529 
Q 2819 -91 2034 -91 
Q 1250 -91 836 529 
Q 422 1150 422 2328 
Q 422 3509 836 4129 
Q 1250 4750 2034 4750 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-13"></use>
      </g>
     </g>
    </g>
    <g id="ytick_2">
     <g id="line2d_27">
      <path d="M 45.082344 261.986443 
L 709.2 261.986443 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_28">
      <g>
       <use xlink:href="#me0f1f518fd" x="45.082344" y="261.986443" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_15">
      
      <g transform="translate(31.719844 265.785271) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-18" d="M 691 4666 
L 3169 4666 
L 3169 4134 
L 1269 4134 
L 1269 2991 
Q 1406 3038 1543 3061 
Q 1681 3084 1819 3084 
Q 2600 3084 3056 2656 
Q 3513 2228 3513 1497 
Q 3513 744 3044 326 
Q 2575 -91 1722 -91 
Q 1428 -91 1123 -41 
Q 819 9 494 109 
L 494 744 
Q 775 591 1075 516 
Q 1375 441 1709 441 
Q 2250 441 2565 725 
Q 2881 1009 2881 1497 
Q 2881 1984 2565 2268 
Q 2250 2553 1709 2553 
Q 1456 2553 1204 2497 
Q 953 2441 691 2322 
L 691 4666 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-18"></use>
      </g>
     </g>
    </g>
    <g id="ytick_3">
     <g id="line2d_29">
      <path d="M 45.082344 218.909799 
L 709.2 218.909799 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_30">
      <g>
       <use xlink:href="#me0f1f518fd" x="45.082344" y="218.909799" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_16">
      
      <g transform="translate(25.357344 222.708627) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-14" d="M 794 531 
L 1825 531 
L 1825 4091 
L 703 3866 
L 703 4441 
L 1819 4666 
L 2450 4666 
L 2450 531 
L 3481 531 
L 3481 0 
L 794 0 
L 794 531 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-14"></use>
       <use xlink:href="#DejaVuSans-13" transform="translate(63.625 0)"></use>
      </g>
     </g>
    </g>
    <g id="ytick_4">
     <g id="line2d_31">
      <path d="M 45.082344 175.833156 
L 709.2 175.833156 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_32">
      <g>
       <use xlink:href="#me0f1f518fd" x="45.082344" y="175.833156" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_17">
      
      <g transform="translate(25.357344 179.631984) scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-14"></use>
       <use xlink:href="#DejaVuSans-18" transform="translate(63.625 0)"></use>
      </g>
     </g>
    </g>
    <g id="ytick_5">
     <g id="line2d_33">
      <path d="M 45.082344 132.756513 
L 709.2 132.756513 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_34">
      <g>
       <use xlink:href="#me0f1f518fd" x="45.082344" y="132.756513" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_18">
      
      <g transform="translate(25.357344 136.555341) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-15" d="M 1228 531 
L 3431 531 
L 3431 0 
L 469 0 
L 469 531 
Q 828 903 1448 1529 
Q 2069 2156 2228 2338 
Q 2531 2678 2651 2914 
Q 2772 3150 2772 3378 
Q 2772 3750 2511 3984 
Q 2250 4219 1831 4219 
Q 1534 4219 1204 4116 
Q 875 4013 500 3803 
L 500 4441 
Q 881 4594 1212 4672 
Q 1544 4750 1819 4750 
Q 2544 4750 2975 4387 
Q 3406 4025 3406 3419 
Q 3406 3131 3298 2873 
Q 3191 2616 2906 2266 
Q 2828 2175 2409 1742 
Q 1991 1309 1228 531 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-15"></use>
       <use xlink:href="#DejaVuSans-13" transform="translate(63.625 0)"></use>
      </g>
     </g>
    </g>
    <g id="ytick_6">
     <g id="line2d_35">
      <path d="M 45.082344 89.679869 
L 709.2 89.679869 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_36">
      <g>
       <use xlink:href="#me0f1f518fd" x="45.082344" y="89.679869" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_19">
      
      <g transform="translate(25.357344 93.478697) scale(0.1 -0.1)">
       <use xlink:href="#DejaVuSans-15"></use>
       <use xlink:href="#DejaVuSans-18" transform="translate(63.625 0)"></use>
      </g>
     </g>
    </g>
    <g id="ytick_7">
     <g id="line2d_37">
      <path d="M 45.082344 46.603226 
L 709.2 46.603226 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke-dasharray: 2.96,1.28; stroke-dashoffset: 0; stroke: #b0b0b0; stroke-opacity: 0.5; stroke-width: 0.8"></path>
     </g>
     <g id="line2d_38">
      <g>
       <use xlink:href="#me0f1f518fd" x="45.082344" y="46.603226" style="stroke: #000000; stroke-width: 0.8"></use>
      </g>
     </g>
     <g id="text_20">
      
      <g transform="translate(25.357344 50.402054) scale(0.1 -0.1)">
       <defs>
        <path id="DejaVuSans-16" d="M 2597 2516 
Q 3050 2419 3304 2112 
Q 3559 1806 3559 1356 
Q 3559 666 3084 287 
Q 2609 -91 1734 -91 
Q 1441 -91 1130 -33 
Q 819 25 488 141 
L 488 750 
Q 750 597 1062 519 
Q 1375 441 1716 441 
Q 2309 441 2620 675 
Q 2931 909 2931 1356 
Q 2931 1769 2642 2001 
Q 2353 2234 1838 2234 
L 1294 2234 
L 1294 2753 
L 1863 2753 
Q 2328 2753 2575 2939 
Q 2822 3125 2822 3475 
Q 2822 3834 2567 4026 
Q 2313 4219 1838 4219 
Q 1578 4219 1281 4162 
Q 984 4106 628 3988 
L 628 4550 
Q 988 4650 1302 4700 
Q 1616 4750 1894 4750 
Q 2613 4750 3031 4423 
Q 3450 4097 3450 3541 
Q 3450 3153 3228 2886 
Q 3006 2619 2597 2516 
z
" transform="scale(0.015625)"></path>
       </defs>
       <use xlink:href="#DejaVuSans-16"></use>
       <use xlink:href="#DejaVuSans-13" transform="translate(63.625 0)"></use>
      </g>
     </g>
    </g>
    <g id="text_21">
     
     <g transform="translate(18.955 243.998633) rotate(-90) scale(0.1 -0.1)">
      <defs>
       <path id="DejaVuSans-50" d="M 3328 2828 
Q 3544 3216 3844 3400 
Q 4144 3584 4550 3584 
Q 5097 3584 5394 3201 
Q 5691 2819 5691 2113 
L 5691 0 
L 5113 0 
L 5113 2094 
Q 5113 2597 4934 2840 
Q 4756 3084 4391 3084 
Q 3944 3084 3684 2787 
Q 3425 2491 3425 1978 
L 3425 0 
L 2847 0 
L 2847 2094 
Q 2847 2600 2669 2842 
Q 2491 3084 2119 3084 
Q 1678 3084 1418 2786 
Q 1159 2488 1159 1978 
L 1159 0 
L 581 0 
L 581 3500 
L 1159 3500 
L 1159 2956 
Q 1356 3278 1631 3431 
Q 1906 3584 2284 3584 
Q 2666 3584 2933 3390 
Q 3200 3197 3328 2828 
z
" transform="scale(0.015625)"></path>
       <path id="DejaVuSans-45" d="M 3116 1747 
Q 3116 2381 2855 2742 
Q 2594 3103 2138 3103 
Q 1681 3103 1420 2742 
Q 1159 2381 1159 1747 
Q 1159 1113 1420 752 
Q 1681 391 2138 391 
Q 2594 391 2855 752 
Q 3116 1113 3116 1747 
z
M 1159 2969 
Q 1341 3281 1617 3432 
Q 1894 3584 2278 3584 
Q 2916 3584 3314 3078 
Q 3713 2572 3713 1747 
Q 3713 922 3314 415 
Q 2916 -91 2278 -91 
Q 1894 -91 1617 61 
Q 1341 213 1159 525 
L 1159 0 
L 581 0 
L 581 4863 
L 1159 4863 
L 1159 2969 
z
" transform="scale(0.015625)"></path>
       <path id="DejaVuSans-3" transform="scale(0.015625)"></path>
       <path id="DejaVuSans-47" d="M 2906 2969 
L 2906 4863 
L 3481 4863 
L 3481 0 
L 2906 0 
L 2906 525 
Q 2725 213 2448 61 
Q 2172 -91 1784 -91 
Q 1150 -91 751 415 
Q 353 922 353 1747 
Q 353 2572 751 3078 
Q 1150 3584 1784 3584 
Q 2172 3584 2448 3432 
Q 2725 3281 2906 2969 
z
M 947 1747 
Q 947 1113 1208 752 
Q 1469 391 1925 391 
Q 2381 391 2643 752 
Q 2906 1113 2906 1747 
Q 2906 2381 2643 2742 
Q 2381 3103 1925 3103 
Q 1469 3103 1208 2742 
Q 947 2381 947 1747 
z
" transform="scale(0.015625)"></path>
       <path id="DejaVuSans-a" d="M 1147 4666 
L 1147 2931 
L 616 2931 
L 616 4666 
L 1147 4666 
z
" transform="scale(0.015625)"></path>
      </defs>
      <use xlink:href="#DejaVuSans-31"></use>
      <use xlink:href="#DejaVuSans-52" transform="translate(74.8125 0)"></use>
      <use xlink:href="#DejaVuSans-50" transform="translate(136 0)"></use>
      <use xlink:href="#DejaVuSans-45" transform="translate(233.40625 0)"></use>
      <use xlink:href="#DejaVuSans-55" transform="translate(296.890625 0)"></use>
      <use xlink:href="#DejaVuSans-48" transform="translate(335.796875 0)"></use>
      <use xlink:href="#DejaVuSans-3" transform="translate(397.328125 0)"></use>
      <use xlink:href="#DejaVuSans-47" transform="translate(429.109375 0)"></use>
      <use xlink:href="#DejaVuSans-a" transform="translate(492.59375 0)"></use>
      <use xlink:href="#DejaVuSans-44" transform="translate(520.078125 0)"></use>
      <use xlink:href="#DejaVuSans-55" transform="translate(581.359375 0)"></use>
      <use xlink:href="#DejaVuSans-57" transform="translate(622.46875 0)"></use>
      <use xlink:href="#DejaVuSans-4c" transform="translate(661.671875 0)"></use>
      <use xlink:href="#DejaVuSans-46" transform="translate(689.453125 0)"></use>
      <use xlink:href="#DejaVuSans-4f" transform="translate(744.4375 0)"></use>
      <use xlink:href="#DejaVuSans-48" transform="translate(772.21875 0)"></use>
      <use xlink:href="#DejaVuSans-56" transform="translate(833.75 0)"></use>
      <use xlink:href="#DejaVuSans-3" transform="translate(885.84375 0)"></use>
      <use xlink:href="#DejaVuSans-53" transform="translate(917.625 0)"></use>
      <use xlink:href="#DejaVuSans-58" transform="translate(981.109375 0)"></use>
      <use xlink:href="#DejaVuSans-45" transform="translate(1044.484375 0)"></use>
      <use xlink:href="#DejaVuSans-4f" transform="translate(1107.96875 0)"></use>
      <use xlink:href="#DejaVuSans-4c" transform="translate(1135.75 0)"></use>
      <use xlink:href="#DejaVuSans-ab" transform="translate(1163.53125 0)"></use>
      <use xlink:href="#DejaVuSans-56" transform="translate(1225.0625 0)"></use>
     </g>
    </g>
   </g>
   <g id="line2d_39">
    <path d="M 75.26951 253.371114 
L 130.155267 305.063086 
L 185.041023 305.063086 
L 239.92678 305.063086 
L 294.812537 305.063086 
L 349.698294 305.063086 
L 404.58405 296.447757 
L 459.469807 244.755785 
L 514.355564 296.447757 
L 569.24132 287.832429 
L 624.127077 261.986443 
L 679.012834 270.601771 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke: #cccccc; stroke-linecap: square"></path>
   </g>
   <g id="line2d_40">
    <path d="M 75.26951 141.371841 
L 130.155267 279.2171 
L 185.041023 261.986443 
L 239.92678 287.832429 
L 294.812537 296.447757 
L 349.698294 279.2171 
L 404.58405 305.063086 
L 459.469807 287.832429 
L 514.355564 236.140457 
L 569.24132 201.679142 
L 624.127077 296.447757 
L 679.012834 175.833156 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke: #a2a2a2; stroke-linecap: square"></path>
   </g>
   <g id="line2d_41">
    <path d="M 75.26951 132.756513 
L 130.155267 305.063086 
L 185.041023 296.447757 
L 239.92678 296.447757 
L 294.812537 296.447757 
L 349.698294 296.447757 
L 404.58405 305.063086 
L 459.469807 296.447757 
L 514.355564 201.679142 
L 569.24132 55.218555 
L 624.127077 141.371841 
L 679.012834 253.371114 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke: #777777; stroke-linecap: square"></path>
   </g>
   <g id="line2d_42">
    <path d="M 75.26951 106.910527 
L 130.155267 218.909799 
L 185.041023 98.295198 
L 239.92678 184.448485 
L 294.812537 227.525128 
L 349.698294 227.525128 
L 404.58405 253.371114 
L 459.469807 261.986443 
L 514.355564 158.602499 
L 569.24132 210.294471 
L 624.127077 236.140457 
L 679.012834 253.371114 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke: #4c4c4c; stroke-linecap: square"></path>
   </g>
   <g id="line2d_43">
    <path d="M 75.26951 167.217827 
L 130.155267 236.140457 
L 185.041023 175.833156 
L 239.92678 115.525855 
L 294.812537 175.833156 
L 349.698294 193.063813 
L 404.58405 227.525128 
L 459.469807 210.294471 
" clip-path="url(#pf92dffec0e)" style="fill: none; stroke: #000000; stroke-width: 3; stroke-linecap: square"></path>
   </g>
   <g id="line2d_44"></g>
   <g id="line2d_45"></g>
   <g id="line2d_46"></g>
   <g id="line2d_47"></g>
   <g id="line2d_48"></g>
   <g id="patch_3">
    <path d="M 45.082344 317.555312 
L 45.082344 42.726328 
" style="fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square"></path>
   </g>
   <g id="patch_4">
    <path d="M 709.2 317.555312 
L 709.2 42.726328 
" style="fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square"></path>
   </g>
   <g id="patch_5">
    <path d="M 45.082344 317.555313 
L 709.2 317.555313 
" style="fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square"></path>
   </g>
   <g id="patch_6">
    <path d="M 45.082344 42.726328 
L 709.2 42.726328 
" style="fill: none; stroke: #000000; stroke-width: 0.8; stroke-linejoin: miter; stroke-linecap: square"></path>
   </g>
   <g id="text_22">
    
    <g transform="translate(196.952734 22.323047) scale(0.12 -0.12)">
     <defs>
      <path id="DejaVuSans-Bold-29" d="M 588 4666 
L 3834 4666 
L 3834 3756 
L 1791 3756 
L 1791 2888 
L 3713 2888 
L 3713 1978 
L 1791 1978 
L 1791 0 
L 588 0 
L 588 4666 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-55" d="M 3138 2547 
Q 2991 2616 2845 2648 
Q 2700 2681 2553 2681 
Q 2122 2681 1889 2404 
Q 1656 2128 1656 1613 
L 1656 0 
L 538 0 
L 538 3500 
L 1656 3500 
L 1656 2925 
Q 1872 3269 2151 3426 
Q 2431 3584 2822 3584 
Q 2878 3584 2943 3579 
Q 3009 3575 3134 3559 
L 3138 2547 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-ab" d="M 4031 1759 
L 4031 1441 
L 1416 1441 
Q 1456 1047 1700 850 
Q 1944 653 2381 653 
Q 2734 653 3104 758 
Q 3475 863 3866 1075 
L 3866 213 
Q 3469 63 3072 -14 
Q 2675 -91 2278 -91 
Q 1328 -91 801 392 
Q 275 875 275 1747 
Q 275 2603 792 3093 
Q 1309 3584 2216 3584 
Q 3041 3584 3536 3087 
Q 4031 2591 4031 1759 
z
M 2881 2131 
Q 2881 2450 2695 2645 
Q 2509 2841 2209 2841 
Q 1884 2841 1681 2658 
Q 1478 2475 1428 2131 
L 2881 2131 
z
M 2700 5119 
L 3584 5119 
L 2431 3944 
L 1819 3944 
L 2700 5119 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-54" d="M 2181 2772 
Q 1825 2772 1636 2509 
Q 1447 2247 1447 1747 
Q 1447 1247 1636 984 
Q 1825 722 2181 722 
Q 2541 722 2730 984 
Q 2919 1247 2919 1747 
Q 2919 2247 2730 2509 
Q 2541 2772 2181 2772 
z
M 2919 506 
Q 2688 197 2409 53 
Q 2131 -91 1766 -91 
Q 1119 -91 703 423 
Q 288 938 288 1747 
Q 288 2556 703 3067 
Q 1119 3578 1766 3578 
Q 2131 3578 2409 3434 
Q 2688 3291 2919 2981 
L 2919 3500 
L 4044 3500 
L 4044 -1331 
L 2919 -1331 
L 2919 506 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-58" d="M 500 1363 
L 500 3500 
L 1625 3500 
L 1625 3150 
Q 1625 2866 1622 2436 
Q 1619 2006 1619 1863 
Q 1619 1441 1641 1255 
Q 1663 1069 1716 984 
Q 1784 875 1895 815 
Q 2006 756 2150 756 
Q 2500 756 2700 1025 
Q 2900 1294 2900 1772 
L 2900 3500 
L 4019 3500 
L 4019 0 
L 2900 0 
L 2900 506 
Q 2647 200 2364 54 
Q 2081 -91 1741 -91 
Q 1134 -91 817 281 
Q 500 653 500 1363 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-48" d="M 4031 1759 
L 4031 1441 
L 1416 1441 
Q 1456 1047 1700 850 
Q 1944 653 2381 653 
Q 2734 653 3104 758 
Q 3475 863 3866 1075 
L 3866 213 
Q 3469 63 3072 -14 
Q 2675 -91 2278 -91 
Q 1328 -91 801 392 
Q 275 875 275 1747 
Q 275 2603 792 3093 
Q 1309 3584 2216 3584 
Q 3041 3584 3536 3087 
Q 4031 2591 4031 1759 
z
M 2881 2131 
Q 2881 2450 2695 2645 
Q 2509 2841 2209 2841 
Q 1884 2841 1681 2658 
Q 1478 2475 1428 2131 
L 2881 2131 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-51" d="M 4056 2131 
L 4056 0 
L 2931 0 
L 2931 347 
L 2931 1631 
Q 2931 2084 2911 2256 
Q 2891 2428 2841 2509 
Q 2775 2619 2662 2680 
Q 2550 2741 2406 2741 
Q 2056 2741 1856 2470 
Q 1656 2200 1656 1722 
L 1656 0 
L 538 0 
L 538 3500 
L 1656 3500 
L 1656 2988 
Q 1909 3294 2193 3439 
Q 2478 3584 2822 3584 
Q 3428 3584 3742 3212 
Q 4056 2841 4056 2131 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-46" d="M 3366 3391 
L 3366 2478 
Q 3138 2634 2908 2709 
Q 2678 2784 2431 2784 
Q 1963 2784 1702 2511 
Q 1441 2238 1441 1747 
Q 1441 1256 1702 982 
Q 1963 709 2431 709 
Q 2694 709 2930 787 
Q 3166 866 3366 1019 
L 3366 103 
Q 3103 6 2833 -42 
Q 2563 -91 2291 -91 
Q 1344 -91 809 395 
Q 275 881 275 1747 
Q 275 2613 809 3098 
Q 1344 3584 2291 3584 
Q 2566 3584 2833 3536 
Q 3100 3488 3366 3391 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-3" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-50" d="M 3781 2919 
Q 3994 3244 4286 3414 
Q 4578 3584 4928 3584 
Q 5531 3584 5847 3212 
Q 6163 2841 6163 2131 
L 6163 0 
L 5038 0 
L 5038 1825 
Q 5041 1866 5042 1909 
Q 5044 1953 5044 2034 
Q 5044 2406 4934 2573 
Q 4825 2741 4581 2741 
Q 4263 2741 4089 2478 
Q 3916 2216 3909 1719 
L 3909 0 
L 2784 0 
L 2784 1825 
Q 2784 2406 2684 2573 
Q 2584 2741 2328 2741 
Q 2006 2741 1831 2477 
Q 1656 2213 1656 1722 
L 1656 0 
L 531 0 
L 531 3500 
L 1656 3500 
L 1656 2988 
Q 1863 3284 2130 3434 
Q 2397 3584 2719 3584 
Q 3081 3584 3359 3409 
Q 3638 3234 3781 2919 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-56" d="M 3272 3391 
L 3272 2541 
Q 2913 2691 2578 2766 
Q 2244 2841 1947 2841 
Q 1628 2841 1473 2761 
Q 1319 2681 1319 2516 
Q 1319 2381 1436 2309 
Q 1553 2238 1856 2203 
L 2053 2175 
Q 2913 2066 3209 1816 
Q 3506 1566 3506 1031 
Q 3506 472 3093 190 
Q 2681 -91 1863 -91 
Q 1516 -91 1145 -36 
Q 775 19 384 128 
L 384 978 
Q 719 816 1070 734 
Q 1422 653 1784 653 
Q 2113 653 2278 743 
Q 2444 834 2444 1013 
Q 2444 1163 2330 1236 
Q 2216 1309 1875 1350 
L 1678 1375 
Q 931 1469 631 1722 
Q 331 1975 331 2491 
Q 331 3047 712 3315 
Q 1094 3584 1881 3584 
Q 2191 3584 2531 3537 
Q 2872 3491 3272 3391 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-4f" d="M 538 4863 
L 1656 4863 
L 1656 0 
L 538 0 
L 538 4863 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-47" d="M 2919 2988 
L 2919 4863 
L 4044 4863 
L 4044 0 
L 2919 0 
L 2919 506 
Q 2688 197 2409 53 
Q 2131 -91 1766 -91 
Q 1119 -91 703 423 
Q 288 938 288 1747 
Q 288 2556 703 3070 
Q 1119 3584 1766 3584 
Q 2128 3584 2408 3439 
Q 2688 3294 2919 2988 
z
M 2181 722 
Q 2541 722 2730 984 
Q 2919 1247 2919 1747 
Q 2919 2247 2730 2509 
Q 2541 2772 2181 2772 
Q 1825 2772 1636 2509 
Q 1447 2247 1447 1747 
Q 1447 1247 1636 984 
Q 1825 722 2181 722 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-44" d="M 2106 1575 
Q 1756 1575 1579 1456 
Q 1403 1338 1403 1106 
Q 1403 894 1545 773 
Q 1688 653 1941 653 
Q 2256 653 2472 879 
Q 2688 1106 2688 1447 
L 2688 1575 
L 2106 1575 
z
M 3816 1997 
L 3816 0 
L 2688 0 
L 2688 519 
Q 2463 200 2181 54 
Q 1900 -91 1497 -91 
Q 953 -91 614 226 
Q 275 544 275 1050 
Q 275 1666 698 1953 
Q 1122 2241 2028 2241 
L 2688 2241 
L 2688 2328 
Q 2688 2594 2478 2717 
Q 2269 2841 1825 2841 
Q 1466 2841 1156 2769 
Q 847 2697 581 2553 
L 581 3406 
Q 941 3494 1303 3539 
Q 1666 3584 2028 3584 
Q 2975 3584 3395 3211 
Q 3816 2838 3816 1997 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-57" d="M 1759 4494 
L 1759 3500 
L 2913 3500 
L 2913 2700 
L 1759 2700 
L 1759 1216 
Q 1759 972 1856 886 
Q 1953 800 2241 800 
L 2816 800 
L 2816 0 
L 1856 0 
Q 1194 0 917 276 
Q 641 553 641 1216 
L 641 2700 
L 84 2700 
L 84 3500 
L 641 3500 
L 641 4494 
L 1759 4494 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-4c" d="M 538 3500 
L 1656 3500 
L 1656 0 
L 538 0 
L 538 3500 
z
M 538 4863 
L 1656 4863 
L 1656 3950 
L 538 3950 
L 538 4863 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-4b" d="M 4056 2131 
L 4056 0 
L 2931 0 
L 2931 347 
L 2931 1625 
Q 2931 2084 2911 2256 
Q 2891 2428 2841 2509 
Q 2775 2619 2662 2680 
Q 2550 2741 2406 2741 
Q 2056 2741 1856 2470 
Q 1656 2200 1656 1722 
L 1656 0 
L 538 0 
L 538 4863 
L 1656 4863 
L 1656 2988 
Q 1909 3294 2193 3439 
Q 2478 3584 2822 3584 
Q 3428 3584 3742 3212 
Q 4056 2841 4056 2131 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-11" d="M 653 1209 
L 1778 1209 
L 1778 0 
L 653 0 
L 653 1209 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-52" d="M 2203 2784 
Q 1831 2784 1636 2517 
Q 1441 2250 1441 1747 
Q 1441 1244 1636 976 
Q 1831 709 2203 709 
Q 2569 709 2762 976 
Q 2956 1244 2956 1747 
Q 2956 2250 2762 2517 
Q 2569 2784 2203 2784 
z
M 2203 3584 
Q 3106 3584 3614 3096 
Q 4122 2609 4122 1747 
Q 4122 884 3614 396 
Q 3106 -91 2203 -91 
Q 1297 -91 786 396 
Q 275 884 275 1747 
Q 275 2609 786 3096 
Q 1297 3584 2203 3584 
z
" transform="scale(0.015625)"></path>
     </defs>
     <use xlink:href="#DejaVuSans-Bold-29"></use>
     <use xlink:href="#DejaVuSans-Bold-55" transform="translate(61.921875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-ab" transform="translate(111.234375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-54" transform="translate(179.0625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-58" transform="translate(250.640625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-48" transform="translate(321.828125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-51" transform="translate(389.65625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-46" transform="translate(460.84375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-48" transform="translate(520.125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-3" transform="translate(587.953125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-50" transform="translate(622.765625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-48" transform="translate(726.96875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-51" transform="translate(794.796875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-56" transform="translate(865.984375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-58" transform="translate(925.5 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-48" transform="translate(996.6875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-4f" transform="translate(1064.515625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-4f" transform="translate(1098.796875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-48" transform="translate(1133.078125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-3" transform="translate(1200.90625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-47" transform="translate(1235.71875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-48" transform="translate(1307.296875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-56" transform="translate(1375.125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-3" transform="translate(1434.640625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-44" transform="translate(1469.453125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-55" transform="translate(1536.9375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-57" transform="translate(1586.25 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-4c" transform="translate(1634.046875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-46" transform="translate(1668.328125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-4f" transform="translate(1727.609375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-48" transform="translate(1761.890625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-56" transform="translate(1829.71875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-3" transform="translate(1889.234375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-56" transform="translate(1924.046875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-58" transform="translate(1983.5625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-55" transform="translate(2054.75 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-3" transform="translate(2104.0625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-56" transform="translate(2138.875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-44" transform="translate(2198.390625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-46" transform="translate(2265.875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-4b" transform="translate(2325.15625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-44" transform="translate(2396.34375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-46" transform="translate(2463.828125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-4b" transform="translate(2523.109375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-58" transform="translate(2594.296875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-44" transform="translate(2665.484375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-11" transform="translate(2732.96875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-46" transform="translate(2770.953125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-52" transform="translate(2830.234375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-50" transform="translate(2898.9375 0)"></use>
    </g>
    
    <g transform="translate(312.823047 36.726328) scale(0.12 -0.12)">
     <defs>
      <path id="DejaVuSans-Bold-b" d="M 2413 -844 
L 1484 -844 
Q 1006 -72 778 623 
Q 550 1319 550 2003 
Q 550 2688 779 3389 
Q 1009 4091 1484 4856 
L 2413 4856 
Q 2013 4116 1813 3408 
Q 1613 2700 1613 2009 
Q 1613 1319 1811 609 
Q 2009 -100 2413 -844 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-28" d="M 588 4666 
L 3834 4666 
L 3834 3756 
L 1791 3756 
L 1791 2888 
L 3713 2888 
L 3713 1978 
L 1791 1978 
L 1791 909 
L 3903 909 
L 3903 0 
L 588 0 
L 588 4666 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-31" d="M 588 4666 
L 1931 4666 
L 3628 1466 
L 3628 4666 
L 4769 4666 
L 4769 0 
L 3425 0 
L 1728 3200 
L 1728 0 
L 588 0 
L 588 4666 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-5a" d="M 225 3500 
L 1313 3500 
L 1900 1088 
L 2491 3500 
L 3425 3500 
L 4013 1113 
L 4603 3500 
L 5691 3500 
L 4769 0 
L 3547 0 
L 2956 2406 
L 2369 0 
L 1147 0 
L 225 3500 
z
" transform="scale(0.015625)"></path>
      <path id="DejaVuSans-Bold-c" d="M 513 -844 
Q 913 -100 1113 609 
Q 1313 1319 1313 2009 
Q 1313 2700 1113 3408 
Q 913 4116 513 4856 
L 1441 4856 
Q 1916 4091 2145 3389 
Q 2375 2688 2375 2003 
Q 2375 1319 2147 623 
Q 1919 -72 1441 -844 
L 513 -844 
z
" transform="scale(0.015625)"></path>
     </defs>
     <use xlink:href="#DejaVuSans-Bold-b"></use>
     <use xlink:href="#DejaVuSans-Bold-4b" transform="translate(45.703125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-52" transform="translate(116.890625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-55" transform="translate(185.59375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-56" transform="translate(234.90625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-3" transform="translate(294.421875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-28" transform="translate(329.234375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-50" transform="translate(397.546875 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-44" transform="translate(501.75 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-46" transform="translate(569.234375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-56" transform="translate(628.515625 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-3" transform="translate(688.03125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-31" transform="translate(722.84375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-48" transform="translate(806.53125 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-5a" transform="translate(874.359375 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-56" transform="translate(966.75 0)"></use>
     <use xlink:href="#DejaVuSans-Bold-c" transform="translate(1026.265625 0)"></use>
    </g>
   </g>
   <g id="legend_1">
    <g id="patch_7">
     <path d="M 644.75 125.730234 
L 702.2 125.730234 
Q 704.2 125.730234 704.2 123.730234 
L 704.2 49.726328 
Q 704.2 47.726328 702.2 47.726328 
L 644.75 47.726328 
Q 642.75 47.726328 642.75 49.726328 
L 642.75 123.730234 
Q 642.75 125.730234 644.75 125.730234 
z
" style="fill: #ffffff; opacity: 0.8; stroke: #cccccc; stroke-linejoin: miter"></path>
    </g>
    <g id="line2d_49">
     <path d="M 646.75 55.824766 
L 656.75 55.824766 
L 666.75 55.824766 
" style="fill: none; stroke: #cccccc; stroke-linecap: square"></path>
    </g>
    <g id="text_23">
     
     <g transform="translate(674.75 59.324766) scale(0.1 -0.1)">
      <use xlink:href="#DejaVuSans-15"></use>
      <use xlink:href="#DejaVuSans-13" transform="translate(63.625 0)"></use>
      <use xlink:href="#DejaVuSans-15" transform="translate(127.25 0)"></use>
      <use xlink:href="#DejaVuSans-15" transform="translate(190.875 0)"></use>
     </g>
    </g>
    <g id="line2d_50">
     <path d="M 646.75 70.825547 
L 656.75 70.825547 
L 666.75 70.825547 
" style="fill: none; stroke: #a2a2a2; stroke-linecap: square"></path>
    </g>
    <g id="text_24">
     
     <g transform="translate(674.75 74.325547) scale(0.1 -0.1)">
      <use xlink:href="#DejaVuSans-15"></use>
      <use xlink:href="#DejaVuSans-13" transform="translate(63.625 0)"></use>
      <use xlink:href="#DejaVuSans-15" transform="translate(127.25 0)"></use>
      <use xlink:href="#DejaVuSans-16" transform="translate(190.875 0)"></use>
     </g>
    </g>
    <g id="line2d_51">
     <path d="M 646.75 85.826328 
L 656.75 85.826328 
L 666.75 85.826328 
" style="fill: none; stroke: #777777; stroke-linecap: square"></path>
    </g>
    <g id="text_25">
     
     <g transform="translate(674.75 89.326328) scale(0.1 -0.1)">
      <defs>
       <path id="DejaVuSans-17" d="M 2419 4116 
L 825 1625 
L 2419 1625 
L 2419 4116 
z
M 2253 4666 
L 3047 4666 
L 3047 1625 
L 3713 1625 
L 3713 1100 
L 3047 1100 
L 3047 0 
L 2419 0 
L 2419 1100 
L 313 1100 
L 313 1709 
L 2253 4666 
z
" transform="scale(0.015625)"></path>
      </defs>
      <use xlink:href="#DejaVuSans-15"></use>
      <use xlink:href="#DejaVuSans-13" transform="translate(63.625 0)"></use>
      <use xlink:href="#DejaVuSans-15" transform="translate(127.25 0)"></use>
      <use xlink:href="#DejaVuSans-17" transform="translate(190.875 0)"></use>
     </g>
    </g>
    <g id="line2d_52">
     <path d="M 646.75 100.827109 
L 656.75 100.827109 
L 666.75 100.827109 
" style="fill: none; stroke: #4c4c4c; stroke-linecap: square"></path>
    </g>
    <g id="text_26">
     
     <g transform="translate(674.75 104.327109) scale(0.1 -0.1)">
      <use xlink:href="#DejaVuSans-15"></use>
      <use xlink:href="#DejaVuSans-13" transform="translate(63.625 0)"></use>
      <use xlink:href="#DejaVuSans-15" transform="translate(127.25 0)"></use>
      <use xlink:href="#DejaVuSans-18" transform="translate(190.875 0)"></use>
     </g>
    </g>
    <g id="line2d_53">
     <path d="M 646.75 115.827891 
L 656.75 115.827891 
L 666.75 115.827891 
" style="fill: none; stroke: #000000; stroke-width: 3; stroke-linecap: square"></path>
    </g>
    <g id="text_27">
     
     <g transform="translate(674.75 119.327891) scale(0.1 -0.1)">
      <defs>
       <path id="DejaVuSans-19" d="M 2113 2584 
Q 1688 2584 1439 2293 
Q 1191 2003 1191 1497 
Q 1191 994 1439 701 
Q 1688 409 2113 409 
Q 2538 409 2786 701 
Q 3034 994 3034 1497 
Q 3034 2003 2786 2293 
Q 2538 2584 2113 2584 
z
M 3366 4563 
L 3366 3988 
Q 3128 4100 2886 4159 
Q 2644 4219 2406 4219 
Q 1781 4219 1451 3797 
Q 1122 3375 1075 2522 
Q 1259 2794 1537 2939 
Q 1816 3084 2150 3084 
Q 2853 3084 3261 2657 
Q 3669 2231 3669 1497 
Q 3669 778 3244 343 
Q 2819 -91 2113 -91 
Q 1303 -91 875 529 
Q 447 1150 447 2328 
Q 447 3434 972 4092 
Q 1497 4750 2381 4750 
Q 2619 4750 2861 4703 
Q 3103 4656 3366 4563 
z
" transform="scale(0.015625)"></path>
      </defs>
      <use xlink:href="#DejaVuSans-15"></use>
      <use xlink:href="#DejaVuSans-13" transform="translate(63.625 0)"></use>
      <use xlink:href="#DejaVuSans-15" transform="translate(127.25 0)"></use>
      <use xlink:href="#DejaVuSans-19" transform="translate(190.875 0)"></use>
     </g>
    </g>
   </g>
  </g>
 </g>
 <defs>
  <clipPath id="pf92dffec0e">
   <rect x="45.082344" y="42.726328" width="664.117656" height="274.828984"></rect>
  </clipPath>
 </defs>
</svg>


</figure>

<p>
et la croissance graduelle de mon vocabulaire français selon mon journal:
</p>


<figure id="org5dcb994">
<img src="https://sachachua.com/blog/2026/08/carnaval-d-emacs-d-aout-la-gestion-d-information-et-les-graphes-de-connaissances/01_cumulative_vocab.png" alt="01_cumulative_vocab.png">

</figure>

<p>
Bien qu'ils ne soient pas des graphes de connaissances classiques, ils m'aident à voir des tendances qui ne sont pas évidentes au jour le jour.
</p>
</div>
</div>
<div id="outline-container-carnaval-d-emacs-d-ao-t-2026-la-gestion-d-information-et-les-graphes-de-connaissances-savoir-collectif" class="outline-3">
<h3 id="carnaval-d-emacs-d-ao-t-2026-la-gestion-d-information-et-les-graphes-de-connaissances-savoir-collectif"><a href="https://sachachua.com/blog/feed/atom/index.xml#carnaval-d-emacs-d-ao-t-2026-la-gestion-d-information-et-les-graphes-de-connaissances-savoir-collectif">Savoir collectif</a></h3>
<div class="outline-text-3" id="text-carnaval-d-emacs-d-ao-t-2026-la-gestion-d-information-et-les-graphes-de-connaissances-savoir-collectif">
<p>
Je suis plus intéressée par le réseau de savoir collectif plutôt que par mes notes personnelles. Depuis plus de dix ans, je rassemble et catégorise de nombreux liens pour <a href="https://sachachua.com/blog/category/emacs-news">Emacs News</a>, ce qui permet de les parcourir. J'adore rencontrer beaucoup d'idées et de nombreuses personnes en chemin. C'est facile à faire et cela ne demande pas trop de temps, donc j'ai pu  continuer ainsi malgré les interruptions de ma vie de maman. En parlant de graphes de connaissances, le bulletin d'information sert à connecter des nœuds et des personnes. De temps en temps, je suis très contente d'entendre qu'un article en inspire un autre, et encore un autre, puis une collaboration… C'est le pouvoir de créer des liens entre les personnes qui apprécient des choses similaires. Si je deviens incapable de faire ce bulletin hebdomadaire, j'espère que quelqu'un le continuera.
</p>

<p>
Grâce à mon assemblage de liens pour Emacs News, je rencontre souvent des occasions de recommander un article ou une personne en réponse à une question ou un message. Si je peux trouver l'article dans mon fichier d'archive d'Emacs News avec <a href="https://github.com/minad/consult">consult-line</a> ou <a href="https://emacsredux.com/blog/2025/03/18/you-have-no-idea-how-powerful-isearch-is/">isearch</a>, je peux coller le lien exact. De temps en temps, je veux présenter une personne, ce qui est un peu difficile sur Mastodon parce que les noms de Mastodon sont souvent très différents de leurs vrais noms. Je note les noms de Mastodon dans mon fichier people.org, et j'ai une petite fonction <a href="https://sachachua.com/dotemacs#mastodon-mastodon-el-mention-people-based-on-regexp">sacha-mastodon-insert-handle-from-contacts</a> pour compléter les noms de Mastodon. J'ai aussi une autre fonction <a href="https://sachachua.com/dotemacs#mastodon-mastodon-el-mention-people-based-on-regexp">sacha-mastodon-insert-interested-handles</a> qui ajoute des personnes qui peuvent être intéressées sur la base des correspondances d'expressions régulières dans le message, comme quand j'écris mes articles.
</p>

<p>
En plus des connexions entre des articles et des personnes, je suis également intéressée par les connexions entre des sujets. Avant d'apprendre une chose, quels sujets doivent la précéder ? Quand on apprend une chose, qu'est-ce qui est proche et plus facile à apprendre par la suite ? C'est peut-être utile pour donner des conseils ou des suggestions en tant que coach, ou pour apprendre en mode autodidacte. Les besoins et les chemins diffèrent selon la personne, donc c'est impossible de tracer un parcours qui convient à tout le monde. J'ai commencé à faire <a href="https://sachachua.com/web/beginner-map.html">une carte des ressources pour les débutants</a>, mais je pense que c'est toujours un peu intimidant, même pour moi. La place naturelle de ces liens est peut-être <a href="https://emacswiki.org">EmacsWiki</a> pour permettre aux autres personnes de les trouver et de les enrichir, si je trouve une façon de sauvegarder les données et si je résous le problème de l'édition de quelques pages. En plus, si j'étudie les flux de travail et que je les classifie par aspect, je pourrais aider quelqu'un à trouver des ressources qui sont similaires à ses idées.
</p>

<p>
Je veux aussi identifier des lacunes sur lesquelles me focaliser quand j'ai du temps libre. Il y a beaucoup de ressources pour les débutants, mais grâce à l'immense capacité de personnaliser Emacs, il y a une explosion combinatoire de possibilités au niveau intermédiaire. J'ai hâte d'explorer mes questions et d'autres. C'est difficile de trouver et de naviguer dans les informations, donc si je commence avec des améliorations personnelles ou des questions concrètes de personnes spécifiques, c'est mieux que d'écrire isolément. Je suis sûre qu'en répondant aux questions individuelles, les points communs émergeront.
</p>

<p>
Je suis aussi fascinée par mes études sur d'autres sujets. J'apprends le français et je m'amuse tellement à bricoler mon environnement Emacs et mon <a href="https://sachachua.com/topic/french/#mon-apprentissage">processus d'apprentissage</a>. Un des conseils pour les débutants est de développer des îlots linguistiques : les mots autour d'un sujet passionnant. (Comme cet article-ci que j'écris en français pour me forcer à enrichir mon vocabulaire.) Je me demande comment visualiser ces choses… Par exemple, si je récupère des listes de mots triés par fréquence (peut-être en analysant la base de données <a href="https://lexique.org/databases/Lexique383/">lexique</a>), je peux créer une matrice de carrés… Hmm…
</p>

<p>
Mes obligations de maman diminuent au fur et à mesure que ma fille grandit. J'espère pouvoir consacrer plus de temps à explorer, à saisir et à partager des choses intéressantes.
</p>
</div>
</div>
<div><a href="https://sachachua.com/blog/2026/08/carnaval-d-emacs-d-aout-la-gestion-d-information-et-les-graphes-de-connaissances/index.org">View Org source for this post</a></div><p>You can <a href="https://social.sachachua.com/@sacha/statuses/01M170Q8N30823KE54NGBXBN1K" target="_blank" rel="noopener noreferrer">comment on Mastodon</a> or <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F08%2Fcarnaval-d-emacs-d-aout-la-gestion-d-information-et-les-graphes-de-connaissances%2F&body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p>]]></content>
		</entry><entry>
		<title type="html">From DC Toedt: Copy Org Mode as Markdown</title>
		<link rel="alternate" type="text/html" href="https://sachachua.com/blog/2026/06/from-dc-toedt-copy-org-mode-as-markdown/"/>
		<author><name><![CDATA[Sacha Chua]]></name></author>
		<updated>2026-06-10T17:25:51Z</updated>
    <published>2026-06-09T15:49:08Z</published>
    <category term="emacs" />
<category term="org" />
		<id>https://sachachua.com/blog/2026/06/from-dc-toedt-copy-org-mode-as-markdown/</id>
		<content type="html"><![CDATA[<div class="update" id="org6a372d6">
<p>
<span class="timestamp-wrapper"><time class="timestamp" datetime="2026-06-10">[2026-06-10 Wed]</time></span>: Add embark way to do things.
</p>

</div>

<p>
DC Toedt is a lawyer and professor of practice who uses Emacs and Org Mode. He wanted a small Emacs Lisp function to convert Org Mode syntax to Markdown and copy it to the clipboard to make it easier to copy the materials he's writing for a course on contract drafting. This seems to be a common need, and here are several other approaches:
</p>

<ul class="org-ul">
<li><code>embark-org-copy-as-markdown</code> in <a target="_blank" href="https://melpa.org/#/embark">embark</a></li>
<li><a href="https://mbork.pl/2021-05-02_Org-mode_to_Markdown_via_the_clipboard">Marcin Borkowski: 2021-05-02 Org-mode to Markdown via the clipboard</a></li>
<li><a href="https://mmk2410.org/2026/04/14/copy-an-org-mode-region-as-markdown">Marcel Kapfer - Copy an Org Mode region as Markdown</a></li>
<li><a href="https://www.reddit.com/r/emacs/comments/17um2fk/does_anyone_have_a_function_they_use_to_quickly/">Reddit</a></li>
<li><a href="https://www.reddit.com/r/emacs/comments/e98yyf/send_output_of_orgmdexportasmarkdownstraight_to/">Reddit</a></li>
</ul>

<p>
Anyway, DC shared how he used Claude to generate a simple function to do it, which is here under public domain:
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">defun</span> <span class="org-function-name">my/org-to-markdown-clipboard</span> ()
  <span class="org-doc">"Export org region (or buffer) to Markdown and copy to clipboard.</span>
<span class="org-doc">With no active region, exports the whole buffer."</span>
  (<span class="org-keyword">interactive</span>)
  (<span class="org-keyword">require</span> <span class="org-highlight-quoted-quote">'</span><span class="org-constant">ox-md</span>)
  (<span class="org-keyword">let*</span> ((text (<span class="org-keyword">if</span> (use-region-p)
                   (buffer-substring-no-properties (region-beginning)
(region-end))
                 (buffer-substring-no-properties (point-min) (point-max))))
         (md (org-export-string-as text <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">md</span> t <span class="org-highlight-quoted-quote">'</span>(<span class="org-builtin">:with-toc</span> nil
                                                <span class="org-builtin">:with-author</span> nil
                                                <span class="org-builtin">:with-date</span> nil
                                                <span class="org-builtin">:with-title</span> nil))))
    (kill-new md)
    (message <span class="org-string">"Markdown copied (%d chars)"</span> (length md))))
(<span class="org-keyword">with-eval-after-load</span> <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">org</span>
  (define-key org-mode-map (kbd <span class="org-string">"C-c m"</span>) <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">my/org-to-markdown-clipboard</span>))
</code></pre>
</div>

<div><a href="https://sachachua.com/blog/2026/06/from-dc-toedt-copy-org-mode-as-markdown/index.org">View Org source for this post</a></div><p>You can <a href="https://sachachua.com/blog/2026/06/from-dc-toedt-copy-org-mode-as-markdown/#comment">view 1 comment</a> or <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F06%2Ffrom-dc-toedt-copy-org-mode-as-markdown%2F&body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p>]]></content>
		</entry><entry>
		<title type="html">Create a Google Calendar event from an Org Mode timestamp</title>
		<link rel="alternate" type="text/html" href="https://sachachua.com/blog/2026/04/create-a-google-calendar-event-from-an-org-mode-timestamp/"/>
		<author><name><![CDATA[Sacha Chua]]></name></author>
		<updated>2026-04-17T13:26:41Z</updated>
    <published>2026-04-17T13:26:41Z</published>
    <category term="org" />
<category term="emacs" />
		<id>https://sachachua.com/blog/2026/04/create-a-google-calendar-event-from-an-org-mode-timestamp/</id>
		<content type="html"><![CDATA[<p>
Time zones are hard, so I let calendaring systems take care of the conversion and confirmation. I've been using Google Calendar because it synchronizes with my phone and people know what to do with the event invite.
<a href="https://orgmode.org/manual/iCalendar-Export.html">Org Mode has iCalendar export</a>, but I sometimes have a hard time getting .ics files into Google Calendar on my laptop, so I might as well just create the calendar entry in Google Calendar directly. Well. Emacs is a lot more fun than Google Calendar, so I'd rather create the calendar entry from Emacs and put it into Google Calendar.
</p>

<p>
This function lets me start from a timestamp like <code>[2026-04-24 Fri 10:30]</code> (inserted with <code>C-u C-c C-!</code>, or <code>org-timestamp-inactive</code>) and create an event based on a template.
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-time-zone</span> <span class="org-string">"America/Toronto"</span> <span class="org-doc">"Full name of time zone."</span>)

<span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-emacs-chat-schedule</span> (<span class="org-type">&amp;optional</span> time)
  <span class="org-doc">"Create a Google Calendar invite based on TIME or the Org timestamp at point."</span>
  (<span class="org-keyword">interactive</span> (list (sacha-org-time-at-point)))
  (browse-url
   (format
    <span class="org-string">"https://calendar.google.com/calendar/render?action=TEMPLATE&amp;text=%s&amp;details=%s&amp;dates=%s&amp;ctz=%s"</span>
    (url-hexify-string sacha-emacs-chat-title)
    (url-hexify-string sacha-emacs-chat-description)
    (format-time-string
     <span class="org-string">"%Y%m%dT%H%M%S"</span> time)
    sacha-time-zone)))

(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-emacs-chat-title</span> <span class="org-string">"Emacs Chat"</span> <span class="org-doc">"Title of calendar entry."</span>)
(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-emacs-chat-description</span>
  <span class="org-string">"All right, let's try this! =) See the calendar invite for the Google Meet link.</span>

<span class="org-string">Objective: Share cool stuff about Emacs workflows that's not obvious from reading configs, and have fun chatting about Emacs</span>

<span class="org-string">Some ideas for things to talk about:</span>
<span class="org-string">- Which keyboard shortcuts or combinations of functions work really well for you?</span>
<span class="org-string">- What's something you love about your setup?</span>
<span class="org-string">- What are you looking forward to tweaking next?</span>

<span class="org-string">Let me know if you want to do it on stream (more people can ask questions) or off stream (we can clean up the video in case there are hiccups). Also, please feel free to send me links to things you'd like me to read ahead of time, like your config!"</span>
  <span class="org-doc">"Description."</span>)
</code></pre>
</div>


<p>
It uses this function to convert the timestamp at point:
</p>

<p>
</p><details open=""><summary>sacha-org-time-at-point: Return Emacs time object for timestamp at point.</summary><div class="org-src-container"><pre class="src src-emacs-lisp">(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-org-time-at-point</span> ()
  <span class="org-doc">"Return Emacs time object for timestamp at point."</span>
  (org-timestamp-to-time (org-timestamp-from-string (org-element-property <span class="org-builtin">:raw-value</span> (org-element-context)))))

</pre></div></details>
<p></p>

<div class="note">This is part of my <a href="https://sachachua.com/dotemacs#streaming">Emacs configuration.</a></div><div><a href="https://sachachua.com/blog/2026/04/create-a-google-calendar-event-from-an-org-mode-timestamp/index.org">View Org source for this post</a></div><p>You can <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F04%2Fcreate-a-google-calendar-event-from-an-org-mode-timestamp%2F&body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p>]]></content>
		</entry><entry>
		<title type="html">Make chapter markers and video time hyperlinks easier to note while I livestream</title>
		<link rel="alternate" type="text/html" href="https://sachachua.com/blog/2026/04/make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream/"/>
		<author><name><![CDATA[Sacha Chua]]></name></author>
		<updated>2026-04-17T04:27:43Z</updated>
    <published>2026-04-17T04:27:43Z</published>
    <category term="org" />
<category term="emacs" />
		<id>https://sachachua.com/blog/2026/04/make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream/</id>
		<content type="html"><![CDATA[<p>
I want to make it easier to add chapter markers to my YouTube video descriptions and hyperlinks to specific times in videos in my blog posts.
</p>
<div id="outline-container-streaming-make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream-capture-timestamps" class="outline-3">
<h3 id="streaming-make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream-capture-timestamps"><a href="https://sachachua.com/blog/feed/atom/index.xml#streaming-make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream-capture-timestamps">Capture timestamps</a></h3>
<div class="outline-text-3" id="text-streaming-make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream-capture-timestamps">
<p>
Using wall-clock time via Org Mode timestamps like <span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T10:40:00-0400">[2026-04-16 Thu 10:40]</time></span> makes more sense to me than using video offsets because they're independent of any editing I might do.
</p>

<p>
<code>C-u C-c C-!</code> (<code>org-timestamp-inactive</code>) creates a timestamp with a time. I probably do often enough that I should create a Yasnippet for it:
</p>


<div class="org-src-container">
<pre class="src src-yasnippet"><code># -*- mode: snippet -*-
# name: insert time
# key: zt
# &#45;&#45;
`(format-time-string "[%Y-%m-%d %a %H:%M]")`
</code></pre>
</div>


<p>
I also have <a href="https://orgmode.org/manual/Capture.html">Org capture</a> templates, like this:
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">with-eval-after-load</span> <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">org-capture</span>
  (add-to-list
   <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">org-capture-templates</span>
   <span class="org-highlight-quoted-quote">`</span>(<span class="org-string">"l"</span> <span class="org-string">"Timestamp"</span> item
     (file+headline ,sacha-stream-inbox-file <span class="org-string">"Timestamps"</span>)
     <span class="org-string">"- %U %i%?"</span>)))
</code></pre>
</div>


<p>
I've been experimenting with a <a href="https://sachachua.com/dotemacs#streaming-display-large-text-and-maybe-qr-code">custom Org Mode link type "stream:"</a> which:
</p>

<ul class="org-ul">
<li>displays the text in a larger font with a QR code for easier copying</li>
<li>sends the text to the YouTube chat via <a href="https://socialstream.ninja">socialstream.ninja</a></li>
<li>adds a timestamped note using the org-capture template above</li>
</ul>

<p>
Here is an example of that link in action. It's the <code>(Log)</code> link that I clicked on.
</p>

<details><summary>Let's extract that clip</summary>
<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(compile-media-sync
 <span class="org-highlight-quoted-quote">'</span>((combined (<span class="org-builtin">:source</span>
              <span class="org-string">"/home/sacha/proj/yay-emacs/ye16-sacha-and-prot-talk-emacs.mp4"</span>
              <span class="org-builtin">:original-start-ms</span> <span class="org-string">"51:09"</span>
              <span class="org-builtin">:original-stop-ms</span> <span class="org-string">"51:16"</span>))
   (combined (<span class="org-builtin">:source</span>
              <span class="org-string">"/home/sacha/proj/yay-emacs/ye16-sacha-and-prot-talk-emacs-link-overlay.png"</span>
              <span class="org-builtin">:output-start-ms</span> <span class="org-string">"0:03"</span>
              <span class="org-builtin">:output-stop-ms</span> <span class="org-string">"0:04"</span>))
   (combined (<span class="org-builtin">:source</span>
              <span class="org-string">"/home/sacha/proj/yay-emacs/ye16-sacha-and-prot-talk-emacs-qr-chat-overlay.png"</span>
              <span class="org-builtin">:output-start-ms</span> <span class="org-string">"0:05"</span>
              <span class="org-builtin">:output-stop-ms</span> <span class="org-string">"0:06"</span>)))
 <span class="org-string">"/home/sacha/proj/yay-emacs/ye16.1-stream-show-string-and-calculate-offset.mp4"</span>)
</code></pre>
</div>

</details>

<div class="media-post" id="orgc803fb4">
<p>
<video controls="1" src="https://sachachua.com/blog/2026/04/make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream/ye16.1-stream-show-string-and-calculate-offset.mp4" type="video/mp4"> <a href="https://sachachua.com/blog/2026/04/make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream/ye16.1-stream-show-string-and-calculate-offset.mp4">Download the video</a></video>
</p>

</div>

<p>
I used it in <a href="https://sachachua.com/blog/2026/04/ye16-sacha-and-prot-talk-emacs/">YE16: Sacha and Prot talk Emacs</a>. It was handy to have a link that I could click on instead of trying to remember a keyboard shortcut and type text.
For example, these are the timestamps that were filed under org-capture:
</p>

<ul class="org-ul">
<li><span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T10:39:00-0400">[2026-04-16 Thu 10:39]</time></span> Getting more out of livestreams</li>
<li><span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T10:57:00-0400">[2026-04-16 Thu 10:57]</time></span> Announcing livestreams</li>
<li><span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T11:05:00-0400">[2026-04-16 Thu 11:05]</time></span> Processing the recordings</li>
<li><span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T11:11:00-0400">[2026-04-16 Thu 11:11]</time></span> Non-packaged code</li>
</ul>

<p>
Here's a short function for getting those times:
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp" id="org361bf8b"><code>(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-org-time-at-point</span> ()
  <span class="org-doc">"Return Emacs time object for timestamp at point."</span>
  (org-timestamp-to-time (org-timestamp-from-string (org-element-property <span class="org-builtin">:raw-value</span> (org-element-context)))))
</code></pre>
</div>


<p>
Next, I wanted to turn those timestamps into a hh:mm:ss offset into the streamed video.
</p>
</div>
</div>
<div id="outline-container-streaming-make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream-calculate-an-org-timestamp-s-offset-into-a-youtube-stream" class="outline-3">
<h3 id="streaming-make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream-calculate-an-org-timestamp-s-offset-into-a-youtube-stream"><a href="https://sachachua.com/blog/feed/atom/index.xml#streaming-make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream-calculate-an-org-timestamp-s-offset-into-a-youtube-stream">Calculate an Org timestamp's offset into a YouTube stream</a></h3>
<div class="outline-text-3" id="text-streaming-make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream-calculate-an-org-timestamp-s-offset-into-a-youtube-stream">
<p>
I post my YouTube videos under a brand account so that just in case I lose access to my main sacha@sachachua.com Google account, I still have access via my @gmail.com account. To enable YouTube API access to my channel, I needed to get my brand account's email address and set it up as a test user.
</p>

<ol class="org-ol">
<li>Go to <a href="https://myaccount.google.com/brandaccounts">https://myaccount.google.com/brandaccounts</a>.</li>
<li>Select the account.</li>
<li>Click on <b>View general account info</b></li>
<li>Copy the <code>...@pages.plusgoogle.com</code> email address there.</li>
<li>Go to <a href="https://console.cloud.google.com/">https://console.cloud.google.com/</a></li>
<li>Enable the YouTube data API for my project.</li>
<li>Download the credentials.json.</li>
<li>Go to <b>Data Access - Audience</b></li>
<li>Set the <b>User type</b> to <b>External</b></li>
<li>Add my brand account as one of the <b>Test users</b>.</li>
<li><p>
Log in at the command line:
</p>

<div class="org-src-container">
<pre class="src src-sh"><code> gcloud auth application-default login <span class="org-sh-escaped-newline">\</span>
     &#45;&#45;client-id-file=credentials.json <span class="org-sh-escaped-newline">\</span>
     &#45;&#45;scopes=<span class="org-string">"https://www.googleapis.com/auth/youtube"</span>
</code></pre>
</div>
</li>
</ol>

<p>
Then the following code calculates the offset of the timestamp at point based on the livestream that contains it.
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code><span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-google-youtube-stream-offset</span> (time)
  <span class="org-doc">"Return the offset from the start of the stream.</span>
<span class="org-doc">When called interactively, copy it."</span>
  (<span class="org-keyword">interactive</span> (list (sacha-org-time-at-point)))
  (<span class="org-keyword">when</span> (<span class="org-keyword">and</span> (stringp time)
             (string-match org-element&#45;&#45;timestamp-regexp time))
    (<span class="org-keyword">setq</span> time (org-timestamp-to-time (org-timestamp-from-string (match-string 0 time)))))
  (<span class="org-keyword">let</span> ((result
         (emacstv-format-seconds (sacha-google-youtube-live-seconds-offset-from-start-of-stream
                                  time))))
    (<span class="org-keyword">when</span> (called-interactively-p <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">any</span>)
      (kill-new result)
      (message <span class="org-string">"%s"</span> result))
    result))

(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-google-access-token</span> nil <span class="org-doc">"Cached access token."</span>)

<span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-google-access-token</span> ()
  <span class="org-doc">"Return Google access token."</span>
  (<span class="org-keyword">or</span> sacha-google-access-token
      (<span class="org-keyword">setq</span> sacha-google-access-token
            (string-trim (shell-command-to-string <span class="org-string">"gcloud auth application-default print-access-token"</span>)))))

(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-google-youtube-live-broadcasts</span> nil <span class="org-doc">"Cache."</span>)
(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-google-youtube-stream-offset-seconds</span> 10 <span class="org-doc">"Number of seconds to offset."</span>)

<span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-google-youtube-live-broadcasts</span> ()
  <span class="org-doc">"Return the list of broadcasts."</span>
  (<span class="org-keyword">or</span> sacha-google-youtube-live-broadcasts
      (<span class="org-keyword">setq</span> sacha-google-youtube-live-broadcasts
            (request-response-data
             (request <span class="org-string">"https://www.googleapis.com/youtube/v3/liveBroadcasts?part=snippet&amp;mine=true&amp;maxResults=10"</span>
               <span class="org-builtin">:headers</span> <span class="org-highlight-quoted-quote">`</span>((<span class="org-string">"Authorization"</span> . ,(format <span class="org-string">"Bearer %s"</span> (sacha-google-access-token))))
               <span class="org-builtin">:sync</span> t
               <span class="org-builtin">:parser</span> <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">json-read</span>)))))

(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-google-youtube-live-get-broadcast-at-time</span> (time)
  <span class="org-doc">"Return the broadcast encompassing TIME."</span>
  (seq-find
   (<span class="org-keyword">lambda</span> (o)
     (<span class="org-keyword">or</span>
      <span class="org-comment-delimiter">;; </span><span class="org-comment">actual</span>
      (<span class="org-keyword">and</span>
       (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o))
       (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualEndTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o))
       (not (time-less-p time (date-to-time (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o)))))
       (time-less-p time (date-to-time (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualEndTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o)))))
      <span class="org-comment-delimiter">;; </span><span class="org-comment">actual, not done yet</span>
      (<span class="org-keyword">and</span>
       (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o))
       (null (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualEndTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o)))
       (not (time-less-p time (date-to-time (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o))))))
      <span class="org-comment-delimiter">;; </span><span class="org-comment">scheduled</span>
      (<span class="org-keyword">and</span>
       (null (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o)))
       (null (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualEndTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o)))
       (not (time-less-p time (date-to-time (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">scheduledStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o))))))))
   (sort
    (seq-filter
     (<span class="org-keyword">lambda</span> (o)
       (<span class="org-keyword">or</span>
        (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o))
        (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">scheduledStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o))))
     (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">items</span>

                (sacha-google-youtube-live-broadcasts)))
    <span class="org-builtin">:key</span> (<span class="org-keyword">lambda</span> (o)
           (<span class="org-keyword">or</span>
            (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o))
            (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">scheduledStartTime</span> (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span> o))))
    <span class="org-builtin">:lessp</span> <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">string&lt;</span>)))

(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-google-youtube-live-seconds-offset-from-start-of-stream</span> (wall-time)
  <span class="org-doc">"Return number of seconds for WALL-TIME from the start of the stream that contains it.</span>
<span class="org-doc">Offset by `</span><span class="org-doc"><span class="org-constant">sacha-google-youtube-stream-offset-seconds</span></span><span class="org-doc">'."</span>
  (+ sacha-google-youtube-stream-offset-seconds
     (time-to-seconds
      (time-subtract
       wall-time
       (date-to-time
        (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">actualStartTime</span>
                   (alist-get <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">snippet</span>
                              (sacha-google-youtube-live-get-broadcast-at-time wall-time))))))))

<span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-google-clear-cache</span> ()
  <span class="org-doc">"Clear cached Google access tokens and data."</span>
  (<span class="org-keyword">interactive</span>)
  (<span class="org-keyword">setq</span> sacha-google-access-token nil)
  (<span class="org-keyword">setq</span> sacha-google-youtube-live-broadcasts nil))
</code></pre>
</div>


<p>
For example:
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(mapcar
 (<span class="org-keyword">lambda</span> (o)
   (list (concat
           <span class="org-string">"vtime:"</span>
           (sacha-google-youtube-stream-offset
            o))
         o))
 timestamps)
</code></pre>
</div>


<table>


<colgroup>
<col class="org-left">

<col class="org-left">
</colgroup>
<tbody>
<tr>
<td class="org-left"><span class="media-time" data-start="1149.000">19:09</span></td>
<td class="org-left"><span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T10:39:00-0400">[2026-04-16 Thu 10:39]</time></span>  Getting more out of livestreams</td>
</tr>

<tr>
<td class="org-left"><span class="media-time" data-start="2229.000">37:09</span></td>
<td class="org-left"><span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T10:57:00-0400">[2026-04-16 Thu 10:57]</time></span>  Announcing livestreams</td>
</tr>

<tr>
<td class="org-left"><span class="media-time" data-start="2709.000">45:09</span></td>
<td class="org-left"><span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T11:05:00-0400">[2026-04-16 Thu 11:05]</time></span>  Processing the recordings</td>
</tr>

<tr>
<td class="org-left"><span class="media-time" data-start="3069.000">51:09</span></td>
<td class="org-left"><span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T11:11:00-0400">[2026-04-16 Thu 11:11]</time></span>  Non-packaged code</td>
</tr>
</tbody>
</table>

<p>
It's not exact, but it gets me in the right neighbourhood. Then I can use the MPV player to figure out a better timestamp if I want, and I can use my custom vtime Org link time to make those clickable when people have Javascript enabled. See <a href="https://sachachua.com/blog/2026/04/ye16-sacha-and-prot-talk-emacs/">YE16: Sacha and Prot talk Emacs</a> for examples.
</p>

<p>
It could be nice to log seconds someday for even finer timestamps. Still, this is handy already!
</p>
</div>
</div>

<div class="note">This is part of my <a href="https://sachachua.com/dotemacs#streaming-make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream">Emacs configuration.</a></div><div><a href="https://sachachua.com/blog/2026/04/make-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream/index.org">View Org source for this post</a></div><p>You can <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F04%2Fmake-chapter-markers-and-video-time-hyperlinks-easier-to-note-while-i-livestream%2F&body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p>]]></content>
		</entry><entry>
		<title type="html">Org Mode: JS for translating times to people's local timezones</title>
		<link rel="alternate" type="text/html" href="https://sachachua.com/blog/2026/04/org-mode-js-for-translating-times-to-people-s-local-timezones/"/>
		<author><name><![CDATA[Sacha Chua]]></name></author>
		<updated>2026-04-14T18:44:16Z</updated>
    <published>2026-04-14T18:44:16Z</published>
    <category term="org" />
<category term="emacs" />
<category term="js" />
		<id>https://sachachua.com/blog/2026/04/org-mode-js-for-translating-times-to-people-s-local-timezones/</id>
		<content type="html"><![CDATA[<p>
I want to get back into the swing of doing <a href="https://sachachua.com/topic/emacs-chat/">Emacs Chats</a> again, which means scheduling, which means timezones. Let's see first if anyone happens to match up with the Thursday timeslots (10:30 or 12:45) that I'd like to use for Emacs-y video things, but I might be able to shuffle things around if needed.
</p>

<p>
I want something that can translate times into people's local timezones.
I use Org Mode timestamps a lot because they're so easy to insert with <code>C-u C-c !</code> (<code>org-timestamp-inactive</code>), which inserts a timestamp like this:
</p>

<p>
<span class="timestamp-wrapper"><time class="timestamp" datetime="2026-04-16T10:30:00-0400">[2026-04-16 Thu 10:30]</time></span>
</p>

<p>
By default, the Org HTML export for it does not include the timezone offset. That's easily fixed by adding <code>%z</code> to the time specifier, like this:
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">setq</span> org-html-datetime-formats <span class="org-highlight-quoted-quote">'</span>(<span class="org-string">"%F"</span> . <span class="org-string">"%FT%T%z"</span>))
</code></pre>
</div>


<p>
Now a little bit of Javascript code makes it clickable and lets us toggle a translated time. I put the time afterwards so that people can verify it visually. I never quite trust myself when it comes to timezone translations.
</p>


<div class="org-src-container">
<pre class="src src-js"><code><span class="org-keyword">function</span> <span class="org-function-name">translateTime</span>(<span class="org-variable-name">event</span>) {
  <span class="org-keyword">if</span> (event.target.getAttribute(<span class="org-string">'datetime'</span>)?.match(<span class="org-string">/[0-9][0-9][0-9][0-9]$/</span>)) {
    <span class="org-keyword">if</span> (event.target.querySelector(<span class="org-string">'.translated'</span>)) {
      event.target.querySelectorAll(<span class="org-string">'.translated'</span>).forEach((o) =&gt; o.remove());
    } <span class="org-keyword">else</span> {
      <span class="org-keyword">const</span> <span class="org-variable-name">span</span> = document.createElement(<span class="org-string">'span'</span>);
      span.classList.add(<span class="org-string">'translated'</span>);
      span.textContent = <span class="org-string">' &#8594; '</span> + (<span class="org-keyword">new</span> <span class="org-type">Date</span>(event.target.getAttribute(<span class="org-string">'datetime'</span>))).toLocaleString(<span class="org-constant">undefined</span>, {
        month: <span class="org-string">'short'</span>,  
        day: <span class="org-string">'numeric'</span>,  
        hour: <span class="org-string">'numeric'</span>, 
        minute: <span class="org-string">'2-digit'</span>,
        timeZoneName: <span class="org-string">'short'</span>
      });
      event.target.appendChild(span);
    }
  }
}
<span class="org-keyword">function</span> <span class="org-function-name">clickForLocalTime</span>() {
  document.querySelectorAll(<span class="org-string">'time'</span>).forEach((o) =&gt; {
    <span class="org-keyword">if</span> (o.getAttribute(<span class="org-string">'datetime'</span>)?.match(<span class="org-string">/[0-9][0-9][0-9][0-9]$/</span>)) {
      o.addEventListener(<span class="org-string">'click'</span>, translateTime);
      o.classList.add(<span class="org-string">'clickable'</span>);
    }
  });
}
</code></pre>
</div>


<p>
And some CSS to make it more obvious that it's now clickable:
</p>


<div class="org-src-container">
<pre class="src src-css"><code><span class="org-css-selector">.clickable</span> {
    <span class="org-css-property">cursor</span>: pointer;
    <span class="org-css-property">text-decoration</span>: underline dotted;
}
</code></pre>
</div>


<p>
Let's see if this is useful.
</p>

<p>
Someday, it would probably be handy to have a button that translates all the timestamps in a table, but this is a good starting point.
</p>
<div><a href="https://sachachua.com/blog/2026/04/org-mode-js-for-translating-times-to-people-s-local-timezones/index.org">View Org source for this post</a></div><p>You can <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F04%2Forg-mode-js-for-translating-times-to-people-s-local-timezones%2F&body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p>]]></content>
		</entry><entry>
		<title type="html">Org Mode: Tangle Emacs config snippets to different files and add boilerplate</title>
		<link rel="alternate" type="text/html" href="https://sachachua.com/blog/2026/04/org-mode-tangle-emacs-config-snippets-to-different-files-and-add-boilerplate/"/>
		<author><name><![CDATA[Sacha Chua]]></name></author>
		<updated>2026-04-11T14:13:19Z</updated>
    <published>2026-04-11T14:13:19Z</published>
    <category term="emacs" />
<category term="org" />
		<id>https://sachachua.com/blog/2026/04/org-mode-tangle-emacs-config-snippets-to-different-files-and-add-boilerplate/</id>
		<content type="html"><![CDATA[<p>
I want to organize the functions in my Emacs configuration so that they are easier for me to test and so that other people can load them from my repository. Instead of copying multiple code blogs from my blog posts or my exported Emacs configuration, it would be great if people could just include a file from the repository. I don't think people copy that much from my config, but it might still be worth making it easier for people to borrow interesting functions. It would be great to have libraries of functions that people can evaluate without worrying about side effects, and then they can copy or write a shorter piece of code to use those functions.
</p>

<p>
<a href="https://protesilaos.com/emacs/dotemacs#h:fc1ea247-5ef6-4c4e-a807-6c7b2482af90">In Prot's configuration (The custom libraries of my configuration)</a>, he includes each library as in full, in a single code block, with the boilerplate description, keywords, and <code>(provide '...)</code> that make them more like other libraries in Emacs.
</p>

<p>
I'm not quite sure my little functions are at that point yet. For now, I like the way that the functions are embedded in the blog posts and notes that explain them, and the org-babel <code>:comments</code> argument can insert links back to the sections of my configuration that I can open with <code>org-open-at-point-global</code> or <code>org-babel-tangle-jump-to-org</code>.
</p>

<details class="code-details" style="padding: 1em;
                 border-radius: 15px;
                 font-size: 0.9em;
                 box-shadow: 0.05em 0.1em 5px 0.01em  #00000057;">
                  <summary><strong>Thinking through the options...</strong></summary>
<p>
Org tangles blocks in order, so if I want boilerplate or if I want to add require statements, I need to have a section near the beginning of my config that sets those up for each file. Noweb references might help me with common text like the license. Likewise, if I want a <code>(provide ...)</code> line at the end of each file, I need a section near the end of the file.
</p>

<p>
If I want to specify things out of sequence, I could use Noweb. By setting <code>:noweb-ref some-id :tangle no</code> on the blocks I want to collect later, I can then tangle them in the middle of the boilerplate. Here's a brief demo:
</p>


<div class="org-src-container">
<pre class="src src-org"><code><span class="org-org-block-begin-line">#+begin_src emacs-lisp :noweb yes :tangle lisp/sacha-eshell.el :comments no</span>
<span class="org-org-block"><span class="org-comment-delimiter">;; </span></span><span class="org-org-block"><span class="org-comment">-*- lexical-binding: t; -*-</span></span>
<span class="org-org-block">&lt;&lt;sacha-eshell&gt;&gt;</span>
<span class="org-org-block">(</span><span class="org-org-block"><span class="org-keyword">provide</span></span><span class="org-org-block"> </span><span class="org-org-block"><span class="org-highlight-quoted-quote">'</span></span><span class="org-org-block"><span class="org-constant">sacha-eshell</span></span><span class="org-org-block">)</span>
<span class="org-org-block-end-line">#+end_src</span>
</code></pre>
</div>


<p>
However, I'll lose the comment links that let me jump back to the part of the Org file with the original source block. This means that if I use <code>find-function</code> to jump to the definition of a function and then I want to find the outline section related to it, I have to use a function that checks if this might be my custom code and then looks in my config for "defun &hellip;". It's a little less generic.
</p>

<p>
I wonder if I can combine multiple targets with some code that knows what it's being tangled to, so it can write slightly different text. <code>org-babel-tangle-single-block</code> currently calculates the result once and then adds it to the list for each filename, so that doesn't seem likely.
</p>

<p>
Alternatively, maybe I can use noweb or my own tangling function and add the link comments from org-babel-tangle-comments.
</p>


</details>

<p>
Aha, I can fiddle with <code>org-babel-post-tangle-hook</code> to insert the boilerplate after the blocks have been written. Then I can add the <code>lexical-binding: t</code> cookie and the structure that makes it look more like the other libraries people define and use. It's always nice when I can get away with a small change that uses an existing hook. For good measure, let's even include a list of links to the sections of my config that affect that file.
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-dotemacs-url</span> <span class="org-string">"https://sachachua.com/dotemacs/"</span>)

<span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-dotemacs-link-for-section-at-point</span> (<span class="org-type">&amp;optional</span> combined)
  <span class="org-doc">"Return the link for the current section."</span>
  (<span class="org-keyword">let*</span> ((custom-id (org-entry-get-with-inheritance <span class="org-string">"CUSTOM_ID"</span>))
         (title (org-entry-get (point) <span class="org-string">"ITEM"</span>))
         (url (<span class="org-keyword">if</span> custom-id
                  (concat <span class="org-string">"dotemacs:"</span> custom-id)
                (concat sacha-dotemacs-url <span class="org-string">":-:text="</span> (url-hexify-string title)))))
    (<span class="org-keyword">if</span> combined
        (org-link-make-string
         url
         title)
      (cons url title))))

(<span class="org-keyword">eval-and-compile</span>
  (<span class="org-keyword">require</span> <span class="org-highlight-quoted-quote">'</span><span class="org-constant">org-core</span> nil t)
  (<span class="org-keyword">require</span> <span class="org-highlight-quoted-quote">'</span><span class="org-constant">org-macs</span> nil t)
  (<span class="org-keyword">require</span> <span class="org-highlight-quoted-quote">'</span><span class="org-constant">org-src</span> nil t))
(<span class="org-keyword">declare-function</span> <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">org-babel-tangle&#45;&#45;compute-targets</span> <span class="org-string">"ob-tangle"</span>)
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-org-collect-links-for-tangled-files</span> ()
  <span class="org-doc">"Return a list of ((filename (link link link link)) ...)."</span>
  (<span class="org-keyword">let*</span> ((file (buffer-file-name))
         results)
    (<span class="org-keyword">org-babel-map-src-blocks</span> (buffer-file-name)
      (<span class="org-keyword">let*</span> ((info (org-babel-get-src-block-info))
             (link (sacha-dotemacs-link-for-section-at-point)))
        (mapc
         (<span class="org-keyword">lambda</span> (target)
           (<span class="org-keyword">let</span> ((list (assoc target results <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">string=</span>)))
             (<span class="org-keyword">if</span> list
                 (<span class="org-keyword">cl-pushnew</span> link (cdr list) <span class="org-builtin">:test</span> <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">equal</span>)
               (<span class="org-keyword">push</span> (list target link) results))))
         (org-babel-tangle&#45;&#45;compute-targets file info))))
    <span class="org-comment-delimiter">;; </span><span class="org-comment">Put it back in source order</span>
    (nreverse
     (mapcar (<span class="org-keyword">lambda</span> (o)
               (cons (car o)
                     (nreverse (cdr o))))
             results))))
(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-emacs-config-module-links</span> nil <span class="org-doc">"Cache for links from tangled files."</span>)

<span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-emacs-config-update-module-info</span> ()
  <span class="org-doc">"Update the list of links."</span>
  (<span class="org-keyword">interactive</span>)
  (<span class="org-keyword">setq</span> sacha-emacs-config-module-links
        (seq-filter
         (<span class="org-keyword">lambda</span> (o)
           (string-match <span class="org-string">"sacha-"</span> (car o)))
         (sacha-org-collect-links-for-tangled-files)))
  (<span class="org-keyword">setq</span> sacha-emacs-config-modules-info
        (mapcar (<span class="org-keyword">lambda</span> (group)
                  <span class="org-highlight-quoted-quote">`</span>(,(file-name-base (car group))
                    (commentary
                     .
                     ,(replace-regexp-in-string
                       <span class="org-string">"^"</span>
                       <span class="org-string">";; "</span>
                       (concat
                        <span class="org-string">"Related Emacs config sections:\n\n"</span>
                        (org-export-string-as
                         (mapconcat
                          (<span class="org-keyword">lambda</span> (link)
                            (concat <span class="org-string">"- "</span> (cdr link) <span class="org-string">"\\\\\n  "</span> (org-link-make-string (car link)) <span class="org-string">"\n"</span>))
                          (cdr group)
                          <span class="org-string">"\n"</span>)
                         <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">ascii</span>
                         t))))))
                sacha-emacs-config-module-links)))

<span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-emacs-config-prepare-to-tangle</span> ()
  <span class="org-doc">"Update module info if tangling my config."</span>
  (<span class="org-keyword">when</span> (string-match <span class="org-string">"Sacha.org"</span> (buffer-file-name))
    (sacha-emacs-config-update-module-info)))
</code></pre>
</div>


<p>
Let's set up the functions for tangling the boilerplate.
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-emacs-config-modules-dir</span> <span class="org-string">"~/sync/emacs/lisp/"</span>)
(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-emacs-config-modules-info</span> nil <span class="org-doc">"Alist of module info."</span>)
(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-emacs-config-url</span> <span class="org-string">"https://sachachua.com/dotemacs"</span>)

<span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-org-babel-post-tangle-insert-boilerplate-for-sacha-lisp</span> ()
  (<span class="org-keyword">when</span> (file-in-directory-p (buffer-file-name) sacha-emacs-config-modules-dir)
    (goto-char (point-min))
    (<span class="org-keyword">let</span> ((base (file-name-base (buffer-file-name))))
      (insert (format <span class="org-string">";;; %s.el &#45;&#45;- %s -*- lexical-binding: t -*-</span>

<span class="org-string">;; Author: %s &lt;%s&gt;</span>
<span class="org-string">;; URL: %s</span>

<span class="org-string">;;; License:</span>
<span class="org-string">;;</span>
<span class="org-string">;; This file is not part of GNU Emacs.</span>
<span class="org-string">;;</span>
<span class="org-string">;; This is free software; you can redistribute it and/or modify</span>
<span class="org-string">;; it under the terms of the GNU General Public License as published by</span>
<span class="org-string">;; the Free Software Foundation; either version 3, or (at your option)</span>
<span class="org-string">;; any later version.</span>
<span class="org-string">;;</span>
<span class="org-string">;; This is distributed in the hope that it will be useful,</span>
<span class="org-string">;; but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="org-string">;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<span class="org-string">;; GNU General Public License for more details.</span>
<span class="org-string">;;</span>
<span class="org-string">;; You should have received a copy of the GNU General Public License</span>
<span class="org-string">;; along with GNU Emacs; see the file COPYING.  If not, write to the</span>
<span class="org-string">;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,</span>
<span class="org-string">;; Boston, MA 02110-1301, USA.</span>

<span class="org-string">;;; Commentary:</span>
<span class="org-string">;;</span>
<span class="org-string">%s</span>
<span class="org-string">;;; Code:</span>

<span class="org-string">\n\n"</span>
                      base
                      (<span class="org-keyword">or</span>
                       (assoc-default <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">description</span>
                                      (assoc-default base sacha-emacs-config-modules-info <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">string=</span>))
                       <span class="org-string">""</span>)
                      user-full-name
                      user-mail-address
                      sacha-emacs-config-url
                      (<span class="org-keyword">or</span>
                       (assoc-default <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">commentary</span>
                                      (assoc-default base sacha-emacs-config-modules-info <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">string=</span>))
                       <span class="org-string">""</span>)))
      (goto-char (point-max))
      (insert (format <span class="org-string">"\n(provide '%s)\n;;; %s.el ends here\n"</span>
                      base
                      base))
      (save-buffer))))
</code></pre>
</div>



<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">setq</span> sacha-emacs-config-url <span class="org-string">"https://sachachua.com/dotemacs"</span>)
(<span class="org-keyword">with-eval-after-load</span> <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">org</span>
  (add-hook <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">org-babel-pre-tangle-hook</span> <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">sacha-emacs-config-prepare-to-tangle</span>)
  (add-hook <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">org-babel-post-tangle-hook</span> <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">sacha-org-babel-post-tangle-insert-boilerplate-for-sacha-lisp</span>))
</code></pre>
</div>


<p>
You can see the results at <a href="https://codeberg.org/sachac/.emacs.d/src/branch/gh-pages/lisp/">.emacs.d/lisp</a>. For example, the function definitions in this post are at <a href="https://codeberg.org/sachac/.emacs.d/src/branch/gh-pages/lisp/sacha-emacs.el">lisp/sacha-emacs.el</a>.
</p>

<div class="note">This is part of my <a href="https://sachachua.com/dotemacs#org-mode-org-babel-tangling-sacha-emacs-config-snippets-to-different-files-and-adding-boilerplate">Emacs configuration.</a></div><div><a href="https://sachachua.com/blog/2026/04/org-mode-tangle-emacs-config-snippets-to-different-files-and-add-boilerplate/index.org">View Org source for this post</a></div><p>You can <a href="https://sachachua.com/blog/2026/04/org-mode-tangle-emacs-config-snippets-to-different-files-and-add-boilerplate/#comment">view 2 comments</a> or <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F04%2Forg-mode-tangle-emacs-config-snippets-to-different-files-and-add-boilerplate%2F&body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p>]]></content>
		</entry><entry>
		<title type="html">YE11: Fix find-function for Emacs Lisp from org-babel or scratch</title>
		<link rel="alternate" type="text/html" href="https://sachachua.com/blog/2026/04/ye11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch/"/>
		<author><name><![CDATA[Sacha Chua]]></name></author>
		<updated>2026-04-05T21:03:48Z</updated>
    <published>2026-04-05T21:03:48Z</published>
    <category term="org" />
<category term="emacs" />
<category term="elisp" />
<category term="stream" />
<category term="yay-emacs" />
		<id>https://sachachua.com/blog/2026/04/ye11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch/</id>
		<content type="html"><![CDATA[<p>
<video controls="1" src="https://archive.org/download/yay-emacs-11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch/ye11-find-function.mp4" poster="https://sachachua.com/blog/2026/04/ye11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch/2026-04-05-19-25-03.png" type="video/mp4"><track kind="subtitles" label="Captions" src="https://sachachua.com/blog/2026/04/ye11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch/Yay%20Emacs%2011:%20Fix%20find-function%20for%20Emacs%20Lisp%20from%20org-babel%20or%20scratch.vtt" srclang="en" default=""><span>Video not supported. Thumbnail:<br><img src="https://sachachua.com/blog/2026/04/ye11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch/2026-04-05-19-25-03.png" alt="Thumbnail"></span></video>
</p>

<p>
<a href="https://archive.org/details/yay-emacs-11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch">Watch on Internet Archive</a>, <a href="https://youtube.com/live/PKkV1Tbev_Y">watch/comment on YouTube</a>, <a href="https://sachachua.com/blog/2026/04/ye11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch/Yay%20Emacs%2011:%20Fix%20find-function%20for%20Emacs%20Lisp%20from%20org-babel%20or%20scratch.vtt">download captions</a>, or <a href="mailto:sacha@sachachua.com">email me</a>
</p>


<p>
Where can you define an Emacs Lisp function so
that you can use <code>find-function</code> to jump to it
again later?
</p>

<ul class="org-ul">
<li><b>A: In an indirect buffer</b> from Org Mode source
block with your favorite eval function like
<code>eval-defun</code> <label class="hint"><input type="checkbox"> <span class="hint-desc">(hint)</span><span class="hint-text">nope</span></label>

<ul class="org-ul">
<li><p>
<code>C-c '</code> (<code>org-edit-special</code>) inside the block; execute the defun with <code>C-M-x</code> (<code>eval-defun</code>), <code>C-x C-e</code> (<code>eval-last-sexp</code>), or <code>eval-buffer</code>.
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>    (<span class="org-keyword">defun</span> <span class="org-function-name">my-test-1</span> () (message <span class="org-string">"Hello"</span>))
</code></pre>
</div>
</li>
</ul></li>

<li><p>
<b>B: In an Org Mode file</b> by executing the block
with C-c C-c <label class="hint"><input type="checkbox"> <span class="hint-desc">(hint)</span><span class="hint-text">nope</span></label>
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>  (<span class="org-keyword">defun</span> <span class="org-function-name">my-test-2</span> () (message <span class="org-string">"Hello"</span>))
</code></pre>
</div>
</li>

<li><p>
<b>C: In a .el file</b> <label class="hint"><input type="checkbox"> <span class="hint-desc">(hint)</span><span class="hint-text">yup</span></label>
</p>

<p>
<a href="https://sachachua.com/blog/2026/04/ye11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch/test-search-function.el">file:///tmp/test-search-function.el</a> : execute the defun with <code>C-M-x</code> (<code>eval-defun</code>), <code>C-x C-e</code> (<code>eval-last-sexp</code>), or <code>eval-buffer</code>
</p></li>

<li><p>
<b>D: In a scratch buffer,</b> other temporary buffer,
or really any buffer thanks to eval-last-sexp
<label class="hint"><input type="checkbox"> <span class="hint-desc">(hint)</span><span class="hint-text">nope</span></label>
</p>

<p>
<code>(defun my-test-4 () (message "Hello"))</code>
</p></li>
</ul>

<p>
Only option C works - it's gotta be in an .el file for
<code>find-function</code> to find it. But I love jumping to
function definitions using <code>find-function</code> or
<code>lispy-goto-symbol</code> (which is bound to <code>M-.</code> if
you use <a target="_blank" href="https://melpa.org/#/lispy">lispy</a> and set up <code>lispy-mode</code>) so
that I can look at or change how something works.
It can be a little frustrating when I try to jump
to a definition and it says, "Don't know where
blahblahblah is defined." I just defined it five
minutes ago! It's there in one of my other
buffers, don't make me look for it myself.
Probably this will get fixed in Emacs core
someday, but no worries, we can work around it
today with a little bit of advice.
</p>

<p>
I did some digging around in the source code.
Turns out that <code>symbol-file</code> can't find the
function definition in the <code>load-history</code> variable
if you're not in a .el file, so
<code>find-function-search-for-symbol</code> gets called with
<code>nil</code> for the library, which causes the error.
(<a href="https://github.com/emacs-mirror/emacs/blob/master/lisp/subr.el">emacs:subr.el</a>)
</p>

<p>
I wrote some advice that searches in any open
<code>emacs-lisp-mode</code> buffers or in a list of other
files, like my Emacs configuration.
This is how I activate it:
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">setq</span> sacha-elisp-find-function-search-extra <span class="org-highlight-quoted-quote">'</span>(<span class="org-string">"~/sync/emacs/Sacha.org"</span>))
(advice-add <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">find-function-search-for-symbol</span> <span class="org-builtin">:around</span> <span class="org-highlight-quoted-quote">#'</span><span class="org-highlight-quoted-symbol">sacha-elisp-find-function-search-for-symbol</span>)
</code></pre>
</div>


<p>
Now I should be able to jump to all those
functions wherever they're defined.
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(my-test-1)
(my-test-2)
(my-test-3)
(my-test-4)
</code></pre>
</div>


<p>
Note that by default, <code>M-.</code> in <code>emacs-lisp-mode</code> uses <code>xref-find-definitions</code>, which seems to really want files. I haven't figured out a good workaround for that yet, but <a target="_blank" href="https://melpa.org/#/lispy">lispy-mode</a> makes <code>M-.</code> work and gives me a bunch of other great shortcuts, so I'd recommend checking that out.
</p>

<p>
Here's the source code for the find function thing:
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">defvar</span> <span class="org-variable-name">sacha-elisp-find-function-search-extra</span>
  nil
  <span class="org-doc">"List of filenames to search for functions."</span>)

<span class="org-comment-delimiter">;;;</span><span class="org-comment">###</span><span class="org-comment"><span class="org-warning">autoload</span></span>
(<span class="org-keyword">defun</span> <span class="org-function-name">sacha-elisp-find-function-search-for-symbol</span> (fn symbol type library <span class="org-type">&amp;rest</span> _)
  <span class="org-doc">"Find SYMBOL with TYPE in Emacs Lisp buffers or `</span><span class="org-doc"><span class="org-constant">sacha-find-function-search-extra</span></span><span class="org-doc">'.</span>
<span class="org-doc">Prioritize buffers that do not have associated files, such as Org Src</span>
<span class="org-doc">buffers or *scratch*. Note that the fallback search uses \"^([</span><span class="org-doc"><span class="org-negation-char">^</span></span><span class="org-doc"> )]+\" so that</span>
<span class="org-doc">it isn't confused by preceding forms.</span>

<span class="org-doc">If LIBRARY is specified, fall back to FN.</span>

<span class="org-doc">Activate this with:</span>

<span class="org-doc">(advice-add 'find-function-search-for-symbol</span>
<span class="org-doc"> :around #'sacha-org-babel-find-function-search-for-symbol-in-dotemacs)"</span>
  (<span class="org-keyword">if</span> (null library)
      <span class="org-comment-delimiter">;; </span><span class="org-comment">Could not find library; search my-dotemacs-file just in case</span>
      (<span class="org-keyword">progn</span>
        (<span class="org-keyword">while</span> (<span class="org-keyword">and</span> (symbolp symbol) (get symbol <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">definition-name</span>))
          (<span class="org-keyword">setq</span> symbol (get symbol <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">definition-name</span>)))
        (<span class="org-keyword">catch</span> <span class="org-highlight-quoted-quote">'</span><span class="org-constant">found</span>
          (mapc
           (<span class="org-keyword">lambda</span> (buffer-or-file)
             (<span class="org-keyword">with-current-buffer</span> (<span class="org-keyword">if</span> (bufferp buffer-or-file)
                                      buffer-or-file
                                    (find-file-noselect buffer-or-file))
               (<span class="org-keyword">let*</span> ((regexp-symbol
                       (<span class="org-keyword">or</span> (<span class="org-keyword">and</span> (symbolp symbol)
                                (alist-get type (get symbol <span class="org-highlight-quoted-quote">'</span><span class="org-highlight-quoted-symbol">find-function-type-alist</span>)))
                           (alist-get type find-function-regexp-alist)))
                      (form-matcher-factory
                       (<span class="org-keyword">and</span> (functionp (cdr-safe regexp-symbol))
                            (cdr regexp-symbol)))
                      (regexp-symbol (<span class="org-keyword">if</span> form-matcher-factory
                                         (car regexp-symbol)
                                       regexp-symbol))

                      (case-fold-search)
                      (regexp (<span class="org-keyword">if</span> (functionp regexp-symbol) regexp-symbol
                                (format (symbol-value regexp-symbol)
                                        <span class="org-comment-delimiter">;; </span><span class="org-comment">Entry for ` (backquote) macro in loaddefs.el,</span>
                                        <span class="org-comment-delimiter">;; </span><span class="org-comment">(defalias (quote \`)..., has a \ but</span>
                                        <span class="org-comment-delimiter">;; </span><span class="org-comment">(symbol-name symbol) doesn't.  Add an</span>
                                        <span class="org-comment-delimiter">;; </span><span class="org-comment">optional \ to catch this.</span>
                                        (concat <span class="org-string">"\\\\?"</span>
                                                (regexp-quote (symbol-name symbol)))))))
                 (<span class="org-keyword">save-restriction</span>
                   (widen)
                   (<span class="org-keyword">with-syntax-table</span> emacs-lisp-mode-syntax-table
                     (goto-char (point-min))
                     (<span class="org-keyword">if</span> (<span class="org-keyword">if</span> (functionp regexp)
                             (funcall regexp symbol)
                           (<span class="org-keyword">or</span> (re-search-forward regexp nil t)
                               <span class="org-comment-delimiter">;; </span><span class="org-comment">`</span><span class="org-comment"><span class="org-constant">regexp</span></span><span class="org-comment">' matches definitions using known forms like</span>
                               <span class="org-comment-delimiter">;; </span><span class="org-comment">`</span><span class="org-comment"><span class="org-constant">defun</span></span><span class="org-comment">', or `</span><span class="org-comment"><span class="org-constant">defvar</span></span><span class="org-comment">'.  But some functions/variables</span>
                               <span class="org-comment-delimiter">;; </span><span class="org-comment">are defined using special macros (or functions), so</span>
                               <span class="org-comment-delimiter">;; </span><span class="org-comment">if `</span><span class="org-comment"><span class="org-constant">regexp</span></span><span class="org-comment">' can't find the definition, we look for</span>
                               <span class="org-comment-delimiter">;; </span><span class="org-comment">something of the form "(SOMETHING &lt;symbol&gt; ...)".</span>
                               <span class="org-comment-delimiter">;; </span><span class="org-comment">This fails to distinguish function definitions from</span>
                               <span class="org-comment-delimiter">;; </span><span class="org-comment">variable declarations (or even uses thereof), but is</span>
                               <span class="org-comment-delimiter">;; </span><span class="org-comment">a good pragmatic fallback.</span>
                               (re-search-forward
                                (concat <span class="org-string">"^([</span><span class="org-string"><span class="org-negation-char">^</span></span><span class="org-string"> )]+"</span> find-function-space-re <span class="org-string">"['(]?"</span>
                                        (regexp-quote (symbol-name symbol))
                                        <span class="org-string">"\\_&gt;"</span>)
                                nil t)))
                         (<span class="org-keyword">progn</span>
                           (beginning-of-line)
                           (<span class="org-keyword">throw</span> <span class="org-highlight-quoted-quote">'</span><span class="org-constant">found</span>
                                   (cons (current-buffer) (point))))
                       (<span class="org-keyword">when-let*</span> ((find-expanded
                                    (<span class="org-keyword">when</span> (trusted-content-p)
                                      (find-function&#45;&#45;search-by-expanding-macros
                                       (current-buffer) symbol type
                                       form-matcher-factory))))
                         (<span class="org-keyword">throw</span> <span class="org-highlight-quoted-quote">'</span><span class="org-constant">found</span>
                                 (cons (current-buffer)
                                       find-expanded)))))))))
           (delq nil
                 (append
                  (sort
                   (match-buffers <span class="org-highlight-quoted-quote">'</span>(derived-mode . emacs-lisp-mode))
                   <span class="org-builtin">:key</span> (<span class="org-keyword">lambda</span> (o) (<span class="org-keyword">or</span> (buffer-file-name o) <span class="org-string">""</span>)))
                  sacha-elisp-find-function-search-extra)))))
    (funcall fn symbol type library)))
</code></pre>
</div>


<p>
I even figured out how to <span title="(ignore (ert &quot;sacha-elisp&#45;&#45;find-function-search-for-symbol&#45;&#45;.*&quot;))">write tests for it</span>:
</p>


<div class="org-src-container">
<pre class="src src-emacs-lisp"><code>(<span class="org-keyword">ert-deftest</span> <span class="org-function-name">sacha-elisp&#45;&#45;find-function-search-for-symbol&#45;&#45;in-buffer</span> ()
  (<span class="org-keyword">let</span> ((sym (make-temp-name <span class="org-string">"&#45;&#45;test-fn"</span>))
        buffer)
    (<span class="org-keyword">unwind-protect</span>
        (<span class="org-keyword">with-temp-buffer</span>
          (emacs-lisp-mode)
          (insert (format <span class="org-string">";; Comment\n(defun %s () (message \"Hello\"))"</span> sym))
          (eval-last-sexp nil)
          (<span class="org-keyword">setq</span> buffer (current-buffer))
          (<span class="org-keyword">with-temp-buffer</span>
            (<span class="org-keyword">let</span> ((pos (sacha-elisp-find-function-search-for-symbol nil (intern sym) nil nil)))
              (<span class="org-keyword">should</span> (equal (car pos) buffer))
              (<span class="org-keyword">should</span> (equal (cdr pos) 12)))))
      (fmakunbound (intern sym)))))

(<span class="org-keyword">ert-deftest</span> <span class="org-function-name">sacha-elisp&#45;&#45;find-function-search-for-symbol&#45;&#45;in-file</span> ()
  (<span class="org-keyword">let*</span> ((sym (make-temp-name <span class="org-string">"&#45;&#45;test-fn"</span>))
         (temp-file (make-temp-file
                     <span class="org-string">"test-"</span> nil <span class="org-string">".org"</span>
                     (format
                      <span class="org-string">"#+begin_src emacs-lisp\n;; Comment\n(defun %s () (message \"Hello\"))\n#+end_src"</span>
                      sym)))
         (sacha-elisp-find-function-search-extra (list temp-file))
         buffer)
    (<span class="org-keyword">unwind-protect</span>
        (<span class="org-keyword">with-temp-buffer</span>
          (<span class="org-keyword">let</span> ((pos (sacha-elisp-find-function-search-for-symbol nil (intern sym) nil nil)))
            (<span class="org-keyword">should</span> (equal (buffer-file-name (car pos)) temp-file))
            (<span class="org-keyword">should</span> (equal (cdr pos) 35))))
      (delete-file temp-file))))
</code></pre>
</div>


<div class="note">This is part of my <a href="https://sachachua.com/dotemacs#org-mode-org-babel-fix-find-function-when-i-ve-evaluated-something-from-org-babel">Emacs configuration.</a></div><div><a href="https://sachachua.com/blog/2026/04/ye11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch/index.org">View Org source for this post</a></div><p>You can <a href="https://social.sachachua.com/@sacha/statuses/01KNFTFSC3D0K7XH1JW1XTF6QG" target="_blank" rel="noopener noreferrer">comment on Mastodon</a> or <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2026%2F04%2Fye11-fix-find-function-for-emacs-lisp-from-org-babel-or-scratch%2F&body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p>]]></content>
		</entry>
</feed>