The Digital Cat - Markdownhttps://www.thedigitalcatonline.com/2021-03-25T14:00:00+01:00Adventures of a curious cat in the land of programmingHow to write a Pelican theme for your static website2021-03-25T14:00:00+01:002021-03-25T14:00:00+01:00Leonardo Giordanitag:www.thedigitalcatonline.com,2021-03-25:/blog/2021/03/25/how-to-write-a-pelican-theme-for-your-static-website/<p>A full-fledged tutorial that shows how to convert an HTML template into a Pelican theme</p><p>I run The Digital Cat using a static site generator called <a href="https://blog.getpelican.com/">Pelican</a>, created by my friend <a href="https://justinmayer.com/">Justin Mayer</a> and actively maintained by him and other developers. I also gave some minor contributions to the project.</p><p>Since I started working on the blog in 2013 I run a great length to customise the theme that I use. I initially went for a pre-made Pelican theme, but I soon started to change small things, and eventually ended up creating a whole new theme that suits my needs.</p><p>Front-end development if not my forte, though, so I didn't want to start from scratch with HTML, CSS and JS. My knowledge of those tools is limited, and I have other interests, so I started from a free (CC BY 3.0) pre-made HTML5 template created by <a href="https://html5up.net/">HTML5 UP</a>. You can see <a href="https://html5up.net/editorial">a demo of the original template</a> and compare it with what you see on this very page.</p><p>Encouraged by Justin, I decided to write down this initial guide on how to port a Pelican theme from a static template. I will show you how to start a blog from scratch, how to get a static template and how to make it usable by Pelican. Everything done step by step without skipping any passage. At the end of the post you will <strong>have a running blog with some demo articles</strong>, you will <strong>have learned how to use the Jinja language and the Pelican variables</strong>, and you will <strong>have an idea of what to do next to further customise your static website</strong>.</p><p>Let's start!</p><h2 id="initial-setup-7d57">Initial setup<a class="headerlink" href="#initial-setup-7d57" title="Permanent link">¶</a></h2><p>Let's create a blog called The Analog Fox, following <a href="https://docs.getpelican.com/en/latest/quickstart.html">Pelican's quickstart guide</a>.</p><p>I created a virtual environment and installed Pelican as suggested, then run</p><div class="code"><div class="content"><div class="highlight"><pre>mkdir theanalogfox
cd theanalogfox
pelican-quickstart
</pre></div> </div> </div><p>For this project I will only run the blog locally, so I didn't configure any specific way to publish it, neither properly set up a URL prefix. If you are about to create a real website please read Pelican's documentation about those settings.</p><div class="code"><div class="content"><div class="highlight"><pre>> Where do you want to create your new web site? [.]
<span class="hll">> What will be the title of this web site? The Analog Fox
</span><span class="hll">> Who will be the author of this web site? Leonardo Giordani
</span>> What will be the default language of this web site? [en]
<span class="hll">> Do you want to specify a URL prefix? e.g., https://example.com (Y/n) n
</span>> Do you want to enable article pagination? (Y/n)
<span class="hll">> How many articles per page do you want? [10] 3
</span>> What is your time zone? [Europe/Paris]
> Do you want to generate a tasks.py/Makefile to automate generation and publishing? (Y/n)
> Do you want to upload your website using FTP? (y/N)
> Do you want to upload your website using SSH? (y/N)
> Do you want to upload your website using Dropbox? (y/N)
> Do you want to upload your website using S3? (y/N)
> Do you want to upload your website using Rackspace Cloud Files? (y/N)
> Do you want to upload your website using GitHub Pages? (y/N)
Done. Your new project is available at /home/leo/devel/theanalogfox
</pre></div> </div> </div><p>If you run <code>pelican -lr</code> now and visit <a href="http://localhost:8000">http://localhost:8000</a> with your browser you will see the first page of the blog rendered with the default theme.</p><h2 id="demo-content-a90a">Demo content<a class="headerlink" href="#demo-content-a90a" title="Permanent link">¶</a></h2><p>Before we venture into the jungle of Jinja templates it's worth creating some content. As this is a very boring activity I prepared a little script that you can run in the terminal.</p><div class="code"><div class="content"><div class="highlight"><pre><span class="ch">#!/bin/bash</span>
<span class="nv">NUM_POSTS</span><span class="o">=</span><span class="m">20</span>
<span class="nv">CONTENT_DIR</span><span class="o">=</span>content
<span class="nv">LOREM_API</span><span class="o">=</span>https://jaspervdj.be/lorem-markdownum/markdown.txt
<span class="nv">IMAGES_API</span><span class="o">=</span>https://placeimg.com/1000/341/animals
rm<span class="w"> </span>-fR<span class="w"> </span>content
mkdir<span class="w"> </span>-p<span class="w"> </span>content/images
<span class="k">for</span><span class="w"> </span>i<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="k">$(</span>seq<span class="w"> </span>-w<span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="si">${</span><span class="nv">NUM_POSTS</span><span class="si">}</span><span class="k">)</span>
<span class="k">do</span>
<span class="w"> </span><span class="nv">post_file</span><span class="o">=</span><span class="si">${</span><span class="nv">CONTENT_DIR</span><span class="si">}</span>/post<span class="si">${</span><span class="nv">i</span><span class="si">}</span>.markdown
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"Creating post </span><span class="si">${</span><span class="nv">i</span><span class="si">}</span><span class="s2">"</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"Title: A sample article </span><span class="si">${</span><span class="nv">i</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span>>><span class="w"> </span><span class="si">${</span><span class="nv">post_file</span><span class="si">}</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"Date: 2021-03-</span><span class="si">${</span><span class="nv">i</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span>>><span class="w"> </span><span class="si">${</span><span class="nv">post_file</span><span class="si">}</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"Category: News"</span><span class="w"> </span>>><span class="w"> </span><span class="si">${</span><span class="nv">post_file</span><span class="si">}</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"Tags: </span><span class="k">$(</span>seq<span class="w"> </span><span class="m">1</span><span class="w"> </span><span class="m">20</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>shuf<span class="w"> </span><span class="p">|</span><span class="w"> </span>head<span class="w"> </span>-n3<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-r<span class="w"> </span>s,<span class="s2">"^"</span>,<span class="s2">"tag"</span>,<span class="w"> </span><span class="p">|</span><span class="w"> </span>paste<span class="w"> </span>-sd<span class="w"> </span><span class="s2">","</span><span class="w"> </span>-<span class="k">)</span><span class="s2">"</span><span class="w"> </span>>><span class="w"> </span><span class="si">${</span><span class="nv">post_file</span><span class="si">}</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"Image: post</span><span class="si">${</span><span class="nv">i</span><span class="si">}</span><span class="s2">.jpg"</span><span class="w"> </span>>><span class="w"> </span><span class="si">${</span><span class="nv">post_file</span><span class="si">}</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">"Summary: Summary of post </span><span class="si">${</span><span class="nv">i</span><span class="si">}</span><span class="s2">"</span><span class="w"> </span>>><span class="w"> </span><span class="si">${</span><span class="nv">post_file</span><span class="si">}</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span>>><span class="w"> </span><span class="si">${</span><span class="nv">post_file</span><span class="si">}</span>
<span class="w"> </span>curl<span class="w"> </span>-s<span class="w"> </span><span class="si">${</span><span class="nv">LOREM_API</span><span class="si">}</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span>-r<span class="w"> </span>s,<span class="s2">"^#"</span>,<span class="s2">"##"</span>,<span class="w"> </span>>><span class="w"> </span><span class="si">${</span><span class="nv">post_file</span><span class="si">}</span>
<span class="w"> </span>curl<span class="w"> </span>-s<span class="w"> </span><span class="si">${</span><span class="nv">IMAGES_API</span><span class="si">}</span><span class="w"> </span>><span class="w"> </span><span class="si">${</span><span class="nv">CONTENT_DIR</span><span class="si">}</span>/images/post<span class="si">${</span><span class="nv">i</span><span class="si">}</span>.jpg
<span class="k">done</span>
</pre></div> </div> </div><p>Save it as <code>create_content.sh</code> and give it execution permissions with <code>chmod 775 create_content.sh</code>. At this point you can run it with <code>./create_content.sh</code> and it will create the directory <code>content</code> with 20 posts and an image for each of them. You can safely run it multiple times, it will automatically delete the previous output.</p><p>If you know bash feel free to hack the script to do something more complicated, but this very simple program does everything we need to work on Pelican themes.</p><p>Running <code>pelican -lr</code> and visiting <a href="http://localhost:8000">http://localhost:8000</a> will now show a richer website.</p>
<div class="advertisement">
<a href="https://www.thedigitalcat.academy/freebie-first-class-objects">
<img src="/images/first-class-objects/cover.jpg" />
</a>
<div class="body">
<h2 id="first-class-objects-in-python-fffa">First-class objects in Python<a class="headerlink" href="#first-class-objects-in-python-fffa" title="Permanent link">¶</a></h2>
<p>Higher-order functions, wrappers, and factories</p>
<p>Learn all you need to know to understand first-class citizenship in Python, the gateway to grasp how decorators work and how functional programming can supercharge your code.</p>
<div class="actions">
<a class="action" href="https://www.thedigitalcat.academy/freebie-first-class-objects">Get your FREE copy</a>
</div>
</div>
</div>
<h2 id="the-template-f1ec">The template<a class="headerlink" href="#the-template-f1ec" title="Permanent link">¶</a></h2><p>From now on I will make extensive use of the documentation at <a href="https://docs.getpelican.com/en/latest/themes.html#creating-themes">https://docs.getpelican.com/en/latest/themes.html#creating-themes</a>, so please be sure to have that page open in your browser.</p><p>For this tutorial I will use the template "Future Imperfect" by <a href="https://html5up.net/">HTML5 UP</a>. The template can be seen in action <a href="https://html5up.net/future-imperfect">at this page</a>, and you can download it using the button in the top right corner of the page itself.</p><p>Please consider supporting HTML UP even only with a Tweet. Being a content creator myself I know how important it can be to receive any type of feedback from readers/users.</p><p>Let's have a quick look at the template before we dive into the core of the post. We have a navbar at the top of the screen, with a link to the homepage, several links to specific pages, a search button, and a menu. In the body of the page there is a sidebar on the left and a preview of the articles on the right.</p><p>The sidebar contains the title and the subtitle of the blog, two lists of posts, the about section, and some social buttons. The first list of posts features image, title, date, and the avatar of the author, while the second list has just a small thumbnail, title, and date. Each post in the main list shows the full image, title, subtitle, name and avatar of the author, publication date, a preview of the content of the article, and a button that links the full version of the article. Last, tags are listed at the bottom right, just next to the number of likes and comments.</p><p>Just to be clear from the start, I won't implement everything we see here in my Pelican theme. I won't touch the navbar, and I won't discuss likes and comments, which require external systems when it comes to static sites. I will also simplify the sidebar, using only one list of posts. Moreover, I will not preview the articles in the main page, but print the full content.</p><p>Unzip the template archive in a subdirectory of the blog directory called <code>future-imperfect</code>. The archive doesn't contains a root folder, so you need to create it explicitly.</p><p>Enter the theme directory and change the layout of the files to follow <a href="https://docs.getpelican.com/en/latest/themes.html#structure">Pelican's requirements</a>:</p><div class="code"><div class="content"><div class="highlight"><pre>mv assets/ static
mv images/ static/
mkdir templates
mv *.html templates/
</pre></div> </div> </div><p>At this point edit the file <code>pelicanconf.py</code> in the main directory of the blog, adding the variable <code>THEME</code></p><div class="code"><div class="title"><code>pelicanconf.py</code></div><div class="content"><div class="highlight"><pre><span class="n">PATH</span> <span class="o">=</span> <span class="s1">'content'</span>
<span class="hll"><span class="n">THEME</span> <span class="o">=</span> <span class="s2">"future-imperfect"</span>
</span>
<span class="n">TIMEZONE</span> <span class="o">=</span> <span class="s1">'Europe/Paris'</span>
<span class="n">DEFAULT_LANG</span> <span class="o">=</span> <span class="s1">'en'</span>
</pre></div> </div> </div><p>If you refresh the blog page now you will see that the output doesn't even have a working style sheet, but don't worry, Pelican is still working correctly. We are overriding Pelican's output with the file <code>future-imperfect/templates/index.html</code>, which is supposed to be a Jinja template, but being part of the HTML5 template is just injecting static content. In particular, the CSS/JS assets are not loaded correctly, as you can see.</p><p>Let's learn the first piece of syntax adjusting the CSS and JS links, then, so that we can at least have a good output to look at. We need to change the path <code>assets/</code> with <code>{{ SITEURL }}/theme/</code></p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre><span class="cp"><!DOCTYPE HTML></span>
<span class="cm"><!--</span>
<span class="cm"> Future Imperfect by HTML5 UP</span>
<span class="cm"> html5up.net | @ajlkn</span>
<span class="cm"> Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)</span>
<span class="cm"> --></span>
<span class="p"><</span><span class="nt">html</span><span class="p">></span>
<span class="p"><</span><span class="nt">head</span><span class="p">></span>
<span class="p"><</span><span class="nt">title</span><span class="p">></span>Future Imperfect by HTML5 UP<span class="p"></</span><span class="nt">title</span><span class="p">></span>
<span class="p"><</span><span class="nt">meta</span> <span class="na">charset</span><span class="o">=</span><span class="s">"utf-8"</span> <span class="p">/></span>
<span class="p"><</span><span class="nt">meta</span> <span class="na">name</span><span class="o">=</span><span class="s">"viewport"</span> <span class="na">content</span><span class="o">=</span><span class="s">"width=device-width, initial-scale=1, user-scalable=no"</span> <span class="p">/></span>
<span class="hll"> <span class="p"><</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">"stylesheet"</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/css/main.css"</span> <span class="p">/></span>
</span> <span class="p"></</span><span class="nt">head</span><span class="p">></span>
[...]
<span class="hll"> <span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/js/jquery.min.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
</span><span class="hll"> <span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/js/browser.min.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
</span><span class="hll"> <span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/js/breakpoints.min.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
</span><span class="hll"> <span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/js/util.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
</span><span class="hll"> <span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/js/main.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
</span>
<span class="p"></</span><span class="nt">body</span><span class="p">></span>
<span class="p"></</span><span class="nt">html</span><span class="p">></span>
</pre></div> </div> </div><p>We also need to correctly link images. Change any occurrence of <code>images/</code> into <code>{{ SITEURL}}/theme/images/</code>, e.g.</p><div class="code"><div class="content"><div class="highlight"><pre> <span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"meta"</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"2015-11-01"</span><span class="p">></span>November 1, 2015<span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"name"</span><span class="p">></span>Jane Doe<span class="p"></</span><span class="nt">span</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
</span> <span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image featured"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/pic01.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
</pre></div> </div> </div><p>If you refresh the page after these changes you will see the template fully rendered (minus the images you saw in the demo, those are replaced by placeholders in the downloaded version).</p><p>A little trick: if you remove the comments at lines 177 and 487 you will get a nice recap of the graphical components of the template. I will not use them, so I removed lines 176-487, but remember that those cheat sheets can be very useful when trying to understand how a template works.</p><p>As I mentioned earlier, I also removed the third list of posts, as it doesn't add anything to what we will learn. You are clearly free to keep it and experiment with it.</p><h3 id="deep-dive-e364">Deep dive</h3><p>How does <code>{{ SITEURL }}/theme</code> work?</p><p>Pelican's <a href="https://docs.getpelican.com/en/latest/settings.html#themes">documentation on themes</a> says</p><div class="callout"><div class="content"><p><code>THEME_STATIC_DIR = 'theme'</code></p>
<p>Destination directory in the output path where Pelican will place the files collected from THEME<em>STATIC</em>PATHS. Default is theme.</p></div></div><p>the variable <code>THEME_STATIC_PATHS</code> is by default <code>static</code>, which is why we created that directory inside the theme.</p><p>As you can see all these paths are configurable, should you prefer different names.</p><h2 id="pelican-variables-db40">Pelican variables<a class="headerlink" href="#pelican-variables-db40" title="Permanent link">¶</a></h2><p>As I mentioned, we are currently overriding Pelican's output with a static template. What we want to do is to inject values known to Pelican into the template itself, be those static variables or more dynamic items like articles, tags, and images.</p><p>To do this, Pelican uses <a href="https://jinja.palletsprojects.com/en/2.11.x/">Jinja</a>, a widely adopted template engine written in Python. If you want to fully understand how to create Pelican themes, then, you need to learn Jinja. Don't worry, it's not complicated, and since Jinja uses Python you will catch up very quickly. I won't get into details about the Jinja syntax that I will use, please check out the <a href="https://jinja.palletsprojects.com/en/2.11.x/">Jinja documentation</a> if you have any doubts.</p><p>We actually already used Pelican's variables and Jinja templates when we prefixed links with <code>{{ SITEURL }}</code>. Aside from that, however, the first and simplest variable injection for our template are title and subtitle.</p><h3 id="title-dfde">Title</h3><p>The Pelican variable we are interested in is <code>SITENAME</code>, which has been initialised by the quickstart script as you can see in the configuration file</p><div class="code"><div class="title"><code>pelicanconf.py</code></div><div class="content"><div class="highlight"><pre><span class="n">SITENAME</span> <span class="o">=</span> <span class="s2">"The Analog Fox"</span>
</pre></div> </div> </div><p>We need to replace the static text with this variable three times: in the tag <code>&lt;title&gt;</code>, in the navigation bar and in the header at the top of the sidebar.</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre><span class="p"><</span><span class="nt">html</span><span class="p">></span>
<span class="p"><</span><span class="nt">head</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">title</span><span class="p">></span><span class="cp">{{</span> <span class="nv">SITENAME</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">title</span><span class="p">></span>
</span> <span class="p"><</span><span class="nt">meta</span> <span class="na">charset</span><span class="o">=</span><span class="s">"utf-8"</span> <span class="p">/></span>
<span class="p"><</span><span class="nt">meta</span> <span class="na">name</span><span class="o">=</span><span class="s">"viewport"</span> <span class="na">content</span><span class="o">=</span><span class="s">"width=device-width, initial-scale=1, user-scalable=no"</span> <span class="p">/></span>
<span class="p"><</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">"stylesheet"</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/css/main.css"</span> <span class="p">/></span>
<span class="p"></</span><span class="nt">head</span><span class="p">></span>
<span class="p"><</span><span class="nt">body</span> <span class="na">class</span><span class="o">=</span><span class="s">"is-preload"</span><span class="p">></span>
<span class="cm"><!-- Wrapper --></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"wrapper"</span><span class="p">></span>
<span class="cm"><!-- Header --></span>
<span class="p"><</span><span class="nt">header</span> <span class="na">id</span><span class="o">=</span><span class="s">"header"</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">h1</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"index.html"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">SITENAME</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h1</span><span class="p">></span>
</span> <span class="p"><</span><span class="nt">nav</span> <span class="na">class</span><span class="o">=</span><span class="s">"links"</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span>Lorem<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
[...]
<span class="cm"><!-- Sidebar --></span>
<span class="p"><</span><span class="nt">section</span> <span class="na">id</span><span class="o">=</span><span class="s">"sidebar"</span><span class="p">></span>
<span class="cm"><!-- Intro --></span>
<span class="p"><</span><span class="nt">section</span> <span class="na">id</span><span class="o">=</span><span class="s">"intro"</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"logo"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/logo.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">h2</span><span class="p">></span><span class="cp">{{</span> <span class="nv">SITENAME</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">h2</span><span class="p">></span>
</span> <span class="p"><</span><span class="nt">p</span><span class="p">></span>Another fine responsive site template by <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"http://html5up.net"</span><span class="p">></span>HTML5 UP<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><h3 id="subtitle-1f67">Subtitle</h3><p>Pelican provides support even for the subtitle, but that wasn't filled in by the setup script for us, so we need to create the variable in the configuration file</p><div class="code"><div class="title"><code>pelicanconf.py</code></div><div class="content"><div class="highlight"><pre><span class="n">SITENAME</span> <span class="o">=</span> <span class="s2">"The Analog Fox"</span>
<span class="n">SITESUBTITLE</span> <span class="o">=</span> <span class="s2">"A great blog about old stuff"</span>
</pre></div> </div> </div><p>Once this is done we can insert the variable at the top of the sidebar, just under the title</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="p"><</span><span class="nt">section</span> <span class="na">id</span><span class="o">=</span><span class="s">"intro"</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"logo"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/logo.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">></span><span class="cp">{{</span> <span class="nv">SITENAME</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">h2</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">SITESUBTITLE</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
</span> <span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><p>Marvellous! Now the page should show the title of the blog in the window header, announcing to the world the The Analog Fox is ready to take over the world of vintage!</p><p>OK, I might be a bit overexcited, but I love when plans come together ;)</p><h3 id="deep-dive-e364">Deep dive</h3><p>Pelican passes the whole configuration file to the template, together with the parsed content of the site itself, so you are free to use any variable, should you need them, or to introduce new ones (which we will do in the next section).</p><p>For now, just to familiarise with the concept, you might try to add <code>TIMEZONE</code> under the subtitle</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">></span><span class="cp">{{</span> <span class="nv">SITENAME</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">SITESUBTITLE</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">TIMEZONE</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
</pre></div> </div> </div><p>I don't think this specific change is really useful, but it's good to remember that all those variables are available.</p><h2 id="social-buttons-d456">Social buttons<a class="headerlink" href="#social-buttons-d456" title="Permanent link">¶</a></h2><p>The template has a section for social buttons under the sidebar, and this is a great use case for a bit of advanced usage of the configuration file.</p><p>Pelican has a native support for social links, as you can see from the <code>SOCIAL</code> variable in <code>pelicanconf.py</code>. For the sake of showing you that you are free to define custom variables in that file and use them I will however ignore it and go with something richer. The template uses nice icons to represent the links, so I'd like to include that information.</p><p>The section of the template that renders those buttons is</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Footer --></span>
<span class="p"><</span><span class="nt">section</span> <span class="na">id</span><span class="o">=</span><span class="s">"footer"</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"icons"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"icon brands fa-twitter"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"label"</span><span class="p">></span>Twitter<span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"icon brands fa-facebook-f"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"label"</span><span class="p">></span>Facebook<span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"icon brands fa-instagram"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"label"</span><span class="p">></span>Instagram<span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"icon solid fa-rss"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"label"</span><span class="p">></span>RSS<span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"icon solid fa-envelope"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"label"</span><span class="p">></span>Email<span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span> <span class="na">class</span><span class="o">=</span><span class="s">"copyright"</span><span class="p">></span><span class="ni">&copy;</span> Untitled. Design: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"http://html5up.net"</span><span class="p">></span>HTML5 UP<span class="p"></</span><span class="nt">a</span><span class="p">></span>. Images: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"http://unsplash.com"</span><span class="p">></span>Unsplash<span class="p"></</span><span class="nt">a</span><span class="p">></span>.<span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><p>Lists are one of the most common patterns when writing templates, as they usually become just a simple for loop. let's start writing down the data, then we will learn how to render the buttons.</p><p>As I mentioned, I created a new variable <code>CONTACTS</code></p><div class="code"><div class="title"><code>pelicanconf.py</code></div><div class="content"><div class="highlight"><pre><span class="c1"># Social widget</span>
<span class="n">SOCIAL</span> <span class="o">=</span> <span class="p">(</span>
<span class="p">(</span><span class="s2">"You can add links in your config file"</span><span class="p">,</span> <span class="s2">"#"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"Another social link"</span><span class="p">,</span> <span class="s2">"#"</span><span class="p">),</span>
<span class="p">)</span>
<span class="hll"><span class="n">CONTACTS</span> <span class="o">=</span> <span class="p">[</span>
</span><span class="hll"> <span class="p">(</span><span class="s2">"Twitter"</span><span class="p">,</span> <span class="s2">"twitter"</span><span class="p">,</span> <span class="s2">"https://twitter.com/theanalogfox"</span><span class="p">),</span>
</span><span class="hll"> <span class="p">(</span><span class="s2">"Facebook"</span><span class="p">,</span> <span class="s2">"facebook-f"</span><span class="p">,</span> <span class="s2">"https://facebook.com/theanalogfox"</span><span class="p">),</span>
</span><span class="hll"> <span class="p">(</span><span class="s2">"Instagram"</span><span class="p">,</span> <span class="s2">"instagram"</span><span class="p">,</span> <span class="s2">"https://www.instagram.com/theanalogfox/"</span><span class="p">),</span>
</span><span class="hll"> <span class="p">(</span><span class="s2">"Email"</span><span class="p">,</span> <span class="s2">"envelope"</span><span class="p">,</span> <span class="s2">"info@theanalogfox.com"</span><span class="p">),</span>
</span><span class="hll"><span class="p">]</span>
</span>
<span class="n">DEFAULT_PAGINATION</span> <span class="o">=</span> <span class="mi">3</span>
</pre></div> </div> </div><p>that is a list of tuples, each one including the title of the button, the name of the icon (Font Awesome), and the link itself. Now we can replace the snippet of code above with this</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Footer --></span>
<span class="p"><</span><span class="nt">section</span> <span class="na">id</span><span class="o">=</span><span class="s">"footer"</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"icons"</span><span class="p">></span>
<span class="hll"> <span class="cp">{%</span> <span class="k">for</span> <span class="nv">name</span><span class="o">,</span> <span class="nv">icon</span><span class="o">,</span> <span class="nv">link</span> <span class="k">in</span> <span class="nv">CONTACTS</span> <span class="cp">%}</span>
</span><span class="hll"> <span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">link</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"icon brands fa-</span><span class="cp">{{</span> <span class="nv">icon</span> <span class="cp">}}</span><span class="s">"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"label"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">name</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">span</span><span class="p">></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
</span><span class="hll"> <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</span> <span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span> <span class="na">class</span><span class="o">=</span><span class="s">"copyright"</span><span class="p">></span><span class="ni">&copy;</span> Untitled. Design: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"http://html5up.net"</span><span class="p">></span>HTML5 UP<span class="p"></</span><span class="nt">a</span><span class="p">></span>. Images: <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"http://unsplash.com"</span><span class="p">></span>Unsplash<span class="p"></</span><span class="nt">a</span><span class="p">></span>.<span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><p>As you can see, the core of the snippet is a <code>for</code> loop that uses Python's unpacking to assign <code>name</code>, <code>icon</code>, and <code>link</code>. The variables are then used directly in the HTML as we did before. Remember that Jinja doesn't understand HTML, it just blindly replaces the variables in a text file, which allows us to perform nice tricks like <code>fa-{{ icon }}</code> to use the right icon for each social button.</p><h2 id="articles-16fa">Articles<a class="headerlink" href="#articles-16fa" title="Permanent link">¶</a></h2><p>Now that we introduced loops and variables we have all the tools we need to work on the two lists of articles. Let's first change the list in the main body of the page, the one in the sidebar will then receive the very same treatment.</p><p>First of all, I reduced the static list of posts to a single one</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Main --></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"main"</span><span class="p">></span>
<span class="cm"><!-- Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"title"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span>Magna sed adipiscing<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span>Lorem ipsum dolor amet nullam consequat etiam feugiat<span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"meta"</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"2015-11-01"</span><span class="p">></span>November 1, 2015<span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"name"</span><span class="p">></span>Jane Doe<span class="p"></</span><span class="nt">span</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image featured"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/pic01.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span>Mauris neque quam, fermentum ut nisl vitae, convallis maximus nisl. Sed mattis nunc id lorem euismod placerat. Vivamus porttitor magna enim, ac accumsan tortor cursus at. Phasellus sed ultricies mi non congue ullam corper. Praesent tincidunt sed tellus ut rutrum. Sed vitae justo condimentum, porta lectus vitae, ultricies congue gravida diam non fringilla.<span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"><</span><span class="nt">footer</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large"</span><span class="p">></span>Continue Reading<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"stats"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span>General<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"icon solid fa-heart"</span><span class="p">></span>28<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"icon solid fa-comment"</span><span class="p">></span>128<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">footer</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="cm"><!-- Pagination --></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions pagination"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">""</span> <span class="na">class</span><span class="o">=</span><span class="s">"disabled button large previous"</span><span class="p">></span>Previous Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large next"</span><span class="p">></span>Next Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div> </div> </div><p>Please note that your content will be slightly different as it has been randomly generated.</p><p>The list of Pelican variables we can access is available at <a href="https://docs.getpelican.com/en/latest/themes.html#index-html">https://docs.getpelican.com/en/latest/themes.html#index-html</a> (variables for the page <code>index.html</code>) and <a href="https://docs.getpelican.com/en/latest/themes.html#article">https://docs.getpelican.com/en/latest/themes.html#article</a> (attributes of <code>Article</code> objects).</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre><span class="hll"> <span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">articles</span> <span class="cp">%}</span>
</span> <span class="cm"><!-- Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"title"</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">h2</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h2</span><span class="p">></span>
</span><span class="hll"> <span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.summary</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
</span> <span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"meta"</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
</span><span class="hll"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"name"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.author</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">span</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
</span> <span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image featured"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/pic01.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="hll"> <span class="cp">{{</span> <span class="nv">article.content</span> <span class="cp">}}</span>
</span> <span class="p"><</span><span class="nt">footer</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large"</span><span class="p">></span>Continue Reading<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"stats"</span><span class="p">></span>
<span class="hll"> <span class="cp">{%</span> <span class="k">for</span> <span class="nv">tag</span> <span class="k">in</span> <span class="nv">article.tags</span> <span class="cp">%}</span>
</span><span class="hll"> <span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">tag.name</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
</span><span class="hll"> <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</span> <span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">footer</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="hll"> <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</pre></div> </div> </div><p>As you can see we can just loop over the page variable <code>articles</code> and read the attributes of object just like we usually do in Python, for example with <code>{{ article.title }}</code> or <code>{{ article.summary }}</code>.</p><p>Jinja filters are very powerful, and as you see I used them twice with dates to give them different formats. One for the internal representation of time <code>{{ article.date | strftime('%Y-%m-%d') }}</code> and one is the more visually pleasant (<code>{{ article.date | strftime('%b %-d, %Y') }}</code>). I don't normally use the American date format, but as the template did I kept it as a good example of what you can do with Jinja filters.</p><p>Last, you can nest for loops in other for loops, as I did with tags. You can see the internal structure of tags <a href="https://docs.getpelican.com/en/latest/themes.html#author-category-tag">in the documentation</a>. Please note that the string representation of tags (and other objects in Pelican) is the attribute <code>name</code>, so we might write</p><div class="code"><div class="content"><div class="highlight"><pre> <span class="cp">{%</span> <span class="k">for</span> <span class="nv">tag</span> <span class="k">in</span> <span class="nv">article.tags</span> <span class="cp">%}</span>
<span class="hll"> <span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">tag</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
</span> <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</pre></div> </div> </div><p>and it would return the same output.</p><p>A note about the content of the article. As you can see <code>{{ article.content }}</code> prints the full article, so if you want to print a preview you need to truncate it. Unfortunately you can't just write something like <code>{{ article.content[:600] }}</code> to print 600 characters. Remember that Jinja works on the output of the readers already, which means that <code>article. content</code> is already HTML, and if you arbitrarily truncate it you leave some tags open, which disrupts the rendering of the page.</p><p>At the end of the post I will show you how you can easily solve this in Pelican, once we have a dedicated page for each article.</p><h2 id="pagination-1e5d">Pagination<a class="headerlink" href="#pagination-1e5d" title="Permanent link">¶</a></h2><p>What we did in the previous section prints all the articles in the blog on the same page. This is clearly not acceptable as the number of articles increases, and the standard solution for this is <em>pagination</em>.</p><p>Pelican fully supports it, and if you remember we set it up when we run <code>pelican-quickstart</code>. You can see the current number of articles per page in <code>pelicanconf.py</code></p><div class="code"><div class="content"><div class="highlight"><pre><span class="n">DEFAULT_PAGINATION</span> <span class="o">=</span> <span class="mi">3</span>
</pre></div> </div> </div><p>To leverage pagination we first need to replace the variable <code>articles</code> with <code>articles_page.object_list</code></p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre><span class="hll"> <span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">articles_page.object_list</span> <span class="cp">%}</span>
</span> <span class="cm"><!-- Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"title"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.summary</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
</pre></div> </div> </div><p>If you render the page in the browser now you'll see that it shows only the last 3 posts, which corresponds to the value of <code>DEFAULT_PAGINATION</code>. If you want you can try to change it and see it affecting the page.</p><p>To use pagination we also need to configure navigation buttons. The template already includes them after all the articles in the main body.</p><div class="code"><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Pagination --></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions pagination"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">""</span> <span class="na">class</span><span class="o">=</span><span class="s">"disabled button large previous"</span><span class="p">></span>Previous Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large next"</span><span class="p">></span>Next Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
</pre></div> </div> </div><p>We have three different cases when it comes to pagination. The first page should grey out or remove the "Previous page" button, the last page should do the same with the "Next page" button, and any page between the two should show both.</p><p>We can achieve it with the following code</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Pagination --></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions pagination"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">articles_page.has_previous</span><span class="o">()</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"/</span><span class="cp">{{</span> <span class="nv">articles_previous_page.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large previous"</span><span class="p">></span>Previous Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">else</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">""</span> <span class="na">class</span><span class="o">=</span><span class="s">"disabled button large previous"</span><span class="p">></span>Previous Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">articles_page.has_next</span><span class="o">()</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"/</span><span class="cp">{{</span> <span class="nv">articles_next_page.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large next"</span><span class="p">></span>Next Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">else</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"disabled button large next"</span><span class="p">></span>Next Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
</pre></div> </div> </div><p>The two functions <code>articles_page.has_previous()</code> and <code>articles_page.has_next()</code> can be used to know if there are pages before of after the current one, and if not we can use the class <code>disabled</code> to grey out the button. The link to the previous or next page is provided by <code>articles_previous_page.url</code> and <code>articles_next_page.url</code> respectively. Again, remember that you can learn everything about all these variables reading <a href="https://docs.getpelican.com/en/latest/themes.html">Pelican's documentation on themes</a>.</p><p>Render the page in the browser and you will see that the "Next page" button leads to <a href="http://localhost:8000/index2.html">http://localhost:8000/index2.html</a>, which is the second page of articles. Indeed, if you click it, you will see articles from 17 to 15, and so on until the last page of articles <a href="http://localhost:8001/index7.html">http://localhost:8001/index7.html</a> that contains the first and the secodn articles of the blog (if you generated 20 articles at the beginning as I did).</p><h2 id="slicing-6582">Slicing<a class="headerlink" href="#slicing-6582" title="Permanent link">¶</a></h2><p>The sidebar is usually the best place to show a fixed set of posts like latest ones. We can easily achieve this slicing the list of articles. To do this let's first reduce the number of mini posts to one, so that we can introduce a loop</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Mini Posts --></span>
<span class="p"><</span><span class="nt">section</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-posts"</span><span class="p">></span>
<span class="cm"><!-- Mini Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">h3</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span>Vitae sed condimentum<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"2015-10-20"</span><span class="p">></span>October 20, 2015<span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/pic04.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><p>We can show the last 4 articles with this simple sintax</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Mini Posts --></span>
<span class="p"><</span><span class="nt">section</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-posts"</span><span class="p">></span>
<span class="hll"> <span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">articles</span><span class="o">[:</span><span class="m">4</span><span class="o">]</span> <span class="cp">%}</span>
</span> <span class="cm"><!-- Mini Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">h3</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span>Vitae sed condimentum<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"2015-10-20"</span><span class="p">></span>October 20, 2015<span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/pic04.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="hll"> <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><p>which will print the same static article 4 times because we are not using Pelican's variables yet. Applying the same changes we introduced for the main list of articles we finally get</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Mini Posts --></span>
<span class="p"><</span><span class="nt">section</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-posts"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">articles</span><span class="o">[:</span><span class="m">4</span><span class="o">]</span> <span class="cp">%}</span>
<span class="cm"><!-- Mini Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">h3</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
</span><span class="hll"> <span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
</span> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/pic04.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><p>And now you will see the proper titles and dates. Please note that this loop depends on <code>articles</code>, which doesn't change from page to page, so this list will be immutable across the blog.</p><h2 id="pictures-436b">Pictures<a class="headerlink" href="#pictures-436b" title="Permanent link">¶</a></h2><p>The script that created demo articles downloaded an image for each article, that can be used as featured image. There are many way to manage images in a website and I won't dive into that particular subject here. I will only show you a basic way to serve images that are not static, but part of the content.</p><p>The images are stored in <code>content/images</code> and this is also an arbitrary decision. The only thing you need to keep in mind is that Pelican's root is usually set in the directory <code>content</code>, so if you place files elsewhere it might be complicated to reach them.</p><p>Through the automated script that we used to generate content we wrote a specific metadata in each article, with the name of the relative image. For example</p><div class="code"><div class="title"><code>content/post01.markdown</code></div><div class="content"><div class="highlight"><pre>Title: A sample article 01
Date: 2021-03-01
Category: News
Tags: tag6,tag11,tag8
<span class="hll">Image: post01.jpg
</span>Summary: Summary of post 01
[...]
</pre></div> </div> </div><p>This shows you that you can add whatever metadata you want to your posts and have them loaded into the object <code>article</code>. To show the image we just need to load the correct file instead of the placeholder, both in the main list</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">articles_page.object_list</span> <span class="cp">%}</span>
<span class="cm"><!-- Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"title"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.summary</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"meta"</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"name"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.author</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">span</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image featured"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"images/</span><span class="cp">{{</span> <span class="nv">article.image</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
</span> <span class="cp">{{</span> <span class="nv">article.content</span> <span class="cp">}}</span>
<span class="p"><</span><span class="nt">footer</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large"</span><span class="p">></span>Continue Reading<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"stats"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">tag</span> <span class="k">in</span> <span class="nv">article.tags</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">tag.name</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">footer</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</pre></div> </div> </div><p>and in the sidebar</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Mini Posts --></span>
<span class="p"><</span><span class="nt">section</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-posts"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">articles</span><span class="o">[:</span><span class="m">4</span><span class="o">]</span> <span class="cp">%}</span>
<span class="cm"><!-- Mini Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">h3</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"images/</span><span class="cp">{{</span> <span class="nv">article.image</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
</span> <span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><p>Now the page is definitely more appealing!</p><h2 id="advanced-techniques-extend-and-include-3d5d">Advanced techniques: extend and include<a class="headerlink" href="#advanced-techniques-extend-and-include-3d5d" title="Permanent link">¶</a></h2><p>As in everything related to computer programming (and not only) you will soon discover that you are repeating yourself, and one of the top design advice that you should follow says: don't do it.</p><p>Jinja templates provide two tags to help you reduce duplicated code, namely <code>extend</code> and <code>include</code>. To see how they work let's focus our attention on the page of a specific article. When we click on an article we would like to go to a dedicated page, while all links at the moment load the same static page <code>single.html</code>.</p><p>The article page, however, won't be that different from the front page we just created. It might be, as you are free to completely change the style, but in general some elements will be in common, for example the navigation, the sidebar, and the footer.</p><p>In the following section I will show you how to use the Jinja tags <code>extends</code> and <code>include</code> to reuse parts of your theme.</p><h3 id="extends-16a0">Extends</h3><p>Since we want to reuse some parts of the page we need to move them to a "common space". Create a new file called <code>future-imperfect/templates/base.html</code> and move the whole content of <code>index.html</code> into it. Then write this single statement in the now empty <code>index.html</code></p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">"base.html"</span> <span class="cp">%}</span>
</pre></div> </div> </div><p>What we did is to tell Jinja that everything we do in <code>index.html</code> should happen on top of <code>base.html</code> (we'll soon discover the meaning of this "on top"). For now you might think about it as <code>index.html</code> copying the content of <code>base.html</code>.</p><p>The problem with this setup is that <code>base.html</code> doesn't have access to the variables that <code>index.html</code> has access to, as <code>base.html</code> is an arbitrary file and not something known to Pelican. Indeed the command <code>pelican -lr</code> that you are running in a terminal should give you this error</p><div class="code"><div class="content"><div class="highlight"><pre>WARNING: Caught exception:
| "'articles_page' is undefined".
</pre></div> </div> </div><p>Since that is something only <code>index.html</code> can provide we need to do something more than just copying the content of <code>base.html</code>, we need to also fill in some parts, which is exactly what you can do with <code>block</code> (see <a href="https://jinja.palletsprojects.com/en/2.11.x/templates/#template-inheritance">Jinja's documentation on template inheritance</a>).</p><p>Grab the whole content of the <code>&lt;div id="main"&gt;</code> and move it in <code>index.html</code> wrapped in <code>{% block content %}</code></p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">"base.html"</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">articles_page.object_list</span> <span class="cp">%}</span>
<span class="cm"><!-- Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"title"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.summary</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"meta"</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"name"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.author</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">span</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image featured"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"images/</span><span class="cp">{{</span> <span class="nv">article.image</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="cp">{{</span> <span class="nv">article.content</span> <span class="cp">}}</span>
<span class="p"><</span><span class="nt">footer</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large"</span><span class="p">></span>Continue Reading<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"stats"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">tag</span> <span class="k">in</span> <span class="nv">article.tags</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">tag.name</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">footer</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="cm"><!-- Pagination --></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions pagination"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">articles_page.has_previous</span><span class="o">()</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"/</span><span class="cp">{{</span> <span class="nv">articles_previous_page.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large previous"</span><span class="p">></span>Previous Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">else</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">""</span> <span class="na">class</span><span class="o">=</span><span class="s">"disabled button large previous"</span><span class="p">></span>Previous Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">articles_page.has_next</span><span class="o">()</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"/</span><span class="cp">{{</span> <span class="nv">articles_next_page.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large next"</span><span class="p">></span>Next Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">else</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"disabled button large next"</span><span class="p">></span>Next Page<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div> </div> </div><p>At the same time fill the empty space you left in <code>base.html</code> with a call for that block</p><div class="code"><div class="title"><code>future-imperfect/templates/base.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Main --></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"main"</span><span class="p">></span>
<span class="hll"> <span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</span> <span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div> </div> </div><p>When this is done, reload the page and... nothing should have changed. Sorry, but this is one of those things that happen behind the scenes and that do not have any immediate benefit. However, Pelican shouldn't give you any error on the command line, which is comforting.</p><p>To see the benefit of what we did let's move on and create the page for the single article, <code>article.html</code></p><div class="code"><div class="title"><code>future-imperfect/templates/article.html</code></div><div class="content"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">"base.html"</span> <span class="cp">%}</span>
</pre></div> </div> </div><p>As we said before <code>base.html</code> is supposed to be the common part of all pages, so <code>article.html</code> should start from that as well. To check how that page looks like now let's update the links from the articles in the main body. Open <code>index.html</code> and replace the URLs of each article</p><div class="code"><div class="title"><code>future-imperfect/templates/index.html</code></div><div class="content"><div class="highlight"><pre><span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"title"</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">h2</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h2</span><span class="p">></span>
</span> <span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.summary</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"meta"</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"name"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.author</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">span</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image featured"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"images/</span><span class="cp">{{</span> <span class="nv">article.image</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
</span> <span class="cp">{{</span> <span class="nv">article.content</span> <span class="cp">}}</span>
<span class="p"><</span><span class="nt">footer</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions"</span><span class="p">></span>
<span class="hll"> <span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large"</span><span class="p">></span>Continue Reading<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
</span> <span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"stats"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">tag</span> <span class="k">in</span> <span class="nv">article.tags</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">tag.name</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">footer</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
</pre></div> </div> </div><p>Now if you render the front page and click on the title of a post in the main column you will end up in the page dedicated to it, which has a worrying empty central column! Well, after all <code>article.html</code> extends <code>base.html</code> but doesn't provide anything for the block <code>content</code>, so let's fix this</p><div class="code"><div class="title"><code>future-imperfect/templates/article.html</code></div><div class="content"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">"base.html"</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}</span>
<span class="cm"><!-- Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"title"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.summary</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"meta"</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"name"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.author</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">span</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image featured"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"images/</span><span class="cp">{{</span> <span class="nv">article.image</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="cp">{{</span> <span class="nv">article.content</span> <span class="cp">}}</span>
<span class="p"><</span><span class="nt">footer</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large"</span><span class="p">></span>Continue Reading<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"stats"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">tag</span> <span class="k">in</span> <span class="nv">article.tags</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">tag.name</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">footer</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div> </div> </div><p>I copied the content of the block from the loop in <code>index.html</code>. In this simple example they have the same code, but in a real production environment you might want to differentiate them. As you can see <code>article.html</code> provides the variable <code>article</code> out of the box. Please note that the page of each article doesn't show the pagination buttons, as they are not part of <code>article.html</code>.</p><h3 id="include-fe56">Include</h3><p>When you write a theme there are often snippets of code that you might need to repeat in different parts of the whole site. The sidebar is typically a good example of a collection of such snippets, like the "About" section or the list of latest posts that you might want to reuse somewhere else.</p><p>Jinja provides the tag <code>include</code> that allows you to easily inject the content of another template file into the current one. Let's see how it works moving the list of latest posts to a separate file.</p><p>Move the content of the mini posts section from <code>base.html</code> to a file called <code>templates/includes/latest_posts.html</code></p><div class="code"><div class="title"><code>templates/includes/latest_posts.html</code></div><div class="content"><div class="highlight"><pre><span class="cm"><!-- Mini Posts --></span>
<span class="p"><</span><span class="nt">section</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-posts"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">articles</span><span class="o">[:</span><span class="m">4</span><span class="o">]</span> <span class="cp">%}</span>
<span class="cm"><!-- Mini Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"mini-post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">h3</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h3</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"single.html"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"images/</span><span class="cp">{{</span> <span class="nv">article.image</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><p>And replace it with a call to <code>include</code> in <code>base.html</code></p><div class="code"><div class="title"><code>templates/includes/base.html</code></div><div class="content"><div class="highlight"><pre> <span class="cm"><!-- Intro --></span>
<span class="p"><</span><span class="nt">section</span> <span class="na">id</span><span class="o">=</span><span class="s">"intro"</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"logo"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/logo.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">></span><span class="cp">{{</span> <span class="nv">SITENAME</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span><span class="cp">{{</span> <span class="nv">SITESUBTITLE</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
<span class="hll"> <span class="cp">{%</span> <span class="k">include</span> <span class="s1">'includes/latest_posts.html'</span> <span class="cp">%}</span>
</span>
<span class="cm"><!-- About --></span>
<span class="p"><</span><span class="nt">section</span> <span class="na">class</span><span class="o">=</span><span class="s">"blurb"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">></span>About<span class="p"></</span><span class="nt">h2</span><span class="p">></span>
<span class="p"><</span><span class="nt">p</span><span class="p">></span>Mauris neque quam, fermentum ut nisl vitae, convallis maximus nisl. Sed mattis nunc id lorem euismod amet placerat. Vivamus porttitor magna enim, ac accumsan tortor cursus at phasellus sed ultricies.<span class="p"></</span><span class="nt">p</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button"</span><span class="p">></span>Learn More<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">section</span><span class="p">></span>
</pre></div> </div> </div><p>Again, reloading the page won't show anything different, but now we isolated a piece of code that shows the latest posts and we can reuse it in another part of the site which is not the sidebar. You can find the documentation of <code>include</code> at <a href="https://jinja.palletsprojects.com/en/2.11.x/templates/#include">https://jinja.palletsprojects.com/en/2.11.x/templates/#include</a>.</p><h3 id="deep-dive-e364">Deep dive</h3><p>What is the difference between <code>extends</code> and <code>include</code>? Which one shall you use?</p><p>The difference between extending and including is the same difference that lies between a <em>framework</em> and a <em>library</em> in the context of programming languages. A framework provides the bulk of the system, and we provide the code for specific operations, while a library provides specific code that we need to put in a bigger picture. This about a Web framework like Django or Flask: they already "work" in the background, but until you provide the endpoints they don't do anything specific. At the same time, when you need to encrypt a password you import a library and use its functions.</p><p>In the same way <code>extends</code> means that another template is providing the main part of the page and that we provide the content of the blocks. When we use <code>include</code> the opposite happens, we get a specific snippet of code and insert it in some wider context.</p><p>As there are no limitations to the number of lines contained in a block or in an imported snippet, there is a certain amount of overlap between the two. Sometimes it might not be immediately clear which one to use, but in the vast majority of cases it should be straightforward.</p><h2 id="preview-articles-5d7d">Preview articles<a class="headerlink" href="#preview-articles-5d7d" title="Permanent link">¶</a></h2><p>Earlier in the post I mentioned a way to create the preview of articles, so now that we have two different pages it makes sense to implement that.</p><p>As I said before the preview of an article has to be created before the content is converted into HTML, or we might leave open tags. Pelican supports this mechanism out of the box, through the <code>summary</code> metadata. If you specify a summary (as I did through the random generation script), Pelican won't do anything, but id the summary is not present it will be initialised with a preview of the article.</p><p>The two variables involved in this process are <code>SUMMARY_MAX_LENGTH</code> and <code>SUMMARY_END_SUFFIX</code> (see <a href="https://docs.getpelican.com/en/latest/settings.html">the documentation</a>), but we can accept the default values for our little project.</p><p>To see the summary in action let's open the last post (<code>post20.markdown</code>) and remove the line <code>Summary: Summary of post 20</code>. Then we need to adjust the code of the page to properly display the summary as content.</p><div class="code"><div class="title"><code>templates/includes/index.html</code></div><div class="content"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">for</span> <span class="nv">article</span> <span class="k">in</span> <span class="nv">articles_page.object_list</span> <span class="cp">%}</span>
<span class="cm"><!-- Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"title"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h2</span><span class="p">></span>
<span class="hll">
</span> <span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"meta"</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"name"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.author</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">span</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span><span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image featured"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"images/</span><span class="cp">{{</span> <span class="nv">article.image</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="hll"> <span class="cp">{{</span> <span class="nv">article.summary</span> <span class="cp">}}</span>
</span> <span class="p"><</span><span class="nt">footer</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large"</span><span class="p">></span>Continue Reading<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"stats"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">tag</span> <span class="k">in</span> <span class="nv">article.tags</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">tag.name</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">footer</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</pre></div> </div> </div><p>In the article page, instead we want the content to be displayed, so we just need to remove the summary (which at this point is not a single line that can be easily displayed under the title.</p><div class="code"><div class="title"><code>templates/includes/article.html</code></div><div class="content"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}</span>
<span class="cm"><!-- Post --></span>
<span class="p"><</span><span class="nt">article</span> <span class="na">class</span><span class="o">=</span><span class="s">"post"</span><span class="p">></span>
<span class="p"><</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"title"</span><span class="p">></span>
<span class="p"><</span><span class="nt">h2</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.title</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">h2</span><span class="p">></span>
<span class="hll">
</span> <span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"meta"</span><span class="p">></span>
<span class="p"><</span><span class="nt">time</span> <span class="na">class</span><span class="o">=</span><span class="s">"published"</span> <span class="na">datetime</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%Y-%m-%d'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.date</span> <span class="o">|</span> <span class="nf">strftime</span><span class="o">(</span><span class="s1">'%b %-d, %Y'</span><span class="o">)</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">time</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span> <span class="na">class</span><span class="o">=</span><span class="s">"author"</span><span class="p">><</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">"name"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">article.author</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">span</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">SITEURL</span> <span class="cp">}}</span><span class="s">/theme/images/avatar.jpg"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">header</span><span class="p">></span>
<span class="p"><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"image featured"</span><span class="p">><</span><span class="nt">img</span> <span class="na">src</span><span class="o">=</span><span class="s">"images/</span><span class="cp">{{</span> <span class="nv">article.image</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">alt</span><span class="o">=</span><span class="s">""</span> <span class="p">/></</span><span class="nt">a</span><span class="p">></span>
<span class="cp">{{</span> <span class="nv">article.content</span> <span class="cp">}}</span>
<span class="p"><</span><span class="nt">footer</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"actions"</span><span class="p">></span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">article.url</span> <span class="cp">}}</span><span class="s">"</span> <span class="na">class</span><span class="o">=</span><span class="s">"button large"</span><span class="p">></span>Continue Reading<span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"><</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">"stats"</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">tag</span> <span class="k">in</span> <span class="nv">article.tags</span> <span class="cp">%}</span>
<span class="p"><</span><span class="nt">li</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"#"</span><span class="p">></span><span class="cp">{{</span> <span class="nv">tag.name</span> <span class="cp">}}</span><span class="p"></</span><span class="nt">a</span><span class="p">></</span><span class="nt">li</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p"></</span><span class="nt">ul</span><span class="p">></span>
<span class="p"></</span><span class="nt">footer</span><span class="p">></span>
<span class="p"></</span><span class="nt">article</span><span class="p">></span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div> </div> </div>
<div class="advertisement">
<a href="https://www.thedigitalcat.academy/freebie-first-class-objects">
<img src="/images/first-class-objects/cover.jpg" />
</a>
<div class="body">
<h2 id="first-class-objects-in-python-fffa">First-class objects in Python<a class="headerlink" href="#first-class-objects-in-python-fffa" title="Permanent link">¶</a></h2>
<p>Higher-order functions, wrappers, and factories</p>
<p>Learn all you need to know to understand first-class citizenship in Python, the gateway to grasp how decorators work and how functional programming can supercharge your code.</p>
<div class="actions">
<a class="action" href="https://www.thedigitalcat.academy/freebie-first-class-objects">Get your FREE copy</a>
</div>
</div>
</div>
<h2 id="next-steps-5961">Next steps<a class="headerlink" href="#next-steps-5961" title="Permanent link">¶</a></h2><p>As I promised, I showed you how to use Jinja tags and Pelican variables, and we went from a purely static template to a rich dynamic one. There are several things that you might want to investigate and implement now:</p><ul><li>Both <code>index.html</code> and <code>article.html</code> contain a great amount of common code (the part that displays the article). Try to work on that to isolate the shared code and remove the duplication. Remember that they are not exactly the same, so you might want to investigate the tag <code>with</code> provided by Jinja.</li><li>Tags and categories. Pelican creates pages with all the articles that belong to a specific category or tag, and they work exactly like the index page. The documentation of the variables available in those pages can be found at <a href="https://docs.getpelican.com/en/latest/themes.html#category-html">https://docs.getpelican.com/en/latest/themes.html#category-html</a> and <a href="https://docs.getpelican.com/en/latest/themes.html#tag-html">https://docs.getpelican.com/en/latest/themes.html#tag-html</a>. You should try to create a page that lists all the articles with a certain tag and connect it to the tag button at the end of each article.</li><li>Pelican can create pages of content (as opposed to articles), and you might want to show those in the navigation bar. You can find the documentation of the <code>Page</code> objects at <a href="https://docs.getpelican.com/en/latest/themes.html#page">https://docs.getpelican.com/en/latest/themes.html#page</a>. Create an "About me" page and link it there.</li><li>If you want to publish the website you probably want to minify assets to save bandwidth and reduce the loading time. Have a look at <code>webassets</code> (<a href="https://github.com/pelican-plugins/webassets">https://github.com/pelican-plugins/webassets</a>), a plugin that makes assets management as easy as pie.</li><li>Speaking of plugins, Pelican has a huge number of them. The developers are in the process of transitioning them to a new better format, so you will find the main plugins at <a href="https://github.com/pelican-plugins">https://github.com/pelican-plugins</a> and the rest at <a href="https://github.com/getpelican/pelican-plugins">https://github.com/getpelican/pelican-plugins</a>. I recommend having a look at <code>sitemap</code>, which is very easy to setup and provides an important tool for search engines to discover your site.</li><li>When it comes to deploying the static website you should definitely read <a href="https://docs.getpelican.com/en/latest/publish.html">Pelican's documentation</a>, as the management scripts support several backends.</li></ul><p>Last, but hopefully not least, the code of this blog is public and can be found at <a href="https://github.com/TheDigitalCatOnline/blog_source">https://github.com/TheDigitalCatOnline/blog_source</a>. While the overall setup contains a bit of legacy code (I started a while ago and many things have changed in the meanwhile), the theme <code>editorial</code> is pretty new, so feel free to have a look at it and to get inspired (<a href="https://github.com/TheDigitalCatOnline/blog_source/tree/master/editorial">https://github.com/TheDigitalCatOnline/blog_source/tree/master/editorial</a>).</p><p>I hope this was useful. Remember that Pelican is open source, and you can always get in touch with the maintainers to ask questions or to submit enhancements. Also remember to drop a line on Twitter to the author of any template you will use (thanks are always welcome) and to link to the source on the website. Happy blogging!</p><h2 id="feedback-d845">Feedback<a class="headerlink" href="#feedback-d845" title="Permanent link">¶</a></h2><p>Feel free to reach me on <a href="https://twitter.com/thedigicat">Twitter</a> if you have questions. The <a href="https://github.com/TheDigitalCatOnline/blog_source/issues">GitHub issues</a> page is the best place to submit corrections.</p>Emacs Configuration for Python/JavaScript, Terraform and blogging2020-07-18T15:30:00+01:002020-07-18T15:30:00+01:00Leonardo Giordanitag:www.thedigitalcatonline.com,2020-07-18:/blog/2020/07/18/emacs-configuration-for-python-javascript-terraform-and-blogging/<p>A step-by-step analysis of the Emacs configuration that I use to write Python/JavaScript/Terraform code and posts for the blog</p><p>(image from https://commons.wikimedia.org/wiki/File:Gnu-listen-half.jpg)</p>
<p>I have been an Emacs user for a long time. There is no specific reason why I started using Emacs: it was available in the RedHat 6.0 distribution that I found in a magazine in 1999, and with which I started my journey in the open source world. It was mentioned in some Linux guide I read at the time, so it became my editor.</p>
<p>I'm not into flame wars, in particular about editors. If I don't like a software/operating system/language/whatever, I just don't use it, and at the same time I'm not scared to test alternatives, even though I'm not actively looking to replace tools that work. Admittedly, at the time I didn't properly configure my Emacs for years, in particular because the C language support was very good out of the box, and that was what I needed, so when I started programming in Python not everything was optimal.</p>
<p>One day a new colleague showed me <a href="https://www.sublimetext.com/">Sublime Text</a> and PyCharm. I don't like IDEs that much, they are too integrated, so the PyCharm wasn't very attractive, but Sublime Text is a very good editor, it's fast and has a lot of features (multiple cursors blew my mind when I first discovered them) and so it became my editor of choice for some years. In time, however I started growing increasingly dissatisfied with it, and with some alternatives that I tested like Atom. The main reason is that modern editor rely too much on the mouse: many people are happy with this, in particular because they use trackpads, but I honestly can't get use to them, and I simply don't want to take my hands off the keyboards while I code because I want to change tab, reorganise the screen, open a file, and so on.</p>
<p>So I went back to Emacs, and started from scratch to configure it in order to match my needs. In this post I want to describe what I did, so that newcomers might be helped to setup their own editor. Emacs is incredibly customisable, and this is one of its main strengths, but a proper setup takes time. Please don't consider configuring your editor a waste of time. If you are a programmer, the editor is your main tool, and you have to take care of it: like any other editor, Emacs has pros and cons, and a proper setup minimises the impact of the shortcomings on your daily work.</p>
<h2 id="requirements">Requirements<a class="headerlink" href="#requirements" title="Permanent link">¶</a></h2>
<p>As always, the choice of tools and their configuration depends on the requirements, so these are the ones I have at the moment.</p>
<ul>
<li>I need to create <strong>keyboard shortcuts</strong> for everything I do often in the editor, I should be able to work without the mouse</li>
<li><strong>Multiple cursors</strong> are a very useful feature and I am used to have them, so there should be an implementation similar to the one I found in Sublime Text</li>
<li><strong>Python</strong>/<strong>JavaScript</strong>/<strong>Terraform</strong> syntax highlighting and formatting/linting</li>
<li>As I have some projects written with React, <strong>JSX</strong> syntax highlighting is also needed</li>
<li><strong>Markdown</strong> syntax highlighting with spell-checking for my blogger activity</li>
</ul>
<h2 id="preamble">Preamble<a class="headerlink" href="#preamble" title="Permanent link">¶</a></h2>
<p>The Emacs configuration file is <code>~/.emacs</code>, and when you install the editor you might get a default minimal version of it. Whenever part of the configuration is changed from the menus, Emacs writes the changes in the .emacs, using the <code>custom-set-variables</code> function. That file also contains the list of packages that I have installed, so I moved the <code>custom-set-variables</code> invocation to a separate file, <code>.emacs-custom</code>. This way Emacs doesn't have to change the main file whenever I install or remove a package and when I customise the face (colours and fonts).</p>
<p>For packages, I'm using the standard <a href="https://melpa.org/#/getting-started">MELPA configuration</a></p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Added by Package.el. This must come before configurations of</span>
<span class="c1">;; installed packages. Don't delete this line. If you don't want it,</span>
<span class="c1">;; just comment it out by adding a semicolon to the start of the line.</span>
<span class="c1">;; You may delete these explanatory comments.</span>
<span class="p">(</span><span class="nv">package-initialize</span><span class="p">)</span>
<span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">custom-file</span><span class="w"> </span><span class="s">"~/.emacs-custom"</span><span class="p">)</span>
<span class="p">(</span><span class="nb">load</span><span class="w"> </span><span class="nv">custom-file</span><span class="p">)</span>
<span class="c1">;; Load package system and add MELPA repository.</span>
<span class="p">(</span><span class="nb">require</span><span class="w"> </span><span class="ss">'package</span><span class="p">)</span>
<span class="p">(</span><span class="nv">add-to-list</span>
<span class="w"> </span><span class="ss">'package-archives</span>
<span class="w"> </span><span class="c1">;; '("melpa" . "https://stable.melpa.org/packages/") ; many packages won't show if using stable</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="s">"melpa"</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="s">"https://melpa.milkbox.net/packages/"</span><span class="p">)</span>
<span class="w"> </span><span class="no">t</span><span class="p">)</span>
</code></pre></div>
<h2 id="global-settings">Global settings<a class="headerlink" href="#global-settings" title="Permanent link">¶</a></h2>
<p>In Emacs you can define new functions and assign them to key combinations, and this is usually a major part of the setup. As I often need to work on the configuration file, at least initially, the first function I defined is one that allows me to quickly open the <code>.emacs</code> file. In the comments I'm following <a href="https://www.emacswiki.org/emacs/EmacsKeyNotation">Emacs key notation</a></p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Open .emacs with C-x c</span>
<span class="p">(</span><span class="nb">defun</span><span class="w"> </span><span class="nv">dotemacs</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">(</span><span class="nv">interactive</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nv">switch-to-buffer</span><span class="w"> </span><span class="p">(</span><span class="nv">find-file-noselect</span><span class="w"> </span><span class="s">"~/.emacs"</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-x c"</span><span class="p">)</span><span class="w"> </span><span class="ss">'dotemacs</span><span class="p">)</span>
</code></pre></div>
<p>I like the <a href="https://www.emacswiki.org/emacs/VisualLineMode">visual line mode</a> to wraps long lines</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Visual line mode everywhere, please</span>
<span class="p">(</span><span class="nv">global-visual-line-mode</span><span class="w"> </span><span class="no">t</span><span class="p">)</span>
</code></pre></div>
<p>I also want to always see <a href="http://ergoemacs.org/emacs/emacs_line_number_mode.html">line numbers</a></p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Display line numbers</span>
<span class="p">(</span><span class="nv">global-display-line-numbers-mode</span><span class="p">)</span>
</code></pre></div>
<p>I use <code>C-End</code> a lot to reach the end of the file, but often I press <code>C-<next></code> (<code>Ctrl-PgDown</code>) by mistake. That is by default associated with <code>scroll-left</code> which is disabled, but Emacs opens a buffer to warn me. I don't want that, so I just unset the key combination</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; I keep pressing C-next by mistake...</span>
<span class="p">(</span><span class="nv">global-unset-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-<next>"</span><span class="p">))</span>
</code></pre></div>
<p>I might not be a purist here. I used <code>M-w</code> and <code>C-y</code> for many years, but I also use other software during my day, and now the <code>Ctrl-c/x/v</code> combinations are universally implemented. It's really hard to remap my brain every time I go back to Emacs, so I prefer to remap Emacs. Welcome <a href="https://www.emacswiki.org/emacs/CuaMode">Cua Mode</a>, which also maps <code>undo</code> to <code>C-z</code></p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Set C-c, C-x, C-v just to be in sync with the rest of the world</span>
<span class="p">(</span><span class="nv">cua-mode</span><span class="w"> </span><span class="no">t</span><span class="p">)</span>
</code></pre></div>
<p>I like Emacs to highlight the <a href="https://www.emacswiki.org/emacs/ShowParenMode">matching parenthesis</a> whenever I'm on an opening or closing one. Please note that the word "parenthesis" here refers to what are more generally called <a href="https://en.wikipedia.org/wiki/Bracket">brackets</a> in English, which includes parentheses or round brackets <code>()</code>, curly brackets or curly braces <code>{}</code>, and square brackets <code>[]</code></p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Show the matching parenthesis</span>
<span class="p">(</span><span class="nv">show-paren-mode</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</code></pre></div>
<p>Speaking of brackets, I like to have a way to automatically match the opened ones. This is good in Lisp because there are more parentheses than words, but also in other languages like Python when dealing with complex data structures. Long story short, I mapped <code>C-]</code> to the auto-closing feature called <code>syntactic-close</code> (installed as a package)</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Syntactic close</span>
<span class="c1">;; https://github.com/emacs-berlin/syntactic-close</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-]"</span><span class="p">)</span><span class="w"> </span><span class="ss">'syntactic-close</span><span class="p">)</span>
</code></pre></div>
<p>Minibuffer is a very important part of Emacs, not only when you open files but also when running commands. I like the Ivy completion, so I installed it with MELPA and activate it. I want to have a quick access to the commands that I run previously (history), but since <code><down></code> and <code><up></code> are already used to navigate the suggestions I mapped the history functions to their Shift version. </p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Ivy completion</span>
<span class="c1">;; https://github.com/abo-abo/swiper</span>
<span class="p">(</span><span class="nv">ivy-mode</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
<span class="p">(</span><span class="nv">define-key</span><span class="w"> </span><span class="nv">ivy-minibuffer-map</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"S-<up>"</span><span class="p">)</span><span class="w"> </span><span class="nf">#'</span><span class="nv">ivy-previous-history-element</span><span class="p">)</span>
<span class="p">(</span><span class="nv">define-key</span><span class="w"> </span><span class="nv">ivy-minibuffer-map</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"S-<down>"</span><span class="p">)</span><span class="w"> </span><span class="nf">#'</span><span class="nv">ivy-next-history-element</span><span class="p">)</span>
</code></pre></div>
<p>The standard behaviour of <code>C-Del</code> in Emacs is far too greedy for me. I'm used to have a combination that deletes all spaces if I'm on a space, and the word if I'm on a word, so I found this</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; https://stackoverflow.com/questions/17958397/emacs-delete-whitespaces-or-a-word</span>
<span class="p">(</span><span class="nb">defun</span><span class="w"> </span><span class="nv">kill-whitespace-or-word</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nv">looking-at</span><span class="w"> </span><span class="s">"[ \t\n]"</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">((</span><span class="nv">p</span><span class="w"> </span><span class="p">(</span><span class="nv">point</span><span class="p">)))</span>
<span class="w"> </span><span class="p">(</span><span class="nv">re-search-forward</span><span class="w"> </span><span class="s">"[^ \t\n]"</span><span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="ss">:no-error</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="nv">backward-char</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="nv">kill-region</span><span class="w"> </span><span class="nv">p</span><span class="w"> </span><span class="p">(</span><span class="nv">point</span><span class="p">)))</span>
<span class="w"> </span><span class="p">(</span><span class="nv">kill-word</span><span class="w"> </span><span class="mi">1</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-<delete>"</span><span class="p">)</span><span class="w"> </span><span class="ss">'kill-whitespace-or-word</span><span class="p">)</span>
</code></pre></div>
<p>Last, as I have a rotating wallpaper with screenshots from my favourite films I like to see them behind the editor and the terminal, so I enable a little bit of transparency. I like this to be callable as an interactive function as I might want to remove the transparency, for example when sharing the screen, as that way the text might be easier to read.</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Set transparency of emacs</span>
<span class="c1">;; https://www.emacswiki.org/emacs/TransparentEmacs</span>
<span class="p">(</span><span class="nb">defun</span><span class="w"> </span><span class="nv">transparency</span><span class="w"> </span><span class="p">(</span><span class="nv">value</span><span class="p">)</span>
<span class="w"> </span><span class="s">"Sets the transparency of the frame window. 0=transparent/100=opaque"</span>
<span class="w"> </span><span class="p">(</span><span class="nv">interactive</span><span class="w"> </span><span class="s">"nTransparency Value 0 - 100 opaque:"</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="nv">set-frame-parameter</span><span class="w"> </span><span class="p">(</span><span class="nv">selected-frame</span><span class="p">)</span><span class="w"> </span><span class="ss">'alpha</span><span class="w"> </span><span class="nv">value</span><span class="p">))</span>
<span class="p">(</span><span class="nv">set-frame-parameter</span><span class="w"> </span><span class="p">(</span><span class="nv">selected-frame</span><span class="p">)</span><span class="w"> </span><span class="ss">'alpha</span><span class="w"> </span><span class="ss">'90</span><span class="p">)</span>
</code></pre></div>
<h2 id="keyboard-mapping">Keyboard mapping<a class="headerlink" href="#keyboard-mapping" title="Permanent link">¶</a></h2>
<p>I'm an Italian native speaker, so I often write texts in that language for my personal blog or for other reasons. In Italian, we use the accented letters à, è, é, ì, ò, ù a lot ("is" is just "è", "why" and "because" are "perché", almost all future tenses end with an accented letter, and so on), so I like to have a proper mapping. Emacs has a very powerful mode for Latin alphabet <a href="https://en.wikipedia.org/wiki/Diacritic">diacritics</a>, which is <code>latin-postfix</code>, where you can write "è" typing <code>e</code> followed by backticks, so that was my first choice. While this is very powerful, and allows me to input almost everything I need also for other languages like German, on the long run I found it very difficult to use efficiently.</p>
<p>First of all, I'm used to the Italian keymap, I know it by heart as I know the English keyboard mapping, so I tend to press keys that are supposed to insert the accented letters directly. Moreover, other software like the browser work with a system keyboard mapping (that Emacs ignores), so again, I need to rewire my brain every time I go back to the editor. Last, <code>latin-postfix</code> is far too generic and has mappings for letters like ą or ę which are created typing "a," which is a combination that we have every time we type a comma in Italian given that almost all words end in a vowel. This forces me to type "a,," whenever I need "a,", which is far too different from the normal system I'm used to.</p>
<p>The input method <code>italian-keyboard</code> unfortunately doesn't map very well on a standard modern English keyboard, so I decided to just write my own mapping using the <a href="http://web.mit.edu/Emacs/source/emacs/lisp/international/quail.el">quail</a> system, which is unsurprisingly not very well documented. I'm sorry to say it, but multilingual input has been and still is one of the great forgotten and messy topics in computer science, in particular in the open source world. Let's not even mention Chinese and other languages not based on an alphabet.</p>
<div class="highlight"><pre><span></span><code><span class="c1">; Define a proper mapping for the Italian keyboard over the English one</span>
<span class="p">(</span><span class="nv">quail-define-package</span>
<span class="w"> </span><span class="s">"italian-english-keyboard"</span><span class="w"> </span><span class="s">"Latin-1"</span><span class="w"> </span><span class="s">"IT@"</span><span class="w"> </span><span class="no">t</span>
<span class="w"> </span><span class="s">"Italian (Italiano) input method for modern English keyboards"</span>
<span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="no">t</span><span class="w"> </span><span class="no">t</span><span class="w"> </span><span class="no">t</span><span class="w"> </span><span class="no">t</span><span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="no">t</span><span class="p">)</span>
<span class="c1">;; \| 1! 2" 3£ 4$ 5% 6& 7/ 8( 9) 0= '? ì^</span>
<span class="c1">;; qQ wW eE rR tT yY uU iI oO pP èé +*</span>
<span class="c1">;; aA sS dD fF gG hH jJ kK lL òç à° ù§</span>
<span class="c1">;; <> zZ xX cC vV bB nN mM ,; .: -_</span>
<span class="c1">;; èè -> È Originally CapsLock+è</span>
<span class="c1">;; àà -> # Originally AltGr+à</span>
<span class="c1">;; òò -> @ Originally AltGr+ò</span>
<span class="c1">;; ìì -> ~ Originally AltGr+ì</span>
<span class="p">(</span><span class="nv">quail-define-rules</span>
<span class="w"> </span><span class="p">(</span><span class="s">"`"</span><span class="w"> </span><span class="nv">?\\</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="s">"¬"</span><span class="w"> </span><span class="nv">?|)</span>
<span class="nv"> ("^" ?&)</span>
<span class="nv"> ("&" ?/)</span>
<span class="nv"> ("*" ?\()</span>
<span class="nv"> ("(" ?\))</span>
<span class="nv"> (")" ?=)</span>
<span class="nv"> ("-" ?') ("_" ??)</span>
<span class="nv"> ("=" ?ì) ("+" ?^) ("==" ?~)</span>
<span class="nv"> ("[" ?è) ("{" ?é) ("[[" ?È)</span>
<span class="nv"> ("]" ?+) ("}" ?*)</span>
<span class="nv"> (";" ?ò) (":" ?ç) (";;" ?@)</span>
<span class="nv"> ("'" ?à) ("@" ?\°) ("''" ?#)</span>
<span class="nv"> ("#" ?ù) ("~" ?§)</span>
<span class="nv"> ("\\" ?<) ("|</span><span class="s">" ?>)</span>
<span class="s"> ("</span><span class="nb"><</span><span class="s">" ?\;)</span>
<span class="s"> ("</span><span class="nb">></span><span class="s">" ?:)</span>
<span class="s"> ("</span><span class="nb">/</span><span class="s">" ?-) ("</span><span class="nv">?</span><span class="err">"</span><span class="w"> </span><span class="nv">?_</span><span class="p">)</span>
<span class="p">)</span>
</code></pre></div>
<p>The standard Italian keyboard allows to input <code>È</code> activating CapsLock, pressing the key for <code>è</code> and deactivating CapsLock. This because <code>Shift-è</code> inputs <code>é</code>. I always found that system incredibly awkward, not to mention that it is impossible (as far as I understand) to create such a combination using quail, so I mapped it to <code>èè</code>, since that combination doesn't exist in Italian.</p>
<p>Another issue is that the Italian keyboard makes use of the right Alt key (AltGr) to input third level characters like <code>#</code>, <code>@</code>, and <code>~</code>. Again, I don't know if and how I can express these in quail so I went for a slight variation of that. Instead of typing AltGr+à for <code>#</code> I will type <code>àà</code> and so on. This is not a perfect mapping, but considering that I don't use those character that much when writing notes or blog posts I can accept it.</p>
<h2 id="lines-and-regions">Lines and regions<a class="headerlink" href="#lines-and-regions" title="Permanent link">¶</a></h2>
<p>This section is about shortcuts to interact with lines and regions. First of all something that comments the regions I highlighted or just the line I'm on. This is a good example of something that Emacs doesn't provide out of the box, maybe surprisingly, but that is easily implemented. OK, "easily" might be an overstatement, but this function is a good starting point if you want to learn how <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/">Emacs Lisp</a> works. If you are not interested you can just copy and paste it and call it a day</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Define C-/ to comment and uncomment regions and lines</span>
<span class="p">(</span><span class="nb">defun</span><span class="w"> </span><span class="nv">comment-or-uncomment-line-or-region</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="s">"Comments or uncomments the region or the current line if there's no active region."</span>
<span class="w"> </span><span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">(</span><span class="nv">beg</span><span class="w"> </span><span class="nv">end</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nv">region-active-p</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">beg</span><span class="w"> </span><span class="p">(</span><span class="nv">region-beginning</span><span class="p">)</span><span class="w"> </span><span class="nv">end</span><span class="w"> </span><span class="p">(</span><span class="nv">region-end</span><span class="p">))</span>
<span class="w"> </span><span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">beg</span><span class="w"> </span><span class="p">(</span><span class="nv">line-beginning-position</span><span class="p">)</span><span class="w"> </span><span class="nv">end</span><span class="w"> </span><span class="p">(</span><span class="nv">line-end-position</span><span class="p">)))</span>
<span class="w"> </span><span class="p">(</span><span class="nv">comment-or-uncomment-region</span><span class="w"> </span><span class="nv">beg</span><span class="w"> </span><span class="nv">end</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="nv">next-line</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-/"</span><span class="p">)</span><span class="w"> </span><span class="ss">'comment-or-uncomment-line-or-region</span><span class="p">)</span>
</code></pre></div>
<p>I want to be able to move up and down lines or regions using <code>Ctrl-Shift-up/down</code>, that is to <a href="https://github.com/rejeep/drag-stuff.el">drag stuff</a></p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Drag-stuff - Drag lines and regions</span>
<span class="p">(</span><span class="nv">drag-stuff-global-mode</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
<span class="c1">;; Use C-S-up/down</span>
<span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">drag-stuff-modifier</span><span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">control</span><span class="w"> </span><span class="nv">shift</span><span class="p">))</span>
<span class="p">(</span><span class="nv">define-key</span><span class="w"> </span><span class="nv">drag-stuff-mode-map</span><span class="w"> </span><span class="p">(</span><span class="nv">drag-stuff--kbd</span><span class="w"> </span><span class="ss">'up</span><span class="p">)</span><span class="w"> </span><span class="ss">'drag-stuff-up</span><span class="p">)</span>
<span class="p">(</span><span class="nv">define-key</span><span class="w"> </span><span class="nv">drag-stuff-mode-map</span><span class="w"> </span><span class="p">(</span><span class="nv">drag-stuff--kbd</span><span class="w"> </span><span class="ss">'down</span><span class="p">)</span><span class="w"> </span><span class="ss">'drag-stuff-down</span><span class="p">)</span>
</code></pre></div>
<p>I also want to be able to duplicate the current line or region with <code>Ctrl-Shift-d</code>. This function is a mixture of several solutions I found on Internet, and I'm not 100% satisfied with it, as when I duplicate a region it also duplicates the last line of the region itself, even though the line is not highlighted. Again, it might be surprising that Emacs doesn't provide a solution out-of-the-box, but this way I can implement the behaviour I prefer. The fact that I'm not able to implement the exact behaviour (yet!) is part of the game, I think.</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Duplicate line with C-S-d</span>
<span class="p">(</span><span class="nb">defun</span><span class="w"> </span><span class="nv">duplicate-current-line-or-region</span><span class="w"> </span><span class="p">(</span><span class="nv">arg</span><span class="p">)</span>
<span class="w"> </span><span class="s">"Duplicates the current line or region ARG times.</span>
<span class="s">If there's no region, the current line will be duplicated. However, if</span>
<span class="s">there's a region, all lines that region covers will be duplicated."</span>
<span class="w"> </span><span class="p">(</span><span class="nv">interactive</span><span class="w"> </span><span class="s">"p"</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">(</span><span class="nv">beg</span><span class="w"> </span><span class="nv">end</span><span class="w"> </span><span class="p">(</span><span class="nv">origin</span><span class="w"> </span><span class="p">(</span><span class="nv">point</span><span class="p">)))</span>
<span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nb">and</span><span class="w"> </span><span class="nv">mark-active</span><span class="w"> </span><span class="p">(</span><span class="nb">></span><span class="w"> </span><span class="p">(</span><span class="nv">point</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nv">mark</span><span class="p">)))</span>
<span class="w"> </span><span class="p">(</span><span class="nv">exchange-point-and-mark</span><span class="p">))</span>
<span class="w"> </span><span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">beg</span><span class="w"> </span><span class="p">(</span><span class="nv">line-beginning-position</span><span class="p">))</span>
<span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="nv">mark-active</span>
<span class="w"> </span><span class="p">(</span><span class="nv">exchange-point-and-mark</span><span class="p">))</span>
<span class="w"> </span><span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">end</span><span class="w"> </span><span class="p">(</span><span class="nv">line-end-position</span><span class="p">))</span>
<span class="w"> </span><span class="p">(</span><span class="k">let</span><span class="w"> </span><span class="p">((</span><span class="nv">region</span><span class="w"> </span><span class="p">(</span><span class="nv">buffer-substring-no-properties</span><span class="w"> </span><span class="nv">beg</span><span class="w"> </span><span class="nv">end</span><span class="p">)))</span>
<span class="w"> </span><span class="p">(</span><span class="nb">dotimes</span><span class="w"> </span><span class="p">(</span><span class="nv">i</span><span class="w"> </span><span class="nv">arg</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="nv">goto-char</span><span class="w"> </span><span class="nv">end</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="nv">newline</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="nv">insert</span><span class="w"> </span><span class="nv">region</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">end</span><span class="w"> </span><span class="p">(</span><span class="nv">point</span><span class="p">)))</span>
<span class="w"> </span><span class="p">(</span><span class="nv">goto-char</span><span class="w"> </span><span class="p">(</span><span class="nb">+</span><span class="w"> </span><span class="nv">origin</span><span class="w"> </span><span class="p">(</span><span class="nb">*</span><span class="w"> </span><span class="p">(</span><span class="nb">length</span><span class="w"> </span><span class="nv">region</span><span class="p">)</span><span class="w"> </span><span class="nv">arg</span><span class="p">)</span><span class="w"> </span><span class="nv">arg</span><span class="p">)))))</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-S-d"</span><span class="p">)</span><span class="w"> </span><span class="ss">'duplicate-current-line-or-region</span><span class="p">)</span>
</code></pre></div>
<p>Multiple cursors! Emacs has an implementation of <a href="https://github.com/magnars/multiple-cursors.el">multiple cursors</a>, that is slightly different from the Sublime Text one, but that can be customised to my needs. Most notably, multiple cursors don't work perfectly with some parts of the editor like <code>TAB</code> for indentation, which is not automatically applied to all of them. So, this part of the setup is not perfect, but it's definitely usable and effective.</p>
<p><code>Ctrl-d</code> creates a second cursor on the next repetition of the current word, <code>Ctrl-c Ctrl-d</code> marks all the repetitions in the text, <code>Ctrl-Alt-up/down</code> add a new cursor on the previous/following line, and last <code>Ctrl-Alt-d</code> marks all the lines in a region</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Multiple cursors</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-d"</span><span class="p">)</span><span class="w"> </span><span class="ss">'mc/mark-next-like-this-word</span><span class="p">)</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-c C-d"</span><span class="p">)</span><span class="w"> </span><span class="ss">'mc/mark-all-words-like-this</span><span class="p">)</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-M-<up>"</span><span class="p">)</span><span class="w"> </span><span class="ss">'mc/mark-previous-lines</span><span class="p">)</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-M-<down>"</span><span class="p">)</span><span class="w"> </span><span class="ss">'mc/mark-next-lines</span><span class="p">)</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-M-d"</span><span class="p">)</span><span class="w"> </span><span class="ss">'mc/edit-lines</span><span class="p">)</span>
</code></pre></div>
<p>How many times do I need to highlight the whole buffer? More than I imagined, so I defined the classic <code>Ctrl-a</code> shortcut</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; C-a marks the whole buffer</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-a"</span><span class="p">)</span><span class="w"> </span><span class="ss">'mark-whole-buffer</span><span class="p">)</span>
</code></pre></div>
<h2 id="windows-and-buffers">Windows and buffers<a class="headerlink" href="#windows-and-buffers" title="Permanent link">¶</a></h2>
<p>As everyone else, when I code I need to keep multiple files open, and often to have them side-by-side. Emacs provides out of the box the window split shortcuts <code>Ctrl-2</code> (horizontal split) and <code>Ctrl-3</code> (vertical split), but I need a shortcut to quickly move between them. Enter <a href="https://www.emacswiki.org/emacs/WindMove">Windmove</a>, which by default uses <code>Shift-<arrow></code> combinations, which I instead want to keep for highlighting regions, so I remapped it to <code>Alt-<arrow></code></p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Windmove - move between windows use ALT</span>
<span class="p">(</span><span class="nv">windmove-default-keybindings</span><span class="w"> </span><span class="ss">'meta</span><span class="p">)</span>
<span class="c1">;; Unset Shift-arrow keybindings</span>
<span class="p">(</span><span class="nv">global-unset-key</span><span class="w"> </span><span class="p">(</span><span class="nb">vector</span><span class="w"> </span><span class="p">(</span><span class="nb">list</span><span class="w"> </span><span class="ss">'shift</span><span class="w"> </span><span class="ss">'left</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">global-unset-key</span><span class="w"> </span><span class="p">(</span><span class="nb">vector</span><span class="w"> </span><span class="p">(</span><span class="nb">list</span><span class="w"> </span><span class="ss">'shift</span><span class="w"> </span><span class="ss">'right</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">global-unset-key</span><span class="w"> </span><span class="p">(</span><span class="nb">vector</span><span class="w"> </span><span class="p">(</span><span class="nb">list</span><span class="w"> </span><span class="ss">'shift</span><span class="w"> </span><span class="ss">'up</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">global-unset-key</span><span class="w"> </span><span class="p">(</span><span class="nb">vector</span><span class="w"> </span><span class="p">(</span><span class="nb">list</span><span class="w"> </span><span class="ss">'shift</span><span class="w"> </span><span class="ss">'down</span><span class="p">)))</span>
</code></pre></div>
<p>Next I need to move between buffers (open files not currently visible) Emacs used buffers also for its own internal logs, and all those buffers have a name surrounded by <code>*</code>, so I filter them out when I move through open files</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Skip system buffers when cycling</span>
<span class="p">(</span><span class="nv">set-frame-parameter</span><span class="w"> </span><span class="p">(</span><span class="nv">selected-frame</span><span class="p">)</span><span class="w"> </span><span class="ss">'buffer-predicate</span>
<span class="w"> </span><span class="p">(</span><span class="k">lambda</span><span class="w"> </span><span class="p">(</span><span class="nv">buf</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nb">not</span><span class="w"> </span><span class="p">(</span><span class="nv">string-match-p</span><span class="w"> </span><span class="s">"^*"</span><span class="w"> </span><span class="p">(</span><span class="nv">buffer-name</span><span class="w"> </span><span class="nv">buf</span><span class="p">)))))</span>
</code></pre></div>
<p>To move between buffers I map <code>previous-buffer</code> and <code>next-buffer</code> to <code>Ctrl-Super-left/right</code> (Super here is my left Win key, which is between Ctrl and Alt)</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Map previous and next buffer to C-s-</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-s-<left>"</span><span class="p">)</span><span class="w"> </span><span class="ss">'previous-buffer</span><span class="p">)</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-s-<right>"</span><span class="p">)</span><span class="w"> </span><span class="ss">'next-buffer</span><span class="p">)</span>
</code></pre></div>
<p>Oh, I love the <a href="https://github.com/roman/golden-ratio.el">golden ratio mode</a> that splits window giving more space to the current one </p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Golden ratio mode</span>
<span class="p">(</span><span class="nb">require</span><span class="w"> </span><span class="ss">'golden-ratio</span><span class="p">)</span>
<span class="p">(</span><span class="nv">golden-ratio-mode</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
</code></pre></div>
<h2 id="spell-checking">Spell checking<a class="headerlink" href="#spell-checking" title="Permanent link">¶</a></h2>
<p>When I will learn how to properly spell <code>inconceivably</code> and <code>counter-intuitive</code> I might get rid of this. In the meanwhile a good spell check is a blessing from heaven. I haven't used function keys that much so far, and since I'm used to the standard Sublime Text mapping <code>F6</code> I reused that.</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Spell check</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"<f6>"</span><span class="p">)</span><span class="w"> </span><span class="ss">'flyspell-mode</span><span class="p">)</span>
<span class="c1">;; Spell check with hunspell</span>
<span class="p">(</span><span class="nb">when</span><span class="w"> </span><span class="p">(</span><span class="nv">executable-find</span><span class="w"> </span><span class="s">"hunspell"</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="nv">setq-default</span><span class="w"> </span><span class="nv">ispell-program-name</span><span class="w"> </span><span class="s">"hunspell"</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">ispell-really-hunspell</span><span class="w"> </span><span class="no">t</span><span class="p">))</span>
</code></pre></div>
<p>By the way, I misspell simpler words all the time, no need to get into inconceivably counter-intuitive words. And I'm sure there will be typos in this text, no matter how many times I check and read it =)</p>
<h2 id="python-development">Python development<a class="headerlink" href="#python-development" title="Permanent link">¶</a></h2>
<p>At last, let's get into development! Emacs has a very good package for Python, called <a href="https://elpy.readthedocs.io/en/latest/">Elpy</a>.</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Enable Elpy for Python development</span>
<span class="c1">;; https://elpy.readthedocs.io/en/latest/</span>
<span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">elpy-rpc-python-command</span><span class="w"> </span><span class="s">"python3"</span><span class="p">)</span>
<span class="p">(</span><span class="nv">elpy-enable</span><span class="p">)</span>
</code></pre></div>
<p>There are some adjustment needed to prevent the mode to override the Windmove and other binding</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Prevent Elpy from overriding Windmove shortcuts</span>
<span class="p">(</span><span class="nv">eval-after-load</span><span class="w"> </span><span class="s">"elpy"</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">cl-dolist</span><span class="w"> </span><span class="p">(</span><span class="nv">key</span><span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="s">"M-<up>"</span><span class="w"> </span><span class="s">"M-<down>"</span><span class="w"> </span><span class="s">"M-<left>"</span><span class="w"> </span><span class="s">"M-<right>"</span><span class="p">))</span>
<span class="w"> </span><span class="p">(</span><span class="nv">define-key</span><span class="w"> </span><span class="nv">elpy-mode-map</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="nv">key</span><span class="p">)</span><span class="w"> </span><span class="no">nil</span><span class="p">)))</span>
<span class="c1">;; Prevent Elpy from overriding standard cursor movements</span>
<span class="p">(</span><span class="nv">eval-after-load</span><span class="w"> </span><span class="s">"elpy"</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">cl-dolist</span><span class="w"> </span><span class="p">(</span><span class="nv">key</span><span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="s">"C-<left>"</span><span class="w"> </span><span class="s">"C-<right>"</span><span class="p">))</span>
<span class="w"> </span><span class="p">(</span><span class="nv">define-key</span><span class="w"> </span><span class="nv">elpy-mode-map</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="nv">key</span><span class="p">)</span><span class="w"> </span><span class="no">nil</span><span class="p">)))</span>
</code></pre></div>
<p>Since I use <a href="https://github.com/psf/black">black</a> to format Python code I run it on save. Plus I have a shortcut to fix the syntax in the buffer at any time. Since the syntax document is PEP8 <code>C-8</code> is a nice combination.</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Run black on save</span>
<span class="p">(</span><span class="nv">add-hook</span><span class="w"> </span><span class="ss">'elpy-mode-hook</span><span class="w"> </span><span class="p">(</span><span class="k">lambda</span><span class="w"> </span><span class="p">()</span>
<span class="w"> </span><span class="p">(</span><span class="nv">add-hook</span><span class="w"> </span><span class="ss">'before-save-hook</span><span class="w"> </span><span class="ss">'elpy-black-fix-code</span><span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="no">t</span><span class="p">)))</span>
<span class="c1">;; Set C-8 to format Python code</span>
<span class="p">(</span><span class="nv">global-set-key</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-8"</span><span class="p">)</span><span class="w"> </span><span class="ss">'elpy-black-fix-code</span><span class="p">)</span>
</code></pre></div>
<h2 id="javascript-development">JavaScript development<a class="headerlink" href="#javascript-development" title="Permanent link">¶</a></h2>
<p>Let's go full-stack and add some JavaScript and JSX to the recipe. The <a href="https://github.com/felipeochoa/rjsx-mode">rjsx-mode</a> is perfect for React development and similar things</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; JSX</span>
<span class="c1">;;https://github.com/felipeochoa/rjsx-mode</span>
<span class="p">(</span><span class="nv">add-to-list</span><span class="w"> </span><span class="ss">'auto-mode-alist</span><span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="s">"\\.js\\'"</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="nv">rjsx-mode</span><span class="p">))</span>
<span class="c1">;; Don't override my beloved multiple cursors</span>
<span class="p">(</span><span class="nv">with-eval-after-load</span><span class="w"> </span><span class="ss">'rjsx-mode</span>
<span class="w"> </span><span class="p">(</span><span class="nv">define-key</span><span class="w"> </span><span class="nv">rjsx-mode-map</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"C-d"</span><span class="p">)</span><span class="w"> </span><span class="no">nil</span><span class="p">))</span>
</code></pre></div>
<p>As I will install Node.js modules locally in <code>node_modules</code> I want code formatters and other tools to run the binaries stored there</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Use binaries in node_modules</span>
<span class="c1">;; https://github.com/codesuki/add-node-modules-path</span>
<span class="p">(</span><span class="nv">add-hook</span><span class="w"> </span><span class="ss">'js2-mode-hook</span><span class="w"> </span><span class="ss">'add-node-modules-path</span><span class="p">)</span>
</code></pre></div>
<p>And also JS need to be beautified, at least when I have to read and understand it. I use <a href="https://prettier.io/">prettier</a> and <a href="https://github.com/prettier/prettier-emacs">prettier-emacs</a></p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Pretty JS code</span>
<span class="c1">;; https://github.com/prettier/prettier-emacs</span>
<span class="p">(</span><span class="nb">require</span><span class="w"> </span><span class="ss">'prettier-js</span><span class="p">)</span>
<span class="p">(</span><span class="nv">add-hook</span><span class="w"> </span><span class="ss">'js2-mode-hook</span><span class="w"> </span><span class="ss">'prettier-js-mode</span><span class="p">)</span>
</code></pre></div>
<h2 id="other-languages">Other languages<a class="headerlink" href="#other-languages" title="Permanent link">¶</a></h2>
<p>Other languages I use are less demanding in term of customisation (generally because they are simpler or less general-purpose). The <a href="https://github.com/emacsorphanage/terraform-mode">Terraform mode</a> automatically fixes the syntax of the file on save</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Terraform</span>
<span class="c1">;; https://github.com/emacsorphanage/terraform-mode</span>
<span class="p">(</span><span class="nb">require</span><span class="w"> </span><span class="ss">'terraform-mode</span><span class="p">)</span>
<span class="p">(</span><span class="nv">add-to-list</span><span class="w"> </span><span class="ss">'auto-mode-alist</span><span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="s">"\\.tf\\'"</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="nv">terraform-mode</span><span class="p">))</span>
<span class="p">(</span><span class="nv">add-hook</span><span class="w"> </span><span class="ss">'terraform-mode-hook</span><span class="w"> </span><span class="nf">#'</span><span class="nv">terraform-format-on-save-mode</span><span class="p">)</span>
<span class="c1">;; YAML</span>
<span class="p">(</span><span class="nb">require</span><span class="w"> </span><span class="ss">'yaml-mode</span><span class="p">)</span>
<span class="p">(</span><span class="nv">add-to-list</span><span class="w"> </span><span class="ss">'auto-mode-alist</span><span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="s">"\\.ya?ml\\'"</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="nv">yaml-mode</span><span class="p">))</span>
</code></pre></div>
<h2 id="files-and-projects">Files and projects<a class="headerlink" href="#files-and-projects" title="Permanent link">¶</a></h2>
<p>My setup is still a work in progress here, I'm testing <a href="https://docs.projectile.mx/projectile/usage.html">Projectile</a>, <a href="https://github.com/raxod502/prescient.el">Prescient</a>, and <a href="https://github.com/Alexander-Miller/treemacs">Treemacs</a>. So far, only Projectile made it to the configuration file, but I'm not using it that much yet. I think I might use a good sidebar with Git integration through colours and icons, but I still have to find something I feel comfortable with.</p>
<div class="highlight"><pre><span></span><code><span class="c1">;; Projectile</span>
<span class="c1">;; https://docs.projectile.mx/projectile/usage.html</span>
<span class="p">(</span><span class="nb">require</span><span class="w"> </span><span class="ss">'projectile</span><span class="p">)</span>
<span class="p">(</span><span class="nv">define-key</span><span class="w"> </span><span class="nv">projectile-mode-map</span><span class="w"> </span><span class="p">(</span><span class="nv">kbd</span><span class="w"> </span><span class="s">"s-p"</span><span class="p">)</span><span class="w"> </span><span class="ss">'projectile-command-map</span><span class="p">)</span>
<span class="p">(</span><span class="nv">projectile-mode</span><span class="w"> </span><span class="mi">+1</span><span class="p">)</span>
<span class="p">(</span><span class="k">setq</span><span class="w"> </span><span class="nv">projectile-completion-system</span><span class="w"> </span><span class="ss">'ivy</span><span class="p">)</span>
</code></pre></div>
<h2 id="the-custom-file">The custom file<a class="headerlink" href="#the-custom-file" title="Permanent link">¶</a></h2>
<p>As I mentioned when I discussed the preamble the file <code>.emacs-custom</code> contains the customisation of variables and faces, and this is what I have</p>
<div class="highlight"><pre><span></span><code><span class="p">(</span><span class="nv">custom-set-variables</span>
<span class="w"> </span><span class="c1">;; custom-set-variables was added by Custom.</span>
<span class="w"> </span><span class="c1">;; If you edit it by hand, you could mess it up, so be careful.</span>
<span class="w"> </span><span class="c1">;; Your init file should contain only one such instance.</span>
<span class="w"> </span><span class="c1">;; If there is more than one, they won't work right.</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">ansi-color-faces-vector</span>
<span class="w"> </span><span class="nv">[default</span><span class="w"> </span><span class="nv">default</span><span class="w"> </span><span class="nv">default</span><span class="w"> </span><span class="nv">italic</span><span class="w"> </span><span class="nv">underline</span><span class="w"> </span><span class="nv">success</span><span class="w"> </span><span class="kt">warning</span><span class="w"> </span><span class="nv">error]</span><span class="p">)</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">custom-enabled-themes</span><span class="w"> </span><span class="p">(</span><span class="k">quote</span><span class="w"> </span><span class="p">(</span><span class="nv">tango-dark</span><span class="p">)))</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">default-input-method</span><span class="w"> </span><span class="p">(</span><span class="k">quote</span><span class="w"> </span><span class="nv">italian-english-keyboard</span><span class="p">))</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">inhibit-startup-screen</span><span class="w"> </span><span class="no">t</span><span class="p">)</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">js-indent-level</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">package-selected-packages</span>
<span class="w"> </span><span class="p">(</span><span class="k">quote</span>
<span class="w"> </span><span class="p">(</span><span class="nv">syntactic-close</span><span class="w"> </span><span class="nv">ivy</span><span class="w"> </span><span class="nv">projectile</span><span class="w"> </span><span class="nv">rjsx-mode</span><span class="w"> </span><span class="nv">js2-mode</span><span class="w"> </span><span class="nv">golden-ratio</span>
<span class="w"> </span><span class="nv">add-node-modules-path</span><span class="w"> </span><span class="nv">prettier-js</span><span class="w"> </span><span class="nv">tide</span><span class="w"> </span><span class="nv">elpy</span><span class="w"> </span><span class="nv">jinja2-mode</span><span class="w"> </span><span class="nv">drag-stuff</span>
<span class="w"> </span><span class="nv">markdown-mode</span><span class="w"> </span><span class="nv">fcitx</span><span class="w"> </span><span class="nv">command-log-mode</span><span class="w"> </span><span class="nv">yaml-mode</span><span class="w"> </span><span class="nv">terraform-mode</span><span class="w"> </span><span class="nv">multiple-cursors</span><span class="p">))))</span>
<span class="p">(</span><span class="nv">custom-set-faces</span>
<span class="w"> </span><span class="c1">;; custom-set-faces was added by Custom.</span>
<span class="w"> </span><span class="c1">;; If you edit it by hand, you could mess it up, so be careful.</span>
<span class="w"> </span><span class="c1">;; Your init file should contain only one such instance.</span>
<span class="w"> </span><span class="c1">;; If there is more than one, they won't work right.</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">flymake-error</span><span class="w"> </span><span class="p">((</span><span class="no">t</span><span class="w"> </span><span class="p">(</span><span class="ss">:foreground</span><span class="w"> </span><span class="s">"orange red"</span><span class="w"> </span><span class="ss">:background</span><span class="w"> </span><span class="s">"yellow"</span><span class="p">))))</span>
<span class="w"> </span><span class="o">'</span><span class="p">(</span><span class="nv">js2-external-variable</span><span class="w"> </span><span class="p">((</span><span class="no">t</span><span class="w"> </span><span class="p">(</span><span class="ss">:foreground</span><span class="w"> </span><span class="s">"orange red"</span><span class="w"> </span><span class="ss">:background</span><span class="w"> </span><span class="s">"yellow"</span><span class="p">)))))</span>
</code></pre></div>
<p>As you can see I have a default theme <code>tango-dark</code>. The default alternate input method activated by <code>C-\</code> is the one I defined previously, <code>italian-english-keyboard</code>. JavaScript uses 2 spaces for indentation, and last I changed some colours to make errors in Python and JavaScript stand out very clearly.</p>
<h2 id="final-words">Final words<a class="headerlink" href="#final-words" title="Permanent link">¶</a></h2>
<p>Any configuration is a work in progress, as it changes with the personal preferences and the requirements, but this has been my configuration for a while now, so it seems pretty stable. I hope this might help whoever wants to try emacs or who is already using it but struggles to properly configure it. Happy coding!</p>
<h2 id="feedback">Feedback<a class="headerlink" href="#feedback" title="Permanent link">¶</a></h2>
<p>Feel free to reach me on <a href="https://twitter.com/thedigicat">Twitter</a> if you have questions. The <a href="https://github.com/TheDigitalCatOnline/blog_source/issues">GitHub issues</a> page is the best place to submit corrections.</p>