<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Arun Mani J</title><link>https://arunmani.in/</link><description/><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>🄯 Copyleft 2024 Arun Mani J.</copyright><managingEditor>Arun Mani J (j.arunmani@proton.me)</managingEditor><webmaster>j.arunmani@proton.me</webmaster><lastBuildDate>Sun, 18 Feb 2024 16:53:23 +0530</lastBuildDate><atom:link href="https://arunmani.in/index.xml" rel="self" type="application/rss+xml"/><item><title>The Palace of Illusions</title><link>https://arunmani.in/library/palace-of-illusions/</link><pubDate>Sun, 18 Feb 2024 16:53:23 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/palace-of-illusions/</guid><enclosure url="https://arunmani.in/library/palace-of-illusions/cover.webp" length="1024" type="image/webp"/><description>&lt;p>This book was gifted to me by my friend Levi from a book club for Christmas.
Thanks Levi.&lt;/p>
&lt;p>The last few months, I have been reading a lot of books related to Mahabharata.
May be not so &lt;em>a lot&lt;/em> but &lt;em>a lot&lt;/em> at least. The same story is presented with
little variations and adjustments in different books and narrations. Nobody
knows which is the true one, if it ever exists.&lt;/p>
&lt;p>So this book, it narrates you Mahabharata from &lt;a href="https://en.wikipedia.org/wiki/Draupadi">Draupadi
(Panchaali)&lt;/a>&amp;rsquo;s point of view. If you are
new to Mahabharata, then I suggest you to not start from this book. Read any
other Mahabharata book from a third-party perspective and then read this book.&lt;/p>
&lt;p>This book? It is awesome. I read Mahabharata from &lt;a href="https://arunmani.in/library/jaya">Jaya by Devdutt
Patnaik&lt;/a>, which tries to present a neutral narrative of what
happened with a list of variations at the end of each chapter. If you read &lt;a href="https://arunmani.in/library/jaya">my
review for Jaya&lt;/a>, you will realize how I loved the book for its
short, to-the-point descriptions. But by sacrificing the adjectives, the words
lack any emotions.&lt;/p>
&lt;p>However, The Palace of Illusions is completely opinionated. It speaks from
Draupadi&amp;rsquo;s view. So there is a good amount of expressions and feelings preserved
inside the book. It also presents a cinematic style of stories where the twist
or surprise is at the last paragraph or sentence.&lt;/p>
&lt;p>Overall, I loved the book for its presentation. If you are new to Mahabharata,
then some plots may not be so &lt;em>obvious&lt;/em> to you. That&amp;rsquo;s why, this book is great
&lt;em>once&lt;/em> you know Mahabharata.&lt;/p></description></item><item><title>Plato and a Platypus Walk Into a Bar: Understanding Philosophy Through Jokes</title><link>https://arunmani.in/library/plato-and-a-platypus/</link><pubDate>Tue, 30 Jan 2024 21:38:14 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/plato-and-a-platypus/</guid><enclosure url="https://arunmani.in/library/plato-and-a-platypus/cover.webp" length="1024" type="image/webp"/><description>&lt;p>For a long time, I thought philosophy means having abstract vague questions that
are highly opinionated in nature and don&amp;rsquo;t have a solid answer. It includes
questions like &lt;em>what is the meaning of life?&lt;/em>, &lt;em>is the action fair?&lt;/em> etc. But
then I felt like - &lt;em>okay, but what is there for someone to study it so
seriously?&lt;/em>. In short, I thought philosophy is a topic of conversation people
have from time to time in boring evenings where they themselves know that there
is no proper answer. &lt;em>Sigh&lt;/em>.&lt;/p>
&lt;p>Okay, turned out to be, philosophy is &lt;em>kinda that&lt;/em> but &lt;em>not that&lt;/em>. I asked my
friend to give me practical examples of where philosophy is used. I asked her
to give a problem and explain how philosophy is used to solve it. She tried
explaining me that you can&amp;rsquo;t understand philosophy just like that and yes, I
didn&amp;rsquo;t.&lt;/p>
&lt;p>I found out this book from a bookclub. The name sounded good and I felt like it
will help me understanding philosophy. Well, after reading I can say that the
book didn&amp;rsquo;t help me with my original objective in anyway. But, at least, it told
me that philosophy is so vast and yea, spawns some long boring evenings and end
up confusing people like me.&lt;/p>
&lt;p>So the book presents some topic and a lot of jokes. I expected the book to
explain the concept and then explain it with the jokes or at least explain the
joke with the concept. But, the book takes a lot of things for granted. There is
no real explanation actually. The book discusses a few paragraphs about the
topic and then presents jokes.&lt;/p>
&lt;p>The jokes are popular too, some small differences and twists. So it is highly
probable that you know the jokes already.&lt;/p>
&lt;p>In conclusion, if you already know or learning philosophy, then this book can be
a nice companion in the journey. But if like me, you are a fresher, then this
book may not be ideal, unless you wanted a book of jokes.&lt;/p></description></item><item><title>Twenty Two Goblins</title><link>https://arunmani.in/library/twenty-two-goblins/</link><pubDate>Thu, 11 Jan 2024 19:45:33 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/twenty-two-goblins/</guid><enclosure url="https://arunmani.in/library/twenty-two-goblins/cover.webp" length="1024" type="image/webp"/><description>&lt;p>When I was young, a friend of mine told me a story of three skilled men and
asked me who is the &lt;em>best&lt;/em> among them. I forgot what answer I gave. But I
started liking such stories where the conclusion is left to the reader.&lt;/p>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Vetala_Panchavimshati">Vikram-Vetala&lt;/a> is a story
about a king who is tasked by a sorcerer to bring a vampire to him. The vampire
tells the king a few stories. At the end of each story, the vampire asks the
king a question. If the king knows the answer but doesn&amp;rsquo;t reply, his head will
burst into pieces. If he answers, the vampire will escape back to its origin. So
for every story, the vampire flies back and the king goes back to fetch it. This
continues for about twenty two stories (or twenty five as per Wikipedia).&lt;/p>
&lt;p>After reading Mahabharata and a few other stories of Indian mythology, I thought
of reading Vikram-Vetala tales too. I used Wikipedia as a reference to suggest
me books. First I tried &lt;a href="https://archive.org/details/cu31924024159760">Richard Burton&amp;rsquo;s
retelling&lt;/a> but it was verbose
and its language not easy for me.&lt;/p>
&lt;p>Then I tried Twenty Two Goblins. The book suited me well because it was short
and the language felt like literal translation. Like, the author even translated
the names of people and cities to English.&lt;/p>
&lt;p>Most of the stories had a similar plot. A love affair and almost all of them a
&lt;em>love at the first site&lt;/em>. The answers by king were also just and reflective,
though a few controversial as per modern trends. Anyway, the stories flow
through the classical Indian rules of justice, hierarchy and authority, which is
good enough to keep you &lt;em>day dreaming&lt;/em>.&lt;/p>
&lt;p>Both of these books are in public domain, so you can read them right away 😇.&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://www.gutenberg.org/ebooks/2290">Twenty-Two Goblins in Project
Gutenberg&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.gutenberg.org/ebooks/2400">Vikram and the Vampire in Project Gutenberg&lt;/a>&lt;/li>
&lt;/ol></description></item><item><title>The Midnight Library</title><link>https://arunmani.in/library/the-midnight-library/</link><pubDate>Mon, 18 Sep 2023 21:34:19 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-midnight-library/</guid><enclosure url="https://arunmani.in/library/the-midnight-library/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Every moment in life, we have an infinite amount of choices though most of them
are hidden from our sight. This book is a reminder of the same.&lt;/p>
&lt;p>General narration to story, everything was nice. The book has short chapters
which is what people like me love.&lt;/p>
&lt;p>A non-spoiling gist of the story is it is about parallel world &lt;em>kinda&lt;/em> life
where each choice branches to a different one. The protagonist gets to live most
of those different lives of her and realize herself.&lt;/p>
&lt;p>I really like how this book has actual story instead of beating around the bush
with boring text on depression etc. That&amp;rsquo;s a big plus.&lt;/p>
&lt;p>Once you read the first few chapters, you will be able to predict the climax.
But still reading the book fully is needed to understand the &lt;em>why&lt;/em> of the
ending.&lt;/p>
&lt;p>In short, it is a very good story and a quick read too.&lt;/p></description></item><item><title>State of Stateless - DebConf 2023</title><link>https://arunmani.in/articles/state-of-stateless/</link><pubDate>Sun, 17 Sep 2023 21:29:49 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/articles/state-of-stateless/</guid><enclosure url="https://arunmani.in/articles/state-of-stateless/cover.webp" length="1024" type="image/webp"/><description>&lt;p>I presented &lt;a href="https://debconf23.debconf.org/talks/41-state-of-stateless-a-talk-about-immutability-and-reproducibility-in-debian/">this
talk&lt;/a>
in DebConf 2023, Kochi, India.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="state-of-stateless.pdf">Slides&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2023/DebConf23/debconf23-242-state-of-stateless-a-talk-about-immutability-and-reproducibility-in-debian.av1.webm">Video - 166
MB&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://meetings-archive.debian.net/pub/debian-meetings/2023/DebConf23/debconf23-242-state-of-stateless-a-talk-about-immutability-and-reproducibility-in-debian.lq.webm">Video - 81 MB&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Below is the gist.&lt;/p>
&lt;p>Debian is one of the most used Linux operating systems. While RPM based OSes
like Fedora, OpenSUSE are moving to Transaction-Rollback style package
management, the scenario in Debian is still untouched.&lt;/p>
&lt;p>In our talk, we explore and propose a user-perspective view on how a transaction
based system can be introduced in Debian. We discuss about various technologies
like layering of file system, taking advantage of BTRFS, and snapshot algorithms
etc.&lt;/p>
&lt;p>We also shed light on the new trends in Linux ecosystem like Flatpak, Nix, Guix
and similar isolated package management systems.&lt;/p>
&lt;p>Our talk is aimed at everyday users of Debian as the main motive of Debian is to
ensure stability, having a deterministic and reproducible packages ensures that
Debian systems can be deployed and used by users with least technical knowledge.
This also means that Debian can be used in enterprise institutes with a stable
base and fully-flexible changes to the packages in it. This can allow
reduced-downtime updates of applications and services.&lt;/p>
&lt;p>In short we enhance Debian’s 007 principle. 0 stability issues, 0 security
issues and 7000 reasons to use Debian.&lt;/p>
&lt;p>We highly believe that this talk will act as a stepping stone in bringing up the
features that shall enhance the traditional operating system metaphor.&lt;/p></description></item><item><title>Creating Blurred Background Image using ImageMagick</title><link>https://arunmani.in/articles/creating-blurred-background-image/</link><pubDate>Sun, 13 Aug 2023 09:55:41 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/articles/creating-blurred-background-image/</guid><enclosure url="https://arunmani.in/articles/creating-blurred-background-image/cover.webp" length="1024" type="image/webp"/><description>&lt;p>I get it, the title is confusing. Read along and you will understand.&lt;/p>
&lt;p>If you are new to the concept of images. An image of size &lt;code>100x200&lt;/code> means the
image is &lt;code>100&lt;/code> &lt;a href="https://en.wikipedia.org/wiki/Pixel">pixels&lt;/a> wide and &lt;code>200&lt;/code>
pixels in height.&lt;/p>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Aspect_ratio_(image)">Aspect ratio&lt;/a> is the ratio
of its width to height. For an image of size &lt;code>100x200&lt;/code>, the aspect ratio is
&lt;code>1:2&lt;/code> or &lt;code>0.5&lt;/code>. It means, for every for every unit of width, the height must be
twice the unit.&lt;/p>
&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>We want to resize an image of arbitrary size such that&lt;/p>
&lt;ol>
&lt;li>It matches aspect ratio &lt;code>x:y&lt;/code>.&lt;/li>
&lt;li>The aspect ratio of the original image is also respected.&lt;/li>
&lt;/ol>
&lt;p>Okay, say you have an image of size &lt;code>320x428&lt;/code> and you want to resize it to
&lt;code>600x300&lt;/code>.&lt;/p>
&lt;figure>&lt;img src="original.webp"
alt="An image of a cat of dimension 320x428"/>&lt;figcaption>
&lt;p>Photo by Alena Koval: &lt;a href="https://www.pexels.com/photo/orange-tabby-cat-on-brown-knitted-textile-982300/">https://www.pexels.com/photo/orange-tabby-cat-on-brown-knitted-textile-982300/&lt;/a> See how the cat is concerned about its size!&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>You can do a &lt;em>brute force&lt;/em> style of resizing the image. But.&lt;/p>
&lt;figure>&lt;img src="force-resized.webp"
alt="An image of a cat which has been forcefully resized to 600x300"/>&lt;figcaption>
&lt;p>Oh no, the cat lost his cool&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>As you can see, the forced resize gives off ugly results. And depending upon the
nature of the image, it can even become disastrous. Like, you don&amp;rsquo;t want to
do a &lt;em>forced resize&lt;/em> of a map or plot!&lt;/p>
&lt;h2 id="the-need">The Need&lt;/h2>
&lt;p>Now you might ask — &lt;em>why do resize at all?!&lt;/em> Because the world expects you to
🤷. For me, it was my website. If you go to the &lt;a href="https://arunmani.in/">homepage&lt;/a>, you will see how
the article and library cards are arranged neatly.&lt;/p>
&lt;p>It is because I have &lt;em>blurred their background and resized them&lt;/em> to a fixed
dimension of &lt;code>640x360&lt;/code>. If I didn&amp;rsquo;t do the resize,&lt;/p>
&lt;ol>
&lt;li>The cards will be of different size each.&lt;/li>
&lt;li>There will be an ugly empty space around images that don&amp;rsquo;t fit the card&amp;rsquo;s size.&lt;/li>
&lt;/ol>
&lt;p>As an example, see the below image. There are white spaces around my cat&amp;rsquo;s
image.&lt;/p>
&lt;figure>&lt;img src="bad-card.webp"
alt="An image that shows an image with white spaces surrounding it"/>
&lt;/figure>
&lt;p>For a website like mine, images come from various sources and they all have a
different aspect ratio and size. So doing a forceful resize without preserving
the original image&amp;rsquo;s aspect ratio is not good.&lt;/p>
&lt;h3 id="just-crop">Just Crop?&lt;/h3>
&lt;p>Yes, you can simply &lt;em>chop&lt;/em> of the segments and shape your image to the size you
like. But the problem with cropping is that it works only when your image&amp;rsquo;s size
is greater than the expected size.&lt;/p>
&lt;p>You can &lt;em>enlarge&lt;/em> the image but it leads to broken images. (Just try zooming a
very small image, and you will see how the pixels start breaking with every zoom).&lt;/p>
&lt;p>And obviously, cropping leads to the loss of data.&lt;/p>
&lt;h2 id="blurred-background-image">Blurred Background Image&lt;/h2>
&lt;p>Let me restate our objectives.
We want to resize an image of arbitrary size such that&lt;/p>
&lt;ol>
&lt;li>It matches aspect ratio &lt;code>x:y&lt;/code>.&lt;/li>
&lt;li>The aspect ratio of the original image is also respected.&lt;/li>
&lt;/ol>
&lt;p>The solution I use is like this&lt;/p>
&lt;ol>
&lt;li>Forcefully resize the image to the desired size, call it &lt;code>A&lt;/code>.&lt;/li>
&lt;li>Blur &lt;code>A&lt;/code> enough to cover the broken pixels.&lt;/li>
&lt;li>Do a ratio-preserving resize of the original image, call it &lt;code>B&lt;/code>.&lt;/li>
&lt;li>Put &lt;code>B&lt;/code> over &lt;code>A&lt;/code> and call it &lt;code>C&lt;/code>.&lt;/li>
&lt;li>&lt;code>C&lt;/code> is the resultant image.&lt;/li>
&lt;/ol>
&lt;p>You might have a question now — &lt;em>what is ratio-preserving resize?&lt;/em>
Say you have an image of size &lt;code>WxH&lt;/code> and your target image must be of size &lt;code>PxQ&lt;/code>. A
ratio-preserving resize scales the original image such that its size is less
that &lt;code>PxQ&lt;/code>. That is, the resized image of size &lt;code>MxN&lt;/code> will satisfy &lt;code>M &amp;lt;= P AND N &amp;lt;= Q AND M/N == W/H&lt;/code>.&lt;/p>
&lt;p>Taking back our cat example, the original image is of size &lt;code>320x428&lt;/code>. If we do
the ratio-preserving resize to &lt;code>600x300&lt;/code>, then it becomes &lt;code>224x300&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">320&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">428&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">0.7476635514018691&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">224&lt;/span>&lt;span style="color:#f92672">/&lt;/span>&lt;span style="color:#ae81ff">300&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">0.7466666666666667&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Both of their ratio is approximately equal to &lt;code>0.74&lt;/code>. Also see how our new image
fits within the &lt;code>600x300&lt;/code> requirement.&lt;/p>
&lt;p>We can impose this image on the force-resized-and-blurred image. That&amp;rsquo;s it, we
get a clean image of desired size.&lt;/p>
&lt;h3 id="why-blur">Why Blur?&lt;/h3>
&lt;p>Instead of blurring, you might want to use a solid color like &lt;em>white&lt;/em>, &lt;em>black&lt;/em>
or even &lt;em>transparency&lt;/em>. The issue with the &lt;em>constant&lt;/em> colors is that they are not
adaptive. For example, my site has both light theme and dark theme. Depending
upon your device settings, it chooses the color theme. Now, if I used a solid
color of white, then users of dark theme will find it ugly. Similarly, users of
light theme will find the black color background ugly.&lt;/p>
&lt;p>Transparency is not even option because it takes us back to original problem of
&lt;em>space around the image&lt;/em>!&lt;/p>
&lt;p>But blurring an image means the background is filled with the colors of the original
image. If your image has a pink background, then the target image is also
filled with pink background.&lt;/p>
&lt;p>Blurred background images are not anything new. They have been there for a
longtime. There are websites that lets you do it. There is a 110% chance that your
&lt;em>favorite image editor&lt;/em> already has a way to do it with less number of steps.&lt;/p>
&lt;p>If the idea is still unclear, then have a look at this Graphic Design question -
&lt;a href="https://graphicdesign.stackexchange.com/questions/96635/is-there-an-automatic-way-to-resize-images-to-a-specific-dimension-blur-backgr">Is there an automatic way to resize images to a specific dimension. (blur
background and not crop
image)&lt;/a>.&lt;/p>
&lt;h2 id="automating-it-using-imagemagick">Automating It Using ImageMagick&lt;/h2>
&lt;p>Actually, the main aim of the article is to tell you how to create the blurred
background using &lt;a href="https://imagemagick.org/">ImageMagick&lt;/a>.&lt;/p>
&lt;p>If you don&amp;rsquo;t know what ImageMagick is, then quoting from their website;&lt;/p>
&lt;blockquote>
&lt;p>ImageMagick® is a free, open-source software suite, used for editing and manipulating digital images. It can be used to create, edit, compose, or convert bitmap images, and supports a wide range of file formats, including JPEG, PNG, GIF, TIFF, and PDF.&lt;/p>
&lt;/blockquote>
&lt;p>But why ImageMagick? Because;&lt;/p>
&lt;blockquote>
&lt;p>One of the key features of ImageMagick is its support for scripting and automation. This allows users to create complex image manipulation pipelines that can be run automatically, without the need for manual intervention.This can be especially useful for tasks that require the processing of large numbers of images, or for tasks that need to be performed on a regular basis.&lt;/p>
&lt;/blockquote>
&lt;p>If you go through the website, you will realize how ImageMagick is one of
the best software that has been ever written.&lt;/p>
&lt;p>The commands I used here are for ImageMagick 7. They should work fine with
version 6 though. Depending upon your installation and version, the executable
could be either &lt;code>convert&lt;/code> or &lt;code>magick&lt;/code>&lt;/p>
&lt;h2 id="the-command">The Command&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>magick input.jpg &lt;span style="color:#ae81ff">\(&lt;/span> -clone &lt;span style="color:#ae81ff">0&lt;/span> -blur 0x9 -resize 640x360! &lt;span style="color:#ae81ff">\)&lt;/span> &lt;span style="color:#ae81ff">\(&lt;/span> -clone &lt;span style="color:#ae81ff">0&lt;/span> -resize 640x360 &lt;span style="color:#ae81ff">\)&lt;/span> -delete &lt;span style="color:#ae81ff">0&lt;/span> -gravity center -compose over -composite output.webp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>That is a pretty long command, but once you know the basics, it is very easy to
understand. On an overview, we can say ImageMagick takes an image &lt;code>input.jpg&lt;/code>,
does some &lt;em>magic&lt;/em> and saves the result as &lt;code>output.webp&lt;/code>. You can replace
&lt;code>input.jpg&lt;/code> and &lt;code>output.webp&lt;/code> with your image names.&lt;/p>
&lt;p>Let&amp;rsquo;s break down the command now!&lt;/p>
&lt;h3 id="image-sequence-and-parenthesis">Image Sequence and Parenthesis&lt;/h3>
&lt;p>The &lt;a href="https://legacy.imagemagick.org/Usage/basics/#image_lists">best explanation&lt;/a>
I have read is from ImageMagick documentation itself. Check it out, however I
will try my best too.&lt;/p>
&lt;p>ImageMagick works on a list of images. It means, to it, you give a list of
images, ask it to operate on them and save the result. The images can be
referenced by their position which starts from &lt;code>0&lt;/code>.&lt;/p>
&lt;p>Now the parentheses &lt;code>( )&lt;/code> is used to perform a set of operations and append the
result to the end of images list. It is a very powerful feature, because it
allows you to create a pipeline only for a specific set of images. In other
words, it saves you from creating temporary images and then merge them together.&lt;/p>
&lt;p>With this in mind, our command can be imagined to be like,&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>[input]--+-BLUR-+--[input, blurred]--+-RATIO_RESIZE-+--[input, blurred, resized]--...
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...--+-DELETE_0-+--[blurred, resize]--+-COMPOSITE-+--[output]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="blurring">Blurring&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">\(&lt;/span> -clone &lt;span style="color:#ae81ff">0&lt;/span> -blur 0x9 -resize 640x360! &lt;span style="color:#ae81ff">\)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This command blurs the input image (which is at index &lt;code>0&lt;/code>). But to be precise,
it doesn&amp;rsquo;t blur the input image but blurs a &lt;em>clone&lt;/em> of the input image. It
clones the image on index &lt;code>0&lt;/code>, blurs it and the resizes it to &lt;code>640x360&lt;/code>. The
exclamation symbol &lt;code>!&lt;/code> is to do a forced resize.&lt;/p>
&lt;p>The &lt;code>0x9&lt;/code> is radius (&lt;code>0&lt;/code>) and sigma (&lt;code>9&lt;/code>) of the blur. More details can be found
in &lt;a href="https://imagemagick.org/script/command-line-options.php#blur">&lt;code>blur&lt;/code>&amp;rsquo;s manual page&lt;/a>.&lt;/p>
&lt;p>Similarly, see &lt;a href="https://imagemagick.org/script/command-line-options.php#resize">&lt;code>resize&lt;/code>&amp;rsquo;s manual
page&lt;/a> and
&lt;a href="https://imagemagick.org/script/command-line-options.php#clone">&lt;code>clone&lt;/code>&amp;rsquo;s manual page&lt;/a>.&lt;/p>
&lt;h3 id="ratio-preserving-resize">Ratio-Preserving Resize&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">\(&lt;/span> -clone &lt;span style="color:#ae81ff">0&lt;/span> -resize 640x360 &lt;span style="color:#ae81ff">\)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Similar to blurring, we create a copy of the input and resize it to &lt;code>640x360&lt;/code>.
Note how there is no &lt;code>!&lt;/code> symbol at the end. It means we are doing a
ratio-preserving resize.&lt;/p>
&lt;h3 id="delete-input">Delete Input&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>-delete &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;a href="https://imagemagick.org/script/command-line-options.php#delete">&lt;code>delete&lt;/code>&lt;/a>
removes the image from the images list. (See the pipeline overview above). But,
remember, it doesn&amp;rsquo;t delete the file in anyway.&lt;/p>
&lt;p>We are deleting the input, because we don&amp;rsquo;t want it to be a part of the merge. Our
merge should happen between the blurred and resized image.&lt;/p>
&lt;h3 id="gravity">Gravity&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>-gravity center
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The blurred and resized images are of different sizes. We should now merge them.
But the resized image should be at the center of the blurred background.
&lt;a href="https://imagemagick.org/script/command-line-options.php#gravity">&lt;code>gravity&lt;/code>&lt;/a>
does that by moving the images to center.&lt;/p>
&lt;h3 id="compose">Compose&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>-compose over -composite
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;em>merge&lt;/em> process is called &lt;em>compose&lt;/em>.&lt;/p>
&lt;p>There are a lot of ways to &lt;em>add&lt;/em> two images together. Like you can add their
colors or subtract them etc. We want the resized image to placed &lt;em>over&lt;/em> the
blurred image. This is done using
&lt;a href="https://www.imagemagick.org/script/command-line-options.php#compose">&lt;code>compose&lt;/code>&lt;/a>
&lt;code>over&lt;/code>.&lt;/p>
&lt;p>Finally, we perform the &lt;em>composition&lt;/em> using
&lt;a href="https://www.imagemagick.org/script/command-line-options.php#composite">&lt;code>composite&lt;/code>&lt;/a>.&lt;/p>
&lt;p>The resulting image is saved as &lt;code>output.webp&lt;/code>.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>Applying the command to our cat image, we get,&lt;/p>
&lt;figure>&lt;img src="output.webp"
alt="The blurred background resize of the cat image"/>&lt;figcaption>
&lt;p>The cat is happy now!&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>Creating such images are not &lt;em>rocket science&lt;/em>, but having a handy command that
works offline and lets you do a rich set of operations is excellent.&lt;/p>
&lt;p>Hope you enjoyed the reading!&lt;/p></description></item><item><title>Jaya</title><link>https://arunmani.in/library/jaya/</link><pubDate>Thu, 03 Aug 2023 19:58:17 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/jaya/</guid><enclosure url="https://arunmani.in/library/jaya/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Since my childhood, I always wanted to read Mahabharta. I tried once in my
school days but didn&amp;rsquo;t have a nice time thanks to the number of characters and
the family tree.&lt;/p>
&lt;p>During my semester break, I thought I should try again but with a different
book. The main reason is that I wanted to read the philosophy.&lt;/p>
&lt;p>However, most of the books were really huge and had the old English. Then I
found this book in Quora.&lt;/p>
&lt;p>If you are beginner and like me — just wants the story without &lt;em>beating around
the bush&lt;/em>, then this is book for you. There are no paragraphs of adjectives or
&lt;em>simply talking&lt;/em>. The author comes to the point and has very crisp sentences.
Each of the chapter is very small and it manages to tell you the essence. Apart
from that, each chapter comes with a list of notes that talks about the
variations, contemporary nature etc.&lt;/p>
&lt;p>Such a wonderful book in itself. Highly recommended.&lt;/p>
&lt;p>Okay, my thoughts on Mahabharta itself? It is very cunning and smart way of
bending the rules, especially in the warfare. It is awesome. Though I feel like
it is injustice sometimes, the other voice in me says - &lt;em>it is what it is,
everything got perfectly balanced&lt;/em>. So, once again, really awesome.&lt;/p></description></item><item><title>The Graveyard Book</title><link>https://arunmani.in/library/the-graveyard-book/</link><pubDate>Thu, 03 Aug 2023 19:42:54 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-graveyard-book/</guid><enclosure url="https://arunmani.in/library/the-graveyard-book/cover.webp" length="1024" type="image/webp"/><description>&lt;p>This book was suggested to me by friend Mangesh.&lt;/p>
&lt;p>The title of the book itself was interesting and had an aroma of fantasy around
it. And as someone who loves fantasy like anything, I gave it a try.&lt;/p>
&lt;p>The book has a very simple synopsis. A family is murdered by a skilled murderer
but a baby manages to escape. This baby finds care in a graveyard by the very
ghosts. But the murderer is still looking for the baby. So the story is all
about how the boy (the grownup baby) meets the murderer and learns some &lt;em>really
twisty&lt;/em> secrets about why the murderer is very keen on killing him.&lt;/p>
&lt;p>With such a simple overview, you can get a &lt;em>sorta&lt;/em> story completion by reading
the first and last few chapters. The intermediate chapters feel like some random
happenings in the boy&amp;rsquo;s life. BUT. Only at the climax you get to understand why
all these intermediaries were there in the first place. Each and everyone of
them has a small contribution at the last.&lt;/p>
&lt;p>The book has a nice narration and so you won&amp;rsquo;t be bored if you ready a chapter a
day.&lt;/p>
&lt;p>What disappointed me is that the ending was a little vague. It just leaves you
incomplete without telling you &lt;em>what&amp;rsquo;s next?&lt;/em>, as if there is a sequel.&lt;/p>
&lt;p>Apart from that, the book was good!&lt;/p></description></item><item><title>Publishing Book with Emacs and OrgMode</title><link>https://arunmani.in/articles/publishing-book-emacs/</link><pubDate>Mon, 17 Jul 2023 19:29:28 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/articles/publishing-book-emacs/</guid><enclosure url="https://arunmani.in/articles/publishing-book-emacs/cover.webp" length="1024" type="image/webp"/><description>&lt;p>I coauthored my &lt;em>first&lt;/em> book — &lt;a href="https://www.yesdee.com/product/problem-solving-with-python-programming/">Problem Solving with Python
Programming&lt;/a>
&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>. The book was written entirely in &lt;a href="https://www.gnu.org/software/emacs/">GNU
Emacs&lt;/a> using &lt;a href="https://orgmode.org/">Org
mode&lt;/a> and exported as PDF using LaTeX. As a way of filling
the empty blog and also to thank the open source communities behind the
software, I decided to write this article.&lt;/p>
&lt;h2 id="brief-about-the-book-can-be-skipped">Brief About The Book (Can be skipped)&lt;/h2>
&lt;p>The book is written for the courses &lt;code>GE3151 Problem Solving and Python Programming&lt;/code> and &lt;code>GE3171 Problem Solving and Python Programming Laboratory&lt;/code> of
&lt;a href="https://en.wikipedia.org/wiki/Anna_University">Anna University&lt;/a>. The syllabus
is more about problem solving than Python and being a course mandatory for all
the engineering branches (so not just Computer Science and Engineering), it
doesn&amp;rsquo;t touch the deeper realms of Python like Object Oriented Programming (OOP)
etc.&lt;/p>
&lt;p>If you did the course wholeheartedly, then you would be able to replace Python
as your &lt;em>desk calculator&lt;/em> and use it as a handy tool for housekeeping tasks like
&lt;em>mass editing&lt;/em> of files etc.&lt;/p>
&lt;p>We sticked best to the syllabus because&lt;/p>
&lt;ul>
&lt;li>We didn&amp;rsquo;t want to overwhelm the reader (a student or teacher) with full blast
of Python.&lt;/li>
&lt;li>The important excuse — the book with the &lt;em>stick to syllabus&lt;/em> philosophy itself
drew about 500 pages. Adding more to it will increase the pages which
proportionally increases the cost of the book.&lt;/li>
&lt;/ul>
&lt;p>However for the chapters I wrote and code snippets I did, I tried my best
to advocate the principles I have learnt so far in my journey of using Python
(my favorite programming language).&lt;/p>
&lt;h2 id="it-started-in-my-first-year">It Started In My First Year&lt;/h2>
&lt;p>It started in the year 2020, when I finished my school and entered &lt;a href="https://en.wikipedia.org/wiki/Anna_University_Regional_Campus,_Coimbatore">Anna
University Regional Campus
Coimbatore&lt;/a>
for Bachelors of Engineering (B.E.) in Computer Science and Engineering (CSE). I
happen to be lucky to have my class advisor as the Python course instructor — Dr. Preethi J.&lt;/p>
&lt;p>Having learnt Python since my school days and also using &lt;a href="https://www.debian.org/">Debian
GNU/Linux&lt;/a>, I was one of the very few in my class who
signed up for B.E. CSE because of interest in computer science than other
reasons like &lt;em>job availability&lt;/em>, &lt;em>easy to graduate&lt;/em> etc. If I wanted to write my
college story, then it would be as lengthy as a book, but that is not what the
article is about. So let&amp;rsquo;s move forward.&lt;/p>
&lt;p>Because that I was the Class Representative during the first year, I established
a good name in the college. Once I had to meet my class advisor Dr. Preethi J
for something and that&amp;rsquo;s when she asked — &lt;em>&amp;ldquo;I and your senior Akila are writing
a book on Python, would you like to join us?&amp;rdquo;&lt;/em>.&lt;/p>
&lt;p>&lt;em>Akila&lt;/em>; she was my senior and I had already met her during the online
senior-junior meet-up (yes it was during the pandemic, so Google Meet). Being
someone who doesn&amp;rsquo;t easily say &lt;em>No&lt;/em> — I accepted the invite.&lt;/p>
&lt;h2 id="how-to-write-a-book">How To Write A Book?&lt;/h2>
&lt;p>We divided the syllabus. I was to write a unit (the syllabus contains 5 units)
and do the laboratory manual. I was in home (actually I was in home only for the
first and half a year because of the pandemic) and free of any classes because
of semester holidays. It was the time to start writing. &lt;em>But how?&lt;/em>&lt;/p>
&lt;p>Yes really, how do you write a book? I mean what software should you use? I have
used &lt;a href="https://www.libreoffice.org/">Libre Office&lt;/a>,
&lt;a href="https://www.scribus.net/">Scribus&lt;/a>, &lt;a href="https://www.lyx.org/">LyX&lt;/a> etc. since my
childhood but I was confused which one would be perfect. I was in no position to
use Microsoft Word because I can&amp;rsquo;t install Windows on my laptop and I can&amp;rsquo;t pay
for the software either. The online version needs a Microsoft account; which
means — &lt;em>No thanks, I will use something else&lt;/em>.&lt;/p>
&lt;p>I already dropped Scribus because I didn&amp;rsquo;t remember doing anything usefully in
it beyond some samples. So the first one in the list is Libre Office. The
biggest advantage of LO is that it is free and open source. The other authors
can also install it on their Windows OS. Moreover, if they decide to use
Microsoft Word, I can import the &lt;code>.docx&lt;/code> file in Libre Office. So in terms of
collaboration, it is a perfect tool. Next the graphical user interface means
easy to learn (actually it is discover-ability).&lt;/p>
&lt;p>But I really didn&amp;rsquo;t like to use Libre Office to write a book. It felt too
fragile.&lt;/p>
&lt;figure>&lt;img src="moving-image-word.webp"
alt="A meme that shows how moving an image in Microsoft Word changes the entire document alignment"/>&lt;figcaption>
&lt;p>Meme downloaded from &lt;a href="https://www.memedroid.com/memes/detail/3510839">https://www.memedroid.com/memes/detail/3510839&lt;/a>&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>The meme applies for Libre Office too in my opinion. Moreover, having to click
around the UI for everything felt annoying when you needed the same
configuration in another document. Because if you used a base template for all
documents and decided to make a small change in the template, now you have to
make the change in all the documents too.&lt;/p>
&lt;p>But apart from all these, the most important &lt;em>showstopper&lt;/em> for me was that I
didn&amp;rsquo;t manage to get syntax highlighting to work in Libre Office. I tried a bunch
of add-ons and solutions of Stack Overflow but they didn&amp;rsquo;t work. What is a
programming book without syntax highlighting? 🤷‍&lt;/p>
&lt;h2 id="here-comes-emacs">Here Comes Emacs&lt;/h2>
&lt;p>So now the option is to consider LyX. But. This is where a few brain cells left
in me woke up and said — &lt;em>Hey! If you are going to use LyX, why not use Emacs
itself?&lt;/em>. The beauty of LyX is that it gives you the beautiful LaTeX typeset PDF
without having to learn LaTeX. But if that was it, Org mode can do it already.
Instead of having to install a Qt application in my GNOME/Sway desktop, I can
simply use my existing Emacs installation. I was already a diehard Emacs
follower thanks to &lt;a href="https://github.com/doomemacs/doomemacs">Doom Emacs&lt;/a> and the
open source community in general. So using Emacs should be easy for me.&lt;/p>
&lt;p>Honestly speaking, looking back at the moment, the reason I chose Emacs that
time is because of laziness to install LyX and the voice inside me that kept
saying — &lt;em>Dude simply start writing, you can shift to other tools when needed&lt;/em>.
But now if you ask me if the choice was right — I can stand up and shout a BIG
YES!.&lt;/p>
&lt;p>Yes, using Emacs came with a massive set of advantages that was not visible at
the time of choosing. I have summarized it in the last sections.&lt;/p>
&lt;h2 id="so-org-mode-and-latex">So Org mode and LaTeX&lt;/h2>
&lt;figure>&lt;img src="emacs-learning-curve.webp"
alt="A meme that shows how the learning curve of Emacs is an endless spiral"/>&lt;figcaption>
&lt;p>Meme downloaded from &lt;a href="https://www.reddit.com/r/emacs/comments/fzwk6u/learning_curve_on_emacs/">https://www.reddit.com/r/emacs/comments/fzwk6u/learning_curve_on_emacs/&lt;/a>&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>Jokes aside, I&amp;rsquo;m not a power user of Emacs in any way. I have been able to use
Emacs because of Doom Emacs, which takes care of providing an amazing workflow.
I don&amp;rsquo;t write Elisp and my configuration (on-top-of Doom Emacs) is &lt;a href="https://gitlab.com/Arun-Mani-J/dotfiles/-/blob/main/.config/doom/config.el">hardly ten
lines&lt;/a>
I copied from various blogs and solutions to provide &lt;a href="http://www.gnu.org/software/emacs/manual/html_node/emacs/CUA-Bindings.html">CUA
Mode&lt;/a>,
enable paragraph filling etc.&lt;/p>
&lt;p>The next big thing is Org mode. I have used it just because I have seen people
making miracles with it. I tried maintaining a &lt;em>TODO&lt;/em> or &lt;em>Agenda&lt;/em> via Org mode
but it failed. However I do use &lt;a href="https://orgzly.com/">Orgzly&lt;/a> in my phone to remind me of birthdays,
but that&amp;rsquo;s a different story. I have exported Org files to PDF using &lt;code>pdflatex&lt;/code>
(available in Emacs via &lt;code>C-c C-e l p&lt;/code>). The beauty of LaTeX with the best
text-editing features provided by Emacs, makes Org mode a killer software.&lt;/p>
&lt;p>I accept, the experience of using Org mode was not butter-smooth. I occasionally
messed up indentation (Org mode uses indentation!) and had to switch to
&lt;code>text-mode&lt;/code> or open up the file in another text editor to fix the issue. Learning
Org mode syntax and keybindings took its own time. Once I look up and use it, I
felt confident but after an hour or day passes, I forgot the keybindings or
syntax and had to look up again. In short, the muscle memory took a long time to
build up.&lt;/p>
&lt;p>LaTeX? Don&amp;rsquo;t ask 🙂. I have been able to use LaTeX only because of software like
LyX and Org mode. I can proudly say that I know no LaTeX command by-heart before
writing the book and also after writing the book. To me LaTeX belongs to the
smartest of smartest people (no offense please!) and I don&amp;rsquo;t think I will learn
it any day soon.&lt;/p>
&lt;p>Org mode was good enough to hide 99% of LaTeX away from me and the remaining 1%
was available by web searches.&lt;/p>
&lt;p>Gathering my guts, I wrote my first unit (a single &lt;code>.org&lt;/code> file). This is the template
I used.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+TITLE&lt;/span>&lt;span style="color:#75715e">: Unit Name&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+OPTIONS&lt;/span>&lt;span style="color:#75715e">: author:nil date:nil title:nil H:4 num:2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>*&lt;span style="font-weight:bold"> Heading&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>… content goes here …
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It produced a good looking PDF without the author and date (which was not
irrelevant for a book). I had to tweak the limit of headings via &lt;code>H:4 num:2&lt;/code>
because some low-level headings were converted to definition lists. Obviously
this was with time-consuming web searches.&lt;/p>
&lt;p>If you used the above template, you did get a page that looks like this.&lt;/p>
&lt;figure>&lt;img src="initial-template-without-sh.webp"
alt="An image that shows the initial template file rendered a PDF page"/>
&lt;/figure>
&lt;p>But if you follow carefully, you must have noted that one of the reasons to
leave Libre Office — syntax highlighting, is absent! So we have to enable syntax
highlighting in the PDFs exported in Org mode. If you do a web search for &lt;em>Org
mode export syntax highlighting&lt;/em>, you see helpful &lt;a href="https://emacs.stackexchange.com/questions/20839/exporting-code-blocks-to-pdf-via-latex/20841#20841">Emacs Stack
Exchange&lt;/a>
threads.&lt;/p>
&lt;p>So you have to install &lt;a href="https://pygments.org/">Pygments&lt;/a> and add the following
to your Emacs config.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-el" data-lang="el">&lt;span style="display:flex;">&lt;span>(require &lt;span style="color:#e6db74">&amp;#39;org&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(require &lt;span style="color:#e6db74">&amp;#39;ox-latex&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(add-to-list &lt;span style="color:#e6db74">&amp;#39;org-latex-packages-alist&lt;/span> &lt;span style="color:#f92672">&amp;#39;&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;minted&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(setq org-latex-listings &lt;span style="color:#e6db74">&amp;#39;minted&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(setq org-latex-pdf-process
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#39;&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This gives us a syntax highlighted PDF like this.&lt;/p>
&lt;figure>&lt;img src="initial-template-with-sh.webp"
alt="An image that shows the rendered PDF with syntax highlighting"/>
&lt;/figure>
&lt;h2 id="shaping-for-lab-manual">Shaping for Lab Manual&lt;/h2>
&lt;p>With the above template, everything worked well for unit. But once I started
writing lab manual, it became a little difficult because of two issues:&lt;/p>
&lt;ol>
&lt;li>Maintenance of programs.&lt;/li>
&lt;li>Creation of flowcharts.&lt;/li>
&lt;/ol>
&lt;h3 id="maintenance-of-programs">Maintenance of Programs&lt;/h3>
&lt;p>Though Emacs provided syntax highlighting and automatic indentation while
editing code blocks in an Org file, it is very much limited. Once your program
goes past hundred lines, you wish there was full-fledged Python environment that
provided auto-completion and formatting.&lt;/p>
&lt;p>To aid in this task, Org mode has &lt;a href="https://orgmode.org/manual/Include-Files.html">&lt;code>#+INCLUDE: file.py src python&lt;/code>&lt;/a> directive that adds
&lt;code>file.py&lt;/code> to the Org document as a code block. It means I can edit the file as
an ordinary Python file and while exporting the PDF it will be properly included
with all the goodies.&lt;/p>
&lt;h3 id="creation-of-flowcharts">Creation of Flowcharts&lt;/h3>
&lt;p>Now comes the task of creating flowcharts. For someone who sucks at any kind of
artistic creativity, making flowcharts using a GUI tool is very difficult
because of the &lt;em>click-click&lt;/em> process. I thought it would be great if there was a
software that drew flowcharts from a text file containing the rules.&lt;/p>
&lt;p>AT&amp;amp;T Labs Research faced the same issue and designed the golden
&lt;a href="https://graphviz.org/">Graphviz&lt;/a>. After skimming over a few tutorials and
understanding the syntax, I was able to make flowcharts.&lt;/p>
&lt;p>Like any other Emacsen, I wanted a way to edit the &lt;code>.gv&lt;/code> files inside Emacs and
found &lt;a href="https://github.com/ppareit/graphviz-dot-mode">graphviz-dot-mode&lt;/a>.&lt;/p>
&lt;p>One issue, I haven&amp;rsquo;t been able to resolve in Graphviz yet is making the edges
come out of the vertices instead of anywhere in the shape. However I ignored it for
all flowcharts except a few. For the few, I used
&lt;a href="https://app.diagrams.net/">draw.io&lt;/a> (and draw.io is great!).&lt;/p>
&lt;h2 id="getting-a-publisher">Getting a Publisher&lt;/h2>
&lt;p>The first year became second year and the second year became third year. We all
became busy in our own works and the book writing came to a temporary halt because the
syllabus was about to change.&lt;/p>
&lt;p>Once the new syllabus came (which luckily had less changes) we thought to hurry
up the process. To hurry up means to get a publisher, because once we knew
someone is waiting, we would try to finish the work as soon as possible. We
tried a few big academic publishers but they were reluctant to accept the proposal
because the &lt;em>coauthors were students&lt;/em>. Yes. They didn&amp;rsquo;t accept because they
don&amp;rsquo;t take books from students except PhD students. However they were ready if
we agreed that only our professor is the author. Means the book will have only
our professor&amp;rsquo;s name.&lt;/p>
&lt;p>Thankfully, our professor didn&amp;rsquo;t go with it. We then got help from college
librarian and got contact of a publisher named
&lt;a href="https://www.yesdee.com/">Yes Dee&lt;/a>.&lt;/p>
&lt;p>The company&amp;rsquo;s managing director and technical editor met us in college and they
were really happy to see that the book was written by students. So that was it,
they accepted our proposal and we signed the contracts.&lt;/p>
&lt;p>After many topics, our discussion came to the manuscript format. Our professor
pointed to me and said that I&amp;rsquo;m using LaTeX to type the book. I took my laptop
and showed them the units and lab manual I have written so far.&lt;/p>
&lt;p>The publishing team said that since I knew LaTeX already, they would give me the
guidelines for the book like fonts, layout, dimensions and I was to give them
the final PDF as per the guidelines.&lt;/p>
&lt;p>Yes 🙂. They assumed I know LaTeX. I till, the moment of the very sentence,
thought that we can submit the manuscript is any legible format and publisher
would take care of shaping it to the right layout.&lt;/p>
&lt;p>May be my assumption was wrong or it was my luck, I do not know. I didn&amp;rsquo;t deny
the offer because of two reasons:&lt;/p>
&lt;ol>
&lt;li>If I denied because I don&amp;rsquo;t know LaTeX then my professor would be upset
because I had convinced her LaTeX is the best option over Microsoft Word. I
promised her that I would take care of any issues arising due to this choice.&lt;/li>
&lt;li>I felt that if I did the formatting then I can make any changes required to
their guidelines wherever deemed fit.&lt;/li>
&lt;/ol>
&lt;p>Whatever it was, I accepted and we were to submit the final PDF in a month. I
still told them that I don&amp;rsquo;t know LaTeX much and they said they will help me. 😁&lt;/p>
&lt;h2 id="sudden-fear">Sudden Fear&lt;/h2>
&lt;p>Since I was supposed to format and submit the PDF, I was stuck by fear and doubt
if I will be able to do it. I didn&amp;rsquo;t use LaTeX directly but LaTeX on top of
Org mode. So every issue I face has to be first checked against Org mode and then
LaTeX.&lt;/p>
&lt;p>This was the moment, on a fine Sunday, I was questioning myself if by using
Org mode I have made the biggest mistake. Had I used LaTeX directly, then I can
ask in LaTeX forums directly but with having Org mode as an interface I had to
explain them Org mode too, which might affect the answers.&lt;/p>
&lt;p>So I thought — &lt;em>okay, let us use LyX&lt;/em>. Org mode already produced &lt;code>.tex&lt;/code> files
during PDF export, I thought of importing them in LyX and drop the dependency of
having to use Emacs completely. I also convinced myself that it would allow
other coauthors to collaborate as it is easy for them to use LyX than learn and
use Emacs.&lt;/p>
&lt;p>Importing the &lt;code>.tex&lt;/code> file didn&amp;rsquo;t go smooth though. Some LaTeX commands inserted
by Org mode didn&amp;rsquo;t compile in LyX. And I was already counting my luck. &lt;em>Okay!&lt;/em> A
new idea comes. &lt;em>Let us copy paste the paragraphs into a new LyX file itself and
make the necessary formatting.&lt;/em> It is a tedious job but I forced myself to do
it. I tried a chapter but couldn&amp;rsquo;t go through it. Clicking the buttons, enabling
syntax highlighting and so and so, it was a pain.&lt;/p>
&lt;p>I gathered hope again. &lt;em>No, stop it.&lt;/em> I told myself that whatever it is, I will
stick to Emacs and finish it. If I couldn&amp;rsquo;t do it, I will let the publisher
know. I don&amp;rsquo;t know what gave me that hope but it worked! Importing the entire
book into LyX itself would have taken a week (remember, I have classes from 9 AM
to 5 PM and other works too) and could have caused more harm than good.&lt;/p>
&lt;p>Back to Emacs.&lt;/p>
&lt;h2 id="merging-chapters">Merging Chapters&lt;/h2>
&lt;p>A lot changed after we met the publisher. Our professor said that breaking the
five units into individual chapters would be a good idea. I agree because they
are more easy to follow than grasping an entire unit. As the other coauthor was
busy with her placements and I was assigned two more units. My professor said
she will take care of solved questions and exercises for every chapter.&lt;/p>
&lt;p>Writing has never been an issue for me, if needed I could have written the
entire book because Python is my favorite language and I loved writing about it.&lt;/p>
&lt;p>But, merging other people&amp;rsquo;s work was very hectic. It was &lt;code>.docx&lt;/code> files from the
other coauthors. I opened them in Libre Office, copy pasted them in &lt;code>.org&lt;/code> file
and reformatted them. This I did paragraph by paragraph. Copy in Libre Office.
Paste in Emacs. Reformat the paragraph and replicate the bold, italics etc.
Repeat.&lt;/p>
&lt;p>Sometimes the &lt;code>.docx&lt;/code> files had images and I had to save them using Libre Office
&lt;code>Right Click -&amp;gt; Save&lt;/code> and then insert it in Emacs. Images come with their own
headaches. I had to resize the image and make sure its placement doesn&amp;rsquo;t affect
the other text.&lt;/p>
&lt;p>A little by little, I converted all the Word files to Org. After making the
changes, I emailed the chapters to the editor at the publishing company. The
editor, she must have had a lot of patience, reading through the text and
marking up the changes. I on the other hand, fixed them. The grammatical
corrections were easy. The changes regarding layout were trouble. It means I had
to step into LaTeX world and hunt for the commands. It was a nightmare. This
process went for around three times I think.&lt;/p>
&lt;h2 id="final-steps">Final Steps&lt;/h2>
&lt;p>I created all the pages from the front page, copyright, acknowledgments to
chapters in Org mode and exported them as PDFs. I then combined the PDFs together
using Ghostscript.&lt;/p>
&lt;p>After ensuring that all the corrections have been made, the book went for
printing. After a month, we received the authors&amp;rsquo; copies last week. It felt so
great to have your time and efforts as a physical item in your hands.&lt;/p>
&lt;p>I smiled at the book and told myself — &lt;em>Yes! I did it. I did it using Emacs and
Org mode&lt;/em>. It is not a flex but a reminder that I did that even though I doubted
myself. Looking back, it feels like a lovely nightmare. 🙈&lt;/p>
&lt;h2 id="the-right-choice">The Right Choice&lt;/h2>
&lt;p>Did I make the right choice by using Emacs and Org mode instead of something
else? With the book in my hand, I can say yes. Doing it this way gave its own
set of advantages.&lt;/p>
&lt;p>Everything is text. Org files are text files, they can be edited in any text
editor, though Emacs has the best interface to &lt;em>interact&lt;/em> with Org files. Text
is the universal format. Because of this fact, I was able to edit the Org files
in various ways. Like, I could do some complicated &lt;em>search and replace&lt;/em> using
Python etc.&lt;/p>
&lt;p>The best of all is that any change in template is just addition or removal of
few lines of text. So I can simply copy paste it in all the files. Add this to
the powerful Emacs commands, you have everything in your reach.&lt;/p>
&lt;p>Now compare it with using word processors like Libre Office. I think they save
their files in some form of XML. Every change would be accompanied with a number
of mouse clicks, pop-ups, menus etc. Going from the simple text format to a word
processor would have been like tying my hands.&lt;/p>
&lt;p>But every advantage comes with its own disadvantage. Using Emacs made it a sort
of vendor lock-in. Only I could do the formatting work because the other
coauthors used Windows. Installing Emacs, LaTeX in Windows and making them learn
it might be difficult.&lt;/p>
&lt;p>During the corrections phase, my senior and coauthor Akila helped with
grammatical corrections. I asked her to install &lt;a href="https://github.com/vscode-org-mode/vscode-org-mode">VSCode
Org mode&lt;/a> plugin to at least
get the syntax highlighting of Org files. But she was limited to grammatical
corrections. Anything beyond like layout or formatting needed LaTeX knowledge,
so I had to it. This way I ended up being the pressure bearer.&lt;/p>
&lt;p>May be if there was a web app of Emacs with all the goodies, it could have
helped but none existed when I searched.&lt;/p>
&lt;p>The next disadvantage is that most of the commands, Elisp code I used where
blind copy-paste with a very little knowledge of what&amp;rsquo;s happening underneath. If
something broke, I had to search the error and fix it. Because I didn&amp;rsquo;t know
LaTeX or Org mode well, it was a slow process.&lt;/p>
&lt;p>Had there been a major version upgrade in LaTeX or Org mode such that the
commands from five to ten years old didn&amp;rsquo;t work, then I would have been in a BIG
TROUBLE.&lt;/p>
&lt;p>But luckily nothing of that sort happened. Good software lasts long. Emacs and
LaTeX did for me. I&amp;rsquo;m happy for them.&lt;/p>
&lt;h2 id="technical-details">Technical Details&lt;/h2>
&lt;p>If you wanted me to &lt;em>shut up&lt;/em> and &lt;em>show the code&lt;/em>, then there you go. I will try
my best to explain the commands and organization of the source files.&lt;/p>
&lt;h3 id="setting-up-emacs">Setting up Emacs&lt;/h3>
&lt;p>I used &lt;a href="https://github.com/doomemacs/doomemacs">Doom Emacs&lt;/a>. Though I haven&amp;rsquo;t
tried, nothing I did is exclusive to Doom Emacs and should work with other
variants too as long as Org mode exists.&lt;/p>
&lt;h3 id="setting-up-latex">Setting up LaTeX&lt;/h3>
&lt;p>The next step is to install LaTeX. The way of installation depends upon your OS.
I started from a standard install and installed extra packages as needed. If you
are using Debian GNU/Linux, then the following command should suffice.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo apt install texlive texlive-latex-extra texlive-plain-generic --no-install-recommends
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I have added &lt;code>--no-install-recommends&lt;/code> to avoid cluttering with unnecessary
packages like X11 tools.&lt;/p>
&lt;h3 id="miscellaneous-packages">Miscellaneous Packages&lt;/h3>
&lt;p>Once you have installed LaTeX, you need to install some other helpful packages.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo apt install ghostscript imagemagick mupdf-tools python3-pygments
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;a href="https://www.ghostscript.com/">Ghostscript&lt;/a> for merging PDFs.&lt;/li>
&lt;li>&lt;a href="https://imagemagick.org/">ImageMagick&lt;/a> for editing images.&lt;/li>
&lt;li>&lt;a href="https://www.mupdf.com/">MuPDF&lt;/a> for extracting table of contents.&lt;/li>
&lt;li>&lt;a href="https://pygments.org/">Pygments&lt;/a> for source code highlighting.&lt;/li>
&lt;/ul>
&lt;h3 id="enabling-syntax-highlighting">Enabling Syntax Highlighting&lt;/h3>
&lt;p>To enable syntax highlighted code blocks in PDFs, you need to add the following
lines to your Emacs config.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-el" data-lang="el">&lt;span style="display:flex;">&lt;span>(require &lt;span style="color:#e6db74">&amp;#39;org&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(require &lt;span style="color:#e6db74">&amp;#39;ox-latex&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(add-to-list &lt;span style="color:#e6db74">&amp;#39;org-latex-packages-alist&lt;/span> &lt;span style="color:#f92672">&amp;#39;&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;minted&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(setq org-latex-listings &lt;span style="color:#e6db74">&amp;#39;minted&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(setq org-latex-pdf-process
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#39;&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="organization">Organization&lt;/h3>
&lt;p>I wrote each chapter in a separate Org file. The advantage is easy to maintain
but the disadvantage is that I had to manually set the page number of the first
page and then merge them properly.&lt;/p>
&lt;h3 id="the-template">The Template&lt;/h3>
&lt;p>The &lt;code>.org&lt;/code> file I used as template for all the chapters is as follows.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+title&lt;/span>&lt;span style="color:#75715e">: 4 Control Flow&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_CLASS&lt;/span>&lt;span style="color:#75715e">: extarticle&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage[paperwidth=152.4mm,paperheight=228.6mm]{geometry}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \geometry{verbose,tmargin=25.95mm,bmargin=19.3mm,lmargin=16.2mm,rmargin=16.2mm}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \setcounter{page}{143}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage{minted}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usemintedstyle{bw}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \setminted{frame=lines,breaklines=true}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage{fancyhdr}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \pagestyle{fancy}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhf{}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[LE]{Problem Solving and Python Programming}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[RE]{\thepage}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[LO]{\ifnum \thepage=143 \textbf{\Huge{4}} \else \thepage \fi}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[RO]{\ifnum \thepage=143 \textbf{\Huge{Control Flow}} \else Control Flow \fi}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \renewcommand*{\thesection}{4.\arabic{section}}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+OPTIONS&lt;/span>&lt;span style="color:#75715e">: author:nil date:nil toc:nil title:nil H:4 num:2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \tolerance=1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \emergencystretch=\maxdimen&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \hyphenpenalty=10000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \hbadness=10000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>*&lt;span style="font-weight:bold"> Verbatim&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+begin_src &lt;/span>&lt;span style="color:#75715e">text&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>Monospaced Text
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+end_src&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>*&lt;span style="font-weight:bold"> Code&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+begin_src &lt;/span>&lt;span style="color:#75715e">python&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">for&lt;/span> i &lt;span style="color:#f92672">in&lt;/span> range(&lt;span style="color:#ae81ff">10&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(&lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+end_src&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>*&lt;span style="font-weight:bold"> Unnumbered Heading&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">:PROPERTIES:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e"> :UNNUMBERED: t
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">:END:&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let us go through it part by part.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+title&lt;/span>&lt;span style="color:#75715e">: 4 Control Flow&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_CLASS&lt;/span>&lt;span style="color:#75715e">: extarticle&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage[paperwidth=152.4mm,paperheight=228.6mm]{geometry}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \geometry{verbose,tmargin=25.95mm,bmargin=19.3mm,lmargin=16.2mm,rmargin=16.2mm}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \setcounter{page}{143}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The first line sets the chapter title. Next to it we set the LaTeX class to
&lt;a href="https://www.ctan.org/tex-archive/macros/latex/contrib/extsizes">&lt;code>extarticle&lt;/code>&lt;/a>
which allows extra font sizes. See this
&lt;a href="https://superuser.com/questions/896741/how-do-i-configure-org-latex-classes-in-emacs">post&lt;/a>
for more details.&lt;/p>
&lt;p>Then we set the page dimensions followed by the margin at each side. The top
margin is more than bottom margin because top of the page contains the chapter
header. (Reduce it and see, to know what I&amp;rsquo;m saying). Finally we set the page
number of the first page in the chapter.&lt;/p>
&lt;p>Determining the page number is a two-way process. First you compile all the
chapters with page counter as 1. This way you get to know how many pages each
chapter has and note it down in a file. After that, you set the page counters to
the values noted.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage{minted}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usemintedstyle{bw}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \setminted{frame=lines,breaklines=true}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here we tell LaTeX to use &lt;a href="https://github.com/gpoore/minted">minted&lt;/a> for code
snippets. This will take care of printing the code with syntax highlighting. I&amp;rsquo;m
using &lt;em>black and white&lt;/em> &lt;code>bw&lt;/code> style because the book would be printed in black and
white. Then we put each code block between two lines. &lt;code>breaklines=true&lt;/code> makes
sure LaTeX breaks the lengthy lines into newlines (that is &lt;em>wrapping&lt;/em>) instead
of letting them run past the margin.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage{fancyhdr}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \pagestyle{fancy}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhf{}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[LE]{Problem Solving and Python Programming}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[RE]{\thepage}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[LO]{\ifnum \thepage=143 \textbf{\Huge{4}} \else \thepage \fi}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[RO]{\ifnum \thepage=143 \textbf{\Huge{Control Flow}} \else Control Flow \fi}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>It is time to style the headers of each page using
&lt;a href="https://ctan.org/pkg/fancyhdr?lang=en">fancyhdr&lt;/a>. The layout of the header is
simple. The publisher told me that every new chapter should start at the right
hand side. If the chapter ends in right, then I was supposed to add a blank
page, so that the next chapter starts in the right.&lt;/p>
&lt;p>In the configuration above, &lt;code>L&lt;/code> means &lt;em>left&lt;/em>, &lt;code>R&lt;/code> means &lt;em>right&lt;/em>, &lt;code>E&lt;/code> means
&lt;em>even&lt;/em> and &lt;code>O&lt;/code> means &lt;em>odd&lt;/em>. The header is divided into three parts — left,
center and right. This header can be in an even page or odd page.&lt;/p>
&lt;p>If you use &lt;em>right-odd&lt;/em> numbering system (where the right hand side contains odd
page numbers), then every new chapter will be on an odd page. So the layout I
used is as follows:&lt;/p>
&lt;ul>
&lt;li>On every even page (left hand side), put the book title at the left corner and
the page number at the right corner.&lt;/li>
&lt;li>For every odd page,
&lt;ul>
&lt;li>If the page is the starting page of a chapter &lt;code>\ifnum \thepage=143&lt;/code>, then we
put the chapter number at the left corner and chapter name at the right
corner in a huge font size.&lt;/li>
&lt;li>Else, the page number at the left corner and chapter name at the right
corner.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>Here &lt;code>143&lt;/code> is the page number at which the chapter starts and has to be set
properly as we did with the page counter.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \renewcommand*{\thesection}{4.\arabic{section}}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+OPTIONS&lt;/span>&lt;span style="color:#75715e">: author:nil date:nil toc:nil title:nil H:4 num:2&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The first command adds &lt;code>4.&lt;/code> to every section number. Here the number &lt;code>4&lt;/code> denotes
the chapter number. So sections in this chapter come out like &lt;code>4.1&lt;/code>, &lt;code>4.1.1&lt;/code>,
&lt;code>4.2&lt;/code> etc.&lt;/p>
&lt;p>The next command turns off displaying of author, date, table of contents and
title. Then it sets the depth of sections.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \tolerance=1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \emergencystretch=\maxdimen&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \hyphenpenalty=10000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \hbadness=10000&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>All these four commands work toward one common goal — to prevent hyphenation of
words altogether. This was a requirement from the publisher. These commands made
sure that if a word had to be hyphenated, then it must be in the next line
without any breakage.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>*&lt;span style="font-weight:bold"> Verbatim&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+begin_src &lt;/span>&lt;span style="color:#75715e">text&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>Monospaced Text
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+end_src&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>*&lt;span style="font-weight:bold"> Code&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+begin_src &lt;/span>&lt;span style="color:#75715e">python&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">for&lt;/span> i &lt;span style="color:#f92672">in&lt;/span> range(&lt;span style="color:#ae81ff">10&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(&lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+end_src&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>*&lt;span style="font-weight:bold"> Unnumbered Heading&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">:PROPERTIES:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e"> :UNNUMBERED: t
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">:END:&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>These are not part of the template but to help me remember the syntax for
frequently used content. The important one is &lt;code>:UNNUMBERED: t&lt;/code> which made sure
that the corresponding heading isn&amp;rsquo;t numbered in the output. It was necessary
for the headings like solved questions and exercises at the end of the chapter,
which shouldn&amp;rsquo;t be numbered.&lt;/p>
&lt;h3 id="creating-table-of-contents">Creating Table of Contents&lt;/h3>
&lt;p>The issue with table of contents and other front matter is that they use Roman
numbering. Because of this, &lt;code>\ifnum \thepage=143&lt;/code> command to set the header
depending upon the value of page number (&lt;code>\thepage&lt;/code>) doesn&amp;rsquo;t work with Roman
numbers.&lt;/p>
&lt;p>I tried searching the web but didn&amp;rsquo;t find any solution that works with
&lt;code>fancyhdr&lt;/code>. Since the number of pages is less in number, I split the ToC into
two Org files. The first Org file has a header and the other Org file do not.&lt;/p>
&lt;p>For the listings of the chapter itself, I merged all the chapters using
Ghostscript and then extracted the table of contents using MuPDF. Then I used a
Python script to convert the ToC to the section listings.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+title&lt;/span>&lt;span style="color:#75715e">: Table of Contents&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_CLASS&lt;/span>&lt;span style="color:#75715e">: extarticle&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage[paperwidth=152.4mm,paperheight=228.6mm]{geometry}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \geometry{verbose,tmargin=25.95mm,bmargin=19.3mm,lmargin=16.2mm,rmargin=16.2mm}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \pagenumbering{roman}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \setcounter{page}{7}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage{fancyhdr}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \pagestyle{fancy}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhf{}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \renewcommand{\headrulewidth}{0pt}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+OPTIONS&lt;/span>&lt;span style="color:#75715e">: author:nil toc:nil title:nil date:nil H:4 num:2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \tolerance=1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \emergencystretch=\maxdimen&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \hyphenpenalty=10000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \hbadness=10000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+BEGIN_EXPORT &lt;/span>&lt;span style="color:#75715e">latex&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\begin&lt;/span>{center}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\textbf&lt;/span>{&lt;span style="color:#66d9ef">\Large&lt;/span>{Contents}}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\end&lt;/span>{center}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+END_EXPORT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+BEGIN_EXPORT &lt;/span>&lt;span style="color:#75715e">latex&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\contentsline&lt;/span> {section}{&lt;span style="color:#66d9ef">\numberline&lt;/span> {}{&lt;span style="color:#66d9ef">\emph&lt;/span>{Preface}}}{xix}{section}&lt;span style="color:#75715e">%
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">\contentsline&lt;/span> {section}{&lt;span style="color:#66d9ef">\numberline&lt;/span> {}{&lt;span style="color:#66d9ef">\emph&lt;/span>{Acknowledgements}}}{xxi}{section}&lt;span style="color:#75715e">%
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\begin&lt;/span>{center}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\textbf&lt;/span>{Problem Solving with Python Programming}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\end&lt;/span>{center}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\contentsline&lt;/span> {section}{&lt;span style="color:#66d9ef">\numberline&lt;/span> {1}{Computational Thinking}}{3--94}{section}&lt;span style="color:#75715e">%
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">\contentsline&lt;/span> {subsection}{&lt;span style="color:#66d9ef">\numberline&lt;/span> {1.1}Fundamentals of Computing}{3}{subsection}&lt;span style="color:#75715e">%
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">\contentsline&lt;/span> {subsubsection}{&lt;span style="color:#66d9ef">\numberline&lt;/span> {1.1.1}Variables}{3}{subsubsection}&lt;span style="color:#75715e">%
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">\contentsline&lt;/span> {subsection}{&lt;span style="color:#66d9ef">\numberline&lt;/span> {1.2}Identification of Computational Problems}{3}{subsection}&lt;span style="color:#75715e">%
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">\contentsline&lt;/span> {subsubsection}{&lt;span style="color:#66d9ef">\numberline&lt;/span> {1.2.1}Decision Problems}{3}{subsubsection}&lt;span style="color:#75715e">%
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>…
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+END_EXPORT&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Everything is same as the normal template except the fact that I wrote LaTeX
directly for the listings. It is pretty hard-coded, so every time the pages in
the chapters change, I have to change the table of contents too.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+BEGIN_EXPORT &lt;/span>&lt;span style="color:#75715e">latex&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\begin&lt;/span>{center}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\textbf&lt;/span>{&lt;span style="color:#66d9ef">\Large&lt;/span>{Contents}}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\end&lt;/span>{center}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+END_EXPORT&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This code block is present only at the title page but for the remaining I use
the below template.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+title&lt;/span>&lt;span style="color:#75715e">: Table of Contents&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_CLASS&lt;/span>&lt;span style="color:#75715e">: extarticle&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage[paperwidth=152.4mm,paperheight=228.6mm]{geometry}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \geometry{verbose,tmargin=25.95mm,bmargin=19.3mm,lmargin=16.2mm,rmargin=16.2mm}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \pagenumbering{roman}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \setcounter{page}{8}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage{fancyhdr}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \pagestyle{fancy}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhf{}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \renewcommand{\headrulewidth}{0pt}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[LE]{Contents}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[RE,LO]{\thepage}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \fancyhead[RO]{Contents}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+OPTIONS&lt;/span>&lt;span style="color:#75715e">: author:nil toc:nil title:nil date:nil H:4 num:2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \tolerance=1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \emergencystretch=\maxdimen&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \hyphenpenalty=10000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \hbadness=10000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+BEGIN_EXPORT &lt;/span>&lt;span style="color:#75715e">latex&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">\contentsline&lt;/span> {subsubsection}{&lt;span style="color:#66d9ef">\numberline&lt;/span> {1.9.2}Shapes}{34}{subsubsection}&lt;span style="color:#75715e">%
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">\contentsline&lt;/span> {subsection}{&lt;span style="color:#66d9ef">\numberline&lt;/span> {}Solved Problems}{35}{subsection}&lt;span style="color:#75715e">%
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>…
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+END_EXPORT&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="designing-front-matter">Designing Front Matter&lt;/h3>
&lt;p>The other pages present in front matter includes title page, copyright, table of
contents, preface, acknowledgments etc. For those all, I used the following
template.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-org" data-lang="org">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+title&lt;/span>&lt;span style="color:#75715e">: Dedication&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_CLASS&lt;/span>&lt;span style="color:#75715e">: extarticle&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \usepackage[paperwidth=152.4mm,paperheight=228.6mm]{geometry}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \geometry{verbose,tmargin=19.3mm,bmargin=19.3mm,lmargin=16.2mm,rmargin=16.2mm}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \thispagestyle{empty}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \pagenumbering{roman}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+LATEX_HEADER&lt;/span>&lt;span style="color:#75715e">: \setcounter{page}{5}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+OPTIONS&lt;/span>&lt;span style="color:#75715e">: title:nil toc:nil author:nil date:nil H:3 num:nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+BEGIN_EXPORT &lt;/span>&lt;span style="color:#75715e">latex&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>…content…
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#+END_EXPORT&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="finishing-up">Finishing Up&lt;/h3>
&lt;p>With the above templates I created the front matter and content PDFs. Then
combined them using Ghostscript. For about 500 pages, it came about 5 MB.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>That was it. This was my path of ambiguities and errors to successfully publish
the book. Success of the book itself is not known yet but I was more excited
about the launch phase itself.&lt;/p>
&lt;p>Will I use Emacs again if I had to publish another book? Pretty sure, once you
are comfortable with the process, you are ready for another dose 😉.&lt;/p>
&lt;p>I also frankly admit that there could have been a better way but I did what I
could with the tight deadline. I&amp;rsquo;m open to ideas on how it can be improved 😁.&lt;/p>
&lt;p>For a formal conclusion, hear me out. Book writing (means the text itself, not
the formatting, LaTeX or Org mode) is a process where you (re)evaluate what you
understood. I have heard the saying that &lt;em>if you can&amp;rsquo;t explain something to
someone then you haven&amp;rsquo;t understood it in the first place&lt;/em>. Leaving aside the
rigorous rules, the saying is really apt.&lt;/p>
&lt;p>Explaining the concepts like string slicing with negative indices were not so
easy. I rewrote the paragraphs again and again until I felt confident that the
words were easy. Sometimes I had to cross check my understanding to ensure that
I don&amp;rsquo;t provide wrong information.&lt;/p>
&lt;p>Definitions are a thing on another level. In my opinion a definition or a group
of definitions must be as independent as possible. That is, you don&amp;rsquo;t want
definitions to link to definitions and have the reader turn pages to connect
them.&lt;/p>
&lt;p>At such situations, I have found that using two definitions work better. First
definition that is isolated and independent of other definitions and a second
definition that links to other definitions.&lt;/p>
&lt;p>Thanks for reading! If you have any comments, questions or suggestions feel free
to reach me out using the links in footer. Have a nice day.&lt;/p>
&lt;h2 id="footnotes">Footnotes&lt;/h2>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>The website shows only the professor name because the publisher said that
their convention is to use only the first author for copyright and website display.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>The Nightingale</title><link>https://arunmani.in/library/the-nightingale/</link><pubDate>Sat, 15 Jul 2023 14:26:26 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-nightingale/</guid><enclosure url="https://arunmani.in/library/the-nightingale/cover.webp" length="1024" type="image/webp"/><description>&lt;p>One of the worst things in &lt;em>this world&lt;/em> is being punished for your birth and
background to which you had no control over. This includes all sort of
discrimination based on your caste, color, race, name, family etc.&lt;/p>
&lt;p>The next worst thing is suffering because of someone else&amp;rsquo;s greed and being
pulled into trouble because &lt;em>they&lt;/em> think it is right. This includes all the wars
that have been taken millions of lives because of someone&amp;rsquo;s ego, pride and
wrong-thinking.&lt;/p>
&lt;p>I have already read &lt;a href="https://arunmani.in/library/mans-search-for-meaning">Man&amp;rsquo;s Search for Meaning&lt;/a>
and it gave me an account of the horrors in the concentration camps.&lt;/p>
&lt;p>This book was different. Assume we can divide the people into three groups during
war - those suffering by fighting for their country, those suffering by being
in prison and finally those left in their homes to suffer with the hell caused
by war. &lt;em>The Nightingale&lt;/em> belongs to the last category. It tells the story of
two sisters about their lives and acts during the World War II.&lt;/p>
&lt;p>Though it is fiction, the book had a sense of realism to it. It is based on a
true war bought by true people which took true lives of innocents. The narration
was beautiful. I at sometimes, lost myself in thoughts on what I would do if a
war broke out. Or sometimes, I question what my action would be if I was in the
place of the protagonists. A war changes everything.&lt;/p>
&lt;p>I loved reading the book. I had a goal of reading five chapters a day but soon
began to cross the limit and read as much as I can. I feel like the last
few chapters were rushed up and some more details could have been added to
ensure the smooth flow. Apart from that, this was a joyful reading of a past
nightmare.&lt;/p></description></item><item><title>Looking for Alaska</title><link>https://arunmani.in/library/looking-for-alaska/</link><pubDate>Thu, 29 Jun 2023 15:02:36 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/looking-for-alaska/</guid><enclosure url="https://arunmani.in/library/looking-for-alaska/cover.webp" length="1024" type="image/webp"/><description>&lt;p>I forgot this book completely. Yesterday at 2 AM, while thinking of completing
the &lt;a href="https://arunmani.in/library/malgudi-days">Malgudi Days&lt;/a>, I suddenly got reminded of it.&lt;/p>
&lt;p>So &lt;em>only ~200 pages&lt;/em>? I can finish it.&lt;/p>
&lt;p>Reminder to self - be careful when reading a love story 🥹.&lt;/p>
&lt;p>This is really a paradoxical love mystery, and it reminded me of &lt;a href="https://arunmani.in/library/norwegian-wood">Norwegian
Wood&lt;/a>. The narration was simple and a little more explicit with American slang.
Yea fine, Malgudi Days had Indian slang and so why not 😉.&lt;/p>
&lt;p>The first part of the book was real fun. Full of events and happenings, it had
the visual feel attached to it.&lt;/p>
&lt;p>The second half became a real slow wheel. Grinding the same thing again and
again and you feel like all the grinding was for nothing by the time you read
the last page. If this was an Indian film, then the second part would be two
songs and a 5 minutes scene.&lt;/p>
&lt;p>But at least, the aroma of the first half, forces you to read the second. And
the first part is good enough to tickle you with memories or worry you with the
lack-of (&lt;em>like me&lt;/em>) depending upon what kind of childhood you had and the school 😎.&lt;/p></description></item><item><title>Malgudi Days</title><link>https://arunmani.in/library/malgudi-days/</link><pubDate>Thu, 29 Jun 2023 14:55:03 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/malgudi-days/</guid><enclosure url="https://arunmani.in/library/malgudi-days/cover.webp" length="1024" type="image/webp"/><description>&lt;p>I had my exams this month, so I didn&amp;rsquo;t read much, though I tried my best to read
one story a day.&lt;/p>
&lt;p>Once you &lt;em>ignore&lt;/em> the foreword by some author (gosh it covered pages and did more
harm to me), this book is smooth.&lt;/p>
&lt;p>The stories don&amp;rsquo;t have any path, you just read and it finishes. So what kept me
reading? It is the &lt;em>narration&lt;/em>.&lt;/p>
&lt;p>It gives you the feel of a village folklore, of the daily happenings in your
neighborhood. Yes the story happened in the days where there was no phone or so
and yes I don&amp;rsquo;t belong to that era. But born in a relatively remote area with a
parents of rich childhood memories, who here and there narrated me their
stories, Malgudi Days gave me the equivalent feel.&lt;/p>
&lt;p>Reading through the stories without any objective felts like a usual gossiping.
You stand in your home and your neighbor comes and tell you of something in the
town. This book gave me that experience.&lt;/p>
&lt;p>A few of the stories were interesting. A few simply left a sad impression, for
example the snake charmers, knife sharpeners, cobblers etc. The story described
the real life. No &lt;em>hero&lt;/em>, no &lt;em>rich mansion heroine&lt;/em>, no &lt;em>action-romantic sequence&lt;/em>. It
was like a hard truth. Take it or forget it.&lt;/p>
&lt;p>If you are someone from the Indian locality (not the urban region), then you
might get a strange nostalgia reading this book. At least, its stories are 10
pages roughly. So reading one a day won&amp;rsquo;t be a big deal either.&lt;/p></description></item><item><title>The Shadow of the Wind</title><link>https://arunmani.in/library/the-shadow-of-the-wind/</link><pubDate>Tue, 25 Apr 2023 23:52:20 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-shadow-of-the-wind/</guid><enclosure url="https://arunmani.in/library/the-shadow-of-the-wind/cover.webp" length="1024" type="image/webp"/><description>&lt;p>After a long time (may be not so long), I read a book with 400+ pages. I should
say that the efforts paid were completely worth. I had to read the book amidst a
busy schedule like project submissions and internal exams. So I spent an hour or
so whenever I felt like I need to forget the real world. Sometimes I even forced
myself to read the book because the story really pulled me in. 🙈&lt;/p>
&lt;p>What&amp;rsquo;s the speciality of the book? The protagonist (actually, the book doesn&amp;rsquo;t
have a &lt;em>single&lt;/em> one) is a hero with no magical powers. He goes through a lot
of hard-times and disappointments. Almost every character you encounter in the
story has a very pitiful past in one way or the other. May be, this environment
gave the book a &lt;em>realistic&lt;/em> feel.&lt;/p>
&lt;p>As a personal favorite, all chapters were with ten pages, which is satisfying if
you are someone who counts progress based on number of chapters you have read.
🙂&lt;/p>
&lt;p>I don&amp;rsquo;t want to spoil the story, but if you are a fan of thrillers, twists and
especially love, then this book can be a great time sucker. Bear in mind, the
love you are about to see also includes some heart breaks.&lt;/p>
&lt;p>Finally, such a well written book and I enjoyed it. 😊&lt;/p></description></item><item><title>Norse Mythology</title><link>https://arunmani.in/library/norse-mythology/</link><pubDate>Fri, 24 Mar 2023 22:42:10 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/norse-mythology/</guid><enclosure url="https://arunmani.in/library/norse-mythology/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Honest disclosure, I&amp;rsquo;m a huge fan of fantasy and mythology, so I could be &lt;em>over positive&lt;/em> about this book.&lt;/p>
&lt;p>After having a total failure on The Starless Sea, this book served as a big aid
in getting me back to reading™. I love mythology so crazily, and no matter how
much expressive they are, I always feel like that&amp;rsquo;s not enough. But that&amp;rsquo;s just
another story.&lt;/p>
&lt;p>Now about this book- it was excellent. It has a little number of chapters where
each chapter is a short story involving Gods and giants. The stories were &lt;em>really
short&lt;/em>, nothing verbose or boring. The number of pages in the book itself is
less, so a professional book dragon 🐉 can eat up from cover to cover within a
day.&lt;/p>
&lt;p>It starts, like any other mythology story, with the narration of world creation.
After that a few stories about the famous Gods like Odin, Thor, Loki etc. The
middle stories are all about other Gods and other happenings. The final
chapters describes the &lt;em>end&lt;/em>, which I guess, if I explain, would become a
spoiler.&lt;/p>
&lt;p>What I liked more about the stories (or the Norse mythology itself) is that most
of the stories have a connection with the life we lead now. It could be about
cheating or wordplay or underestimation etc.&lt;/p>
&lt;p>Finally, if you are in need of short stories of short duration to fill your
break time, then I highly recommend this book. You need not remember the
previous stories to read a new one as the stories are not much connected. So it
reduces the burden on your memory especially if you are a person like me who
forgets everything easily. 🤓&lt;/p>
&lt;p>A great book, enjoyed every word of it.&lt;/p></description></item><item><title>Let's Make A Silly JSON-like Parser</title><link>https://arunmani.in/articles/silly-json-parser/</link><pubDate>Wed, 01 Mar 2023 00:00:00 +0000</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/articles/silly-json-parser/</guid><enclosure url="https://arunmani.in/articles/silly-json-parser/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Hey there everybody! To give a &lt;em>tl;dr;&lt;/em>, we are going to make a &lt;em>silly&lt;/em> parser for
&lt;em>JSON-like&lt;/em> syntax. I call it &lt;em>silly&lt;/em> because the main aim is to simply write
one for pure fun and not focus on any blazing efficiency. Second of all, it is
&lt;em>JSON-like&lt;/em> because, the syntax closely resembles JSON but it isn&amp;rsquo;t exactly
one. But we drop the suffix &lt;em>like&lt;/em> for the sake of brevity.&lt;/p>
&lt;h2 id="understanding-our-data">Understanding Our Data&lt;/h2>
&lt;p>Before writing our parser, we must know what our data
is and how it looks like. If you know JSON, then there won&amp;rsquo;t be much
discrepancies.&lt;/p>
&lt;ol>
&lt;li>Our notation supports numbers, strings, lists, JSONs and &lt;code>null&lt;/code>.&lt;/li>
&lt;li>The numbers can be positive or negative. Both integers and floats are
supported but only in base 10 representation. Examples include &lt;code>123&lt;/code>, &lt;code>2.17&lt;/code>,
&lt;code>-3.14&lt;/code>, &lt;code>+20.2&lt;/code>.&lt;/li>
&lt;li>Strings must start and end with double quotes, like &lt;code>&amp;quot;Alice&amp;quot;&lt;/code>, &lt;code>&amp;quot;Hello, World&amp;quot;&lt;/code>.&lt;/li>
&lt;li>A list consists of comma separated elements within square brackets &lt;code>[ ]&lt;/code>. The
elements can be heterogeneous, so &lt;code>[1, 2.3, &amp;quot;hello&amp;quot;, [0, 10], null]&lt;/code> is
valid.&lt;/li>
&lt;li>JSON is enclosed inside curly braces &lt;code>{ }&lt;/code>. It contains &lt;em>key-value&lt;/em> pairs of
the syntax &lt;code>key: value&lt;/code>. Colon &lt;code>:&lt;/code> is used to separate a key from value. Keys
must be strings. Value can be any valid type. The key-value pairs are
separated by comma. Examples include &lt;code>{&amp;quot;name&amp;quot;: &amp;quot;Joe&amp;quot;, &amp;quot;age&amp;quot;: 25, &amp;quot;numbers&amp;quot;: [10, 20, 30]}&lt;/code>.&lt;/li>
&lt;li>&lt;code>null&lt;/code> is included as it is. Fully lowercase and no quotes.&lt;/li>
&lt;li>Space can be used deliberately. For numbers, there can be multiple space
between the sign and value, for example &lt;code>+ 19.27&lt;/code> (we will see why later.)
Here space means any whitespace character including newline, tab etc.&lt;/li>
&lt;/ol>
&lt;p>Phew! With the above seven rules, an example data could be as follows.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;key&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;value&amp;#34;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;number&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">-3.14&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;list&amp;#34;&lt;/span>: [&lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#ae81ff">20&lt;/span>, &lt;span style="color:#ae81ff">30&lt;/span>],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;json&amp;#34;&lt;/span>: {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;key&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">null&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="jason---the-parser">Jason - The Parser&lt;/h2>
&lt;p>Meet Jason! It is the name of our JSON parser. We will use
Python to create it. So let&amp;rsquo;s begin with creating a file called &lt;code>jason.py&lt;/code> and
call it a day! Please don&amp;rsquo;t name it &lt;code>json.py&lt;/code> as it conflicts with
Python&amp;rsquo;s standard module &lt;a href="https://docs.python.org/3/library/json.html">&lt;code>json&lt;/code>&lt;/a>.&lt;/p>
&lt;p>Our parser will consist of tiny functions, each meant to extract some value. After
parsing, we get a Python object that matches the data we parsed.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>#&lt;/th>
&lt;th>JSON Type&lt;/th>
&lt;th>Python Type&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>1.&lt;/td>
&lt;td>List&lt;/td>
&lt;td>&lt;code>list&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>2.&lt;/td>
&lt;td>JSON&lt;/td>
&lt;td>&lt;code>dict&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>3.&lt;/td>
&lt;td>Number&lt;/td>
&lt;td>&lt;code>float&lt;/code> or &lt;code>int&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>4.&lt;/td>
&lt;td>String&lt;/td>
&lt;td>&lt;code>str&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>5.&lt;/td>
&lt;td>&lt;code>null&lt;/code>&lt;/td>
&lt;td>&lt;code>None&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="the-preparation">The Preparation&lt;/h2>
&lt;p>Our data is a string, that is text. It can come from two places, either a file
or a Python &lt;code>str&lt;/code>. We won&amp;rsquo;t be reading the data in an entire go, we will read it
character by character. This presents some problems:&lt;/p>
&lt;ol>
&lt;li>We need a short and standard API to read both string and file. Python strings
are a sequence. It means, we can access individual characters by their
indices.
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Joe&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>print(name[&lt;span style="color:#ae81ff">1&lt;/span>]) &lt;span style="color:#75715e"># o&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>This syntax is short, just two square brackets and a number inside it.&lt;/li>
&lt;li>But, when we try to read an index beyond the string&amp;rsquo;s length, we get an
&lt;code>IndexError&lt;/code>.
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Joe&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>print(name[&lt;span style="color:#ae81ff">100&lt;/span>]) &lt;span style="color:#75715e"># IndexError: string index out of range&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>Wrapping every index access inside a &lt;code>try except&lt;/code> block is too verbose.
So we need a workaround for this noise.&lt;/li>
&lt;/ol>
&lt;p>For the first problem, we will create a reader that takes care of taking an index
and returning a character. For the second problem, we will create a special
class &lt;code>EOF&lt;/code> (end of file), which is returned whenever we try to read beyond the
length.&lt;/p>
&lt;p>This is how our &lt;code>EOF&lt;/code> looks like:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">EOF&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">pass&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The abstract class (or template) for our reader is:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Data&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __getitem__(self, i: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">NotImplementedError&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here &lt;a href="https://docs.python.org/3/reference/datamodel.html?#object.__getitem__">&lt;code>__getitem__&lt;/code>&lt;/a> is a &lt;a href="https://docs.python.org/3/reference/datamodel.html?#special-method-names">magic
method&lt;/a>.
This allows us to access the data at index via &lt;code>data[i]&lt;/code> syntax. Our &lt;code>Data&lt;/code>
class is abstract, that&amp;rsquo;s why it raises &lt;code>NotImplementedError&lt;/code>.&lt;/p>
&lt;p>Let&amp;rsquo;s write the concrete classes now. For a string data:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">StringData&lt;/span>(Data):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __init__(self, txt: str):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>_txt &lt;span style="color:#f92672">=&lt;/span> txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __getitem__(self, i: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>_txt[i]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">except&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> EOF
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We store the data in a private variable &lt;code>_txt&lt;/code>. See how our &lt;code>__getitem__&lt;/code> has
been overwritten with new code. We wrap the index access inside a &lt;code>try except&lt;/code>
and return &lt;code>EOF&lt;/code> if we get any error.&lt;/p>
&lt;p>For data from file:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> typing &lt;span style="color:#f92672">import&lt;/span> IO
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">FileData&lt;/span>(Data):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __init__(self, fp: IO):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>_fp &lt;span style="color:#f92672">=&lt;/span> fp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __getitem__(self, i: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>_fp&lt;span style="color:#f92672">.&lt;/span>seek(i, &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>_fp&lt;span style="color:#f92672">.&lt;/span>read(&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> EOF
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> char
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>At the first line, we import &lt;code>IO&lt;/code> from &lt;code>typing&lt;/code> to set type hint for our file
object. Our class takes a &lt;em>file pointer&lt;/em> and stores it in &lt;code>_fp&lt;/code>. To get a
character at an index, we first seek to that index via &lt;code>fp.seek&lt;/code>. The first
argument &lt;code>i&lt;/code> is the position and the second argument &lt;code>0&lt;/code> means the position &lt;code>i&lt;/code>
is counted from the beginning of the file.&lt;/p>
&lt;p>We have to do seeking because, Python automatically moves our file cursor when
we read the data. So two consecutive read calls to the file gives the subsequent
data stored in it. Also, unlike &lt;code>str&lt;/code>, trying to read a file beyond its length
returns an empty string. To be consistent with our reader API, we check for an
empty string and return &lt;code>EOF&lt;/code> in place of it.&lt;/p>
&lt;p>Putting this all together, our &lt;code>jason.py&lt;/code> should look like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">from&lt;/span> typing &lt;span style="color:#f92672">import&lt;/span> IO
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">EOF&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">pass&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Data&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __getitem__(self, i: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">NotImplementedError&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">StringData&lt;/span>(Data):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __init__(self, txt: str):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>_txt &lt;span style="color:#f92672">=&lt;/span> txt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __getitem__(self, i: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>_txt[i]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">except&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> EOF
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">FileData&lt;/span>(Data):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __init__(self, fp: IO):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>_fp &lt;span style="color:#f92672">=&lt;/span> fp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __getitem__(self, i: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> self&lt;span style="color:#f92672">.&lt;/span>_fp&lt;span style="color:#f92672">.&lt;/span>seek(i, &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>_fp&lt;span style="color:#f92672">.&lt;/span>read(&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> EOF
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> char
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s do a little testing of our API. You need to launch an interpreter and load
the module in it. Assuming the module is in the same location as your terminal,
you can simply do &lt;code>python -i jason.py&lt;/code>. (On some systems it may be &lt;code>python3&lt;/code> or
&lt;code>py&lt;/code> or &lt;code>py3&lt;/code>).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">~/&lt;/span>Scratch &lt;span style="color:#960050;background-color:#1e0010">❯&lt;/span> python3 &lt;span style="color:#f92672">-&lt;/span>i jason&lt;span style="color:#f92672">.&lt;/span>py
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello World!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data &lt;span style="color:#f92672">=&lt;/span> StringData(string)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">0&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">&amp;#39;H&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">5&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">&amp;#39; &amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">7&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">&amp;#39;o&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">2&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">&amp;#39;l&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">100&lt;/span>] &lt;span style="color:#75715e"># beyond length&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">__main__&lt;/span>&lt;span style="color:#f92672">.&lt;/span>EOF&lt;span style="color:#e6db74">&amp;#39;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">100&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> EOF
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">True&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> fp &lt;span style="color:#f92672">=&lt;/span> open(&lt;span style="color:#e6db74">&amp;#34;test.json&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;w&amp;#34;&lt;/span>) &lt;span style="color:#75715e"># prepare a sample&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> fp&lt;span style="color:#f92672">.&lt;/span>write(&lt;span style="color:#e6db74">&amp;#39;&amp;#34;Hello&amp;#34;&amp;#39;&lt;/span>) &lt;span style="color:#75715e"># write data in it&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">7&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> fp&lt;span style="color:#f92672">.&lt;/span>close() &lt;span style="color:#75715e"># save the sample&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> fp &lt;span style="color:#f92672">=&lt;/span> open(&lt;span style="color:#e6db74">&amp;#34;test.json&amp;#34;&lt;/span>) &lt;span style="color:#75715e"># open it back for reading&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data &lt;span style="color:#f92672">=&lt;/span> FileData(fp)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">0&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">&amp;#39;&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">1&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">&amp;#39;H&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">2&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">&amp;#39;e&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">10&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">&amp;#39;&lt;/span>&lt;span style="color:#a6e22e">__main__&lt;/span>&lt;span style="color:#f92672">.&lt;/span>EOF&lt;span style="color:#e6db74">&amp;#39;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> data[&lt;span style="color:#ae81ff">10&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> EOF
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">True&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Yay! Our reader is ready. Now we are moving to the core, where we extract the
values. 🐕&lt;/p>
&lt;h2 id="defining-constants">Defining Constants&lt;/h2>
&lt;p>Our syntax has a few literals like comma, colon, quotes etc. Let us define them
as constants.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>COMMA &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>JSON_START &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;{&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>JSON_END &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>JSON_SEP &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;:&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LIST_START &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;[&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>LIST_END &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;]&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PERIOD &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>MINUS &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;-&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>PLUS &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;+&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>NULL &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;null&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>STRING_START &lt;span style="color:#f92672">=&lt;/span> STRING_END &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>TERMINALS &lt;span style="color:#f92672">=&lt;/span> (EOF, COMMA, LIST_END, JSON_END)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Most of the constants should be self explanatory. &lt;code>TERMINALS&lt;/code> is a tuple with
literals which are used to indicate the end of a value. For example, when
parsing a data like &lt;code>123,&lt;/code>, we know the number stops at comma, hence it is a terminal.&lt;/p>
&lt;h2 id="our-functions">Our Functions&lt;/h2>
&lt;p>We will write separate functions to extract different values. Each of these
functions take two arguments - a &lt;code>Data&lt;/code> &lt;code>data&lt;/code> and an integer &lt;code>pos&lt;/code>. It means that the
function has to read &lt;code>data&lt;/code> from position &lt;code>pos&lt;/code> and extract the value from it.&lt;/p>
&lt;p>These functions read till they meet a terminal character. Then, they convert the
read string to valid data type and return it along with the position they have
read so far. This position is used by the next function to know from where the
next value should be read.&lt;/p>
&lt;p>It could be a little confusing, but once you see it in practice, I hope it will
be clear.&lt;/p>
&lt;h2 id="extracting-value">Extracting Value&lt;/h2>
&lt;p>JSON can be parsed recursively. We start with making an entrypoint function that
matches the first character and calls the appropriate extraction function.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">extract_value&lt;/span>(data: Data, pos: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> EOF:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>, pos
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> JSON_START:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> val, pos &lt;span style="color:#f92672">=&lt;/span> extract_json(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> LIST_START:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> val, pos &lt;span style="color:#f92672">=&lt;/span> extract_list(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> NULL&lt;span style="color:#f92672">.&lt;/span>startswith(char):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> val, pos &lt;span style="color:#f92672">=&lt;/span> extract_null(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> char&lt;span style="color:#f92672">.&lt;/span>isdigit() &lt;span style="color:#f92672">or&lt;/span> char &lt;span style="color:#f92672">in&lt;/span> (MINUS, PLUS):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> val, pos &lt;span style="color:#f92672">=&lt;/span> extract_number(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> STRING_START:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> val, pos &lt;span style="color:#f92672">=&lt;/span> extract_string(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;unexpected character: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(char)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> val, pos
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The first &lt;code>if&lt;/code> checks whether the data has any character left. If we get &lt;code>EOF&lt;/code>,
it means either the data is empty or that data has been already read. In that
case, we return with an empty string and an unmodified position.&lt;/p>
&lt;p>The subsequent &lt;code>if&lt;/code>s match the character with a known data type and on success,
they call the respective extract function. At last the &lt;code>else&lt;/code> is there as
fallback, which raises a &lt;code>ValueError&lt;/code>, because that character doesn&amp;rsquo;t match our
syntax guide.&lt;/p>
&lt;p>&lt;code>repr&lt;/code> function is used to print the character&amp;rsquo;s representation. We use &lt;code>repr&lt;/code>
instead of directly printing the character to help in case of &lt;em>non-printable&lt;/em>
characters.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> char &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#ae81ff">\t&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Oops what character is this &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>char&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Oops what character &lt;span style="color:#f92672">is&lt;/span> this
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Oops what character is this &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(char)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Oops what character &lt;span style="color:#f92672">is&lt;/span> this &lt;span style="color:#e6db74">&amp;#39;&lt;/span>&lt;span style="color:#ae81ff">\t&lt;/span>&lt;span style="color:#e6db74">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>See how the first &lt;code>print&lt;/code> prints a tab which is quite confusing as it is not visible. However
the second &lt;code>print&lt;/code> clearly prints the escape character.&lt;/p>
&lt;h2 id="skipping-space">Skipping Space&lt;/h2>
&lt;p>As said earlier, we are going to be make space insignificant in our syntax. So
any space character, (unless they are within quotes) is gently ignored. We now
create a function that does the same.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">skip_space&lt;/span>(data: Data, pos: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">while&lt;/span> char &lt;span style="color:#f92672">!=&lt;/span> EOF &lt;span style="color:#f92672">and&lt;/span> char&lt;span style="color:#f92672">.&lt;/span>isspace():
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> pos
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This function reads the data character by character and stops only when it
encounters &lt;code>EOF&lt;/code> or a non-space character. After the encounter, it returns the
position of the non-space character.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> skip_space(StringData(&lt;span style="color:#e6db74">&amp;#34; 1&amp;#34;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> skip_space(StringData(&lt;span style="color:#e6db74">&amp;#34; 1 &amp;#34;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> skip_space(StringData(&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#ae81ff">\t\n&lt;/span>&lt;span style="color:#e6db74"> X&amp;#34;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">3&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Our function cares only about the leading space.&lt;/p>
&lt;h2 id="extracting-number">Extracting Number&lt;/h2>
&lt;p>The logic for extracting a number is as follows:&lt;/p>
&lt;ol>
&lt;li>If the number starts with plus, we ignore it. For minus, we add it to our
string buffer.&lt;/li>
&lt;li>We then skip the space (continue reading to know why).&lt;/li>
&lt;li>We use &lt;code>is_float&lt;/code> as flag to know if the number is a float.&lt;/li>
&lt;li>Characters are read from the data as long as they are not a terminal.&lt;/li>
&lt;li>If the character is a digit, we add it to our buffer.&lt;/li>
&lt;li>If the character is a period (&lt;code>.&lt;/code>), we check if &lt;code>is_float&lt;/code> is &lt;code>True&lt;/code>.&lt;/li>
&lt;li>If it is &lt;code>True&lt;/code>, it means we already found a period in the number. It is an
error, so we raise an exception.&lt;/li>
&lt;li>In case, &lt;code>is_float&lt;/code> is &lt;code>False&lt;/code>, we set it to &lt;code>True&lt;/code> and append the period to
our buffer.&lt;/li>
&lt;li>If the character is a space, we skip all of them. After skipping, we check if
the non-space character is a terminal, if not we raise an exception.&lt;/li>
&lt;li>The last &lt;code>else&lt;/code> raises an exception as the character is neither a digit nor
period nor space.&lt;/li>
&lt;li>Finally, we convert the buffer to a float or an integer depending upon the
value of &lt;code>is_float&lt;/code>.&lt;/li>
&lt;/ol>
&lt;p>So the function looks like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">extract_number&lt;/span>(data: Data, pos: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> data[pos] &lt;span style="color:#f92672">in&lt;/span> (MINUS, PLUS):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> num &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;-&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> data[pos] &lt;span style="color:#f92672">==&lt;/span> MINUS &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">=&lt;/span> skip_space(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> num &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> is_float &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">False&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">while&lt;/span> char &lt;span style="color:#f92672">not&lt;/span> &lt;span style="color:#f92672">in&lt;/span> TERMINALS:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char&lt;span style="color:#f92672">.&lt;/span>isdigit():
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> num &lt;span style="color:#f92672">+=&lt;/span> char
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> PERIOD:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> is_float:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;extra &amp;#39;.&amp;#39; found in floating point number&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> is_float &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">True&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> num &lt;span style="color:#f92672">+=&lt;/span> PERIOD
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> char&lt;span style="color:#f92672">.&lt;/span>isspace():
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">=&lt;/span> skip_space(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">not&lt;/span> &lt;span style="color:#f92672">in&lt;/span> TERMINALS:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;invalid syntax for number&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;unexpected character in number: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(char)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> is_float:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> float(num), pos
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> int(num), pos
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>First of all, we allow space after the signs just for the visual sake. This
allows us to create lists like this:&lt;/p>
&lt;pre tabindex="0">&lt;code class="language-jason" data-lang="jason">[
+ 10,
- 15,
+ 3,
+ 5,
]
&lt;/code>&lt;/pre>&lt;p>Not really that great, but yea, it exists.&lt;/p>
&lt;p>We don&amp;rsquo;t allow multiple periods to prevent numbers like &lt;code>12.34.56&lt;/code>, which is not
valid at all. Similarly, we check the first character after skipping space to
terminals. For example consider the data &lt;code>12.34 13&lt;/code>. What does that even
mean? If you think, it should be parsed as &lt;code>12.3413&lt;/code>, then what about data like
&lt;code>12.34 &amp;quot;hello&amp;quot;&lt;/code> or &lt;code>12.34 [10, 20]&lt;/code>? To avoid any of such ambiguity, we don&amp;rsquo;t
want any non-terminal character to follow a number.&lt;/p>
&lt;p>Now let us check our function with some values.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_number(StringData(&lt;span style="color:#e6db74">&amp;#39;12&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#ae81ff">12&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_number(StringData(&lt;span style="color:#e6db74">&amp;#39;10.0&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#ae81ff">10.0&lt;/span>, &lt;span style="color:#ae81ff">4&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_number(StringData(&lt;span style="color:#e6db74">&amp;#39;-2.71&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">2.71&lt;/span>, &lt;span style="color:#ae81ff">5&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_number(StringData(&lt;span style="color:#e6db74">&amp;#39;- 3.14 &amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">3.14&lt;/span>, &lt;span style="color:#ae81ff">10&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_number(StringData(&lt;span style="color:#e6db74">&amp;#39;10.20.30&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">172&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_number
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;extra &amp;#39;.&amp;#39; found in floating point number&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: extra &lt;span style="color:#e6db74">&amp;#39;.&amp;#39;&lt;/span> found &lt;span style="color:#f92672">in&lt;/span> floating point number
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_number(StringData(&lt;span style="color:#e6db74">&amp;#39;10.0 20&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">181&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_number
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;invalid syntax for number&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: invalid syntax &lt;span style="color:#66d9ef">for&lt;/span> number
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_number(StringData(&lt;span style="color:#e6db74">&amp;#39;Not a number&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">183&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_number
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;unexpected character in number: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(char)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: unexpected character &lt;span style="color:#f92672">in&lt;/span> number: &lt;span style="color:#e6db74">&amp;#39;N&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="extracting-string">Extracting String&lt;/h2>
&lt;p>Compared to numbers, strings are easy. We start the double quotes and append
every character we get to the buffer till we meet either a double quote or
&lt;code>EOF&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">extract_string&lt;/span>(data: Data, pos: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">while&lt;/span> char &lt;span style="color:#f92672">not&lt;/span> &lt;span style="color:#f92672">in&lt;/span> (STRING_END, EOF):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> string &lt;span style="color:#f92672">+=&lt;/span> char
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> EOF:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;string terminated without: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>STRING_END&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">=&lt;/span> skip_space(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> string, pos
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The first &lt;code>pos += 1&lt;/code> skips the double quotes character. From there we read till
we get &lt;code>EOF&lt;/code> or double quotes. Once our while loop completes, we check if the
last character is &lt;code>EOF&lt;/code>. If yes, it means that our string has not been properly
closed with a double quote, so we raise an exception.&lt;/p>
&lt;p>Otherwise, we do another &lt;code>pos += 1&lt;/code> to go past the quotes. Then we skip the space
following the string and then return the extracted value.&lt;/p>
&lt;p>Let&amp;rsquo;s test our function to make sure it works well.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_string(StringData(&lt;span style="color:#e6db74">&amp;#39;&amp;#34;Hello, World!&amp;#34;&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#e6db74">&amp;#39;Hello, World!&amp;#39;&lt;/span>, &lt;span style="color:#ae81ff">15&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_string(StringData(&lt;span style="color:#e6db74">&amp;#39;&amp;#34;Hello, World!&amp;#34; &amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#e6db74">&amp;#39;Hello, World!&amp;#39;&lt;/span>, &lt;span style="color:#ae81ff">24&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_string(StringData(&lt;span style="color:#e6db74">&amp;#39;&amp;#34;Hello, World! &amp;#34; &amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#e6db74">&amp;#39;Hello, World! &amp;#39;&lt;/span>, &lt;span style="color:#ae81ff">27&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_string(StringData(&lt;span style="color:#e6db74">&amp;#39;&amp;#34;New &lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74"> Line&amp;#34;&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#e6db74">&amp;#39;New &lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74"> Line&amp;#39;&lt;/span>, &lt;span style="color:#ae81ff">12&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_string(StringData(&lt;span style="color:#e6db74">&amp;#39;&amp;#34;Not closed&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">202&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_string
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;string terminated without: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>STRING_END&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: string terminated without: &lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="extracting-list">Extracting List&lt;/h2>
&lt;p>Similar to strings, lists are enclosed inside square brackets. But in addition,
they contain commas inside. Since our functions are already made with
terminals in mind, we just call &lt;code>extract_value&lt;/code> whenever we find a character
that is not a comma or space.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">extract_list&lt;/span>(data: Data, pos: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> list &lt;span style="color:#f92672">=&lt;/span> []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> found &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">False&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">while&lt;/span> char &lt;span style="color:#f92672">not&lt;/span> &lt;span style="color:#f92672">in&lt;/span> (LIST_END, EOF):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> COMMA:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">not&lt;/span> found:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;empty comma in array&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> found &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">False&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> char&lt;span style="color:#f92672">.&lt;/span>isspace():
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">=&lt;/span> skip_space(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> val, pos &lt;span style="color:#f92672">=&lt;/span> extract_value(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> list&lt;span style="color:#f92672">.&lt;/span>append(val)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> found &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">True&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> EOF:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list terminated without &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>LIST_END&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">=&lt;/span> skip_space(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> list, pos
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The flag &lt;code>found&lt;/code> is used to avoid empty commas like &lt;code>[1, ,, 20]&lt;/code>. We set it to
&lt;code>True&lt;/code> when we append some value, so that the function knows that the comma was
indeed used with a value before it. When we meet a comma, we again reset it to
&lt;code>False&lt;/code>.&lt;/p>
&lt;p>We call &lt;code>skip_space&lt;/code> when we find a space as spaces can be ignored inside a
list.&lt;/p>
&lt;p>Time to check our function with some values.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_list(StringData(&lt;span style="color:#e6db74">&amp;#39;[1, 2, 3]&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>([&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>], &lt;span style="color:#ae81ff">9&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_list(StringData(&lt;span style="color:#e6db74">&amp;#39;[]&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>([], &lt;span style="color:#ae81ff">2&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_list(StringData(&lt;span style="color:#e6db74">&amp;#39;[ ]&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>([], &lt;span style="color:#ae81ff">4&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_list(StringData(&lt;span style="color:#e6db74">&amp;#39;[&amp;#34;Hello&amp;#34;, 12.3, -3, [1, 2 ]]&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>([&lt;span style="color:#e6db74">&amp;#39;Hello&amp;#39;&lt;/span>, &lt;span style="color:#ae81ff">12.3&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">3&lt;/span>, [&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>]], &lt;span style="color:#ae81ff">28&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_list(StringData(&lt;span style="color:#e6db74">&amp;#39;[1, 2,, 4]&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">115&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_list
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;empty comma in array&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: empty comma &lt;span style="color:#f92672">in&lt;/span> array
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_list(StringData(&lt;span style="color:#e6db74">&amp;#39;[1, 2&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">128&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_list
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;list terminated without &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>LIST_END&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: list terminated without ]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="extracting-json">Extracting JSON&lt;/h2>
&lt;p>Luckily, extracting JSON is as same as lists but with an addition of extracting
both key and value. A &lt;em>key-value&lt;/em> is separated by a colon and there can be any
amount of space between them. As we mentioned in our spec, keys can be of only
string type. So anything else as a key raises an exception.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">extract_json&lt;/span>(data: Data, pos: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> json &lt;span style="color:#f92672">=&lt;/span> {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> found &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">False&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">while&lt;/span> char &lt;span style="color:#f92672">not&lt;/span> &lt;span style="color:#f92672">in&lt;/span> (JSON_END, EOF):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> COMMA:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">not&lt;/span> found:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;empty comma in JSON&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> found &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">False&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> STRING_START:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> key, pos &lt;span style="color:#f92672">=&lt;/span> extract_key(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> val, pos &lt;span style="color:#f92672">=&lt;/span> extract_value(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> json[key] &lt;span style="color:#f92672">=&lt;/span> val
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> found &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">True&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> char&lt;span style="color:#f92672">.&lt;/span>isspace():
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">=&lt;/span> skip_space(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;expected key&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">==&lt;/span> EOF:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;JSON terminated without &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>JSON_END&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">=&lt;/span> skip_space(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> json, pos
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here we check for double quotes and if found, we extract the key from it. And
then we extract the value. The &lt;code>extract_key&lt;/code> function is given below.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">extract_key&lt;/span>(data: Data, pos: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> key, pos &lt;span style="color:#f92672">=&lt;/span> extract_string(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">!=&lt;/span> JSON_SEP:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;expected &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>JSON_SEP&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> but found: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(char)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">=&lt;/span> skip_space(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> key, pos
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The logic to extract a key is to first extract the string. Then we check if the
string is followed by a colon. If not, we raise an exception. Remember that
&lt;code>extract_string&lt;/code> already skips the spaces following the quotes, so data like
&lt;code>{&amp;quot;hello&amp;quot;: &amp;quot;space before me&amp;quot;}&lt;/code> is extracted properly.&lt;/p>
&lt;p>Let&amp;rsquo;s now test these functions.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_json(StringData(&lt;span style="color:#e6db74">&amp;#39;{&amp;#34;key&amp;#34;: 10,}&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>({&lt;span style="color:#e6db74">&amp;#39;key&amp;#39;&lt;/span>: &lt;span style="color:#ae81ff">10&lt;/span>}, &lt;span style="color:#ae81ff">12&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_json(StringData(&lt;span style="color:#e6db74">&amp;#39;{ &amp;#34;key&amp;#34; : 10 ,}&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>({&lt;span style="color:#e6db74">&amp;#39;key&amp;#39;&lt;/span>: &lt;span style="color:#ae81ff">10&lt;/span>}, &lt;span style="color:#ae81ff">24&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_json(StringData(&lt;span style="color:#e6db74">&amp;#39;&lt;/span>&lt;span style="color:#e6db74">{}&lt;/span>&lt;span style="color:#e6db74">&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>({}, &lt;span style="color:#ae81ff">2&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_json(StringData(&lt;span style="color:#e6db74">&amp;#39;{&amp;#34;key 1&amp;#34;: 10, &amp;#34;key 2&amp;#34;: { &amp;#34;key 3&amp;#34;: 20}}&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>({&lt;span style="color:#e6db74">&amp;#39;key 1&amp;#39;&lt;/span>: &lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;key 2&amp;#39;&lt;/span>: {&lt;span style="color:#e6db74">&amp;#39;key 3&amp;#39;&lt;/span>: &lt;span style="color:#ae81ff">20&lt;/span>}}, &lt;span style="color:#ae81ff">38&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_json(StringData(&lt;span style="color:#e6db74">&amp;#39;{10: &amp;#34;key not string&amp;#34;}&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">80&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_json
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;expected key&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: expected key
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_json(StringData(&lt;span style="color:#e6db74">&amp;#39;{&amp;#34;key&amp;#34; = &amp;#34;not colon&amp;#34;}&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">73&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_json
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> key, pos &lt;span style="color:#f92672">=&lt;/span> extract_key(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">^^^^^^^^^^^^^^^^^^^^^^&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">98&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_key
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;expected &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>JSON_SEP&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> but found: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(char)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: expected : but found: &lt;span style="color:#e6db74">&amp;#39;=&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="extracting-null">Extracting &lt;code>null&lt;/code>&lt;/h2>
&lt;p>Finally, let&amp;rsquo;s make the &lt;a href="https://maximilianocontieri.com/null-the-billion-dollar-mistake">billion dollar
mistake&lt;/a> by
extracting &lt;code>null&lt;/code>. To do so, we read four characters and check they equal &lt;code>null&lt;/code>. We also
ensure that the read character is not a terminal so we can quit in advance. For
example, if our data is &lt;code>nu,2&lt;/code>, then once we find comma, there is no point in
reading the next character (&lt;code>2&lt;/code>).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">extract_null&lt;/span>(data: Data, pos: int):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> word &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> count &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">while&lt;/span> char &lt;span style="color:#f92672">not&lt;/span> &lt;span style="color:#f92672">in&lt;/span> TERMINALS &lt;span style="color:#f92672">and&lt;/span> count &lt;span style="color:#f92672">!=&lt;/span> len(NULL):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> word &lt;span style="color:#f92672">+=&lt;/span> char
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> count &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> count &lt;span style="color:#f92672">==&lt;/span> len(NULL) &lt;span style="color:#f92672">and&lt;/span> word &lt;span style="color:#f92672">==&lt;/span> NULL:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pos &lt;span style="color:#f92672">=&lt;/span> skip_space(data, pos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>, pos
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;unexpected literal: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(word)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We actually used &lt;code>len(NULL)&lt;/code> instead of four because we don&amp;rsquo;t want to hardcode
the value as changing &lt;code>NULL&lt;/code> means the length should also be updated.&lt;/p>
&lt;p>Now some testing of the function.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_null(StringData(&lt;span style="color:#e6db74">&amp;#39;null&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#66d9ef">None&lt;/span>, &lt;span style="color:#ae81ff">4&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_null(StringData(&lt;span style="color:#e6db74">&amp;#39;null &amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#66d9ef">None&lt;/span>, &lt;span style="color:#ae81ff">6&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_null(StringData(&lt;span style="color:#e6db74">&amp;#39;nu,0&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">151&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract_null
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;unexpected literal: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(word)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: unexpected literal: &lt;span style="color:#e6db74">&amp;#39;nu&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="are-we-done-yet">Are We Done Yet?&lt;/h2>
&lt;p>This is getting a bit lengthier than it should be… Okay, so now our function
&lt;code>extract_value&lt;/code> is ready, we should be able to extract JSON pretty fine… right? Well yes but,&lt;/p>
&lt;ol>
&lt;li>
&lt;p>In the tests we conducted so far, we manually passed a &lt;code>StringData&lt;/code> and position. To be a
good library, we should provide some shortcuts.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>extract_value&lt;/code> just extracts &lt;em>a&lt;/em> value. Yes, only one value. It means, if
your data is &lt;code>&amp;quot;hello&amp;quot; &amp;quot;they do not know me&amp;quot;&lt;/code>, then our function parses only
&lt;code>&amp;quot;hello&amp;quot;&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> extract_value(StringData(&lt;span style="color:#e6db74">&amp;#39;&amp;#34;hello&amp;#34; &amp;#34;they do not know me&amp;#34;&amp;#39;&lt;/span>), &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>(&lt;span style="color:#e6db74">&amp;#39;hello&amp;#39;&lt;/span>, &lt;span style="color:#ae81ff">9&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>But the given data is invalid.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Let us introduce three more functions to tackle the above problems.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">extract&lt;/span>(data: Data):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> val, pos &lt;span style="color:#f92672">=&lt;/span> extract_value(data, &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> char &lt;span style="color:#f92672">=&lt;/span> data[pos]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> char &lt;span style="color:#f92672">!=&lt;/span> EOF:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;unexpected character: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(char)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> val
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">load&lt;/span>(fp: IO):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> extract(FileData(fp))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">loads&lt;/span>(txt: str):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> extract(StringData(txt))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The first function &lt;code>extract&lt;/code> takes a &lt;code>Data&lt;/code> as argument and extracts the value
in it, &lt;em>AND&lt;/em>, it checks if the character left after the value is &lt;code>EOF&lt;/code>. If it is
not &lt;code>EOF&lt;/code>, it means some other characters are still there, which is an invalid
syntax. So, we raise an exception. Since, our &lt;code>extract_*&lt;/code> functions already
consume space, the character left must be either &lt;code>EOF&lt;/code> or a non-space
character.&lt;/p>
&lt;p>The last two functions &lt;code>load&lt;/code> and &lt;code>loads&lt;/code> are similar to
&lt;a href="https://docs.python.org/3/library/json.html#json.load">&lt;code>json.load&lt;/code>&lt;/a> and
&lt;a href="https://docs.python.org/3/library/json.html#json.loads">&lt;code>json.loads&lt;/code>&lt;/a>
respectively.&lt;/p>
&lt;p>&lt;code>load&lt;/code> takes a file pointer and parses the data from it. &lt;code>loads&lt;/code> parses the data
from a Python &lt;code>str&lt;/code>.&lt;/p>
&lt;h2 id="are-we-done-yet-1">Are We Done Yet??!!&lt;/h2>
&lt;p>Yes yes, we are! Now let us test our parser with a sample JSON data.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-json" data-lang="json">&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;hello&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;another&amp;#34;&lt;/span>: &lt;span style="color:#960050;background-color:#1e0010">+&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;extra&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">-3&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;then&amp;#34;&lt;/span>: &lt;span style="color:#ae81ff">2.17&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;but&amp;#34;&lt;/span>: [&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;also&amp;#34;&lt;/span>: { &lt;span style="color:#f92672">&amp;#34;1&amp;#34;&lt;/span>: &lt;span style="color:#66d9ef">null&lt;/span>, &lt;span style="color:#f92672">&amp;#34;2&amp;#34;&lt;/span>: [] },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">&amp;#34;end&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Bye&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s say this file is saved as &lt;code>test.json&lt;/code>. Now let us call our parser.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">~/&lt;/span>Scratch &lt;span style="color:#960050;background-color:#1e0010">❯&lt;/span> python3 &lt;span style="color:#f92672">-&lt;/span>i jason&lt;span style="color:#f92672">.&lt;/span>py
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> fp &lt;span style="color:#f92672">=&lt;/span> open(&lt;span style="color:#e6db74">&amp;#34;test.json&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> json &lt;span style="color:#f92672">=&lt;/span> load(fp)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> fp&lt;span style="color:#f92672">.&lt;/span>close()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span style="color:#f92672">from&lt;/span> pprint &lt;span style="color:#f92672">import&lt;/span> pprint
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> pprint(json)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{&lt;span style="color:#e6db74">&amp;#39;also&amp;#39;&lt;/span>: {&lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>: &lt;span style="color:#66d9ef">None&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;2&amp;#39;&lt;/span>: []},
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;another&amp;#39;&lt;/span>: &lt;span style="color:#ae81ff">2&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;but&amp;#39;&lt;/span>: [&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;end&amp;#39;&lt;/span>: &lt;span style="color:#e6db74">&amp;#39;Bye&amp;#39;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;extra&amp;#39;&lt;/span>: &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">3&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;hello&amp;#39;&lt;/span>: &lt;span style="color:#ae81ff">1&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;then&amp;#39;&lt;/span>: &lt;span style="color:#ae81ff">2.17&lt;/span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Oh yea, it works 🙂. We used
&lt;a href="https://docs.python.org/3/library/pprint.html#pprint.pprint">&lt;code>pprint&lt;/code>&lt;/a> to
&lt;em>pretty print&lt;/em> the returned dictionary. Let us now check what happens if we pass
more than one value as data.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> loads(&lt;span style="color:#e6db74">&amp;#39;&amp;#34;parse me&amp;#34; &amp;#34;not me&amp;#34;&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">247&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> loads
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> extract(StringData(txt))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">^^^^^^^^^^^^^^^^^^^^^^^^&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">237&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;unexpected character: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(char)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: unexpected character: &lt;span style="color:#e6db74">&amp;#39;&amp;#34;&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&amp;gt;&lt;/span> loads(&lt;span style="color:#e6db74">&amp;#39;&amp;#34;parse me&amp;#34; 3.14&amp;#39;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Traceback (most recent call last):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>module&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">247&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> loads
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> extract(StringData(txt))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">^^^^^^^^^^^^^^^^^^^^^^^^&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> File &lt;span style="color:#e6db74">&amp;#34;/home/arun-mani-j/Scratch/jason.py&amp;#34;&lt;/span>, line &lt;span style="color:#ae81ff">237&lt;/span>, &lt;span style="color:#f92672">in&lt;/span> extract
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> &lt;span style="color:#a6e22e">ValueError&lt;/span>(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;unexpected character: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>repr(char)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">ValueError&lt;/span>: unexpected character: &lt;span style="color:#e6db74">&amp;#39;3&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Yes! It &lt;em>fails&lt;/em> successfully 🎉.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>We managed to write a parser for our JSON-like syntax perfectly well. Of
course, it can be improved a lot. May be the entire logic is flawed and we
should rewrite with a different algorithm. However, it is beyond our scope and
objective. We wanted a silly parser and now we got it.&lt;/p>
&lt;p>The full source code of &lt;code>jason.py&lt;/code> in my &lt;a href="https://gitlab.com/-/snippets/2508116">snippets&lt;/a>.&lt;/p>
&lt;p>Thanks for reading! Please feel free to share your
thoughts and suggestions. You can contact me via the links in footer.&lt;/p>
&lt;p>Good day! 👐&lt;/p></description></item><item><title>Aayra</title><link>https://arunmani.in/projects/aayra/</link><pubDate>Mon, 02 Jan 2023 00:50:24 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/projects/aayra/</guid><enclosure url="https://arunmani.in/projects/aayra/cover.webp" length="1024" type="image/webp"/><description>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Language&lt;/td>
&lt;td>Python&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Repository&lt;/td>
&lt;td>&lt;a href="https://gitlab.com/arun-mani-j/aayra">https://gitlab.com/arun-mani-j/aayra&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GUI Framework&lt;/td>
&lt;td>GTK, Adwaita&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Aayra is an eBook reader and audiobooks player. Its speciality is being able to do both of the functionality within the same app in a simplistic manner.&lt;/p>
&lt;p>It uses &lt;a href="https://www.gtk.org">GTK&lt;/a> for GUI and &lt;a href="https://www.sqlite.org">SQLite&lt;/a> for database. The app is under heavy development, so you can keep track of the repository to know the changes.&lt;/p></description></item><item><title>aurthy</title><link>https://arunmani.in/projects/aurthy/</link><pubDate>Mon, 02 Jan 2023 00:50:16 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/projects/aurthy/</guid><enclosure url="https://arunmani.in/projects/aurthy/cover.webp" length="1024" type="image/webp"/><description>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Languages&lt;/td>
&lt;td>Python, TypeScript&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Frontend&lt;/td>
&lt;td>Nuxt, TailwindCSS, daisyUI&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Backend&lt;/td>
&lt;td>FastAPI&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Database&lt;/td>
&lt;td>PostgreSQL&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Repository&lt;/td>
&lt;td>&lt;a href="https://gitlab.com/aurcc/aurthy">https://gitlab.com/aurcc/aurthy&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>aurthy is a &lt;a href="https://www.aurcc.in">university&lt;/a> project that lets a person or entity sign and distribute documents digitally. The receiving person can verify the originality by using the unique identifier. The aim of the project was to reduce the paperwork and go completely digital for everything from certificates to permission forms etc.&lt;/p>
&lt;p>The working principle behind aurthy is simple. Each user gets a username and password. After logging in to their account, they can upload the documents and provide a username of the signer. The signer then receives the request, where they verify the credentials and approve the request. This generates a unique identifier using UUID and a certificate with QR code in it, which is then sent to the requester. Using the certificate, anybody can verify the authentication by scanning the QR code.&lt;/p>
&lt;p>The threat model here is that the server is safe and if the server is able to verify a certificate then the certificate is valid.&lt;/p>
&lt;p>The backend was written in &lt;a href="https://www.python.org">Python&lt;/a> using &lt;a href="https://fastapi.tiangolo.com/">FastAPI&lt;/a> framework. Frontend uses &lt;a href="https://nuxt.com">Nuxt&lt;/a> with &lt;a href="https://tailwindcss.com">TailwindCSS&lt;/a> and &lt;a href="https://daisyui.com">daisyUI&lt;/a> for CSS. The data regarding users and documents were stored in a &lt;a href="https://www.postgresql.org">PostgreSQL&lt;/a> database.&lt;/p>
&lt;p>The project is currently in a halt because the HR team of the college said that many firms do not accept digital signatures. Plans are there to expand the scope of digital certificates using government schemes.&lt;/p></description></item><item><title>Aashii</title><link>https://arunmani.in/projects/aashii/</link><pubDate>Mon, 02 Jan 2023 00:50:11 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/projects/aashii/</guid><enclosure url="https://arunmani.in/projects/aashii/cover.webp" length="1024" type="image/webp"/><description>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Language&lt;/td>
&lt;td>Python&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Repository&lt;/td>
&lt;td>&lt;a href="https://github.com/arun-mani-j/Aashii">https://github.com/arun-mani-j/Aashii&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Aashii is a Telegram bot to simplify communication between members and admins of a group. Consider a Telegram group a lot of members and multiple admins. Here, the ability to let every user personally message an admin for any issue is a big trouble, both in terms of privacy and availability. To simplify this communication, Aashii is used.&lt;/p>
&lt;p>Initially, all the admins of a group are added to a separate private group with Aashii as a member. Now, any member who wishes to contact the admins can contact the bot. The bot acts as a middle-hand forwarding messages in both directions.&lt;/p>
&lt;p>In addition to message forwarding, Aashii supports multiple features like flood resistance, on the fly edits of messages, complete media support and broadcasting.&lt;/p>
&lt;p>The bot is written in &lt;a href="https://www.python.org">Python&lt;/a> using &lt;a href="https://python-telegram-bot.org/">python-telegram-bot&lt;/a> framework and &lt;a href="https://www.postgresql.org">PostgreSQL&lt;/a> is used as the database management system.&lt;/p>
&lt;p>Aashii is a self-hosted solution. It is currently being used by many Telegram users to provide customer service to their members.&lt;/p></description></item><item><title>DoNotRepeatBot</title><link>https://arunmani.in/projects/donotrepeatbot/</link><pubDate>Mon, 02 Jan 2023 00:49:54 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/projects/donotrepeatbot/</guid><enclosure url="https://arunmani.in/projects/donotrepeatbot/cover.webp" length="1024" type="image/webp"/><description>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Language&lt;/td>
&lt;td>Python&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Repository&lt;/td>
&lt;td>&lt;a href="https://github.com/arun-mani-j/DoNotRepeatBot">https://github.com/arun-mani-j/DoNotRepeatBot&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>DNR is a Telegram bot that allows you to share messages via &lt;a href="https://core.telegram.org/bots/features#inline-requests">inline feature&lt;/a> of Telegram. By storing repetitive messages in the bot, you can send the messages to any chat by calling the bot inline.&lt;/p>
&lt;p>Initially, the bot worked only for text messages (so called &lt;em>snippets&lt;/em>) but as days progressed, I rewrote the bot to allow any media type that Telegram allows to be sent via inline query. This means photos, audios, videos, documents and of course texts.&lt;/p>
&lt;p>The version 2.0 also saw a new profile picture, designed by a Telegram user named Happy Princess, for the bot.&lt;/p>
&lt;p>Personally I used to use this bot a lot to send messages in GNU/Linux groups where few questions liking mixing desktop environments, clarifications on WSL and normal distro are frequent.&lt;/p>
&lt;p>The bot is written in &lt;a href="https://www.python.org">Python&lt;/a> using &lt;a href="https://python-telegram-bot.org/">python-telegram-bot&lt;/a> framework and &lt;a href="https://www.postgresql.org">PostgreSQL&lt;/a> is used as the database management system.&lt;/p>
&lt;p>DNR was hosted on Heroku and available to users via &lt;a href="https://t.me/donotrepeatbot">@donotrepeatbot&lt;/a> bot account, but after Heroku decided to drop its &lt;a href="https://blog.heroku.com/next-chapter">free plan&lt;/a>, the bot is inactive. However, DNR was a fun ride as it was the first Telegram bot I made which used inline queries.&lt;/p>
&lt;p>&lt;strong>Update&lt;/strong>
The bot is back alive thanks to &lt;a href="https://suhasa.info/">Suhasa SJ&lt;/a>!&lt;/p></description></item><item><title>Debian Day’22, Bishop Heber College, Trichy</title><link>https://arunmani.in/articles/debday22-trichy/</link><pubDate>Wed, 24 Aug 2022 18:30:00 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/articles/debday22-trichy/</guid><enclosure url="https://arunmani.in/articles/debday22-trichy/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Debian GNU/Linux, the universal operating system was officially released in 16
August 1993 by Ian Murdock. To celebrate the birth day of Debian, open source
community and enthusiasts gather together, which is known by the name Debian
Day. Anyone is free to organize the event both virtually and physically. The
main objective of the Day is celebration, so any strict rules and protocols are
relaxed.&lt;/p>
&lt;p>The free and open source users of south India planned to conduct the event in
Kerala and Tamil Nadu. Due to unfortunate flood related issues in Kerala, the
event was done through online. In Tamil Nadu, we organized the Day in Bishop
Heber College of Trichy. From the entire making blueprint to bringing it in
action was done by the students of BHC led by Ravishanker. Ash and Abraham Raji
guided us in the process. I reached the spot with the help of Ravi on 16 August.&lt;/p>
&lt;p>The event was to be simple but fun. Since it is organized in a college where it
is highly possible that many are not aware of what Debian or Linux is, we
shifted our focus from just celebrating Debian to celebrating by spreading
awareness. Or in the other words, we wanted students and the audience to know
what Debian is, about the free and open source software etc.&lt;/p>
&lt;figure>&lt;img src="vp.webp"
alt="Photo of Vice Principal of BHC presenting the welcome speech"/>&lt;figcaption>
&lt;p>Vice Principal of BHC presenting the welcome speech&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>The Day with prayer song followed by welcome speech by the Vice Principal of
BHC. He was such a lively person whose mere presence itself meant a big support.
He said he spent a few hours last night on searching about Debian, &lt;code>dpkg&lt;/code> etc.
He was very happy to know that the event is organized by students who are
involved in free and open source contributions during their studies itself. We
then joined with the Principal of BHC who met us virtually and welcomed us to
the event.&lt;/p>
&lt;p>After his speech, Ravishanker presented a lightning talk on FOSS. He had a
stuffed up presentation with memes and points that was successful in engaging
the audience to the stage.&lt;/p>
&lt;figure>&lt;img src="trishiraj.webp"
alt="Photo of Trishiraj on the day"/>&lt;figcaption>
&lt;p>Trishiraj on the day&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>Following that, Trishiraj, the lead developer of CorvusOS joined us via online.
Being a native of Tamil Nadu, he spoke in a mix of Tamil and English, which was
highly useful because the audience felt his words. Trishi talked about his ROM,
the Android Open Source Project and a layperson guide to contributions.&lt;/p>
&lt;p>After this, I presented a speech on history of Debian to how to get started with
it. I also included my personal history on how I got familiar with both FOSS and
Debian.&lt;/p>
&lt;figure>&lt;img src="kyle.webp"
alt="Photo of Kyle presenting his talk"/>&lt;figcaption>
&lt;p>Kyle presenting his talk&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>We had a small tea-break which was followed by a talk by Kyle Robbertze, Debian
Developer. Kyle joined us virtually and presented about the advantages of
Debian, the contribution guide and etc. Kyle’s talk brought a lot of questions
like aboutpackage management, Debian’s Salsa etc. Due to technical issues on our
side, I attended the QA for him. The final event was an interactive quiz on
FOSS. The questions were based on different spectrum of FOSS but from the user’s
perspective. The last question was a Beat the Clock, with the question of naming
as many as FOSS applications/projects as possible. We gave a small memento to
the student who named the majority.&lt;/p>
&lt;figure>&lt;img src="group-pic.webp"
alt="Photo of a few organizers of the event"/>&lt;figcaption>
&lt;p>A few organizers of the event, Ravi on the extreme right and me to his left&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>The Day was awesome. It was the first event we conducted both on our own and
represented the Debian community (instead of students). The main target we set
for the event was that we need to kindle a spark in the minds of students and
staffs about Debian and FOSS. In that regard, the event is a grand success. We
had the chance to meet the Vice Principal after the event and he was very happy
for the Day. He was so inspired by Debian and the community that he said that
they will and be welcoming to conduct more such events.&lt;/p>
&lt;p>The Day could not have been possible without the FOSS community and so, it is
neither &lt;em>you&lt;/em>, nor &lt;em>me&lt;/em>, it is &lt;em>us&lt;/em>. We did it. Looking forward to join more
such events in the coming days!&lt;/p></description></item><item><title>One Hundred Years of Solitude</title><link>https://arunmani.in/library/one-hundred-years-of-solitude/</link><pubDate>Mon, 02 May 2022 14:10:45 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/one-hundred-years-of-solitude/</guid><enclosure url="https://arunmani.in/library/one-hundred-years-of-solitude/cover.webp" length="1024" type="image/webp"/><description>&lt;p>A brilliant narration of a family.&lt;/p></description></item><item><title>The Pregnant King</title><link>https://arunmani.in/library/the-pregnant-king/</link><pubDate>Mon, 02 May 2022 14:09:51 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-pregnant-king/</guid><enclosure url="https://arunmani.in/library/the-pregnant-king/cover.webp" length="1024" type="image/webp"/><description>&lt;p>A wonderful combination of magic and philosophy.&lt;/p></description></item><item><title>Educated</title><link>https://arunmani.in/library/educated/</link><pubDate>Mon, 07 Mar 2022 13:43:10 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/educated/</guid><enclosure url="https://arunmani.in/library/educated/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Power of education for someone from a conservative family.&lt;/p></description></item><item><title>Norwegian Wood</title><link>https://arunmani.in/library/norwegian-wood/</link><pubDate>Tue, 08 Feb 2022 13:42:37 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/norwegian-wood/</guid><enclosure url="https://arunmani.in/library/norwegian-wood/cover.webp" length="1024" type="image/webp"/><description>&lt;p>A big love tale.&lt;/p></description></item><item><title>Quack</title><link>https://arunmani.in/projects/quack/</link><pubDate>Thu, 03 Feb 2022 20:28:08 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/projects/quack/</guid><enclosure url="https://arunmani.in/projects/quack/cover.webp" length="1024" type="image/webp"/><description>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Language&lt;/td>
&lt;td>Rust&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Repository&lt;/td>
&lt;td>&lt;a href="https://gitlab.com/arun-mani-j/quack">https://gitlab.com/arun-mani-j/quack&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Quack is a command-line app to search the web via DuckDuckGo. It uses DDG&amp;rsquo;s API to fetch the instant answers and results.&lt;/p>
&lt;p>The project is very simple in nature with the main objective to learn and try out Rust for something realistic. The app uses &lt;a href="https://github.com/seanmonstar/reqwest">&lt;code>reqwest&lt;/code>&lt;/a> for the HTTP requests, &lt;a href="https://github.com/clap-rs/clap">&lt;code>clap&lt;/code>&lt;/a> for command-line handling and &lt;a href="https://github.com/serde-rs/json">&lt;code>serde_json&lt;/code>&lt;/a> to parse JSON.&lt;/p></description></item><item><title>New Website</title><link>https://arunmani.in/articles/new-website/</link><pubDate>Thu, 03 Feb 2022 00:49:24 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/articles/new-website/</guid><enclosure url="https://arunmani.in/articles/new-website/cover.webp" length="1024" type="image/webp"/><description>&lt;p>This is the first blog post I&amp;rsquo;m publishing in this website. I just finished adding final touch-ups to the site, which took me a three long evenings to make. With the finish, I thought of removing the placeholder posts (if you want to see those placeholders, then you can look at the source code repository 😉) and adding &lt;em>real&lt;/em> articles. Yes, this is a real article.&lt;/p>
&lt;h2 id="preface">Preface&lt;/h2>
&lt;p>To get started, I&amp;rsquo;m not a professional website developer, which you might have guessed with how the site looks 🙈, but still, I thought of giving it a try. I&amp;rsquo;m not really a fan of making websites because&lt;/p>
&lt;ul>
&lt;li>They are really difficult&lt;/li>
&lt;li>I&amp;rsquo;m not that creative&lt;/li>
&lt;li>I don&amp;rsquo;t have enough resources&lt;/li>
&lt;/ul>
&lt;p>The above statements might sound vague to you, so let me explain.&lt;/p>
&lt;blockquote>
&lt;p>They are really difficult&lt;/p>
&lt;/blockquote>
&lt;p>Yes. Gone the days with simple websites. Nowadays every website has a pretty complexity around it. From a rich collection of frameworks to a massive list of variations like browsers (Chrom*, Firefox, Safari etc.), screen sizes (desktop, phone, tablet etc.), personal preferences (dark mode, privacy conscious etc.). A professional website developer may not be worried of these, but as I said in the starting, I&amp;rsquo;m not a &lt;em>professional&lt;/em>. So, it is not really easy from a newbie point of view.&lt;/p>
&lt;blockquote>
&lt;p>I&amp;rsquo;m not that creative&lt;/p>
&lt;/blockquote>
&lt;p>Creativity and me are opposite ends. I&amp;rsquo;m not really a fan of eyes-stealing fancy frills. I like to keep things simple, easy and tweak-able. Apart from that, I&amp;rsquo;m a sort of person who feels that I should not spend too much time in something that I don&amp;rsquo;t understand quite well. An example is navigation menu. I wanted to avoid JavaScript at the &lt;em>client&lt;/em> side, so I looked for alternatives. One such, I found is a &lt;a href="https://css-tricks.com/the-checkbox-hack/#hide-the-sidebar">hack using checkbox&lt;/a>. I tried it, it neither worked nor I understood why. I left it.&lt;/p>
&lt;blockquote>
&lt;p>I don&amp;rsquo;t have enough resources&lt;/p>
&lt;/blockquote>
&lt;p>This is a big obstacle in my tech life and so it is for web development. I have a laptop with 2 GB RAM. Yep very old one. You know how difficult it is even to browse modern day websites, then how can I even dream of making one. Thanks to low-memory environment I have made myself comfortable of, I was able to make this site finely. The low-memory environment is nothing but &lt;a href="https://swaywm.org">SwayWM&lt;/a> and &lt;a href="https://www.gnu.org/software/emacs/">GNU Emacs&lt;/a>. I will explain about it later.&lt;/p>
&lt;p>Now you might get an idea on the problems I face. Yet, I was able to finish the site by doing &lt;em>this and that&lt;/em>. Oh yes!&lt;/p>
&lt;h2 id="my-old-website">My Old Website&lt;/h2>
&lt;p>The first real world website I made is a website for me. I was a very newbie to web development that time. I wanted a website for &lt;em>namesake&lt;/em>. So I used (still use) &lt;a href="https://pages.gitlab.io">GitLab Pages&lt;/a> for hosting. I wrote the code using &lt;a href="https://vuejs.org">VueJS&lt;/a> and it was a very fine mess. But it did work.&lt;/p>
&lt;p>It was not made for blog or ideas sharing, but just a website for namesake. The site was not colorful, it was full black text on a clear white background.&lt;/p>
&lt;p>Soon after making the site, I forgot to improve it and later forgot its very existence.&lt;/p>
&lt;h2 id="bedtime-inspiration">Bedtime Inspiration&lt;/h2>
&lt;p>Thanks to the COVID-19 pandemic, I got a lot of free time. In that free time, I was able to meet new people of different point of views (online and in Telegram of course!). From them, I learnt of new technologies and frameworks. But apart from those frameworks, I learnt about &lt;em>simple awesome&lt;/em> websites. There are a lot to name. Those are the websites that don&amp;rsquo;t use JavaScript or try to nuke your privacy with ads and data harvest.&lt;/p>
&lt;p>Examples include websites of &lt;a href="https://www.gnu.org">GNU&lt;/a>, &lt;a href="https://www.debian.org">Debian&lt;/a>, &lt;a href="https://drewdevault.com/">Drew DeVault&lt;/a>. They were simply fascinating, and that&amp;rsquo;s how I was also inspired to make a website that is simple. That&amp;rsquo;s it.&lt;/p>
&lt;h2 id="time-to-start-playing">Time To Start Playing&lt;/h2>
&lt;p>So now it&amp;rsquo;s time to start making the website. I decided to use &lt;a href="https://gohugo.io">Hugo&lt;/a> for building the website and &lt;a href="https://tailwindcss.com">TailwindCSS&lt;/a> for CSS. Now after the finish of site, I think I have made a solid decision to use them. They have good documentation and a pretty big community. It really helped.&lt;/p>
&lt;p>Also thanks to a vast resources and tutorials available in Internet guiding various topics like semantic web, image optimization etc.&lt;/p>
&lt;p>Finally, I solved the first two issues I mentioned &lt;a href="#preface">earlier&lt;/a>, what about the third issue?&lt;/p>
&lt;figure>&lt;img src="workspace_one.webp"
alt="An image showing my first workspace with Firefox open"/>&lt;figcaption>
&lt;p>First workspace with Firefox open.&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>I used to keep three workspaces in Sway. The first has Firefox with two tabs. The first tab has &lt;code>localhost:1313&lt;/code> with my developing website. The second tab has documentation of either Hugo or TailwindCSS or any important site.&lt;/p>
&lt;figure>&lt;img src="workspace_two.webp"
alt="An image showing my second workspace with Emacs open"/>&lt;figcaption>
&lt;p>Second workspace with Emacs open.&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>The second workspace has Emacs with code of my site. I don&amp;rsquo;t know how many buffers will be active there, most of the time it is around ten. But at the front (means at Emacs window), I keep only one or two panes at most (two panes if I&amp;rsquo;m referencing some other code).&lt;/p>
&lt;figure>&lt;img src="workspace_three.webp"
alt="An image showing my third workspace with Foot windows open"/>&lt;figcaption>
&lt;p>Third workspace with Foot windows open.&lt;/p>
&lt;/figcaption>
&lt;/figure>
&lt;p>The third workspace has two &lt;a href="https://codeberg.org/cglogic/foot">Foot&lt;/a> terminal windows. Since the website is in development stage, I run watch mode of TailwindCSS and Hugo in the two windows. Watch mode is nothing but a watchdog that reloads and builds the website on file changes.&lt;/p>
&lt;p>With this setup, my memory usage comes around 80%. And sometimes I need to debug the site, so I have to open Firefox&amp;rsquo;s developer tools. So I&amp;rsquo;m pretty choking my system. But, this choking is the main reason, I need the website to be minimal. Neither can I make a website that is greedy on resources without killing my laptop 🤷.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>After pretty good headache, I finally finished the site. Also, for your kind information, I didn&amp;rsquo;t jump directly from my old VueJS based site to this one. In between, I spent a lot of time in making 2 to 3 websites for my friends and contacts. For them, I used Hugo and TailwindCSS. This strengthened my experience and helped me in making my site without a lot of hassle.&lt;/p>
&lt;p>My first blog post should not be so long, so let&amp;rsquo;s finish it up. The website&amp;rsquo;s source code is available for public reference in my &lt;a href="https://gitlab.com/j-arun-mani/j-arun-mani.gitlab.io">GitLab repository&lt;/a>, feel free to have a look. Don&amp;rsquo;t forget to share your feedback and thoughts via any Telegram or EMail (links are there in footer!).&lt;/p>
&lt;p>Thanks for your time 😊.&lt;/p>
&lt;h2 id="new-update">New Update&lt;/h2>
&lt;p>Time has changed, I bought a new laptop - ThinkPad E14. Now, the memory constraints are pretty much not an issue. I also learnt about &lt;a href="https://daisyui.com">daisyUI&lt;/a> and rewrote the website with a few parts using it. A lot of hard coded values were replaced with the help of daisyUI style classes. I&amp;rsquo;m now using &lt;a href="https://www.gnome.org">GNOME&lt;/a> but GNU (Doom) Emacs is still my default text editor. Somethings don&amp;rsquo;t change right 😉?&lt;/p></description></item><item><title>A Man Called Ove</title><link>https://arunmani.in/library/a-man-called-ove/</link><pubDate>Fri, 07 Jan 2022 13:41:41 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/a-man-called-ove/</guid><enclosure url="https://arunmani.in/library/a-man-called-ove/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Ove is the chad neighbor we all hate but at the end miss.&lt;/p></description></item><item><title>The Jaunt</title><link>https://arunmani.in/library/the-jaunt/</link><pubDate>Fri, 19 Nov 2021 13:41:19 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-jaunt/</guid><enclosure url="https://arunmani.in/library/the-jaunt/cover.webp" length="1024" type="image/webp"/><description>&lt;p>A future that is scary because of science.&lt;/p></description></item><item><title>The Little Prince</title><link>https://arunmani.in/library/the-little-prince/</link><pubDate>Sat, 02 Oct 2021 14:10:12 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-little-prince/</guid><enclosure url="https://arunmani.in/library/the-little-prince/cover.webp" length="1024" type="image/webp"/><description>&lt;p>A refreshing story that was fun to read.&lt;/p></description></item><item><title>The Husband Stitch</title><link>https://arunmani.in/library/the-husband-stitch/</link><pubDate>Sat, 02 Oct 2021 11:53:47 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-husband-stitch/</guid><enclosure url="https://arunmani.in/library/the-husband-stitch/cover.webp" length="1024" type="image/webp"/><description>&lt;p>A scary, interesting short story.&lt;/p></description></item><item><title>The Handmaid's Tale</title><link>https://arunmani.in/library/the-handmaids-tale/</link><pubDate>Thu, 02 Sep 2021 11:51:32 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-handmaids-tale/</guid><enclosure url="https://arunmani.in/library/the-handmaids-tale/cover.webp" length="1024" type="image/webp"/><description>&lt;p>If this is the future, then please don&amp;rsquo;t.&lt;/p></description></item><item><title>Hyperbole and a Half</title><link>https://arunmani.in/library/hyperbole-and-a-half/</link><pubDate>Mon, 02 Aug 2021 11:52:32 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/hyperbole-and-a-half/</guid><enclosure url="https://arunmani.in/library/hyperbole-and-a-half/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Beautiful narration of various scenarios.&lt;/p></description></item><item><title>Anxious People</title><link>https://arunmani.in/library/anxious-people/</link><pubDate>Mon, 02 Aug 2021 11:51:19 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/anxious-people/</guid><enclosure url="https://arunmani.in/library/anxious-people/cover.webp" length="1024" type="image/webp"/><description>&lt;p>A refreshing tale of our human lives.&lt;/p></description></item><item><title>Forever Series</title><link>https://arunmani.in/library/forever-series/</link><pubDate>Fri, 02 Jul 2021 14:09:21 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/forever-series/</guid><enclosure url="https://arunmani.in/library/forever-series/cover.webp" length="1024" type="image/webp"/><description>&lt;p>A modern love tale with suspense and mystery.&lt;/p></description></item><item><title>In a Grove</title><link>https://arunmani.in/library/in-a-grove/</link><pubDate>Fri, 02 Jul 2021 11:53:15 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/in-a-grove/</guid><enclosure url="https://arunmani.in/library/in-a-grove/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Awesome mystery surrounding a murder.&lt;/p></description></item><item><title>Strange Planet</title><link>https://arunmani.in/library/strange-planet/</link><pubDate>Fri, 02 Jul 2021 11:51:09 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/strange-planet/</guid><enclosure url="https://arunmani.in/library/strange-planet/cover.webp" length="1024" type="image/webp"/><description>&lt;p>After reading, you realize that Earth is really strange.&lt;/p></description></item><item><title>The Song of Achilles</title><link>https://arunmani.in/library/the-song-of-achilles/</link><pubDate>Wed, 02 Jun 2021 11:50:58 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-song-of-achilles/</guid><enclosure url="https://arunmani.in/library/the-song-of-achilles/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Trojan War but from a different amazing viewpoint.&lt;/p></description></item><item><title>My Days in the Underworld</title><link>https://arunmani.in/library/my-days-in-the-underworld/</link><pubDate>Fri, 02 Apr 2021 11:52:06 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/my-days-in-the-underworld/</guid><enclosure url="https://arunmani.in/library/my-days-in-the-underworld/cover.webp" length="1024" type="image/webp"/><description>&lt;p>From the man who ruled the underworld.&lt;/p></description></item><item><title>Sherlock Holmes</title><link>https://arunmani.in/library/sherlock-holmes/</link><pubDate>Tue, 02 Mar 2021 14:09:27 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/sherlock-holmes/</guid><enclosure url="https://arunmani.in/library/sherlock-holmes/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Each story teaches you a new form of out-of-box thinking.&lt;/p></description></item><item><title>The Kite Runner</title><link>https://arunmani.in/library/the-kite-runner/</link><pubDate>Mon, 02 Nov 2020 11:50:35 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-kite-runner/</guid><enclosure url="https://arunmani.in/library/the-kite-runner/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Beautiful narration of a culture, traditions and difficulties.&lt;/p></description></item><item><title>Man's Search for Meaning</title><link>https://arunmani.in/library/mans-search-for-meaning/</link><pubDate>Wed, 02 Sep 2020 11:50:22 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/mans-search-for-meaning/</guid><enclosure url="https://arunmani.in/library/mans-search-for-meaning/cover.webp" length="1024" type="image/webp"/><description>&lt;p>A lot of tough and difficult scenarios.&lt;/p></description></item><item><title>Crime and Punishment</title><link>https://arunmani.in/library/crime-and-punishment/</link><pubDate>Sun, 02 Aug 2020 11:49:55 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/crime-and-punishment/</guid><enclosure url="https://arunmani.in/library/crime-and-punishment/cover.webp" length="1024" type="image/webp"/><description>&lt;p>I went full upside down reading this book. Perspective changing story.&lt;/p></description></item><item><title>The Girl on the Train</title><link>https://arunmani.in/library/the-girl-on-the-train/</link><pubDate>Thu, 02 Jul 2020 01:01:12 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/the-girl-on-the-train/</guid><enclosure url="https://arunmani.in/library/the-girl-on-the-train/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Fantastic thriller with a nice twist at the end.&lt;/p></description></item><item><title>Recursion</title><link>https://arunmani.in/library/recursion/</link><pubDate>Tue, 02 Jun 2020 00:53:32 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/recursion/</guid><enclosure url="https://arunmani.in/library/recursion/cover.webp" length="1024" type="image/webp"/><description>&lt;p>First ever sci-fi novel I have ever read. As always time machines are dangerous.&lt;/p></description></item><item><title>Nothing Lasts Forever</title><link>https://arunmani.in/library/nothing-lasts-forever/</link><pubDate>Mon, 20 Jan 2020 13:42:18 +0530</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/library/nothing-lasts-forever/</guid><enclosure url="https://arunmani.in/library/nothing-lasts-forever/cover.webp" length="1024" type="image/webp"/><description>&lt;p>Mysteries within mysteries.&lt;/p></description></item><item><title/><link>https://arunmani.in/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/about/</guid><description>&lt;h1 id="about-me">About Me&lt;/h1>
&lt;p>Note: If you need a formal description, then please check out my &lt;a href="https://arunmani.in/resume">resume&lt;/a>.&lt;/p>
&lt;p>I&amp;rsquo;m Arun Mani. You might me find me online with names J Arun Mani or Arun Mani J. Here &lt;em>J&lt;/em> is my &lt;a href="https://en.wikipedia.org/wiki/Indian_name#Tamil">initial&lt;/a>. Please address me by my full name &lt;em>Arun Mani&lt;/em> or just &lt;em>Arun&lt;/em>. Whatever you feel comfortable with 🙂.&lt;/p>
&lt;p>My native is Tamil Nadu, India. I can speak Tamil (mother tongue!), English and can understand and speak basic Hindi.&lt;/p>
&lt;p>I&amp;rsquo;m currently studying B.E Computer Science Engineering in Anna University, Regional Campus, Coimbatore. Apart from studies, I spend time reading books, coding and reading articles.&lt;/p>
&lt;h2 id="computer-science">Computer Science&lt;/h2>
&lt;p>I can&amp;rsquo;t find a better name for this section as I think I&amp;rsquo;m not just &lt;em>a programmer&lt;/em>. I mean, yes I&amp;rsquo;m one but not just one. 😉&lt;/p>
&lt;p>I started coding at grade 9 (9th standard in Indian terms). For me, I was attracted to computers by video games. After a lot of web searches, I started with Python. Now after a few years, I know Python quite well. I also know basics of C, Java, JavaScript and Rust. My personal favorite is Python and Rust, because Python is simple and elegant and Rust has such a lovely compiler.&lt;/p>
&lt;h2 id="free-libre-and-open-source">Free Libre and Open Source&lt;/h2>
&lt;p>I&amp;rsquo;m an advocate of free libre and open source (FLOSS) technologies with respect for privacy. Most of the software I used are based on this opinion. But there are some things, both proprietary and privacy destroying, that I have to use because of various social constraints.&lt;/p>
&lt;h2 id="nerdy-cool-things">Nerdy Cool Things&lt;/h2>
&lt;p>I use &lt;a href="https://github.com/hlissner/doom-emacs">Doom Emacs&lt;/a>, a configuration kit for GNU Emacs. For operating system, I use &lt;a href="https://debian.org">GNU Debian Linux&lt;/a>. Simplicity is key!&lt;/p>
&lt;h2 id="reading-preferences">Reading Preferences&lt;/h2>
&lt;p>I like books on fiction. Non-fiction is fine as long as it is not boring. I also love reading books on philosophy 🌟. I&amp;rsquo;m not an avid reader, but I try my best to complete at least one book a month. If you got a good book to share, don&amp;rsquo;t forget me!&lt;/p>
&lt;p>Reading blogs and articles is also my way of passing time. I try to read anything that is mildly interesting.&lt;/p>
&lt;h2 id="contact-me">Contact Me&lt;/h2>
&lt;p>Feel free to contact me for any feedback, comments and chit chat. For instant reply, use Telegram, for classic way, use email. The links are available in footer.&lt;/p></description></item><item><title/><link>https://arunmani.in/rss/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/rss/</guid><description>&lt;h1 id="really-simple-syndication-rss">Really Simple Syndication (RSS)&lt;/h1>
&lt;p>RSS stands for Really Simple Syndication. If you need to dive deep into the specification, then you should check out the &lt;a href="https://www.rssboard.org/rss-specification">official website&lt;/a>. Here, I&amp;rsquo;m going to focus on the user&amp;rsquo;s perspective. Please note that the article is not fool-proof, some mistakes surely exist. Please let me know, so I can update it.&lt;/p>
&lt;h2 id="what-is-rss">What is RSS?&lt;/h2>
&lt;p>RSS is a format by which you can access the updates to a website. The website developer, stores the changes in a file, for example in &lt;code>www.example.org/index.xml&lt;/code>, the &lt;code>index.xml&lt;/code> contains the changes made to the website. You on your end, will use an app known as &lt;a href="https://en.wikipedia.org/wiki/News_aggregator">news aggregator&lt;/a> to access the updates. So all you need to do is, install an aggregator app, add the website to its list. Now that app will let you know of the changes whenever it happens. The only requirement is that the developer of website has RSS enabled. Sounds simple right?&lt;/p>
&lt;h2 id="why-not-newsletter">Why not Newsletter?&lt;/h2>
&lt;p>Many &lt;em>modern&lt;/em> websites actually use newsletter, where you provide your email and they send you all the updates. Let&amp;rsquo;s see what are its advantages and disadvantages.&lt;/p>
&lt;h3 id="advantages">Advantages&lt;/h3>
&lt;ul>
&lt;li>Emails can be personalized. The company can target your needs and draft the content in a way you might like. RSS on the other hand is plain and same for everyone. Though, some tweaks can be done, that is a headache.&lt;/li>
&lt;li>Delivery of an email is ensured (provided the email address is valid), which means the company knows that you actually received it (provided you haven&amp;rsquo;t blocked it). But in RSS, it is you who has the control. If you decide to stop visiting a website, then all you need to do is just delete the link from your app. Emails require you to unsubscribe, where the company can collect your feedback and so.&lt;/li>
&lt;/ul>
&lt;h3 id="disadvantages">Disadvantages&lt;/h3>
&lt;ul>
&lt;li>User is not in control. To let go off the updates, you need to unsubscribe from the company. It can be a big hassle.&lt;/li>
&lt;li>If the email addresses stored in the company database is breached, then it will be a threat to your privacy and security.&lt;/li>
&lt;li>Requires an email server. It can be costly, so not affordable by all.&lt;/li>
&lt;/ul>
&lt;h2 id="so-rss">So RSS&lt;/h2>
&lt;p>The advantages of RSS are the disadvantages of the email. Full control for the user and no need of any email server. For an individual developer who is not any interested in user&amp;rsquo;s usage (so called &lt;em>tracking&lt;/em>), RSS is the best.&lt;/p>
&lt;p>Many RSS aggregators exist, including free and open source ones. If you are on Android, you can check out &lt;a href="https://gitlab.com/spacecowboy/Feeder">Feeder&lt;/a>. The steps to add a website to an app, depends on the app in particular.&lt;/p>
&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>The article was meant to brief introduction to RSS. You can learn more about it from the world wild web. RSS is an old technology, it was once at the peak of usage. With the growth in personalized and targeted advertisements, it has gone to a decline. These days, especially among the personal blogs and websites, there is a growing interest in RSS because of privacy and control of user. Hope it continues and enriches.&lt;/p></description></item><item><title>Resume</title><link>https://arunmani.in/resume/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>Arun Mani J (j.arunmani@proton.me)</author><guid>https://arunmani.in/resume/</guid><description/></item></channel></rss>