# rss_item

guid: https://based.cooking/yibin-burning-noodles.html
title: Yibin Burning Noodles
url: https://based.cooking/yibin-burning-noodles.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Yibin Burning Noodles</h1>

<p>This is a dry noodle dish from the town of Yibin in Sichuan, China.</p>

<h2>Ingredients</h2>

<h3>Yibin Chili Oil</h3>

<ul>
<li>Sichuan ground chilies, 1/3 cup</li>
<li>Roasted rapeseed oil (caizi you) or Chinese peanut oil, 2/3 cup</li>
<li>Peeled and smashed ginger, 2 inches</li>
<li>Cassia bark (or cinnamon stick), 2 inches</li>
<li>Star anise, 2</li>
<li>Chinese black cardamom (optional), 1</li>
<li>Sichuan peppercorn, 1 tsp</li>
<li>Roughly chopped walnut pieces, 2 tbsp</li>
<li>High-quality melted pork lard, 1/3 cup</li>
</ul>


<h3>Noodles</h3>

<ul>
<li>Fresh alkaline noodles, 150g</li>
<li><strong>Yibin Chili Oil</strong>, 2 tbsp</li>
<li>Light soy sauce, 1 tbsp</li>
<li>White sesame oil, 1 tbsp</li>
<li>Toasted yacai, 2 tbsp</li>
<li>Mixed toasted crushed peanuts/sesame, 2 tbsp</li>
<li>Sliced scallion greens, 2 tbsp</li>
<li>MSG, &frac14; tbsp</li>
</ul>


<h2>Directions</h2>

<h3>Yibin Chili Oil</h3>

<ol>
<li>Add ground chilies to a heat-proof jar or bowl.</li>
<li>Heat rapeseed oil (or Chinese peanut oil) over medium heat until lightly smoking at approximately 230°C for 2 minutes.</li>
<li>Turn off heat and let oil cool down to about 150°C.</li>
<li>Turn flame back to medium and add ginger, cassia bark, star anise, black cardamom, Sichuan peppercorn and chopped walnut pieces.</li>
<li>Simmer for 10 minutes.</li>
<li>Ensure the oil is approximately 150°C</li>
<li>Pour oil through a strainer onto the ground chilies.</li>
<li>Stir thoroughly.</li>
<li>Add the melted pork lard.</li>
<li>Stir thoroughly.</li>
</ol>


<h3>Noodles</h3>

<ol>
<li>Boil the noodles for approximately 1 minute (slightly past al dente).</li>
<li>Strain the noodles thoroughly.</li>
<li>Add all the sauces and oils from the &ldquo;Noodles&rdquo; ingredients list.</li>
<li>Top with the remaining ingredients.</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>ThePademelon</li>
</ul>


<p>;tags: noodles asian chinese spicy</p>


guid: https://based.cooking/diannes-southwest-salad.html
title: Dianne's Southwestern Cornbread Salad
url: https://based.cooking/diannes-southwest-salad.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Dianne&rsquo;s Southwestern Cornbread Salad</h1>

<p><img src="pix/diannes-cornbread-salad.webp" alt="Dianne's Southwestern Cornbread Salad" /></p>

<p>Dianne&rsquo;s Southwestern Cornbread Salad is as colorful as it is delicious.</p>

<ul>
<li>⏲️ Prep time: 30 min</li>
<li>🍳 Cook time: 15 min</li>
<li>🍽️ Servings: 10-12</li>
<li>🥶 Chill: 2 hrs</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>1 (6-ounce) package Mexican cornbread mix</li>
<li>1 (1-ounce) envelope buttermilk Ranch salad dressing mix</li>
<li>1 small head romaine lettuce, shredded</li>
<li>2 large tomatoes, chopped</li>
<li>1 (15-ounce) can black beans, rinsed and drained</li>
<li>1 (8-ounce) package shredded Mexican four-cheese blend</li>
<li>6 bacon slices, cooked and crumbled</li>
<li>5 green onions, chopped</li>
</ul>


<h2>Directions</h2>

<ol>
<li><strong>Prepare</strong> cornbread according to package directions, cool, and crumble. Then set aside.</li>
<li><strong>Prepare</strong> salad dressing according to package directions.</li>
<li><strong>Layer</strong> a large bowl with half each of cornbread, lettuce, and the next 6 ingredients: spoon half of dressing evenly over top. Repeat layers with remaining ingredients and dressing. Cover and chill at least 2 hours.</li>
</ol>


<p>;tags: salad mexican southwest</p>


guid: https://based.cooking/tanzania-tea-with-milk.html
title: Tanzanian Tea w/ Milk
url: https://based.cooking/tanzania-tea-with-milk.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Tanzanian Tea w/ Milk</h1>

<p><img src="pix/tanzania-tea-with-milk-01.webp" alt="tea-n-milk" /></p>

<p>This is a very traditional simple beverage from Tanzania, a country in East Africa. While I stayed there in Mwanza and Dar es Salaam, they
would always have this option for breakfast (or in general).</p>

<ul>
<li>⏲️ Prep time: 5-10 min</li>
<li>🍳 Cook time: 3-8 min</li>
<li>🍽️ Servings: 1</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>Black Ceylon Tea (Preferably, you want a dark, herbal flavor from your tea. I have some from Dar es Salaam,
but when I tried researching, I couldn&rsquo;t find out what kind of tea it is. No, they didn&rsquo;t list the ingredients on
the box lol)</li>
<li>Milk/Sweet Cream</li>
<li>Sweetener (Sugar, Syrup, Monk Fruit extract, etc.) (optional, but recommended)</li>
</ul>


<h2>Directions</h2>

<p><img src="pix/tanzania-tea-with-milk-02.webp" alt="tea" /></p>

<ol>
<li>Bring some hot water to boil and seep the tea. Depending on how strong you like it, you can do this for up to 10 min at most.
Be warned; typically black teas are very strong.</li>
<li>When done seeping, add in the milk (or cream).</li>
<li>Sweeten to taste. Remember you can always add more if there isn&rsquo;t enough.</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>extramundane (Ex) - <a href="https://extramundane.xyz">website</a>, <a href="https://extramundane.xyz/donate.html">donate</a></li>
</ul>


<p>;tags: drink milk quick</p>


guid: https://based.cooking/yorkshire-puddings.html
title: Yorkshire Puddings
url: https://based.cooking/yorkshire-puddings.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Yorkshire Puddings</h1>

<p><img src="pix/yorkshire-puddings.webp" alt="Yorkshire Puddings" /></p>

<p>Basically the northern England equivalent of the french pancake ( a means to make use of extra flour when you didn&rsquo;t have enough for bread ). They go well with Sunday Roasts.
Puddings may be preserved in freezer for up to a month.</p>

<ul>
<li>⏲️ Prep time: 5 min</li>
<li>🍳 Cook time: 20 min</li>
<li>🍽️ Servings: 2</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>140g flour</li>
<li>4 eggs</li>
<li>200ml milk</li>
<li>sunflower oil</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Preheat oven to 230°C / gas mark 8.</li>
<li>Drizzle oil into 24 &lsquo;cupcake tin&rsquo; slots. (The pans you make cupcakes in). Heat in oven.</li>
<li>Pour flour into bowl.</li>
<li>Whisk eggs, add to bowl.</li>
<li>Add milk to bowl in small amounts, beating/whisking after each addition. Until there are no lumps in the batter. You may season with salt &amp; pepper.</li>
<li>Tip batter into a jug so that you may pour into the cupcake pan slots evenly and carefully.</li>
<li>Bake undisturbed ( opening oven will impede the rising ), until the puddings have puffed up and browned.</li>
</ol>


<p>Originally published at https://www.bbcgoodfood.com/recipes/best-yorkshire-puddings</p>

<h2>Contribution</h2>

<ul>
<li>siggines - <a href="http://jacobsiggins.co.uk">website</a></li>
</ul>


<p>;tags: english side</p>


guid: https://based.cooking/honey-garlic-chicken.html
title: Honey Garlic Chicken with Broccoli and Brown Rice
url: https://based.cooking/honey-garlic-chicken.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Honey Garlic Chicken with Broccoli and Brown Rice</h1>

<p>Very easy, high protein.</p>

<ul>
<li>Servings: 2</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>&frac12; cup ( 100g ) brown rice</li>
<li>&frac12; cup ( 70g ) frozen peas</li>
<li>1 head broccoli (you can use really any amount of broccoli)</li>
<li>2 chicken breasts</li>
<li>1 tbsp honey</li>
<li>1 tbsp low-sodium soy sauce</li>
<li>1 tbsp minced garlic</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Cook rice in a pot. Instructions are on the bag it comes in.</li>
<li>While rice is cooking, cut chicken breasts into cube. Season with olive oil, black pepper, and
paprika. Cut broccoli into pieces and place into steamer basket over pot &frac12; filled with water, do
not start it yet.</li>
<li>Put chicken cubes into a hot pan and cook for ~3 minutes. After 3 minutes add honey, soy sauce,
and garlic. Cook for another 5 minutes. Begin boiling broccoli water.</li>
<li>Add frozen peas to rice and stir, they will heat up quickly.</li>
<li>Add rice and peas to chicken and stir.</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>Connor McLean</li>
</ul>


<p>;tags: chicken broccoli rice quick</p>


guid: https://based.cooking/chicken-tenders-airfried.html
title: Chicken Tenders Airfried
url: https://based.cooking/chicken-tenders-airfried.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Chicken Tenders Airfried</h1>

<ul>
<li>⏲️ Prep time: 5 min</li>
<li>🍳 Cook time: 20 min</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>Raw chicken strips</li>
<li>Flour</li>
<li>Egg wash</li>
<li>Bread crumbs</li>
<li>Vegetable oil</li>
<li>Seasoning:salt and pepper with cayenne or paprika (optional)</li>
</ul>


<h2>Directions</h2>

<ol>
<li>In a plate, mix a little over a table spoon of spices into your flour.</li>
<li>Dip the chicken into the flour one strip at a time coating the entire surface.</li>
<li>Dip the floured chicken into the eggwash.</li>
<li>Press the chicken into the breadcrumbs trying to pick up as much as possible.</li>
<li>Repeat until all strips have been floured egged and breaded.</li>
<li>Coat both sides of the tenders with a light amount of vegetable oil.</li>
<li>Place the tenders into your airfryer, do not layer them on top of each other.</li>
<li>Set your airfryer to chicken mode and cook for 20 minutes at 360 degrees fahrenheit.</li>
<li>Serve with honey mustard for maximum effect.</li>
</ol>


<h2>Contribution</h2>

<p>Original recipe by Mental Outlaw on Youtube and Odysee.
Translated from video to text by Yoshiguy35.
Any changes I made were to abide by rule #4.
<a href="https://www.youtube.com/watch?v=PymSsu_LufA">original video</a></p>

<ul>
<li>Mental Outlaw - <a href="https://www.youtube.com/user/MentalOutlawStudios">youtube</a>, xmr: <code>45F2bNHVcRzXVBsvZ5giyvKGAgm6LFhMsjUUVPTEtdgJJ5SNyxzSNUmFSBR5qCCWLpjiUjYMkmZoX9b3cChNjvxR7kvh436</code></li>
<li>Yoshiguy35 - <a href="https://www.youtube.com/channel/UCWX13rdnpFNeMh7gOhexnlg">youtube</a>, <a href="https://www.yoshiguy35.com/">website</a></li>
</ul>


<p>;tags: chicken fry</p>


guid: https://based.cooking/chorizo-and-chickpea-soup.html
title: Chorizo & Chickpea Soup
url: https://based.cooking/chorizo-and-chickpea-soup.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Chorizo &amp; Chickpea Soup</h1>

<p>Recommend serving with corn bread.</p>

<ul>
<li>🍳 Cook time: 10-15 min</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>Chorizo Sausage(s)</li>
<li>2 Garlic cloves</li>
<li>Ginger</li>
<li>Paprika, 2 Tsp</li>
<li>Cumin, Parsley</li>
<li>Juice from whole Lemon</li>
<li>Chickpeas, 400g ( drained )</li>
<li>Butter and sunflower oil, for frying</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Fry the sliced Chorizo in butter, along-with diced Ginger and Garlic. Add oil after a couple mins.</li>
<li>Pour in Lemon-juice, Chickpeas, and Cumin &amp; Paprika. Then 100ml of water.</li>
<li>Allow to boil for 5 or so min. Add Parsley and then salt to taste.</li>
</ol>


<h2>Contribution</h2>

<p>Recipe modified from original published at: ( https://www.bbcgoodfood.com/recipes/chorizo-chickpea-stew )</p>

<ul>
<li>Siggines - <a href="http://jacobsiggins.co.uk">website</a></li>
</ul>


<p>;tags: pork soup spanish quick</p>


guid: https://based.cooking/curry-sauce.html
title: Curry sauce
url: https://based.cooking/curry-sauce.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Curry sauce</h1>

<p>I like to make double this amount and freeze the rest.</p>

<ul>
<li>⏲️ Prep time: 20 min</li>
<li>🍳 Cook time: 60 min</li>
<li>🍽️ Servings: 4</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>25g butter</li>
<li>1 onion, sliced</li>
<li>2 garlic cloves, sliced</li>
<li>Thumb of ginger, sliced</li>
<li>2 tbsp curry powder</li>
<li>&frac12; tsp turmeric</li>
<li>1 tbsp malt vinegar</li>
<li>1 star anise</li>
<li>250ml chicken stock</li>
<li>1 tbsp cornflour</li>
<li>2 tbsp water</li>
<li>Lemon juice (optional)</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Melt the butter in a large saucepan over medium heat.</li>
<li>Add in the sliced onion, sliced garlic, and ginger.</li>
<li>Fry for 15 min, until the onion soft.</li>
<li>Add the curry powder, turmeric, vinegar, and star anise.</li>
<li>Fry for 1 minute.</li>
<li>Pour in the stock.</li>
<li>Simmer for 30 minutes while stirring.</li>
<li>Remove the star anise.</li>
<li>Add the cornflour and water.</li>
<li>Simmer for 5 minutes while stirring.</li>
<li>Blend the sauce. Add in some lemon juice if you want.</li>
</ol>


<h2>Contribution</h2>

<p>Fiddelate</p>

<p>;tags: sauce indian curry</p>


guid: https://based.cooking/coleslaw.html
title: Coleslaw
url: https://based.cooking/coleslaw.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Coleslaw</h1>

<p>This is a coleslaw recipe that I got from a chili restaurant in my neighborhood that closed down a few years ago. This recipe makes more dressing than needed for the coleslaw, so you can save it or use it as a vegetable dip.</p>

<ul>
<li>⏲️ Prep time: 25 min</li>
<li>🥶 Fridge time: 1 hr</li>
<li>🍽️ Servings: 8 - 10</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>&frac34; cup mayonnaise</li>
<li>&frac12; cup buttermilk</li>
<li>3 tbsp lemon juice</li>
<li>3 tbsp apple cider vinegar</li>
<li>4 tbsp distilled vinegar</li>
<li>1/3 cup canola oil</li>
<li>&frac14; cup granulated sugar</li>
<li>1 &frac12; tsp kosher salt</li>
<li>1 tsp ground black pepper</li>
<li>1 tsp celery seeds</li>
<li>&frac12; tsp onion powder</li>
<li>&frac14; tsp granulated garlic</li>
<li>&frac14; tsp mustard powder</li>
<li>One large head of green cabbage</li>
<li>One large carrot</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Finely shred, rinse, and drain the carrot</li>
<li>Finely shred the cabbage (use a food processor if possible)</li>
<li>Whisk together the mayonnaise, buttermilk, lemon juice, cider vinegar, distilled vinegar, canola oil, and sugar</li>
<li>Add the salt, pepper, celery seeds, onion powder, and granulated garlic, and combine well</li>
<li>Combine the shredded cabbage and carrot in a separate bowl</li>
<li>Slowly add the dressing until it lightly coats the vegetables, and toss well. Add more dressing until it tastes good</li>
<li>Refrigerate for at least an hour before serving</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>Declan Cash - <a href="https://declancash.com">website</a></li>
</ul>


<p>;tags: side cabbage southern salad</p>


guid: https://based.cooking/mushroom-stragonov.html
title: Mushroom Stroganov
url: https://based.cooking/mushroom-stragonov.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Mushroom Stroganov</h1>

<p>Prep time: 10 Minutes
Cook time: 20 Minutes
Servings: 2</p>

<h2>Ingredients</h2>

<ul>
<li>8 oz uncooked pasta (spaghetti or any other long noodle will work. Stroganov can also be served over rice.)</li>
<li>12 oz mushrooms (I reccommend shitake, but white, portabello, or maitake will also work.)</li>
<li>2 cloves of garlic, minced</li>
<li>1 small yellow onion, minced</li>
<li>2 Tbsp butter</li>
<li>1 Tbsp general purpose flour</li>
<li>1 Cup vegetable broth</li>
<li>1 Tsp dijon mustard</li>
<li>1 Tsp Smoked paprika</li>
<li>4 Tbsp creme fraiche (can be made by mixing equal parts heavy and sour cream)</li>
<li>2 Tbsp parsely</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Bring a large pot of salted water to a boil and cook pasta al dente</li>
<li>In a cup, combine flour, mustard, smoked paprika, salt and pepper. Add broth and whisk until no lumps remain.</li>
<li>While pasta is cooking, melt butter in a medium skillet and over medium heat.</li>
<li>When the butter is melted, add onions and cook until softened.</li>
<li>Add mushrooms and cook until all water evaporates and mushrooms are slightly browned, about 7 minutes.</li>
<li>Add garlic and cook for another 30 seconds.</li>
<li>Pour the flour and broth mixture into the mushrooms and cook until thickens, about 2 minutes.</li>
<li>Stir in Creme Fraiche.</li>
<li>Add the strained pasta to the mushroom sauce and stir to coat the pasta completely.</li>
<li>Serve immediately.</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>Aayla Semyonova - <a href="https://aayla.dev">website</a></li>
</ul>


<p>;tags: russian pasta mushrooms</p>


guid: https://based.cooking/ravioli.html
title: Ravioli
url: https://based.cooking/ravioli.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Ravioli</h1>

<p><img src="pix/ravioli-01.webp" alt="Ravioli" /></p>

<ul>
<li>⏲️ Prep time: 30 min</li>
<li>🍳Cook time: 2 min</li>
<li>🍽️ Servings: 4</li>
</ul>


<h2>Ingredients</h2>

<h3>Dough</h3>

<ul>
<li>4 eggs</li>
<li>400 g 00 flour</li>
<li>Drizzle of olive oil</li>
</ul>


<h3>Cheese Filling</h3>

<ul>
<li>1 lemon</li>
<li>50 g grated Pecorino Romano cheese</li>
<li>250 g ricotta</li>
<li>1 egg</li>
</ul>


<h3>Seafood Fillings</h3>

<ul>
<li>Chopped leftover lobster legs, lobster tail, or minced crab (optional)</li>
</ul>


<h2>Directions</h2>

<ol>
<li>The basic rule of thumb I use for pasta is 100g, 1 egg per person</li>
<li>For this recipe you can go two ways, the old school &ldquo;well&rdquo; method or a kitchen aid mixer (skip to step 7)</li>
<li>For the well method, pile the flour onto the counter and with your hand carve a hole or a well in the center</li>
<li>Crack the eggs into the center of the well, and drizzle a bit of olive oil into the center</li>
<li>With a fork, begin slowly breaking up, mixing, and incorporating the egg into the flour until there is no longer any loose egg that can escape the outer well border</li>
<li>At this point use your hands to bring the sandy mixture together and knead the dough for about 5-10 minutes or until the dough is smooth</li>
<li>For the stand mixer method just throw all the ingredients into the mixer with a dough hook and set it to level 4 for about 3-5 minutes and it will be done</li>
<li>You might need to scrape the sides down and maybe hand knead the dough a bit longer after it&rsquo;s done to make it into a nice smooth ball</li>
<li>Cover the dough with plastic wrap and let it rest in the fridge a bit so it&rsquo;s easier to roll out (15-30 mins)</li>
<li>While the dough is resting, make the filling by first mixing the  ricotta and egg into a bowl</li>
<li>Zest and juice a lemon peel into the bowl</li>
<li>Optionally add seafood ingredients at this point</li>
<li>Grate the Pecorino into the bowl, add salt and pepper to taste, and mix to distribute the ingredients evenly</li>
<li>Take out the dough and cut it into 4 pieces, keeping the ones not currently being worked on covered so they don&rsquo;t dry out</li>
<li>Roll the dough out with a pasta machine down to the point where you can just barely see your hand through it (setting 2-3 out of 7) or roll it out with a rolling pin into a long sheet, maybe like 16 x 8 inches or so</li>
<li>At this point you can either cut the sheet in half and make two sheets, a top and bottom, or one sheet, where you will fold the dough over and use the folded seam as one side of the ravioli
<img src="pix/ravioli-02.webp" alt="Lobster Ravioli" /></li>
<li>Using a teaspoon, evenly space out the ricotta filling onto the sheets, leaving a few inches on each side for the seams</li>
<li>As stated in step 16, either take the 2nd sheet and place it over top or fold over the dough and press down firmly, forcing out any air and making sure the two pieces of dough stick</li>
<li>You may need to brush some water onto the dough if it is too heavily floured and not sticking</li>
<li>Using a fancy pasta cutter, a knife, or even a pizza cutter, cut evenly between the seams of the raviolis to separate them</li>
<li>If you used a pasta cutter, you are now done, store the raviolis on a floured wax paper sheet or freeze them for later
<img src="pix/ravioli-03.webp" alt="Finished Ravioli" /></li>
<li>If you don&rsquo;t have a pasta cutter, use a fork to press down the dough around the edges of the cut raviolis to ensure they are firmly closed and no leaks or air bubbles are visible, or else they will explode when cooked</li>
<li>To cook, throw them in salted boiling water and they will let you know when they&rsquo;re done when they float to the top (1-2 minutes)</li>
<li>Serve the seafood version with a simple fresh red sauce and basil, or spice it up a bit and go with a base of red sauce with some added heavy cream, and a pinch of red pepper flakes to make a pink sauce for the seafood version
<img src="pix/ravioli-04.webp" alt="Served Ravioli" /></li>
</ol>


<h2>Contribution</h2>

<ul>
<li>mfed3 - xmr: <code>48eEMdYtCQaV5wY7wvmxK6jCxKkia9dgpNTMNT1do7RLWXCwWDgSKjN3kiZ6yHbAuAXWgDGN6imnGT9NPeHWD7zX9hSyHu2</code></li>
</ul>


<p>;tags: pasta italian</p>


guid: https://based.cooking/ragu-napoletano.html
title: Ragu Napoletano
url: https://based.cooking/ragu-napoletano.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Ragu Napoletano</h1>

<p>This recipe is known by Italian-Americans as &ldquo;Sunday Gravy&rdquo;, which originated from the Southern Italian dish Ragu Napoletano. This is my variation of my family&rsquo;s version which was passed down 3 generations to me.</p>

<p><img src="pix/ragu-napoletano-1.webp" alt="Ragu Napoletano" /></p>

<ul>
<li>⏲️ Prep time: 30-60 min</li>
<li>🍳Cook time: 4-5 hrs</li>
<li>🍽️ Servings: 10-12</li>
</ul>


<h2>Ingredients</h2>

<h3>Tomato Sauce</h3>

<ul>
<li>6-10 lbs San Marzano plum tomatoes (fresh or canned peeled)</li>
<li>Tomato paste (optional)</li>
</ul>


<h3>Aromatics and Herbs</h3>

<ul>
<li>8 cloves garlic</li>
<li>1.5 white onions</li>
<li>6-8 oz red wine</li>
<li>8 fresh basil leaves</li>
<li>Dry oregano</li>
<li>Red pepper</li>
</ul>


<h3>Meat</h3>

<ul>
<li>1-2 lb pork tenderloin</li>
<li>1-2 lb sweet and or spicy Italian sausage</li>
<li>1 lb cubed stewing beef (chuck, short rib, or oxtail)</li>
</ul>


<h3>Meatballs</h3>

<ul>
<li>1-2 lb total of ground beef chuck, veal, and pork</li>
<li>1 &frac12; cups grated Pecorino Romano cheese</li>
<li>1 &frac12; cups breadcrumbs (baked stale bread, oregano, salt and pepper pulsed in a food processor)</li>
<li>2-3 eggs</li>
<li>Splash of milk</li>
<li>Handfull of fresh parsley chopped</li>
<li>Sprig of fresh basil chopped</li>
<li>&frac12; onion minced</li>
<li>4-8 cloves garlic minced</li>
</ul>


<h2>Directions</h2>

<ol>
<li>If you already have tomato sauce skip to step 5</li>
<li>For fresh tomatoes, wash and cut out off the green stems of the tomatoes and cut them into a few chunks and lightly salt them over a collander or strainer so they release water and break down quicker</li>
<li>For canned tomatoes, use your hands to crush the peeled tomatoes (don&rsquo;t use a food processor)</li>
<li>In a large stock pot cook down the tomatoes for approximately 30 mins then use a food mill or strainer to remove the skins and seeds to yield tomato sauce (this can be done beforehand and frozen / canned for months)
<img src="pix/ragu-napoletano-2.webp" alt="Sauce" /></li>
<li>Mix all the ingredients in the Meatballs section by hand and form equal sized meatballs</li>
<li>Either bake the meatballs at 400°F until brown or fry them with the the other meats in step 7</li>
<li>Coat the bottom of a dutch oven or large stock pot with olive oil and  sear each meat one by one, removing from the pot once browned on the outside (do not cook the meat all the way through)</li>
<li>Sweat the onion and garlic, then deglaze the pan with the red wine</li>
<li>Fill the pot with the seared meat, tomato sauce, add the fresh basil, then season with dried oregano, red pepper, salt, pepper, and a pinch of sugar to taste
<img src="pix/ragu-napoletano-1.webp" alt="Meats" /></li>
<li>Cook on very low flame uncovered for 4-5 hours stirring making sure it doesn&rsquo;t burn</li>
<li>Serve over cooked dry pasta such as ziti, penne, rigatoni</li>
<li>Portion the sauce and meats and freeze in containers for up to 4-6 months</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>mfed3 - xmr: <code>48eEMdYtCQaV5wY7wvmxK6jCxKkia9dgpNTMNT1do7RLWXCwWDgSKjN3kiZ6yHbAuAXWgDGN6imnGT9NPeHWD7zX9hSyHu2</code></li>
</ul>


<p>;tags: tomato sauce italian pork veal</p>


guid: https://based.cooking/mapo-tofu.html
title: Mapo Tofu (麻婆豆腐)
url: https://based.cooking/mapo-tofu.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Mapo Tofu (麻婆豆腐)</h1>

<p><img src="pix/mapo-tofu-01.webp" alt="Mapo Tofu Over Rice" /></p>

<ul>
<li>⏲️ Prep time: 10 min</li>
<li>🍳Cook time: 15 min</li>
<li>🍽️ Servings: 4</li>
</ul>


<h2>Ingredients</h2>

<h3>Marinated Pork</h3>

<ul>
<li>450 g (1 lb) ground pork</li>
<li>1 tbsp soy sauce</li>
<li>1 tbsp Shaoxing cooking wine</li>
<li>1 tsp cornstarch</li>
<li>1 tsp white pepper powder</li>
</ul>


<h3>Braise</h3>

<ul>
<li>2 tbsp spicy doubanjiang (la doubanjiang)</li>
<li>1 tsp dou-chi</li>
<li>2-3 chopped scallions white and green separated)</li>
<li>2-4 minced garlic cloves</li>
<li>2 inch minced ginger (similar amount as garlic)</li>
<li>400 ml chicken broth or water</li>
<li>340 g (1 package) soft tofu cut into 1.5cm (&frac12; inch cubes)</li>
<li>1 tbsp Sichuan peppercorns crushed</li>
</ul>


<h2>Directions</h2>

<p><img src="pix/mapo-tofu-02.webp" alt="Mapo Tofu Simmering" />
1. Marinade the pork in shaoxing cooking wine, a splash of cooking oil, the soy sauce,
2. Add cooking oil to a wok and sear the ground pork until browned, chopping it up as it cooks
3. Add the doubanjiang and let it simmer for about a minute
4. Add the minced aromatics (ginger, garlic) scallion whites, and dou-chi and cook until fragrant
5. Add the stock and a splash of soy sauce, turn up the gas and bring to a boil
6. Add the tofu, lower the gas, and braise for around 15 mins
7. You&rsquo;ll know it&rsquo;s done when the tofu shows their trademark &ldquo;pockmarks&rdquo; and the seasoning sticks to them
8. Mix in the crushed sichuan peppercorns and green parts of the scallions right before serving
9. Serve over steamed rice</p>

<h2>Contribution</h2>

<ul>
<li>mfed3 - xmr: <code>48eEMdYtCQaV5wY7wvmxK6jCxKkia9dgpNTMNT1do7RLWXCwWDgSKjN3kiZ6yHbAuAXWgDGN6imnGT9NPeHWD7zX9hSyHu2</code></li>
</ul>


<p>;tags: chinese pork tofu</p>


guid: https://based.cooking/limoncello.html
title: Limoncello
url: https://based.cooking/limoncello.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Limoncello</h1>

<p><img src="pix/limoncello.webp" alt="Limoncello" /></p>

<ul>
<li>⏲️ Prep time: 10 min</li>
<li>🍳Wait time: 20 days</li>
<li>🍽️ Servings: 22</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>5-7 organic lemons (regular lemons are covered in wax)</li>
<li>300ml 95% ABV grain alcohol</li>
<li>700ml water</li>
<li>500ml sugar</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Pour the alcohol into a 1 liter mason jar</li>
<li>Peel the lemons avoiding the white pith (it will make your limoncello bitter) and submerse them in the alcohol</li>
<li>Cover the jar and let the lemons infuse the alcohol for 20 days</li>
<li>After the infusion is completed, create a simple syrup by boiling the water and dissolving the sugar in the water</li>
<li>Allow the water to cool completely, then strain the alcohol into the sugar water and stir</li>
<li>Bottle or put it back into the mason jar</li>
<li>Feel free to scale the recipe up or down, and adjust the sugar to the sweetness you like, but the ABV should remain somewhere around 28-30%</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>mfed3 - xmr: <code>48eEMdYtCQaV5wY7wvmxK6jCxKkia9dgpNTMNT1do7RLWXCwWDgSKjN3kiZ6yHbAuAXWgDGN6imnGT9NPeHWD7zX9hSyHu2</code></li>
</ul>


<p>;tags: alcohol lemons digestivo liquor</p>


guid: https://based.cooking/italian-mulled-wine.html
title: Italian Mulled Wine
url: https://based.cooking/italian-mulled-wine.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Italian Mulled Wine</h1>

<p><img src="pix/italian-mulled-wine.webp" alt="Italian Mulled Wine" /></p>

<ul>
<li>⏲️ Prep time: 5 min</li>
<li>🍳Cook time: 15 min</li>
<li>🍽️ Servings: 4</li>
</ul>


<h2>Ingredients</h2>

<h3>Crushed Ingredients</h3>

<ul>
<li>1 star anise</li>
<li>1 bay leaf</li>
<li>1 pinch rosemary</li>
<li>1 pinch peppercorn</li>
<li>1 pinch thyme</li>
<li>1 pinch red pepper</li>
<li>1 pinch fennel seeds</li>
<li>1 pinch cloves</li>
<li>1 pinch nutmeg</li>
</ul>


<h3>Non-Crushed Ingredients</h3>

<ul>
<li>1 bottle Italian red wine</li>
<li>1 orange</li>
<li>1 lemon</li>
<li>1 tbsp honey</li>
<li>1 tsp vanilla</li>
<li>1 stick cinnamon</li>
<li>4 figs (optional)</li>
<li>100 ml limoncello (optional)</li>
<li>50 ml sweet vermouth (optional)</li>
<li>50 ml bourbon, brandy, or cognac (optional)</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Pour the wine into a stock pot and turn the gas on medium high</li>
<li>Crush all the &ldquo;Crushed Ingredients&rdquo; in a mortar and pestle</li>
<li>Peel and juice the orange and lemon (toss the peels and juice into the wine but not the white pith)</li>
<li>When the wine is up to a simmer, immediately bring the gas down to low and pour in all the rest of the ingredients</li>
<li>Cook on low for at least 15 minutes to infuse the flavors</li>
<li>Keep the flame on low so the wine stays warm and continues to infuse, but doesn&rsquo;t bubble / burn off the alcohol</li>
<li>Feel free to double the recipe or scale any of these ingredients up or down to suite your taste</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>mfed3 - xmr: <code>48eEMdYtCQaV5wY7wvmxK6jCxKkia9dgpNTMNT1do7RLWXCwWDgSKjN3kiZ6yHbAuAXWgDGN6imnGT9NPeHWD7zX9hSyHu2</code></li>
</ul>


<p>;tags: alcohol wine liquor drink</p>


guid: https://based.cooking/chocolate-chip-cookies.html
title: Chocolate Chip Cookies
url: https://based.cooking/chocolate-chip-cookies.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Chocolate Chip Cookies</h1>

<p><img src="pix/chocolate-chip-cookies.webp" alt="Chocolate Chip Cookies" /></p>

<ul>
<li>⏲️ Prep time: 10 min</li>
<li>🍳Cook time: 10 min</li>
<li>🍽️ Servings: 4</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>230 g melted butter (2 sticks)</li>
<li>330 g bread flour</li>
<li>5 g salt</li>
<li>5 g baking soda</li>
<li>100-200 g white sugar</li>
<li>100-200 g brown sugar</li>
<li>1 egg</li>
<li>15 g milk</li>
<li>5 g vanilla</li>
<li>225 g 50-70% dark chocolate chips or semi-sweet milk chocolate chips</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Preheat oven to 375°F</li>
<li>Mix the flour, baking soda, and salt in a bowl</li>
<li>Using a mixer or whisk, beat the butter, sugar, eggs, and vanilla in a separate bowl for a few mins</li>
<li>Combine and stir in the dry ingredients, then the chocolate chips</li>
<li>Use an ice cream scooper or spoon to make uniform balls of cookie dough to the size you like and evenly space them out on a parchment paper lined baking sheet (you may need more than one sheet depending on the size of the cookies)</li>
<li>Bake in the oven one baking sheet at a time for around 8-10 minutes, taking them out when they start to brown</li>
<li>Cool for a few minutes then put them on a cooling rack</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>mfed3 - xmr: <code>48eEMdYtCQaV5wY7wvmxK6jCxKkia9dgpNTMNT1do7RLWXCwWDgSKjN3kiZ6yHbAuAXWgDGN6imnGT9NPeHWD7zX9hSyHu2</code></li>
</ul>


<p>;tags: dessert cookies sweet chocolate</p>


guid: https://based.cooking/apple-pie.html
title: Apple Pie
url: https://based.cooking/apple-pie.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Apple Pie</h1>

<p><img src="pix/apple-pie.webp" alt="Apple Pie" /></p>

<ul>
<li>⏲️ Prep time: 30 min</li>
<li>🍳Cook time: 45 min</li>
<li>🍽️ Servings: 8</li>
</ul>


<h2>Ingredients</h2>

<h3>Filling</h3>

<ul>
<li>900 g (4-5) golden delicious apples</li>
<li>15 g (1 tbsp) lemon juice</li>
<li>50 g white sugar</li>
<li>65 g brown sugar</li>
<li>5 g (1 tsp) cinnamon</li>
<li>1-2 g nutmeg</li>
<li>15 g cornstarch</li>
<li>15 g ice water</li>
<li>226 g (2 sticks) cold butter, cut into slices</li>
</ul>


<h3>Crust</h3>

<ul>
<li>350 g flour</li>
<li>5 g salt</li>
<li>30 g white sugar</li>
<li>225 g butter</li>
<li>50-100 ml ice water</li>
</ul>


<h3>Egg Wash</h3>

<ul>
<li>1 egg (optional)</li>
<li>15 g water (optional)</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Peel and cut the apples into 1-2 inch strips</li>
<li>Put the apples in a bowl and mix in the lemon juice, sugar, cinnamon, nutmeg, and cornstarch and let it sit for 15 mins to release water</li>
<li>Transfer the filling mixture to a sauce pan and reduce the liquid over medium to low heat for around 15 mins, stirring regularly, then turn off the gas</li>
<li>While the filling is sitting / reducing, start the crust by putting the flour, salt, sugar, and pieces of butter in a food processor</li>
<li>Run the food processor until it resembles a coarse sand (5-10 seconds) then start dripping in the ice water until the mixture starts to chunk together</li>
<li>You&rsquo;ll know when it&rsquo;s done if you can pinch the dough with your hand and it sticks together</li>
<li>Preheat oven to 350°F then start making the pie crust</li>
<li>Cut the dough in half and roll both halves out with a rolling pin until they are big enough to cover your pie pan (around 9 inch diameter)</li>
<li>Put the bottom half dough into the pie pan and cut off the excess dough with a knife</li>
<li>Dump the sauce pan full of the filling into the pie pan and even it out</li>
<li>Cover the pie filling with the top dough and fold over and tuck in the excess crust</li>
<li>Use a fork or your fingers to pinch down the top crust to the bottom crust so you don&rsquo;t have air gaps</li>
<li>Optionally you can now brush on the egg wash to make the crust get a shiny golden brown color when it cooks</li>
<li>Cut a few slits in the top crust with a knife to give it a nice design and allow for air to release</li>
<li>Bake 45 minutes at 350°F or until the crust is brown to your liking and the apples are bubbling inside</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>mfed3 - xmr: <code>48eEMdYtCQaV5wY7wvmxK6jCxKkia9dgpNTMNT1do7RLWXCwWDgSKjN3kiZ6yHbAuAXWgDGN6imnGT9NPeHWD7zX9hSyHu2</code></li>
</ul>


<p>;tags: dessert pie sweet apples</p>


guid: https://based.cooking/soleier.html
title: Soleier (pickled eggs)
url: https://based.cooking/soleier.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Soleier (pickled eggs)</h1>

<p><img src="pix/soleier.webp" alt="Soleier" /></p>

<p>Soleier are a german pub dish. They are typically enjoyed between two beers.</p>

<ul>
<li>⏲️ Preparation time: 10min</li>
<li>🍳 Cook time: 10min</li>
<li>🍽️ Servings: 10</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>peels of five onions</li>
<li>10 eggs</li>
<li>2 loorber leaves</li>
<li>3 cloves</li>
<li>4 allspice</li>
<li>1Tbsp peppercorns</li>
<li>1Tbsp caraway seeds</li>
<li>1Tbsp mustard seeds</li>
<li>1tsp of Szechuan pepper (optional)</li>
<li>1tsp lovage (optional)</li>
<li>1tsp nutmeg (optional)</li>
<li>100mL vinegar</li>
<li>3 cloves of garlic</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Put 750mL of water and the peels of five onions in a pot and let them cook for five minutes. Remove the peels about twenty minutes later.</li>
<li>Put the eggs, one teaspoon of sugar, two tablespoons of salt and all spices (but vinegar and garlic) in the pot, bring it to a boil and cook them for seven minutes.</li>
<li>Use a spoon to remove the eggs from the pot and crack them all around. Do not remove the eggshell!</li>
<li>Place the eggs and the garlic in a jar, fill it with the spiced water and add the vinegar. Add water, if needed, so that the eggs are covered.</li>
<li>Let them rest for at least three days and at most two weeks at room temperature or slightly below.</li>
</ol>


<h2>Consumption Recommendation</h2>

<ol>
<li>Peel the egg and cut it in half.</li>
<li>Remove the yolk and fill the egg with mustard, oil, salt and pepper.</li>
<li>Place the yolk on top.</li>
</ol>


<h2>Contribution</h2>

<ul>
<li>SvenT<a href="https://github.com/s8svtang">github</a></li>
</ul>


<p>;tags: snack german eggs pub</p>


guid: https://based.cooking/beef-kidney.html
title: Beef Kidney
url: https://based.cooking/beef-kidney.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Beef Kidney</h1>

<p>My wife&rsquo;s beef kidney recipe</p>

<ul>
<li>⏲️ Prep time: 10 min</li>
<li>🍳 Cook time: 45 min</li>
<li>🍽️ Servings: 2</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>1 beef kidney</li>
<li>60g butter</li>
<li>2 onions</li>
<li>2 shallots</li>
<li>1 sprig of fresh parsley</li>
<li>3 bay leaves</li>
<li>400g croutons or toasted bread in pieces</li>
</ul>


<h2>Directions</h2>

<ol>
<li>clean the kidney and remove the fat</li>
<li>cut the kidney into small chunks (2cm or &frac34;")</li>
<li>put butter in a casserole dish</li>
<li>add kidney, parsley, bay leaf, salt, pepper</li>
<li>brown in the casserole for 10 minutes while stirring (don&rsquo;t burn)</li>
<li>add 2 glasses of dry white wine</li>
<li>add half a glass of water so that the mixture is well-bathed</li>
<li>simmer for 35 minutes</li>
<li>add about 400g of toasted bread in pieces</li>
<li>simmer for another 10 minutes</li>
</ol>


<h2>Contribution</h2>

<p>Philip Wittamore - <a href="https://wittamore.com">Website</a></p>

<p>;tags: kidney beef</p>


guid: https://based.cooking/aussie-snags.html
title: Aussie Snags (sausage sizzle)
url: https://based.cooking/aussie-snags.html
feedurl: https://based.cooking/rss.xml
content:
<h1>Aussie Snags (sausage sizzle)</h1>

<p>An Australian BBQ classic tradition that is simple and very easy to make. Great for parties and outdoor events
especially national events. Sometimes served at hardware chains.</p>

<ul>
<li>⏲️ Prep time: 2 min</li>
<li>🍳 Cook time: 20 min</li>
<li>🍽️ Servings: Depends</li>
</ul>


<h2>Ingredients</h2>

<ul>
<li>Sausages (thin)</li>
<li>Onions (4g per sausage)</li>
<li>Tomato sauce</li>
<li>Mustard (optional)</li>
<li>White sliced bread</li>
<li>Butter</li>
<li>Oil</li>
<li>Wood chips (optional, fuel for smokey flavour)</li>
</ul>


<h2>Directions</h2>

<ol>
<li>Chop up the onions into rings</li>
<li>Bring the sausages to the grill, turning once every 5 mins</li>
<li>Add oil of your choice to the hotplate then add the onions</li>
<li>Use your tongs to toss the onions until they are golden brown</li>
<li>When the onions are golden brown turn off the hotplate</li>
<li>When the sausages are cooked, butter the bread, then the onions, and add a sausage (optionally split)</li>
<li>Finally tomato sauce on top</li>
</ol>


<p>;tags: basic snack australian pork</p>


guid: https://medium.com/p/c89ec9b5a628
title: Python, SQLAlchemy, and Concurrency
author: Nick McHenry
feedurl: https://medium.com/feed/better-programming
url:
https://betterprogramming.pub/python-sqlalchemy-and-concurrency-c89ec9b5a628?source=rss----d0b105d10f0a---4

content:
<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://betterprogramming.pub/python-sqlalchemy-and-concurrency-c89ec9b5a628?source=rss----d0b105d10f0a---4"><img src="https://cdn-images-1.medium.com/max/2600/0*J3SVD5rvDH0XV0T_" width="6016"></a></p><p class="medium-feed-snippet">A practical overview of modern, asynchronous features in Python and the SQLAlchemy ORM</p><p class="medium-feed-link"><a href="https://betterprogramming.pub/python-sqlalchemy-and-concurrency-c89ec9b5a628?source=rss----d0b105d10f0a---4">Continue reading on Better Programming »</a></p></div>


guid: https://medium.com/p/869364313bd3
title: How to Convert Your iOS Network Layer to Work With Combine or Async/await
author: Riccardo Cipolleschi
feedurl: https://medium.com/feed/better-programming
url:
https://betterprogramming.pub/how-to-convert-your-ios-network-layer-to-work-with-combine-or-async-await-869364313bd3?source=rss----d0b105d10f0a---4

content:
<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://betterprogramming.pub/how-to-convert-your-ios-network-layer-to-work-with-combine-or-async-await-869364313bd3?source=rss----d0b105d10f0a---4"><img src="https://cdn-images-1.medium.com/max/2600/0*MweyOL_AEmRNlWto" width="4835"></a></p><p class="medium-feed-snippet">Adapting your network layer to different interfaces</p><p class="medium-feed-link"><a href="https://betterprogramming.pub/how-to-convert-your-ios-network-layer-to-work-with-combine-or-async-await-869364313bd3?source=rss----d0b105d10f0a---4">Continue reading on Better Programming »</a></p></div>


guid: https://medium.com/p/77352e12be95
title: How URL Shorteners Work and How to Build One
author: Nicholas Obert
feedurl: https://medium.com/feed/better-programming
url:
https://betterprogramming.pub/how-url-shorteners-work-and-how-to-build-one-77352e12be95?source=rss----d0b105d10f0a---4

content:
<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://betterprogramming.pub/how-url-shorteners-work-and-how-to-build-one-77352e12be95?source=rss----d0b105d10f0a---4"><img src="https://cdn-images-1.medium.com/max/2293/0*yn8tnS_dc7_6joAv" width="2293"></a></p><p class="medium-feed-snippet">Explore how long URLs get shortened for ease of sharing, concealing malicious links, and better looks</p><p class="medium-feed-link"><a href="https://betterprogramming.pub/how-url-shorteners-work-and-how-to-build-one-77352e12be95?source=rss----d0b105d10f0a---4">Continue reading on Better Programming »</a></p></div>


guid: https://medium.com/p/b2699315961f
title: A Complete Guide to Design Patterns
author: Emre Tanriverdi
feedurl: https://medium.com/feed/better-programming
content_mime_type: text/html
url:
https://betterprogramming.pub/design-patterns-a-complete-guide-b2699315961f?source=rss----d0b105d10f0a---4

content:
<h4>Design patterns explained with simple examples</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DQkiSDUkuOkiRI_4" /><figcaption>Photo by <a href="https://unsplash.com/@indraddd?utm_source=medium&amp;utm_medium=referral">Indra Utama</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>1- Strategy Pattern</h3><blockquote><strong>“Strategy Pattern </strong>defines a family of algorithms, encapsulates each one, and makes them <strong><em>interchangeable</em></strong>. Strategy lets the algorithm vary <strong><em>independently</em></strong> from clients that use them.”</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MvOU--Wo77R2GoodKwks4g.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@kellysikkema?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Kelly</a> on <a href="https://unsplash.com/photos/qWwpHwip31M?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Aside from formal definition, <strong>Strategy Pattern</strong> is widely used when you need to <strong><em>switch</em></strong> your algorithm or strategy in different places of your code.</p><p><strong>Simple Example:</strong></p><p>Suppose you build a game that has a <strong>Cat</strong> class that implements a <strong>Diet </strong>class. But let’s say your cat gained too much weight and now it needs to go on a diet that will help it lose weight for its health.</p><p>In this case, you can implement<strong> a Strategy Pattern </strong>such as:</p><pre>interface EatBehavior {<br>    public void eat();<br>}</pre><p><em>diet types that implements the eat behavior</em></p><pre>public class NormalDiet implements EatBehavior {<br>    @Override<br>    public void eat() {<br>        // normal food<br>    }<br>}</pre><pre>public class LosingWeightDiet implements EatBehavior {<br>    @Override<br>    public void eat() {<br>        // healthy food<br>    }<br>}</pre><p><em>cat class that </em><strong><em>HAS-A </em></strong><em>eat behavior</em></p><pre>public abstract class Cat {</pre><pre>    EatBehavior eatBehavior;</pre><pre>    public Cat(){}<br>    <br>    public void eat() {<br>        eatBehavior.eat();<br>    }<br>}</pre><p>And the client code would be like this:</p><pre>cat.eat();            // Cat eats as usual.</pre><pre>cat.setEatBehavior(new LosingWeightDiet());</pre><pre>cat.eat();           // Cat eats with a healthier diet.</pre><p><strong>Strategy Patterns</strong> can also help you assign<strong> different behaviors </strong>for different subtypes.</p><p>Let’s say you have a spyhnx cat (a species of cat that doesn’t have any fur) and a tabby cat (or any other cat species that has a fur).</p><p>You can easily update your classes as follows:</p><pre>interface EatBehavior {<br>    public void eat();<br>}<br>interface DisplayBehavior {<br>    public void display();<br>}</pre><p><em>fur types that implements the display behavior</em></p><pre>public class HasFur implements DisplayBehavior {<br>    @Override<br>    public void display() {<br>        // display with fur<br>    }<br>}</pre><pre>public class NoFur implements DisplayBehavior {<br>    @Override<br>    public void display() {<br>        // display without fur<br>    }<br>}</pre><p><em>a cat class that </em><strong><em>IS-A</em></strong><em> Cat type and </em><strong><em>HAS-A </em></strong><em>eat and display behavior</em></p><pre>public class Sphynx extends Cat {</pre><pre>    EatBehavior eatBehavior;<br>    DisplayBehavior displayBehavior;</pre><pre>    public Sphynx() {<br>        eatBehavior = normalDiet();<br>        <strong>displayBehavior = noFur();</strong><br>    }</pre><pre>    public void eat() {<br>        eatBehavior.eat();<br>    }</pre><pre>    public void display() {<br>        displayBehavior.display();<br>    }<br>}</pre><p><em>another cat class that </em><strong><em>IS-A</em></strong><em> Cat type and </em><strong><em>HAS-A</em></strong><em> eat behavior with a </em><strong><em>different</em></strong><em> display behavior</em></p><pre>public class Tabby extends Cat {<br>    <br>    EatBehavior eatBehavior;<br>    DisplayBehavior displayBehavior;</pre><pre>    public Tabby() {<br>        eatBehavior = normalDiet();<br>        <strong>displayBehavior = hasFur();</strong><br>    }</pre><pre>    public void eat() {<br>        eatBehavior.eat();<br>    }</pre><pre>    public void display() {<br>        displayBehavior.display();<br>    }<br>}</pre><p>And the client code would be like this:</p><pre>Cat spyhnx = new Spyhnx();<br>sphynx.display(); // displays cat without fur</pre><pre>Cat tabby = new Tabby();<br>tabby.display(); // displays cat with fur</pre><p>As seen above, it can also help you <strong><em>separate</em></strong> <strong><em>concerns</em></strong> of classes.</p><p>If one day you want to remove fur from the tabby for your game, you can just change how displayBehavior is set in the Tabby class and the client won’t need to be notified of this change.</p><p>Each class will only care of its own. (Single Responsibility Principle)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*D5LLHBtaHOBkREiCi--9vA.png" /><figcaption>Photo by <a href="https://unsplash.com/@karberg?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Kelly</a> on <a href="https://unsplash.com/s/photos/two-cats?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Real-Life Example:</strong></p><p>Suppose you are writing a software that will show weather forecasts but you want to store the user information in a database and weather information in another database.</p><p><em>different database types that implements the database strategy</em></p><pre>public class PostgreStrategy implements DatabaseStrategy {<br>    @Override<br>    public void save() {<br>        // save to PostgreSQL<br>    }<br>}</pre><pre>public class CouchbaseStrategy implements DatabaseStrategy {<br>    @Override<br>    public void save() {<br>        // save to Couchbase<br>    }<br>}</pre><p>The client code:</p><pre>DatabaseContext db = new DatabaseContext();</pre><pre>db.setDatabaseStrategy(new PostgreStrategy());<br>db.save(userInformation);</pre><pre>db.setDatabaseStrategy(new CouchbaseStrategy());<br>db.save(weatherInformation);</pre><p>Again, if one day you want to change the way how PostgreStrategy or CouchbaseStrategy works, you won’t need to touch the client code.</p><p>In short, <strong>Strategy Pattern </strong>helps us to <strong><em>dynamically</em></strong> change the way our components work as we write code and <strong><em>separates </em>our concerns</strong>.</p><p><strong>To read it as a single story:</strong> <a href="http://emretanriverdi.medium.com/design-patterns-strategy-pattern-d57a13c593b7">Strategy Pattern — A Quick Guide</a> (3 min read)</p><h3>2- Decorator Pattern</h3><blockquote>“<strong>Decorator Pattern </strong>attaches additional responsibilities to an object <strong><em>dynamically</em></strong>. Decorators provide a flexible alternative to subclassing for extending functionality.”</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KJSbSQEseuA58aEav7_FNQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@chris_jolly?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Christopher Jolly</a> on <a href="https://unsplash.com/@chris_jolly?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Aside from formal definition, <strong>Decorator Pattern</strong> wraps around an object of a <strong>Decorator</strong> class, allowing you to dynamically change the behavior of an object at client code.</p><p><strong>Simple Example:</strong></p><p>Suppose you own a <strong><em>local</em></strong> <strong><em>pizza shop</em></strong>.</p><p>Of course you have menus with fixed prices, but you also have a <em>“have-it-your-way”</em> style pizza that allows customers to add whatever ingredient they want.</p><p>You calculated the <strong><em>costs</em></strong> of them all by yourself with a piece of paper and a pen, but now your business is growing larger and you can’t catch up anymore.</p><p>It’s time to build a software for it! :)</p><p>So, let’s make a <strong>Pizza </strong>superclass with subclasses such as <strong>PizzaWithMushrooms, PizzaWithCorn, PizzaWithSalami, PizzaWithMushroomsAndCorn, PizzaWithMushroomsAndSalami, PizzaWithCornAndSalami, PizzaWithMushroomsAndCornAndSalami.</strong></p><p>Oops. That’s not a very good practice, is it?</p><p>What if we want to add a new ingredient in the future? What if we want to add a new crust type, like Thin Crust Pizza? What if we want to update prices of each ingredient? What if we want to add x2 more corn?</p><p>In our case, this practice would result in a <strong><em>maintenance nightmare</em></strong>.</p><p>Our goal must be to allow our classes to add new behaviors, without modifying existing code. (Open-Closed Principle)</p><p>Written code should be <strong><em>reusable</em></strong>.</p><p>To achieve this, we can implement <strong>Decorator Pattern</strong> such as:</p><pre>public interface Pizza {<br>    String getSummary();<br>    int getPrice();<br>}</pre><p><em>pizza classes that implements the Pizza interface</em></p><pre>public class StandardCrustPizza implements Pizza</pre><pre><strong>    private static final String PRICE = 25;</strong><br>    <br>    @Override<br>    public String getSummary() {<br>        return &quot;Standard Pizza (&quot; + PRICE + &quot;)&quot;;<br>    }</pre><pre>    @Override<br>    public int getPrice() {<br>        return PRICE;<br>    }<br>}</pre><pre>public class ThinCrustPizza implements Pizza {</pre><pre><strong>    private static final String PRICE = 30; </strong>   <br>   <br>    @Override<br>    public String getSummary() {<br>        return &quot;Thin Crust Pizza (&quot; + PRICE + &quot;)&quot;;<br>    }</pre><pre>    @Override<br>    public int getPrice() {<br>        return PRICE;<br>    }<br>}</pre><p><em>pizza decorator abstract class that implements the Pizza interface</em></p><pre>abstract class PizzaDecorator implements Pizza {</pre><pre>    @Override<br>    public abstract String getSummary();<br>    <br>    @Override<br>    public abstract int getPrice();<br>}</pre><p><strong><em>pizza ingredients</em></strong><em> that extends </em><strong><em>PizzaDecorator abstract class</em></strong></p><pre>public class Corn extends PizzaDecorator {<br>    <br>    private Pizza pizza;<br>    <strong>private static final String PRICE = 4;</strong><br>    <br>    Corn(Pizza pizza) {<br>        this.pizza = pizza;<br>    }</pre><pre>    @Override<br>    public String getSummary() {<br>        return pizza.getSummary() +<br>               &quot;, with corn (&quot; + PRICE + &quot;)&quot;;<br>    }</pre><pre>    @Override<br>    public int getPrice() {<br>        return pizza.getPrice() + PRICE;<br>    }<br>}</pre><pre>public class Mushrooms extends PizzaDecorator {</pre><pre>    private Pizza pizza;<br>    <strong>private static final String PRICE = 6;</strong></pre><pre>    Mushrooms(Pizza pizza) {<br>        this.pizza = pizza;<br>    }</pre><pre>    @Override<br>    public String getSummary() {<br>        return pizza.getSummary() +<br>               &quot;, with mushrooms (&quot; + PRICE + &quot;)&quot;;<br>    }</pre><pre>    @Override<br>    public int getPrice() {<br>        return pizza.getPrice() + PRICE;<br>    }<br>}</pre><pre>public class Salami extends PizzaDecorator {<br>    <br>    private Pizza pizza;<br>    <strong>private static final String PRICE = 5;</strong></pre><pre>    Salami(Pizza pizza) {<br>        this.pizza = pizza;<br>    }</pre><pre>    @Override<br>    public String getSummary() {<br>        return pizza.getSummary() +<br>               &quot;, with salami  (&quot; + PRICE + &quot;)&quot;;<br>    }</pre><pre>    @Override<br>    public int getPrice() {<br>        return pizza.getPrice() + PRICE;<br>    }<br>}</pre><p>And the client code would be like this:</p><pre>Pizza pizza = new StandardPizza(); // standard pizza, base: 25<br>pizza = new Salami(pizza);        // salami added, total: 30<br>pizza = new Corn(pizza);         // corn added, total: 34<br>pizza = new Corn(pizza);        // corn x 2 portion added, total: 38</pre><pre>Output:<br>Standard Pizza (25), with salami (5), with corn (4), with corn (4)<br>Price: 38</pre><pre>Pizza pizza = new ThinCrustPizza(); // thin crust pizza, base: 30<br>pizza = new Mushroom(pizza);       // mushroom added, total: 36<br>pizza = new Salami(pizza);        // salami added, total: 41</pre><pre>Output:<br>Thin Crust Pizza (30), with mushroom (6), with salami (5)<br>Price: 41</pre><p>See, it’s all very reusable! If one day you want to add a new crust/ingredient or update the prices of current ones, you won’t need to touch the client code.</p><p>Each class will only care of its own. (Single Responsibility Principle)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pnSwFqQrIuJhGHGfRctHAw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@karthikgarikapati?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Karthik</a> on <a href="https://unsplash.com/s/photos/pizza?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Real-Life Example:</strong></p><p><strong>Decorator Pattern</strong> is widely used in <strong><em>java.io package, </em></strong>such as:</p><pre>InputStream in = new FileInputStream(file);<br>in = new BufferedInputStream(in);<br>in = new DataInputStream(in);</pre><p>FileInputStream is the<em> crust type</em> here, while BufferedInputStream and DataInputStream are the<strong><em> </em></strong><em>ingredients</em>.</p><p>You can even write your own decorator<em> </em>to your program by simply extending the<em> java.io package </em>decorators’ superclass (FilterInputStream) and wrap it around the base class FileInputStream.</p><pre>public class UpperCaseInputStream extends FilterInputStream {<br>    public UpperCaseInputStream(InputStream in) {<br>        super(in);<br>    }</pre><pre>    @Override<br>    public int read() throws IOException {<br>        return Character.<em>toUpperCase</em>(super.read());<br>    }<br>}</pre><p>And the client code would be like this:</p><pre>InputStream in = new FileInputStream(file);<br>in = new UpperCaseInputStream(in);</pre><pre>// other decorators</pre><p>In short, <strong>Decorator Pattern </strong>helps us to <strong><em>dynamically</em></strong> attach additional functionalities to our base class as we write code.</p><p><strong>To read it as a single story:</strong> <a href="http://emretanriverdi.medium.com/design-patterns-decorator-pattern-3b50880173e1">Decorator Pattern — A Quick Guide</a> (4 min read)</p><h3>3- Observer Pattern</h3><blockquote>“<strong>Observer Pattern</strong> defines one-to-many dependency between objects so that when one object <strong><em>changes</em></strong> <strong><em>state</em></strong>, all of its dependents are <strong><em>notified and updated automatically.</em></strong><em>”</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*87yHOvQeAma_QqYbZIK_fQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@daltonabraham?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Dalton Abraham</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Aside from formal definition, <strong>Observer Pattern</strong> helps us to listen (subscribe) to a subject and<strong><em> be up-to-date whenever a change occurs.</em></strong></p><p><strong>Subjects</strong> are open for the <strong>Observers</strong> to <em>subscribe,</em> and does not know (nor care about) how they are implemented and vice versa.</p><p><strong>Simple Example:</strong></p><p>Suppose you are building a social media app and implementing it for multiple platforms.</p><p><em>a platform enum (for the sake of simplicity)</em></p><pre>public enum Platform {<br>    <em>WEB(1)</em>,<br>    MOBILE(2);<br>}</pre><p><em>a view interface that has a display method</em></p><pre>public interface View {<br>    void display();<br>}</pre><p><em>a subject interface that has add/delete observer and notify observers methods</em></p><pre>public interface Subject {<br>    void registerObserver(Observer observer);<br>    void removeObserver(Observer observer);<br>    void notifyObservers();<br>}</pre><p><em>an observer interface that has an update method</em></p><pre>public interface Observer {<br>    void update(Double x, Double y);<br>}</pre><p>Let’s say you want to show currency information in our app. Based on incoming data, you’ll update the numbers on the screen.</p><p><em>a currency class that implements the methods in Subject interface</em></p><pre>public class CurrencyData implements Subject {<br>    private final List&lt;Observer&gt; observers = new ArrayList&lt;&gt;();<br>    private Double value;<br>    private Double interestRate;</pre><pre>    @Override<br>    public void registerObserver(Observer observer) {<br>        observers.add(observer);<br>    }</pre><pre>    @Override<br>    public void removeObserver(Observer observer) {<br>        observers.remove(observer);<br>    }</pre><pre>    @Override<br>    public void notifyObservers() {<br>        observers.forEach(observer -&gt;<br>                <strong>observer.update(value, interestRate)</strong>);<br>    }</pre><pre>    public void setValue(Double value) {<br>        this.value = value;<br>        <strong>notifyObservers();</strong><br>    }</pre><pre>    public void setInterestRate(Double interestRate) {<br>        this.interestRate = interestRate;<br>        <strong>notifyObservers();</strong><br>    }</pre><pre>// getters</pre><pre>}</pre><p><em>Notice how </em><strong><em>notifyObservers()</em></strong><em> is called whenever a change occurs.</em></p><p>As your app grows larger, you may want to add new functionalities, such as weather information.</p><p><em>a weather class that implements the methods in Subject interface</em></p><pre>public class WeatherData implements Subject {<br>    private final List&lt;Observer&gt; observers = new ArrayList&lt;&gt;();<br>    private Double temperature;<br>    private Double humidity;</pre><pre>    @Override<br>    public void registerObserver(Observer observer) {<br>        observers.add(observer);<br>    }</pre><pre>    @Override<br>    public void removeObserver(Observer observer) {<br>        observers.remove(observer);<br>    }</pre><pre>    @Override<br>    public void notifyObservers() {<br>        observers.forEach(observer -&gt;<br>                <strong>observer.update(temperature, humidity)</strong>);<br>    }</pre><pre>    public void setTemperature(Double temperature) {<br>        this.temperature = temperature;<br>        <strong>notifyObservers();</strong><br>    }</pre><pre>    public void setHumidity(Double humidity) {<br>        this.humidity = humidity;<br>        <strong>notifyObservers();</strong><br>    }</pre><pre>// getters</pre><pre>}</pre><p><em>a currency display class that implements the methods in Observer and View interfaces</em></p><pre>public class CurrencyDisplay implements Observer, View {<br>    private Platform platform;<br>    private Double value;<br>    private Double interestRate;</pre><pre>    public CurrencyDisplay(Platform platform, Subject subject) {<br>       this.platform = platform;     <br>       subject.registerObserver(this);<br>    }</pre><pre>    public void unsubscribe(Subject subject) {<br>        subject.removeObserver(this);<br>    }</pre><pre>    @Override<br>    public void update(Double temperature, Double humidity) {<br>        this.value = temperature;<br>        this.interestRate = humidity;<br>        display();<br>    }</pre><pre>    @Override<br>    public void display() {<br>        // display<br>    }<br>}</pre><p><em>a weather display class that implements the methods in Observer and View interfaces</em></p><pre>public class WeatherDisplay implements Observer, View {<br>    private Platform platform;    <br>    private Double temperature;<br>    private Double humidity;</pre><pre>    public WeatherDisplay(Platform platform, Subject subject) {<br>        this.platform = platform;<br>        subject.registerObserver(this);<br>    }</pre><pre>    public void unsubscribe(Subject subject) {<br>        subject.removeObserver(this);<br>    }</pre><pre>    @Override<br>    public void update(Double temperature, Double humidity) {<br>        this.temperature = temperature;<br>        this.humidity = humidity;<br>        display();<br>    }</pre><pre>    @Override<br>    public void display() {<br>        // display<br>    }<br>}</pre><p>Let’s see it in action:</p><pre>CurrencyData currency = new CurrencyData();<br>WeatherData weather = new WeatherData();</pre><pre>CurrencyDisplay webCurrency = new CurrencyDisplay(WEB, currency);<br>CurrencyDisplay mobileCurrency<br>                         = new CurrencyDisplay(MOBILE, currency);<br>// currency information is available for both platforms</pre><pre>WeatherDisplay mobileWeather = new WeatherDisplay(MOBILE, weather);<br>// weather information is available for mobile,<br>// not available for web</pre><pre>double temperature = 21.05;<br>weather.setTemperature(temperature);<br>// for weather -&gt; only mobile is notified</pre><pre>double interestRate = 14.18;<br>currency.setInterestRate(interestRate);<br>// for currency -&gt; both web and mobile got notified</pre><pre>mobileCurrency.unsubscribe(currency);<br>// for currency -&gt; mobile is not listening anymore</pre><pre>interestRate = 15.20;<br>currency.setInterestRate(interestRate);<br>// for currency -&gt; only web is notified</pre><p>In<strong> Observer Pattern</strong>, the <strong>Subject</strong> is an <strong><em>open book</em></strong>. <strong>Observer</strong> is free to subscribe and unsubscribe <strong>based on its needs</strong>.</p><p>If you want to unsubscribe, it’s so easy! Since this design is <strong><em>loosely coupled, </em></strong>you can just call <strong>unsubscribe(subject) </strong>and it’s all done!</p><blockquote>Loosely coupled designs allow us to build flexible object-oriented systems that can handle change. They minimize the interdependency between objects.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QcNFBGnVAzuVaA4OQOpokg.png" /><figcaption>Photo by <a href="https://unsplash.com/@claybanks?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Clay Banks</a> on <a href="https://unsplash.com/s/photos/clay-banks-dogecoin?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Real-Life Example:</strong></p><p><strong>Observer Pattern</strong> is widely used in <strong><em>javax.swing package.</em></strong></p><p>Let’s think of a service that will update both the displays and the database information based on change of data:</p><pre>UserData data = new UserData();</pre><pre>Display webDisplay = new Display(WEB, data);<br>Display mobileDisplay = new Display(MOBILE, data);</pre><pre>Database postgresql = new Postgresql(data);<br>Database couchbase = new Couchbase(data);</pre><pre>// web display, mobile display, postgresql and couchbase<br>// all subscribed to user data.</pre><p>Button is the <strong>subject</strong> here, when the button is clicked, data gets changed.</p><pre>button.addActionListener((ActionListener) <br>                ae -&gt; data.setEmail(email));</pre><p>When data gets <strong>changed, all observers get notified </strong>and updated.</p><p><strong>To read it as a single story:</strong> <a href="http://emretanriverdi.medium.com/observer-pattern-a-quick-guide-38865dc9bae2">Observer Pattern — A Quick Guide</a> (4 min read)</p><h3>4- Factory Pattern</h3><blockquote>“There are 3 types of Factory Pattern: <strong>Simple, Method and Abstract.”</strong></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xIj2ay1qzULuOA7ZrgJJDA.png" /><figcaption>Photo by <a href="https://unsplash.com/@nataliekuhl?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Natalie Kuhl</a> on <a href="https://unsplash.com/s/photos/factory?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h4>Simple Factory</h4><p>Suppose you have a <strong><em>local pizza shop </em></strong>and you instantiate <strong>a</strong> <strong>pizza object</strong> for every order you get.</p><pre>Pizza pizza = new Pizza();</pre><p>Instead of that, you can simply do this:</p><pre>public class Pizza {<br>    private Pizza(){}     // hide the constructor, so no one         <br>                                initializes pizza with &quot;new&quot;</pre><pre>    public static Pizza create() {<br>        return new Pizza();<br>    }<br>}</pre><p>or this:</p><pre>public class PizzaFactory {<br>    public static Pizza create() {<br>        return new Pizza();<br>    }<br>}</pre><pre>public class Pizza {<br>   <br>   // assuming your models are in the same package, you can<br>   make this package-private to make sure constructor won&#39;t be    <br>   called from client code<br>   protected Pizza(){}<br>}</pre><p>and the client code will be like this:</p><pre>Pizza pizza = Pizza.create();</pre><pre>or</pre><pre>Pizza pizza = PizzaFactory.create();</pre><p>If you’d like to change how this method works (or maybe add some business logic to it), you can update <strong>create</strong> instead of putting the logic code to the constructor.</p><p>Don’t fret, I hear you, you say we could achieve the same thing with a constructor.<br>Well, Simple Factory is basically a constructor that has a custom name.</p><p>Think of it like this:</p><pre>Person person = new Person(170);</pre><pre>to</pre><pre>Person person = Person.fromHeight(170);</pre><pre>or</pre><pre>Person person = PersonFactory.fromHeight(170);</pre><p>It’s up to you to use it or not. I personally like it.</p><p>Some people don’t even count Simple Factory as a Design Pattern, though.<br>Factory Method and Abstract Factory on the other hand, is a bit different.</p><p>So let’s get to <strong>Factory Method</strong>.</p><h4>Factory Method</h4><p>So… back to the order management system.</p><p>Let’s say your business is larger now and you start to sell burgers.</p><p>Factory Method helps you to select between pizza and burger by overriding a method but keeps non-varying parts in a common method.</p><p>Let’s first create a Meal interface with meals implementing it.</p><pre>public interface Meal {<br>    // implementations<br>}</pre><pre>public class Pizza implements Meal {<br>    // implementations<br>}</pre><pre>public class Burger implements Meal {<br>    // implementations<br>}</pre><p>Let’s make a more generic MealFactory interface with both PizzaFactory and BurgerFactory implementing it.</p><pre>interface MealFactory {<br>    //factory method<br>    <strong>Meal</strong> create();        // compulsory inheritance<br>}</pre><pre>public class PizzaFactory implements MealFactory {<br>    // implementations</pre><pre>    @Override<br>    Meal create() {<br>        return new Pizza();<br>    }<br>}</pre><pre>public class BurgerFactory implements MealFactory {<br>    // implementations<br>   <br>    @Override<br>    Meal create() {<br>        return new Burger();<br>    }<br>}</pre><p>Both pizza types override <strong>create</strong> according their own needs.</p><p>Now client code would be like:</p><pre>MealFactory pizzaFactory = new PizzaFactory();<br>Meal pizza = pizzaFactory.create();</pre><pre>MealFactory burgerFactory = new BurgerFactory();<br>Meal burger = burgerFactory.create();</pre><p>That’s it!</p><p>If both Meals have a common method regardless of their type, you can turn MealFactory to abstract class instead of an interface.</p><pre>abstract class MealFactory {<br>    //factory method<br>    protected abstact <strong>Meal</strong> create();     // compulsory inheritance</pre><pre>    public void createAndSendOrder() {<br>        Meal meal = create();<br>        // do stuff<br>    }<br>}</pre><pre>public class PizzaFactory extends MealFactory {<br>    // implementations</pre><pre>    @Override<br>    protected Meal create() {<br>        return new Pizza();<br>    }<br>}</pre><pre>public class BurgerFactory extends MealFactory {<br>    // implementations<br>   <br>    @Override<br>    protected Meal create() {<br>        return new Burger();<br>    }<br>}</pre><p>And the client code would be like:</p><pre>MealFactory pizzaFactory = new PizzaFactory();<br>pizzaFactory.createAndSendOrder();</pre><pre>MealFactory burgerFactory = new BurgerFactory();<br>burgerFactory.createAndSendOrder();</pre><p>It’s great because I also encapsulated the creation logic from client completely.</p><h4>Abstract Factory</h4><p>Now let’s add vegan options of pizza and burger.</p><p>So it will be like:</p><pre>interface MealFactory {<br>    <strong>Pizza</strong> createPizza();      // no inheritance needed<br>    <strong>Burger</strong> createBurger();    // no inheritance needed<br>}</pre><pre>public class VeganMealFactory implements MealFactory {</pre><pre>    @Override<br>    public Pizza createPizza() {<br>        return new VeganPizza();<br>    }</pre><pre>    @Override<br>    public Burger createBurger() {<br>        return new VeganBurger();<br>    }<br>}</pre><pre>public class NonVeganMealFactory implements MealFactory {</pre><pre>    @Override<br>    public Pizza createPizza() {<br>        return new NonVeganPizza();<br>    }</pre><pre>    @Override<br>    public Burger createBurger() {<br>        return new NonVeganBurger();<br>    }<br>}</pre><p>Now it’s a factory of factories.</p><p>In Factory Method, only a single method was responsible of creation of a pizza, here we have separate methods for separate pizzas, so whole class is responsible.</p><p>In Factory Method,Pizza and Burger needed to be in type Meal,<br>here it’s not compulsory.</p><p>Let’s see the client code:</p><pre>MealFactory veganMealFactory = new VeganMealFactory();<br>MealFactory nonVeganMealFactory = new NonVeganMealFactory();</pre><pre>Pizza veganPizza = veganMealFactory.createPizza();<br>Burger veganBurger = veganMealFactory.createBurger();</pre><pre>Pizza nonVeganPizza = nonVeganMealFactory.createPizza();<br>Burger nonVeganBurger = nonVeganMealFactory.createBurger();</pre><p>Since both VeganMealFactory and NonVeganMealFactory are of type PizzaFactory, can’t we just decide between them using a simple decider?</p><p>Let’s try it:</p><pre>public class MealFactoryDecider {</pre><pre>    private MealFactoryDecider(){}</pre><pre>    public static MealFactory decide(MealType mealType) {<br>        switch (mealType) {<br>            case <em>VEGAN</em>:<br>                return new VeganMealFactory();<br>            case <em>NONVEGAN</em>:<br>                return new NonVeganMealFactory();<br>            default: throw new RuntimeException(&quot;Invalid type.&quot;);<br>        }<br>    }<br>}</pre><p>And the final client code would be like:</p><pre>MealFactory veganMealFactory =<br>MealFactoryDecider.decide(<em>VEGAN</em>);</pre><pre>MealFactory nonVeganMealFactory = MealFactoryDecider.decide(<em>NONVEGAN</em>);</pre><pre>Pizza veganPizza = veganMealFactory.createPizza();<br>Burger veganBurger = veganMealFactory.createBurger();</pre><pre>Pizza nonVeganPizza = nonVeganMealFactory.createPizza();<br>Burger nonVeganBurger = nonVeganMealFactory.createBurger();</pre><p>Voila!</p><p>Remember to combine multiple patterns if you feel like it’ll be a good fit.</p><h4>Wrap-Up</h4><p><strong>Simple Factory </strong>relies on readability: while it may not be considered a design pattern, it’s a simple way to decouple your clients from concrete classes.</p><p><strong>Factory Method</strong> relies on inheritance: object creation is delegated to subclasses which implement the specific factory method to create objects.</p><p><strong>Abstract Factory</strong> relies on composition: object creation is implemented in multiple methods exposed in the factory interface.</p><blockquote>All factory patterns promote loose coupling by reducing the dependency of your application on concrete classes.</blockquote><p><strong>To read it as a single story:</strong> <a href="https://emretanriverdi.medium.com/factory-pattern-a-quick-guide-cd31eeeefb74">Factory Pattern — A Quick Guide</a> (4 min read)</p><h3>5- Singleton Pattern</h3><blockquote><strong>“Singleton Pattern</strong> ensures a class has only <strong>one instance</strong>, and provides a global point of access to it.”</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QjfFAqhFIA2aP802Js_sJw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@davisuko?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">davisuko</a> on <a href="https://unsplash.com/s/photos/unique?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Simple Example:<br></strong>Suppose you need a carpenter for a sofa, chairs and a cupboard.<br>It’d be the best if you call a one carpenter and do all the work with him.<br><strong>It wouldn’t be wise to call a different carpenter for each object.</strong></p><p><strong>Real-Life Example:<br></strong>It’s very similar to Simple Example. Let’s say you need a database client that you’ll handle all the CRUD operations.<br>You wouldn’t want to have multiple database clients since it will cause unexpected behaviors such as memory issues and data corruption.</p><h4>Implementation</h4><pre>public class Singleton {</pre><pre>private static Singleton instance;<br>    <br>    private Singleton(){}    // hiding the constructor<br>    <br>    public static Singleton getInstance() {<br>        if (instance == null) {<br>            instance = new Singleton();<br>        }<br>        return instance;<br>    }<br>    // other methods<br>}</pre><p>And the client code is:</p><pre>Singleton singleton = Singleton.getInstance();</pre><p>In the above implementation, the logic is such as:<br>if object does not exist → create and return object<br>if object exists → return already created object</p><h4>Dealing with Multithreading</h4><p>The problem with above code block is that in a multithreaded application objects might get initialized multiple times if threads access the same<strong> </strong>if<strong> </strong>block concurrently when <strong>getInstance()</strong> is used for the first time.</p><p>Let’s continue with possible solutions:</p><p><strong>1. Eager Initialization</strong></p><pre>public class Singleton {</pre><pre>private static Singleton instance = new Singleton();<br>    <br>    private Singleton(){}    // hiding the constructor<br>    <br>    public static Singleton getInstance() {<br>       return instance;<br>    }<br>    // other methods<br>}</pre><p>Using this approach, we pass the responsibility to JVM and it initializes our Singleton instance when the class is loaded, so multithreading is not an issue.</p><p>You can use this if you are sure you’ll use <strong>getInstance() </strong>at least one time in your application.</p><p><strong>2. Locking the Initialization</strong></p><pre>public class Singleton {</pre><pre>private static Singleton instance;<br>    <br>    private Singleton(){}    // hiding the constructor<br>    <br>    public static <strong>synchronized</strong> Singleton getInstance() {<br>        if (instance == null) {<br>            instance = new Singleton();<br>        }<br>        return instance;<br>    }<br>    // other methods<br>}</pre><p>We can lock the <strong>getInstance() </strong>by using <strong>synchronized</strong> keyword and force other threads to wait current thread to exit before entering this code block.</p><p>While the above example is correct (and used in most examples), this is a bad practice. We don’t need to lock the method every time <strong>getInstance() </strong>is called, <strong>we need to lock it the first time it’s being called. </strong>Since locking is a performance-wise expensive operation, we had better not lock whole method.</p><pre>public class Singleton {</pre><pre>private static <strong>volatile</strong> Singleton instance;<br>    <br>    private Singleton(){}    // hiding the constructor<br>    <br>    public static Singleton getInstance() {<br>        if (instance == null) {<br>            <strong>synchronized(Singleton.class) {<br>                instance = new Singleton();<br>            }</strong><br>        }<br>        return instance;<br>    }<br>    // other methods<br>}</pre><p>Voila!</p><h4>Things to Consider</h4><p>While Singleton Pattern is great and widely being used, it’s sometimes considered as an anti-pattern since it can help us mask bad design.</p><p><strong>1. Violating loose-coupling<br></strong>When we pass Singleton classes around like <strong>Singleton.getInstance(),<br></strong>we may not realize the classes of our app know too much about each other, being too tightly-coupled.<br>For example passing the database client all over our app is a bad practice.</p><p><strong>2. Violating Single Responsibility Principle<br></strong>Singleton Pattern both handles ensuring a class has only one instance and providing an access point to it, which makes it carry two huge responsibilities on its shoulders.</p><p><strong>3. Singleton Pattern vs Static Classes<br></strong>We can make Singleton lazy-initialized with our if check above, static methods are lazy-initialized by default.<br>Singleton allows method overriding, static methods don’t allow overriding but can achieve similar behavior by method hiding.</p><p><strong>When to use static class:</strong> If you are planning to write helper methods such as math, array manipulations etc., it can be easier to just use a class full of static helper methods.</p><p><strong>When to use Singleton:</strong> Rest of everything. Singleton Class is just a normal class following normal OOP principles.</p><p><strong>4. Singleton Pattern vs Dependency Injection<br></strong>If you are already using a framework that handles injections, it may be a better practice to just inject classes instead of applying Singleton Pattern.</p><p>I prefer to first check if it’s a helper method, if yes, create a static class.<br>If not, check our DI availabilities. If yes, use DI. If not, use Singleton.</p><p><strong>To read it as a single story: </strong><a href="https://emretanriverdi.medium.com/singleton-pattern-a-quick-guide-2836a3e1696e">Singleton Pattern — A Quick Guide</a> (4 min read)</p><h3>6- Builder Pattern</h3><blockquote><strong>“Builder Pattern</strong> helps us construct complex objects by allowing creation of different representations of that object using same construction code.”</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wPNYZYkpKjGfMo0SdUvCqg.png" /><figcaption>Photo by <a href="https://unsplash.com/@neonbrand?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">neonbrand</a> on <a href="https://unsplash.com/s/photos/brick?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Builder Pattern </strong>is just a simple alternative of <strong><em>telescoping constructors </em></strong>and<strong><em><br>many lines of setters.</em></strong></p><pre>public class Pizza {</pre><pre>   private int slices;<br>   private boolean cheese;<br>   private boolean mushrooms;</pre><pre>public Pizza(int slices) { … }  <br>   public Pizza(int slices, boolean cheese) { … }<br>   public Pizza(int slices, boolean cheese, boolean mushrooms) { … }</pre><pre>// implement methods</pre><pre>}</pre><p>So this is what a telescoping constructor look like.<br>We can extend it even more:</p><pre>public Pizza(int slices, boolean cheese, boolean mushrooms, boolean pepperoni, boolean onions, boolean studentDiscount…) { … }</pre><p>Assuming slices is a required parameter and the rest of them is not,<br>it wouldn’t be wise to create a different constructor for each optional field to satisfy all object combinations.</p><p>Simplest way to get rid of this would be to just create a constructor which takes slice parameter and sets rest of the fields upon our needs.</p><pre>public class Pizza {</pre><pre>private int slices;<br>   private boolean cheese;<br>   private boolean mushrooms;</pre><pre>public Pizza(int slices) { … }</pre><pre>}</pre><p>And the client code would be like:</p><pre>Pizza pizza = new Pizza(2);</pre><pre>pizza.setCheese(true);<br>pizza.setMushrooms(true);<br>pizza.setPepperoni(true);<br>…</pre><p>This alternative doesn’t look good either.<br>The easiest way to save this code is to make a builder class, such as:</p><pre>public class Pizza {<br>    private int slices;<br>    private boolean cheese;<br>    private boolean mushrooms;<br>    private boolean pepperoni;<br>    private boolean onions;<br>    private boolean studentDiscount;</pre><pre>    public Pizza(Builder builder) {<br>        this.slices = builder.slices;<br>        this.cheese = builder.cheese;<br>        this.mushrooms = builder.mushrooms;<br>        this.pepperoni = builder.pepperoni;<br>        this.onions = builder.onions;<br>        this.studentDiscount = builder.studentDiscount;<br>    }</pre><pre>// getters &amp; setters</pre><pre>public static final class Builder {<br>        private int slices;<br>        private boolean cheese;<br>        private boolean mushrooms;<br>        private boolean pepperoni;<br>        private boolean onions;<br>        private boolean studentDiscount;</pre><pre>    private Builder() {}</pre><pre>    public static Builder initialize(int slices) {<br>            return new Builder().withSlices(slices);<br>        }</pre><pre>    public Builder withSlices(int slices) {<br>            this.slices = slices;<br>            return this;<br>        }</pre><pre>    public Builder withCheese() {<br>            this.cheese = true;<br>            return this;<br>        }</pre><pre>    public Builder withMushrooms() {<br>            this.mushrooms = true;<br>            return this;<br>        }</pre><pre>    public Builder withPepperoni() {<br>            this.pepperoni = true;<br>            return this;<br>        }</pre><pre>    public Builder withOnions() {<br>            this.onions = true;<br>            return this;<br>        }</pre><pre>    public Builder withStudentDiscount() {<br>            this.studentDiscount = true;<br>            return this;<br>        }</pre><pre>    public Pizza build() {<br>            return new Pizza(this);<br>        }<br>    }<br>}</pre><p>Since slices is a required field, Builder’s private constructor is hidden and has a simple factory method that only permits to initialize with slices.</p><p>Up until <strong>build() </strong>method is called, Builder returns a Builder type<strong>,<br>build() </strong>method transforms Pizza.Builder to an actual Pizza object.</p><p>And the client code would be like:</p><pre>Pizza pizza = Pizza<em>.Builder</em><br>                  <em> .initialize(</em>2<em>)<br>                   .withCheese()<br>                   .withMushrooms()<br>                   .withStudentDiscount()<br>                   </em>.build();</pre><p>Voila!</p><p><strong>To read it as a single story: </strong><a href="https://emretanriverdi.medium.com/builder-pattern-a-quick-guide-e93494d5429e">Builder Pattern — A Quick Guide</a> (2 min read)</p><h3>7- Command Pattern</h3><blockquote><strong>“Command Pattern</strong> encapsulates a request as an object, helping us to use it with different requests and support undo operation.”</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*98CNTMs1GjsZWO06vME4yg.png" /><figcaption>Photo by <a href="https://unsplash.com/@_danbrad?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Daniel Bradley</a> on <a href="https://unsplash.com/s/photos/order?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Command Pattern</strong> is like ordering at a restaurant.</p><p>Chef does not hear orders from the client itself, he/she uses a helper.<br>(like a waiter/waitress)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Cup0IhpHkupy0aJBkvzpOQ.png" /><figcaption>Art by <a href="https://zhart.us/">Dmitry Zhart</a></figcaption></figure><p>Suppose you have an air conditioner and you need to turn it on/off.</p><p>Normally in this use case, you would simply write an<strong> AirConditioner</strong> class with <strong>turnOn()</strong> and <strong>turnOff() </strong>methods, but this time <strong>we’ll implement the actions in classes instead of methods.</strong></p><p>To do this, you can write a helper class such as <strong>RemoteControl.</strong></p><p>Now it’s like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sQF8PC6SDWVpuv3wlFpVRw.png" /><figcaption>Art by <a href="https://zhart.us/">Dmitry Zhart</a></figcaption></figure><p>We are the client, remote control is the waiter/waitress and AC is the chef.</p><p>Let’s see it in code:</p><pre>public class AirConditioner {<br>    private boolean active;</pre><pre>    void turnOn() {<br>        active = true;<br>    }</pre><pre>    void turnOff() {<br>        active = false;<br>    }<br>}</pre><p>You need separate classes for on/off actions (commands), such as:</p><pre>public interface Command {<br>    void execute();<br>    void undo();<br>}</pre><pre>public class <strong>AirConditionerOff</strong> implements Command {<br>    private final AirConditioner airConditioner;</pre><pre>    public AirConditionerOff(AirConditioner airConditioner) {<br>        this.airConditioner = airConditioner;<br>    }</pre><pre>    @Override<br>    public void execute() {<br>        <strong>airConditioner.turnOff();</strong><br>    }</pre><pre>    @Override<br>    public void undo() {<br>        airConditioner.turnOn();<br>    }<br>}</pre><pre>public class <strong>AirConditionerOn</strong> implements Command {<br>    private final AirConditioner airConditioner;</pre><pre>    public AirConditionerOn(AirConditioner airConditioner) {<br>        this.airConditioner = airConditioner;<br>    }</pre><pre>    @Override<br>    public void execute() {<br>        <strong>airConditioner.turnOn();</strong><br>    }</pre><pre>    @Override<br>    public void undo() {<br>        airConditioner.turnOff();<br>    }<br>}</pre><p>And you need a helper (invoker) to communicate between us and AC:</p><pre>public class RemoteControl {</pre><pre>private RemoteControl(){}         // hiding the constructor</pre><pre>    public static void submit(Command command) {<br>        command.execute();<br>    }</pre><pre>    public static void undo(Command command) {<br>        command.undo();<br>    }<br>}</pre><p>And the client code would be like:</p><pre>AirConditioner airConditioner = new AirConditioner();</pre><pre>Command turnOn = new AirConditionerOn(airConditioner);<br>Command turnOff = new AirConditionerOff(airConditioner);</pre><pre>RemoteControl.<em>submit</em>(turnOn);    // turned air conditioner on<br>RemoteControl.<em>undo</em>(turnOn);      // turned air conditioner off</pre><pre>RemoteControl.<em>submit</em>(turnOn);    // turned air conditioner on<br>RemoteControl.<em>submit</em>(turnOff);   // turned air conditioner off</pre><p><strong>Multiple Commands &amp; Stack</strong></p><p>What if you want to create an app with multiple commands, not just on/off?</p><pre>public class AirConditioner {<br>    private int power;</pre><pre>    void off() {<br>        power = Power.<em>OFF</em>;     // OFF = 0<br>    }</pre><pre>    void low() {<br>        power = Power.<em>LOW</em>;     // LOW = 1<br>    }</pre><pre>    void medium() {<br>        power = Power.<em>MEDIUM</em>;  // MEDIUM = 2<br>    }</pre><pre>    void high() {<br>        power = Power.<em>HIGH</em>;    // HIGH = 3<br>    }<br>}</pre><pre>public interface Command {<br>    void execute();<br>    <br>  <em> // undo is gone from here for now, we&#39;ll see it below later</em></pre><pre>}</pre><pre>public class <strong>AirConditionerOff</strong> implements Command {<br>    private final AirConditioner airConditioner;</pre><pre>    public AirConditionerOff(AirConditioner airConditioner) {<br>        this.airConditioner = airConditioner;<br>    }</pre><pre>    @Override<br>    public void execute() {<br>        <strong>airConditioner.off();</strong><br>    }<br>}</pre><pre>public class <strong>AirConditionerLowPower</strong> implements Command {<br>    private final AirConditioner airConditioner;</pre><pre>    public AirConditionerLowPower(AirConditioner airConditioner) {<br>        this.airConditioner = airConditioner;<br>    }</pre><pre>    @Override<br>    public void execute() {<br>        <strong>airConditioner.low();</strong><br>    }<br>}</pre><pre>public class <strong>AirConditionerMediumPower</strong> implements Command {<br>    private final AirConditioner airConditioner;</pre><pre>    public AirConditionerMediumPower(AirConditioner airConditioner){<br>        this.airConditioner = airConditioner;<br>    }</pre><pre>    @Override<br>    public void execute() {<br>        <strong>airConditioner.medium();</strong><br>    }<br>}</pre><pre>public class <strong>AirConditionerHighPower</strong> implements Command {<br>    private final AirConditioner airConditioner;</pre><pre>    public AirConditionerHighPower(AirConditioner airConditioner){<br>        this.airConditioner = airConditioner;<br>    }</pre><pre>    @Override<br>    public void execute() {<br>        <strong>airConditioner.high();</strong><br>    }<br>}</pre><p>But this time undo operation is a bit more complicated. Since now there are multiple commands, you need to know the exact steps client took.</p><p>To achieve this you can use Stack data structure.</p><pre>public class RemoteControl {</pre><pre>    private RemoteControl() {}</pre><pre>    private static final Stack&lt;Command&gt; undoStack = new Stack&lt;&gt;();<br>    private static final Stack&lt;Command&gt; redoStack = new Stack&lt;&gt;();</pre><pre>    public static void submit(Command command) {<br>        command.execute();</pre><pre>    undoStack.add(command);<br>        redoStack.clear();<br>    }</pre><pre>    public static void undo() {<br>        if (!undoStack.isEmpty()) {<br>            undoStack.peek().execute();<br>            redoStack.add(undoStack.pop());<br>        }<br>    }</pre><pre>    public static void redo() {<br>        if (!redoStack.isEmpty()) {<br>            redoStack.peek().execute();<br>            undoStack.add(redoStack.pop());<br>        }<br>    }<br>}</pre><p>Now we should be able to use multiple commands and also support undo/redo operation. :)</p><p>Let’s see it in client code:</p><pre>AirConditioner airConditioner = new AirConditioner();</pre><pre>Command highPower = new AirConditionerHighPower(airConditioner);<br>Command mediumPower = new AirConditionerMediumPower(airConditioner);<br>Command lowPower = new AirConditionerLowPower(airConditioner);<br>Command off = new AirConditionerOff(airConditioner);</pre><pre>// feel free to apply any creational design pattern above</pre><pre>RemoteControl.<em>submit</em>(highPower);      // air conditioner set HIGH<br>RemoteControl.<em>submit</em>(lowPower);       // air conditioner set LOW<br>RemoteControl.<em>submit</em>(mediumPower);    // air conditioner set MEDIUM</pre><pre>RemoteControl.<em>undo</em>();                 // air conditioner set LOW<br>RemoteControl.<em>undo</em>();                 // air conditioner set HIGH</pre><pre>RemoteControl.<em>redo</em>();                 // air conditioner set LOW</pre><pre>RemoteControl.<em>submit</em>(off);            // air conditioner set OFF</pre><p>It works!</p><p><strong>To read it as a single story: </strong><a href="https://emretanriverdi.medium.com/command-pattern-a-quick-guide-3e618fe82f1c">Command Pattern — A Quick Guide</a> (4 min read)</p><h3>8- Adapter Pattern</h3><blockquote><strong>“Adapter Pattern </strong>converts the interface of a class into another interface the clients expect.<strong> </strong>Adapter<strong> lets classes work together</strong> that couldn’t otherwise because of <strong>incompatible interfaces.”</strong></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*omo70eXsCq0D_SPDAmddaA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@markuswinkler?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Markus Winkler</a> on <a href="https://unsplash.com/s/photos/plug?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Simple Example:<br></strong>Suppose you are traveling from Europe to USA, since there are different outlets being used, you need an adapter/wrapper/converter for you to be able to use your devices.</p><p><strong>Real-Life Example:<br></strong>Suppose you are writing an app and you are using a Kafka client to consume messages from a topic.</p><p>This client has methods called <strong>consume</strong> and <strong>produce</strong> to read and write messages to a Kafka topic and the broker you are listening the topic from has version 1.8.<br>Let’s call this: <em>Client A.</em></p><p>Now you need to listen to an another topic from another broker.<br>This broker has version 2.4 and your Kafka client does not support this version yet. You find another Kafka client to help you.<br>Let’s call this: <em>Client B.</em></p><p>But there is a problem: You wrote all your code according to<em> Client A</em> but <br><em>Client B</em> uses different convention.</p><p>For example, it uses the name<strong> read </strong>instead of <strong>consume </strong>and uses the name <strong>write </strong>instead of<strong> produce.</strong></p><p>You don’t want to migrate all your code to <em>Client B</em>, because you’ve heard that <em>Client A</em> will soon start supporting newer versions and <em>Client B</em> overall uses more memory than <em>Client A</em>.</p><p>Since our code should be<strong> open for extension, but closed for modification,</strong> the best thing to do there is to not touch existing code and just wrap<em> Client A</em>’s code around <em>Client B</em> to work with existing logic.</p><p>There may be lots of other similar scenarios to use Adapter Pattern, it’s a very common need to convert types to each other.</p><h4>Implementation</h4><pre>public class ClientBAdapter extends ClientA {<br>    private final ClientB clientB;</pre><pre>    public ClientBAdapter(ClientB clientB) {<br>        this.clientB = clientB;<br>    }</pre><pre>    @Override<br>    public void consume() {<br>        clientB.read();<br>    }</pre><pre>    @Override<br>    public void produce() {<br>        clientB.write();<br>    }<br>}</pre><p>With this approach, ClientB can easily act like ClientA.</p><pre>ClientB clientB = new ClientB();</pre><pre>clientB.write();<br>clientB.read();</pre><pre>ClientA clientBAdapted = new ClientBAdapter(clientB);<br>// feel free to use a static helper method instead of a constructor</pre><pre>clientBAdapted.consume();<br>clientBAdapted.produce();</pre><p>It works!</p><p>We didn’t change any existing code, just wrote one helper class.<br>Simple and a quick solution. :)</p><blockquote>Facade and Adapter both wrap multiple classes, but a Facade’s intent is to simplify, while an Adapter’s is to convert the interface to something different.</blockquote><p><strong>To read it as a single story: </strong><a href="http://emretanriverdi.medium.com/adapter-pattern-a-quick-guide-3fcd2477eda8">Adapter Pattern — A Quick Guide</a> (2 min read)</p><h3>9- Facade Pattern</h3><blockquote><strong>“Facade Pattern </strong>provides a unified interface that is easier to use for sets of interfaces in a subsytem.”</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ucPTuWA0Bta-dZalerOP4A.png" /><figcaption>Photo by <a href="https://unsplash.com/@yusufevli?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Yusuf Evli</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Simple Example:<br></strong>Suppose you are going to build a house and there are lots of steps to achieve this. You need to build walls and a roof, buy furnitures, paint the walls etc…<br>You may just want to paint the walls as standalone feature in the future,<br>but it would be good to have an all-in-one package for building a house, as we need a complete house right now.</p><p><strong>Real-Life Example:<br></strong>Suppose you are writing an app and you need to make HTTP requests.<br>You need to tweak it with different variations of configurations according to your needs.</p><p>It would be best if you do all the configurations inside a method and just call that method from client code for simplified usage.</p><h4>Implementation</h4><pre>public class HttpClientFacade {<br>    private final HttpClient httpClient;</pre><pre>    public HttpClientFacade(HttpClient httpClient) {<br>        this.httpClient = httpClient;<br>    }</pre><pre>    public JsonObject getRequest(String url, String agentName) {<br>        httpClient.setConnectTimeout(5000);<br>        httpClient.expectCompression(true);<br>        httpClient.setHeader(&quot;agentname&quot;, agentName);<br>        //...<br>        //...<br>        return httpClient.get(url);<br>    }<br>}</pre><p>When you need to add/remove a property during GET request, you just need to implement it into this method and it’ll be a quick and an easy change.<br>Other parts of the code don’t need to know the details of <strong>getRequest.</strong></p><p>And the client code will be like:</p><pre>HttpClient httpClient = new HttpClient();<br>HttpClientFacade httpClientFacade =<br>new HttpClientFacade(httpClient);</pre><pre>httpClientFacade.getRequest(&quot;emretanriverdi.medium.com&quot;, &quot;itsme&quot;);</pre><blockquote>Facade and Adapter both wrap multiple classes, but a Facade’s intent is to simplify, while an Adapter’s is to convert the interface to something different.</blockquote><p><strong>To read it as a single story: </strong><a href="http://emretanriverdi.medium.com/facade-pattern-a-quick-guide-b1f2277f9e52">Facade Pattern — A Quick Guide</a> (2 min read)</p><h3>10- Chain of Responsibility Pattern</h3><blockquote><strong>“Chain of Responsibility</strong> <strong>Pattern</strong> lets you pass requests along a chain of handlers. Upon receiving a request, each handler decides either to process the request or to pass it to the <strong>next handler in the chain.”</strong></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kepM5YzK3Qi6NrBRp5kyDw.png" /><figcaption>Photo by <a href="https://unsplash.com/@kwhatswong?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Keith Wong</a> on <a href="https://unsplash.com/s/photos/chain?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Simple Example:<br></strong>Suppose you want to play a video game on your computer and the game is trying to choose the optimal settings based on your GPU.</p><p>It checks if your GPU can handle Ultra, if not;<br>it checks if your GPU can handle High, if not;<br>it checks if your GPU can handle Medium.<br>And if you are lucky enough, it stops there.</p><p>If your GPU still isn’t enough, it checks if you can handle Low,<br>then Ultra Low (if the game has this option).</p><p>If your GPU still isn’t enough, the game simply won’t work on your computer.</p><p><strong>Chain of Responsibility</strong> <strong>Pattern</strong> is actually as simple as this.</p><p><strong>Real-Life Example:</strong></p><p>Up until now you must have realized this is all bunch of <strong>if</strong> &amp; <strong>else if</strong> statements.</p><pre>public void initialize(VisualEntity visualEntity,<br>                       FrameRequest frameRequest) {<br>    <br>    initializeCommonFields(visualEntity, frameRequest);</pre><pre>    if (frameRequest.isCircle()) {<br>        // initialize circle<br>    } else if (frameRequest.isSquare()) {<br>        // initialize square<br>    } else if (frameRequest.isRectangle()) {<br>        // initialize rectangle<br>    } else throw new UnsupportedOperationException(&quot;message&quot;);<br>}</pre><p>Let’s say you have a code block like this where you let your client choose a frame for their photo.</p><p>Available paths are:</p><p>Your client chooses Circle,<br>Code checks if it’s circle,<br>Code initializes Circle.</p><p>Your client chooses Square,<br>Code checks if it’s circle,<br>Code checks if it’s square,<br>Code initializes Square.</p><p>Your client chooses Rectangle,<br>Code checks if it’s circle,<br>Code checks if it’s square,<br>Code checks if it’s rectangle,<br>Code initializes Rectangle.</p><p>Your client chooses Triangle (which doesn’t exist in our app),<br>Code checks if it’s circle,<br>Code checks if it’s square,<br>Code checks if it’s rectangle,<br>Code throws exception.</p><p>But I believe we can agree that all these<strong> if blocks </strong>don’t look very beautiful and if one day you want to add Triangle to your available frames, or maybe a Heart symbol for couples, the code block would get even larger.</p><p>So let’s try a different design with Chain of Responsibility!</p><h4>Implementation</h4><pre>public abstract class InitializerSelector {<br>    private InitializerSelector successor;</pre><pre>    abstract void initialize(VisualEntity visualEntity,<br>                             FrameRequest frameRequest);</pre><pre>    public InitializerSelector getSuccessor() {<br>        return successor;<br>    }</pre><pre>    public void setSuccessor(InitializerSelector successor) {<br>        this.successor = successor;<br>    }<br>}</pre><pre>public class <strong>CircleInitializer</strong> extends InitializerSelector {</pre><pre>    public CircleInitializer(SquareInitializer squareInitializer) {<br>        <strong>setSuccessor(squareInitializer);</strong><br>    }</pre><pre>    @Override<br>    public void initialize(VisualEntity visualEntity,<br>                           FrameRequest frameRequest) {<br>        if (frameRequest.isCircle()) {<br>            // initialize circle<br>        } else {<br>            <strong>getSuccessor().initialize(visualEntity, frameRequest);</strong><br>        }<br>    }<br>}</pre><pre>public class <strong>SquareInitializer</strong> extends InitializerSelector {</pre><pre>    public SquareInitializer(RectangleInitializer<br>                             rectangleInitializer) {<br>        <strong>setSuccessor(rectangleInitializer);</strong><br>    }</pre><pre>    @Override<br>    public void initialize(VisualEntity visualEntity,<br>                           FrameRequest frameRequest) {<br>        if (frameRequest.isSquare()) {<br>            // initialize square<br>        } else {<br>            <strong>getSuccessor().initialize(visualEntity, frameRequest);</strong><br>        }<br>    }<br>}</pre><pre>public class <strong>RectangleInitializer</strong> extends InitializerSelector {<br>    @Override<br>    public void initialize(VisualEntity visualEntity,<br>                           FrameRequest frameRequest) {<br>        if (frameRequest.isRectangle()) {<br>            // initialize rectangle<br>        } else {<br>            <strong>throw new UnsupportedOperationException(&quot;message&quot;);</strong><br>        }<br>    }<br>}</pre><p>If one day you need to add TriangleInitializer, you can add it as a successor of RectangleInitializer and move the Exception to TriangleInitializer.</p><p>And the client code would be like:</p><pre>public void initialize(VisualEntity visualEntity,<br>                       FrameRequest frameRequest) {<br>    initializeCommonFields(visualEntity, frameRequest);<br>    <strong>circleInitializer</strong>.initialize(visualEntity, frameRequest);<br>}</pre><p>You can finalize the client code by changing the initial call from circleInitializer to something more abstract, to not reveal logic to client code. You can create a new class which will start the flow by calling CircleInitializer.</p><pre>public void initialize(VisualEntity visualEntity,<br>                       FrameRequest frameRequest) {<br>    initializeCommonFields(visualEntity, frameRequest);<br>    <strong>frameInitializer</strong>.initialize(visualEntity, frameRequest);<br>}</pre><p>Voila!</p><blockquote>There are many other ways to implement the Chain of Responsibility Pattern and Spring has its own built-in way to implement it even easier, feel free to use different approaches based on your situation (and framework choice).</blockquote><p><strong>To read it as a single story:<br></strong><a href="https://emretanriverdi.medium.com/chain-of-responsibility-pattern-a-quick-guide-86b04bdbbba8">Chain of Responsibility Pattern — A Quick Guide</a> (3 min read)</p><h3>11- Template Method Pattern</h3><blockquote><strong>“Template Method Pattern</strong> defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm <strong>without changing the algorithm’s structure.”</strong></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I1rVcixndprNMiFXx5zerw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@mildlee?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Mildlee</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Example:</strong></p><p>Let’s say you have an application that helps you deploy your applications to Staging or Production Environments, like this:</p><pre>public class <strong>StagingDeploy</strong> {<br>    <br>    public void deploy() {<br>        runUnitTests();<br>        pushSemanticVersioningTag();<br>        pushTaggedImage();<br>        saveImageToRegistryAsBackup();<br>    }</pre><pre>    void runUnitTests() {<br>        // implementation for unit tests<br>    }</pre><pre>    void pushSemanticVersioningTag() {<br>        // implementation for semantic versioning<br>    }</pre><pre>    void pushTaggedImageToStaging() {<br>       // implementation for pushing tagged image to staging<br>    }<br>    <br>    void saveImageToRegistryAsBackup() {<br>       // implementation for saving image as backup<br>    }<br>}</pre><pre>public class <strong>ProductionDeploy</strong> {<br>    <br>    public void deploy() {<br>        runSmokeTests();<br>        pushReleaseTag();<br>        pushTaggedImage();<br>        saveImageToRegistryAsBackup();<br>    }</pre><pre>    void runSmokeTests() {<br>        // implementation for smoke tests<br>    }</pre><pre>    void pushReleaseTag() {<br>        // implementation for release versioning<br>    }</pre><pre>    void pushTaggedImageToProduction() {<br>        // implementation for pushing tagged image to production<br>    }</pre><pre>    void saveImageToRegistryAsBackup() {<br>        // implementation for saving image as backup<br>    }<br>}</pre><p>There are clear similarities between Staging and Production deploys, so you can create a <strong>template </strong>for both of them to use.</p><h4>Implementation</h4><pre>public <strong>abstract</strong> <strong>class</strong> <strong>Deploy</strong> {<br>    <br>    public void final deploy() {<br>        runTests();<br>        pushTag();<br>        pushTaggedImage();<br>        saveImage();<br>    }</pre><pre>    abstract void runTests();</pre><pre>    abstract void pushTag();</pre><pre>    abstract void pushTaggedImage();</pre><pre>    abstract void saveImage();<br>}</pre><p>and now you can extend it like this:</p><pre>public class <strong>StagingDeploy extends Deploy </strong>{</pre><pre>    @Override<br>    void runTests() {<br>        // implementation for unit tests<br>    }</pre><pre>    @Override<br>    void pushTag() {<br>        // implementation for semantic versioning<br>    }</pre><pre>    @Override<br>    void pushTaggedImage() {<br>        // implementation for pushing tagged image to staging<br>    }</pre><pre>    @Override<br>    void saveImage() {<br>        // implementation for saving image as backup<br>    }<br>}</pre><pre>public class <strong>ProductionDeploy extends Deploy</strong> {</pre><pre>    @Override<br>    void runTests() {<br>        // implementation for smoke tests<br>    }</pre><pre>    @Override<br>    void pushTag() {<br>        // implementation for release versioning<br>    }</pre><pre>    @Override<br>    void pushTaggedImage() {<br>        // implementation for pushing tagged image to production<br>    }</pre><pre>    @Override<br>    void saveImage() {<br>        // implementation for saving image as backup<br>    }<br>}</pre><p>And the client code would be like:</p><pre>StagingDeploy stagingDeploy = new StagingDeploy();<br>stagingDeploy.deploy();</pre><pre>ProductionDeploy productionDeploy = new ProductionDeploy();<br>productionDeploy.deploy();</pre><p>For this case, you may have realized <em>saveImage() </em>method is the same for both classes. So you can change the code like this:</p><pre>public <strong>abstract</strong> <strong>class</strong> <strong>Deploy</strong> {<br>    <br>    public void final deploy() {<br>        runTests();<br>        pushTag();<br>        pushTaggedImage();<br>        saveImage();<br>    }</pre><pre>    abstract void runTests();</pre><pre>    abstract void pushTag();</pre><pre>    abstract void pushTaggedImage();</pre><pre>    void saveImage() {<br>        // implementation for saving image as backup<br>    }</pre><pre>}</pre><pre>public class <strong>StagingDeploy extends Deploy </strong>{</pre><pre>    @Override<br>    void runTests() {<br>        // implementation for unit tests<br>    }</pre><pre>    @Override<br>    void pushTag() {<br>        // implementation for semantic versioning<br>    }</pre><pre>    @Override<br>    void pushTaggedImage() {<br>        // implementation for pushing tagged image to staging<br>    }<br>}</pre><pre>public class <strong>ProductionDeploy extends Deploy</strong> {</pre><pre>    @Override<br>    void runTests() {<br>        // implementation for smoke tests<br>    }</pre><pre>    @Override<br>    void pushTag() {<br>        // implementation for release versioning<br>    }</pre><pre>    @Override<br>    void pushTaggedImage() {<br>        // implementation for pushing tagged image to production<br>    }<br>}</pre><h4>Hooks</h4><p>There is also another concept called Hooks.<br>Hooks are methods in abstract classes that can be overriden, but not have to.</p><p>Suppose you want to add “performance tests” step to our <strong>template</strong> but you don’t want it to run in Staging and Production environments.</p><p>Let’s say you now have a new environment that crucial apps work and you want to make sure the applications deployed here runs faster than 2ms.</p><pre>public <strong>abstract</strong> <strong>class</strong> <strong>Deploy</strong> {<br>    <br>    public void final deploy() {<br>        runPerformanceTests();<br>        runTests();<br>        pushTag();<br>        pushTaggedImage();<br>        saveImage();<br>    }</pre><pre><strong>    void runPerformanceTests() {<br>        // empty<br>    }</strong></pre><pre>    abstract void runTests();</pre><pre>    abstract void pushTag();</pre><pre>    abstract void pushTaggedImage();</pre><pre>    void saveImage() {<br>        // implementation for saving image as backup<br>    }<br>}</pre><pre>public class <strong>StagingDeploy extends Deploy </strong>{</pre><pre>    @Override<br>    void runTests() {<br>        // implementation for unit tests<br>    }</pre><pre>    @Override<br>    void pushTag() {<br>        // implementation for semantic versioning<br>    }</pre><pre>    @Override<br>    void pushTaggedImage() {<br>        // implementation for pushing tagged image to staging<br>    }<br>}</pre><pre>public class <strong>ProductionDeploy extends Deploy</strong> {</pre><pre>    @Override<br>    void runTests() {<br>        // implementation for smoke tests<br>    }</pre><pre>    @Override<br>    void pushTag() {<br>        // implementation for release versioning<br>    }</pre><pre>    @Override<br>    void pushTaggedImage() {<br>        // implementation for pushing tagged image to production<br>    }<br>}</pre><pre>public class <strong>NewProductionDeploy extends Deploy</strong> {</pre><pre><strong>    @Override</strong><br>    <strong>void runPerformanceTests() {<br>        // implementation for performance tests<br>    }</strong></pre><pre>    @Override<br>    void runTests() {<br>        // implementation for both unit &amp; smoke tests<br>    }</pre><pre>    @Override<br>    void pushTag() {<br>        // implementation for release versioning<br>    }</pre><pre>    @Override<br>    void pushTaggedImage() {<br>        // implementation for pushing tagged image to new production<br>    }<br>}</pre><p><strong>Hooks:</strong> You CAN override the method to add behavior, but you don’t have to.<br><strong>Abstract Methods: </strong>You MUST override the method.</p><h4>Things to Consider</h4><p>While Template Method Pattern is great and widely being used (sometimes without even realizing), we should think twice before using it:</p><p><strong>1. Always favor composition over inheritance.</strong><br>Before using Template Method Pattern, check if Strategy Pattern could be a better fit. Template Method Pattern works at the class level, so it’s a bit more static. Strategy Pattern works on the object level, letting you switch behaviors at runtime.</p><p><strong>2. Be aware that you may violate the Liskov Substitution Principle.<br></strong>LSP basically says that objects of a superclass should be replaceable with objects of its subclasses without breaking the application. While it sounds easy, as the application gets larger in the future, we may unknowingly modify the template to not be suitable for all subclasses.</p><p><strong>3. Be aware that you may violate the Open-Closed Principle.<br></strong>OCD basically says that classes should be open for extension, but closed for modification. As classes get larger, maintaining the template for each class becomes a problem and instead of classes adapting themselves to the template, things turn around and template starts to adapt itself to classes.</p><p><strong>To read it as a single story:<br></strong><a href="https://emretanriverdi.medium.com/template-method-pattern-a-quick-guide-f734bd9385a5">Template Method Pattern — A Quick Guide</a> (4 min read)</p><p><strong>Note:<br></strong>This story is a work in progress and will continue with the following design patterns over time:</p><p>12. Bridge Pattern<br>13. Iterator Pattern<br>14. Composite Pattern<br>15. State Pattern<br>16. Proxy Pattern<br>17. Prototype Pattern<br>18. Memento Pattern</p><blockquote>Thank you for reading!</blockquote><p><strong>Reference(s)</strong></p><ul><li>Head First Design Patterns. by Eric Freeman, Elisabeth Robson, Bert Bates, Kathy Sierra. Released October 2004. Publisher(s): O’Reilly Media, Inc.</li><li>Dive into Design Patterns. by Alexander Shvets, Released 2019.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b2699315961f" width="1" height="1" alt=""><hr><p><a href="https://betterprogramming.pub/design-patterns-a-complete-guide-b2699315961f">A Complete Guide to Design Patterns</a> was originally published in <a href="https://betterprogramming.pub">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>


guid: https://medium.com/p/fa48b05a1f5
title: 3 Steps To Forge Your Perfect Job Environment
author: Andreas D.
feedurl: https://medium.com/feed/better-programming
url:
https://betterprogramming.pub/3-steps-to-forge-your-perfect-job-environment-fa48b05a1f5?source=rss----d0b105d10f0a---4

content:
<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://betterprogramming.pub/3-steps-to-forge-your-perfect-job-environment-fa48b05a1f5?source=rss----d0b105d10f0a---4"><img src="https://cdn-images-1.medium.com/max/2600/0*e72ziq0s1OJhiDtM" width="4240"></a></p><p class="medium-feed-snippet">A systematic way to discover your needs and derive a plan to satisfy them</p><p class="medium-feed-link"><a href="https://betterprogramming.pub/3-steps-to-forge-your-perfect-job-environment-fa48b05a1f5?source=rss----d0b105d10f0a---4">Continue reading on Better Programming »</a></p></div>


guid: https://medium.com/p/f3e984fa49e2
title: My Favorite Coding Interview Task for Frontend Developers
author: Edgar Abgaryan
feedurl: https://medium.com/feed/better-programming
content_mime_type: text/html
url:
https://betterprogramming.pub/my-favorite-coding-interview-task-for-frontened-developers-f3e984fa49e2?source=rss----d0b105d10f0a---4

content:
<h4>Display the actual value of the vertical scroll of the window</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UHG3_V_EYGcPz2h6v5PieQ.jpeg" /></figure><p>A year ago my company first asked me to do a front-end interview. Then I came up with this task for my own topicality.</p><p>The task is simple and checks basic knowledge. But, as it turned out, many interesting mistakes can be made in it. It also contains non-obvious details that might be interesting to experienced developers too.</p><p>I decided to analyze the task in great detail in this article for pedagogical purposes. This post is primarily aimed at new react developers.</p><h3>Statement of the Problem</h3><p>There is a component implementation that requires two things:</p><ol><li>display the actual value of the vertical scroll of the window (window.scrollY)</li><li>after mounting, asynchronously receive a number and display it</li></ol><p>Find, explain and fix as many implementation issues as possible.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d97b8fb0665be641c93b72ac52c711a2/href">https://medium.com/media/d97b8fb0665be641c93b72ac52c711a2/href</a></iframe><p>I highly recommend fixing everything you find yourself before reading further.</p><h3>First things first</h3><p>The first thing that everyone correctly notes is that useEffect has no second argument.</p><p>There should be an empty array of dependencies, because we only need to get the <em>number </em>from the “server” once when mounting. And it makes no sense to re-subscribe to the scroll event repeatedly.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d2f012ff44221010bdc2e8506e750e94/href">https://medium.com/media/d2f012ff44221010bdc2e8506e750e94/href</a></iframe><p>A common mistake is passing an array of dependencies like this: [scroll]. If you also have made that mistake, then go back to the code and make sure that you don’t need the current scroll value in order to update it.</p><p>The second thing that is usually noticed is the async keyword in the callback. Usually, candidates had personal experience of writing in this way. So, they know that it cannot be done in this way. But why? This question baffles someone.</p><p>According to the react documentation, the callback should either return nothing (undefined) or return a cleanup function. That is, there are only 2 valid values ​​to return: undefined<em> </em>and function. But, of course, you know that async<em> </em>functions always return a promise<em>.</em> That is, in the current implementation, the callback does not return a cleanup function, but returns the <em>promise </em>of that function.</p><p>We need to remove the async<em> </em>keyword and redo the callback to work. Some beginners have had problems with it. The simplest is to write with promise:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cc434a938264a3f0488cf449f422d607/href">https://medium.com/media/cc434a938264a3f0488cf449f422d607/href</a></iframe><p>If you have written fetchRandomNumber().then(num =&gt; setNumber(num)), take a minute to realize that fetchRandomNumber().then(setNumber)<em> </em>does the same thing, but shorter and more optimal.</p><p>The last blunder is that the scroll listener is not cleared anyway. I will try to give my own analogy to explain the error. Let’s say you bought a new phone. You set an alarm on it at 5 a.m. to get up for a run along the waterfront. Then you changed your mind.</p><p>But instead of turning off the alarm on your new phone, you go back to the store, buy another phone of the same model, open the alarm settings in it and turn everything off at 5 a.m. (however, there is nothing to turn off there).</p><p>Both phones are absolutely identical and there are practically no visible differences, but they are still different phones. In the implemented code the same nonsense is written. Every time we write the expression () =&gt; setScroll(window.scrollY), we create a new function. Often this problem was solved in a some strange way:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d40155be4e9317afa4a7f60956f25062/href">https://medium.com/media/d40155be4e9317afa4a7f60956f25062/href</a></iframe><p>This works, but the problem is that the handleScroll<em> </em>will be<em> </em>created for each render of the component but will be used in the useEffect callback only. So, it will be used only on first render. So, extra work is done and the code is more scattered.</p><p>A more correct way could look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/155e2ef36c25e65d5658c09fe21c6dbb/href">https://medium.com/media/155e2ef36c25e65d5658c09fe21c6dbb/href</a></iframe><h3>Less Important Issues</h3><p>Another point that I ask candidates to pay attention to is the initial values of the states. Juniors often write this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/057dde536602156e48c4b3944165dbb3/href">https://medium.com/media/057dde536602156e48c4b3944165dbb3/href</a></iframe><p>There are people who think that the initial value is mandatory. And if this is a number, then for sure 0<strong><em> </em></strong>is best choise. But in this case we can’t give the number var<em> </em>an adequate initial value and it is better to leave it undefined.</p><p>For the scroll variable, the initial value of 0 is incorrect, because our component can appear when the browser page has already scrolled down. The expected code is:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/787226aef5ba607dc2100f8cf6c28d89/href">https://medium.com/media/787226aef5ba607dc2100f8cf6c28d89/href</a></iframe><p>Here is quite decent code. At this point I usually move on to the next task in the interview. But if the candidate is doing well, I suggest them to think a little more about the code snippet.</p><p>It is a plus for the candidate if he knows what <a href="https://lodash.com/docs/4.17.15#throttle">throttling</a> is and applies it correctly. For example like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cfc22785cb1ecd3cbef993eaa8174585/href">https://medium.com/media/cfc22785cb1ecd3cbef993eaa8174585/href</a></iframe><p>A good question here is why 37ms. The value of the variable can be more meaningful. For example, we can set throttleWait = 1000/60<strong><em> </em></strong>because we want 60 <a href="https://en.wikipedia.org/wiki/Frame_rate">FPS</a>. But really advanced solution in terms of FPS is using <em>requestAnimationFrame </em>instead of <em>throttle.</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e36b6951369fa78c9828f6345525347e/href">https://medium.com/media/e36b6951369fa78c9828f6345525347e/href</a></iframe><p>Another thing I’d like to see is the application of the <a href="https://en.wikipedia.org/wiki/Single-responsibility_principle">Single-responsibility principle</a> to <em>useEffect</em>. Now same <em>useEffect </em>is responsible for both the asynchronous number retrieval logic and the scrolling logic. The result might look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4571f94e5502f1fa5327a0b91bf1b87a/href">https://medium.com/media/4571f94e5502f1fa5327a0b91bf1b87a/href</a></iframe><p>This code will run subtly slower, but it will be much easier to read and change over time. In addition, after this step, it is much easier to see a custom hook to extract for the same purposes:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7889d3d263f6e28611210102586fc06b/href">https://medium.com/media/7889d3d263f6e28611210102586fc06b/href</a></iframe><p>Have you ever seen such a warning in your console?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*11JX9SVS96aPwbrWPueMwQ.png" /></figure><p>In most cases that warning is completely harmless but annoying. To remove it you should be sure your component isn’t unmounted before call setState. Example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/37a35c6809965c9617aea25529b6d674/href">https://medium.com/media/37a35c6809965c9617aea25529b6d674/href</a></iframe><h4>SSR problem</h4><p>In this code, we are using window<em> </em>object. But the Node.js<em> </em>envirement doesn’t have a window<em> </em>object. Our code should be <a href="https://www.lullabot.com/articles/what-is-an-isomorphic-application"><em>isomorphic</em></a> if we want to use SSR.</p><h3>Unobvious</h3><p>There is such thing in JS that is rarely used in everyday work — <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">descriptors</a>. You can make it so that when you get a property from an object, a getter function will be called and the result of this call will be returned.</p><p>The Object.getOwnPropertyDescriptor function can show you if an object property is regular or tricky defined with descriptors. So if you run Object.getOwnPropertyDescriptor (window, ‘scrollY’);<strong><em> </em></strong>in the console, you will find that the scrollY property has a setter and a getter</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vfOx_vhLXgD5cLWaN1JfWA.png" /></figure><p>So, when we write window.scrollY, we add this getter function to the <a href="http://latentflip.com/loupe/">call stack</a>. So, if we write useState(() =&gt; window.scrollY)<em> </em>instead of useState(window.scrollY) then for each render there will be one less function on the call stack (if you pass a function to useState, it will be called only during the first render and the initial value will be the result of this call).</p><p>Optimization! In fact, such optimization doesn’t provide any practical benefit. But it seems to me that the important thing here is the awareness of these processes, the conscious writing of each line of code. Another reason to pass function into useState is that every <a href="https://gist.github.com/paulirish/5d52fb081b3570c81e3a/565c05680b27c9cfd9f5e971d295cd558c3e1843">window.scrollY<strong><em> </em></strong>will trigger reflow</a>. The final code will look something like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/947c6dda3e205477aed19acf280948f8/href">https://medium.com/media/947c6dda3e205477aed19acf280948f8/href</a></iframe><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodesandbox.io%2Fembed%2Fwk5gu&amp;display_name=CodeSandbox&amp;url=https%3A%2F%2Fcodesandbox.io%2Fs%2Fwk5gu&amp;image=https%3A%2F%2Fcodesandbox.io%2Fapi%2Fv1%2Fsandboxes%2Fwk5gu%2Fscreenshot.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codesandbox" width="1000" height="500" frameborder="0" scrolling="no"><a href="https://medium.com/media/27569f0d722faf6909d6215be01f9422/href">https://medium.com/media/27569f0d722faf6909d6215be01f9422/href</a></iframe><h3>Bonus Exercise</h3><p>For those who like to wiggle their brains once again, I propose to figure out how to benchmark the “optimization” from the previous section. I have never written such synthetic tests before but for a comprehensive article, I set myself this goal and this is what came out:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodesandbox.io%2Fembed%2Fg34e1&amp;display_name=CodeSandbox&amp;url=https%3A%2F%2Fcodesandbox.io%2Fs%2Fg34e1&amp;image=https%3A%2F%2Fcodesandbox.io%2Fapi%2Fv1%2Fsandboxes%2Fg34e1%2Fscreenshot.png&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codesandbox" width="1000" height="500" frameborder="0" scrolling="no"><a href="https://medium.com/media/35a9ef715b1e79e44a56caf7f779ce34/href">https://medium.com/media/35a9ef715b1e79e44a56caf7f779ce34/href</a></iframe><p>My laptop makes 20,000 component renders in ~ 3500ms (for useState (window.scrollY)) and ~ 3300ms (for useState (() =&gt; window.scrollY))</p><p>I find it fascinating how deep we can dive into such a simple task. Thanks for reading.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f3e984fa49e2" width="1" height="1" alt=""><hr><p><a href="https://betterprogramming.pub/my-favorite-coding-interview-task-for-frontened-developers-f3e984fa49e2">My Favorite Coding Interview Task for Frontend Developers</a> was originally published in <a href="https://betterprogramming.pub">Better Programming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>


guid: https://medium.com/p/3c7cf44ad6fe
title: Everything You Need to Know About Databases in Flask
author: Esther Vaati
feedurl: https://medium.com/feed/better-programming
url:
https://betterprogramming.pub/everything-you-need-to-know-about-databases-in-flask-3c7cf44ad6fe?source=rss----d0b105d10f0a---4

content:
<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://betterprogramming.pub/everything-you-need-to-know-about-databases-in-flask-3c7cf44ad6fe?source=rss----d0b105d10f0a---4"><img src="https://cdn-images-1.medium.com/max/2600/1*jxyqXlAsH2ky6xPDfJVNsg.jpeg" width="6000"></a></p><p class="medium-feed-snippet">Add functionality to your Flask apps with databases</p><p class="medium-feed-link"><a href="https://betterprogramming.pub/everything-you-need-to-know-about-databases-in-flask-3c7cf44ad6fe?source=rss----d0b105d10f0a---4">Continue reading on Better Programming »</a></p></div>


guid: https://medium.com/p/60a76be88bb5
title: Build a Sliding Puzzle Game With SwiftUI
author: Mark Lucking
feedurl: https://medium.com/feed/better-programming
url:
https://betterprogramming.pub/build-a-sliding-puzzle-game-with-swiftui-60a76be88bb5?source=rss----d0b105d10f0a---4

content:
<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://betterprogramming.pub/build-a-sliding-puzzle-game-with-swiftui-60a76be88bb5?source=rss----d0b105d10f0a---4"><img src="https://cdn-images-1.medium.com/max/839/1*YpXeqpY0n62fCS0H-3gbUw.png" width="839"></a></p><p class="medium-feed-snippet">Puzzle 9 using alignment and matchedGeometry</p><p class="medium-feed-link"><a href="https://betterprogramming.pub/build-a-sliding-puzzle-game-with-swiftui-60a76be88bb5?source=rss----d0b105d10f0a---4">Continue reading on Better Programming »</a></p></div>


guid: https://medium.com/p/ee38532db51b
title: 5 Non-Technical Developer Skills to Take Your Career to the Next Level
author: Nick McHenry
feedurl: https://medium.com/feed/better-programming
url:
https://betterprogramming.pub/5-non-technical-developer-skills-to-take-your-career-to-the-next-level-ee38532db51b?source=rss----d0b105d10f0a---4

content:
<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://betterprogramming.pub/5-non-technical-developer-skills-to-take-your-career-to-the-next-level-ee38532db51b?source=rss----d0b105d10f0a---4"><img src="https://cdn-images-1.medium.com/max/2600/0*pHeCkXrwRWNxU-vY" width="3936"></a></p><p class="medium-feed-snippet">Writing great code is just the beginning</p><p class="medium-feed-link"><a href="https://betterprogramming.pub/5-non-technical-developer-skills-to-take-your-career-to-the-next-level-ee38532db51b?source=rss----d0b105d10f0a---4">Continue reading on Better Programming »</a></p></div>


guid: https://medium.com/p/4d025baa3dc6
title: Writing High Order Functions for General Process Like a Senior JavaScript Developer
author: bytefish
feedurl: https://medium.com/feed/better-programming
url:
https://betterprogramming.pub/writing-high-order-functions-for-general-process-like-a-senior-javascript-developer-4d025baa3dc6?source=rss----d0b105d10f0a---4

content:
<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://betterprogramming.pub/writing-high-order-functions-for-general-process-like-a-senior-javascript-developer-4d025baa3dc6?source=rss----d0b105d10f0a---4"><img src="https://cdn-images-1.medium.com/max/2600/1*Wz8_k3T3DkKhTwlmbgR-gw.png" width="3106"></a></p><p class="medium-feed-snippet">The power of functional programming</p><p class="medium-feed-link"><a href="https://betterprogramming.pub/writing-high-order-functions-for-general-process-like-a-senior-javascript-developer-4d025baa3dc6?source=rss----d0b105d10f0a---4">Continue reading on Better Programming »</a></p></div>


guid: https://protesilaos.com/codelog/2020-09-05-emacs-note-mixed-font-heights/
title: Emacs: note on mixed font heights
url: https://protesilaos.com/codelog/2020-09-05-emacs-note-mixed-font-heights/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>In a recent entry on <a href="https://protesilaos.com/codelog/2020-07-17-emacs-mixed-fonts-org/">configuring mixed
fonts</a>,
I outlined how to specify your typefaces of choice by configuring the
<code>default</code>, <code>variable-pitch</code>, and <code>fixed-pitch</code> faces.  This would allow
you to benefit from variegated typography, such as having paragraph text
rendered in a proportionately spaced font, while inline code is
displayed as monospaced.</p>

<p>The overall approach of controlling the three basic faces is fine, but
the code I shared had the unintended consequence of breaking the
built-in <code>text-scale-adjust</code> command (by default bound to <code>C-x C-+</code>,
<code>C-x C--</code>, <code>C-x C-0</code>).  Here I issue a corrective to the technique that
was used before.</p>

<h2>The code that breaks ‘text-scale-adjust’</h2>

<p>This is the gist of what I was using for several months:</p>

<pre><code class="language-elisp">(set-face-attribute 'default nil :font "Hack-16")
(set-face-attribute 'fixed-pitch nil :font "Hack-16")
(set-face-attribute 'variable-pitch nil :font "FiraGO-16")
</code></pre>

<p>A variant of the above can be expressed as follows:</p>

<pre><code class="language-elisp">(set-face-attribute 'default nil :family "Hack" :height 160)
(set-face-attribute 'fixed-pitch nil :family "Hack" :height 160)
(set-face-attribute 'variable-pitch nil :family "FiraGO" :height 160)
</code></pre>

<p>If you set fonts this way and try to use <code>text-scale-adjust</code> in a buffer
with mixed fonts, you will notice that only the main text, affected by
the <code>default</code> face, gets scaled.  The rest retain their height—not good.</p>

<p>This is because of a hard-wired assumption in the <code>text-scale-adjust</code>
command to only target the <code>default</code> face: <code>variable-pitch</code> and
<code>fixed-pitch</code> remain in tact, thus breaking our expectations.</p>

<p>The problem consists in the fact that we are specifying an absolute size
for each font family.  Whereas we should be benefiting from relative
sizes that all have a single point of reference, which is easy to do.</p>

<h2>The recommended way to set font heights with faces</h2>

<p>Let us re-purpose the sample code from the previous section, in order to
get the behaviour we expect out of <code>text-scale-adjust</code>.</p>

<pre><code class="language-elisp">(set-face-attribute 'default nil :font "Hack-16")
(set-face-attribute 'fixed-pitch nil :family "Hack" :height 1.0)
(set-face-attribute 'variable-pitch nil :family "FiraGO" :height 1.0)
</code></pre>

<p>A alternative to the above is this:</p>

<pre><code class="language-elisp">(set-face-attribute 'default nil :family "Hack" :height 160)
(set-face-attribute 'fixed-pitch nil :family "Hack")
(set-face-attribute 'variable-pitch nil :family "FiraGO")
</code></pre>

<p>Notice that we set an absolute point size only for the <code>default</code> face.
While we instruct Emacs to interpret the height of <code>fixed-pitch</code> and
<code>variable-pitch</code> as relative to that constant.  Therein lies the
difference between integer and floating point values for the <code>:height</code>
attribute (remember to consult <code>C-h f set-face-attribute</code>).</p>

<p>Strictly speaking, the <code>:height 1.0</code> is not necessary, unless you are
overriding a prior state.  It is what applies when the specification is
omitted.  Rendering it explicit here helps us spot the subtleties in
notation and be clear about what is at play.</p>

<h2>Details are tricky</h2>

<p>I was using the old technique for several months, adjusting fonts
through a bespoke function of mine that altered their absolute sizes.
What inspired me to investigate and eventually address this issue is a
particular statement in the doc string of <code>set-face-attribute</code>:</p>

<blockquote>
  <p>Note that for the ‘default’ face, you must specify an absolute height
(since there is nothing for it to be relative to).</p>
</blockquote>

<p>Which implied that if the <code>default</code> was a constant, all other faces
could simply have a relative height.  This is because of the peculiar
nature of that face to serve as the foundation upon which all others are
established.  As such, a <code>:height</code> with a floating point is a multiple
of the <code>default</code> font size.  Simple and effective!</p>

<p>I am now happily using <code>text-scale-adjust</code> in tandem with the tools I
mentioned in my recent video about <a href="https://protesilaos.com/codelog/2020-07-16-emacs-focused-editing/">“Focused editing” for
Emacs</a>.</p>

<p>This information is also documented in the <a href="https://protesilaos.com/emacs/modus-themes/">official manual of the Modus
themes</a> because they are designed
to cope well with mixed font scenaria, such as when the user decides to
enable the built-in <code>variable-pitch-mode</code>.</p>
        
      


guid: https://protesilaos.com/codelog/2020-09-11-emacs-elfeed-bongo/
title: Manage podcasts in Emacs with Elfeed and Bongo
url: https://protesilaos.com/codelog/2020-09-11-emacs-elfeed-bongo/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=EWApxQd1sYI">https://www.youtube.com/watch?v=EWApxQd1sYI</a></p>
         
         <p>In this video I demonstrate how I combine Elfeed and Bongo into a
workflow for storing and playing content from my multimedia feeds
(podcasts and videos).  The implementation is fairly straightforward and
the overall result is quite effective, based on my expectations.</p>

<p>On a more general note, this shows yet again how integration between
various otherwise standalone tools is one of Emacs’ greatest strengths.</p>

<p>To understand how I use Elfeed and Bongo separately, you can watch my
recent videos:</p>

<ul>
  <li>Bongo and my extras: <a href="https://protesilaos.com/codelog/2020-08-06-emacs-bongo-extras/">https://protesilaos.com/codelog/2020-08-06-emacs-bongo-extras/</a></li>
  <li>Elfeed and my extras: <a href="https://protesilaos.com/codelog/2020-06-09-emacs-elfeed-demo/">https://protesilaos.com/codelog/2020-06-09-emacs-elfeed-demo/</a></li>
</ul>

<p>Also make sure to visit my Emacs configuration file, from where you can
get the code: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a></p>
        
      


guid: https://protesilaos.com/codelog/2020-09-14-modus-themes-review-blues/
title: Modus themes: report on the review of the main blue colours
url: https://protesilaos.com/codelog/2020-09-14-modus-themes-review-blues/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>The “Modus themes” is a pair of highly accessible themes for Emacs that
conform with the WCAG AAA standard for colour contrast between
combinations of designated background and foreground values (a minimum
contrast ratio of 7:1).</p>

<p>Modus Operandi is a light theme.  Modus Vivendi is dark.  The themes are
part of Emacs’ <code>master</code> branch, each of them currently tagged with
version <code>0.12.0</code>, while they are also distributed through various
package archives.  Consult their Info manual for the specifics (the
manual is not yet in Emacs—coming in version <code>0.13.0</code>):
<a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a>.</p>

<p>The present report documents changes that will be made available in
version <code>0.13.0</code> of the themes, expected at the end of September 2020.</p>

<p>The following is a valid <code>org-mode</code> text that was used to prepare this
report.  The gist is that even seemingly trivial changes require a lot
of work.  If, by the way, anyone knows of a more elegant syntax to write
those tables, please do <a href="https://protesilaos.com/contact/">contact me</a>:
I have little experience with spread sheets, formulas, etc.</p>

<pre><code class="language-org">#+TITLE: Modus themes: report on the minor review of the main blue colours
#+AUTHOR: Protesilaos Stavrou

* Scope of the review

To refine the three main blue foreground values so as to improve the
distinction between themselves which, in turn, means that they work
better in various contexts.

* Conformance with the WCAG AAA standard

This test compares the new and the old colour values relative to the
three main backgrounds they are intended to be combined with: =bg-main=, 
=bg-dim=, =bg-alt= in this order from columns 3 to 5.  The minimum
contrast ratio must be 7.00:1.

#+NAME: Modus Operandi main blue colours against main backgrounds (new vs old)
| Colour name          |         | #ffffff | #f8f8f8 | #f0f0f0 |
|----------------------+---------+---------+---------+---------|
| blue                 | #0031a9 |   10.44 |    9.83 |    9.16 |
| blue (old)           | #0030a6 |   10.64 |   10.02 |    9.34 |
| blue-alt             | #2544bb |    8.01 |    7.54 |    7.03 |
| blue-alt (old)       | #223fbf |    8.30 |    7.81 |    7.28 |
| blue-alt-other       | #0000c0 |   11.92 |   11.23 |   10.46 |
| blue-alt-other (old) | #0000bb |   12.23 |   11.51 |   10.73 |
#+TBLFM: $3='(clr $2 @1$3);%0.2f :: $4='(clr $2 @1$4);%0.2f :: $5='(clr $2 @1$5);%0.2f

#+NAME: Modus Vivendi main blue colours against main backgrounds (new vs old)
| Colour name        |         | #000000 | #110b11 | #181a20 |
|--------------------+---------+---------+---------+---------|
| blue               | #2fafff |    8.70 |    8.05 |    7.20 |
| blue (o)           | #29aeff |    8.59 |    7.96 |    7.12 |
| blue-alt           | #79a8ff |    8.86 |    8.20 |    7.34 |
| blue-alt (o)       | #72a4ff |    8.47 |    7.84 |    7.01 |
| blue-alt-other     | #00bcff |    9.64 |    8.93 |    7.98 |
| blue-alt-other (o) | #00bdfa |    9.66 |    8.95 |    8.00 |
#+TBLFM: $3='(clr $2 @1$3);%0.2f :: $4='(clr $2 @1$4);%0.2f :: $5='(clr $2 @1$5);%0.2f

* Distance relative to selected colours

These tables show the distance in colour space between the blue values
and selected colours which are deemed relevant based on either their
proximity to the blue side of the spectrum or their use in various
contexts (e.g. syntax highlighting).  We do not target a specific number
here.  Just to show the effect of the review.  A higher value means that
there is a greater distance between two colours.

+ Columns 3 and 4 are the new and old =blue= respectively.
+ Columns 5 and 6 are the same for =blue-alt=.
+ Columns 7 and 8 are for =blue-alt-other=.

For Modus Operandi the table shows that the new =blue= and =blue-alt-other=
are slightly more distinct than relevant colours: we witness a modest
increase throughout.  Whereas =blue-alt= has been corrected to be slightly
less distinct than its old value (in relative terms, as the colour
distance is still considerable).  The rationale for this becomes
apparent in the next section, where we compare the blue colours between
themselves.

#+NAME: Modus Operandi colour distance of blue colours (new vs old by column pair)
| Name              |         | #0031a9 | #0030a6 | #2544bb | #223fbf | #0000c0 | #0000bb |
|-------------------+---------+---------+---------+---------+---------+---------+---------|
| fg-main           | #000000 |   96032 |   92602 |  124671 |  126256 |  111457 |  105727 |
| fg-dim            | #282828 |   52676 |   50355 |   65226 |   67814 |   77829 |   73427 |
| fg-alt            | #505050 |   40482 |   39232 |   36703 |   40383 |   75655 |   72518 |
| cyan              | #00538b |    7381 |    7142 |   10564 |   12014 |   36264 |   34737 |
| cyan-alt          | #30517f |   14156 |   13707 |   11225 |   13453 |   43685 |   41855 |
| cyan-alt-other    | #005a5f |   23333 |   22352 |   29782 |   32591 |   61101 |   58244 |
| green             | #005e00 |   94516 |   91844 |  108755 |  114129 |  147077 |  141348 |
| green-alt         | #315b00 |   95771 |   93172 |  102232 |  107966 |  146343 |  140797 |
| green-alt-other   | #145c33 |   49824 |   48089 |   56775 |   60974 |   94266 |   90134 |
| magenta           | #721045 |   61495 |   59579 |   62564 |   64325 |   72489 |   69117 |
| magenta-alt       | #8f0075 |   64087 |   62865 |   58357 |   58745 |   62414 |   60426 |
| magenta-alt-other | #5317ac |   17766 |   17638 |   13557 |   12852 |   18292 |   17791 |
#+TBLFM: $3='(color-distance $2 @1$3) :: $4='(color-distance $2 @1$4) :: $5='(color-distance $2 @1$5) :: $6='(color-distance $2 @1$6) :: $7='(color-distance $2 @1$7) :: $8='(color-distance $2 @1$8)

For Modus Vivendi we have slightly increased the luminance of =blue= and
=blue-alt=, while we have decreased it a tiny bit for =blue-alt-other=.
These minor adjustments mean that the first two have been toned down in
terms of their colour distance to relevant values, while the latter has
been marginally amplified.  The differences are negligible in practice.
Again, the intent is to make the blue colours more distinct between
themselves, as illustrated in the next section.

Recall that:

+ Columns 3 and 4 are the new and old =blue= respectively.
+ Columns 5 and 6 are the same for =blue-alt=.
+ Columns 7 and 8 are for =blue-alt-other=.

#+NAME: Modus Vivendi colour distance of blue colours (new vs old by column pair)
| Name              |         | #2fafff | #29aeff | #79a8ff | #72a4ff | #00bcff | #00bdfa |
|-------------------+---------+---------+---------+---------+---------+---------+---------|
| fg-main           | #ffffff |  138824 |  145545 |   80047 |   87953 |  181930 |  181457 |
| fg-dim            | #e0e6f0 |   92680 |   98243 |   44639 |   50561 |  131039 |  130382 |
| fg-alt            | #a8a8a8 |   55597 |   59075 |   24276 |   26233 |   88244 |   86135 |
| cyan              | #00d3d0 |   16356 |   15543 |   46616 |   44209 |    8811 |    7284 |
| cyan-alt          | #4ae8fc |   14766 |   16029 |   21839 |   22484 |   19669 |   19303 |
| cyan-alt-other    | #6ae4b9 |   32726 |   34890 |   27684 |   29353 |   45240 |   43022 |
| green             | #44bc44 |   99451 |  100612 |  100991 |  100499 |  110970 |  105644 |
| green-alt         | #80d200 |  194546 |  197894 |  171840 |  174524 |  219273 |  212104 |
| green-alt-other   | #00cd68 |   75106 |   74489 |  102017 |   99701 |   70103 |   65480 |
| magenta           | #feacd0 |  117256 |  123303 |   53869 |   59090 |  169026 |  168037 |
| magenta-alt       | #f78fe7 |  109400 |  114975 |   47387 |   51382 |  162374 |  162196 |
| magenta-alt-other | #b6a0ff |   45889 |   49624 |    9986 |   12089 |   81840 |   82136 |
#+TBLFM: $3='(color-distance $2 @1$3) :: $4='(color-distance $2 @1$4) :: $5='(color-distance $2 @1$5) :: $6='(color-distance $2 @1$6) :: $7='(color-distance $2 @1$7) :: $8='(color-distance $2 @1$8)

* Colour distance of the blues between themselves

Here we compare the blue colours between them.  The first table shows
the new values, while the second holds the old ones.  The order for
columns and rows is =blue=, =blue-alt=, =blue-alt-other=.

For Modus Operandi, this proves that by correcting =blue-alt= and slightly
tweaking =blue= and =blue-alt-other= we are able to make these colours more
distinct, which is good when they are combined in various contexts (blue
is one of the dominant foreground colours in the themes).

#+NAME: Modus Operandi new blues between them (blue, blue-alt, blue-alt-other)
|---------+---------+---------+---------|
|         | #0031a9 | #2544bb | #0000c0 |
|---------+---------+---------+---------|
| #0031a9 |       0 |    5270 |   11278 |
| #2544bb |    5270 |       0 |   21574 |
| #0000c0 |   11278 |   21574 |       0 |
#+TBLFM: $2='(color-distance $1 @1$2) :: $3='(color-distance $1 @1$3) :: $4='(color-distance $1 @1$4)

#+NAME: Modus Operandi old blues between them (blue, blue-alt, blue-alt-other)
|---------+---------+---------+---------|
|         | #0030a6 | #223fbf | #0000bb |
|---------+---------+---------+---------|
| #0030a6 |       0 |    5162 |   10621 |
| #223fbf |    5162 |       0 |   18455 |
| #0000bb |   10621 |   18455 |       0 |
#+TBLFM: $2='(color-distance $1 @1$2) :: $3='(color-distance $1 @1$3) :: $4='(color-distance $1 @1$4)

Same principle for Modus Vivendi, where we increased the luminance of
=blue= and =blue-alt= while reducing it for =blue-alt-other=.

#+NAME: Modus Vivendi new blues between them (blue, blue-alt, blue-alt-other)
|---------+---------+---------+---------|
|         | #2fafff | #79a8ff | #00bcff |
|---------+---------+---------+---------|
| #2fafff |       0 |   13053 |    5339 |
| #79a8ff |   13053 |       0 |   34624 |
| #00bcff |    5339 |   34624 |       0 |
#+TBLFM: $2='(color-distance $1 @1$2) :: $3='(color-distance $1 @1$3) :: $4='(color-distance $1 @1$4)

#+NAME: Modus Vivendi old blues between them (blue, blue-alt, blue-alt-other)
|---------+---------+---------+---------|
|         | #29aeff | #72a4ff | #00bdfa |
|---------+---------+---------+---------|
| #29aeff |       0 |   12776 |    4505 |
| #72a4ff |   12776 |       0 |   31712 |
| #00bdfa |    4505 |   31712 |       0 |
#+TBLFM: $2='(color-distance $1 @1$2) :: $3='(color-distance $1 @1$3) :: $4='(color-distance $1 @1$4)

* ANNEX: Tools for measuring relative luminance and previewing colours

This is the implementation of the WCAG formula.

#+begin_src emacs-lisp
;; Code is courtesy of Omar Antolín Camarena:
;; https://github.com/oantolin/emacs-config
(defun wcag (hex)
  (apply #'+
         (cl-mapcar
          (lambda (k x)
            (* k (if (&lt;= x 0.03928)
                     (/ x 12.92)
                   (expt (/ (+ x 0.055) 1.055) 2.4))))
          '(0.2126 0.7152 0.0722)
          (color-name-to-rgb hex))))

(defun clr (c1 c2)
  (let ((ct (/ (+ (wcag c1) 0.05)
               (+ (wcag c2) 0.05))))
    (max ct (/ ct))))
#+end_src

Use =rainbow-mode= to preview the colour values presented herein.

#+begin_src emacs-lisp
(use-package rainbow-mode
  :ensure
  :commands rainbow-mode
  :config
  (setq rainbow-ansi-colors nil)
  (setq rainbow-x-colors nil))
#+end_src

The =color-distance= function is built into Emacs.
</code></pre>
        
      


guid: https://protesilaos.com/codelog/2020-09-24-org-headings-adapt/
title: Emacs: Org heading faces now adapt to their context
url: https://protesilaos.com/codelog/2020-09-24-org-headings-adapt/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>As of commit <code>979e82fc3</code>, upstream Org mode now contains a patch that
allows faces that are combined with headings, such as to-do keywords and
priority cookies, to inherit from the underlying heading’s properties.
The code will become widely available in Org version
9.5.<sup id="fnref:NoteOrgVersion" role="doc-noteref"><a href="#fn:NoteOrgVersion" class="footnote" rel="footnote">1</a></sup></p>

<p>This practically means that if you (or your theme) use a <code>:background</code>,
<code>:overline</code>, <code>:height</code>, or <code>:weight</code> for Org’s heading levels, those
attributes will also be passed on to elements that do not have them.
Overall, it makes for a visually consistent experience.</p>

<p>The following screenshots on <code>emacs -Q</code> show the before and after
states, while also highlighting the inconsistency of some faces actually
adapting to their context even prior to the patch.</p>

<p><img alt="Org headings before" src="https://protesilaos.com/assets/images/attachments/org-adaptive-headings-before.png" /></p>

<p><img alt="Org headings after" src="https://protesilaos.com/assets/images/attachments/org-adaptive-headings-after.png" /></p>

<h2>A collective effort</h2>

<p>The author of the patch is Ihor Radchenko, to whom I am most thankful.
Special thanks to Org’s maintainer, Bastien Guerry who made this a goal
for Org 9.5.</p>

<p>The fix comes as a response to a thread that I <a href="https://lists.gnu.org/archive/html/emacs-orgmode/2020-04/msg00406.html">initiated in late April
2020</a>,
in which I initially documented the inconsistencies and then, with
advice from Bastien, shared <a href="https://lists.gnu.org/archive/html/emacs-orgmode/2020-09/msg00240.html">reproducible recipes for testing
them</a>.</p>

<p>Ihor’s patch ties together feedback from various sources, which I helped
put together.  In particular, I conveyed information and insights
gathered from <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/37">issue 37 on my Modus themes’ Gitlab
repo</a>.  Anders
Johansson’s contribution was instrumental in identifying the source of
the problem in Org’s code base, namely, how font-lock was configured to
work for some faces.</p>

<p>I had experienced the problem while developing the Modus themes, which
have comprehensive customisation options for headings (see <a href="https://protesilaos.com/emacs/modus-themes">their
manual</a>).</p>

<h2>Being pro-active and working with upstream</h2>

<p>On the mailing list I was informed that a partial fix for this issue
already existed in Doom Emacs, specifically the themes packaged for it.
Bastien informed me that it was never communicated to them, which I
consider a missed opportunity.</p>

<p>As such, it is pertinent to remind ourselves that Emacs is a community
that thrives on feedback loops of communication.  These presuppose a
pro-active disposition to report findings to the relevant sources as
soon as they arise.  When we share know-how, we help grow our stock of
knowledge and thus refine the tools derived from it.  When we contribute
a bug fix upstream, we ensure that everyone is better off as a result.
Whereas when we maintain uncoordinated patches we set ourselves up for
longer term trouble, in the form of non-reproducible maintenance burdens
and unnecessary heterogeneity.</p>

<p>Please be reminded that people contribute to Emacs in their free time.
While some notable exceptions do raise an income from their
contributions (which is consistent with free software values), the fact
is that the community at-large operates on a voluntary basis.</p>

<p>You must be prepared to make an effort if you wish to see things move
forward.  Learn who the maintainers are and what is their preferred
medium of communication.  The best way to help is to elucidate your
ideas and share them accordingly.  For bug reports, this often means
that you need to write down the steps necessary to reproduce your issue
in an <code>emacs -Q</code> session.  Or you may have to include a visual
representation of your case while using the offending package.  Adapt to
the specifics of the case, while remaining faithful to the spirit of
pro-action and collaboration.</p>

<p>When in doubt, do not hesitate to ask.  Be humble about it, remain
prepared to do some work, and do not expect anyone to spoon-feed you
because of some misplaced sense of entitlement (i.e. don’t go on some
forum and complain about how this or that is “garbage”—petulance is
not helpful).  Everyone starts off as a beginner.  We are all in this
together.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:NoteOrgVersion" role="doc-endnote">
      <p>Emacs 28, the development branch which currently is
just part of <code>master</code>, ships Org 9.3, so you must install Org from
source if you cannot wait for an update.  Same principle for the
latest stable version of Emacs: 27.1. <a href="#fnref:NoteOrgVersion" class="reversefootnote" role="doc-backlink">[^]</a></p>
    </li>
  </ol>
</div>
        
      


guid: https://protesilaos.com/codelog/2020-10-08-intro-usls-emacs-notes/
title: My simple note-taking system for Emacs (without Org)
url: https://protesilaos.com/codelog/2020-10-08-intro-usls-emacs-notes/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p class="info">Update 2020-10-09 06:55 +0300:  Added annex with Karl Voit’s comment.</p>

<p>Earlier today I <a href="https://protesilaos.com/emacs/dotemacs/#h:787df548-0d95-4512-a61d-27852198f561">published as part of my
dotemacs</a>
the initial implementation of <code>usls</code>, the “Unassuming Sidenotes of
Little Significance” (USLS).  This is a small set of utilities that help
me write and maintain timestamped and categorised plain text files in a
flat directory listing.  It builds on core Emacs commands, such as
<code>dired</code> and <code>find-file</code>, while relying on functionality provided by
standard libraries like <code>thingatpt</code>.</p>

<p>The present article offers an overview of <code>usls</code>, my workflow, and their
underlying values.</p>

<h2>Plain text and Emacs commands</h2>

<p>USLS is the realisation of a personal note-taking system that I have
developed over the course of the last few months.  Its primary aim is to
remain faithful to a plain text workflow that could, in principle, be
implemented with nothing but a POSIX shell.</p>

<p>Everything from the resulting file name to the actual contents must be
usable in the most basic computing environment, such as a TTY, or a
generic text editor and file manager.  It must also be intelligible to
non-Emacs users for when I wish to share a note or, perhaps in the
future, to ask someone to act on my files.</p>

<p>To accomplish this, we set on a naming convention that offers an
adequate filtering mechanism at the visual level (more on naming in the
next section).  Each filename is written as <code>DATE--CATEGORY--TITLE.txt</code>:</p>

<pre><code>/home/prot/Documents/notes:
20201006_113858--politics--eu-deep-concerns-about-varosha.txt
20201006_120634--economics--google-and-fitbit-merger-is-a-scary-prospect.txt
20201007_124941--economics--plentiful-and-predictable-liquidity.txt
</code></pre>

<p>While this may seem primitive, just looking at a long list of that kind
will quickly reveal patterns.  With the help of <code>dired</code>, we can filter
by regular expression.  For example:</p>

<ul>
  <li>mark items that match a regexp with <code>% m</code>.</li>
  <li><code>t</code> to toggle the mark so that you select all the files that did not
match the initial search.</li>
  <li><code>k</code> to hide those from the list (bring everything back with <code>g</code>).</li>
</ul>

<p>Simple and super effective.</p>

<p>Speaking of Dired, one can always use <code>j</code> to jump to a file’s line using
completion.  I have Icomplete with the <code>orderless</code> pattern matching
style by Omar Antolín Camarena (check my dotemacs).  Jumping to a file
using out-of-order groups of flex/regexp matches feels empowering—and
is what I am used to doing throughout my Emacs setup.</p>

<p>Same principle for other standard tools, such as when conducting a
directory-wide grep.  There is no need to have a <code>usls</code>-specific
solution when there are plenty of general purpose alternatives in the
Emacs milieu, including the capable built-in <code>project.el</code> library that
<a href="https://www.manueluberti.eu/emacs/2020/09/18/project/">Manuel Uberti recently wrote about</a> (2020-09-18).</p>

<p>In short, <code>usls</code> does not implement a file manager, content searcher,
project organiser, etc.  Its focus is on streamlining the process of
creating notes.</p>

<h2>The file’s name and contents</h2>

<p>The command <code>usls-new-note</code> is the main point of entry to this tool.
Calling it will first open a minibuffer prompt asking for the file’s
title.  That gets inserted in the resulting buffer as-is, while a
hyphenated variant is used to construct the filename.  Once that prompt
closes, a second one appears asking for a category.  Here the user is
presented with a list of completion candidates.  It is possible to pick
an item from those on offer or type in a new one (for Icomplete I bind
<code>exit-minibuffer</code> to <code>C-j</code> as a means to forcefully send input, just as
for a non-matching item or a substring).</p>

<p>The resulting buffer is as follows (<code>%?</code> indicates the point):</p>

<pre><code>title: Plentiful and predictable liquidity
date: 2020-10-07
category: Economics
orig_name: ~/Documents/notes/20201007_124941--economics--plentiful-and-predictable-liquidity.txt
orig_id: 20201007_124941
------------------------

%?
</code></pre>

<p>The date, the original filename and ID are generated automatically.
Those header fields are mostly intended for grep operations and to offer
a sense of context without having to resort to demanding alternatives
for meta-data management (powerful though they may be).</p>

<p>Now here comes the feature I use the most: invoking <code>usls-new-note</code>
while the region is active will append its text to the resulting buffer.</p>

<pre><code>title: Plentiful and predictable liquidity
date: 2020-10-07
category: Economics
orig_name: ~/Documents/notes/20201007_124941--economics--plentiful-and-predictable-liquidity.txt
orig_id: 20201007_124941
------------------------

%?

* * *

REGION GOES HERE
</code></pre>

<p>This alone makes it easy to benefit from some of that <code>org-capture</code>
goodness while remaining faithful to the overarching design principle of
simplicity.  I use this a lot when going through <code>elfeed</code> news, <code>gnus</code>
mails/groups, and even websites accessed via <code>eww</code>.  There is no setup
for any of them.  All we do is copy the region.</p>

<p>Concerning the actual contents of the note, I tend to write long and
carefully considered entries, though the system does not impose any
particular paradigm.  One could easily maintain bullet points.  Seeing
though as this is plain text, there is not much you can do with graphics
or all those extras that Org provides (unless you reinvent Org, but I
digress).  I actually consider such a constraint an upside: it focuses
the mind on the task of distilling an idea or set thereof.</p>

<h2>Categories and the absence of tags</h2>

<p>Tags never worked for me.  This has been true ever since I created my
first blog circa 2011.  You add a bundle of words to each entry,
expecting that over the long term this method will give rise to emergent
themes.  Wordpress even provides a “tag cloud” widget (last time I
checked) so that you can see which word has the most entries.  Perhaps
this yields returns for large sets of files and is appropriate for data
mining on an industrial scale.  On my end, however, it always felt like
tags were an assortment of terms that offered little insight into the
linkages between my writings.</p>

<p>Think about a set of tags for this blog post: “emacs”, “notes”,
“library”, “package”.  When studied <em>as a group</em> they do have a
descriptive value: an emergent quality.  We can infer what this is all
about.  Yet when each of those is interpreted in its own right it is
more likely to confuse rather than enlighten us.  Imagine having ten
entries under “library” and another ten under “books”.  You then realise
that you must invent more specific tags such as “university-library” or
“emacs-library”, until you reach a point where you have too many tags
for too few entries.  Which eventually forces you to expend energy on
administrivia rather than the essence of your text: which tags to
select, whether three or five of them are enough, and so on.</p>

<p>As such, I have settled on a simple rule of assigning a single word to
each entry, which I call a “category”.  It describes in very broad terms
what the note is about.  To help you choose among competing options,
think which one would have the highest descriptive value when read on
its own.  So the current article would be associated with “emacs”
instead of “code”, “library”, “package”…</p>

<p>Categories must be generic though remain sufficiently informative.  It
would, for instance, be impractical to archive an economics’ piece under
“science”, just as it would be tricky to write sub-categories like
“monetary”, “finance”, “fiscal”, etc. which would inevitably introduce
the same problems as with tags.  There is no magic solution here.  Just
pick a word that makes sense to you and is flexible enough.</p>

<p>On the technical side of things, <code>usls-new-note</code> presents its completion
candidates for categories using two sources that get combined in to a
single list:</p>

<ol>
  <li>A pre-determined list (<code>usls-known-categories</code> as of this writing);</li>
  <li>Dynamically inferred entries based on filenames in <code>usls-directory</code>.</li>
</ol>

<h2>Linking entries and finding connections</h2>

<p>Most of my notes are standalone pieces.  I elucidate my thoughts as best
I can and try not to rely on implicit information or “further reading”
material for statements I make (with the understanding that I do have
all of it in my head).  Still, there are cases where links to other
items are mandatory.  My answer is quite uninspiring on the surface
level: add a unique identity (timestamp) that points to a file name,
plus some caret signs.</p>

<pre><code>Some text I am writing.^20201007_124941

^^ 20201007_124941--economics--plentiful-and-predictable-liquidity.txt
</code></pre>

<p>Those are conveniently inserted with <code>usls-id-insert</code>, which uses
completion to select among a list of files that includes every item in
the <code>usls-directory</code>, except the current entry.</p>

<p>Strictly speaking, this is not a link.  It is a reference to a file name
whose location is assumed as relative to the directory that includes
those files.  Emacs can handle such cases gracefully.  Place the point
over either the ID (single caret) or the full name (double caret) and
type <code>C-x C-f M-n</code>.  There should only ever be a single match.  To make
this process a bit faster, though still faithful to what Emacs already
does, <code>usls-follow-link</code> presents completion candidates of all such
references (the “follow link” misnomer notwithstanding).</p>

<p>There is no backward linking feature to speak of.  While appealing and
probably beneficial in some fields of endeavour, it requires lots of
extras to work reliably; extras that I would rather avoid else risk
jeopardising my attempt at a minimalist setup.</p>

<p>If you need to find all files that reference a given ID/name, call some
grep command (<code>rg.el</code>, <code>counsel-rg</code> and the rest of the bunch, or
<code>occur</code>, <code>multi-occur</code> for buffers).  It works just fine.  Plus, with
the <code>wgrep</code> package you can edit the results of grep in a dedicated
buffer, in case you ever wish to refactor things—combine that with the
standard <code>wdired</code> for maximum effect and don’t forget <code>query-replace</code>,
keybard macros or multiple cursors, etc.</p>

<h2>This is not a “second brain”</h2>

<p>You can already discern the elements of my approach to the task of
composing plain text notes: leverage standard Emacs functions, avoid
duplication of efforts, minimise dependencies or complexity, and focus
on the text you intend to write, all while relying on a straightforward
file naming scheme and some ancillary syntactic notation.  Any extras
can come from existing packages, per the user’s needs.</p>

<p>The name of this library—Unassuming Sidenotes of Little Significance
or <code>usls</code>—is a mere joke about it being “useless” when compared with
comprehensive solutions that promise to grant you a second brain.</p>

<p>While my code is just an exercise in Emacs Lisp that impliments a
simplistic private system for recording thoughts, I do believe that the
key to productivity does not rest with any of the tools on offer, but
with the clarity of concept one has developed prior to making use of
them.</p>

<p>What is the utility of a second brain if you have not yet realised the
potential of the first one?</p>

<p>In conclusion, what I have right now is a working prototype.  I will
continue to iterate on it whenever I discover some area that could be
improved further, without deviating from the underlying design values
documented herein.  The library is currently part of my dotemacs and is
available under this heading:
<a href="https://protesilaos.com/emacs/dotemacs/#h:787df548-0d95-4512-a61d-27852198f561">https://protesilaos.com/emacs/dotemacs/#h:787df548-0d95-4512-a61d-27852198f561</a>.
Perhaps it will inspire you to implement a workflow that matches your
expectations and makes you feel in control of what is happening.</p>

<p>Also note that <code>usls</code> is not meant as a substitute for Org, such as to
track to-do lists, produce an agenda, etc.  This is about private
records of longer form notes, such as commentary on a paper I read.  I
still use Org to organise life’s details and also to produce documents
such as my literate Emacs configuration (my dotemacs) or the Info manual
of my Modus themes.</p>

<h2>Annex with comment made by Karl Voit</h2>

<p>Karl Voit is an expert on Personal Information Management (PIM) and
contacted me to share valuable insights.  Message reproduced with
permission in the text block below.</p>

<p>The short version of my reply is that I am open to reviewing things and
learning from others.  Some decisions, such as the format of the date or
the lack of spaces are purely stylistic or matters of convenience: I am
fine with other techniques.  What matters is the general principle of
keeping things simple and accessible.</p>

<p>In concrete terms, I plan to use <code>completing-read-multiple</code> so that one
could insert more than one category at the prompt (notwithstanding other
ideas I may take from <a href="https://karl-voit.at/">Karl’s website</a>, once I
eventually read through the wealth of knowledge found there).</p>

<pre><code>From: Karl Voit
Subject: USLS
To: public@protesilaos.com
Date: Thu, 8 Oct 2020 18:11:51 +0200

Hi,

Thanks for writing down about your cool system.

I do have a few remarks on your approach. I don't assume, you will
change your approach. However, I'd like to mention a few things
related to your file name convention and categories.


DATE--CATEGORY--TITLE.txt
with:
20201006_113858--politics--eu-deep-concerns-about-varosha.txt

I'd prefer a more ISO 8601 approach for general compatibility.

My own concept with focus on shell and CLI tools is summarized on:
https://karl-voit.at/managing-digital-photographs/

It consists of conventions + a set of self-written tools.

In my case, the file name convention looks like:

/this/is/a/folder/2014-04-20T17.09 Picknick in Graz -- food graz.jpg
 [ move2archive  ] [  date2name   ] [appendfilename] [ filetags ]

ISO 8601 can not be applied to file names directly because ":" is
not a valid character on Microsoft file systems. Therefore, I
settled with ".".

You do seem to avoid spaces in file names. IMHO, while this was good
practice up to maybe ten or fifteen years ago, I don't see any
reason to continue. I myself switched to spaces and (most recently)
also to special characters in file names as well without an issue.
YMMV. I got sick of looking for "*Vorhaenge*" as well as for
"*Vorhaenge*" in order to locate my own files (german Umlauts as
7-bit-pendants) and file names from others using the proper Umlaut.

Support from all standard tools in my zsh is perfect for special
characters such as Umlauts as well. No reason left to limit myself.


Categories vs. tags:

I do have some background there and this is maybe the main reason
for my comments.

The issues you're describing are very common aspects when tags are
used. IMHO a promising approach is to curate a finite and limited
set of tags, called "controlled vocabulary" (CV). Compare to
https://github.com/novoid/filetags which offers methods to deal with
CVs - even multiple of them - in an elegant way, I think.

This way, you need to limit yourself to high-level concepts instead
of describing the content of the information.

This should avoid the excessive use of new tags for all kinds of
files. 

Furthermore, multi-classification is a good thing to have. 

You're describing one possible approach to curcimvent
multi-classification: choosing the currently most important
category.

This is a valid approach but it comes with a well-studied
disadvantage: your mental model of the world is constantly changing.
The way you're thinking while creating the file name is different
from the world and context when retrieving the information.

From this background, it would be wiser not to have any category at
all and use the content to locate information (3rd order of orders
according to David Weinberger): full-text search.


I experienced with those ideas myself for quite some years until I
defined my method, conventions and wrote my tools.

Again: since you've invested so much already, there will be a very
small chance that you will change anything here. However, I had to
think about similar topics and came out with a different approach.
Maybe there is something you can take away from my result for your
system as well.


PS: If you - for some reason - want to publish my text. I'm fine
with it as long as you omit my email address.
</code></pre>
        
      


guid: https://protesilaos.com/codelog/2020-10-08-modus-themes-0-13-0/
title: Released Modus themes 0.13.0
url: https://protesilaos.com/codelog/2020-10-08-modus-themes-0-13-0/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Just published version <code>0.13.0</code> of the Modus themes.  The release notes
are reproduced below.  This is the largest release to date and also the
first one since the themes were incorporated in upstream Emacs.</p>

<p>Packages may take a while to get the update, so please be patient.
<a href="https://protesilaos.com/contact/">Contact me</a> in case something is
amiss.</p>

<hr />

<h2>Modus Operandi and Modus Vivendi version 0.13.0</h2>

<p>By Protesilaos Stavrou <a href="mailto:info@protesilaos.com">info@protesilaos.com</a> on 2020-10-08</p>

<p>This entry documents the changes since version 0.12.0 (2020-08-26).
There have been around 150 commits in the meantime, making this the
largest release to date (though sheer volume should not be conflated
with quality, of which there is plenty).</p>

<p>As always, everything described herein conforms with the overarching
accessibility objective of the themes for a minimum contrast ratio of
7:1 between background and foreground values in their given combinations
(conformance with the WCAG AAA standard).</p>

<h2>Overview</h2>

<ol>
  <li>
    <p>There is a new Info manual that documents the customisation options
as well as every other piece of information pertinent to the themes.
You will find it in the Info pages inside of Emacs.  Or browse it
online: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a>.</p>
  </li>
  <li>
    <p>New customisation options grant users more power to further adapt the
active theme to their preferences.</p>
  </li>
  <li>
    <p>Extended coverage for even more faces and face groups, adding to the
already comprehensive list of directly supported ones.</p>
  </li>
  <li>
    <p>Lots of tweaks to improve the use of colour and avoid exaggerations
(well, “exaggerations” is relative, since the prior state was already
carefully designed).</p>
  </li>
  <li>
    <p>A new page hosts all pictures that demo the themes across a wide
range of scenaria: <a href="https://protesilaos.com/emacs/modus-themes-pictures">https://protesilaos.com/emacs/modus-themes-pictures</a>.</p>
  </li>
  <li>
    <p>Similarly, the change log also has its own dedicated web page:
<a href="https://protesilaos.com/emacs/modus-themes-changelog">https://protesilaos.com/emacs/modus-themes-changelog</a>.</p>
  </li>
</ol>

<h2>New customisation options</h2>

<p>Note that all customisation options are documented at length in the new
Info manual.  What is offered here is not necessarily exhaustive.</p>

<h3>Diff styles</h3>

<p>Symbol names (“choice” type):</p>

<ul>
  <li>modus-operandi-theme-diffs</li>
  <li>modus-vivendi-theme-diffs</li>
</ul>

<p>Possible values:</p>

<ol>
  <li>nil (default)</li>
  <li>desaturated</li>
  <li>fg-only</li>
</ol>

<p>DEPRECATED (“boolean” type):</p>

<ul>
  <li>modus-operandi-theme-subtle-diffs</li>
  <li>modus-vivendi-theme-subtle-diffs</li>
</ul>

<p>This option supersedes older ones while retaining their functionality.</p>

<p>The default remains unaltered, meaning that the diffs will use fairly
prominent colour-coded combinations for the various elements (e.g. green
text on an unambiguously green backdrop).</p>

<p>A <code>desatured</code> value will tone down the default aesthetic, giving a less
vibrant feel.</p>

<p>While <code>fg-only</code> removes almost all coloured backgrounds, opting to apply
colour only to the relevant text (this was the case with the
now-deprecated options).  There are some exceptions, like word-wise or
“refined” diffs, which still use coloured backgrounds to convey their
meaning.</p>

<h3>Modeline styles</h3>

<p>Symbol names (“choice” type):</p>

<ul>
  <li>modus-operandi-theme-mode-line</li>
  <li>modus-vivendi-theme-mode-line</li>
</ul>

<p>Possible values:</p>

<ol>
  <li>nil (default)</li>
  <li>3d</li>
  <li>moody</li>
</ol>

<p>DEPRECATED (“boolean” type):</p>

<ul>
  <li>modus-operandi-theme-3d-modeline</li>
  <li>modus-vivendi-theme-3d-modeline</li>
</ul>

<p>The default modeline continues to be a two-dimensional rectangle with a
border around it.  Active and inactive modelines use different colour
combinations for their main background and foreground.</p>

<p>Option <code>3d</code> produces an effect similar to what you get in a generic
Emacs session, where the active modeline has a pseudo three-dimensional
effect applied to it.  This option offers the same functionality as that
of the deprecated variables.</p>

<p>Option <code>moody</code> is designed specifically for use with the Moody library,
though it can also be used without it.  Instead of implementing a box
effect, it applies an overline and underline instead, while also toning
down the inactive modeline.</p>

<p>Thanks to Nicolas De Jaeghere for the feedback and code samples in issue
80: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/80">https://gitlab.com/protesilaos/modus-themes/-/issues/80</a></p>

<h3>Headline styles</h3>

<p>Symbol names (“alist” type):</p>

<ul>
  <li>modus-operandi-theme-headings</li>
  <li>modus-vivendi-theme-headings</li>
</ul>

<p>DEPRECATED (“boolean” type):</p>

<ul>
  <li>modus-operandi-theme-rainbow-headings</li>
  <li>modus-operandi-theme-section-headings</li>
  <li>modus-vivendi-theme-rainbow-headings</li>
  <li>modus-vivendi-theme-section-headings</li>
</ul>

<p>Possible values, which can be specified for each heading level (examples
further below):</p>

<ol>
  <li>nil (default fallback option—covers all heading levels)</li>
  <li>t (default style for a single heading, when the fallback differs)</li>
  <li>no-bold</li>
  <li>line</li>
  <li>line-no-bold</li>
  <li>rainbow</li>
  <li>rainbow-line</li>
  <li>rainbow-line-no-bold</li>
  <li>highlight</li>
  <li>highlight-no-bold</li>
  <li>rainbow-highlight</li>
  <li>rainbow-highlight-no-bold</li>
  <li>section</li>
  <li>section-no-bold</li>
  <li>rainbow-section</li>
  <li>rainbow-section-no-bold</li>
</ol>

<p>This supersedes and greatly expands upon what the deprecated variables
once offered.  It is now possible to (i) benefit from more stylistic
choices, and (ii) apply them on a per-level basis.</p>

<p>As always, the defaults remain in tact: headings are just rendered in a
bold weight and their colours are not too saturated to offer a plain
text impression that relies on typography to convey its meaning.</p>

<p>The info manual explains the details.  A few examples:</p>

<pre><code>;; Per-level styles (t means everything else)
(setq modus-operandi-theme-headings
      '((1 . highlight)
        (2 . line)
        (t . rainbow-line-no-bold)))

;; Uniform style for all levels
(setq modus-operandi-theme-headings
      '((t . rainbow-line-no-bold)))

;; Default style for level 1, while others differ
(setq modus-operandi-theme-headings
      '((1 . t)
        (2 . line)
        (t . rainbow-line-no-bold)))
</code></pre>

<p>Thanks to Adam Spiers for the feedback in issue 81:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/81">https://gitlab.com/protesilaos/modus-themes/-/issues/81</a>.  Also thanks
to Nicolas De Jaeghere for helping refine relevant stylistic choices:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/90">https://gitlab.com/protesilaos/modus-themes/-/issues/90</a>.</p>

<h3>No link underlines</h3>

<p>Symbol names (“boolean” type):</p>

<ul>
  <li>modus-operandi-theme-no-link-underline</li>
  <li>modus-vivendi-theme-no-link-underline</li>
</ul>

<p>Possible values:</p>

<ol>
  <li>nil (default)</li>
  <li>t</li>
</ol>

<p>By default, the themes apply an underline effect to links, symbolic
links, and buttons.  Users can now disable this style by setting the new
option to <code>t</code>.</p>

<p>Thanks to Utkarsh Singh for the feedback in issue 94:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/94">https://gitlab.com/protesilaos/modus-themes/-/issues/94</a></p>

<h3>No mixed fonts</h3>

<p>Symbol names (“boolean” type):</p>

<ul>
  <li>modus-operandi-theme-no-mixed-fonts</li>
  <li>modus-vivendi-theme-no-mixed-fonts</li>
</ul>

<p>Possible values:</p>

<ol>
  <li>nil (default)</li>
  <li>t</li>
</ol>

<p>By default, the themes configure some spacing-sensitive faces, such as
Org tables and code blocks, to always inherit from the <code>fixed-pitch</code>
face (documented in the manual).  This is to ensure that those
constructs remain monospaced when users opt for something like the
built-in <code>M-x variable-pitch-mode</code>.  Otherwise the layout would break.</p>

<p>The obvious downside with this theme design is that users need to
explicitly configure the font family of <code>fixed-pitch</code> in order to apply
their desired typeface (how to do this is also covered in the manual).
That may be something they do not want to do.  Hence this option to
disable any kind of font mixing done by the active theme.  Set it to
<code>t</code>.</p>

<h2>Support for new faces or face groups</h2>

<ul>
  <li>awesome-tray</li>
  <li>binder</li>
  <li>cperl-mode</li>
  <li>eldoc-highlight-function-argument</li>
  <li>erc escaped colour sequences</li>
  <li>eshell-syntax-highlighting</li>
  <li>flycheck-color-mode-line</li>
  <li>isearch regexp groups (Emacs version &gt;= 28)</li>
  <li>mpdel</li>
  <li>objed</li>
  <li>org 9.4 new faces: <code>org-headline-todo</code> and <code>org-table-header</code></li>
  <li>racket-mode</li>
  <li>typescript-mode</li>
</ul>

<p>Thanks to:</p>

<ul>
  <li>
    <p>Damien Cassou for reporting the issue with mpdel:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/99">https://gitlab.com/protesilaos/modus-themes/-/issues/99</a></p>
  </li>
  <li>
    <p>Dario Gjorgjevski for reporting the issue with erc:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/92">https://gitlab.com/protesilaos/modus-themes/-/issues/92</a></p>
  </li>
  <li>
    <p>Markus Beppler for contributing the patch for cperl-mode:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/11">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/11</a></p>
  </li>
  <li>
    <p>User “Moesasji” for reporting the issue with objed:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/79">https://gitlab.com/protesilaos/modus-themes/-/issues/79</a></p>
  </li>
</ul>

<h2>Refinements to existing faces</h2>

<ul>
  <li>
    <p>calfw applies colours and styles in a way that makes it consistent
with the rest of the themes’ metaphors.</p>
  </li>
  <li>
    <p>diredfl makes more considerate use of colour.  We still apply colour
everywhere (the whole point of this package) but make sure to avoid
exaggerations.</p>
  </li>
  <li>
    <p>doom-modeline-battery-error face fits better with the rest of the
design.</p>
  </li>
  <li>
    <p>elfeed search buffers use less intense colours, while still keeping
all elements fairly distinct.  The intent is to avoid a “rainbow
effect” in such a dense interface.</p>
  </li>
  <li>
    <p>elfeed read and unread items are more distinct.</p>
  </li>
  <li>
    <p>git commit and vc log edit messages benefit from refined colour
combinations for their various constructs.  The commit’s summary is
now rendered in a bold weight, to better convey the idea that this is
a quasi heading element.</p>
  </li>
  <li>
    <p>gnus heading colours are more consistent.  All information remains
clearly distinct, but we now avoid using colours that are on opposite
sides of the colour spectrum.  Basically to keep things distinct
without going over the top.</p>
  </li>
  <li>
    <p>gnus read and unread items are easier to tell apart.  Thanks to user
“Nick” for reporting the issue:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/97">https://gitlab.com/protesilaos/modus-themes/-/issues/97</a>.</p>
  </li>
  <li>
    <p>help-argument-name has a distinct foreground colour, so that it is
easier to spot it in “<em>Help</em>” buffers.  Its slant is also controlled
by the active theme’s customisation option for slanted constructs (nil
by default—check the manual).</p>
  </li>
  <li>
    <p>helpful-heading now is consistent with other heading styles.  Thanks
to Nicolas De Jaeghere for reporting the issue:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/90">https://gitlab.com/protesilaos/modus-themes/-/issues/90</a>.</p>
  </li>
  <li>
    <p>icomplete, ido, orderless are all tweaked to work better under various
circumstances.</p>
  </li>
  <li>
    <p>info-menu-star uses a red colour to make it easier to select a menu
entry by estimating its number.  This face applies to every third
element and is a nice little extra to have.</p>
  </li>
  <li>
    <p>info quoted strings are configured to always render in <code>fixed-pitch</code>,
in line with the themes’ design for mixed fonts (remember to check the
relevant customisation option).</p>
  </li>
  <li>
    <p>line numbers work properly with <code>text-scale-adjust</code>.  Thanks to user
“jixiuf” for reporting the issue:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/98">https://gitlab.com/protesilaos/modus-themes/-/issues/98</a>.</p>
  </li>
  <li>
    <p>line-number-current-line no longer applies a bold weight to its text.
This is to avoid a certain “jump effect” while moving between lines,
where the affected numbers grow and shrink in weight as the line
changes (once you see it, you will know what I mean).</p>
  </li>
  <li>
    <p>line-number-major-tick and line-number-minor-tick do use a bold weight
because they are fixed on the scale.  Their colours are also improved
to better complement their intended role (these faces are for Emacs 27
or higher).</p>
  </li>
  <li>
    <p>magit-diff-file-heading-selection, magit-diff-hunk-heading-selection
use more appropriate colour combinations.</p>
  </li>
  <li>
    <p>markdown blockquotes and org quote blocks use a different foreground,
which is colder than the previous one.  Just to make sure that they
are not mistaken for inline code.</p>
  </li>
  <li>
    <p>message headers use less exaggerated colour combinations.  The
differences are fairly minor.</p>
  </li>
  <li>
    <p>message-mml no longer uses a green foreground, as that could
potentially cause confusion with quoted text in some cases.  A unique,
albeit less saturated, foreground is used instead.</p>
  </li>
  <li>
    <p>message-separator uses a more neutral colour combination, while
retaining its overall uniqueness within its context (i.e. mail
composition).</p>
  </li>
  <li>
    <p>modeline colours are refined to improve the contrast between active
and inactive states.</p>
  </li>
  <li>
    <p>mu4e-replied-face has a new colour that accounts for colour distance
relative to its context.  Thanks to Shreyas Ragavan for reporting the
issue: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/69">https://gitlab.com/protesilaos/modus-themes/-/issues/69</a>.</p>
  </li>
  <li>
    <p>org agenda date and structure no longer behave like headings in other
Org buffers.  Instead, they have their own styles to better perform
their intended function and to avoid exaggerations.</p>
  </li>
  <li>
    <p>org agenda dimmed to-do items (which have blocked sub-items) are no
longer assigned a subtle grey background colour.  They are instead
rendered with a bold weight and a subtle grey foreground to minimise
distractions.  Thanks to Roman Rudakov for reporting this in issue
101: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/101">https://gitlab.com/protesilaos/modus-themes/-/issues/101</a>.</p>
  </li>
  <li>
    <p>org agenda clocked items are configured to extend their background to
the edge of the window.  Otherwise they are cut off at the last text
character, which creates inconsistencies while using tags: a tag is
placed to the right so the background extends further than without
them.  Based again on the feedback of Roman Rudakov in issue 101:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/101">https://gitlab.com/protesilaos/modus-themes/-/issues/101</a>.</p>
  </li>
  <li>
    <p>org agenda current time no longer uses a background.  A bold weight
and a blue foreground are applied instead.  The intent is to keep
things clean.  This is also covered by Roman Rudakov’s feedback in
issue 101: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/101">https://gitlab.com/protesilaos/modus-themes/-/issues/101</a>.</p>
  </li>
  <li>
    <p>org-checkbox-statistics-done, org-checkbox-statistics-todo inherit
from org-done and org-todo respectively, instead of defining their own
properties.</p>
  </li>
  <li>
    <p>org drawers and their data now use <code>fixed-pitch</code> in the interest of
consistency with other metadata-like faces.  Thanks (yet again!) to
Nicolas De Jaeghere for reporting the issue:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/91">https://gitlab.com/protesilaos/modus-themes/-/issues/91</a>.</p>
  </li>
  <li>
    <p>org-footnote underlines will now always use the same colour, instead
of applying the one of other coloured constructs (e.g. when the
footnote is inline and part of the text is rendered as verbatim).</p>
  </li>
  <li>
    <p>org-meta-line is less prominent and, thus, more consistent with other
metadata-related constructs.</p>
  </li>
  <li>
    <p>org-roam faces are updated to match the current state of the upstream
project.  The main colour of org-roam links is now different than that
of standard links in an attempt to differentiate between the two (due
to their unique semantics).  If this is not desired, you can evaluate
the following:</p>

    <pre><code>(setq org-roam-link-use-custom-faces nil)
</code></pre>
  </li>
  <li>
    <p>org-todo, org-done, as well as relevant faces such as priorities and
statistics are reviewed to work better with all heading combinations.
Though please read the next section about “adaptive headings”, as such
workarounds will no longer be necessary for future stable releases of
Org.</p>
  </li>
  <li>
    <p>selectrum uses different styles than before to account for its unique
property of overlaying matching characters on top of the current
line’s background.  We want to avoid scenaria where matches are
difficult to discern and the current line is not clear.</p>
  </li>
  <li>
    <p>vc modeline states benefit from improved colour choices.  Just minor
adjustments to account for the review of the base modeline colours.</p>
  </li>
  <li>
    <p>vterm base colours now are variants of gray to ensure that some tools,
such as zsh suggestions work properly.  Thanks to user “jixiuf” for
reporting this issue and suggesting a possible solution:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/93">https://gitlab.com/protesilaos/modus-themes/-/issues/93</a>.</p>
  </li>
</ul>

<h2>Contributions to the wider community</h2>

<p>Sometimes the themes reveal bugs in other packages.  It is of paramount
importance that we report those to the upstream developers, try to help
them reproduce the issue, and, where possible, support them in tracing
the problem’s root cause.</p>

<p>Four such cases during this release:</p>

<ol>
  <li>
    <p>Adaptive Org headings.  Solved upstream and documented on my website:
<a href="https://protesilaos.com/codelog/2020-09-24-org-headings-adapt/">https://protesilaos.com/codelog/2020-09-24-org-headings-adapt/</a>.
Reported and discussed on the themes’ issue tracker:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/37">https://gitlab.com/protesilaos/modus-themes/-/issues/37</a>.</p>
  </li>
  <li>
    <p>Alignment of Org tags with proportional fonts.  Ongoing thread:
<a href="https://lists.gnu.org/archive/html/emacs-orgmode/2020-09/msg00415.html">https://lists.gnu.org/archive/html/emacs-orgmode/2020-09/msg00415.html</a>.
Reported and discussed on the themes’ issue tracker:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/85">https://gitlab.com/protesilaos/modus-themes/-/issues/85</a>.</p>
  </li>
  <li>
    <p>Org priority cookie has extra space.  Ongoing thread:
<a href="https://lists.gnu.org/archive/html/emacs-orgmode/2020-09/msg00696.html">https://lists.gnu.org/archive/html/emacs-orgmode/2020-09/msg00696.html</a>.
Reported and discussed on the themes’ issue tracker, with feedback
from Roman Rudakov:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/95">https://gitlab.com/protesilaos/modus-themes/-/issues/95</a>.</p>
  </li>
  <li>
    <p>Company overlay pop-up misaligns items.  Reported upstream and
acknowledged as a known issue that occurs in certain cases:
<a href="https://github.com/company-mode/company-mode/issues/1010">https://github.com/company-mode/company-mode/issues/1010</a>.
Discussion on the themes’ issue tracker, with feedback from Iris
Garcia: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/96">https://gitlab.com/protesilaos/modus-themes/-/issues/96</a>.</p>
  </li>
</ol>

<h2>Miscellaneous</h2>

<ul>
  <li>
    <p>Belatedly (by about 2 weeks) pushed tag for version 0.12.0.  Thanks to
Alex Griffin for bringing this to my attention:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/89">https://gitlab.com/protesilaos/modus-themes/-/issues/89</a></p>
  </li>
  <li>
    <p>Fixed a bug with how some older customisation options were declared as
obsolete.  Thanks to Tassilo Horn for noticing and reporting the
problem: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/88">https://gitlab.com/protesilaos/modus-themes/-/issues/88</a>.</p>
  </li>
  <li>
    <p>Fixed a misplaced optional prefix argument in the manual for how to
switch themes using a custom function.  Thanks to Manuel Uberti for
catching this omission of mine and reporting it:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/84">https://gitlab.com/protesilaos/modus-themes/-/issues/84</a>.</p>
  </li>
  <li>
    <p>Silenced the Elisp package linter for a spurious error on a single
eldoc face.  Thanks to Steve Purcell for the guidance:
<a href="https://github.com/purcell/package-lint/issues/187">https://github.com/purcell/package-lint/issues/187</a>.</p>
  </li>
  <li>
    <p>Defined two new dedicated background colours for exceptional cases.
These are intended for internal use in very special circumstances.</p>
  </li>
  <li>
    <p>Reword GuixSD to “Guix System” in the list of package formats
currently available.</p>
  </li>
  <li>
    <p>Reviewed the main blue colours for both themes.  While the changes are
practically impossible to discern upon first sight, the process was
far from straightforward.  A complete report documents the minutia:
<a href="https://protesilaos.com/codelog/2020-09-14-modus-themes-review-blues/">https://protesilaos.com/codelog/2020-09-14-modus-themes-review-blues/</a>.</p>
  </li>
  <li>
    <p>Reviewed the “active” palette subset, typically used in the modelines.
No report was necessary for those, as the changes were fairly simple.</p>
  </li>
  <li>
    <p>Reviewed the “intense” background colour that comes into effect when
users opt for the customisation option for intense paren-match styles
(check the manual).  Both the hue and the saturation have been changed
to better conform with the intended function of this particular entry.</p>
  </li>
  <li>
    <p>Reviewed the fringe-specific accented backgrounds.  Commit 7316e3320
contains tables that compare the relative luminance of old and new
values.</p>
  </li>
  <li>
    <p>Improved the advice for setting fonts using <code>set-face-attribute</code>.  The
information is in the manual and is also available as a blog entry:
<a href="https://protesilaos.com/codelog/2020-09-05-emacs-note-mixed-font-heights/">https://protesilaos.com/codelog/2020-09-05-emacs-note-mixed-font-heights/</a>.</p>
  </li>
  <li>
    <p>Rewrote an expression as “(or x y)” instead of “(if x x y)” in one
place.  Just goes to show that tweaking the code is also part of the
deal.</p>
  </li>
  <li>
    <p>Abstracted and simplified heading level properties by using bespoke
theme faces.  Makes it easier to keep things consistent across the
various face groups.</p>
  </li>
  <li>
    <p>Same principle as above for diff-related styles.</p>
  </li>
  <li>
    <p>Users who prefer to do things their own way or who just wish to
contribute code to the Modus themes may wish to read my “Notes for
aspiring Emacs theme developers”:
<a href="https://protesilaos.com/codelog/2020-08-28-notes-emacs-theme-devs/">https://protesilaos.com/codelog/2020-08-28-notes-emacs-theme-devs/</a>.</p>
  </li>
</ul>

<p>This has been yet another period of intense work: reviewing faces and
applying colours is never easy, adding new customisation options is
always tricky, and documenting everything takes a lot of time (unless
you do all of those on a whimsy, which hopefully is not the case here).</p>

<p>Thanks again to everyone who helped improve the themes!</p>
        
      


guid: https://protesilaos.com/codelog/2020-10-21-emacs-favourite-package/
title: Why Emacs itself is my “favourite Emacs package”
url: https://protesilaos.com/codelog/2020-10-21-emacs-favourite-package/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=RiXK7NALgRs">https://www.youtube.com/watch?v=RiXK7NALgRs</a></p>
         
         <p>In this video blog I talk about the persistent question of “the killer
app” that gets asked in the Emacs community.  I explain why I think the
identification of a single package is often not enough to appreciate the
true value proposition of Emacs.  My case emphasises the importance of
workflows; workflows that typically combine lots of distinct tools and
benefit from core Emacs attributes.  It is the whole system that
matters, because all those packages—in their given combinations—make
up our day-to-day computing experience with Emacs.</p>

<p>The text of the presentation is written in <code>org-mode</code> notation and is
reproduced below.  Also check my Emacs configuration file, from where
you can get the code I use: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.</p>

<hr />

<pre><code class="language-org">#+TITLE: Vlog: Emacs is my “favourite Emacs package”
#+AUTHOR: Protesilaos Stavrou · protesilaos.com

* Getting into the Emacs mindset

I will to talk to you about my approach to a recurring topic in the
Emacs community, best encapsulated in this question:

/What is your favourite package?/

Similar formulations:

+ What is the one thing that makes Emacs indispensable to you?
+ Which is Emacs' killer app?

Such questions can lead us to valuable findings.  There is truth to be
had in the insights drawn from them and we must learn as much as we can
in the process.

Note though that this type of inquiry expects from us to engage in an
analytical exercise that extracts an object from its milieu.  It puts us
in a frame of mind that can miss the true value proposition of Emacs.

The problématique comes with the latent risk of holding us captive to a
frame of mind characterised by *decontextualisation*, of examining an
object without reference to the environment that renders it possible.

Instead of thinking about workflows that can take you from one context
to another, we are expected to identify some silo of functionalities.
Are we then underestimating everything else that contributes to our
day-to-day /experience/ with Emacs?

* Don't ignore the forest while looking at the tree

Now before I get misunderstood: yes, Org and Magit are great; yes, there
are lots of individual packages that make your life easier; and yes,
there is value in finding which package[s] people enjoy the most.

What about the combination of all utilities?  What about the *gestalt*?

If you claim that “my favourite package is X” and then fail to couch
your statement in terms of the rest of the toolkit you rely on, you are
likely to underappreciate---or altogether ignore---the true value
proposition of Emacs.

You do not acknowledge how the whole system is pieced together.  More
importantly, you may not realise the potential of Emacs' extensibility,
which is dynamic or case-dependent.

In other words, Emacs provides the means to implement a metaphor like
that of the vaunted Unix pipes across its entire space.  In practical
terms, you can connect your email client to your agenda, your RSS reader
to your custom note-taking system, your music manager to your directory
editor, and so on.  And all these can benefit from interfaces for
searching, editing in bulk, etc.

My claim here is that most of the times there is no one package or
narrow subset that make Emacs great.  It rather is the linkages between
several pieces of code that make Emacs a pleasure to work with.  They
contribute to predictable-yet-flexible workflows.  These keep Emacs
relevant and, dare I say, intriguing.

* The three core attributes of Emacs

Emacs is programmable and introspectable.  Both presuppose transparency.
These make the Emacs experience open-ended.

+ Programmable :: One set of features can be made to interface with
  another, even though it was not conceived with the express purpose of
  optimising for that particular scenario.  What can be done with Emacs
  is not predetermined.  There is always scope for something new.

+ Introspectable :: The user can examine the entire code base or a
  specific implementation and, potentially, figure out how to connect to
  it through some other tool.  This is further supported by the robust
  self-documentation facilities of Emacs, as well as the high quality of
  material that is readily available through the built-in Info reader.
  Introspection has contributed to the /documentation culture/ that
  characterises the Emacs community at-large.

+ Transparent :: Emacs does not conceal its internals.  Virtually every
  case can be handled using the same language the code is written in
  (Emacs Lisp) while benefiting from live evaluation of new code.  You
  change something and you see it in action.  Combined with the
  self-documenting nature of Emacs, transparency provides insight into
  practically every single construct that makes up Elisp.  Which
  empowers us to make best use of Emacs' programmability.

When considered together, these engender the *interconnectedness* that
defines the Emacs space.
* Introspection in action

Quick demo of running =C-h o= (=describe-symbol=) over =mapcar= and =mapconcat=
and then testing those expressions.

#+begin_src emacs-lisp
(mapcar #'upcase '("one" "two" "three"))

(mapconcat #'upcase '("one" "two" "three") "-")
#+end_src

We can use =C-x C-e= (=eval-last-sexp=) to get live feedback of what each
function does.

We can check the log with =C-h e= (=view-echo-area-messages=).

These are the rudimentary tools you rely on to start using ELisp.  They
offer you the means to experiment with how to extend Emacs.
* A quick look at combining tools

Now let me switch to another window layout, where I have some plain text
files in a standard directory.  Nothing fancy here.  Just to show how
standard Emacs tools can combine together to deliver a consistent
computing experience.

+ Switching to another layout involves the built-in tabs (=tab-bar-mode=)
  plus some bespoke code of mine.
+ Find file at point using a filename or just part of a file (=C-x C-f M-n=).
+ Use a completion framework (=icomplete-mode= in my case).
+ Benefit from a pattern-matching style (=orderless= for me).
+ Jump to the directory that contains the file (=dired-jump=).
+ While in Dired, jump to an item using completion (=dired-goto-file=).
+ Or filter the Dired list and then find the item (=% m= potentially
  followed by =t k=).

* Interconnectedness in the Emacs space

My point is to highlight the true value of Emacs' extensibility.  Which
is realised in the connections you make between several pieces of
functionality.

And, as I already mentioned, one package does not need to know about the
presence of another /in advance/.

Your focus should be on the workflow.  On the whole system that helps
you get things done with Emacs.  Because that is what your actual
experience is about.  You benefit from the set of /emergent qualities/
that become available in the combination of otherwise disparate pieces
of functionality.

Let me stress the importance of interconnectedness in the Emacs space by
showing you another quick demo that combines three distinct packages
that were not developed for the express purpose of being combined
together:

+ =elfeed= for reading RSS/Atom feeds.
+ =bongo= for managing media files or links.
+ And my own experimental note-taking system (=usls=).

Finally, this entire presentation is made possible by combining several
tools:

+ =org-mode=
+ =olivetti-mode=
+ =org-tree-slide-mode=
+ =variable-pitch-mode=
+ my own commands for setting fonts
</code></pre>
        
      


guid: https://protesilaos.com/codelog/2020-10-24-org-export-dispatcher-face/
title: Org’s export dispatcher has a new face for its keys
url: https://protesilaos.com/codelog/2020-10-24-org-export-dispatcher-face/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p class="info"><strong>Update 2020-10-25 10:57 +0300:</strong> Added screen shots with the Modus
Operandi and Modus Vivendi themes.</p>

<p class="info"><strong>Update 2020-11-28 15:33 +0300:</strong> Update screen shots for
<code>modus-themes</code> version <code>1.0.0</code>.</p>

<p>As of commit <code>7ebb2d562</code> in the git repo of Emacs’ Org mode, the export
dispatcher uses a new face to highlight its available keys and possible
options: <code>org-dispatcher-highlight</code>.  It supersedes the general purpose
<code>org-warning</code> for this particular interface.</p>

<h2>Before and after</h2>

<p>This demonstration is on <code>emacs -Q</code>.  First without the patch and then
with it:</p>

<p><img alt="Org dispatcher before" src="https://protesilaos.com/assets/images/attachments/org-export-dispatcher-face-old.png" /></p>

<p><img alt="Org dispatcher after" src="https://protesilaos.com/assets/images/attachments/org-export-dispatcher-face-new.png" /></p>

<p>And below are <a href="https://protesilaos.com/emacs/modus-themes">my Modus themes</a>
(Modus Operandi and Modus Vivendi, version <code>1.0.0</code> or higher) with the
new face tweaked to match their established metaphors.  We apply yellow
colouration to convey a sense of urgency, as the dispatcher is a special
window that remaps common key bindings by assigning special commands to
them:</p>

<p><img alt="Modus Operandi Org dispatcher wide" src="https://protesilaos.com/assets/images/attachments/modus-operandi-org-export-wide.png" /></p>

<p><img alt="Modus Operandi Org dispatcher narrow" src="https://protesilaos.com/assets/images/attachments/modus-operandi-org-export-narrow.png" /></p>

<p><img alt="Modus Vivendi Org dispatcher wide" src="https://protesilaos.com/assets/images/attachments/modus-vivendi-org-export-wide.png" /></p>

<p><img alt="Modus Vivendi Org dispatcher narrow" src="https://protesilaos.com/assets/images/attachments/modus-vivendi-org-export-narrow.png" /></p>

<h2>In the interest of usability</h2>

<p>The <a href="https://lists.gnu.org/archive/html/emacs-orgmode/2020-10/msg00158.html">email to the Org mailing
list</a>
reveals my rationale:</p>

<blockquote>
  <p>The export dispatcher’s active keys are highlighted using the
<code>org-warning</code> face.  That face is applied in various contexts,
including the agenda.</p>

  <p>Users who have difficulty reading the active keys of the export
dispatcher are therefore forced to modify <code>org-warning</code> throughout
their setup, even though their problem is present only while viewing
the dispatch UI (because highlighted keys are one or a few characters
long).</p>

  <p>The attached patch is an attempt to address this issue by creating a
new face that is specifically designed for the dispatch UI.</p>

  <p>For the background+foreground combinations, the selected values conform
with the highest accessibility standard for colour contrast (WCAG AAA,
else a minimum contrast ratio of 7:1).  I limited my options to what
<code>M-x list-colors-display</code> provides.</p>
</blockquote>

<p>The relevant diff:</p>

<pre><code class="language-diff"> lisp/org-faces.el | 14 ++++++++++++++
 lisp/ox.el        |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/lisp/org-faces.el b/lisp/org-faces.el
index c0556b8bb..94b283ad6 100644
--- a/lisp/org-faces.el
+++ b/lisp/org-faces.el
@@ -45,6 +45,20 @@ The foreground color of this face should be equal to the background
 color of the frame."
   :group 'org-faces)
 
+(defface org-dispatcher-highlight
+  '((default :weight bold)
+    (((class color) (min-colors 88) (background dark))
+     :background "gray20" :foreground "gold1")
+    (((class color) (min-colors 88) (background light))
+     :background "SlateGray1" :foreground "DarkBlue")
+    (((class color) (min-colors 16) (background dark))
+     :foreground "yellow")
+    (((class color) (min-colors 16) (background light))
+     :foreground "blue")
+    (t :inverse-video t))
+  "Face for highlighted keys in the dispatcher."
+  :group 'org-faces)
+
 (defface org-level-1 '((t :inherit outline-1))
   "Face used for level 1 headlines."
   :group 'org-faces)
diff --git a/lisp/ox.el b/lisp/ox.el
index 6dd2cd4a0..5ffd66816 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -6706,7 +6706,7 @@ back to standard interface."
 	    ;; on the first key, if any.  A nil value means KEY will
 	    ;; only be activated at first level.
 	    (if (or (eq access-key t) (eq access-key first-key))
-		(propertize key 'face 'org-warning)
+		(propertize key 'face 'org-dispatcher-highlight)
 	      key)))
 	 (fontify-value
 	  (lambda (value)
</code></pre>

<p>This commit resolves a conundrum that theme developers could find
themselves in:</p>

<ul>
  <li>Should I make the keys in the export dispatcher as clear as possible
without compromising on their utility?</li>
  <li>Or should I allow deadlines in the agenda to have a sense of urgency
without becoming intrusive and outright unpleasant?</li>
</ul>

<p>The introduction of the new face removes this constraint altogether by
disaggregating the uses of <code>org-warning</code>: dispatcher keys can be drawn
in a style that best complements the intended function of their
presentation, while agenda buffers and other interfaces can still
present <em>warnings</em>, such as pending tasks, in a manner that suits the
significations attached to that word.</p>

<p>To retain the old export dispatcher aesthetic, instruct
<code>org-dispatcher-highlight</code> to inherit from <code>org-warning</code> (or petition
your theme’s developer to consider such a reform).  For example:</p>

<pre><code class="language-elisp">(set-face-attribute 'org-dispatcher-highlight nil :inherit 'org-warning)
</code></pre>

<p>Please note that what matters is the presence of a new face, not the
exact colour values assigned to it, as shown by the tweaks I made to it
in my Modus themes.</p>

<h2>Thanks to the community</h2>

<p>I wrote this patch after receiving <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/2#note_427541924">valuable feedback from user
“Anders”</a>
on the Modus themes’ issue tracker.</p>

<p>My gratitude extends to Bastien Guerry, the maintainer of Org mode, for
accepting my code and for their valuable contributions in general.</p>
        
      


guid: https://protesilaos.com/codelog/2020-12-05-modus-themes-1-0-0/
title: Modus themes 1.0.0 (backward-incompatible changes)
url: https://protesilaos.com/codelog/2020-12-05-modus-themes-1-0-0/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Just published version <code>1.0.0</code> of the Modus themes.  The release notes
are reproduced below.  Please read them carefully as there are some
breaking changes that require manual intervention in user init files.</p>

<p>Feel welcome to <a href="https://protesilaos.com/contact/">contact me</a> if you
need to.</p>

<hr />

<h2>Modus themes version 1.0.0</h2>

<p>By Protesilaos Stavrou <a href="mailto:info@protesilaos.com">info@protesilaos.com</a> on 2020-12-05</p>

<p>This entry documents the changes since version 0.13.0 (2020-10-08).
They constitute a major release with backward-incompatible additions
which are described below.</p>

<p>As always, every colour-related modification documented herein conforms
with the overarching accessibility objective of the themes for a minimum
contrast ratio of 7:1 between background and foreground values in their
given combination (conformance with the WCAG AAA standard).</p>

<p>Expect to find examples of basic and advanced customisations in the
comprehensive Info manual bundled with the themes, which is also
available at: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a>.</p>

<h2>Overview of major changes</h2>

<ol>
  <li>
    <p>The option that was present in earlier releases to override the
colour palette has been removed.  It cannot work with byte
compilation.  We must not compromise on performance, especially in
light of the fairly high line count of the themes (broad face
coverage combined with a multitude of customisation options).</p>
  </li>
  <li>
    <p>The code base has been refactored.  The two themes, Modus Operandi
(light) and Modus Vivendi (dark), derive from the same source.</p>
  </li>
  <li>
    <p>The refactoring makes it possible to distribute the two themes as
part of a single package.  You can find <code>modus-themes</code> on MELPA, with
other archives and core Emacs following suit soon thereafter (the
Modus themes are built into Emacs since their version 0.12.0).</p>
  </li>
  <li>
    <p>The <code>modus-operandi-theme</code> and <code>modus-vivendi-theme</code> packages in
MELPA and GNU ELPA are obsolete.  MELPA has already deleted them and
now only provides <code>modus-themes</code>, while GNU ELPA shall do so soon
enough.</p>

    <ul>
      <li>Package providers of GNU/Linux distros, or other archives, are
encouraged to update their sources so that they only deliver a
single package that covers both themes.</li>
    </ul>
  </li>
  <li>
    <p>To avoid surprises, the refactored code is in the <code>main</code> branch which
becomes the default henceforth.  The <code>master</code> branch, from where all
prior releases were built, is thus deprecated.  Existing installs of
<code>modus-operandi-theme</code> and/or <code>modus-vivendi-theme</code> must manually
switch to the new package sources, which offer a certain guarantee
that they are informed of the breaking changes documented herein.</p>

    <ul>
      <li>Users of <code>straight.el</code> must make sure that they pull from the
<code>main</code> branch.  This may also be the case for other such tools,
though I have not had the time to test them all.</li>
    </ul>
  </li>
  <li>
    <p>The refactoring introduces a unified customisation framework.  Now
all user-facing variables are named <code>modus-themes-*</code> instead of
<code>modus-operandi-*</code> and <code>modus-vivendi-*</code>.  Users of both items can
thus cut down on duplicate code or inelegant workarounds on their
end.  Example:</p>

    <pre><code>modus-operandi-bold-constructs
   |   |   |   |   |   |   |   ====&gt; modus-themes-bold-constructs
modus-vivendi-bold-constructs
</code></pre>
  </li>
  <li>
    <p>The themes now provide common user-facing functions.</p>

    <ul>
      <li>
        <p><code>modus-themes-load-operandi</code> and <code>modus-themes-load-vivendi</code> can be
used in Lisp to load the theme they name, while disabling their
counterpart and running <code>modus-themes-after-load-theme-hook</code>.  The
hook can be used to override or further customise faces (examples
are furnished in the manual).</p>
      </li>
      <li>
        <p><code>modus-themes-toggle</code> interactively switches between Modus Operandi
and Modus Vivendi or opens a minibuffer prompt to select between
the two if none of them is active.  It ultimately calls the
aforementioned functions to load the themes, so it also triggers
the hook.  Bind this command to a key of your convenience (the
author uses F5).</p>
      </li>
      <li>
        <p><code>modus-themes-color</code> returns the colour value of a symbol in the
alists that hold the themes’ palettes.  The alists are
<code>modus-themes-colors-operandi</code> and <code>modus-themes-colors-vivendi</code>.
<code>modus-themes-color</code> always operates on the active theme, making it
suitable for post-theme-load customisations (via the hook we
covered earlier).  Its usage is documented in the manual and is
meant to be employed by those who are prepared to assume
responsibility for face-related changes they introduce on their
setup.</p>
      </li>
      <li>
        <p><code>modus-themes-color-alts</code> occupies the same niche as the one right
above, with the exception that it takes two arguments.  The first
is the alist key to be used by <code>modus-operandi</code> and the second is
for <code>modus-vivendi</code>.</p>
      </li>
      <li>
        <p><code>modus-themes-wcag-formula</code> implements the WCAG formula to measure
a colour value’s relative luminance.  While <code>modus-themes-contrast</code>
applies the formula to derive the contrast ratio between two colour
values in hexadecimal RGB notation.  This can be used to verify the
accessibility of colour combinations provided by the themes or new
ones defined at the user level (the Modus themes conform with the
WCAG AAA standard which means that this kind of contrast is 7:1 or
higher for all applicable background+foreground combinations).</p>
      </li>
    </ul>
  </li>
</ol>

<h2>Customisation options</h2>

<p>This is the complete list with all the customisation options:</p>

<pre><code>modus-themes-slanted-constructs             (boolean)
modus-themes-bold-constructs                (boolean)
modus-themes-variable-pitch-headings        (boolean)
modus-themes-no-mixed-fonts                 (boolean)
modus-themes-headings                       (alist)
modus-themes-scale-headings                 (boolean)
modus-themes-fringes                        (choice)
modus-themes-org-blocks                     (choice)
modus-themes-prompts                        (choice)
modus-themes-mode-line                      (choice)
modus-themes-diffs                          (choice)
modus-themes-syntax                         (choice)
modus-themes-intense-hl-line                (boolean)
modus-themes-paren-match                    (choice)
modus-themes-region                         (choice)
modus-themes-links                          (choice)
modus-themes-completions                    (choice)
</code></pre>

<p>Plus those which are contingent on <code>modus-themes-scale-headings</code>:</p>

<pre><code>modus-themes-scale-1
modus-themes-scale-2
modus-themes-scale-3
modus-themes-scale-4
modus-themes-scale-5
</code></pre>

<p>Consult the manual for each of them and please verify that none of the
older options remains in your init file.</p>

<h3>Customisation options that did not exist in earlier versions</h3>

<p>New entries and their possible values:</p>

<ol>
  <li>
    <p>modus-themes-syntax</p>

    <ul>
      <li>nil (default)</li>
      <li>faint</li>
      <li>yellow-comments</li>
      <li>green-strings</li>
      <li>yellow-comments-green-strings</li>
      <li>alt-syntax</li>
      <li>alt-syntax-yellow-comments</li>
    </ul>

    <p>(supersedes options for “faint syntax” and “comments”)</p>
  </li>
  <li>
    <p>modus-themes-links</p>

    <ul>
      <li>nil (default)</li>
      <li>faint</li>
      <li>neutral-underline</li>
      <li>faint-neutral-underline</li>
      <li>no-underline</li>
    </ul>

    <p>(supersedes options for “no underlines”)</p>
  </li>
  <li>
    <p>modus-themes-paren-match</p>

    <ul>
      <li>nil (default)</li>
      <li>intense</li>
      <li>subtle-bold</li>
      <li>intense-bold</li>
    </ul>

    <p>(supersedes options for “intense paren match”)</p>
  </li>
  <li>
    <p>modus-themes-region</p>

    <ul>
      <li>nil (default)</li>
      <li>no-extend</li>
      <li>bg-only</li>
      <li>bg-only-no-extend</li>
    </ul>
  </li>
</ol>

<p>Furthermore, the <code>modus-themes-diff</code> has a new option to choose from:
the symbol <code>bg-only</code>.  It applies colour-coded backgrounds but does not
override any syntax highlighting that may be present.  This makes it
suitable for use with a non-nil value for diff-font-lock-syntax (which
is the default for diff-mode buffers in Emacs 27 or higher).</p>

<h2>Support for new faces or face groups</h2>

<ul>
  <li>consult</li>
  <li>macrostep</li>
  <li>make-mode</li>
  <li>pdf-tools</li>
  <li>popup</li>
  <li>shr</li>
  <li>sieve-mode</li>
</ul>

<p>(remember that the list of supported packages is already comprehensive)</p>

<p>Thanks to:</p>

<ul>
  <li>
    <p>Adam Spiers for bringing <code>macrostep</code> to my attention.</p>
  </li>
  <li>
    <p>Madhavan Krishnan for submitting the code for pdf-tools:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/14">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/14</a>.</p>
  </li>
  <li>
    <p>Manuel Uberti for reporting the issue with popup.el:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/107">https://gitlab.com/protesilaos/modus-themes/-/issues/107</a>.</p>
  </li>
  <li>
    <p>Again thanks to Manuel for consult:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/123">https://gitlab.com/protesilaos/modus-themes/-/issues/123</a>.  And to
Daniel Mendler, its developer, for communicating with us on the status
of the project.</p>
  </li>
  <li>
    <p>Togan Muftuoglu for reporting the issue with sieve-mode:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/121">https://gitlab.com/protesilaos/modus-themes/-/issues/121</a>.</p>
  </li>
</ul>

<h2>Refinements to existing faces</h2>

<ul>
  <li>
    <p>The diary and holiday marks in <code>M-x calendar</code> are displayed using a
slightly tinted background in order to improve their contrast.
Holidays are also rendered in a bold font.  Thanks to Nicolas De
Jaeghere for reporting the issue and following it up with valuable
feedback: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/127">https://gitlab.com/protesilaos/modus-themes/-/issues/127</a>.</p>
  </li>
  <li>
    <p>Code blocks in <code>markdown-mode</code> now have a subtle background that
extends to the edge of the window.  Thanks to Roman Rudakov for the
suggestion and Hörmetjan Yiltiz for further testing:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/115">https://gitlab.com/protesilaos/modus-themes/-/issues/115</a>.</p>
  </li>
  <li>
    <p>Inline code in <code>markdown-mode</code> has a subtle background that covers the
length of the construct.  Refer to issue #115 as above.</p>
  </li>
  <li>
    <p>Ivy’s main pattern-matching faces are slightly adjusted to work more
effectively when users opt for “modus-themes-completions ‘moderate” or
“modus-themes-completions ‘opinionated”.</p>
  </li>
  <li>
    <p>Swiper’s <code>swiper-isearch</code> command defaults to a more colourful
presentation that clearly disambiguates matching pattern groups
between themselves as well as their own active and inactive states.
Thanks to John Haman for reporting the problem:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/125">https://gitlab.com/protesilaos/modus-themes/-/issues/125</a>.</p>
  </li>
  <li>
    <p>Swiper’s remaining faces are tweaked to better convey the intent of
this tool.</p>
  </li>
  <li>
    <p>The border of <code>ivy-posframe</code> is more noticeable.  Thanks to Pete
Kazmier: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/126">https://gitlab.com/protesilaos/modus-themes/-/issues/126</a>.</p>
  </li>
  <li>
    <p>The <code>fringe</code> face no longer returns a nil background, which allows
<code>dap-ui-controls-mode</code> to display things properly.  Thanks to Simon
Pugnet: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/106">https://gitlab.com/protesilaos/modus-themes/-/issues/106</a>.</p>
  </li>
  <li>
    <p>Tags and priority cookies in Org mode no longer have a box property.
This is because of changes in upstream Org that we helped solve and
that are covered in the previous CHANGELOG entry (in short: Org
heading constructs inherit the underlying heading’s properties that
are not part of their own specs, while they retain those that are
explicitly defined for them—adaptive headings).  Properly solves the
following issues:</p>

    <ul>
      <li>
        <p><a href="https://gitlab.com/protesilaos/modus-themes/-/issues/104">https://gitlab.com/protesilaos/modus-themes/-/issues/104</a>.  Thanks
to user “bepolymathe”.</p>
      </li>
      <li>
        <p><a href="https://gitlab.com/protesilaos/modus-themes/-/issues/95">https://gitlab.com/protesilaos/modus-themes/-/issues/95</a>.  Thanks
to Roman Rudakov.</p>
      </li>
    </ul>
  </li>
  <li>
    <p>The faces of <code>M-x re-builder</code> are less intrusive.</p>
  </li>
  <li>
    <p>All the following now inherit from basic font-lock faces and thus
benefit from options such as <code>modus-themes-syntax</code>:</p>

    <ul>
      <li>geiser</li>
      <li>nxml-mode</li>
      <li>tuareg</li>
      <li>web-mode</li>
      <li>xah-elisp-mode</li>
    </ul>
  </li>
  <li>
    <p>Diff headers have a subtle grey background that extends to the edge of
the window.</p>
  </li>
  <li>
    <p>The faces of log-view and change-log use colour combinations that
better differentiate the various objects on display.</p>
  </li>
  <li>
    <p><code>font-lock-type-face</code> uses a cyan hue instead of magenta.</p>
  </li>
  <li>
    <p><code>magit-header-line-key</code> uses a blue foreground colour instead of red.</p>
  </li>
  <li>
    <p>Doc strings in code syntax are rendered in a new dedicated colour.
The change is fairly subtle and should practically go unnoticed.</p>
  </li>
  <li>
    <p><code>org-date</code> now respects the <code>modus-themes-no-mixed-fonts</code> option.
Thanks to user “fleimgruber” for reporting the issue:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/124">https://gitlab.com/protesilaos/modus-themes/-/issues/124</a>.</p>
  </li>
  <li>
    <p><code>org-property-value</code> uses a slightly different shade of cyan.</p>
  </li>
  <li>
    <p><code>dim-autoload</code> will always look like a regular comment.</p>
  </li>
  <li>
    <p>The <code>italic</code> face is inhereted by all relevant faces instead of
hard-wiring a slant property.  This offers the potential advantage of
specifying a distinct family (or other properties) for constructs that
are meant to be rendered in italics (the manual has an example in its
DIY sections for this scenario though it uses the <code>bold</code> face—just
apply the same idea to the <code>italic</code> face).</p>
  </li>
  <li>
    <p><code>dictionary-reference-face</code> inherits from <code>button</code> (as with all
links).</p>
  </li>
  <li>
    <p>Several comment-related faces beyond the basic ones work with
<code>modus-themes-syntax</code> when that has an effect on the colour of
comments.  The faces are:</p>

    <ul>
      <li>git-commit-comment-file</li>
      <li>git-commit-comment-heading</li>
      <li>git-rebase-comment-hash</li>
      <li>git-rebase-comment-heading</li>
    </ul>
  </li>
  <li>
    <p><code>transient-value</code> is more noticeable and fits better in its context.</p>
  </li>
  <li>
    <p>All remaining Org metadata-related faces are refined for consistency
between them in an attempt to make them unobtrusive.  More subtle
colouration is applied.  Affected faces:</p>

    <ul>
      <li>org-drawer</li>
      <li>org-property-value</li>
      <li>org-special-keyword</li>
    </ul>
  </li>
</ul>

<h2>Theme-related contributions to the wider community</h2>

<ul>
  <li>
    <p>Defined the <code>log-view-commit-body</code> for Emacs 28.1:
<a href="https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg00303.html">https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg00303.html</a>
and
<a href="https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg02196.html">https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg02196.html</a>.</p>
  </li>
  <li>
    <p>Specified the version of the <code>diff-error</code> face for Emacs 28.1:
<a href="https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg01328.html">https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg01328.html</a>.</p>
  </li>
  <li>
    <p>Added the <code>org-dispatcher-highlight</code> face to upstream Org:
<a href="https://lists.gnu.org/archive/html/emacs-orgmode/2020-10/msg00158.html">https://lists.gnu.org/archive/html/emacs-orgmode/2020-10/msg00158.html</a>.</p>

    <ul>
      <li>Report with screenshots:
<a href="https://protesilaos.com/codelog/2020-10-24-org-export-dispatcher-face/">https://protesilaos.com/codelog/2020-10-24-org-export-dispatcher-face/</a>.</li>
    </ul>
  </li>
  <li>
    <p>Helped fix face of Flymake’s unknown backend in inactive modelines:
<a href="https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg01119.html">https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg01119.html</a>.</p>
  </li>
  <li>
    <p>Solved bug#44198 about a user not knowning the themes are in Emacs:
<a href="https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-10/msg02001.html">https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-10/msg02001.html</a>.</p>
  </li>
</ul>

<h2>Miscellaneous</h2>

<ul>
  <li>
    <p>The new default <code>main</code> branch of the Modus themes’ git repo is an idea
that was presented by user “Emacs Contrib” in issue 112:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/112">https://gitlab.com/protesilaos/modus-themes/-/issues/112</a>.  Raising
awareness about the negative impact of potentially, tacitly, or
explicitly offensive language is a goal worth pursuing.  Plus “main”
is a more appropriate name for the primary branch of a project and we
do not lose anything by introducing this change as part of version
1.0.0, which anyhow requires manual interventions in user
configurations.</p>
  </li>
  <li>
    <p>Thanks to Manuel Uberti, Jeremy Friesen, and Gitlab user “Eugene” for
their feedback during the process that eventually led to the
development of the <code>modus-themes-syntax</code> customisation option:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/105">https://gitlab.com/protesilaos/modus-themes/-/issues/105</a>.</p>
  </li>
  <li>
    <p>Thanks to André Alexandre Gomes for the feedback in issue 111, which
led to the simplification of the manual’s references to Guix:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/111">https://gitlab.com/protesilaos/modus-themes/-/issues/111</a>.</p>
  </li>
  <li>
    <p>Thanks to Nicolas De Jaeghere for noting that BBDB is indirectly
supported: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/128">https://gitlab.com/protesilaos/modus-themes/-/issues/128</a>.</p>
  </li>
</ul>

<p>Between the refactoring of the code base and all other changes, this has
been yet another period of hard work to deliver on the promise of themes
that are (i) highly accessible and (ii) comprehensive in both their face
coverage and customisation options, while always conforming with the
highest accessibility standard for legible text.</p>

<p>Special thanks to the MELPA maintainers for all their contributions.
MELPA is an integral part of the wider Emacs community.  Thanks, in
particular, to Chris Rayner who has reviewed all my pull requests
hitherto, and to Jonas Bernoulli for checking the latest one (and its
concomitant issue) that introduced the new <code>modus-themes</code> package.</p>

<p>Thank you, the reader, for your attention and for understanding the
longer term benefits of the refactoring, despite the short term friction
it may have introduced.</p>
        
      


guid: https://protesilaos.com/codelog/2020-12-27-modus-themes-review-rainbow-delimiters/
title: Modus themes: review rainbow-delimiters faces
url: https://protesilaos.com/codelog/2020-12-27-modus-themes-review-rainbow-delimiters/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>The present report documents the otherwise subtle changes to the styling
of the <code>rainbow-delimiters</code> faces.  I received user feedback from
Christopher Dimech, to whom I am most thankful.  What we have tried to
achieve is two-fold (any errors are my own):</p>

<ol>
  <li>Broaden the selection of colours, without prejudice to the
overarching accessibility standard of the themes (quantified as a
contrast in relative luminance of 7:1 between any given combination
of background and foreground—the WCAG AAA standard).</li>
  <li>Control the colour distance between adjacent values, as those apply
to each level of delimiter depth.</li>
</ol>

<p>Those combined enhance the “rainbow” quality of the aforementioned
library and, thus, make the support for it at the theme level better
overall.</p>

<h2>Before and after</h2>

<p>Here are some close-up screenshots comparing the levels of delimiter
depth between old and new styles.  Notice how the first level of the new
ones is the same as the main foreground (black/white).  This little
touch ensures that you do not get colouration with no semantic value for
balanced expressions that are only one level deep.</p>

<p><img alt="Modus Operandi delimiters old" src="https://protesilaos.com/assets/images/attachments/modus-operandi-rainbow-delimiters-parens-old.png" /></p>

<p><img alt="Modus Operandi delimiters new" src="https://protesilaos.com/assets/images/attachments/modus-operandi-rainbow-delimiters-parens-new.png" /></p>

<p><img alt="Modus Vivendi delimiters old" src="https://protesilaos.com/assets/images/attachments/modus-vivendi-rainbow-delimiters-parens-old.png" /></p>

<p><img alt="Modus Vivendi delimiters new" src="https://protesilaos.com/assets/images/attachments/modus-vivendi-rainbow-delimiters-parens-new.png" /></p>

<h2>Contexualised effect</h2>

<p>Using those same styles, here is some code.  Open the images to see them
at full scale.  Also remember that bold and slanted constructs are
optional, as well as several other parameters—consult <a href="https://protesilaos.com/emacs/modus-themes">the Modus
themes manual</a>).</p>

<p><img alt="Modus Operandi delimiters code old" src="https://protesilaos.com/assets/images/attachments/modus-operandi-rainbow-delimiters-code-large-old.png" /></p>

<p><img alt="Modus Operandi delimiters code new" src="https://protesilaos.com/assets/images/attachments/modus-operandi-rainbow-delimiters-code-large-new.png" /></p>

<p><img alt="Modus Vivendi delimiters code old" src="https://protesilaos.com/assets/images/attachments/modus-vivendi-rainbow-delimiters-code-large-old.png" /></p>

<p><img alt="Modus Vivendi delimiters code new" src="https://protesilaos.com/assets/images/attachments/modus-vivendi-rainbow-delimiters-code-large-new.png" /></p>

<h2>Colour distance between the old colours</h2>

<p>The following tables, written in <code>org-mode</code> notation, calculate the
colour distance between adjacent delimiter foregrounds while accounting
for their positional placement (so 1 compared with 2, 2 with 3, and so
on):</p>

<pre><code class="language-org">#+DESCRIPTION: Colour distance between foregrounds (Modus Operandi old)
| 1       | 2       | Distance |
|---------+---------+----------|
| #145c33 | #5317ac |    69287 |
| #5317ac | #005a5f |    50065 |
| #005a5f | #863927 |    53989 |
| #863927 | #0000c0 |   118623 |
| #0000c0 | #315b00 |   146343 |
| #315b00 | #8f0075 |    90740 |
| #8f0075 | #30517f |    48311 |
| #30517f | #70480f |    43837 |
#+TBLFM: $3='(color-distance $1 $2)

#+DESCRIPTION: Colour distance between foregrounds (Modus Vivendi old)
| 1       | 2       | Distance |
|---------+---------+----------|
| #00cd68 | #b6a0ff |   147580 |
| #b6a0ff | #6ae4b9 |    45596 |
| #6ae4b9 | #f0ce43 |    82999 |
| #f0ce43 | #00bcff |   234824 |
| #00bcff | #80d200 |   219273 |
| #80d200 | #f78fe7 |   178927 |
| #f78fe7 | #4ae8fc |   112296 |
| #4ae8fc | #cfdf30 |   148519 |
#+TBLFM: $3='(color-distance $1 $2)
</code></pre>

<p>You can see in the third column that the colour distance is
inconsistent, with some combinations being better than others.  Our
intent here is to normalise the distance between each pair so that the
results are more uniform.</p>

<h2>Colour distance between the new colours</h2>

<p>Same principle as above, only now we are applying new colours in a
different sequence that is conducive to our ends.  You can now tell that
the third column shows a greater level of consistency, understood as a
harmonised distance in colour space between each pair.</p>

<pre><code class="language-org">#+DESCRIPTION: Colour distance between foregrounds (Modus Operandi new)
| 1       | 2       | Distance |
|---------+---------+----------|
| #000000 | #a8007f |   109670 |
| #a8007f | #005f88 |   102860 |
| #005f88 | #904200 |   101746 |
| #904200 | #7f10d0 |   118454 |
| #7f10d0 | #006800 |   187726 |
| #006800 | #b60000 |   122282 |
| #b60000 | #1f1fce |   169872 |
| #1f1fce | #605b00 |   141743 |
#+TBLFM: $3='(color-distance $1 $2)

#+DESCRIPTION: Colour distance between foregrounds (Modus Vivendi new)
| 1       | 2       | Distance |
|---------+---------+----------|
| #ffffff | #ff62d4 |   103094 |
| #ff62d4 | #3fdfd0 |   160498 |
| #3fdfd0 | #fba849 |   149161 |
| #fba849 | #9f80ff |   103680 |
| #9f80ff | #4fe42f |   166683 |
| #4fe42f | #fe6060 |   157802 |
| #fe6060 | #4fafff |   166841 |
| #4fafff | #f0dd60 |   137617 |
#+TBLFM: $3='(color-distance $1 $2)
</code></pre>

<p>The exact same distance is not always possible, because each colour
value must also conform with our accessibility target when compared to
its background.  What we do here is an approximation or else an attempt
to optimise the use of resources within an overarching constraint (a
good one, but a constraint nonetheless).</p>

<h2>Ongoing refinements</h2>

<p>Note that it is always easier to work with colours against a dark
backdrop.  Colour is luminant and darkness is interpreted as the absence
of luminance, so nuances are easier to spot.  This, in turn, means that
the potential for errors is greater, even after having narrowed the
colour space to only the values that pass the accessibility criterion of
the themes (the 7:1 contrast—also check the <code>modus-themes-contrast</code>
function that is documented in the manual).</p>

<p>Technicalities aside, this review constitutes another step towards
delivering a comprehensive package for styling GNU Emacs in accordance
with the highest legibility standard.  It comes just a few days after
the overhaul of the <code>org-habit</code> faces (no report for that as I had other
things to write, but you can read the minutia in <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/135">issue
135</a>—thanks
again to Gustavo Barros for the feedback there).</p>

<p>With the major release of version <code>1.0.0</code> earlier this month, we are in
the process of iterating on what already is a solid basis.  Propitious
growth, one might say.</p>

<p>If you use the themes and feel that something does not work well enough,
please <a href="https://protesilaos.com/contact">contact me</a>.  I am always eager
to review things and learn from your insights.</p>
        
      


guid: https://protesilaos.com/codelog/2020-12-28-comment-unix-vs-emacs/
title: Comment on Unix versus Emacs
url: https://protesilaos.com/codelog/2020-12-28-comment-unix-vs-emacs/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>I receive messages from time to time asking me to share my views on the
topic of whether Emacs can fit into a Unix-centric workflow.  One such
email arrived in my inbox yesterday.  I replied to it and asked whether
I could publish the answer on my website, while omitting all private
information.</p>

<p>My commentary is reproduced below.  In block quotes (indented
paragraphs) are the statements I am replying to.</p>

<hr />

<blockquote>
  <p>For the past 2-3 months I having using Emacs as my “Integrated
Environment” but unlike my vim days I am struggling to recommend
it to someone or convince myself ‘Emacs » vim+cli-tools’.</p>

  <p>For ex:</p>
  <ul>
    <li>Why use vim? -&gt; To edit text efficiently.</li>
    <li>Why use TWM? -&gt; You can manage TUI with ease.</li>
    <li>Why use Emacs? -&gt; For integrity? For lisp? For Emacs-like-bindings?</li>
  </ul>
</blockquote>

<p>I think Vim and Emacs are quite similar in several key areas:
interactive, extensible, scriptable, and featureful out-of-the-box or
with third-party extensions.  The differences are matters of approach,
perspective, and degree or concern issues of a secondary nature and/or
ancillary utility.</p>

<p>The fact that Vim and Unix are talked about in the same breadth suggests
to me that we—the general “we”—are treating terms somewhat
cavalierly.  If one wants to remain faithful to Unix, then why are they
making a special exception for Vim, instead of using vi, ed, or just
sed?  Those other programs are truer to the Unix ethos of small
specialised tools.</p>

<p>For example, newer versions of Vim come with the <code>:term</code> command that
spawns a built-in terminal.  And we still pretend that Vim partakes of
the Unixy quality while Emacs does not.</p>

<p>To be clear, I am not arguing that Vim should not have such a feature.
It is useful and am sure a lot of people like it, especially in light of
NeoVim gaining ground in the community.  I am just pointing out an
inconsistency in the thesis of those who extol the Unix virtues while
still peddling Vim as a paragon of minimalism.</p>

<blockquote>
  <p>My main concern with Emacs is “we are trying to redo everything
in elisp or we are trying to run a elisp WM” which is quite
different from what I have learned.</p>

  <p>Video: https://www.youtube.com/watch?v=1mr3issv79s</p>
</blockquote>

<p>I think no one needs to switch to Emacs.  If what you already have
covers your needs, then there is absolutely no reason to redo everything
and refashion it as its Elisp equivalent.</p>

<p>With regard to Luke’s video, I feel that he is making an assessment on
the premise of indirect or incomplete information.  Again, no one has to
switch to Emacs.  Though if you are the kind of person who wants to
speak their mind from a position of knowledge, you need to stop being
opinionated and vociferous about something you have not given a fair
chance to and tried in earnest.  To put it differently, start using
Emacs from scratch, go through the manual, tinker with Elisp, work full
time with it for ~6 months and then tell us what you think.  “But I do
not want to!”  Well, I repeat that you do not have to.</p>

<p>This is how I converted to Emacs in the summer of 2019.  Started with an
empty init file, without any prior experience in Lisp (and I am not a
programmer anyway), and with no false expectations of wanting Emacs to
become my powerhouse of productivity from day one.  The first days were
very difficult.  Fast forward to present time and am happy to have made
such an investment: there is no going back.</p>

<p>The whole “switching to Emacs” theme is something I discussed at length
one year ago (watch <a href="https://protesilaos.com/codelog/2019-12-20-vlog-switch-emacs/">All about switching to Emacs</a>
(2019-12-20)). Also, I agree that Org being ‘cool’—whatever that
means—is not a compelling reason to try it: I am not much of an Org
user myself.  In a more recent video I talked about the concept of
“favourite package” in the Emacs milieu (watch <a href="https://protesilaos.com/codelog/2020-10-21-emacs-favourite-package/">Why Emacs itself is my
“favourite Emacs package”</a>
(2020-10-21)).</p>

<blockquote>
  <p>This video [of Luke] really provide some good reasons why to invest on
‘coreutils’ to build a small, maintainable and decentralized system
rather than investing on a giant mutable system.</p>
</blockquote>

<p>Prior to switching to Emacs, I was using BSPWM+Vim+Tmux+CLI for years.
My Vim had no plugins at all.  For email I had mutt, newsboat for feeds,
ncmpcpp+mpd for music, lemonbar for a system panel…  Everything was
done in accordance with this notion of “small, maintainable and
decentralized” programs that are loosely tied together into a computing
environment.</p>

<p>The main problem with such a framework is that there is no layer of
integration between those tools.  When you actually start piecing
together a system you are introducing complexity on a case-by-case, ad
hoc manner, because you now need to write extra code that connects the
otherwise disparate tools.  Can you make your ncmpcpp interface with
newsboat?  Would you like to be able to capture the contents of a mutt
email and produce a note or to-do task out of them?</p>

<p>You can of course tie all those together.  Though you will oftentimes
have to use Vimscript for Vim, some other syntax for mutt, newsboat,
ncmpcpp+mpd, yet another for the suckless programs, another still for
Lemonbar, Polybar or whatever, and so on.</p>

<p>Not only are configuration or scripting languages/paradigms different,
discoverability is also inconsistent.  Vim has on-line help.  Others
have man pages, suckless expects you to read some incomplete README
which constitutes a misunderstanding of minimalism and/or study the
source code.  Again, these are discrepancies that you need to
circumvent, while rationalising them ex post facto as virtues of
peerless Unix engineering.</p>

<p>Side note: I define minimalism as minimum necessary completeness.
Incomplete documentation fails the completeness test.  For a more
theoretical take, read my <a href="https://protesilaos.com/notes-simplicity/">Notes on simplicity</a> (2019-06-22).</p>

<p>So the “small and decentralised” stops being as “maintainable” as you
would like to think of it in abstract.  Those issues accumulate and
culminate in an inconsistent user experience.  Say you have some nice
theme for Vim.  Now you need to write another theme for newsboat, mutt,
ncmcpp, dmenu, lemonbar…  You get the point.</p>

<p>I am a firm believer in the Unix philosophy, though I do not interpret
it as a dogma but as a set of guidelines whose scope of application is
strictly confined to a given paradigm of interaction.  When the
constitution of the case changes, so must the reasoning about it, else
there is no correspondence between the theory and the reality it is
supposed to apply to.  Unix works well when you are dealing with text
streams.  It leaves something to be desired when you need interactivity
and consistency across a wide range of applications.</p>

<p>For some more abstract writings, read:</p>

<ul>
  <li><a href="https://protesilaos.com/ethos-dialectic">On the Dialectician’s Ethos</a> (2020-09-30).</li>
  <li><a href="https://protesilaos.com/materiality-emergence">On materiality and emergence</a> (2020-12-20).</li>
</ul>

<blockquote>
  <p>Rather than talking in abstract I will now jump straight to my question:
“Why I should add a layer of complexity on my system rather than using
existing tools(coreutils, pipes, …)”</p>
</blockquote>

<p>I believe your question already assumes the answer you expect.  If you
frame Emacs as “complexity” and, by extension, as being a priori surplus
to requirements, then it follows that you do not want it, for that would
be frivolous.</p>

<p>If, on the other hand, you take a critical look at the emergent system
of several Unixy tools in unison, like my BSPWM setup from yesteryear,
then you must think of things in a new light: “what is missing from my
coreutils, pipes, and friends?”.  Then you can start searching for ways
to ameliorate the issues I outlined above, namely, to achieve a greater
level of consistency and integration between otherwise standalone
applications.  How you go about it is your prerogative.</p>

<p>I treat Emacs as a layer of interactivity on top of Unix.  For example,
I wanted to refactor some things in my website’s code base.  I ran an
rg/grep command to put the results in a buffer.  Then I edited that
buffer and saved my changes.  Voila!  A ~1000 matches rewritten in a
matter of seconds, all while I could do things interactively and use the
full power of Emacs’ editing capabilities.  Yes, I could probably do the
same with grep, sed, or whatnot, but I would still be missing that ease
of use, indeed the safety, of performing such sweeping changes from the
comfort of Emacs.</p>

<p>Which brings me to the final point: is anyone going to give me hacker
points for relying only on grep and sed?  Do I want to turn my computing
environment into a tokenistic affair; a symbolism that captures my
vanity and pretences on social standing?  Do I want to become an avatar
of social expectations, seeking to extract as much “nerd credibility”
out of my fellows’ ideas about me?  Or do I want to get work done and do
so while benefiting from a comprehensive, integrated, singular
experience?  I just want the latter and am unapologetic about it.</p>

<p>This is not to claim that only Emacs can perform such tasks.  Maybe Vim
or some other program can do those as well.  Good!  Use whatever feels
right for you.  My position is more nuanced: we should avoid the
pitfalls that come with ideology and ideocentric perspectives on states
of affairs.  Are you working exclusively with text streams?  Then write
a one-liner on the command line that pipes some output to sed and you
are good to go.  Do you need interactivity?  Then forget about Unix
pipes and use the right tool for the job.  Whether that is Emacs, Vim,
or whatever is another discussion altogether; one that I do not find
particularly interesting and fecund.</p>

<p>In conclusion, I am of the opinion that propitious enthusiasm is all too
often the source of self-righteousness and misguided attempts at
evangelism.  We witness such a recurring theme happen with Unix, Arch
Linux, Emacs, and more.  Some user discovers a new cool workflow and now
they want to convert their peers to it.  This hints at the kind of
thinking that treats the world in simplistic, binary terms: Unix is
simple VS Emacs is complex; Arch Linux is for hackers VS Ubuntu is for
simpletons…  Those are stereotypes that rest on misunderstandings
about the intent and the purpose of each of those paradigms, their
context-specific pros and cons, as well as the potentially numerous
reasons one may have to opt for a given choice.</p>

<p>To my mind, the exuberant disciple is prone to dogmatism because they
read the rules as the single source of authority, while the teacher who
has long studied and internalised those topics knows the extent of their
application—their limitations, that is—and, above all, understands
when they should be circumvented and how.</p>
        
      


guid: https://protesilaos.com/codelog/2021-01-06-emacs-default-completion/
title: Default Emacs completion and extras
url: https://protesilaos.com/codelog/2021-01-06-emacs-default-completion/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=43Dg5zYPHTU">https://www.youtube.com/watch?v=43Dg5zYPHTU</a></p>
         
         <p>In this video I offer an overview of my current completion framework for
Emacs.  It consists of a set of modules that are pieced together into a
robust system.  The centrepiece is the standard minibuffer.</p>

<p>The text of the presentation is available right below (<code>org-mode</code>
notation).  Refer to my Emacs configuration file (“dotemacs”) for the
implementation details of my completion framework and everything else I
currently have: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.</p>

<hr />

<pre><code class="language-org">#+TITLE: Default Emacs completion and extras
#+AUTHOR: Protesilaos Stavrou · protesilaos.com

* Piecing together a completion framework

Today I will talk to you about how I currently handle completion in
Emacs.  The plan is to tour you around the various tools I use; tools
which comprise my system for narrowing down a list of candidates.

My system consists of the following constituents:

+ Default minibuffer (exactly what you get when you run =emacs -Q= from
  the command line).
+ =orderless= completion style, which extends the built-in list of pattern
  matching =completion-styles=.
+ =embark= to visualise the list of completion candidates, as well as
  provide actions on a per-item or per-set basis.
+ =consult= to enhance several minibuffer-centric commands.
+ =marginalia= to provide meta-information to various completion lists.

All of the above are modular tools that are independent of each other
yet can operate in tandem.  One can, for example, use =icomplete= or
=selectrum= instead of the default minibuffer.

* Orderless and the built-in ~partial-completion~

As its name suggests, Orderless matches groups out-of-order.  A "group"
can be one among many styles, including a regular expression, a literal
string, an initialism, and so on.  The styles are configurable, while
the list is comprehensive.

Orderless has a concept of "style dispatchers".  Those are user-defined
single characters that are used as a suffix to each group and assign to
it a particular pattern matching style.  For example, I use the equals
sign to declare that a group should be read as a literal string.

While the built-in =partial-completion= covers the niche of dynamic
completion for certain commands.  A case in point is with the =find-file=
command (=C-x C-f=), where it can expand an abbreviated path =~/.l/s/fo=
into =~/.local/share/fonts=.

* Embark for per-item actions (part 1)

The best way to conceptualise Embark is as a contextual menu.  It lets
you carry out context-dependent actions on targets.

What constitutes a "target" will depend on the case: it can it the
current item in the completion list, the symbol at point, or some URL
right under the cursor.  Your conduit to this mode of operation is the
=embark-act= command, which you should bind to a convenient key (=C-,= in my
case).

Let us try these actions on individual targets:

+ Get help for =embark-act= by placing point over it.
+ Browse https://protesilaos.com/emacs/modus-themes with =eww=.  Then save the
  link to the kill-ring and yank from there afterwards.
+ Run =describe-function= and insert some function here.
+ Run =M-x switch-buffers= and then kill a buffer instead of switching to
  it.

Each context is bound to a keymap.  The keymap holds the associations
between key bindings and commands that you may call on the given target.

To learn more about the commands you can use after invoking =embark-act=,
type =C-h= (or set up =which-key=---check my dotemacs for the implementation
details).

[ remember that =C-h= as a suffix to any key chord, is a standard way to
  get a Help buffer for all keys that complete the chord ]

* Embark for per-set actions (part 2)

Other than act on a per-item basis, Embark can operate on entire sets of
targets.  Allow me to introduce this concept with an example: we invoke
=M-x describe-keymap= and then search for "embark" to find all keymaps
that pertain to the various contexts in which Embark can perform
meaningful tasks (I bind that help command to =C-h K=).  Now we use
=embark-occur= to produce a persistent buffer with the list of candidates.
It will still run the default action on each target.

You have also seen Embark's "live occur", but let me formally introduce
it to you.  This is a buffer that is initially linked to an active
minibuffer session.  It gets auto-updated to match the input in the
minibuffer and to narrow the list of candidates accordingly.  So if I
call =M-x switch-buffers= (=C-x b=) and type something, this "live occur"
will show me what the matching buffers are.

Because these are standard buffers, we can store them on the disk and
revisit them in the future.  Use =M-x write-file= (=C-x C-w=).

Embark offers another neat utility: =embark-export=.  It produces a buffer
whose major mode matches the category of the targets: =dired-mode= for
files/directories and =ibuffer-mode= for buffers.  Then you can benefit
from the power of those modes.

This per-set functionality of Embark is what allows us to use the
default minibuffer for all completions.  While we could add =icomplete= or
=selectrum= to the mix, there is no need for such an addition.  Embark
live occur merely shows the candidates that are already there and which
the minibuffer is fully aware of.

* Consult for enhanced minibuffer commands

=consult= has a dual purpose:

1. Enhance existing commands, like =M-x imenu= or =M-x switch-to-buffer=.
2. Provide new functionality, such as =consult-line=, =consult-mark=, and
   asynchronously updating grep/find commands.

What this "enhancement" means depends on the case.  Commands such as
those that navigate lines, get an optional preview.  The likes of
=consult-imenu= offer a concept of filtering per type of input: this is
called "narrowing" in Consult's verbiage and is controlled by a key map.

Let us try some common workflows to witness the synergies between the
modules that comprise my system.

+ Visit a large Org file.  Invoke =consult-outline= and produce a
  persistent buffer out of it with =embark-occur=.  This works as an index
  of buffer positions, a "table of contents" if you will.

+ Call =consult-imenu= and use =consult-narrow= to filter by the type of the
  syntactic constructs.

* Marginalia for completion annotations

Finally we have =marginalia=, which you have already seen in the various
Embark live occur buffers I have put on display.  It enriches completion
candidates with pertinent meta information.

Here are some commands that benefit from such annotations:

+ all =describe-*= commands present the first line of the doc string.

+ =switch-to-buffer= (=C-x b=) documents the buffer's major mode and status,
  as well as its underlying file's path.

+ =find-file= (=C-x C-f=) includes the file size, permissions and date.

You get the idea.

Currently those annotations are decorative, in the sense that you cannot
use them as filter predicates or have something like =orderless= do
perform pattern matching against them.  Still, I find this lightweight
utility to be quite valuable.

* A system I can understand

About a year ago I switched from Ivy to Icomplete.  I wanted to simplify
my setup in order to make sense of it.  Doing so helped me learn some
Elisp, mostly through trial and error, and by relying on Emacs'
introspection utilities.  This reminded me of the value proposition of
modularity: a system of linkable-yet-standalone tools is robust in its
own right, while it can be constructed and deconstructed at will both in
pursuit of utilitarian ends and for educational purposes.

By piecing together a system out of Embark, Consult, Orderless,
Marginalia, the default minibuffer, and my extras, I am in a position to
clearly comprehend what is going on.  This is not knowledge for its own
sake: it has the tangible benefit of equipping me with the means to
extend or otherwise tweak my completion framework so that it aligns with
my expectations.

I thus wish to congratulate the authors of those packages.  We have Omar
Antolín Camarena, who develops =embark= and =orderless=.  While Daniel
Mendler produces =consult= (among others).  While both of them maintain
the =marginalia= library.  I really appreciate what they do: their code is
top-notch, but they also invest a lot of effort in documentation.
Manuals and informative READMEs are of paramount importance in bridging
the gap between developers and users.  You read the instructions and you
learn how the thing works.  Then, once you have the requisite confidence
in your abilities, you can delve into the source code.

Here is my rule of thumb: if a project has good docs, then it shows that
the developer is dedicated and meticulous in their work.  Use that as
your guide when picking software.  I am happy to have done so.

* Further information

Refer to my "dotemacs" for my complete setup:
&lt;https://protesilaos.com/emacs/dotemacs&gt;.

And check the Git repositories of all those projects:

+ &lt;https://github.com/minad/consult&gt;
+ &lt;https://github.com/oantolin/embark&gt;
+ &lt;https://github.com/minad/marginalia&gt;
+ &lt;https://github.com/oantolin/orderless&gt;
</code></pre>
        
      


guid: https://protesilaos.com/codelog/2021-01-09-emacs-embark-extras/
title: Embark and my extras (Emacs)
url: https://protesilaos.com/codelog/2021-01-09-emacs-embark-extras/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=uoP9ZYdNCHg">https://www.youtube.com/watch?v=uoP9ZYdNCHg</a></p>
         
         <p>In this video I provide an overview of Embark’s features.  I discuss
everything from the basic concepts of acting on targets, to how you can
extend it as your front-end for completion candidates.  There is also a
demonstration of <code>embark-become</code> and how that can be used to make your
minibuffer-centric workflows more efficient.</p>

<p>The text of the presentation is copied below (<code>org-mode</code> notation).
Refer to my Emacs configuration file (“dotemacs”) for the implementation
details: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.  And check the Git
repositories of the projects I covered:</p>

<ul>
  <li><a href="https://github.com/oantolin/embark">https://github.com/oantolin/embark</a></li>
  <li><a href="https://github.com/minad/consult">https://github.com/minad/consult</a></li>
</ul>

<hr />

<pre><code class="language-org">#+TITLE: Emacs: Embark and my extras
#+AUTHOR: Protesilaos Stavrou · protesilaos.com

* Brief introduction to Embark

Embark provides a unified framework of regular Emacs keymaps which let
you carry out /contextually relevant actions/ on *targets* through a common
*point of entry*, typically a /prefix key/.

+ "Actions" are standard Emacs commands, such as =describe-symbol= or some
  interactive command you have defined that reads an argument from the
  minibuffer.

+ "Targets" are semantically sensitive constructs, such as the symbol at
  point, a URL, a file name, the active region, or the current
  completion candidate in the minibuffer (or the completions'
  buffer---more on that in the next section).  Embark has so-called
  "classifiers" which help it determine the category that the target
  belongs to.

+ The "contextually relevant [actions]" are defined in keymaps whose
  scope matches the category of the target.  So =embark-file-map= holds
  all key and command assossiations for when Embark recognises a file
  name as its target.  =embark-region-map= is for actions pertaining to
  the active region; =embark-buffer-map= for buffer names that you access
  through, say, =switch-to-buffer= (=C-x b=).  And so on.

+ As for the "point of entry" or "prefix key", it is an Embark command,
  such as =embark-act=, =embark-act-noexit=, or =embark-become=.  Those
  activate the appropriate keymap, thus granting you access to the
  relevant commands.

Embark can act on individual targets (e.g. the region) or sets of
targets (e.g. the list of minibuffer completion candidates).
* Embark collections and how to cycle completions

Here we will be discussing Embark's ability to act on a set of targets.
Our specific case is to instruct it (via a hook), to automatically
gather the completion candidates of the minibuffer and put them in a
live-updating buffer.  In other words: a front-end to the minibuffer's
underlying completion mechanisms.

Let's test this with =switch-to-buffer= (=C-x b=) and some input that we
provide.  The "Embark Collect" buffer pops up and shows us what we are
currently matching.  We can then produce a snapshot or export this set
to an appropriate major-mode (=ibuffer-mode= in this case).

I received a lot of questions about my workflow with the Embark
completions buffer.  The idea was:

+ How do you select an item when you narrow to a short list?
+ Do you manually switch from the minibuffer to the completions?

The short answer is that I have written some extensions that handle this
"candidate cycling".

The long answer is best illustrated by an example (the following is a
natural cycling behaviour):

+ =C-n= in the minibuffer takes us to the top of the completions' buffer.
+ =C-p= in the minibuffer moves to the completions' bottom.
+ =C-n= inside the completions' buffer moves the line normally or, when at
  the end, switches to the minibuffer.
+ =C-p= inside the completions' buffer also moves the line, though in the
  opposite direction, and when at the top it switches to the minibuffer.

* Perform default action while cycling

A common workflow with Embark is to produce a snapshot of the
minibuffer's collection you have narrowed to and then inspect that
buffer.

Let's try this with =M-x describe-keymap RET embark= (I bind that help to
=C-h K=).  Then we produce a snapshot with =embark-act= (you have a key
binding for that) and =S= for =embark-collect-snapshot=.

In this buffer we can move up and down normally and hit =RET= when we want
to perform the default action which, in this case, is to get a help
buffer for the symbol at point.

With my =C-M-n= or =C-M-p= we essentially combine =C-n= or =C-p= into a single
motion.  This is useful when we want to continue from one line to the
next, such as by inspecting the help buffer of each of those embark
keymaps that we got the snapshot for.

[ this is a concept I got from Ivy's own version of operating on sets of
  targets ]
* Manual previews for Consult commands (consult.el)

Those specific "move+act" motions allow me to get manual previews for
all =consult.el= commands, even though I use the default minibuffer.
Otherwise I would need to use some other library to cycle candidates,
like =icomplete= or =selectrum=.

So here is an example with =consult-line= and purposeful manual previews:

+ Search a file for a pattern
+ Cycle the Embark candidates
+ Use =C-M-j= to "preview" the line at point or, =C-M-n= / =C-M-p= to preview
  the next/previous one and move the point there (the latter two accept
  a numeric argument)

The benefit of this workflow is that I can display a preview only when I
want to and, most importantly, I do it from inside the Embark buffer
instead of the minibuffer (which is why I can avoid Icomplete or
Selectrum).

NOTE: consult can be configured to display previews manually or on a
case-by-case basis, though I feel you only benefit from that if you are
using it with Icomplete or Selectrum.
* A look at ~embark-become~ and cross-package integration

One of my goals with extending Embark for my personal needs is to have
some fluidity or seamlessness while performing minibuffer-centric
actions.  This can be achieved with the =embark-become= command: it lets
you re-use the current minibuffer's input in another minibuffer command.

The default =embark-become= lets you switch contexts between =find-file=
(=C-x C-f=) and =switch-to-buffer= (=C-x b=).  Start either of those actions,
type something, and the invoke =embark-become= to switch to the other (you
should bind =embark-become= to some key---see my dotemacs).

The design of Embark is based on the principle of scoping actions inside
keymaps.  Each of those keymaps applies to a context that Embark can
interpret by reading the category of what is being completed against or
what the target at point is.  Long story short: we can bind our own
actions to keys in each of those contexts and/or we can define our own
keymaps (general or specific) to extend the default options.

What I have here is a work in progress, but consider those two scenaria
with Consult commands for (1) grep and find, (2) outline and line
search:

1. We can invoke the relevant grep command and then decide that what we
   were actually looking for is a find operation.  So we rely on
   =embark-become= to take us from one place to the next without losing
   what we have already inserted in the minibuffer.
2. Same principle for =consult-outline= and =consult-line=, where we may be
   searching for a pattern that exists in a heading only to realise that
   we wanted to query for all lines instead.  =embark-become= to the
   rescue!

* Further information

Refer to my "dotemacs" for the complete setup:
&lt;https://protesilaos.com/emacs/dotemacs&gt;.

And check the Git repositories of the projects:

+ &lt;https://github.com/oantolin/embark&gt;
+ &lt;https://github.com/minad/consult&gt;
</code></pre>
        
      


guid: https://protesilaos.com/codelog/2021-01-11-modus-themes-review-select-faint-colours/
title: Modus themes: review of select “faint” colours
url: https://protesilaos.com/codelog/2021-01-11-modus-themes-review-select-faint-colours/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p class="info">UPDATE 2021-01-19 14:21 +0200: The <code>color-tools.el</code> is now called
<code>ct.el</code>.</p>

<p>The Modus themes come with a customisation option to tweak the looks of
programming modes (there are lots of customisation options—consult the
<a href="https://protesilaos.com/emacs/modus-themes">official manual</a>):
<code>modus-themes-syntax 'faint</code>.  The present entry documents the
refinements that were introduced to a subset of those “faint” colours.</p>

<p>In this report I am making use of the new <a href="https://github.com/neeasade/ct.el">ct.el library</a>,
developed by Github user neeasade.  Even though it is not available in
any package archive as of this writing, I highly recommend it to every
Emacs user who has an interest in colour and/or who is a theme designer.
Consider it as a complement to the built-in <code>color.el</code> Emacs library
(check the source code with <code>M-x find-library</code> and then insert <code>color</code>).
What it offers compared to the built-in option is an element of
convenience, as it lets us use the colour space of our choice.  In my
case that is RGB while the notation is hexadecimal.</p>

<p>Colour enthusiasts are also encouraged to read neeasade’s essay:
<a href="https://notes.neeasade.net/color-spaces.html">Reasoning about colors</a>.</p>

<p>The <code>color-tools</code> function that introduces a new test to my workflow is
<code>ct-name-distance</code>, which applies the CIE Δ<em>E</em> 2000 formula.  For the
purposes of this article, I am also applying <code>ct-contrast-ratio</code>, even
though there exists <code>modus-themes-contrast</code> as part of my themes, which
builds on the same WCAG formula for contrast in relative luminance
between two values (implemented in <code>modus-themes-wcag-formula</code>).</p>

<h2>Old and new values for “faint” blues and magentas</h2>

<p>The tables below merely present the affected variables and the change in
values assigned to them.  The overall intent is to slightly increase the
saturation of those colours while accounting for differences between
them in lieu of their intended purpose, which is to highlight code in a
more subtle way than the default aesthetic of the themes—read the doc
string of <code>modus-themes-syntax</code>.</p>

<p><code>cyan-faint</code> and <code>cyan-alt-other-faint</code> for Modus Operandi have also
been corrected for hueness, mainly by reducing their red light channel.
Other changes are more subtle.</p>

<pre><code class="language-org">#+DESCRIPTION: Affected values for Modus Operandi
| Internal name           | Old     | New     |
|-------------------------+---------+---------|
| cyan-faint              | #12506f | #005077 |
| cyan-alt-other-faint    | #2e584f | #125458 |
| blue-faint              | #002f88 | #003497 |
| blue-alt-faint          | #003f78 | #0f3d8c |
| blue-alt-other-faint    | #1f0f6f | #001087 |
| magenta-alt-faint       | #70256f | #7b206f |
| magenta-alt-other-faint | #5f3f7f | #55348e |

#+DESCRIPTION: Affected values for Modus Vivendi
| Internal name           | Old     | New     |
|-------------------------+---------+---------|
| blue-alt-faint          | #a4b0ff | #a0acf5 |
| blue-alt-other-faint    | #8fc5ff | #87c8ff |
| magenta-alt-other-faint | #d0b4ff | #cfa6ff |
</code></pre>

<p>Here is a picture of the same table with <code>M-x rainbow-mode</code> enabled, so
if it does not look clear please open it in another window:</p>

<p><img alt="Modus themes select faint colours" src="https://protesilaos.com/assets/images/attachments/modus-themes-review-faint-2021-01-11.png" /></p>

<p>Notice the fine tweaks (yes, those are the lengths we go to).</p>

<h2>Harmonising colour distance for Modus Operandi</h2>

<p>The following table only concerns Modus Operandi (we employ another
technique for Modus Vivendi—next section).  It measures the distance
of the new values relative to black and white (CIE Δ<em>E</em> 2000).  A value
of 100 is the maximum and it would mean in practical terms that the
closer our values are to the maximum, the more they appear as variants
of black for our light theme.</p>

<p>The table must thus be read as an attempt to slightly “brighten up”
those values and/or normalise the distance between some of them.  As
such compare columns 2 to 4 and 3 to 6 (all tables are in <code>org-mode</code>
notation).</p>

<pre><code class="language-org">#+DESCRIPTION: Modus Operandi cie-DE2000 distance for faint blues and magentas
| old     | #ffffff | #000000 | new     | #ffffff | #000000 |
|---------+---------+---------+---------+---------+---------|
| #12506f |      58 |      27 | #005077 |      58 |      28 |
| #2e584f |      55 |      28 | #125458 |      58 |      27 |
| #002f88 |      71 |      29 | #003497 |      68 |      31 |
| #003f78 |      65 |      27 | #0f3d8c |      65 |      30 |
| #1f0f6f |      83 |      28 | #001087 |      81 |      30 |
| #70256f |      64 |      31 | #7b206f |      62 |      32 |
| #5f3f7f |      59 |      32 | #55348e |      63 |      32 |
#+TBLFM: $2='(ct-name-distance $1 @1$2);%0.0f :: $3='(ct-name-distance $1 @1$3);%0.0f :: $5='(ct-name-distance $4 @1$5);%0.0f :: $6='(ct-name-distance $4 @1$6);%0.0f
</code></pre>

<p>[ does anyone know of a more succinct <code>#+TBLFM</code> expression? ]</p>

<p>An interesting observation to make with regard to the innate properties
of the channels of light, is how <code>#001087</code> and its old <code>#1f0f6f</code>
(<code>blue-alt-other-faint</code>) is perceived as being closer to black while
compared to pure white, even though it is impressed in more-or-less the
same way as the other colours when compared to pure black (the
discrepancies in the values shown on row 6, relative to the other rows).
This is because the blue channel, here represented as pure blue
(<code>#0000ff</code>), is the darkest among the three components of the RGB
triplet that we are using (green is the brightest, red is medium (though
not precisely)).</p>

<h2>Color distance between the values of Modus Vivendi</h2>

<p>While we tested our colours against black and white for Modus Operandi,
that technique was not suitable for Modus Vivendi.  This is because a
dark theme has different requirements and the reason is that the human
eye is more attuned to spot differences in colour against a dark
backdrop (and colour is, in essence, an expression of light, while the
pure black main background of Modus Vivendi is meant to represent the
absence of light—notwithstanding screen technology that always uses
light even for black).</p>

<p>As such, we are mostly interested in adjusting the distance between the
colour values that were deemed somewhat problematic (always in relative
terms, as those tweaks are virtually not discernible by the untrained
observer).</p>

<pre><code class="language-org">#+DESCRIPTION: Modus Vivendi cie-DE2000 distance OLD
|         |         | Distance |
|---------+---------+----------|
| #a4b0ff | #8fc5ff |  10.2885 |
| #8fc5ff | #d0b4ff |  19.9316 |
| #d0b4ff | #a4b0ff |  10.5743 |
#+TBLFM: $3='(ct-name-distance $1 $2);%0.4f

#+DESCRIPTION: Modus Vivendi cie-DE2000 distance NEW
|         |         | Distance |
|---------+---------+----------|
| #a0acf5 | #87c8ff |  13.2249 |
| #87c8ff | #cfa6ff |  24.2411 |
| #cfa6ff | #a0acf5 |  11.7710 |
#+TBLFM: $3='(ct-name-distance $1 $2);%0.4f
</code></pre>

<h2>Contrast compared to the main (and relevant) background values</h2>

<p>For the sake of completeness, the following tables confirm that the new
values are consistent with the overarching design principle of the
themes for a minimum contrast in relative luminance between background
and foreground of 7:1 or higher.</p>

<pre><code>#+DESCRIPTION: Modus Operandi WCAG contrast for select "faint" colours
|         | #ffffff | #f8f8f8 | #f0f0f0 |
|---------+---------+---------+---------|
| #005077 |    8.70 |    8.19 |    7.63 |
| #125458 |    8.63 |    8.12 |    7.57 |
| #003497 |   10.84 |   10.20 |    9.51 |
| #0f3d8c |   10.16 |    9.57 |    8.92 |
| #001087 |   14.75 |   13.89 |   12.94 |
| #7b206f |    9.22 |    8.68 |    8.09 |
| #55348e |    9.26 |    8.72 |    8.12 |
#+TBLFM: $2='(ct-contrast-ratio $1 @1$2);%0.2f :: $3='(ct-contrast-ratio $1 @1$3);%0.2f :: $4='(ct-contrast-ratio $1 @1$4);%0.2f

#+DESCRIPTION: Modus Vivendi WCAG contrast for select "faint" colours
|         | #000000 | #110b11 | #181a20 |
|---------+---------+---------+---------|
| #a0acf5 |    9.71 |    9.00 |    8.05 |
| #87c8ff |   11.74 |   10.87 |    9.72 |
| #cfa6ff |   10.55 |    9.77 |    8.74 |
#+TBLFM: $2='(ct-contrast-ratio $1 @1$2);%0.2f :: $3='(ct-contrast-ratio $1 @1$3);%0.2f :: $4='(ct-contrast-ratio $1 @1$4);%0.2f
</code></pre>

<p>As has been noted before, such as in the recent review of the <a href="https://protesilaos.com/codelog/2020-12-27-modus-themes-review-rainbow-delimiters/">faces
that pertain to the rainbow-delimiters package</a>,
there are a lot of considerations to be made when designing a theme.  My
opinion is that this endeavour stands at the intersection of art and
science.  We employ scientific insight in support of our choices, while
we exercise artistic judgement or freedom in interpreting the propriety
of every result in its particular context.  And we do so in a
non-dogmatic way, meaning that we are prepared at all times to review
our work and challenge our assumptions.</p>

<p>Consequently and despite the fact that we remain committed to the
minimum 7:1 contrast ratio, we cannot tolerate some inadequate technique
of procedurally picking colours which conform with a target of that
sort, nor can we confine ourselves to arbitrary constraints such as
relying only on 4, 8, 16 colours or whatnot.  Constraints need be
conducive to the primary design objectives and must thus remain subject
to continuous interpretation and evaluation, in order to stay in sync
with the evolving requirements of the project.</p>

<p>It is the designer who sets the constraints and delineates the
boundaries of their artistic discretion, so that there necessarily
exists an element of auto-nomy (self-determination) as opposed to
hetero-nomy (determined by an other [source]), pursuant to the tenets of
the project.  The minimum contrast ratio is inviolable, yet there is
wide range of scenaria that remains to be tested and carefully examined
even after accounting for that principle.</p>
        
      


guid: https://protesilaos.com/codelog/2021-01-22-emacs-vc-git-extras/
title: Extensions for Emacs’ vc-git
url: https://protesilaos.com/codelog/2021-01-22-emacs-vc-git-extras/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=mvjmokeifCo">https://www.youtube.com/watch?v=mvjmokeifCo</a></p>
         
         <p>In this video I demonstrate some of the commands I have for working with
the built-in version control (VC) framework and, specifically, its Git
back-end.  Those offer a layer of interactivity on top of the <code>git</code>
program you normally get on the command line, while the make various VC
interfaces easier to use.</p>

<p>Refer to my Emacs configuration file (“dotemacs”) for the implementation
details: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.  The specific item that
contains those extensions is <code>prot-vc.el</code>.  Everything is part of my
dotfiles’ repository: <a href="https://gitlab.com/protesilaos/dotfiles">https://gitlab.com/protesilaos/dotfiles</a>.</p>
        
      


guid: https://protesilaos.com/codelog/2021-01-24-modus-themes-1-1-0/
title: Modus themes 1.1.0 for GNU Emacs
url: https://protesilaos.com/codelog/2021-01-24-modus-themes-1-1-0/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Just published version <code>1.1.0</code> of <a href="https://protesilaos.com/emacs/modus-themes">the Modus
themes</a>.  The release notes
are reproduced below.  For any questions pertaining to this publication,
or anything else for that matter, feel welcome to <a href="https://protesilaos.com/contact/">contact
me</a>.</p>

<p>Please note that the version of the themes currently in Emacs 28 is
<code>0.13.0</code>, though we are working towards keeping everything in sync.
Likewise, GNU ELPA is at <code>0.12.0</code> and will eventually be made to pull
directly from emacs.git.  This is a volunteer effort: things need their
time, also in light of the prevailing conditions.</p>

<hr />

<h2>Modus themes version 1.1.0</h2>

<p>By Protesilaos Stavrou <a href="mailto:info@protesilaos.com">info@protesilaos.com</a> on 2021-01-24</p>

<p>This entry records the changes introduced to the project since the
publication of version 1.0.0 (2020-12-05).  There have been around 150
commits in the meantime, qualifying this as one of the largest releases
to date.</p>

<p>As always, every colour-related modification documented herein conforms
with the overarching accessibility objective of the themes for a minimum
contrast ratio of 7:1 between background and foreground values in their
given combination (conformance with the WCAG AAA standard).</p>

<p>As the official manual is referenced several times, make sure to store
its URL: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a>.</p>

<p>If you are coming from older versions, please consult the change log
entry for version 1.0.0.</p>

<h2>Overview</h2>

<ul>
  <li>
    <p>We have brought back the options that were present in version 0.13.0
or earlier which allowed users to override colors for either—or
both—of Modus Operandi and Modus Vivendi.  Compared to the old
mechanism, the new one is more robust and should work regardless of
whether users run byte compiled code or not.  This is considered and
advanced, “do-it-yourself” pathway to theme customisation.  It is
discussed at length in the manual.</p>
  </li>
  <li>
    <p>The new <code>modus-themes-with-colors</code> macro makes it possible to read
palette variables from the active theme and, thus, pass them to
arbitrary functions or variables.  Again, this is part of the advanced
customisations that are covered in the manual.</p>
  </li>
  <li>
    <p>Several of the existing customisation options provide new stylistic
variants, further expanding their utility.  While there are some new
customisations altogether.  Combined with the above, we provide the
infrastructure that allows the themes to adapt gracefully to a variety
of circumstances and cover a broad range of demands.</p>
  </li>
  <li>
    <p>More packages are added to the already comprehensive list of supported
face groups.</p>
  </li>
  <li>
    <p>Some of the supported faces have benefited from further, albeit
subtle, refinements, demonstrating our commitment to consistency as
well as our attention to detail.</p>
  </li>
  <li>
    <p>Two reports on such “further refinements” were published on the code
log section of protesilaos.com: <a href="https://protesilaos.com/codelog">https://protesilaos.com/codelog</a>.</p>
  </li>
  <li>
    <p>We have more people contributing to the project (and assigning
copyright to the FSF—as the themes are part of Emacs) and newer
users reporting issues.  Also, there is anecdotal evidence from
several sources on an increased interest to make new or existing faces
accessible by default (such as by copying colour combinations from the
themes).</p>
  </li>
</ul>

<h2>New customisation options</h2>

<ul>
  <li>
    <p>The existing <code>modus-themes-mode-line</code> variable now supports three new
borderless styles: <code>borderless</code>, <code>borderless-3d</code>, <code>borderless-moody</code>.</p>

    <ul>
      <li>
        <p>The <code>borderless</code> value uses the same colors as the default (nil
value), but removes the border effect.  This is done by making the
box property use the same color as the background, effectively
blending the two and creating some padding.</p>
      </li>
      <li>
        <p>The <code>borderless-3d</code> and <code>borderless-moody</code> approximate the <code>3d</code> and
<code>moody</code> options respectively, while removing the borders.  However,
to ensure that the inactive modelines remain visible, they apply a
slightly more prominent background to them than what their
counterparts do (same inactive background as with the default).</p>
      </li>
    </ul>

    <p>The complete list of options:</p>

    <ol>
      <li>nil (default)</li>
      <li>3d</li>
      <li>moody</li>
      <li>borderless</li>
      <li>borderless-3d</li>
      <li>borderless-moody</li>
    </ol>
  </li>
  <li>
    <p><code>modus-themes-lang-checkers</code> provides several styles for spell
checkers and code linters with regard to how they underline text.  The
default (nil) is to use a colour-coded wavy underline, without
changing the foreground of the affected text.  Other options include
the ability to set a straight underline and to control the saturation
of the foreground, while one also provides for a change in the
background of the text in question.  The valid symbols are as follows
(read the manual for more on the matter):</p>

    <ol>
      <li>nil (default)</li>
      <li>straight-underline</li>
      <li>subtle-foreground</li>
      <li>subtle-foreground-straight-underline</li>
      <li>intense-foreground</li>
      <li>intense-foreground-straight-underline</li>
      <li>colored-background</li>
    </ol>
  </li>
  <li>
    <p>The <code>modus-themes-org-habit</code> lets users pick between three styles for
the <code>org-habit</code> table: (1) nil (the default), which uses a total of
eight colours, (2) ‘simplified’ which reduces the effective colours to
four, while applying less saturated hues, and (3) <code>traffic-light</code>
which bring the colour count to three, thus blending the “clear” and
“ready” states for workflows where the distinction between is not
useful.</p>

    <p>Please read the manual for a more detailed description of those
variants.</p>

    <p>Thanks to Gustavo Barros for suggesting the idea, providing user
feedback on stylistic choices, as well as sharing insights on the
workflow that made the <code>traffic-light</code> style possible:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/135">https://gitlab.com/protesilaos/modus-themes/-/issues/135</a>.</p>
  </li>
  <li>
    <p><code>modus-themes-variable-pitch-ui</code> when set to a non-nil value applies a
proportionately spaced typeface (controlled by the <code>variable-pitch</code>
face) to the User Interface, specifically the mode line, header line,
and tab-{bar,line}.</p>
  </li>
  <li>
    <p>The existing <code>modus-themes-links</code> variable now has a colourless
stylistic alternative: <code>underline-only</code>.  The available styles:</p>

    <ol>
      <li>nil (default)</li>
      <li>faint</li>
      <li>neutral-underline</li>
      <li>faint-neutral-underline</li>
      <li>no-underline</li>
      <li>underline-only</li>
    </ol>
  </li>
  <li>
    <p>The existing <code>modus-themes-prompts</code> variable has two new grayscale
styles: <code>subtle-gray</code>, <code>intense-gray</code>.  Furthermore, their old
<code>subtle</code> and <code>intense</code> values have more informative aliases in the
form of <code>subtle-accented</code> and <code>intense-accented</code>.  All available
values:</p>

    <ol>
      <li>nil (default)</li>
      <li>subtle-accented (<code>subtle</code> remains for backward-compatibility)</li>
      <li>intense-accented (<code>intense</code> remains for backward-compatibility)</li>
      <li>subtle-gray</li>
      <li>intense-gray</li>
    </ol>
  </li>
  <li>
    <p>The existing <code>modus-themes-headings</code> variable now accepts two new
styles: <code>no-color</code>, <code>no-color-no-bold</code>.  All stylistic variants:</p>

    <ol>
      <li>nil (default fallback option—covers all heading levels)</li>
      <li>t (default style for a single heading, when the fallback differs)</li>
      <li>no-bold</li>
      <li>line</li>
      <li>line-no-bold</li>
      <li>rainbow</li>
      <li>rainbow-line</li>
      <li>rainbow-line-no-bold</li>
      <li>highlight</li>
      <li>highlight-no-bold</li>
      <li>rainbow-highlight</li>
      <li>rainbow-highlight-no-bold</li>
      <li>section</li>
      <li>section-no-bold</li>
      <li>rainbow-section</li>
      <li>rainbow-section-no-bold</li>
      <li>no-color</li>
      <li>no-color-no-bold</li>
    </ol>

    <p>Please read the manual for instructions on how to apply those
universally or on a per-level basis.</p>
  </li>
</ul>

<h2>Added support for packages</h2>

<ul>
  <li>cfrs (used by treemacs)</li>
  <li>cperl-mode</li>
  <li>
    <p>diredc</p>
  </li>
  <li>
    <p>display-fill-column-indicator-mode.  Thanks to Gustavo Barros for the
feedback: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/148">https://gitlab.com/protesilaos/modus-themes/-/issues/148</a>.</p>
  </li>
  <li>
    <p>evil-snipe.  Thanks to Peter Wu for the feedback:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/139">https://gitlab.com/protesilaos/modus-themes/-/issues/139</a>.</p>
  </li>
  <li>
    <p>isl (isearch-light).  Thanks to Manuel Uberti for the feedback:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/144">https://gitlab.com/protesilaos/modus-themes/-/issues/144</a>.</p>
  </li>
  <li>marginalia</li>
  <li>org-tree-slide</li>
  <li>
    <p>recursion-indicator</p>
  </li>
  <li>solaire.  Thanks to CsBigDataHub1 for the feedback:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/137">https://gitlab.com/protesilaos/modus-themes/-/issues/137</a>.</li>
</ul>

<h2>Refinements to already supported faces</h2>

<ul>
  <li>
    <p>Reviewed the <code>rainbow-delimiters</code> faces.  Everything is documented in
a separate report (with screenshots).  The short version is that we
pay close attention to detail and are willing to go to great lengths
in pursuit of improving the overall user experience:
<a href="https://protesilaos.com/codelog/2020-12-27-modus-themes-review-rainbow-delimiters/">https://protesilaos.com/codelog/2020-12-27-modus-themes-review-rainbow-delimiters/</a>.</p>
  </li>
  <li>
    <p>Updated the dedicated colours for <code>whitespace-mode</code>.  The background
should now be easier to discern.  Also removed any remaining
inconsistencies.  Thanks to Toon Claes for the feedback:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/149">https://gitlab.com/protesilaos/modus-themes/-/issues/149</a>.</p>
  </li>
  <li>
    <p>Refined the faces of regexp constructs for strings affected by certain
values passed to the <code>modus-themes-syntax</code> option.  This is done to
disambiguate the backslashes and grouping delimiters from the rest of
the string.  The relevant values for <code>modus-themes-syntax</code> are:</p>

    <ul>
      <li>green-strings</li>
      <li>yellow-comments-green-strings</li>
      <li>alt-syntax</li>
      <li>alt-syntax-yellow-comments</li>
    </ul>

    <p>The default colour for strings is blue, while regexp faces are yellow
and red, whereas in those variants the strings become green, hence the
need to make regexp faces more distinct (blue and magenta contrast
better with green and also between themselves, thus matching the
alternative aesthetics).</p>
  </li>
  <li>
    <p>Reviewed dictionary.el faces (which ships with Emacs 28):</p>

    <ul>
      <li>
        <p>Made <code>dictionary-reference-face</code> look like all other links.</p>
      </li>
      <li>
        <p>Removed all properties from <code>dictionary-word-definition-face</code>:
the default sets a font family, which can create inconsistencies.</p>
      </li>
      <li>
        <p>Converted <code>dictionary-word-entry-face</code> into comment-like text.</p>
      </li>
    </ul>
  </li>
  <li>
    <p>Refined and expanded the faces of Consult.</p>

    <ul>
      <li>
        <p>Made its grep commands look the same as those of all other grep
tools.</p>
      </li>
      <li>
        <p>Ensured that line number previews, such as for the <code>consult-line</code>
command use their own style of a subtle foreground instead of
inheriting from the <code>line-number</code> face.  This is to avoid cases
where previewed numbers and actual line numbers could be conflated
for one another.</p>
      </li>
      <li>
        <p>Removed the foreground pertinent to <code>consult-imenu-prefix</code>, as its
bold weight combined with the structure of Imenu indices was deemed
sufficient to differentiate it from actual <code>consult-imenu</code> targets.</p>
      </li>
    </ul>
  </li>
  <li>
    <p>Eliminated exaggerations in the use of colour for various <code>which-key</code>
faces.</p>
  </li>
  <li>
    <p>Removed the needless background from the <code>log-view-commit-body</code> face.
This is a new face that ships with Emacs 28 (its inclusion upstream
was documented in the last changelog entry).</p>
  </li>
  <li>
    <p>Applied a subtle background to the <code>log-view-message</code> face, in the
interest of improving the usability of its interface, in particular,
to contribute to heightened situational awareness while invoking
<code>log-view-toggle-entry-display</code> in buffers such as those produced by
<code>vc-print-root-log</code>.</p>
  </li>
  <li>
    <p>Introduced a neutral background for all <code>outline-minor-faces</code> instead
of merely mirroring the style of <code>outline-mode</code> headings.  This is
because it can sometimes be hard to tell whether <code>outline-minor-mode</code>
is active, provided certain fairly common configurations in the
<code>modus-themes-headings</code> user option (refer to the manual for all
customisation options).</p>
  </li>
  <li>
    <p>Tweaked <code>diff-mode</code> headings.</p>

    <ul>
      <li>
        <p>Adjusted the values of the dedicated colours for diff headings in
order to amplify their relative contrast.</p>
      </li>
      <li>
        <p>Assigned a bold typographic weight to the <code>diff-hunk-header</code> face so
as to enforce a greater sense of structure.</p>
      </li>
      <li>
        <p>Instructed <code>diff-function</code> to inherit <code>modus-theme-diff-heading</code> in
order to eliminate exaggerations in colouration.</p>
      </li>
    </ul>
  </li>
  <li>
    <p>Removed unnecessary underline from <code>selectrum-current-candidate</code>.
Thanks to Daniel Mendler for the feedback:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/132">https://gitlab.com/protesilaos/modus-themes/-/issues/132</a>.</p>
  </li>
  <li>
    <p>Made <code>counsel-outline</code> inherit from the underlying Org faces.  Also
corrected the style of <code>counsel-outline-default</code> to use the main
foreground colour.  Thanks to Gustavo Barros for the feedback:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/134">https://gitlab.com/protesilaos/modus-themes/-/issues/134</a>.</p>
  </li>
  <li>
    <p>Prevented headings, ultimately governed by the <code>modus-themes-headings</code>
user option, from inheriting the <code>default</code> face as that could lead to
unintended consequences, such as by retaining a background colour when
none was expected.</p>
  </li>
  <li>
    <p>Refashioned all faces that specified a foreground value of <code>fg-alt</code> to
inherit the <code>shadow</code> face instead (<code>fg-alt</code> is the colour that is
used, for example, in code comments by default).  This makes it
possible for users to enact change across the theme just by tweaking
<code>shadow</code>.</p>
  </li>
  <li>
    <p>Fixed <code>ruler-mode</code> text scaling adjustment, to make it cope well with
<code>text-scale-adjust</code> and relevant commands.  Also introduced minor
stylistic changes to the remainder of the <code>ruler-mode</code> faces.</p>
  </li>
  <li>
    <p>Eliminated the potentially problematic form of <code>:foreground nil</code> from
the <code>org-ellipsis</code> face.  In such cases it is always better to either
specify no foreground whatsoever, or declare an unspecified value.</p>
  </li>
</ul>

<h2>Patches from the community</h2>

<p>Remember that the themes are part of Emacs and, thus, contributions that
exceed a cumulative total of ~15 lines require the assignment of
copyright to the Free Software Foundation.  Please consult the themes’
manual on the matter.</p>

<ul>
  <li>
    <p>Nicolas De Jaeghere added support for <code>exwm-floating-border-color</code>:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/15">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/15</a>.</p>
  </li>
  <li>
    <p>Anders Johansson added support for <code>helm-fd-finish</code>:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/16">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/16</a>.</p>
  </li>
  <li>
    <p>Carlo Zancanaro fixed misquoting of <code>tuareg-font-lock-multistage-face</code>:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/17">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/17</a>.</p>
  </li>
  <li>
    <p>Xinglu Chen expanded Notmuch support to all its remaining faces:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/18">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/18</a>.</p>
  </li>
  <li>
    <p>Kostadin Ninev added support for Dired+:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/19">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/19</a>.</p>
  </li>
  <li>
    <p>Nicolas De Jaeghere expanded the supported items of <code>pdf-faces</code>.  Also
added an entry to the manual pertaining to link hints and the
requisite setup:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/20">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/20</a>.</p>
  </li>
  <li>
    <p>Nicolas De Jaeghere wrote the new <code>modus-themes-with-colors</code> macro,
which is documented at length in the manual:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/21">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/21</a>.</p>
  </li>
  <li>
    <p>Nicolas De Jaeghere set up the infrastructure that grants users the
ability to override palette colors; an option that was removed in the
transition from version 0.13.0 to 1.0.0.  The relevant variables are
<code>modus-themes-colors-operandi</code>, <code>modus-themes-colors-vivendi</code> (again,
consult the manual):
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/23">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/23</a>.</p>
  </li>
  <li>
    <p>Nicolas De Jaeghere deleted the <code>modus-themes-core.el</code> file and merged
its contents into the main <code>modus-themes.el</code> library:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/24">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/24</a> and
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/25">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/25</a>.</p>
  </li>
  <li>
    <p>Nicolas De Jaeghere made the <code>compilation-info</code> face consistent with
other compilation faces in terms of their optional bold weight:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/26">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/26</a>.</p>
  </li>
</ul>

<p>Any remaining faults that may exist, despite our best intentions to
remove them, are those of the maintainer and will be addressed as soon
as they are identified.</p>

<p>FSF copyright status:</p>

<table>
  <thead>
    <tr>
      <th>Full name</th>
      <th>Copyright</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Anders Johansson</td>
      <td>covered</td>
    </tr>
    <tr>
      <td>Carlo Zancanaro</td>
      <td>not required</td>
    </tr>
    <tr>
      <td>Kostadin Ninev</td>
      <td>covered</td>
    </tr>
    <tr>
      <td>Nicolas De Jaeghere</td>
      <td>covered</td>
    </tr>
    <tr>
      <td>Xinglu Chen</td>
      <td>not required</td>
    </tr>
  </tbody>
</table>

<h2>Theme-related contributions to the wider community</h2>

<ul>
  <li>
    <p>Helped address an incomplete colour value in <code>org-transclusion-block</code>:
<a href="https://github.com/nobiot/org-transclusion/issues/41">https://github.com/nobiot/org-transclusion/issues/41</a>.</p>
  </li>
  <li>
    <p>Contributed to the formation of the zebra striping of <code>embark</code>:
<a href="https://github.com/oantolin/embark/commit/bb4ae2a666ab1f4a307edd71f77bcbb90fb25cef">https://github.com/oantolin/embark/commit/bb4ae2a666ab1f4a307edd71f77bcbb90fb25cef</a>.</p>
  </li>
  <li>
    <p>Reviewed the faces of <code>goggles</code>:
<a href="https://github.com/minad/goggles/commit/d6e584a2c9487d3df4aee818c43485e437cb87ef">https://github.com/minad/goggles/commit/d6e584a2c9487d3df4aee818c43485e437cb87ef</a>.</p>
  </li>
  <li>
    <p>Helped raise awareness about refactoring <code>org-tree-slide-header-overlay-face</code>:
<a href="https://github.com/takaxp/org-tree-slide/issues/38">https://github.com/takaxp/org-tree-slide/issues/38</a>.</p>
  </li>
  <li>
    <p>Reported an issue for Moody that would affect the subset of Emacs 28
users who enable the new <code>mode-line-compact</code> option:
<a href="https://github.com/tarsius/moody/issues/28">https://github.com/tarsius/moody/issues/28</a>.</p>
  </li>
  <li>
    <p>Did the same for Keycast: <a href="https://github.com/tarsius/keycast/issues/13">https://github.com/tarsius/keycast/issues/13</a>.</p>
  </li>
  <li>
    <p>Defined the new <code>perl-non-scalar-variable</code> in upstream Emacs:
<a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45840">https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45840</a>.</p>
  </li>
</ul>

<h2>Miscellaneous</h2>

<ul>
  <li>
    <p>Created a new palette subset for “graph” colours, as none of the
existing paradigms would suffice for cases where faithfulness to
colour huenesss is important.  Those are currently used by
<code>modus-themes-org-habit</code>.</p>
  </li>
  <li>
    <p>Ensured that theme functions which need to produce an error message do
so by calling <code>error</code> instead of <code>user-error</code>.</p>
  </li>
  <li>
    <p>Added a <code>modus-themes-load-themes</code> function that users can add to
their init files.</p>
  </li>
  <li>
    <p>Expanded the project’s git repo README file with a sample
<code>use-package</code> configuration.</p>
  </li>
  <li>
    <p>The previous two points followed from an inquiry into the subtleties
between <code>enable-theme</code> and <code>load-theme</code>.  Those are now documented at
length in the manual.</p>
  </li>
  <li>
    <p>Added screenshots to the web page that holds the official manual.
Thanks to Damien Cassou for the feedback:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/147">https://gitlab.com/protesilaos/modus-themes/-/issues/147</a>.</p>
  </li>
  <li>
    <p>Swapped the values of <code>cyan-faint</code> and <code>cyan-alt-faint</code> for Modus
Vivendi.</p>
  </li>
  <li>
    <p>Tweaked <code>font-lock-doc-face</code> and <code>font-lock-type-face</code> variations when
“faint syntax” is in effect: (setq modus-themes-syntax ‘faint).</p>
  </li>
  <li>
    <p>Refined <code>font-lock-doc-face</code> for when modus-themes-syntax is given a
value of either <code>yellow-comments-green-strings</code> or <code>green-strings</code>.
The changes are minor when treated in isolation, though they have
helped improve the overall consistency of the end result: the gestalt.</p>
  </li>
  <li>
    <p>Reviewed select “faint” colours for both Modus Operandi and Modus
Vivendi.  The technicalities are discussed in a complete report:
<a href="https://protesilaos.com/codelog/2021-01-11-modus-themes-review-select-faint-colours/">https://protesilaos.com/codelog/2021-01-11-modus-themes-review-select-faint-colours/</a>.</p>
  </li>
  <li>
    <p>Ensured that (setq modus-themes-syntax ‘alt-syntax) and its “yellow
comments” variant are more truthful to their intended style, by
eliminating any exaggerations in the use of colour.</p>
  </li>
  <li>
    <p>Adjusted the saturation of the green-alt value of Modus Vivendi.</p>
  </li>
  <li>
    <p>Updated the manual to reflect all of the aforementioned.</p>
  </li>
</ul>

<p>Thanks once again to everyone who contributed patches or reported an
issue.  This has been yet another period of intense work; work which
helps solidify the Modus themes as (i) uncompromisingly accessible in
accordance with the highest legibility standard, (ii) highly
customisable in true Emacs fashion, (iii) thoroughly comprehensive in
terms of face coverage, and (iv) meticulously designed throughout.</p>
        
      


guid: https://protesilaos.com/codelog/2021-01-26-git-diff-hunk-elisp-org/
title: Informative diff hunks for Emacs Lisp and Org
url: https://protesilaos.com/codelog/2021-01-26-git-diff-hunk-elisp-org/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p class="info"><strong>Update 2021-01-26 20:30 +0200:</strong> Fixed link to dotfiles.<br />
<strong>Update 2021-01-27 13:55 +0200:</strong> Tweaked Org regexp to avoid bold text at
the beginning of the line.<br />
<strong>Update 2021-01-27 16:39 +0200:</strong> Added Annex.</p>

<p>Today I learnt how to instruct <code>git</code> to read the syntactically relevant
beginning of the given context when producing diff hunk headings.  My
intent is to improve the output for Emacs Lisp and Org mode files.</p>

<p>The diff hunk heading is the text that is appended to the lines of a
given change.  You must have noticed those:</p>

<pre><code>@@ -210,7 +210,7 @@ TEXT OF THE HEADING
</code></pre>

<p>By default, the text for Elisp buffers is not particularly informative.
For example:</p>

<pre><code class="language-diff"> emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el b/emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el
index 318bb63e..3ea711f9 100644
--- a/emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el
+++ b/emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el
@@ -210,7 +210,7 @@ with the specified date."
   (interactive "P")
   (let* ((date prot-simple-date-specifier)
          (time prot-simple-time-specifier)
-         (format (if arg (format "%s %s" date time) date)))
+         (format (if arg (format "%s %s" date time) date))) ; This is a test
     (when (use-region-p)
       (delete-region (region-beginning) (region-end)))
     (insert (format-time-string format))))
</code></pre>

<p>The heading <code>with the specified date."</code> does not really enlighten us as
to what function is touched by this change.  Whereas with my newfound
knowledge I get this:</p>

<pre><code class="language-diff"> emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el b/emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el
index 318bb63e..3ea711f9 100644
--- a/emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el
+++ b/emacs/.emacs.d/straight/repos/prot-lisp/prot-simple.el
@@ -210,7 +210,7 @@ (defun prot-simple-inset-date (&amp;optional arg)
   (interactive "P")
   (let* ((date prot-simple-date-specifier)
          (time prot-simple-time-specifier)
-         (format (if arg (format "%s %s" date time) date)))
+         (format (if arg (format "%s %s" date time) date))) ; This is a test
     (when (use-region-p)
       (delete-region (region-beginning) (region-end)))
     (insert (format-time-string format))))
</code></pre>

<p>The <code>(defun prot-simple-inset-date (&amp;optional arg)</code> is insightful as it
lets us understand in more precise terms the context of the relevant
change.</p>

<p>Same principle for Org, where it will read the heading under which the
diff occurs:</p>

<pre><code class="language-diff"> emacs/.emacs.d/emacs-init.org | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/emacs/.emacs.d/emacs-init.org b/emacs/.emacs.d/emacs-init.org
index efe0d8a7..d71f8f8d 100644
--- a/emacs/.emacs.d/emacs-init.org
+++ b/emacs/.emacs.d/emacs-init.org
@@ -3359,6 +3359,8 @@ *** Version control framework (vc.el and prot-vc.el)
 all basic versioning needs.  It however never stands as Magit's peer
 when it comes to the sheer coverage of Git features.
 
+This is a test.
+
 To my mind, VC and Magit can be used as part of the same setup.  Employ
 the former for common tasks such as viewing diffs and logs, committing
 changes in bulk, pushing and pulling from a remote.  And let Magit
</code></pre>

<p>Got the correct heading: <code>*** Version control framework (vc.el and
prot-vc.el)</code>.  Much better!</p>

<h2>Git config and attributes files</h2>

<p>To get things to work we need to create <code>~/.config/git/attributes</code> and
add at least the following:</p>

<pre><code>*.lisp  diff=lisp
*.el    diff=lisp
*.org   diff=org
</code></pre>

<p>Then, in <code>~/.config/git/config</code> append:</p>

<pre><code>[diff "lisp"]
  xfuncname = "^(\\(.*)$"
[diff "org"]
  xfuncname = "^(\\*+ +.*)$"
</code></pre>

<p>And you should be good to go.</p>

<p>This is based on information I got from the manpages.  The first version
of the regular expressions comes from this page:
<a href="https://gist.github.com/ruediger/5647207">https://gist.github.com/ruediger/5647207</a>.</p>

<p>My Git config:</p>

<pre><code>[user]
  name = Protesilaos Stavrou
  email = info@protesilaos.com
  signingkey = 99BD6459CD5CA3EA
[core]
  excludesfile = ~/.config/git/ignore
  attributesfile = ~/.config/git/attributes
[commit]
  gpgsign = true
[merge]
  conflictstyle = diff3
[pull]
  rebase = false
[format]
  thread = true
[diff "lisp"]
  xfuncname = "^(\\(.*)$"
[diff "org"]
  xfuncname = "^(\\*+ +.*)$"
</code></pre>

<h2>Quality-of-life improvements</h2>

<p>I am very happy with this otherwise minor tweak and am looking forward
to learn more about optimising my computing environment.  Git, in
particular, is a powerful and comprehensive suite of tools that has a
lot to offer.  I have been reading through its manpages now that I am
not a total novice (with either <code>M-x man</code> or <code>M-x woman</code>) and am
discovering new information that can, among others, benefit my Emacs
setup.</p>

<p>My git-related configurations are part of my dotfiles.  That is where I
also keep all my Emacs files: <a href="https://gitlab.com/protesilaos/dotfiles">https://gitlab.com/protesilaos/dotfiles</a>.</p>

<p>If some Emacs power user knows how to improve upon this setup, please do
contact me: <a href="https://protesilaos.com/contact">https://protesilaos.com/contact</a>.</p>

<h2>Annex</h2>

<p>Gustavo Barros contacted me to share another take on the Elisp regexp.
I am sharing it with permission.  This matches <code>outline-minor-mode</code>
comment headings, any top-level form at beginning of line, and some
selected forms even when indented:</p>

<pre><code>[diff "lisp"]
  xfuncname = "^(((;;;+ )|\\(|([ \t]+\\(((cl-|el-patch-)?def(un|var|macro|method|custom)|gb/))).*)$"
</code></pre>

<p>I like the idea and am excited to see what else we can do with this and
other “hidden gems” of Git.</p>
        
      


guid: https://protesilaos.com/codelog/2021-02-08-emacs-vc-workflow/
title: My workflow with VC for Git projects (Emacs)
url: https://protesilaos.com/codelog/2021-02-08-emacs-vc-workflow/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=0YlYX_UjH5Q">https://www.youtube.com/watch?v=0YlYX_UjH5Q</a></p>
         
         <p>In this video I provide an overview of my workflow with the built-in
Version Control (VC) framework of Emacs.  I am using it to manage all of
my Git projects.  VC has become my primary interface for Git even though
I keep Magit installed.  The latter is only needed for some specialised
operations—VC and my extras cover my day-to-day needs.</p>

<p>This demo includes lots of custom extensions that I have written in an
attempt to make VC work the way I want.  Refer to my Emacs configuration
file (“dotemacs”) for the implementation details:
<a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.  The specific item that contains
those extensions is <code>prot-vc.el</code>.  Everything is part of my dotfiles’
repository: <a href="https://gitlab.com/protesilaos/dotfiles">https://gitlab.com/protesilaos/dotfiles</a>.</p>
        
      


guid: https://protesilaos.com/codelog/2021-02-22-modus-themes-exporter/
title: Introducing the Modus themes exporter (Emacs library)
url: https://protesilaos.com/codelog/2021-02-22-modus-themes-exporter/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>I just published the initial version of the <code>modus-themes-exporter.el</code>
as part of <a href="https://gitlab.com/protesilaos/dotfiles">my dotfiles’ Emacs setup</a>.</p>

<p>The library consists of a set of functions that help produce a port of
the active Modus theme (<code>modus-operandi</code> or <code>modus-vivendi</code>) for a
variety of external applications.  Currently covered entries are XTerm,
URxvt (rxvt-unicode), Xfce terminal (xfce4-terminal), and Vim (gui and
term, as well as NeoVim).</p>

<p>The exporting is performed by the <code>modus-themes-exporter-export</code>
command.  Its doc string reads thus:</p>

<pre><code>Export current Modus theme using TEMPLATE.

When called interactively, TEMPLATE is chosen from a list of candidates
using completion.  Else it must be a string that corresponds to the car
of a cons cell in `modus-themes-exporter-templates-alist'.

The output is stored in the kill ring.

When called from Lisp with optional FILE as a path to a regular file,
write there directly.  When called interactively with the universal
prefix argument (\\[universal-argument]), prompt for FILE instead:
supplying a non-existent path will create that file outright.  Once the
output has been written to the file, prompt to visit it.

With optional NO-VISIT, either as a non-nil symbol in Lisp or a
double prefix argument interactively, do not prompt to visit the
file.
</code></pre>

<p>Here is a side-by-side presentation of Emacs (left) and Xfce’s terminal
with Vim running inside of it (right).  Click to enlarge.</p>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-22-modus-themes-exporter-light.png"><img alt="Modus themes exporter light" src="https://protesilaos.com/assets/images/attachments/2021-02-22-modus-themes-exporter-light.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-22-modus-themes-exporter-dark.png"><img alt="Modus themes exporter dark" src="https://protesilaos.com/assets/images/attachments/2021-02-22-modus-themes-exporter-dark.png" /></a></p>

<h2>What is this all about?</h2>

<p>Before we start… No, I do not intend to switch back to Vim: I plan to
remain a full time Emacs user for years to come.</p>

<p>The <code>modus-themes-exporter.el</code> allows me to satisfy the demand for
porting my Modus themes to other applications.  I have done so several
times in private, where I would supply an Xresources file or whatnot to
the person emailing me.  I have also offered my consent to those who
asked whether they could create ports for VSCode—none of those
endeavours has yielded any results as far as I know.</p>

<p>Demand for ports has also been expressed publicly on the issue tracker
of the Modus themes’ repo (<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/116">issue
116</a>) as well
as my dotfiles (<a href="https://gitlab.com/protesilaos/dotfiles/-/issues/31">issue
31</a>).  Furthermore,
Simon Pugnet wrote the
<a href="https://github.com/polaris64/modus-exporter">modus-exporter</a> a while
ago which, however, is targeted at older versions of the themes prior to
their major refactoring in version <code>1.0.0</code>.</p>

<p>I must stress that insofar as external text editors are concerned <strong>the
output of this library does not constitute a fully fledged theme</strong>.
Creating an original piece, especially one with the technical
requirements for uncompromising legibility that the Modus themes stand
for, requires a lot of work and painstaking attention to detail (I have
been doing so for ~1.5 years now, ever since day one of switching to
Emacs).  No automated process invented thus far can replace the
context-specific aesthetic judgement of the designer.  Still, a
templating system can help <em>approximate</em> what has already been achieved,
while acknowledging the constraints imposed by the incompatibilities
between the various applications and Emacs (e.g. how they highlight
code, as illustrated in the screenshots above).</p>

<p>With those granted, the ports cover a subset of the palette used in each
of the Modus themes which means, ipso facto, that they make compromises
in the interest of maintainability.  Similarly, there is no plan
whatsoever to replicate the customisation options that the real themes
for Emacs have, as well as implement anew their advanced,
“do-it-yourself” features (consult <a href="https://protesilaos.com/emacs/modus-themes/">the Modus themes’
manual</a>, which, by the way, is
pushing towards 20k words).</p>

<h2>Experimental release</h2>

<p>Please bear in mind that there is still a lot of work to be done before
this library reaches a certain standard of quality:</p>

<ol>
  <li>Refine the templating system.</li>
  <li>Test automated processes for outputting ports in bulk.</li>
  <li>Improve Vim’s colour mapping so that it mimics that of Emacs, to the
extent possible.</li>
  <li>Write ports for the GTK Source view widget (Gedit, GNOME Builder,
etc.).</li>
  <li>Expand support for more terminal emulators, such as Kitty, Alacritty.</li>
  <li>Convert colours from hexadecimal RGB notation to decimal, so that we
can cover KDE’s Konsole and, potentially, Kate, Kwrite, etc.</li>
</ol>

<p>Patches and user feedback are most welcome!</p>
        
      


guid: https://protesilaos.com/codelog/2021-02-25-modus-themes-diffs-deuteranopia/
title: The Modus themes now cover deuteranopia in diffs
url: https://protesilaos.com/codelog/2021-02-25-modus-themes-diffs-deuteranopia/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>I just extended the <code>modus-themes-diffs</code> customisation option with the
ability to read a <code>deuteranopia</code> value.</p>

<p><em>Deuteranopia</em> describes insensitivity to the green channel of light.
This includes the possibility of not distinguishing between red and
green; the two colours that are typically codified in diff buffers as
denoting “removed” and “added” states respectively.</p>

<p>Evaluating <code>(setq modus-themes-diffs 'deuteranopia)</code> and then re-loading
the theme of choice will replace all instances of green in diff buffers
with variants of blue.  This affects the standard <code>diff-mode</code>, Ediff,
Smerge, Magit, Vdiff, and any other library that inherits from those.</p>

<p>Below are illustrations of the phenomenon while using Magit diffs as an
example with word-wise differences enabled (“refined” diffs).  We try to
simulate how deuteranopia is experienced.  Those with it see red and
green as variants of brown/yellow and interpret shades of magenta
without its red channel’s intensity (magenta consists primarily of red
and blue, so it looks closer to a desaturated blue).</p>

<h2>Red VS Green (default)</h2>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-operandi-diff-default.png"><img alt="Modus Operandi default" src="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-operandi-diff-default.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-operandi-diff-default-simulated.png"><img alt="Modus Operandi default simulated" src="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-operandi-diff-default-simulated.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-vivendi-diff-default.png"><img alt="Modus Vivendi default" src="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-vivendi-diff-default.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-vivendi-diff-default-simulated.png"><img alt="Modus Vivendi default simulated" src="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-vivendi-diff-default-simulated.png" /></a></p>

<h2>Red VS Blue (‘deuteranopia’ option)</h2>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-operandi-diff-deuteranopia.png"><img alt="Modus Operandi deuteranopia" src="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-operandi-diff-deuteranopia.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-operandi-diff-deuteranopia-simulated.png"><img alt="Modus Operandi deuteranopia simulated" src="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-operandi-diff-deuteranopia-simulated.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-vivendi-diff-deuteranopia.png"><img alt="Modus Vivendi deuteranopia" src="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-vivendi-diff-deuteranopia.png" /></a></p>

<p><a href="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-vivendi-diff-deuteranopia-simulated.png"><img alt="Modus Vivendi deuteranopia simulated" src="https://protesilaos.com/assets/images/attachments/2021-02-25-modus-vivendi-diff-deuteranopia-simulated.png" /></a></p>

<h2>Accessibility broadly understood</h2>

<p>While <a href="https://protesilaos.com/emacs/modus-themes/">the Modus themes</a> are not
designed with the express goal of optimising for deuteranopia across all
of Emacs’ interfaces, we can always make steps towards improving that
experience.  The fact that we already conform with the highest standard
for colour contrast (WCAG AAA) puts us in a good position to expand our
commitment to accessibility so that it accounts for variations in colour
perception.</p>

<p>Designing for such cases is no mean feat.  I had to take screenshots of
all relevant configurations, display them in the GNU Image Manipulation
Program, and set a filter that simulates deuteranopia vision: from GNU
IMP’s “View” menu, search for “Display Filters” and then apply “Color
Deficient Vision”.  That had to be done tens of times during the testing
process.</p>

<p>What inspired me to add support for <code>(setq modus-themes-diffs
'deuteranopia)</code> is the blog post of Sam Kleinman (aka “tycho garen”) on
<a href="https://tychoish.com/post/editor-themes/">Editor Themes</a> (2021-02-24),
which echoes the relevant wishlist item on my project’s issue tracker
(<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/118">issue 118</a>)
where I got feedback from Hörmetjan Yiltiz.</p>

<p>Apart from its immediate utility, consider this new feature a statement
of intent: I want to make the themes as accessible as possible and am
willing to act on user feedback to that end.</p>

<p>If you believe something does not work properly while using either
<code>modus-operandi</code> or <code>modus-vivendi</code>, please do not hesitate to bring the
issue to my attention.  Colour is a complex phenomenon: even when we
formally conform with the lofty target of a minimum 7:1 contrast in
relative luminance, we may still encounter cases where things do not
“feel right”.  We can always fix those outright or, where necessary,
benefit from the power of Elisp to provide the relevant customisation
options.</p>
        
      


guid: https://protesilaos.com/codelog/2021-03-03-emacs-query-replace-downcase/
title: Use ‘M-x query-replace-regexp’ to downcase matches
url: https://protesilaos.com/codelog/2021-03-03-emacs-query-replace-downcase/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Earlier today I wanted to convert a bunch of Org meta data keywords to
lower case notation, with the help of <code>isearch-forward-regexp</code> and
<code>query-replace-regexp</code>.  This included everything from special comments,
like <code>#+TITLE:</code> to property drawers in the form of <code>:PROPERTIES:</code>.
There were 340 such cases in my file and I was reluctant to do so
manually.  Thankfully, Emacs makes such a task fairly simple once you
get past the essentials, because it lets you evaluate arbitrary Elisp
forms for the replacement text.  This includes the possibility of
running some function on a matched regexp group.  In this case that
function was <code>(downcase OBJECT)</code>.</p>

<p>First I needed a regular expression that would capture all targets.
<code>isearch-forward-regexp</code> and its <code>query-replace-regexp</code> counterpart
expect a single backslash for the escape character, so I ended up with
this pattern:</p>

<pre><code>^\(#\|:\)[^ ].*?:
</code></pre>

<p>If I were to test this in the buffer, I could use <code>M-x re-builder</code>,
which however requires double backslashes (same for when you write Elisp
code):</p>

<pre><code>^\\(#\\|:\\)[^ ].*?:
</code></pre>

<ul>
  <li>
    <p>Once I was sure of the regular expression I had to use, I went to the
top of the buffer and invoked <code>isearch-forward-regexp</code> (bound to
<code>C-M-s</code> by default).</p>
  </li>
  <li>
    <p>Entered the pattern <code>^\(#\|:\)[^ ].*?:</code>, got live feedback of the
matching items, and switched to <code>query-replace</code> with <code>C-%</code>
(<code>isearch-query-replace</code>).  When the Isearch is regexp-aware so is the
corresponding <code>query-replace</code>.</p>
  </li>
  <li>
    <p>For the replacement text I instructed the command to evaluate the
<code>downcase</code> function.  This is done by escaping the comma operator
(<code>,</code>) and then supplying the function with a regexp group.  Because I
wished to match everything, the group should be <code>\0</code>.  Which means
that the replacement should be expressed thus: <code>\,(downcase \0)</code>.</p>
  </li>
</ul>

<p>Try this with any string in a buffer, say, <code>Hello</code>:</p>

<ul>
  <li><code>M-x query-replace-regexp</code></li>
  <li><code>Hello</code></li>
  <li><code>\,(upcase \0)</code></li>
</ul>

<p>Confirm the operation and you should get <code>HELLO</code>.  This works with
multiple groups and can read a series of Elisp forms.  An example with
<code>Hello world</code>:</p>

<ul>
  <li><code>M-x query-replace-regexp</code></li>
  <li><code>\(Hello\) \(world\)</code></li>
  <li><code>\,(downcase \1) \,(capitalize \2)</code></li>
</ul>

<p>Which should give you <code>hello World</code>.</p>

<p>The elegant minimalism of the <code>query-replace</code> interface grants you the
power to either replace each match one at a time or hit the exclamation
mark (<code>!</code>) to answer “yes to all”.  This is what I did to downcase all
340 matches.  Voila!  All of my Org file’s meta data were converted to
lower case in one go.</p>

<p>Finally, I discovered <code>query-replace-regexp-eval</code> which saves you from
adding the escaped comma operator for the replacement’s Elisp form.
However its doc string reads thus:</p>

<pre><code>Interactive use of this function is deprecated in favor of the
‘\,’ feature of ‘query-replace-regexp’.  For non-interactive use, a loop
using ‘search-forward-regexp’ and ‘replace-match’ is preferred.
</code></pre>
        
      


guid: https://protesilaos.com/codelog/2021-03-04-modus-themes-1-2-0/
title: Modus themes 1.2.0 for GNU Emacs
url: https://protesilaos.com/codelog/2021-03-04-modus-themes-1-2-0/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Just published version <code>1.2.0</code> of <a href="https://protesilaos.com/emacs/modus-themes">the Modus themes</a>.
The detailed release notes are reproduced below.  For any questions
pertaining to this publication feel welcome to <a href="https://protesilaos.com/contact/">contact me</a>.</p>

<p>My immediate task now is to prepare patches for upstream Emacs so that
the <code>modus-operandi-theme</code> and <code>modus-vivendi-theme</code> can be updated from
version <code>0.13.0</code> to the current one.</p>

<hr />

<h2>Modus themes version 1.2.0</h2>

<p>By Protesilaos Stavrou <a href="mailto:info@protesilaos.com">info@protesilaos.com</a> on 2021-03-04</p>

<p>This entry records the changes introduced to the project since the
publication of version 1.1.0 (2021-01-24).  There have been close to 100
commits in the meantime.</p>

<p>Every colour-related modification documented herein conforms with the
overarching accessibility objective of the themes for a minimum contrast
ratio of 7:1 between background and foreground values in their given
combination (the WCAG AAA standard).</p>

<p>As the official manual is referenced several times throughout this log,
make sure to store its URL: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a>.  Or
read it from Emacs’ Info reader by evaluating this form:</p>

<pre><code>(info "(modus-themes) Top")
</code></pre>

<p>If you are coming from older versions, please consult the change log
entry for version 1.0.0 with regard to the breaking changes that were
introduced.</p>

<h2>Prior notice: Upgrading the themes in Emacs28 and GNU ELPA</h2>

<p>Emacs28, the current development target, now includes a <code>require-theme</code>
function.  It is a prerequisite to upgrading the Modus themes to their
current version.  Prior to the definition of that function, the themes
could not transition from their 0.13.0 version to &gt;=1.0.0.  Special
thanks to Basil L. Contovounesios for making it happen, as well Mauro
Aranda and Eli Zaretskii for their feedback and support.</p>

<p>Expect the Modus themes in upstream Emacs to be updated shortly after
the publication of this document.</p>

<p>GNU ELPA currently ships version 0.12.0 of the two standalone packages
<code>modus-operandi-theme</code> and <code>modus-vivendi-theme</code>.  This will change in
the immediate future, as a new <code>modus-themes</code> package will succeed them.
That new package will be built directly from emacs.git, as it must now
become a <code>:core</code> entity instead of being listed as an <code>:external</code> one.</p>

<p>Again, expect a patch to be applied to elpa.git shortly after this
document goes live.</p>

<h2>Customisation options</h2>

<p>[ All variables and their values are documented in the themes’ manual.
  The default value is always nil. ]</p>

<ul>
  <li>
    <p>The new boolean <code>modus-themes-subtle-line-numbers</code> variable will make
the effect of <code>display-line-numbers-mode</code> more subtle when set to a
non-nil value.  It removes the underlying background of the unfocused
lines while toning down their foreground.</p>
  </li>
  <li>
    <p>The <code>modus-themes-diffs</code> variable now accepts a <code>deuteranopia</code> value.
This optimises for red-green colour deficiency in all modes that show
diffs (diff-mode, ediff, Magit…).  In practice, all instances of
green are replaced with appropriate blue hues.  For more on the
matter, read the report which also includes pictures:
<a href="https://protesilaos.com/codelog/2021-02-25-modus-themes-diffs-deuteranopia/">https://protesilaos.com/codelog/2021-02-25-modus-themes-diffs-deuteranopia/</a>.</p>
  </li>
  <li>
    <p>The <code>modus-themes-syntax</code> variable now reads <code>faint-yellow-comments</code>
as a valid value.  This has the same scope as the existing <code>faint</code>
value with the added effect of assigning a yellow tint to comments: it
tones down the saturation of colours that apply to code syntax
(standard font-lock faces and others inheriting from them).</p>
  </li>
  <li>
    <p>The <code>modus-themes-links</code> variable is expanded to accept the new value
of <code>neutral-underline-only</code>: it removes the foreground from the link
and draws a neutral gray underline below it.</p>
  </li>
</ul>

<h2>Refinements to existing packages or face groups</h2>

<ul>
  <li>
    <p>Refashioned all faces that pertain to emails, including Gnus, Mu4e,
Notmuch, and the standard <code>message.el</code> library.  This concerns the
colours that apply to the message header keys and their values, as
well as quote levels.</p>

    <ul>
      <li>
        <p>Introduced more contrasting hues for headings and made more
considerate use of bold typography.  The new colour combinations are
better suited for the task of delivering a sense of structure;
structure that is at once effective and subtle.</p>
      </li>
      <li>
        <p>Applied less intense colours throughout all quotation levels.</p>
      </li>
      <li>
        <p>Revised the sequencing of hues in quotation levels to allow distinct
levels to stand out more without relying on excessive saturation.</p>
      </li>
      <li>
        <p>Aligned the styling of Notmuch header dates with their counterparts
in other similar contexts, in pursuit of theme-wide consistency.</p>
      </li>
    </ul>
  </li>
  <li>
    <p>Rewrote the faces of EBDB to achieve a better sense of structure.</p>
  </li>
  <li>
    <p>Refined the colour combinations of change-log and log-view buffers to
make it easier to discern distinct elements.</p>
  </li>
  <li>
    <p>Tweaked the colours of certain Elfeed constructs to improve the
overall presentation of its search buffers.</p>
  </li>
  <li>
    <p>Changed the colour combinations of <code>M-x re-builder</code> to amplify the
distinction between the matching regexp groups while still reducing
their overall intensity.</p>
  </li>
  <li>
    <p>Reconfigured the <code>diff-changed</code> face to always extend its background
to the edge of the window.  Such “changed” lines are visible in
<code>diff-mode</code> buffers when the command <code>diff-unified-&gt;context</code> is
invoked.</p>
  </li>
  <li>
    <p>Tweaked the colour combinations of ancillary faces in diff buffers
when the variable <code>modus-themes-diffs</code> is set to the value <code>fg-only</code>.
In particular:</p>

    <ul>
      <li>
        <p>Removed the subtle background from the diff hunk headings and changed
their colour to ensure good visibility—guarantees a sense of
structure.</p>
      </li>
      <li>
        <p>Made the context lines inherit the default foreground colour (pure
black/white), so that it contrasts better with red, green, and
yellow text.</p>
      </li>
      <li>
        <p>Applied an accented foreground to the diff header.  This is to
ensure that it is not mistaken for a diff hunk’s context.</p>
      </li>
    </ul>

    <p>All these guarantee that the foreground-only highlights in line-wise
differences draw more attention to themselves.</p>
  </li>
  <li>
    <p>Aligned all the standard hi-* faces with their default aesthetics.
Those are used by commands such as <code>highlight-symbol-at-point</code>.
Thanks to Philip K. for the valuable feedback in issue 157:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/157">https://gitlab.com/protesilaos/modus-themes/-/issues/157</a>.</p>
  </li>
  <li>
    <p>Removed obsolete Consult faces and added new ones, so as to remain in
sync with the latest developments in that project.  Thanks to Daniel
Mendler (Consult’s maintainer) for reporting the inconsistency in
issue 155: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/155">https://gitlab.com/protesilaos/modus-themes/-/issues/155</a>.</p>

    <ul>
      <li>
        <p><code>consult-preview-line</code> now retains fontification on the current
line, instead of applying its own foreground.</p>
      </li>
      <li>
        <p><code>consult-narrow-indicator</code> is refashioned to be colour-coded in a
consistent way with <code>consult-async-split</code>, as both denote the
delineation of a given scope.</p>
      </li>
      <li>
        <p><code>consult-imenu-prefix</code> contrasts better with text on its current
line, while it adapts to possible customisations performed on the
Consult front.</p>
      </li>
    </ul>
  </li>
  <li>
    <p>Expanded the coverage of <code>marginalia</code> faces to two include
<code>marginalia-char</code> and <code>marginalia-type</code>.  This is done in the interest
of internal consistency between the elements of this set, as their
defaults were also accessible (they inherit from standard faces that
we already support).</p>
  </li>
  <li>
    <p>Opted to render the Notmuch logo in a neutral gray backdrop.  This was
deemed necessary as the logo is an immutable image file that consists
of black and white strokes.  Black and white are the main background
values of <code>modus-vivendi</code> and <code>modus-operandi</code> respectively, which
could lead to confusion.  The neutral gray ensures that the logo is
visible at all times.  Thanks to Utkarsh Singh for the feedback in
issue 122: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/122">https://gitlab.com/protesilaos/modus-themes/-/issues/122</a>.</p>
  </li>
  <li>
    <p>Refined the dedicated colour values used for diff hunk headings, as
seen in diff-mode buffers or Magit.  The new colours yield text that
is easier to read by slightly toning down the combined intensity of
background+foreground.</p>
  </li>
  <li>
    <p>Removed the subtle background of <code>diff-header</code> and <code>diff-file-header</code>.
The header’s foreground and textual representation suffice to render
it distinct in its context.</p>
  </li>
  <li>
    <p>Tweaked <code>org-agenda-structure</code> and <code>org-scheduled</code> to enhance the
usability of Org Agenda buffers.</p>

    <ul>
      <li>
        <p>Made <code>org-agenda-structure</code> use the largest possible height that we
expose to users: <code>modus-themes-scale-5</code>.</p>
      </li>
      <li>
        <p>Re-calibrated the hueness of <code>org-scheduled</code> and amplified its
saturation, in order to better convey the meaning of a scheduled
task.</p>
      </li>
    </ul>

    <p>Thanks to Morgan Smith for the valuable feedback in issue 153:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/153">https://gitlab.com/protesilaos/modus-themes/-/issues/153</a>.</p>
  </li>
  <li>
    <p>Tweaked the faces of the <code>bongo</code> package to enhance the
distinctiveness of the constructs they style.</p>
  </li>
  <li>
    <p>Adjusted the overall aesthetic of calendar faces in the interest of
theme-wide consistency.</p>
  </li>
  <li>
    <p>Aligned the visual metaphors of <code>org-code</code> with those of <code>org-macro</code>
and <code>org-verbatim</code>, by ensuring that a subtle background is present
behind the affected text, while the foreground conforms with the norms
of the <code>modus-themes-no-mixed-fonts</code> customisation option.</p>
  </li>
  <li>
    <p>Made quoted text in Info buffers look the same as <code>org-verbatim</code> and
Markdown’s inline code.</p>
  </li>
  <li>
    <p>Instructed the faces of <code>info-colors</code> to inherit from appropriate
font-lock faces.  This guarantees that everything works as intended
with the various values of <code>modus-themes-syntax</code>.</p>
  </li>
  <li>
    <p>Refined the language tag of Markdown fenced blocks so that it does
attract unwarranted attention while delivering on its intended
purpose.</p>
  </li>
  <li>
    <p>Rendered explicit the slant of ace-window hints, guaranteeing that it
does not inherit from the underlying text.  Thanks to Nicolas De
Jaeghere for the patch:
<a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/27">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/27</a>.</p>

    <p>[ Some more changes have been discussed, but those require tweaks to
  the upstream package. ]</p>
  </li>
  <li>
    <p>Ensured that the <code>org-tree-slide-header-overlay-face</code> never draws an
overline when the variable <code>modus-themes-headings</code> includes a relevant
setting for heading level 1.  Such as with the following example (all
customisation options are documented in the themes’ manual):</p>

    <p>(setq modus-themes-headings
        ‘((1 . section)
          …))</p>
  </li>
  <li>
    <p>Extended support for the new <code>tab-line-tab-inactive-alternate</code> face as
that occurs in Emacs28 (current development target).  It comes into
effect when the variable <code>tab-line-tab-face-functions</code> includes a
value of <code>tab-line-tab-face-inactive-alternating</code>.</p>
  </li>
</ul>

<h2>Newly supported packages</h2>

<ul>
  <li>
    <p>bbdb :: Thanks to Nicolas De Jaeghere in issue 128:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/128">https://gitlab.com/protesilaos/modus-themes/-/issues/128</a>.</p>
  </li>
  <li>
    <p>mmm-mode :: Thanks to Davor Rotim for the feedback in issue 161:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/161">https://gitlab.com/protesilaos/modus-themes/-/issues/161</a>.</p>
  </li>
  <li>
    <p>quick-peek :: Thanks to Burgess Chang for the feedback in issue 151:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/151">https://gitlab.com/protesilaos/modus-themes/-/issues/151</a></p>
  </li>
  <li>
    <p>selectrum-prescient :: This new package was brought to my attention by
Manuel Uberti.  The intent is to phase out the faces in Selectrum,
namely <code>selectrum-primary-highlight</code>, <code>selectrum-secondary-highlight</code>,
though those will still be supported by the Modus themes for the
foreseeable future.</p>
  </li>
  <li>
    <p>shortdoc</p>
  </li>
  <li>
    <p>spray</p>
  </li>
  <li>
    <p>terraform-mode :: Thanks to Kevin Fleming for the feedback in issue
159: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/159">https://gitlab.com/protesilaos/modus-themes/-/issues/159</a>.</p>
  </li>
  <li>
    <p>vc-dir (Emacs28)</p>
  </li>
</ul>

<h2>Theme-related contributions to the wider community</h2>

<ul>
  <li>
    <p>Contributed the faces for <code>vc-dir</code> in Emacs28 and applied them to all
VC backends: <a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=46358">https://debbugs.gnu.org/cgi/bugreport.cgi?bug=46358</a> and
<a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=46745">https://debbugs.gnu.org/cgi/bugreport.cgi?bug=46745</a>.</p>
  </li>
  <li>
    <p>Contributed a new face and some related tweaks to Emacs’
<code>shortdoc.el</code>: <a href="http://debbugs.gnu.org/cgi/bugreport.cgi?bug=46748">http://debbugs.gnu.org/cgi/bugreport.cgi?bug=46748</a>.</p>
  </li>
  <li>
    <p>Added faces to the <code>tab-bar-echo-area.el</code> package:
<a href="https://github.com/fritzgrabo/tab-bar-echo-area/pull/2">https://github.com/fritzgrabo/tab-bar-echo-area/pull/2</a>.</p>
  </li>
  <li>
    <p>Reported issue that led to the review of the header face in
<code>org-tree-slide</code>: <a href="https://github.com/takaxp/org-tree-slide/issues/38">https://github.com/takaxp/org-tree-slide/issues/38</a>.</p>
  </li>
  <li>
    <p>Helped refine the faces of the <code>rlist.el</code> package:
<a href="https://gitlab.com/mmemmew/rlist/-/commit/386f506d0110bebedd3a48ff972adba96e2232eb">https://gitlab.com/mmemmew/rlist/-/commit/386f506d0110bebedd3a48ff972adba96e2232eb</a>.</p>
  </li>
</ul>

<h2>Documentation updates</h2>

<ul>
  <li>
    <p>Wrote about the indirect support for the <code>goggles</code> package.  I had
helped write its faces, as was documented in the changelog for version
1.1.0 of the themes.  Thanks to Manuel Uberti for bringing this to my
attention in issue 158:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/158">https://gitlab.com/protesilaos/modus-themes/-/issues/158</a>.</p>
  </li>
  <li>
    <p>Explained that any changes to <code>custom-theme-load-path</code> and/or
<code>custom-theme-directory</code> should be performed before the themes are
loaded.  Thanks to Adrian Manea for the feedback in issue 156:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/156">https://gitlab.com/protesilaos/modus-themes/-/issues/156</a>.</p>
  </li>
  <li>
    <p>Included the symbol <code>bg-only</code> in the <code>modus-themes-diffs</code> section of
the manual.  Thanks to user “iSeeU” for reporting the omission:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/154">https://gitlab.com/protesilaos/modus-themes/-/issues/154</a>.</p>
  </li>
  <li>
    <p>Expanded the manual’s entry on the semantics of the optional heading
scale used by the themes (the variables <code>modus-themes-scale-[1-5]</code>).
The values 1-4 apply to regular headings, with 4 being the largest on
the scale.  While <code>modus-themes-scale-5</code> is reserved for special
headers, such as Org <code>#+title:</code> or the Org Agenda’s structure.  Recall
that those variables only come into effect if the boolean variable
<code>modus-themes-scale-headings</code> is set to a non-nil value (it is nil by
default).</p>
  </li>
  <li>
    <p>Made several changes to the <code>modus-themes.org</code> file in an effort to
improve the accuracy of the generated Texinfo markup.  Thanks to Glenn
Morris and Richard Stallman for their valuable feedback in
<a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45143">https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45143</a>.</p>
  </li>
  <li>
    <p>Recorded a note in the manual on the intended colouration of
backgrounds applied by <code>mmm-mode</code>.  It explains what the constraints
are from an accessibility standpoint and how users can configure
things locally for more colourful, yet inaccessible, backgrounds.
Thanks to Davor Rotim for the valuable feedback in issue 161:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/161">https://gitlab.com/protesilaos/modus-themes/-/issues/161</a>.</p>
  </li>
  <li>
    <p>Refined the manual’s note on prism.el, simplifying the code samples
and clarifying the commentary.</p>
  </li>
  <li>
    <p>Wrote indices for concepts, variables, functions, which are rendered
in the Info manual.</p>
  </li>
  <li>
    <p>Elaborated on the possibility—and relative merits—of implementing
a theme-agnostic hook for advanced face configurations, as opposed to
relying on <code>modus-themes-after-load-theme-hook</code>.  Thanks to Daniel
Mendler for the valuable feedback in issue 131:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/131">https://gitlab.com/protesilaos/modus-themes/-/issues/131</a>.</p>
  </li>
</ul>

<h2>Miscellaneous</h2>

<ul>
  <li>
    <p>Rewrote the documentation string of the <code>deftheme</code> declaration of
<code>modus-operandi</code> and <code>modus-vivendi</code>.</p>
  </li>
  <li>
    <p>Provided links to the Info nodes that discuss each of the <code>defcustom</code>
declarations.</p>
  </li>
  <li>
    <p>Wrote doc strings for every custom face that the themes define.</p>
  </li>
</ul>
        
      


guid: https://protesilaos.com/codelog/2021-03-17-modus-themes-packaging-changes/
title: Modus themes: packaging changes for GNU ELPA and MELPA
url: https://protesilaos.com/codelog/2021-03-17-modus-themes-packaging-changes/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p class="info"><strong>Update 2021-03-28:</strong> We got feedback from MELPA: the <code>modus-themes</code>
will stay there after all!  The newer parts of the discussion start from
here: <a href="https://github.com/melpa/melpa/issues/7245#issuecomment-808810507">https://github.com/melpa/melpa/issues/7245#issuecomment-808810507</a>.</p>

<p>As you may know, the Modus themes are part of Emacs28 for a few months
now.  Their latest version was synced upstream recently (read the
<a href="https://protesilaos.com/codelog/2021-03-04-modus-themes-1-2-0/">release notes of version
1.2.0</a>).
The upgrade took longer than usual because there was a major refactoring
between versions <code>0.13.0</code> and <code>1.0.0</code>: in short, the themes are no
longer standalone files but are instead derived from a common source,
share customisation options and functions/commands, and are easier to
maintain.</p>

<p>This update sets in motion a series of events that I wish to be
transparent about.  Users updating from older versions to &gt;= <code>1.0.0</code>,
are advised to read the <a href="https://lists.gnu.org/archive/html/emacs-devel/2021-03/msg00300.html">announcement on the emacs-devel mailing
list</a>.
The <a href="https://protesilaos.com/emacs/modus-themes-changelog/">web page of the change
log</a> is also available.</p>

<h2>Changes for GNU ELPA</h2>

<ul>
  <li>
    <p>GNU ELPA, the official package archive that comes preconfigured with
Emacs, is instructed to build the new <code>modus-themes</code> package directly
from upstream Emacs.  It is considered a <code>:core</code> package, meaning that
whenever we update the themes in emacs.git we will automatically get a
new version on GNU ELPA.  This is meant as a convenience for users who
are running a stable version of Emacs, such as Emacs27.</p>
  </li>
  <li>
    <p>GNU ELPA also serves as a point of reference and credible source
provider for other package archives such as Guix (see <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/111">issue
111</a> on the
Modus themes’ issue tracker).</p>
  </li>
  <li>
    <p>The old GNU ELPA packages <code>modus-operandi-theme</code>,
<code>modus-vivendi-theme</code> (at version <code>0.12.0</code>) will soon be replaced with
code that automatically pulls in the new <code>modus-themes</code> package.
Then, after a grace period of, say, 6 months, the old packages will be
deleted and only <code>modus-themes</code> will remain.  This has been discussed
in Emacs <a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=46964">bug#46964</a>.
I still have not had the time to study how those in-place substitutes
will be implemented, but rest assured that it will be done.</p>
  </li>
  <li>
    <p>The <code>modus-themes</code> in emacs.git and, by extension, in elpa.git are
updated whenever I tag a new release.  This happens every month or so.
The next version is <code>1.3.0</code>, which will be published some time in
mid-April.</p>
  </li>
</ul>

<h2>Removal from MELPA</h2>

<p class="info"><strong>Update 2021-03-28:</strong> We got feedback from MELPA: the <code>modus-themes</code>
will stay there after all!  The newer parts of the discussion start from
here: <a href="https://github.com/melpa/melpa/issues/7245#issuecomment-808810507">https://github.com/melpa/melpa/issues/7245#issuecomment-808810507</a>.</p>

<ul>
  <li>
    <p>MELPA maintainers, who have become aware of the status of the themes
as described above, have asked me to delete the <code>modus-themes</code> package
from their archive (see issues
<a href="https://github.com/melpa/melpa/issues/7245">#7245</a> and
<a href="https://github.com/melpa/melpa/issues/7246">#7246</a>).  The idea is
that too many package variants can be confusing to users.</p>
  </li>
  <li>
    <p>I will comply with the MELPA maintainers’ request to delete the
<code>modus-themes</code> package from their archive.  This will be done with a
pull request against melpa.git either before the end of this week or
the beginning of the next.</p>
  </li>
  <li>
    <p>Existing users should be able to switch to the package provided by GNU
ELPA.  I honestly do not know whether the transition will be seamless
(e.g. if you have <code>(use-package modus-themes ...</code>) or whether it will
require manual intervention.  My apologies for whatever inconvenience.</p>
  </li>
</ul>

<hr />

<p>All of the above combined mean that there will no longer be a package
archive that contains a version of the themes corresponding to the
latest commit on modus-themes.git.  To run the bleeding edge, you must
either use something like <code>quelpa</code> or <code>straight.el</code>, or manually clone
and maintain a local copy of
<a href="https://gitlab.com/protesilaos/modus-themes">modus-themes.git</a>.</p>

<p>This is all for now.  Please <a href="https://protesilaos.com/contact/">contact
me</a> if you have any questions.  I am
also posting this announcement on the Modus themes’ issue tracker, in
case you want to comment there: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/167">https://gitlab.com/protesilaos/modus-themes/-/issues/167</a>.</p>
        
      


guid: https://protesilaos.com/codelog/2021-03-25-emacs-eww/
title: EWW and my extras (text-based Emacs web browser)
url: https://protesilaos.com/codelog/2021-03-25-emacs-eww/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=1lyGegcYxTI">https://www.youtube.com/watch?v=1lyGegcYxTI</a></p>
         
         <p>In this video I demonstrate the text-based web browser that is built
into Emacs: <code>eww</code>, or else the “Emacs Web Wowser”.  While it is quite
usable without any customisations, I have written several extensions for
it to make my quotidian usage a bit more pleasant.</p>

<p>Refer to my Emacs configuration file (“dotemacs”) for the implementation
details: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.  The specific item that
contains those extensions is <code>prot-eww.el</code>.  Everything is part of my
dotfiles’ repository: <a href="https://gitlab.com/protesilaos/dotfiles">https://gitlab.com/protesilaos/dotfiles</a>.</p>
        
      


guid: https://protesilaos.com/codelog/2021-04-14-emacs-diary-calendar/
title: Emacs Diary and Calendar for tracking appointments
url: https://protesilaos.com/codelog/2021-04-14-emacs-diary-calendar/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=NkhgIB64zgc">https://www.youtube.com/watch?v=NkhgIB64zgc</a></p>
         
         <p>In this video I demonstrate how I use the suite of tools that is built
into Emacs for keeping track of time-sensite events in my life.  Its two
main components are the Diary and the Calendar.</p>

<p>Apart from the present demo, I have also written at length about this
topic and discussed my particular opinions in context.  Refer to my
Emacs configuration file (“dotemacs”) for the relevant documentation and
the accompanying configurations: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a>.</p>

<p>The specific item that contains my extensions for both the Diary and the
Calendar is called <code>prot-diary.el</code>.  Everything is part of my dotfiles’
repository: <a href="https://gitlab.com/protesilaos/dotfiles">https://gitlab.com/protesilaos/dotfiles</a>.</p>
        
      


guid: https://protesilaos.com/codelog/2021-04-15-emacs-diary-outline-minor-mode/
title: Make the Emacs Diary work as an Outline (outline-minor-mode)
url: https://protesilaos.com/codelog/2021-04-15-emacs-diary-outline-minor-mode/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>If you are new to the topic of the Emacs Diary and the Calendar, please
refer to yesterday’s video introduction:
<a href="https://protesilaos.com/codelog/2021-04-14-emacs-diary-calendar/">https://protesilaos.com/codelog/2021-04-14-emacs-diary-calendar/</a>.</p>

<p>One of the major upsides of the Emacs Diary is that it is a regular file
that you can navigate using whatever tools you like: Isearch and <code>M-x
occur</code>, Swiper or <code>consult-line</code>, and the like.  It also is possible to
extend it so that it uses the foldable headings that are familiar to
users of Org mode; a feature that comes from <code>outline-mode</code>.  We can add
that to any major mode by means of <code>outline-minor-mode</code>.</p>

<p>To make the outline work, we need to specify a pattern of what
constitutes a heading within the file.  This is controlled by the
buffer-local variable <code>outline-regexp</code>.  The best candidate for headings
is the Diary’s own comments.  It feels natural for users of Elisp to set
those to <code>;;</code>, so we have this:</p>

<pre><code class="language-elisp">(setq diary-comment-start ";;")
(setq diary-comment-end "")
</code></pre>

<p>Then we need to write the pattern for the headings.  I prefer that
heading levels start with at least three semicolons and a space, which
lets us still use comments for their intended purpose (the same way it
is in <code>elisp-mode</code>):</p>

<pre><code class="language-elisp">;; The pattern evaluates to ";;+\\{2,\\} [^ \t\n]"
(setq outline-regexp (format "%s+\\{2,\\} [^ \t\n]" diary-comment-start))
</code></pre>

<p>We can test our pattern in a new buffer with <code>M-x re-builder</code> and some
text samples:</p>

<pre><code>;; A regular comment.  This should not be matched.

;;; A heading level 1
;;;; A heading level 2
;;;;; A heading level 3
</code></pre>

<p>Now that we got everything in order, we just need to integrate with with
<code>diary-mode</code>:</p>

<pre><code class="language-elisp">(defun my-diary-extras-setup ()
  "Additional setup for Diary mode buffers."
  (when (derived-mode-p 'diary-mode)
    (setq outline-regexp (format "%s+\\{2,\\} [^ \t\n]" diary-comment-start))))

(add-hook 'diary-mode-hook #'my-diary-extras-setup)
</code></pre>

<p>Next time we access the <code>diary-file</code> and <code>diary-mode</code> gets enabled, we
will get headings function the way we want.  It then is up to you to
specify the key bindings you want to make navigating the outline easier.
For example:</p>

<pre><code class="language-elisp">(with-eval-after-load 'outline
  (let ((map outline-minor-mode-map))
    (define-key map (kbd "C-c C-n") 'outline-next-visible-heading)
    (define-key map (kbd "C-c C-p") 'outline-previous-visible-heading)
    (define-key map (kbd "C-c C-f") 'outline-forward-same-level)
    (define-key map (kbd "C-c C-b") 'outline-backward-same-level)
    (define-key map (kbd "C-c C-u") 'outline-up-heading)
    (define-key map (kbd "C-c C-a") 'outline-show-all)
    (define-key map (kbd "C-c C-v") 'outline-move-subtree-down)
    (define-key map (kbd "C-c M-v") 'outline-move-subtree-up)
    (define-key map (kbd "&lt;C-tab&gt;") 'outline-cycle))) ; This is from Emacs28
</code></pre>

<p>Finally we need to enable <code>outline-minor-mode</code>:</p>

<pre><code class="language-elisp">(add-hook 'diary-mode-hook #'outline-minor-mode)
</code></pre>

<p>Or <code>M-x outline-minor-mode</code>.</p>

<p>With those in place, we have set the foundations to make the Diary
buffer very easy to navigate, all while retaining its overall
simplicity.  I am using Daniel Mendler’s <code>consult</code> library, which
includes the <code>consult-outline</code> command (among many others): it lets you
jump to a heading using minibuffer completion and requires no extra
setup the way the built-in <code>imenu</code> does (though Imenu is also great in
its own right).</p>

<p>Personally, I also change the fontification of the Diary buffer, but
will not bother you with the technicalities.  Please refer to my
dotemacs instead: <a href="https://protesilaos.com/emacs/dotemacs">https://protesilaos.com/emacs/dotemacs</a> (specifically the
section <a href="https://protesilaos.com/emacs/dotemacs/#h:b4040bc0-7a2a-4f17-824d-42de621bd1b9">Calendar and Diary (and
prot-diary.el)</a>).</p>
        
      


guid: https://protesilaos.com/codelog/2021-04-16-emacs-moral-lessons/
title: Moral lessons from free software and GNU Emacs
url: https://protesilaos.com/codelog/2021-04-16-emacs-moral-lessons/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Raw link: <a href="https://www.youtube.com/watch?v=gwT5PoXrLVs">https://www.youtube.com/watch?v=gwT5PoXrLVs</a></p>
         
         <p>In this video blog I talk about my background with computers.  This
experience helped me learn five important lessons that apply to life in
general and free software in particular, especially GNU Emacs.</p>

<p>Below you can find the text of the presentation in <code>org-mode</code> notation
(this is plain text, in case you do not know).  I just noticed a few
typos and an error in the “forgo […] a loss” statements, but I hope
you get what I wanted to say (“to accept a loss…”).</p>

<hr />

<pre><code>#+TITLE: Vlog: Moral lessons from switching to Emacs
#+AUTHOR: Protesilaos Stavrou (https://protesilaos.com/)

In this video blog I want to share with you a topic that comes up from
time to time in my private email exchanges.  And that is my background
in computers and, basically, how I became an Emacs user.

I want to share with you my story, though I also wish to draw some
lessons from it and generalise them into insights that might be useful
for other people.

I think that as with life in general, our experience with computers goes
through various phases in which we become better at adapting to or
coping with evolving states of affairs, once we gain some familiarity
with the case-specific surroundings or parameters.

Each person is different and there is no one way of learning things.  I
feel though that hearing another person's experiences can broaden our
horizon, the same way we can read a book and get the essence of its
author's years of labour to accumulate the requisite knowledge.

* The first lesson from the early years of adulthood

I did not have a computer growing up.  I first started using one in the
university where I had to submit all my assignments in doc or pdf format
(circa 2006).  At the time I would visit the university's computer lab
to type in my work which I had prepared a manuscript for.

Even my typing skills back then were rudimentary and extremely clumsy.
I was using the index finger on both of my hands to hit the keys and had
to always look down to make sure I was typing the right thing.

This was true for all my years at the university, where I was enrolled
in the humanities.  I did, nonetheless, set up a blog in 2011 which
later evolved into my current website, though I had no technical
understanding of things back then: I just had essays which I thought
were worth publishing.

Then I got a job at the European Parliament and moved to Brussels,
Belgium (2012).  There I would have to use the computer at the office
every single day for most of my tasks.  I would have to write analyses,
edit or prepare amendments to legislation, deal with emails... You get
the idea.

At some point I was working on a colleague's laptop because I did not
have one myself.  The task involved switching between two apps to copy
and paste text back and forth.  By "copy and paste", I mean to right
click, find the "copy" action, then move the mouse and right click again
for "paste".  It was a tedious process and I was still not competent as
a computer user.  So the colleague asked me why I was not using Alt+Tab.
My reaction was to ask what kind of app that is and how to enable it...

That day I learnt how to use a keyboard shortcut.  It was a revelation!
Soon thereafter I followed it up with Ctrl+c, Ctrl+v, Ctrl+z, Ctrl+a.

The first lesson from this experience is that when you have no access to
learning resources, when you are not exposed to a superior paradigm, you
are always trapped in a cycle of self deprecation and perceived
powerlessness.  Humans are good at rationalising their own condition, so
we can come up with plausible explanations such as that "my dexterity is
not good enough", or "it actually helps me write better, as it is more
deliberate", and the like.

Knowledge or a means of learning is key to emancipate yourself from your
own inadequacies.  Never make excuses that hinder your potential to
learn something new.  Always keep an open mind.

* The second lesson before the transition to free software

I was eventually granted a laptop at my work.  It was a Macbook Pro of
some sort, though I still have no idea what its model was.  It did not
matter.  What I cared about was that it was the first time in my life
where I had my own computer---I could use it from home and start
learning more about it in my free time!

So I started personalising my computer experience over time.  This meant
that I would buy various apps that were supposed to help me with
boosting my productivity.  That is when the next set of post-hoc
rationalisations started developing.  I was deluding myself into
thinking that "oh, my efficiency was not good enough, but thankfully
this app has fixed the problem".  It did not.  It could not.

And this is something that relates to Emacs as well.  There is no
magical way to boost your productivity by changing the software you use,
while keeping your mindset constant.  To become productive you have to
identify the patterns in your method or workflow that hamper your
output.  Apps are tools that you use.  And, despite its extensibility,
Emacs can neither read your mind, nor reprogram it.  It all starts with
your mentality and with how you conduct yourself.

I had thus wasted a fair bit of money on shiny apps that claimed to fix
my perceived problems.  I would speculate, in retrospect, that the
absence of tools for self learning that is prevalent in the proprietary
app ecosystem conditions users, perhaps inadvertently, into not
questioning things and conforming with the status quo.

We are all different and this means that what works for one may not
apply to another.  Thus, a user who is not offered genuine alternatives,
a method that helps them decide for themselves, is eventually led to
rationalise their condition as a fault of their own.  This happened to
me.  I bought apps for productivity but did not really change anything
in my life.  Instead I thought that the real reason for not being
productive was with my awkwardness as a computer user, or something
along those lines.

The second lesson I learnt the hard way is that you must always assess
someone on their own merits.  Do not judge people for trying and failing
to meet some other person's standards.  And, extended to computers, do
not fall into the trap of T.I.N.A., which is an acronym for "There Is No
Alternative".  There always are alternatives---always---provided you
change your mindset and stop internalising your induced victimhood as
some supposedly intrinsic quality of yours.  It is not your fault.

* The third lesson after switching to GNU/Linux

I still had that Macbook laptop in 2016 when I finally decided to switch
to free software.  I had read a bit about Linux and how it was
Unix-like, though I did not understand what that meant.  It was too far
removed from my knowledge at the time.  Instead, what helped me get
started was the GNU Image Manipulation Program; a good tool, which goes
by an unfortunate acronym.  Alas!

Anyhow, I installed the GNU IMP on my laptop because I wanted to do some
basic image editing and was not willing to spend money on yet another
shiny app from the store.  The program was good enough for my needs, so
I thought I would check their website in case they were making some
other programs as well.  At the time I was still thinking that "free
software" meant free of charge.  But I soon learnt about the moral
qualities of free software, about liberty and being in control of your
own computer, which means to be in control of a large part of your life.

So I decided to nuke the Mac and replace it with Linux Mint.  This
happened in the summer of 2016.  After a weeks, I decided to distro hop
and went with Arch Linux.  I still had no idea what I was doing.  I just
read the wiki and it somehow worked!

Moving to free software changed my life for the better because it put me
in a course of escaping from /heteronomy/: rule by another.  I wanted
/autonomy/: rule by one self.  My time buying apps for the Mac was one of
heteronomy not only because I did not control the software, but mostly
due to the mentality that is associated with using tools that you do not
understand: you are always dependent on someone else, you are trapped in
that cycle of powerlessness and victimhood that I alluded to earlier.

The third lesson is that autonomy comes at a cost.  It presupposes
responsibility, and that is predicated on discipline.  If you do not
want to be responsible, if you prefer to be spoon-fed what life has to
offer, then you remain in a state of heteronomy with its fake comforts.
This is not about the Mac per se.  It is about understanding your
system.

Here I must stress that discipline is not the same as conformity with
the established order.  No!  Discipline is a virtue.  It is about
overcoming your pernicious rationalisations; those that keep you trapped
in a state of perceived helplessness.  It is about deciding to be in
charge of yourself and being prepared to deal with the challenges from a
position of control.  Discipline is about adding structure to a
theretofore chaotic life.

Never mistake conformism or obedience with virtue.

* The fourth lesson that brought me to GNU Emacs

I had not fully understood the third lesson of autonomy even after I had
switched to GNU/Linux because I retained one very bad habit from the old
days: I was not reading the wealth of documentation on offer.  Instead I
would search the Web for some quick and easy fix, copy-paste it, and
move on to the next task.

This mentality held back my potential.  I was still behaving
heteronomously and I was still rationalising it as "oh, this is too
difficult for me---I was just a student of liberal arts!".  That is
nonsense.  It is a mindset that sets you up for failure.

What made me change habits was the realisation that there is no "cheat
code" or "secret life hack" to gaining expertise in any given field.
You have to earn it.  And this means you have to put some serious effort
into it.

I understand how people feel for finding themselves in such a
predicament.  I was just like that until not too long ago.  Just look
around you: the zeitgeist, the general spirit of our times, is to do
things quickly.  The most common example is some formulaic video
tutorial that promises to make you a pro in five minutes: "here are 10
tricks to be happy!".

We can discern the same pattern in the Emacs space.  You must have
noticed this type of post where someone claims to want to switch to
Emacs but they do not wish to lose any of their productivity.  That only
shows that they do not understand what they want.  They have been led to
believe in this narrative of the quick fix, the secret life hack, the
one magic thing that provides a shortcut to wisdom, and so on.  There is
none of that.  It is all a lie.  You are chasing chimeras.  As for Emacs
in particular, you simply cannot be an Emacs tourist---it does not work
that way.

To learn your way with free software, and to gain expertise in general,
you must commit to it with an open mind.  This means that you must have
already prepared yourself mentally, which implies that you are willing
to forgo some short-term loss in productivity in pursuit of a longer
term transition to a more autonomous modus vivendi.

So the fourth lesson I learnt is to be modest, patient, persistent, and
courageous.  In the free software space this set of virtues boils down
to a simple yet critical instruction: *read the documentation* and be
methodical about it.  Don't entertain unrealistic expectations of doing
it in 5 minutes.  Take your time.  Read, read, read!  And proceed slowly
from the basics to the more advanced issues.

* The fifth lesson after switching to GNU Emacs

I became an Emacs user in the summer of 2019 while I had bought my first
computer in 2018, which is the Thinkpad X220 that I am now using.  I
started from scratch, read the manual, and gradually worked my way to
where I currently am.  I am not a programmer, though that is not an
excuse: it is just a matter of fact as well as a statement of intent to
continue to improve.  But I do not want to talk to you about my
Emacs-related projects.  Those are chronicled in all the videos I have
published, as well as the relevant information I post on my website.

Instead, I want to focus on a general theme which I think hints again at
heteronomy: which is the self-description of the geek or the nerd.  Now
I understand that those terms are given a positive spin, though I am
still not happy with them.  My problem with them comes from the
dichotomy they assume where on the one side you have "normies" and on
the other you get the geeks/nerds.  My experience as a computer user
tells me that there is no such binary there is a spectrum of possible
combinations and permutations in between the extremes.  Plus, I am not
convinced that "normal" means what we want.

"Normal" signifies the norm, the common pattern.  Though it can also
hint at normativity in the form of an exhortation: this is how people
should behave.  I object to such false morality because in the computer
it translates into "people should remain trapped in arrangements they do
not control and in which they are utterly powerless to enact reform".  I
transcended those fake constraints and I believe that everyone can do
the same if only we show them the way.

Furthermore, I object to the characterisation of the free software
expert as some sort of a weirdo, even if you put a positive spin to it.
Remember that we are talking about liberty, about autonomy and a life
that is characterised by an ethos of discipline.  This is not weird: it
is about realising your potential.  It is about tearing apart that
cobweb of induced helplessness and rationalisations that keeps you
subservient to forces outside your control as an individual and as a
member of a wider community.

There is a song of an old Greek rock band which says: "what are we even
doing here in the others' night?" (Τρύπες: Τι γυρεύουμε εμείς μέσα στη
νύχτα των άλλων).  Which I think is a great metaphor for this fifth
lesson: do not live under some other person's shadow, do not use their
language or their associations to make sense of the world because that
forces you to vindicate the categories they assume as constant.

No, I am not a nerd.  I am an Emacs user as a consequence of the fact
that I want more autonomy.  I am unapologetic about it and fully
prepared to deal with the consequences.

* Emacs is just another tool

In conclusion, I must say that the main takeaway from this video blog is
that you need to check your mentality and you need to get into the
mindset of doing things that give you more control.  This involves
learning by reading, as well as through trial and error.

Couched in those terms, Emacs will not solve the problems in your life.
It will not become your powerhouse of productivity after one weekend's
worth of effort.  You are willing to commit to it for the long term
because you are driven by the spirit of liberty, of controlling your own
setup and being very deliberate about how the whole system is pieced
together.

Now I can almost hear your rationalisations speaking: "but it is hard",
"oh, but I am a dummy" and stuff like that.  You need to stop heeding
those calls.  They are not your friends.  If you set yourself up for
failure, you will always think that you are inadequate, that something
is wrong with you.  And your mind will play along, whispering to you
that you are all those things and that you deserve to remain in that
inert state.

What my journey as a computer user taught me, and what Emacs rendered
crystal clear, is that you will always think that you are an idiot for
as long as you remain heteronomous.  Things will begin changing once you
start making steps towards autonomy.  In my case that took a few years.
It is a gradual process which, I think, has made me a competent computer
user as well as a better person.

To recapitulate:

1. Without knowledge you are trapped in a cycle of self deprecation and
   perceived powerlessness.  Seek knowledge.
2. You must always assess someone on their own merits, instead of some
   other person's standards.  Do not fall into the trap of TINA (There
   Is No Alternative), because there always is an alternative.
3. Autonomy comes at cost.  You must be prepared to forgo some
   short-term comfort in order to prepare yourself for gaining control.
   This presupposes discipline (and discipline is not conformism!).
4. Be modest, patient, persistent, and courageous.  In practical terms,
   understand that there is no shortcut to gaining expertise.  For
   software, this means that you must always read the documentation.
5. Do not live under another person's shadow ("in the night of the
   others"); do not play along with their role games; do not vindicate
   their narratives and provide assent to their presumptions.

With those in mind you will be prepared to use free software in general
and GNU Emacs in particular.  You will upgrade yourself.
</code></pre>
        
      


guid: https://protesilaos.com/codelog/2021-04-17-modus-themes-1-3-0/
title: Modus themes 1.3.0 for GNU Emacs
url: https://protesilaos.com/codelog/2021-04-17-modus-themes-1-3-0/
feedurl: https://protesilaos.com/codelog.xml
content_mime_type: text/html
content:
        
         
         <p>Just published version <code>1.3.0</code> of <a href="https://protesilaos.com/emacs/modus-themes">the Modus themes</a>.
The detailed release notes are reproduced below.  For any questions
pertaining to this publication feel welcome to <a href="https://protesilaos.com/contact/">contact me</a>.</p>

<p>My immediate task now is to prepare patches for upstream Emacs
(Emacs28).  GNU ELPA syncs directly from emacs.git, so expect an update
shortly thereafter.</p>

<hr />

<h2>Modus themes version 1.3.0</h2>

<p>By Protesilaos Stavrou <a href="mailto:info@protesilaos.com">info@protesilaos.com</a> on 2021-04-17</p>

<p>This entry records the changes introduced to the project since the
publication of version 1.2.0 (2021-03-04).  There have been around 100
commits in the meantime, as is the norm with all releases hitherto.</p>

<p>Every colour-related modification documented herein conforms with the
overarching accessibility objective of the themes for a minimum contrast
ratio of 7:1 between background and foreground values in their given
combination (the WCAG AAA standard).</p>

<p>As the official manual is referenced several times throughout this log,
make sure to store its URL: <a href="https://protesilaos.com/emacs/modus-themes">https://protesilaos.com/emacs/modus-themes</a>.  Or
read it from Emacs’ Info reader by evaluating this form:</p>

<pre><code>(info "(modus-themes) Top")
</code></pre>

<p>If you are coming from older versions, please consult the change log
entry for version 1.0.0 with regard to the breaking changes that were
introduced.</p>

<p>Remember that the themes are built into Emacs28, and are available on
GNU ELPA, as well as other archives.</p>

<h2>Customisation options</h2>

<ul>
  <li>
    <p>The old <code>modus-themes-intense-hl-line</code> boolean variable has been
replaced by <code>modus-themes-hl-line</code>, which provides several options for
how to style the current line of <code>hl-line-mode</code>.  To retain the old
effect, one must do this:</p>

    <pre><code>;; Replacement for (setq modus-themes-intense-hl-line t)
(setq modus-themes-hl-line 'intense-background)
</code></pre>

    <p>The list of possible values:</p>

    <ol>
      <li>nil (default)</li>
      <li>intense-background</li>
      <li>accented-background</li>
      <li>underline-neutral</li>
      <li>underline-accented</li>
      <li>underline-only-neutral</li>
      <li>underline-only-accented</li>
    </ol>

    <p>The doc string of <code>modus-themes-hl-line</code> as well as the manual
describe the specifics.  Thanks to Manuel Uberti for the feedback in
commit b020592:
<a href="https://gitlab.com/protesilaos/modus-themes/-/commit/b020592e1a96d6e00d7d03faf9c293ec6081d49c">https://gitlab.com/protesilaos/modus-themes/-/commit/b020592e1a96d6e00d7d03faf9c293ec6081d49c</a>.</p>
  </li>
  <li>
    <p>The <code>modus-themes-mode-line</code> variable now accepts three new “accented”
styles that complement the existing set:</p>

    <ol>
      <li>nil (default)</li>
      <li>3d</li>
      <li>moody</li>
      <li>borderless</li>
      <li>borderless-3d</li>
      <li>borderless-moody</li>
      <li>accented</li>
      <li>accented-3d</li>
      <li>accented-moody</li>
    </ol>
  </li>
  <li>
    <p>The <code>modus-themes-region</code> is extended with two new options of an
“accent” background:</p>

    <ol>
      <li>nil (default)</li>
      <li>no-extend</li>
      <li>bg-only</li>
      <li>bg-only-no-extend</li>
      <li>accent</li>
      <li>accent-no-extend</li>
    </ol>
  </li>
  <li>
    <p>The default value of <code>modus-themes-headings</code> for per-level styles can
now be set to nil.  This fixes an inconsistency between the fallback
value, which accepted nil, and the per-level styles which did not.
Thanks to Mauro Aranda for reporting this in issue 163:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/163">https://gitlab.com/protesilaos/modus-themes/-/issues/163</a>.</p>

    <p>Please read the manual for the specifics of this variable, as it is an
alist that accepts several possible combinations.</p>
  </li>
</ul>

<h2>Updates to the manual</h2>

<ul>
  <li>
    <p>Rewrote the sections that cover the aforementioned customisation
options.</p>

    <ul>
      <li>For <code>modus-themes-mode-line</code>, we had to revise the recommendation
for setting <code>face-near-same-color-threshold</code> to 45000.  That value
is appropriate for the <code>moody</code> and <code>borderless-moody</code> options.
Whereas for <code>accented-moody</code> the number should be raised to 70000.
Thanks to Nicolas De Jaeghere for providing this piece of
information:
<a href="https://gitlab.com/protesilaos/modus-themes/-/commit/ab6ba698269f012ec880b690282264649bfb3b0d#note_551342198">https://gitlab.com/protesilaos/modus-themes/-/commit/ab6ba698269f012ec880b690282264649bfb3b0d#note_551342198</a></li>
    </ul>
  </li>
  <li>
    <p>Rephrased the GNU Free Documentation License quote to match the style
of other manuals that are also built into Emacs.</p>
  </li>
  <li>
    <p>Documented <code>org-mode</code> variables that affect the looks of various
fontification styles.</p>
  </li>
  <li>
    <p>Simplified the <code>kbd</code> macro that is declared in modus-themes.org to
allow GNU ELPA’s build system to parse the file for Emacs 26.</p>
  </li>
  <li>
    <p>Documented existing support for <code>tab-bar-mode</code> and <code>tab-line-mode</code>.</p>
  </li>
  <li>
    <p>Wrote a note on how to configure the <code>dimmer.el</code> library by Neil
Okamoto, in order to guarantee consistent results with the themes.
The key is to use the RGB colour space instead of CIELAB.</p>
  </li>
  <li>
    <p>Included note on shr.el fonts and how those are used by EWW and
Elfeed.</p>
  </li>
  <li>
    <p>Added a “Do-It-Yourself” (DIY) section on how to remap buffer-local
faces.</p>
  </li>
  <li>
    <p>Detailed a DIY method to make the buffer-local backdrop of a pdf-tools
page use a distinct colour than the default white for Modus Operandi.
Extended the same principle to Modus Vivendi and described how to
adapt to theme changes (such as via <code>modus-themes-toggle</code>).  Thanks to
Utkarsh Singh for providing feedback on this topic in issue 175:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/175">https://gitlab.com/protesilaos/modus-themes/-/issues/175</a>.</p>
  </li>
  <li>
    <p>Elaborated on DIY techniques to programmatically override the
saturation of all colours specified by the active Modus theme.  Thanks
to user pRot0ta1p for the feedback in issue 166:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/166">https://gitlab.com/protesilaos/modus-themes/-/issues/166</a>.</p>
  </li>
</ul>

<h2>Support for packages</h2>

<p>These are added to the already comprehensive list of explicitly
supported packages:</p>

<ul>
  <li>corfu</li>
  <li>
    <p>embark</p>
  </li>
  <li>
    <p>pandoc-mode.  Thanks to Farasha Euker for the feedback in issue 171:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/171">https://gitlab.com/protesilaos/modus-themes/-/issues/171</a>.</p>
  </li>
  <li>tab-bar-groups</li>
  <li>telega</li>
  <li>vertico</li>
</ul>

<p>Also added support for the <code>help-key-binding</code> face which is part of
Emacs 28.</p>

<h2>Changes to already supported faces or face groups</h2>

<ul>
  <li>
    <p>Renamed all internal faces that the themes defined from
“modus-theme-<em>” to “modus-themes-</em>”.</p>
  </li>
  <li>
    <p>Refashioned all Ediff faces in the process of a major review of this
tools’ overall design.  The manifold changes are:</p>

    <ul>
      <li>
        <p>All inactive diffs respect the underlying fontification
(e.g. programming syntax highlighting).  Before they would override
it with a gray foreground.</p>
      </li>
      <li>
        <p>All inactive diffs have been toned down, as their background is a
finer shade of gray than the prominent one that was used before.</p>
      </li>
      <li>
        <p>There no longer is a visual distinction between even and odd
inactive diffs (by means of different shades of gray).  We are of
the opinion that such subtleties, whose utility is marginal at best,
have no place in themes that are designed for accessibility.</p>
      </li>
      <li>
        <p>All bespoke gray colour combinations that were only intended for
those inactive diffs have thus been removed from each theme’s
palette.</p>
      </li>
      <li>
        <p>Active diffs follow the same style as diff-mode, to ensure
theme-wide consistency (all diff styles are controlled by the
variable <code>modus-themes-diffs</code>).</p>
      </li>
    </ul>

    <p>This topic was discussed at length (with screenshots) in issue 169:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/169">https://gitlab.com/protesilaos/modus-themes/-/issues/169</a>.  Thanks to
peniblec and Nicolas De Jaeghere for their feedback.</p>
  </li>
  <li>
    <p>Made <code>smerge-markers</code> and <code>vdiff-closed-fold-face</code> look like the
headings in <code>diff-mode</code> in the interest of consistency, especially
while configuring the <code>modus-themes-diffs</code> variable.</p>
  </li>
  <li>
    <p>Ensured consistency between all faces that pertain to key bindings in
contexts where the hint to the key is active, in that pressing the key
performs the action (e.g. Magit’s transient buffers, which-key,…).
The <code>help-key-binding</code> for Emacs 28 is not included in this group,
because it applies in cases where the keys are not active, such as in
Help buffers.</p>
  </li>
  <li>
    <p>Refined <code>epa-validity-disabled</code> and <code>epa-validity-high</code> faces.  The
former no longer uses a background, as that was considered an
exaggeration.  While the latter is cast in a cyan hue instead of green
for greater clarity (this relates to the general push to optimise for
red-green colour deficiency, which means to only use green where it is
absolutely necessary and, in such cases, to provide for a blue-ish
alternative, as with the <code>deuteranopia</code> value that can be assigned to
<code>modus-themes-diffs</code>).</p>
  </li>
  <li>
    <p>Reworked <code>ace-window</code>, <code>avy</code>, and <code>magit-blame</code> faces to ensure that
their overlays do not inherit the face properties of underlying text,
such as a different font family or height.  Thanks to Nicolas De
Jaeghere for the multiple merge requests and the concomitant feedback:</p>

    <ul>
      <li><a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/27">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/27</a>.</li>
      <li><a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/29">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/29</a>.</li>
      <li><a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/30">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/30</a>.</li>
      <li><a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/31">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/31</a>.</li>
      <li><a href="https://gitlab.com/protesilaos/modus-themes/-/merge_requests/32">https://gitlab.com/protesilaos/modus-themes/-/merge_requests/32</a>.</li>
    </ul>

    <p>Also thanks to Damien Cassou for reporting an intermediate problem
with <code>avy</code> in issue 177; a problem that was eventually addressed by
Nicolas De Jaeghere in merge request 31 (cited above):
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/177">https://gitlab.com/protesilaos/modus-themes/-/issues/177</a>.</p>
  </li>
  <li>
    <p>Optimised the colour combinations used by <code>avy</code> to improve the
distinction between consecutive characters.</p>
  </li>
  <li>
    <p>Reduced the brightness of EWW certificate faces, as they would attract
disproportionate attention to themselves.</p>
  </li>
  <li>
    <p>Reworked all EWW text field and button faces to look more like what
they are supposed to.</p>
  </li>
  <li>
    <p>Removed the slant and distinct foreground from the <code>org-quote</code> face,
as they would interfere with emphasis within the quote block.  Thanks
to Farasha Euker for the feedback in issue 171:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/171">https://gitlab.com/protesilaos/modus-themes/-/issues/171</a>.</p>
  </li>
  <li>
    <p>Reduced the intensity in colouration of <code>org-code</code> and <code>org-macro</code> in
order to avoid exaggerations and prevent their compounding effect in
technical documents that include a high concentration of those faces.
They still retain their overall character and continue to look like
variants of <code>org-verbatim</code>.</p>
  </li>
  <li>
    <p>Extended support for Selectrum’s new <code>selectrum-quick-keys-highlight</code>
and <code>selectrum-quick-keys-match</code>.</p>
  </li>
  <li>
    <p>Adjusted a few bongo faces for improved consistency and a more
pleasant result overall.  Quote from commit 07224cda08:</p>

    <pre><code>Refine bongo faces for consistency

The previous design was meant to keep the track fields distinct
from each other.  However the use of yellow was not good
aesthetically: it does not fit with the rest of the theme.

Upon further experimentation, I realised that the album field
(yellow) is only present when the artist and title fields are also
available: first is the title, then the artist, and finally the
album.  This is true even with `bongo-join-inserted-tracks` set to
a non-nil value.  So changing the face from yellow to a neutral
value is safe.

The other two faces are adapted to look better in the new context.
</code></pre>
  </li>
  <li>
    <p>Made more command prompt faces respond to changes in the variable
<code>modus-themes-prompts</code>.  This concerns faces from the groups cider,
circe, erc, indium, rcirc.</p>
  </li>
  <li>
    <p>Refashioned typescript faces, making them more prominent by default,
while also exposing them to the value of <code>modus-themes-syntax</code>.</p>
  </li>
  <li>
    <p>Revised the style of <code>info-colors-ref-item-command</code>.  This makes
commands look the same as functions, which is technically correct.  It
also predicates the exact style on the value of the variable
<code>modus-themes-syntax</code>.</p>
  </li>
  <li>
    <p>Made all enh-ruby-mode faces adapt to <code>modus-themes-syntax</code>.  Same for
julia.</p>
  </li>
  <li>
    <p>Reconfigured all ztree faces for stylistic consistency.  The
<code>ztreep-diff-model-add-face</code> now responds to the <code>deuteranopia</code> value
that can be passed to <code>modus-themes-diffs</code>.</p>
  </li>
  <li>
    <p>Appended the <code>:extend t</code> attribute to <code>gnus-summary-cancelled</code> and
<code>gnus-summary-selected</code>.  These are only noticeable on Emacs 28
following commit 88409b21c2 in emacs.git.</p>
  </li>
  <li>
    <p>Tweaked all faces of <code>highlight-changes-mode</code> to better deliver on the
intent of that mode.</p>
  </li>
  <li>
    <p>Opted to unconditionally render all <code>dired-async</code> faces in a bold
typographic weight, instead of basing them on a non-nil value for
<code>modus-themes-bold-constructs</code>.  Also changed <code>dired-async-message</code> to
a blue foreground, which further improves the themes’ performance for
red-green colour deficiency.</p>
  </li>
  <li>
    <p>Adjusted the colours of some <code>notmuch-crypto-*</code> faces to better convey
their meaning.</p>
  </li>
  <li>
    <p>Removed remaining conditional logic for underline styles in some
spell- and linter- related faces to ensure that all such cases are
controlled by the variable <code>modus-themes-lang-checkers</code> (building on
work that had been done in the past).</p>
  </li>
  <li>
    <p>Stopped changing <code>keycast-key</code> to match the modeline style, as that
diluted the meaning of the variable <code>modus-themes-mode-line</code>.</p>
  </li>
  <li>
    <p>Tweaked calendar and diary faces for stylistic effect, except for the
<code>diary</code> face which has been converted from a green to a blue variant
for the purposes of coping with cases of red-green colour deficiency.</p>
  </li>
</ul>

<h2>Miscellaneous</h2>

<ul>
  <li>
    <p>Clarified the changes in the backward-incompatible transition from
version 0.13.0 of the themes to &gt;= 1.0.0.  Thanks to Damien Cassou for
reporting the absence of easy-to-find information in issue 174:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/174">https://gitlab.com/protesilaos/modus-themes/-/issues/174</a>.</p>
  </li>
  <li>
    <p>There were three point releases after 1.2.0 which refined certain
aspects of the themes’ packaging so that they could work both as
built-in themes for Emacs as well as in package format via the likes
of GNU ELPA.  Those issues were eventually resolved by Basil
L. Contovounesios:</p>

    <ul>
      <li>Issue 162: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/162">https://gitlab.com/protesilaos/modus-themes/-/issues/162</a>.</li>
      <li>Emacs bug#45068: <a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45068#218">https://debbugs.gnu.org/cgi/bugreport.cgi?bug=45068#218</a>.</li>
    </ul>
  </li>
  <li>
    <p>Rewrote the <code>modus-themes-headings</code> variable’s declaration to improve
its presentation in Custom interfaces.  Thanks to Mauro Aranda for
submitting the patch for commit 1c60927ebd.</p>
  </li>
  <li>
    <p>Applied the <code>:format</code> keyword to all <code>defcustom</code> forms, based on the
aforementioned patch.  This should make all options look better in the
various Custom interfaces.  Thanks to Mauro Aranda for the feedback in
issue 163: <a href="https://gitlab.com/protesilaos/modus-themes/-/issues/163">https://gitlab.com/protesilaos/modus-themes/-/issues/163</a>.</p>
  </li>
  <li>
    <p>Refined the colour values <code>bg-alt</code> and <code>bg-dim</code> in <code>modus-vivendi</code> to
improve their instantiation on Textual User Interfaces.  In
particular, recalibrated the blue channel of light so that when the
TUI cannot render the colour directly, it defaults to a gray value
instead of a dark blue.</p>
  </li>
  <li>
    <p>Added a “Last-Modified” meta header to modus-themes.el, with gets
updated automatically and uses a timestamp.  This helps users who
track the themes’ git repo directly.  Thanks to Togan Muftuoglu for
the feedback in issue 168:
<a href="https://gitlab.com/protesilaos/modus-themes/-/issues/168">https://gitlab.com/protesilaos/modus-themes/-/issues/168</a>.</p>
  </li>
  <li>
    <p>Expanded the palette of each theme with accent values that are
reserved for use in the tab-bar.  Those are used by the newly
supported <code>tab-bar-groups</code> package.</p>
  </li>
  <li>
    <p>Recalibrated a few colour combinations to improve their resulting
legibility.  The changes should not be noticeable to the untrained
eye.  Interested parties can consult commit 349ea4a943.</p>
  </li>
  <li>
    <p>Tweaked the hueness of the <code>yellow-active</code> colour of <code>modus-operandi</code>.</p>
  </li>
</ul>

<p>Thanks once again to everyone involved!</p>
        
      


