<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Aziz's blog</title><id>https://benalita.tn/feed.xml</id><subtitle>Recent Posts</subtitle><updated>2026-08-05T19:35:19Z</updated><link href="https://benalita.tn/feed.xml" rel="self" /><link href="https://benalita.tn" /><entry><title>I so badly want to move to KDE</title><id>https://benalita.tn/posts/2026-08-03.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2026-08-03T00:00:00Z</updated><link href="https://benalita.tn/posts/2026-08-03.html" rel="alternate" /><content type="html">&lt;p&gt;I recently tried out KDE in a virtual machine after years of doing my own thing.&lt;/p&gt;
&lt;p&gt;A lot of people who jump into Linux will typically present the same symptoms: the initial disappointment, enthusiasm to try everything out, familiarity, the occasional re-appearance of disappointment due to minor inconveniences.&lt;/p&gt;
&lt;p&gt;Maybe my characterization of these symptoms is off, I'm not a doctor. But I feel like I'm in that last stage and my only cure is to move to a polished system that's got it all figured out for me.&lt;/p&gt;
&lt;p&gt;I don't want to put too much pressure on the KDE folks, but have you seen &lt;a href=&quot;https://blogs.kde.org/2026/08/03/this-month-in-kde-linux-july-2026/&quot;&gt;all the cool stuff they're doing&lt;/a&gt;? No wonder they're getting funded left and right, they deserve it.&lt;/p&gt;
&lt;p&gt;Void has served me very well, I admire the work that goes to keeping the wheels turning but I feel like I'm back in that second stage. I can't help but feel like I want to start afresh, perhaps with Fedora or KDE Linux, and take KDE for a real spin, to use as a daily driver.&lt;/p&gt;
&lt;p&gt;I'm hesitating quite a bit with this decision, because my system works very well for me. Too much of me has been poured into it, and that reflection will almost certainly subside in a pre-constructed environment.&lt;/p&gt;
</content></entry><entry><title>Chasing the wild Tunisie Télécom-shaped goose</title><id>https://benalita.tn/posts/2026-07-26.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2026-07-26T00:00:00Z</updated><link href="https://benalita.tn/posts/2026-07-26.html" rel="alternate" /><content type="html">&lt;figure&gt;
  &lt;figcaption&gt;You can also listen to this post:&lt;/figcaption&gt;
  &lt;audio controls=&quot;controls&quot;&gt;
     &lt;source src=&quot;/files/audio/goose-chase.mp3&quot; type=&quot;audio/mp3&quot; /&gt;
  &lt;/audio&gt;
&lt;/figure&gt;
&lt;p&gt;Tunisia's only broadband internet service provider, &lt;a href=&quot;https://fr.wikipedia.org/wiki/Tunisie_T%C3%A9l%C3%A9com&quot;&gt;Tunisie Télécom&lt;/a&gt;, does not provide customers with status information or status updates when their service is suffering from outages.&lt;/p&gt;
&lt;p&gt;Only?... Well, Broadband internet is and has been a state monopoly since it was &lt;a href=&quot;https://fr.wikipedia.org/wiki/Internet_en_Tunisie&quot;&gt;first introduced in 1996&lt;/a&gt;, the cables that run across the poles and underneath the ground are the sole property of Tunisie Télécom.&lt;/p&gt;
&lt;p&gt;None of the upper-level/dowstream internet service providers, like Globalnet, Topnet and Orange will ever contest this. How so?&lt;/p&gt;
&lt;h1&gt;Going on a wild goose chase&lt;/h1&gt;
&lt;p&gt;I haven't had a stable internet connection for the past two weeks, I have called Globalnet, my internet service provider, a sophisticated word for what is essentially a software layer (PPPoE, DNS and a bunch of bullshit cloud services no one uses) for Tunisie Télécom's physical networking infrastructure, a total number of 11 times over the span of 17 days.&lt;/p&gt;
&lt;p&gt;The issue manifests as a blinking DSL LED and a dead internet LED, a slow blink, unlike the usual rapid blinking indicating a proper connection.&lt;/p&gt;
&lt;p&gt;So, what was the cause?&lt;/p&gt;
&lt;p&gt;At no point did Globalnet give me a solid answer, but here's a quick list of what they suggested throughout those 11 calls:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check the telephone lines for damage&lt;/li&gt;
&lt;li&gt;Lower my bandwidth to something my vDSL line (which had been suffering from immense noise) could handle (I was at 50Mbps mind you, which I had lowered down to 30Mbps to test their hypothesis)&lt;/li&gt;
&lt;li&gt;Wait for a technician to come down for an inspection&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Seeing as I had extended the copper telephone line (because it wasn't long enough), there could have very well been an issue with the wiring, so I redid the cabling by myself three times, I even changed my RJ11 wall socket and the RJ11 cable&lt;/li&gt;
&lt;li&gt;Did that, but there were no differences in the line attenuation and SNR margin numbers&lt;/li&gt;
&lt;li&gt;No one came, so unless he was stabbed and hospitalized, I cannot imagine why it would take their technician 17 days to reach me&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I also bypassed Globalnet and called Tunisie Télécom directly. They refused to help and told me to contact my internet service provider, when I protested saying that the issue was likely from their end, they insisted I call Globalnet.&lt;/p&gt;
&lt;p&gt;Interestingly, Globalnet's own internal support ticket (created on July 09) where they described, in their own words (because the tickets are not user-editable), that the issue was not from their end, but rather Tunisie Télécom's.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/images/2026-07-26-support-ticket.webp&quot; alt=&quot;Support ticket created by Globalnet describing Tunisie Télécom at fault&quot; /&gt;&lt;/p&gt;
&lt;h1&gt;Eureka&lt;/h1&gt;
&lt;p&gt;My brother, whose house is beside mine, a Tunisie Télécom customer, was coincidentally suffering the same issue. Our telephone lines come from the same pole, the same terminal. We have different modems from two entirely different manufacturers.&lt;/p&gt;
&lt;p&gt;He did not extend his own cable, and unlike me, he's not the type to fiddle with his modem, so we can rule out the chance of this ordeal being a wiring or configuration issue.&lt;/p&gt;
&lt;p&gt;What's left on the table? A single possibility, Tunisie Télécom is suffering outages it has not been (effectively) communicating.&lt;/p&gt;
&lt;p&gt;Hell, even their service coverage map is down (as of July 26):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/images/2026-07-26-tt-geo-service.webp&quot; alt=&quot;Tunisie Télécom's service coverage map responds with 503 HTTP&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.steg.com.tn/&quot;&gt;STEG&lt;/a&gt;, like Tunisie Télécom, is a state monopoly. Although these two state-run companies seem to have nothing in common, they are both manifestations of the government, so it's not wild to think that they are both built upon a similar mode of operation: &lt;em&gt;obscurity&lt;/em&gt;.&lt;/p&gt;
&lt;h1&gt;Obscurity&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://famma-dhaw.com/&quot;&gt;Famma Dhaw&lt;/a&gt; is a recent public initiative that provides a listing of regions and towns and their respective access to power.&lt;/p&gt;
&lt;p&gt;This, as far as we know, was built under a few weeks, during the major outages that had occured during mid-July, by people like you and me.&lt;/p&gt;
&lt;p&gt;Famma Dhaw did not and likely would never have come out of STEG.&lt;/p&gt;
&lt;p&gt;STEG, by the way, has existed for over 60 years. It is shocking in that during its more than 60 years of existence, none of STEG's executives thought that creating a public outage tracker would have been beneficial.&lt;/p&gt;
&lt;p&gt;Enough with STEG, let's circle back to Tunisie Télécom.&lt;/p&gt;
&lt;h1&gt;Communication&lt;/h1&gt;
&lt;p&gt;In the software industry (what I do for a living), properly communicating your
outages is the &lt;em&gt;baseline&lt;/em&gt;, you just cannot build a reputation on shaky grounds. I don't understand why a seemingly &lt;a href=&quot;https://www.cox.com/residential/support/outages.html&quot;&gt;basic&lt;/a&gt; &lt;a href=&quot;https://www.xfinity.com/support/statusmap&quot;&gt;right&lt;/a&gt; &lt;a href=&quot;https://suivi-des-incidents.orange.fr/infos-incident-local-internet-TV-telephone-fixe&quot;&gt;for&lt;/a&gt; &lt;a href=&quot;https://www.vodafone.co.uk/network/status-checker&quot;&gt;information&lt;/a&gt; is all so foreign.&lt;/p&gt;
&lt;p&gt;This is especially true when you're the single provider of a country's entire
broadband infrastructure.&lt;/p&gt;
&lt;p&gt;Tunisie Télécom, being 30 years old itself, has yet to offer a public outage
tracker... Does that remind you of some... one?&lt;/p&gt;
&lt;p&gt;You might imagine Tunisie Télécom being the 30 year old deadbeat child of a 60
year old STEG, if STEG were to have a child at 30.  The resemblance is quite uncanny.  It's almost like it runs in the family.&lt;/p&gt;
&lt;h1&gt;What's next?&lt;/h1&gt;
&lt;p&gt;Famma Dhaw is the result of dissatisfaction with the current state of affairs and the willingness of the people to take matters into their own hands (a.k.a crowd-sourcing). It is not the
responsibility of ordinary citizens to maintain a public service tracker. It is
fallacious to think otherwise, only Tunisie Télécom can provide its customers,
the tax-payers to whom it owes everything, with a comprehensive and reliable service tracker.&lt;/p&gt;
&lt;p&gt;Anything short of that is unacceptable and proof that obscurity is at the root
of everything wrong with our public institutions.&lt;/p&gt;
</content></entry><entry><title>Municipality of Raoued, you haven't won yet</title><id>https://benalita.tn/posts/2026-05-30.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2026-05-30T00:00:00Z</updated><link href="https://benalita.tn/posts/2026-05-30.html" rel="alternate" /><content type="html">&lt;p&gt;It was Aid these past few days and trash has been quickly piling up, the trash cans are directly facing my house, so it's hard to ignore.&lt;/p&gt;
&lt;p&gt;I have taken the car for a ride to try and see what other neighborhoods look like in a messy period such as this one, and surprisingly, out of the 4 neighborhoods I drove through (granted the sample size is rather small), mine is the only one where trash has piled up so much it had begun to take up significant portions of the road.&lt;/p&gt;
&lt;p&gt;See for yourself:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/images/trash.jpeg&quot; alt=&quot;Trash piling up on the ground in my neighborhood&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That is what happens when garbage men and garbage trucks only care to pick up what's inside the trash cans and intentionally leave behind the exceptionally large volumes of trash on the ground, &lt;em&gt;the sole reason for which they are on the ground is because of a lack of trash cans in the first place&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Yesterday the municipality of Raoued posted on Facebook priding themselves on cleaning up so many other neighborhoods that previously looked like mine as a result of their poor planning for the Aid.&lt;/p&gt;
&lt;p&gt;How can I personally explain to myself, when I saw with my own two eyes when the garbage men clearly signaled to go, despite having left behind three times the volume of what they had picked up, that the reason for their decision isn't ultimately a clear example of the municipality's discriminatory behavior and a lack of fucks given if we (neighborhoods like mine) ever come to that realization.&lt;/p&gt;
&lt;p&gt;When I saw them claiming victory on social media, I couldn't help but feel like the head of that municipality (whose name I could not find) thinks they're doing a good job, when in fact, it's quite the opposite, and that, friends, is so funny to me.&lt;/p&gt;
&lt;p&gt;Clearly the municipality's president is sleeping pretty well at night, and that's kind of the purpose of these social media campaigns. It's just about them feeling good about themselves whether or not they are actually serving the city.&lt;/p&gt;
&lt;h1&gt;Update&lt;/h1&gt;
&lt;p&gt;Two trucks came by later in the day to pick up that mountain of trash. It goes without saying that this issue should have never happened in the first place, it is indicative of a systemic issue. Our municipality, and all the others, need to take a much more proactive approach to make sure this actually never happens again.&lt;/p&gt;
&lt;p&gt;Some people are saying there should be a central location where trash that can accumulate during &lt;em&gt;this particular occasion&lt;/em&gt; can be dropped off (by the people themselves). It's a good idea, but good luck enforcing it, and that makes it a bad first step.&lt;/p&gt;
&lt;p&gt;I personally think a much more feasible first step would be for the government to attempt to instill a much greater sense of responsibility over the handling of trash of this nature on these occasions, such as by placing all of it in &lt;strong&gt;plastic bags&lt;/strong&gt;. That would of course mean that the goal of the social media campaigns moves away from a hey-look-at-us, patting-ourselves-on-the-back approach to making worthwhile public service announcements with clear messaging on the issue and how we can collectively resolve it.&lt;/p&gt;
&lt;p&gt;The plastic bag idea might obvious to anyone with a brain but you'd be surprised how little thought people put into handling their trash during festivities.&lt;/p&gt;
&lt;p&gt;I would honestly love to &lt;a href=&quot;/contact.html&quot;&gt;hear other people's ideas&lt;/a&gt;, mine feels sort of contingent on higher levels of awareness, and cultivating that is really tricky. It takes a lot of work, but well, it's all up to us.&lt;/p&gt;
</content></entry><entry><title>CNSS doesn't want my money</title><id>https://benalita.tn/posts/2026-04-19.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2026-04-19T00:00:00Z</updated><link href="https://benalita.tn/posts/2026-04-19.html" rel="alternate" /><content type="html">&lt;p&gt;&lt;a href=&quot;/posts/2026-04-05.html&quot;&gt;In the previous post&lt;/a&gt;, we looked at eHouwiya's poor
login form design, this time we'll look at an infuriating bug in the CNSS login
form.  For the foreigners, CNSS is Tunisia's social security fund.&lt;/p&gt;
&lt;p&gt;I contacted CNSS via email on April 15 about this very bug, they have yet to
respond, so I took it upon myself to use my personal blog as a bug tracker
for the government.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I know I'm desperate, you don't have to tell me that.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;Preface&lt;/h1&gt;
&lt;p&gt;I hate long lines, and I especially hate taking time from work to wait in long
lines for services which have long been digitized.&lt;/p&gt;
&lt;p&gt;There's a local CNSS office close to where I live which is open on Saturdays. I
entered the office thinking I'd make my quarterly social security payment but
it turns out they don't accept payments on Saturdays. Great.&lt;/p&gt;
&lt;p&gt;I haven't been able to login for close to five months now, so I've missed the
last payment, and that means I'll have to pay a little extra because of late
payment charges. Great.&lt;/p&gt;
&lt;p&gt;During those five months, I kept a close eye on their authentication form,
logging in every week to see how things were evolving. The bug which I'm about to
show you was previously much worse than it currently is.&lt;/p&gt;
&lt;h1&gt;Logging in&lt;/h1&gt;
&lt;p&gt;Getting past eHouwiya's login form is already a chore, but the moment I
authenticate, CNSS redirects me back to the login form, as if it had refreshed
the page.&lt;/p&gt;
&lt;p&gt;Looking at the address bar, I can clearly see a new &lt;code&gt;code&lt;/code&gt; query parameter with a
plausible looking value that the backend generates to identify my session:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;https://tns.cnss.tn/TnsNet/pages/Authentification.xhtml?code=dL***c6
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I've got my session cookie, so what's wrong?&lt;/p&gt;
&lt;p&gt;Well, &lt;a href=&quot;https://www.oauth.com/oauth2-servers/redirect-uris/&quot;&gt;OAuth2 is actually straightforward about what should happen when the user successfully authenticates&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After a user successfully authorizes an application, the authorization server will redirect the user back to the application. Because the redirect URL will contain sensitive information, it is critical that the service doesn’t redirect the user to arbitrary locations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;Redirection&lt;/h1&gt;
&lt;p&gt;What CNSS is doing is actually the opposite, instead of redirecting me to the next page (where I would proceed to give them my money), they redirect me back to the authentication page.&lt;/p&gt;
&lt;p&gt;Here's the payload of what they send to eHouwiya's authentication endpoint:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;response_type code
client_id ***
scope openid phone identity birthdate id_social email
redirect_uri https://tns.cnss.tn/TnsNet/pages/Authentification.xhtml
code_challenge_method S256
code_challenge ***
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Do you see it?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;redirect_uri&lt;/code&gt; points to the same page I use to login. Argh! That explains it.&lt;/p&gt;
&lt;p&gt;Well, seeing as I'm authenticated, I tried guessing the name of the payment
page.  I gave up after my fifth attempt.&lt;/p&gt;
&lt;p&gt;This story, much like the one before it, ends in frustration. You do not get a happy ending.&lt;/p&gt;
&lt;h1&gt;Workaround&lt;/h1&gt;
&lt;p&gt;Assuming you signed in via eHouwiya and have a &lt;code&gt;code&lt;/code&gt; query parameter (URL would end in &lt;code&gt;?code=***&lt;/code&gt;, you can proceed to the payment page by setting the page (the last part of the URL not including the &lt;code&gt;code&lt;/code&gt; parameter) to &lt;code&gt;CotisationEncours.xhtml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Your URL should look like:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;https://tns.cnss.tn/TnsNet/pages/CotisationEncours.xhtml?code=***
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I discovered this by manually signing into the service using the classic credentials form (which I didn't know I could do).&lt;/p&gt;
&lt;p&gt;It's literally that simple, all CNSS would have to do to fix this issue is to set the &lt;code&gt;redirect_uri&lt;/code&gt; to that URL and everything would work as expected.&lt;/p&gt;
</content></entry><entry><title>e-Houwiya/MobileID has a serious UX problem</title><id>https://benalita.tn/posts/2026-04-05.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2026-04-05T00:00:00Z</updated><link href="https://benalita.tn/posts/2026-04-05.html" rel="alternate" /><content type="html">&lt;p&gt;e-Houwiya, also called MobileID, is Tunisia's government-backed identity
platform. I have been using it for a little over a year and I've got several
issues with the way the login form works that I need to talk about.&lt;/p&gt;
&lt;h1&gt;Preface&lt;/h1&gt;
&lt;p&gt;I think e-Houwiya is a step in the right direction.&lt;/p&gt;
&lt;p&gt;My current stance is that e-Houwiya's reliance on SMS verification opens the
system to more than a few vulnerabilities that simply cannot be addressed
unless they exchange it with a more secure verification layer (like TOTP or
hardware key verification).&lt;/p&gt;
&lt;p&gt;Nevertheless, my thoughts on the security implementation are the topic of
another day, today I want to focus solely on MobileId's misguided UX which makes
the service an utter pain to use day-to-day.&lt;/p&gt;
&lt;h1&gt;What we expect&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The ability to copy and paste form input:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Password manager extensions should not fail to automatically insert your login credentials&lt;/li&gt;
&lt;li&gt;A user should have no problem trying to paste their credentials from an external password manager (one they've installed outside of their browser)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The ability to manipulate the contents of the form without breaking common user access (CUA) conventions&lt;/li&gt;
&lt;li&gt;Form validation should prevent you from entering prohibited characters&lt;/li&gt;
&lt;li&gt;Resending the verification SMS should not reset all user input&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;What we get&lt;/h1&gt;
&lt;p&gt;MobileId fails on every account with regards to my own personal expectations of
what it should provide as a tool that I'm supposed to use every day.&lt;/p&gt;
&lt;p&gt;Let's run through those expectations to understand what I mean:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You cannot copy and paste data into the form: the reason for this is because the form has been split into 10 individual &lt;code&gt;input&lt;/code&gt; fields... &lt;em&gt;Seriously? Why?&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You use a password manager to stay safe? Think again.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You use assistive technology? Tough luck, that screen reader is going to struggle to make sense of the DOM.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;../files/images/mobileid-inputs-galore.png&quot; alt=&quot;MobileID OTP form&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You didn't receive your SMS? Too bad, re-enter all your credentials.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;../files/images/mobileid-otp.png&quot; alt=&quot;MobileID&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You cannot rely on the conventions of common user access to navigate fields&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reverse-tabbing (Shift+Tab) doesn't work when the preceding field contains a character&lt;/li&gt;
&lt;li&gt;You cannot use your arrow keys to navigate between every digit&lt;/li&gt;
&lt;li&gt;You cannot use the backspace key to delete more than one digit&lt;/li&gt;
&lt;li&gt;If you're a fast typist, you might even be able to out-pace the navigation logic they implemented to move you from one field to the next&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MobileId only uses digits but the form still lets you enter symbols and alphabetical characters&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;What now?&lt;/h1&gt;
&lt;p&gt;MobileId's form logic is, as of the date of publication, around 400 lines of
JavaScript (embedded directly in the HTML document), 90 of those lines are
spent poorly reimplementing what HTML natively provides in one simple and effective
attribute: &lt;code&gt;&amp;lt;input type=&amp;quot;number&amp;quot;&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I hope someone from Sirat, TunTrust or whomever's managing the project sees
this post and views it as suggestions for improving the service for
everyone using it. I'd love to see MobileId integrated in more and more
government services as it makes my life a lot easier. One could only hope.&lt;/p&gt;
&lt;h1&gt;Update&lt;/h1&gt;
&lt;p&gt;I reached out to SIRAT who quickly responded saying they &amp;quot;think&amp;quot; that the
project is now &amp;quot;owned&amp;quot; by the Ministry of Information and Communication
Technologies. SIRAT is the name of a company that appears at the foot of the
eHouwiya login form.  I presume the project was initially contracted out to them.&lt;/p&gt;
&lt;p&gt;So, I reached out to said ministry though I have yet to receive a response.
I'll update this post as I receive more information.&lt;/p&gt;
</content></entry><entry><title>Leaving Mastodon</title><id>https://benalita.tn/posts/2025-06-21.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2025-06-21T00:00:00Z</updated><link href="https://benalita.tn/posts/2025-06-21.html" rel="alternate" /><content type="html">&lt;p&gt;I removed my Mastodon account two days ago, my reasons for leaving are sort of a personal matter and have nothing to do with Mastodon as a technology or anyone in particular.&lt;/p&gt;
&lt;p&gt;One reason I wouldn't mind sharing is that I wish to be more independent when it comes to where I choose to share my thoughts. I do, after all, have full control of this domain and the contents of this website.&lt;/p&gt;
&lt;p&gt;I'd like for this website to be the manifestation of my self-expression and the home to my writing. If I have anything to say, you may expect to find it here.&lt;/p&gt;
</content></entry><entry><title>Trying out Labwc</title><id>https://benalita.tn/posts/2025-05-01.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2025-05-01T00:00:00Z</updated><link href="https://benalita.tn/posts/2025-05-01.html" rel="alternate" /><content type="html">&lt;p&gt;I've been using &lt;a href=&quot;https://labwc.github.io/&quot;&gt;Labwc&lt;/a&gt; the past week and I've been pleasantly surprised with it, it is a floating window manager inspired by &lt;a href=&quot;https://openbox.org/&quot;&gt;Openbox&lt;/a&gt; but for Wayland.&lt;/p&gt;
&lt;p&gt;For context, I used to use a tabbed layout on &lt;a href=&quot;https://swaywm.org/&quot;&gt;Sway&lt;/a&gt;, making the compositor feel like a web browser. I have a small screen so window tiling is actually disadvantageous.&lt;/p&gt;
&lt;p&gt;This isn't my first time using Labwc, it's actually my second. The first time I used it was in december of last year. I let it go the first time just as one would when faced with an unfamiliar and challenging problem. I came back because Sway was giving me trouble with some really &lt;a href=&quot;https://github.com/swaywm/sway/issues/5757&quot;&gt;nasty&lt;/a&gt; &lt;a href=&quot;https://github.com/swaywm/sway/issues/8434&quot;&gt;bugs&lt;/a&gt; related to my dual monitor setup.&lt;/p&gt;
&lt;p&gt;I have to admit that I generally dislike the floating paradigm. Without recurring to external tools, floating window managers become wasteful and hard to navigate past a certain number of windows.&lt;/p&gt;
&lt;p&gt;Despite my worries, I still wanted to experience the Wayland desktop from another perspective, I had been using Sway for quite a bit of time and it checks every single one of my requirements for a window manager: simple (sometimes a little too simple), efficient, scriptable, well-maintained and enjoys a large community of desktop hackers.&lt;/p&gt;
&lt;p&gt;Labwc draws some parallels with &lt;a href=&quot;https://en.wikipedia.org/wiki/Metacity&quot;&gt;Metacity&lt;/a&gt; in striving to be simple, Metacity has been described as a &amp;quot;Boring window manager for the adult in you&amp;quot;. I think objectives like this are very important especially in a niche that tends to go over the top with customization and bling.&lt;/p&gt;
&lt;p&gt;I dislike panels and have no use for widgets, the &lt;a href=&quot;https://linux.die.net/man/1/dmenu&quot;&gt;dmenu-way&lt;/a&gt; of doing things is, in my opinion, superior in all the ways. &lt;a href=&quot;https://git.sr.ht/~grtcdr/dotfiles/tree/master/item/scripts/.local/menu&quot;&gt;All the fuzzel menus I wrote for Sway&lt;/a&gt; I took with me to Labwc, meaning that my primary way of interacting with my system remains through a dmenu-like interface. I refactored some of those scripts of course but switching was straightforward and the whole experience has been delightful.&lt;/p&gt;
</content></entry><entry><title>Adventures with Void Linux, Wayland and NVIDIA</title><id>https://benalita.tn/posts/2025-02-16.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2025-02-16T00:00:00Z</updated><link href="https://benalita.tn/posts/2025-02-16.html" rel="alternate" /><content type="html">&lt;p&gt;I recently started a new remote job and with it came the obvious need to upgrade my setup. If I'm going to be spending more and more time on a computer, then it needs to be a comfortable experience. You know the drill.&lt;/p&gt;
&lt;p&gt;I brought back my usual 24&amp;quot; monitor thinking I could make use of it. I was surprised to learn that NVIDIA's official drivers were not supported on musl-based Void Linux installations.&lt;/p&gt;
&lt;h1&gt;Denial&lt;/h1&gt;
&lt;p&gt;I scrambled to find a solution though all the advice hinted at running glibc instead. I refused to accept that.&lt;/p&gt;
&lt;p&gt;I tried all the different combinations of &lt;code&gt;WLR_*&lt;/code&gt; &lt;a href=&quot;https://github.com/swaywm/wlroots/blob/master/docs/env_vars.md&quot;&gt;environment variables&lt;/a&gt; there were but none seemed to work. I tried setting a few kernel flags but this part was sort of fuzzy. I didn't &lt;em&gt;really&lt;/em&gt; know what I was doing.&lt;/p&gt;
&lt;p&gt;I proceeded to back up my home directory and then I reinstalled Void Linux, with glibc this time. I went and installed the official NVIDIA drivers thinking my problem was about to be solved. They were the official, ordained drivers after all. I was dead wrong.&lt;/p&gt;
&lt;p&gt;These drivers refused to work in any way with Sway, the only compositor I had been using since I made the move to Wayland a couple years ago, I refuse to use anything else.&lt;/p&gt;
&lt;h1&gt;Bargaining&lt;/h1&gt;
&lt;p&gt;I enabled mode setting for the card, tried a bunch of different &lt;code&gt;WLR_*&lt;/code&gt; combinations once again. This time the monitor worked! Hooray. Oh no, my laptop's display is all black... Long story short: Using a combination of flags either results in a working external monitor or a working laptop display, never both.&lt;/p&gt;
&lt;p&gt;I removed the cursed drivers from my system and gave nouveau another chance. I made sure to enable mode setting this time, perhaps the only thing I should have done in my previous musl installation.&lt;/p&gt;
&lt;h1&gt;Surprise&lt;/h1&gt;
&lt;p&gt;I rebooted the system, and to my surprise, it was all working. Nouveau was able to piece everything together in a way the official drivers couldn't. I was relieved but also largely disappointed with NVIDIA. This is not a rant, so I'm not going to start pointing fingers. I just wanted to put this in writing to get the word out there.&lt;/p&gt;
&lt;p&gt;If you have a card that is an &lt;a href=&quot;https://nouveau.freedesktop.org/PowerManagement.html&quot;&gt;NV160 or higher&lt;/a&gt; (like mine), you can absolutely have a great experience with your NVIDIA card on Linux with Wayland. It's all thanks to the talented people who have been able to reverse-engineer the drivers, it's pretty magical that they work this well in the first place.&lt;/p&gt;
</content></entry><entry><title>On the topic of Emacs themes</title><id>https://benalita.tn/posts/2024-12-09.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2024-12-09T00:00:00Z</updated><link href="https://benalita.tn/posts/2024-12-09.html" rel="alternate" /><content type="html">&lt;p&gt;I missed out on watching EmacsConf as it was taking place but I'm making my way through it now.&lt;/p&gt;
&lt;p&gt;I really enjoyed the talk that &lt;a href=&quot;https://hachyderm.io/@rytswd&quot;&gt;@rytswd@hachyderm.io&lt;/a&gt; gave about colouring Emacs and the considerations in methodology that one should take into account when making their own theme.&lt;/p&gt;
&lt;p&gt;I really struggle at creating consistent color palettes. I just adjust the colors haphazardly until it looks &amp;quot;good&amp;quot; (and it rarely ever does).&lt;/p&gt;
&lt;p&gt;Ryota's tips all sound great for someone wanting to take the next step in making consistently beautiful themes.&lt;/p&gt;
&lt;p&gt;One thing he mentioned that stood out to me was that most (if not all) text editors and integrated development environments rely too heavily on colors. In my opinion, that makes the programming experience atrocious from a legibility perspective.&lt;/p&gt;
&lt;p&gt;I personally like to disable the rainbow vomit by hacking font lock directly and this little function works like a charm:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(defun my/font-lock ()
  &amp;quot;Enable limited syntax highlighting for the current buffer.
Too much coloring is obnoxious and is an impediment to
readability for me. When this function is invoked, only strings
and comments will be highlighted.&amp;quot;
  (setq-local font-lock-keywords nil)
  (turn-on-font-lock))

(add-hook 'prog-mode-hook #'my/font-lock)
(add-hook 'lisp-mode-hook #'my/font-lock)
(add-hook 'scheme-mode-hook #'my/font-lock)
(add-hook 'emacs-lisp-mode-hook #'my/font-lock)
(add-hook 'sh-mode-hook #'my/font-lock)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Still, Ryota's tips about color spaces are going to help me navigate theming more methodically which I'm certain is going to make the experience that much more enjoyable.&lt;/p&gt;
</content></entry><entry><title>Keeping a text log of my job applications</title><id>https://benalita.tn/posts/2024-12-02.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2024-12-02T00:00:00Z</updated><link href="https://benalita.tn/posts/2024-12-02.html" rel="alternate" /><content type="html">&lt;p&gt;Looking for a job is probably the single worst and most boring thing to do at least as a junior software engineer. I recently graduated so this was my fate.&lt;/p&gt;
&lt;p&gt;I started applying left and right to different kinds of jobs in lots of different places. Some jobs I applied for on LinkedIn, others in more obscure job-board platforms.&lt;/p&gt;
&lt;p&gt;I wanted to have some sort of log that was independent of any of these websites to keep track of those jobs and query them in a simpler fashion.&lt;/p&gt;
&lt;p&gt;I stopped applying for jobs and took to &lt;a href=&quot;https://seths.blog/2005/03/dont_shave_that/&quot;&gt;yak shaving&lt;/a&gt;. I came out with a pretty decent text-based format where every job takes up one line with all of its relevant information.&lt;/p&gt;
&lt;p&gt;I added an Emacs &lt;code&gt;completing-read&lt;/code&gt;-based interface for it that helps to manage the database without editing the file directly. The parser is based on simple regular expressions and there's even a major mode that makes the database look pretty.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/images/joblog.webp&quot; alt=&quot;Emacs frame showing joblog selection menu on one side and the text format on the other&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If that sounds appealing to you, go on and have a look at the &lt;a href=&quot;https://git.sr.ht/~grtcdr/joblog&quot;&gt;project's source repository&lt;/a&gt;.&lt;/p&gt;
</content></entry><entry><title>Choosing Void Linux</title><id>https://benalita.tn/posts/2024-11-22.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2024-11-22T00:00:00Z</updated><link href="https://benalita.tn/posts/2024-11-22.html" rel="alternate" /><content type="html">&lt;p&gt;I recently made the switch to Void Linux and I'm really enjoying it. Void Linux is very close in nature to Arch Linux. It's a build-your-own-experience kind of distribution. I like those. For the sake of fairness, comparisons to Arch Linux will not be made going forward.&lt;/p&gt;
&lt;h1&gt;Why switch?&lt;/h1&gt;
&lt;p&gt;I like trying out new and different things. Void Linux was different enough to warrant inspection. I was curious about Void Linux the most because it's a traditional distribution (no fancy-shmancy derivations or immutable filesystems) with a few interesting twists.&lt;/p&gt;
&lt;h1&gt;What's different about Void Linux?&lt;/h1&gt;
&lt;p&gt;Off the top of my head:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the freedom to choose between &lt;code&gt;musl&lt;/code&gt; and &lt;code&gt;libc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;a dead simple init system called &lt;code&gt;runit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a solid package manager called &lt;code&gt;xbps&lt;/code&gt; although the name really sucks to type (for obvious reasons); package updates are sparse so it's easy to keep up with my system&lt;/li&gt;
&lt;li&gt;it's easy to reason about and that boils down to the choices of programs that ship with it by default (have you seen &lt;code&gt;acpid&lt;/code&gt;?)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Initial difficulties&lt;/h1&gt;
&lt;p&gt;I tried to install Void Linux three times with &lt;em&gt;LVM on LUKS&lt;/em&gt; (following the exact instructions of the Void Linux wiki). I failed in every instance.&lt;/p&gt;
&lt;p&gt;GRUB kept insisting that the &lt;code&gt;/boot/efi&lt;/code&gt; filesystem was not a recognized filesystem even though I had used VFAT, I didn't specify the size of the file allocation tables so it was up to &lt;code&gt;mkfs.vfat&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Just to be sure, I tried to use &lt;code&gt;mkfs.fat -F32&lt;/code&gt; but that also wouldn't work.&lt;/p&gt;
&lt;p&gt;I gave up on encryption and used the graphical partitioning menu (which doesn't support encryption) and Void managed to install itself without a hitch.&lt;/p&gt;
&lt;h1&gt;Init with &lt;code&gt;runit&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Runit has turned out to be a really good fit for me. It's fundamentally really simple. It's spread across a number of programs, the manpages of which could be read in a single sitting. They're quality manuals, but in terms of examples, they leave a lot to be desired. Thankfully, despite &lt;code&gt;runit&lt;/code&gt; being a rather niche init system, there were enough articles out there on the web for me to understand how to use it correctly.&lt;/p&gt;
&lt;p&gt;User services are dead simple to set up. I've currently set it up such that &lt;code&gt;sway&lt;/code&gt;, my window manager and compositor, invokes &lt;code&gt;runsvdir&lt;/code&gt; to start all other services, including &lt;code&gt;swaybg&lt;/code&gt;, &lt;code&gt;pipewire&lt;/code&gt;, &lt;code&gt;syncthing&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;I have created two scripts to manage the &lt;a href=&quot;https://git.sr.ht/~grtcdr/dotfiles/tree/master/item/scripts/.local/bin/swayup&quot;&gt;startup&lt;/a&gt; and &lt;a href=&quot;https://git.sr.ht/~grtcdr/dotfiles/tree/master/item/scripts/.local/bin/swaydown&quot;&gt;shutdown&lt;/a&gt; of the compositor and different user services, the shutdown script is especially crucial because user services will hang out forever unless explicitly stopped.&lt;/p&gt;
&lt;p&gt;Note that I'm using &lt;code&gt;greetd&lt;/code&gt; as my login manager and &lt;code&gt;seatd&lt;/code&gt; to manage input devices and such. I'm not using &lt;code&gt;elogind&lt;/code&gt;... About that, let's talk &lt;code&gt;systemd&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;Looking back on &lt;code&gt;systemd&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;I like &lt;code&gt;systemd&lt;/code&gt;, it's a comprehensive solution to a seemingly simple problem. I have no issues with it, &lt;code&gt;systemd&lt;/code&gt; is comfortable with having a large scope but I believe that the people who stand to benefit the most from &lt;code&gt;systemd&lt;/code&gt; are desktop environments. &lt;code&gt;systemd&lt;/code&gt; is the perfect choice for plug-and-play environments. It &lt;em&gt;almost&lt;/em&gt; just works for almost everyone. &lt;em&gt;Almost?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Desktop environments carry a lot of weight, despite the fact that some of them offer a plethora of customization features, an opinionated person such as myself would rather build something of their own. Linux has made me enjoy picking things apart which has meant that none of the desktop environments could satiate my thirst for complete control.&lt;/p&gt;
&lt;p&gt;I was able to build my own &amp;quot;desktop environment&amp;quot; on top of &lt;code&gt;systemd&lt;/code&gt; but it was really hard to pull off. I'd say it felt fragile but it worked and it worked really well. Eventually my own creation became cumbersome to maintain and that contributed to wanting to try out something different.&lt;/p&gt;
&lt;h1&gt;Bugs I encountered&lt;/h1&gt;
&lt;p&gt;First, I was unable to use Emacs in the first few days, I came up against a &lt;a href=&quot;https://lists.gnu.org/archive/html/bug-gnu-emacs/2024-11/msg00817.html&quot;&gt;really odd bug&lt;/a&gt; that should have never happened. That issue luckily and inexplicably &lt;a href=&quot;https://github.com/void-linux/void-packages/issues/53098&quot;&gt;resolved itself&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Second, My screen occasionally flickers and it's really annoying. I disabled &lt;code&gt;i915.enable_psr&lt;/code&gt; which should have eliminated the flickering according to the Arch Wiki but it doesn't seem to have made a difference.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Update (2024-11-25): I was able to fix the screen flickering by adding &lt;code&gt;intel_iommu=igfx_off&lt;/code&gt; to &lt;code&gt;GRUB_CMDLINE_LINUX_DEFAULT&lt;/code&gt; as suggested in the &lt;a href=&quot;https://docs.voidlinux.org/config/graphical-session/graphics-drivers/intel.html?highlight=iommu#troubleshooting&quot;&gt;Void handbook&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That's it, Void Linux has been great otherwise.&lt;/p&gt;
&lt;h1&gt;Notes&lt;/h1&gt;
&lt;p&gt;I'm really enjoying &lt;code&gt;fuzzypkg&lt;/code&gt;; it's a relatively simple package management &lt;code&gt;fzf&lt;/code&gt;-based interface for &lt;code&gt;xbps&lt;/code&gt;. I use it all the time. I went a step further and created a &lt;code&gt;.desktop&lt;/code&gt; file for it.&lt;/p&gt;
&lt;p&gt;I wanted to avoid &lt;code&gt;elogind&lt;/code&gt; at all costs so to work around the lack of an &lt;code&gt;XDG_RUNTIME_DIR&lt;/code&gt;, I resorted to &lt;code&gt;pam_rundir&lt;/code&gt; which worked beautifully. I initially had issues logging back in after logging out where &lt;code&gt;greetd&lt;/code&gt; would exclaim that &lt;code&gt;XDG_RUNTIME_DIR&lt;/code&gt; was undefined. I messed around with the placement of the PAM module and found the best place for it (in the &lt;code&gt;/etc/pam.d/system-login&lt;/code&gt;) was right after:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;password   include    system-auth
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I'm still exploring Void Linux. I've got a lot to learn. I'm really excited to be trying something new for a change. Despite leaving Arch Linux behind (for now), I still rely on the vast knowledge of the Arch Wiki accrued over two decades of lots of hard work by the community.&lt;/p&gt;
</content></entry><entry><title>I changed my mind about Emacs' document viewer</title><id>https://benalita.tn/posts/2024-11-02.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2024-11-02T00:00:00Z</updated><link href="https://benalita.tn/posts/2024-11-02.html" rel="alternate" /><content type="html">&lt;p&gt;My biggest pet peeve used to be Emacs' built-in document viewer. I really wanted to browse PDFs and EPUBs in Emacs but the viewer was blurry and scrolling was horribly slow.&lt;/p&gt;
&lt;p&gt;I used Zathura for many years and Sioyek for a few months, they are both wonderful viewers but I just wasn't satisfied with either.&lt;/p&gt;
&lt;p&gt;Well, things took a turn for the better when yours truly discovered an obscure new variable in Emacs 29.1 that could convert PDFs into SVGs, this variable is called &lt;code&gt;doc-view-mupdf-use-svg&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you have &lt;code&gt;mupdf-tools&lt;/code&gt; installed (the package might be named differently on your distribution) and set &lt;code&gt;doc-view-mupdf-use-svg&lt;/code&gt; to &lt;code&gt;t&lt;/code&gt;, Emacs will render EPUBs, PDFs — and all the other formats that MuPDF supports — as SVGs so sharp and beautiful it will knock the socks off your &lt;code&gt;pdf-tools&lt;/code&gt; installation — and maybe even &lt;code&gt;nov&lt;/code&gt;.&lt;/p&gt;
</content></entry><entry><title>On drafting and messy writing</title><id>https://benalita.tn/posts/2024-10-12.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2024-10-12T00:00:00Z</updated><link href="https://benalita.tn/posts/2024-10-12.html" rel="alternate" /><content type="html">&lt;p&gt;I hacked together a drafting feature/workflow for my blog and it's made
me write (and want to write) more. I'm surprised by this, but to expand
on this idea, it could be that this has freed me to write whatever comes
to mind without worrying too much about whether I'll publish it or not.&lt;/p&gt;
&lt;p&gt;It's a draft, it's there, it's incomplete, it's whatever. I might work
on it. I might not. It's an idea. I could come back to it at anytime or
just keep it there on the off chance that someday the idea could be
useful in some other, possibly irrelevant context.&lt;/p&gt;
&lt;p&gt;I know drafting is obvious for a lot of people, but I've always had a
fear that has handicapped my writing for so long. It's a fear of writing
inadequately. It's actually this style of writing that has lifted the
weight of being perfect all the time off my shoulders. Writing all
messy, and on purpose, is wonderful and &lt;a href=&quot;https://ckarchive.com/b/5quvh7h6ke25&quot;&gt;I have Oliver Burkeman to thank
for it&lt;/a&gt;.&lt;/p&gt;
</content></entry><entry><title>Music to complement your boredom</title><id>https://benalita.tn/posts/2024-09-26.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2024-09-26T00:00:00Z</updated><link href="https://benalita.tn/posts/2024-09-26.html" rel="alternate" /><content type="html">&lt;p&gt;If you ever find yourself in the mood for some music to complement your
excruciating boredom, you're going to want to give Brian Eno a listen.&lt;/p&gt;
&lt;p&gt;Eno's music does not impose itself, it's the kind of music you can pop
in the background and preserve your attention because, in my experience,
while his music doesn't exactly fade into the background, it never
causes any mental interruptions either.&lt;/p&gt;
&lt;p&gt;For your first piece, start with &lt;em&gt;&amp;quot;Bloom&amp;quot;&lt;/em&gt;, an hour and a half long
composition of entrancing melodies that Brian Eno and Peter Chilvers
collaborated to create in June 2024.&lt;/p&gt;
&lt;p&gt;While typing this up, I found out through &lt;a href=&quot;http://www.peterchilvers.com/?p=143&quot;&gt;one of Peter Chilvers' blog
posts&lt;/a&gt; that Bloom was rooted in a rich history dating
back to 2008, when Peter and Eno released an application of an identical
name which would let you compose your own music from a set of equally
soothing notes or take over when idle to generate music ad infinitum.&lt;/p&gt;
&lt;p&gt;Bloom's use of ripple effects and beautiful gradient backgrounds would
really make for a perfect screensaver.&lt;/p&gt;
</content></entry><entry><title>Hot chocolate is my thing now</title><id>https://benalita.tn/posts/2024-09-20.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2024-09-20T00:00:00Z</updated><link href="https://benalita.tn/posts/2024-09-20.html" rel="alternate" /><content type="html">&lt;blockquote&gt;
&lt;p&gt;It's been a while since I last posted, I thought I'd break the ice by
talking about something completely irrelevant to the usual topics
discussed in this blog.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I stopped drinking coffee a couple months ago. I made that decision when
coffee began to seriously interfere with my health during a really
stressful time in my life.&lt;/p&gt;
&lt;p&gt;I went through a bit of a crisis trying to figure out how to patch up
the hole that old addiction had left.&lt;/p&gt;
&lt;p&gt;I mostly drank water, and water is a good drink, in fact it's so good
we're looking for it in outer space. One problem with water is that it's
tasteless. It's not going to replace a refreshing, flavorful drink.&lt;/p&gt;
&lt;p&gt;I went through a tea phase, and tea is nice, but it can get a bit
boring. So I tried icing it, that was fun the first time, then it became
a hassle.&lt;/p&gt;
&lt;p&gt;I was out buying groceries one day when I got the idea to make myself a
nice cup of hot chocolate, I had never done that in all of my
life — I've had hot chocolate before, it just never clicked for me.&lt;/p&gt;
&lt;p&gt;There's something different about preparing a drink &lt;em&gt;for yourself&lt;/em&gt;, a good
cup of hot chocolate feels like a birthday present, a birthday present
for your taste buds and esophagus.&lt;/p&gt;
&lt;p&gt;Coffee had been my de facto drink for a long time, it was easy to
prepare and it's quite a delicious beverage, it was good enough that I
didn't bother trying out some of the alternatives which I've now come to
appreciate.&lt;/p&gt;
</content></entry><entry><title>Bringing XDG Desktop Portal support to Emacs</title><id>https://benalita.tn/posts/2024-01-10.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2024-01-10T00:00:00Z</updated><link href="https://benalita.tn/posts/2024-01-10.html" rel="alternate" /><content type="html">&lt;p&gt;Sandboxes, like those of &lt;code&gt;bwrap&lt;/code&gt; and &lt;code&gt;systemd&lt;/code&gt;, are an effective way to
secure your system from applications you don't or can't trust.&lt;/p&gt;
&lt;p&gt;I may trust Emacs, but I don't trust myself to audit every single line
of code (built-in or third-party) that the Emacs Lisp interpreter
evaluates. Additionally, I may trust in the security of Chromium's
provided sandbox, but I don't trust that it's infallible; no software
is.&lt;/p&gt;
&lt;p&gt;I do however put great effort to keep things secure which is why the
most vulnerable parts of my system, the applications which are first and
foremost a presentation layer over other people's code, are sandboxed
either via &lt;code&gt;bwrap&lt;/code&gt; if an executable or &lt;code&gt;systemd&lt;/code&gt; if a daemon.&lt;/p&gt;
&lt;p&gt;Sandboxing Emacs and reducing its attack vector to an acceptable level
has been a very tedious and error-prone process for me, here's an
excerpt from my &lt;code&gt;emacs.service&lt;/code&gt; file constituting the unit's security
policy:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;# ~/.config/systemd/user/emacs.service

[Service]
# ...
SystemCallArchitectures=native
LockPersonality=yes
ProtectSystem=strict
ProtectClock=yes
ProtectHostname=yes
ProtectProc=invisible
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
PrivateUsers=yes
PrivateDevices=yes
PrivateTmp=yes
RestrictNamespaces=yes
RestrictSUIDSGID=yes
NoNewPrivileges=yes
CapabilityBoundingSet=
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pairing this with a &lt;code&gt;bwrap&lt;/code&gt;-sandboxed &lt;code&gt;qutebrowser&lt;/code&gt; breaks the most
ubiquitious functionality across Emacs: &lt;em&gt;following links&lt;/em&gt;. When Emacs
attempts to follow a link, it's not directly executing the &lt;code&gt;qutebrowser&lt;/code&gt;
binary with the URI as an argument, instead it calls a script that is
silently shadowing it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Shadowing a program is achieved by creating a script with an identical
name as the original program, but storing it in a path preceeding that
of the original program.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Emacs can't spawn a &lt;code&gt;qutebrowser&lt;/code&gt; process because the unit's security
policy prohibits it from spawning a nested sandbox. So, what are we
supposed to do then?&lt;/p&gt;
&lt;p&gt;It's quite easy actually, the Freedesktop/Flatpak team have already
encountered this problem and worked out a thorough and
well-architectured solution known as
&lt;a href=&quot;https://flatpak.github.io/xdg-desktop-portal/&quot;&gt;xdg-desktop-portal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What we require is the &lt;code&gt;OpenURI&lt;/code&gt; method from the
&lt;a href=&quot;https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.OpenURI.html&quot;&gt;org.freedesktop.portal.OpenURI&lt;/a&gt;
interface which forwards a given URI to its associated application.
Sounds good, Emacs has &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_mono/dbus.html&quot;&gt;excellent D-Bus
support&lt;/a&gt;,
we first need a function that forwards the URI [1] to the portal:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(require 'dbus)
(defun browse-url-xdg-desktop-portal (url &amp;amp;rest args)
  &amp;quot;Open URI via a portal backend.&amp;quot;
  (dbus-call-method :session
            &amp;quot;org.freedesktop.portal.Desktop&amp;quot;
            &amp;quot;/org/freedesktop/portal/desktop&amp;quot;
            &amp;quot;org.freedesktop.portal.OpenURI&amp;quot;
            &amp;quot;OpenURI&amp;quot;
            &amp;quot;&amp;quot; url '(:array :signature &amp;quot;{sv}&amp;quot;)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And to then set the default browser function to it:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(setopt browse-url-browser-function #'browse-url-xdg-desktop-portal)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Opening links should now work seamlessly across Emacs.&lt;/p&gt;
</content></entry><entry><title>Circumventing Sourcehut's missing Org support</title><id>https://benalita.tn/posts/2023-06-13.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2023-06-13T00:00:00Z</updated><link href="https://benalita.tn/posts/2023-06-13.html" rel="alternate" /><content type="html">&lt;p&gt;Sourcehut currently has &lt;a href=&quot;https://todo.sr.ht/~sircmpwn/man.sr.ht/13&quot;&gt;no support&lt;/a&gt; for rendering Org
documents, mostly because there are no good parsers out there, but there is a
way around this.&lt;/p&gt;
&lt;p&gt;I looked around the internet and &lt;a href=&quot;https://git.sr.ht/~mplscorwin/org-git-hooks&quot;&gt;found a decent solution&lt;/a&gt;,
written by Corwin Brust, that utilizes a pre- and post-commit hook to convert
Org documents to their Markdown equivalent. I read through the source code and
realized it could be shortened to a simple pre-commit hook. Here's what I came
up with:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;#!/bin/sh

emacs --batch --load &amp;quot;$HOME&amp;quot;/.config/emacs/lisp/+publish.el
git add README.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You'll have to &lt;code&gt;chmod +x&lt;/code&gt; the above file so that git can execute the
script when the hook is triggered, the &lt;code&gt;+publish.el&lt;/code&gt; file could contain
something like:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(require 'ox-md)

(defvar +readme &amp;quot;README.org&amp;quot;
  &amp;quot;Filename of README file.&amp;quot;)

(when (file-exists-p +readme)
  (find-file +readme)
  (let ((org-export-with-toc nil))
    (org-md-export-to-markdown)))

(message &amp;quot;Published documentation&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next time you create a commit, &lt;code&gt;README.org&lt;/code&gt; will be published to its
Markdown equivalent and Sourcehut will finally pick it up and show it
alongside the summary view.&lt;/p&gt;
&lt;p&gt;Furthermore, you're not limited to just Markdown. If, for example,
you're writing a manual for an Emacs Lisp package, you can make it so
the document also gets exported to Texinfo.&lt;/p&gt;
&lt;p&gt;You can do this by modifying the above examples to something along these
lines:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;#!/bin/sh

emacs --batch --load &amp;quot;$HOME&amp;quot;/.config/emacs/lisp/+publish.el
git add README.md MANUAL.md MANUAL.texi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We've staged all the documents we wish to publish; let's update the
publishing script accordingly.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(require 'ox-md)
(require 'ox-texinfo)

(defvar +readme &amp;quot;README.org&amp;quot;
  &amp;quot;Filename of README file.&amp;quot;)

(defvar +manual &amp;quot;MANUAL.org&amp;quot;
  &amp;quot;Filename of MANUAL file.&amp;quot;)

(when (file-exists-p +manual)
  (find-file +manual)
  (org-texinfo-export-to-texinfo)
  (let ((org-export-with-toc nil))
    (org-md-export-to-markdown)))

(when (file-exists-p +readme)
  (find-file +readme)
  (let ((org-export-with-toc nil))
    (org-md-export-to-markdown)))

(message &amp;quot;Published documentation&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I hope this workaround is soon made obsolete by an improvement to the
state and support of the current Org parsers as it's a little annoying
having to keep two copies of everything, but for now, this is pretty
much all we've got.&lt;/p&gt;
</content></entry><entry><title>Delightful project.el features</title><id>https://benalita.tn/posts/2023-03-01.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2023-03-01T00:00:00Z</updated><link href="https://benalita.tn/posts/2023-03-01.html" rel="alternate" /><content type="html">&lt;h1&gt;Global ignore list&lt;/h1&gt;
&lt;p&gt;The computer science community has created so many languages, dialects,
frameworks, build systems and tools – all with their own assumptions,
nuances and gotchas – making the task of coming up with a decent
solution to project management tedious for the developer writing said
solution as well as the user who has to consider and remember all these
arbitrary conventions.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.gitignore&lt;/code&gt; solves this to some degree, though it's up to the language,
framework, etc. to bundle a sensible template so developers can focus on
the important stuff. Going out of your way to create this file for every
new project, which at times doesn't need to be source-controlled, is
just cumbersome.&lt;/p&gt;
&lt;p&gt;This is where &lt;code&gt;project-vc-ignores&lt;/code&gt; comes into play, it takes a list of
patterns and instructs the &lt;code&gt;project.el&lt;/code&gt; library to ignore them, for
example:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(setq project-vc-ignores '(&amp;quot;target/&amp;quot; &amp;quot;bin/&amp;quot; &amp;quot;obj/&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This ignores the &lt;code&gt;target/&lt;/code&gt; directory generated by &lt;code&gt;mvn&lt;/code&gt; and the &lt;code&gt;bin/&lt;/code&gt;
and &lt;code&gt;obj/&lt;/code&gt; directories of &lt;code&gt;dotnet&lt;/code&gt;. The trailing slash is important, it
denotes a directory (regardless of depth).&lt;/p&gt;
&lt;h1&gt;Root markers&lt;/h1&gt;
&lt;p&gt;Emacs 29 is said to be one of the most feature-packed releases to date,
and it certainly holds true for this library. This version introduces
the &lt;code&gt;project-vc-extra-root-markers&lt;/code&gt; variable that takes a list of files
or glob patterns signaling the root of a project, for example:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(setq project-vc-extra-root-markers '(&amp;quot;pom.xml&amp;quot; &amp;quot;*.csproj&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Directories that contain a &lt;code&gt;pom.xml&lt;/code&gt; file or files ending with a
&lt;code&gt;csproj&lt;/code&gt; suffix will now be considered as projects, without needing to
be source-controlled, and we'll still be able to use all the handy
features of &lt;code&gt;project.el&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If your project is made up of multiple subprojects and each one contains
the same root marker, you should refrain from using the above markers
and consider something more general, e.g. &lt;code&gt;.prj&lt;/code&gt; (and it can be an empty
file). If you don't do this, any actions you perform will be limited to
the subproject you're currently in.&lt;/p&gt;
&lt;h1&gt;Custom switch commands&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;project-switch-commands&lt;/code&gt; is a variable that determines the list of
options displayed to the user when switching to a project with &lt;code&gt;C-x p p&lt;/code&gt;, we can extend it as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(add-to-list 'project-switch-commands '(magit-project-status &amp;quot;Magit&amp;quot; ?m))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;C-x p p m&lt;/code&gt; should now take us to the &lt;code&gt;magit-status&lt;/code&gt; view of the project
we just visited, which it normally doesn't do. Additionally, it's very
easy to extend &lt;code&gt;project.el&lt;/code&gt; to &lt;a href=&quot;/posts/2022-08-08.html&quot;&gt;support a workflow involving a to-do
file at the root of the project directory&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Fine-tuned compilation&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;project-compile&lt;/code&gt; uses &lt;code&gt;compile-command&lt;/code&gt; internally, so if your build
system is complex then you might consider configuring it using directory
variables, for example:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;# .dir-locals.el
((nil . ((compile-command . &amp;quot;make --directory=doc/site&amp;quot;))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will tell &lt;code&gt;make&lt;/code&gt; to look for the &lt;code&gt;Makefile&lt;/code&gt; in the &lt;code&gt;doc/site&lt;/code&gt;
directory (relative to the project root).&lt;/p&gt;
&lt;p&gt;If you want to run a specific target, prefixing the &lt;code&gt;project-compile&lt;/code&gt;
keybinding with &lt;code&gt;C-u&lt;/code&gt; will write the value of &lt;code&gt;compile-command&lt;/code&gt; to the
minibuffer and prompt you to write something more specific.&lt;/p&gt;
&lt;p&gt;The manual suggests adding a trailing space, probably to minimize the
amount of keystrokes you have to type before finally performing your
build operation.&lt;/p&gt;
&lt;h1&gt;Carefully killing buffers&lt;/h1&gt;
&lt;p&gt;If you feel a little uneasy about &lt;em&gt;blindly&lt;/em&gt; killing every project buffer
without getting a chance to say goodbye then
&lt;code&gt;project-kill-buffers-display-buffer-list&lt;/code&gt;, introduced in Emacs 29, is
just the thing for you.&lt;/p&gt;
&lt;p&gt;It is however hardwired to use &lt;code&gt;buffer-menu&lt;/code&gt;, so attempting to alias the
functions that it calls internally – specifically
&lt;code&gt;list-buffers-no-select&lt;/code&gt; – to the much cooler &lt;code&gt;ibuffer&lt;/code&gt; will… break
everything.&lt;/p&gt;
&lt;p&gt;Finally, I highly recommend reading the &lt;a href=&quot;info:emacs#Projects&quot;&gt;project.el
manual&lt;/a&gt;, because the various features and tricks
I've just mentioned are merely a fraction of what this library is able
to do.&lt;/p&gt;
</content></entry><entry><title>Implementing per-project package management for Org websites</title><id>https://benalita.tn/posts/2023-02-07.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2023-02-07T00:00:00Z</updated><link href="https://benalita.tn/posts/2023-02-07.html" rel="alternate" /><content type="html">&lt;p&gt;Emacs is an insanely liberating hacking environment, many of the
intricate systems designed for it help me organize and automate the
different facets of my life. A key part of the ecosystem is the
collection of Org Mode libraries which cover many things from &lt;a href=&quot;https://orgmode.org/manual/Citations.html&quot;&gt;exporting
documents&lt;/a&gt; and helping me &lt;a href=&quot;https://orgmode.org/manual/Tracking-your-habits.html&quot;&gt;keep track of habits&lt;/a&gt; to an
&lt;a href=&quot;info:org#Citations&quot;&gt;intuitive citation system&lt;/a&gt; that can be combined
with other integral tools, like the magnificent &lt;a href=&quot;https://github.com/andras-simonyi/citeproc-el&quot;&gt;citeproc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When I initially started using Emacs, it was to distract myself from my
old Vim habits and to learn something new. I was comfortable with my
tools, my ways and ideologies, but it was a
&lt;a href=&quot;https://youtu.be/SzA2YODtgK4&quot;&gt;couple&lt;/a&gt;
&lt;a href=&quot;https://youtu.be/KdcXu_RdKI0&quot;&gt;of&lt;/a&gt;
&lt;a href=&quot;https://youtu.be/JWD1Fpdd4Pc&quot;&gt;presentations&lt;/a&gt; that helped me realize the
vast difference between how I go about accomplishing a task and how
others are doing it.&lt;/p&gt;
&lt;p&gt;I'm currently leveraging &lt;em&gt;ox-publish&lt;/em&gt;, an immensely extensible and
highly documented facility of Org Mode, to build and architecture this
website, a website whose first commit happened around seven months ago.
I've added lots of tiny features since then: preference-based
colorschemes, syntax highlighting, citations, and a &lt;a href=&quot;https://git.sr.ht/~grtcdr/emacs.d/tree/main/item/module/blog.el&quot;&gt;tiny
module&lt;/a&gt; that helps me navigate my blog post directory a lot
more efficiently, to name a few.&lt;/p&gt;
&lt;p&gt;This has also been my first attempt at abstracting the codebase of a
website so that it can span multiple sub-projects, like
&lt;a href=&quot;https://liaison.grtcdr.tn&quot;&gt;liaison&lt;/a&gt; and
&lt;a href=&quot;https://darkman.grtcdr.tn&quot;&gt;darkman.el&lt;/a&gt;, both of which are independent
projects whose source code exists outside of this website's source tree.&lt;/p&gt;
&lt;p&gt;One major pain point to my current system was dependency/packagement
management, an area which can make or break a programming language.
&lt;a href=&quot;https://lists.gnu.org/archive/html/emacs-devel/2022-11/msg01774.html&quot;&gt;Emacs
29&lt;/a&gt;
thankfully added a new &lt;code&gt;--init-directory&lt;/code&gt; flag which we can use to
specify a custom &lt;code&gt;user-emacs-directory&lt;/code&gt;, meaning the packages we install
from say, a publishing script, will not interfere with the user's
general environment.&lt;/p&gt;
&lt;p&gt;To give you an example, we can consider &lt;em&gt;citeproc&lt;/em&gt; a dependency of this
project, the way we'd go about handling this dependency follows this
general ruleset:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Configure the project to use a separate initialization directory&lt;/li&gt;
&lt;li&gt;Install the dependency at the beginning of the publishing script&lt;/li&gt;
&lt;li&gt;Require the library like any other&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To address the first point, we might consider using a Makefile which
will help us streamline the publishing process.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;build:
    emacs --quick --init-directory=.emacs.d --script publish.el --funcall org-publish-all
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the &lt;code&gt;build&lt;/code&gt; recipe is invoked, the emacs batch processor will
create a new &lt;code&gt;.emacs.d&lt;/code&gt; directory adjacent to the &lt;code&gt;Makefile&lt;/code&gt; and use
that to store the source code of the packages we'll install later on.
We're also loading a file named &lt;code&gt;publish.el&lt;/code&gt; whose purpose is to handle
the publishing aspects of the project, this interacts with &lt;em&gt;ox-publish&lt;/em&gt;
to configure how the project should turn out when it is exported via
&lt;code&gt;org-publish-all&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Since the packages we'd like to use aren't not available by default,
we'll have to go out and fetch them like we would any other third-party
package. This involves some preparation which we can easily abstract
into two main functions: the first takes care of initializing the
package archives while the second installs the packages provided in a
list.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(require 'package)

(add-to-list 'package-archives '(&amp;quot;melpa&amp;quot; . &amp;quot;https://melpa.org/packages/&amp;quot;) t)

(defun op-package--initialize ()
  &amp;quot;Initialize the package manager and its archives.&amp;quot;
  (package-initialize)
  (unless package-archive-contents
    (package-refresh-contents)))

(defun op-package-install (packages)
  &amp;quot;Install the list of PACKAGES.&amp;quot;
  (op-package--initialize)
  (dolist (pkg packages)
    (unless (package-installed-p pkg)
      (package-install pkg))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's put our functions to use, we'll install &lt;em&gt;citeproc&lt;/em&gt; – and
&lt;em&gt;htmlize&lt;/em&gt;, because why not?&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(op-package-install '(citeproc htmlize))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We'll jump a couple lines down, and require the two libraries, actually
we won't require &lt;em&gt;htmlize&lt;/em&gt; as it's sort of an exception, that's because
&lt;em&gt;ox-publish&lt;/em&gt; will require it when it needs it.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(require 'citeproc)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This next part, which you may or may not care about, configures &lt;code&gt;oc&lt;/code&gt; to
use &lt;code&gt;citeproc&lt;/code&gt; as a citation processor for the &lt;code&gt;csl&lt;/code&gt; backend and
specifically the
&lt;a href=&quot;https://github.com/citation-style-language/styles/blob/master/ieee.csl&quot;&gt;IEEE&lt;/a&gt;
citation style.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(require 'oc)
(require 'oc-csl)

(setq org-cite-global-bibliography (list (expand-file-name &amp;quot;files/refs.bib&amp;quot;))
      org-cite-csl-styles-dir (expand-file-name &amp;quot;files/csl/styles&amp;quot;)
      org-cite-csl-locales-dir (expand-file-name &amp;quot;files/csl/locales&amp;quot;)
      org-cite-export-processors
      '((html . (csl &amp;quot;ieee.csl&amp;quot;))
    (latex . biblatex)
    (t . simple)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's pretty cool and all, but we should get back to the build process,
it is after all what ties everything together. Let's go take that
&lt;code&gt;build&lt;/code&gt; target we just wrote for a spin and see what it generates.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;Importing package-keyring.gpg...
Contacting host: melpa.org:443
Package refresh done
Contacting host: elpa.gnu.org:443
Package refresh done
Contacting host: elpa.nongnu.org:443
Package refresh done
...
Checking /home/grtcdr/projects/grtcdr.tn/.emacs.d/elpa/citeproc-20230125.1818...
Done (Total of 26 files compiled, 2 skipped)
Package ‘citeproc’ installed.
...
Checking /home/grtcdr/projects/grtcdr.tn/.emacs.d/elpa/htmlize-20210825.2150...
Done (Total of 1 file compiled, 2 skipped)
Package ‘htmlize’ installed.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The packages we require should have been installed and placed, along
with their dependencies, in their new separate environment. We can
verify this by inspecting the contents of the &lt;code&gt;.emacs.d&lt;/code&gt; directory
relative to the root of our project – let's do that:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;.emacs.d
└── elpa
    ├── citeproc-20230125.1818
    ├── dash-20221013.836
    ├── f-20230116.1032
    ├── htmlize-20210825.2150
    ├── parsebib-20221007.1402
    ├── s-20220902.1511
    └── string-inflection-20220910.1306
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The most crucial procedure in the build process is that of the
&lt;code&gt;org-publish-all&lt;/code&gt; function, which thanks to our neat setup, is now able
to build the project with all of the libraries we've added along the
way.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;Publishing file /home/grtcdr/projects/grtcdr.tn/src/now.org using ‘org-html-publish-to-html’
Publishing file /home/grtcdr/projects/grtcdr.tn/src/contact.org using ‘org-html-publish-to-html’
Publishing file /home/grtcdr/projects/grtcdr.tn/src/index.org using ‘org-html-publish-to-html’
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, what if a dependency of ours isn't available in any package
archives? How do we tackle this problem efficiently? I think
&lt;code&gt;package-vc&lt;/code&gt;, a library introduced in Emacs 29, is the answer.&lt;/p&gt;
&lt;p&gt;We can extend the &lt;code&gt;op-package-install&lt;/code&gt; function we previously added with
the capacity to download packages from a repository. First, import the
library somewhere near the top of the publishing script:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(require 'package-vc)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Normally, &lt;code&gt;package-vc-install&lt;/code&gt; would take as its first parameter a URL
to the repository we wish to download, but that's just plain ugly.
Instead, we'll introduce an elegant abstraction that will receive a tiny
bit of information identifying the repository and then translate that to
a functional URL.&lt;/p&gt;
&lt;p&gt;We'll start by defining our version control providers, e.g. GitHub,
SourceHut, etc. and then create a function that can construct the URL
bearing in mind the nuances between the different providers.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(defvar op-package--vc-providers
  '(:github &amp;quot;https://github.com&amp;quot; :sourcehut &amp;quot;https://git.sr.ht&amp;quot;)
  &amp;quot;Property list of version control providers and their associated domains.&amp;quot;)

(defun op-package--vc-repo (provider slug)
  &amp;quot;Construct the base URL of a repository from SLUG depending on the PROVIDER.&amp;quot;
  (let ((domain (plist-get op-package--vc-providers provider)))
    (cond ((eq provider :sourcehut) (format &amp;quot;%s/~%s&amp;quot; domain slug))
      (t (format &amp;quot;%s/%s&amp;quot; domain slug)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Although SourceHut prefixes usernames with a tilde, we managed to
offload that formatting task to the &lt;code&gt;op-package--vc-repo&lt;/code&gt; function, our
interactions with &lt;code&gt;op-package-install&lt;/code&gt; can therefore remain consistent.&lt;/p&gt;
&lt;p&gt;Additionally, it would be beneficial to have &lt;code&gt;op-package-install&lt;/code&gt; be our
sole entrypoint to installing packages, wherever they may be. It does
however need to undergo a tiny adjustment for that to be possible.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(defun op-package-install (packages)
  &amp;quot;Install the list of PACKAGES.&amp;quot;
  (op-package--initialize)
  (dolist (pkg packages)
    (if (plistp pkg)
    (let ((provider (car pkg))
          (slug (cadr pkg)))
      (when (plist-member op-package--vc-providers provider)
        (let* ((base (op-package--vc-repo provider slug))
           (package (intern (file-name-base slug))))
          (unless (package-installed-p package)
        (package-vc-install base :last-release)))))
      (unless (package-installed-p pkg)
    (package-install pkg)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's a pretty big transformation, but the function can now take a list
such as this one &lt;code&gt;'(citeproc htmlize (:github &amp;quot;grtcdr/liaison&amp;quot;))&lt;/code&gt;,
installing &lt;em&gt;citeproc&lt;/em&gt; and &lt;em&gt;htmlize&lt;/em&gt; from the usual package archives and
&lt;em&gt;liaison&lt;/em&gt; from the repository in which it resides.&lt;/p&gt;
&lt;p&gt;I'm currently using &lt;a href=&quot;https://github.com/grtcdr/grtcdr.github.io&quot;&gt;this
setup&lt;/a&gt; to try and deliver a
great reading experience for you. These tools have empowered me to
create an environment that is unique to me, an environment whose
elements are evolving alongside my progression as a writer and
developer, and an environment whose components can be easily swapped
with one another. It's a place that provides me with an opportunity for
continuous research, development and improvement. If you're considering
using &lt;em&gt;ox-publish&lt;/em&gt; as a foundation for your next project, now's the
time.&lt;/p&gt;
&lt;p&gt;I'd like to thank Sacha Chua for including this publication in her
&lt;a href=&quot;https://sachachua.com/blog/2023/02/2023-02-13-emacs-news/&quot;&gt;&amp;quot;Emacs News&amp;quot; posting of February 13,
2023&lt;/a&gt;. I'm
honored to have been included in her weekly digest and grateful to be a
part of this lively community.&lt;/p&gt;
</content></entry><entry><title>Emacs as a .NET development environment</title><id>https://benalita.tn/posts/2023-01-24.html</id><author><name>Taha Aziz Ben Ali</name><email>hello@benalita.tn</email></author><updated>2023-01-24T00:00:00Z</updated><link href="https://benalita.tn/posts/2023-01-24.html" rel="alternate" /><content type="html">&lt;p&gt;&lt;a href=&quot;https://urbigenous.net/library/alicebob.html&quot;&gt;Bob&lt;/a&gt; was tempted to use
an integrated development environment (IDE) to work on his .NET project,
even though he’s heavily invested in Emacs. Fortunately, Alice knows a
thing or two about .NET’s ecosystem and she brought up the idea of
building one’s own environment, proposing that he combine the following
tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/joaotavora/eglot/&quot;&gt;Eglot&lt;/a&gt; – &lt;em&gt;a &lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot;&gt;Language Server
Protocol&lt;/a&gt; (LSP)
client&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/razzmatazz/csharp-language-server&quot;&gt;csharp-ls&lt;/a&gt; – &lt;em&gt;a
server implementation of LSP&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alice said to install[1] the .NET SDK to start off:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;pacman -S dotnet-sdk
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;She told Bob to run &lt;code&gt;dotnet --info&lt;/code&gt; in the command-line to verify that
the installation was successful.&lt;/p&gt;
&lt;p&gt;Alice then insisted on adding the &lt;a href=&quot;https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools&quot;&gt;.NET
tools&lt;/a&gt;
directory onto the &lt;code&gt;PATH&lt;/code&gt; environment variable, so that when Bob finally
installs &lt;em&gt;csharp-ls&lt;/em&gt;, the binary will be available from anywhere on his
system.&lt;/p&gt;
&lt;p&gt;Since Bob is using &lt;em&gt;zsh&lt;/em&gt;, he decided to put the following snippet in his
&lt;code&gt;.zshenv&lt;/code&gt;, a file that is sourced every time the shell is instantiated.&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;PATH=&amp;quot;$HOME/.dotnet/tools:$PATH&amp;quot;
export PATH
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alice, knowing how unnecessarily complicated it can be to install
&lt;em&gt;omnisharp&lt;/em&gt;, recommended &lt;em&gt;csharp-ls&lt;/em&gt; instead which can be installed like
so:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;dotnet tool install --global csharp-ls
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This time, Bob was told to run &lt;code&gt;csharp-ls --version&lt;/code&gt; in the command-line
to verify that the tool was properly installed.&lt;/p&gt;
&lt;p&gt;Bob’s almost there, he just needs to install and configure Eglot so that
Emacs can learn to communicate the same language as any LSP server.
Alice told him to type &lt;code&gt;M-x package-install RET eglot RET&lt;/code&gt; and give the
package a second to install. Alice proceeded to explain that Eglot
internally consults the &lt;code&gt;eglot-server-programs&lt;/code&gt; to check what LSP server
it should use for a specific major mode.&lt;/p&gt;
&lt;p&gt;Because languages don’t necessarily have a single LSP server
implementation, meaning Eglot may not directly recognize every single
one, she told Bob to add &lt;em&gt;csharp-ls&lt;/em&gt; to that list like so:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(add-to-list 'eglot-server-programs
         '(csharp-mode . (&amp;quot;csharp-ls&amp;quot;)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next snippet instructs Eglot to automatically start in C# buffers:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(add-hook 'csharp-mode-hook 'eglot-ensure)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These functions may be combined and expressed as such:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(with-eval-after-load 'eglot
  (add-to-list 'eglot-server-programs
         '(csharp-mode . (&amp;quot;csharp-ls&amp;quot;)))
  (add-hook 'csharp-mode-hook 'eglot-ensure))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that roughly translates to this &lt;code&gt;use-package&lt;/code&gt; form:&lt;/p&gt;
&lt;pre&gt;&lt;code infostring=&quot;&quot;&gt;(use-package eglot
  :commands (eglot eglot-ensure)
  :hook ((csharp-mode . eglot-ensure))
  :config
  (add-to-list 'eglot-server-programs
         '(csharp-mode . (&amp;quot;csharp-ls&amp;quot;))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Bob’s very happy with the result. He’s capable of doing all the smart
things a modern programming environment can do from the comfort of his
favorite text editor.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/images/2023-01-24--dotnet.png&quot; alt=&quot;Emacs .NET development environment&quot; /&gt;&lt;/p&gt;
</content></entry></feed>