<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Posts | Library of Trantor</title>
  <link href="https://www.shimmy1996.com/en/posts/"/>
  <link href="https://www.shimmy1996.com/en/posts/index.xml" rel="self"/>
  <updated>2021-04-24T21:44:00-05:00</updated>
  <author><name>Shimmy Xu</name></author>
  <id>https://www.shimmy1996.com/en/posts/</id>
  
  
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2021-04-24-bio-pages-multiscale-writing-and-xpa/</id>
    <title type="html"><![CDATA[Bio Pages, Multiscale Writing, and XPA]]></title><updated>2021-04-24T21:44:00-05:00</updated>
    <content type="html"><![CDATA[<p>Or, a roundabout way of explaining why I don't have an dedicated &quot;About&quot; page.</p>
<h2>Bio Pages</h2>
<p>I find bio pages hard to write.</p>
<p>I've always despised bio pages that sound like:</p>
<blockquote>
<p>Scott Danger Solo, MIB, is a WHSA certified Sigma-level worm-hole surfing professional that shoots first, crosses the streams, and thinks 4th-dimensionally.</p>
</blockquote>
<p>It grosses me out the same way that ego-flavored bubble gums would. I can't help but take these statements as a desperate attempt at smearing online contents with every last drop of legitimacy squeezed out of grand-yet-insincere-sounding words.</p>
<p>Most of the time, I opt to not include a bio on my online presences. Among the few exceptions is my old WordPress blog where I put:</p>
<blockquote>
<p>EE major; new to WP and not very good at it; weeb; disproportional appetite for new hardware compared to my wallet size; may appear on social networks as <code>shimmy1996</code>; let's be friends XDD.</p>
</blockquote>
<p>Even that felt too revealing for me. In other cases, I just use random made up sci-fi one-liners, for instance:</p>
<blockquote>
<p>University of Trantor, Extraterrestrial Lifeform Breeding and Culinary Arts Major</p>
</blockquote>
<p>Coming up with imaginary professions is actually a lot of fun and I can do this all day long. Just to give you a sneak peek at my stockpile:</p>
<ul>
<li>Supervillain mechanic (the kind that engages in their repair and restoration, not actually in taking over the world);</li>
<li>Saturnian folklore and Demonology enthusiast;</li>
<li>Native speaker of Fishish (a dialect of Atlantish, used by most crustaceans and aquatic mammals in the North Atlantic Ocean; confusing name, I know);</li>
<li>Genff panel (chorono-voltaic modules, think about it as a reversed flux capacitor) technician;</li>
<li>Collector of ultrasonic music (no, that does not include Snake Jazz, they are inferior to Whale Blues or Bat Rock);</li>
<li>Star magnitude calibration specialist;</li>
<li>Dream composition and cinematography expert.</li>
</ul>
<p>The list would have been longer if full-spectrum photography is not actually a thing.</p>
<p>Ah, see how easily I get distracted by these? Back to bio pages on a version of Earth where birds (or Biofueled InspectoR Drones if you prefer) are real and tree octopus aren't, unfortunately.</p>
<p>Why do I always read bio pages under the assumption that they are written with the purpose of exerting authority or &quot;crafting your personal brand&quot;? Wouldn't that make me, who is showing contempt and animosity towards others' qualifications, the one actually displaying syndromes bordering superiority complex? Is it being brought up hearing &quot;modesty is the best policy&quot; all the time finally backfiring? What should the bio page contain anyways? If the purpose is to sprinkle a few hashtags for others to shoehorn my personality into, I would rather not provide such a distraction from contents of the site. Then again, one can argue that if my personality as manifested through the site is easily swayed by the bio page, perhaps the contents aren't really speaking much for themselves after all.</p>
<h2>Multiscale Writing</h2>
<p>I currently classify contents on this site loosely into three categories:</p>
<ul>
<li>Posts: anything with a publish time and a title;</li>
<li>Hoots: anything with a publish time but without a title;</li>
<li>Fixed: anything without a publish time.</li>
</ul>
<p>Up till now, I have always put bio pages under the &quot;fixed&quot; category. However, I have come to realize this have more subtle implications.</p>
<p>This first came struck me as I was casually browsing my RSS reader and landed on a blog post without any indication of publish time. Since I vaguely recognize the page title from memory, I instinctively scanned through the page, searching for a timestamp of any kind. After some detective work, I was able to date the post by checking the HTML source. Realizing that this page was published long ago and only showed up in my RSS reader again due to updated feeds, I promptly left the page. Could there have been subtle wording changes? Maybe, but I didn't remember my first read well enough to recognize them. Could there have been substantial additions? Equally likely, but unless there's a FOMO-inducing &quot;updated XXXX-XX-XX&quot; in huge red fonts, I doubt I would have scrolled down. On a related note, I also see blogs displaying not only publish time, but also a glaring banner warning the readers that the contents may be out of date and the author's opinions may have changed since. Funny how the latter is apparently no longer obvious short of an explicit no-responsibility clause now, but it does illustrate the point: I treat pages without any indication of publish time as ones set in stone, completed works, and ultimate truths of the universe (from the author's view).</p>
<p>There's a mismatch between what I hoped to express through bio pages and the typical fixed page format itself. Well, what are the alternatives? I don't want an <a href="https://sawv.org/en.html">E/N site</a>, as I value the process of organizing my fragments of thoughts as much as, if not more than, the process of collecting them. I've played around with the idea of a <a href="https://alexschroeder.ch/">personal wiki</a>, but I would like to have separate pages for &quot;major versions&quot;, instead of cramming all edits, regardless of importance, into editing history. While for technical contents, latest edition with all the errata incorporated is naturally the most desirable, I don't view my former self necessarily as obsolete or wrong, yet I also don't want to mix past and present on the same page &quot;<a href="https://www.gwern.net/About#long-content">long content</a>&quot; style.</p>
<p>I want bio pages to be condensed me-flavored words, which would be a moving target that a fixed page will forever be playing catching up with as my thoughts evolve over time. Between fixed pages and posts, there is a missing time scale: I need something that manifests change faster than a fixed page, but more long-lasting than regular dated post.</p>
<h2>XPA (eXtensible Personality Archive)</h2>
<p>Cool name, right? It's a happy accident that XPA is also the name of a protein (and the corresponding gene) <a href="https://en.wikipedia.org/wiki/XPA#Function">responsible for repairing DNA damage</a>.</p>
<p>Now, now, before discounting this as unnecessary formality, hear me out. Instead of a single fixed bio page, I think the most fitting substitute is a collection of gradually updated documents, not dissimilar to chapters of a book. While some books, like manga or web novels, are normally published chapter after chapter non-stop Markov-process-style, I'm thinking more of a non-linear progression where rewrites and revisions can happen more frequently.</p>
<p>Some blogs I visit feature sections named &quot;articles&quot; or &quot;opinions&quot; that are distinct from &quot;posts&quot; and serve similar purposes. The format I have in mind though is closer to <a href="https://www.ietf.org/standards/rfcs/">RFCs</a>, <a href="https://www.python.org/dev/peps/">PEPs</a>, etc. XPAs would be numbered, each XPA would be a dump of my current thoughts and personality pertaining to a specific topic, and they can be superseded by a later one with similar coverage. Meanwhile, posts are reserved for concrete things I did or experienced. In other words, XPAs contains literal states of my mind and posts/hoots serve to document some of the incremental changes between those states.</p>
<p>Following its definition strictly, XPA is actually a much more flexible format than I originally thought: reviews could also fall under its umbrella, for instance. Great Scott, just think about all the possibilities! Now the only remaining bike-shedding to be done before I can get started is to determine how XPAs should be presented on the site, whether I count from 0, which numerical system to use, how should we format the identifiers...</p>
<p>Hmm, naming really is hard isn't it.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2021-04-24-bio-pages-multiscale-writing-and-xpa/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2021-01-01-2020-in-review/</id>
    <title type="html"><![CDATA[2020 in Review]]></title><updated>2021-01-01T10:07:00-06:00</updated>
    <content type="html"><![CDATA[<p>Rooftops are covered in patches of white this morning. All the billboards have lost their typical splendor to the gloomy sky. Even the street lamps' orange glow failed to add any warmth to the car-free roads. Spots of light from a handful of building windows, however, do appear extra dazzling.</p>
<p>What a year. It feels like space-time has a higher viscosity than usual—dense enough to reduce sunlight to just an ivory ambiance—given how eventful the past 300-or-so days have been.</p>
<p>I'm actually glad that the first day of 2021 still feels like any day in 2020. Not very much should physically change simply because of a number flip, not to mention a rather arbitrary one, but perhaps it's exactly for the lack of change that we need to forge something new, something that gives an adrenaline kick, no matter how small.</p>
<p>Ugh, fine. I see no harm in giving in to this cheap psychological trick every once in a while.</p>
<p>Happy New Year, we made it.</p>
<h2>2020: Apocalypse</h2>
<p>I'm not cutting myself any more slacks this time around.</p>
<ul>
<li>☑ <del>Run 550 miles.</del> Run 205 miles and cycle 865 miles (2.5x). <code>[205/205]</code><code>[872/865]</code></li>
<li>☑ Write 14 blog posts. <code>[16/14]</code></li>
<li>☑ No donuts.</li>
<li>☐ Dive into Go and C++20. <code>[1/2]</code></li>
<li>☐ Set up proper backup workflow.</li>
<li>☐ Read non-technical books.</li>
</ul>
<p>Because of COVID-19, I have stopped running outdoors since early March. After a few months of hiatus, I got a bike and a trainer in June and started cycling indoors instead. The 2.5x scaling factor is based on the speed differences between cycling and running. Working out in a more controlled environment is very enjoyable. Aside from easy access to fueling and shielding from the weather, being able to watch anime/listen to seiyuu radio while riding is a game changer. Behold, technology!</p>
<p>Blogging about the blog itself still takes up a sizable portion of my posts (and is a frustratingly self-defeating practice), but I did at least accumulated quite the amount of hoots: these fleeting thoughts aren't organized enough to be its own post, but still interesting enough that I want to write it down. I also use hoots to house my replies to other blogs and the rather cumbersome process of which makes me realize how little I really have to say most of the time. Not to color my still largely manual approach superior, but I do think there is some merit in eliminating low-effort-high-noise contents, both for myself and others.</p>
<p>Ah, donuts, the honey glazed shackles of guilt, the deep-fried cuffs of indulgence. While I would like to attribute this to my will of steel, it is COVID-19 that got the better of such temptations. My laziness and excitement for bunker life eliminated any chances of late night Dunkin' visits. Guess it's time to turn up the dial.</p>
<p>Writing Go was quite the mindless fun exercise. Finding an effective way to learn the C++20 features proved to be harder. <code>&lt;format&gt;</code> is the straightforward one and pretty much works as you'd expect (no compiler supports the standard version yet, so checkout <a href="https://fmt.dev">the original</a>). <code>&lt;ranges&gt;</code> is similar to Rust's iterator methods and allows chaining, too. Maybe I should update my <a href="/en/posts/2019-04-27-enumerate-with-c-plus-plus/">enumerate() with C++ post</a>. <code>&lt;concepts&gt;</code> seems like the logical solution to the problems SFINAE tried to solve, but I don't have a good context to test out its prowess yet. On a related note, Zig's compile-time function approach to generics is also intriguing.</p>
<p>3 copies, check. 2 different media, check. 1 offsite backup, not yet. I'm also counting Syncthing copies here, and whether they can be relied upon as full fledged backups is debatable. Still some way to go here.</p>
<p>Technically, I did <em>read</em> non-technical books; I didn't <em>finish</em> any (not counting manga at least). The truth is, aside from those I read purely for entertainment, I am not so sure about what to read. Most non-fiction books look like success stories marinated in flattery and survivor-ship bias. Fictions, on the other hand, just don't attract me that much: knowing another story to tell isn't as exciting as learning a new algorithm for me. Gee that sounded harsh. Do I really think my blog posts fare any better? Anyways, before admitting defeat, I will give this a more serious attempt this year.</p>
<h2>2021: Days of Future Past</h2>
<p>The ongoing pandemic sparkled nostalgia like never before. People look back at the &quot;normal days&quot; with fondness that I find repulsive. Not that I'm completely immune to the atmosphere though, just that it rubs me in the opposite way: I find myself grew more assertive than before. After all, doesn't everyone secretly think they are above average and thus know better, especially after reading the news? At the same time, the voice of reason tells me to suppress this urge before it turns into arrogance, or even worse, ignorance. Perhaps I should learn to let these out in the form of blog posts, like <a href="https://www.cs.utexas.edu/users/EWD/">EWDs</a>, except non-technical.</p>
<p>On a positive note, my transition to wake-up-at-5-sleep-before-10 schedule is a resounding success. The lockdown WFH actually helped in that I have more leeway to adjust my sleep schedule. Now I have plenty of time for exercise every morning or even the option of another two—or three if I'm really pushing it—hours of sleep. Given how I was able to clock in the last 100 miles of rides within the winter holidays, I'll bump the target mileage up a bit this year.</p>
<p>The schedule change also made me realize how unproductive the few hours before bed really is for me: after a day of work and much needed dinner, I don't feel motivated enough to exercise or focus on anything for an extended period of time. Since I started <a href="https://beancount.github.io/">beancount</a>-ing in 2020, I'm now looking to apply a similar methodology to my time. I've been testing out <a href="https://www.toggl.com/track/">Toggl Track</a> to log how I spend the larger chunks of my day and how many minutes in between slipped away with me blanking out watching YouTube. In particular, I figured having a crude &quot;Strava for reading&quot; system would also make my reading goals easier to achieve. As for which books to read, I'm thinking classic fictions.</p>
<p>After donuts, my challenge this year is to abstain from cookies, which can frequently be found in my work place lunch bags. It's strange how exponentially more attractive cookies are to their ingredients, i.e. sticks of butter and bags of sugar, the latter of which would have been sickening to consume directly.</p>
<p>I wonder if this is an age thing: at some point, human's auditory perception would just click with the sound of electric guitars, making it impossible to resist. I'm looking to sink more time into learning the instrument and be good enough to play a song or two by end of 2021.</p>
<p>The generation after Z is named <a href="https://en.wikipedia.org/wiki/Generation%5FAlpha">Alpha</a>, which makes no sense at all. To hell with inconsistent naming. To hell with COVID-19 (for other reasons, of course).</p>
<blockquote>
<p>Un de ces matins disparaissent<br/>
Le soleil brillera toujours.</p>
</blockquote>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2021-01-01-2020-in-review/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2020-12-25-get-going/</id>
    <title type="html"><![CDATA[Get GOing]]></title><updated>2020-12-25T18:50:00-06:00</updated>
    <content type="html"><![CDATA[<p>Yes, I <a href="https://git.shimmy1996.com/advent-of-code/">finished</a> the <a href="https://adventofcode.com/">Advent of Code</a> this year! Aside from the problems being easier (for me) than 2019, I'm also using Go for this year's challenge and I find it to be particularly suited for this type of endeavor.</p>
<p>This year's puzzles mostly involve string parsing and finding efficient data structures. Majority of the logic flow are pretty straight forward and there's little need for sophisticated algorithms.</p>
<p>For string parsing, regex, which Go has built-in support for, is definitely the way to go. The abundance of parsing related problems means using only basic string manipulation could be rather painful, and I've definitely seen my share of horrible blobs of find/substr/trim.</p>
<p>Most of the time, slices and maps are all I needed. Go has multiple return values but no tuples, whose usage, I find, is largely replaced by either arrays or structs. Versatility of these data structures are actually increased due to the language's encouragement to use constants instead of enums: storing all information as ints opens up the door to some shortcuts and less conversion between types. Surely they don't give you the peace of mind type checked enums provide, but (ab)using them in short programs does provide the odd walking-on-a-knife-edge (or not-wearing-pants-during-Zoom-call) kind of satisfaction.</p>
<p>Imperative programs are easy to write in Go, mostly because of the language's plain and simple control flows and lack of mixed paradigms. There's no need to worry about whether we should use an STL algorithm or chained iterator methods: just write the loop. Reasonable mutability behaviors also helps: whether it's changing a map while looping through it or passing a struct containing a slice to another function, I can get the language to do what I mean without checking the specification line by line.</p>
<p>There's <a href="https://en.wikipedia.org/wiki/Zero%5Fone%5Finfinity%5Frule">the ZOI rule</a> about how the only reasonable numbers are zero, one, and infinity. Quite a few other languages I know, such as Python, C++, and Rust, all seem to hinge on the extreme ends of the spectrum in pursuit of consistency: everything follows the same rules and users can dictate what the syntax means as much as the base language. Go definitely has more exceptions (without supporting it) and &quot;one&quot; moments: built-in containers are magically generic, their methods can have variable number of return values, and everything else is denied the privilege of being eligible to be iterated over.</p>
<p>While just a quick comparison without touching other traits of Go (say interfaces or goroutines, but you don't really need them for Advent of Code), I do find Go's choices peculiar and interesting: <a href="https://lukeplant.me.uk/blog/posts/everything-is-an-x-pattern/">everything is, well, just its own thing</a>.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2020-12-25-get-going/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2020-07-17-tired-a-personal-rating-system/</id>
    <title type="html"><![CDATA[TIReD: A Personal Rating System]]></title><updated>2020-07-17T21:30:00-05:00</updated>
    <content type="html"><![CDATA[<p>As the pandemic gives me a chance to look through my backlog of movies, shows, and books (read: anime and manga), I started to consider establishing a personal rating system to ease up writing (hypothetical) reviews.</p>
<h2>Guiding Principles</h2>
<p>Typical rating scales feature 10 or more levels, which is in my opinion way too wide a range to choose from, not to mention those featuring a 100-point-scales. Even the most common 5-star system gets cumbersome fast as soon as we take half-stars into consideration. What exactly differentiates a 6 from a 7 or a 4.6 from a 5.1? Higher granularity could be useful in aggregated ratings, but not so much from an individual reviewer's perspective. I much prefer the approach <a href="http://s1vote.com/">s1vote</a> took: give the users fewer but more distinctive levels to pick from.</p>
<p>My anecdotal evidences show that most online ratings converge around the 70% mark, a rating just as safe and useless as <a href="https://statmodeling.stat.columbia.edu/2020/06/29/this-one-quick-trick-will-allow-you-to-become-a-star-forecaster/">predicting a 40% success rate for anything</a>. In other words, the lower half of most rating scales are underutilized: how often would you rate something one-and-a-half-star instead of just one? Besides, more often than not, I read ratings and reviews to find out about good shows, not the bad ones. It should be sufficient to only focus on &quot;the better half&quot;: why would I sit through the entirety of a bad show and take the effort to give it a rating anyways? There is no -1 star in Michelin Guide, is there?</p>
<p>Summarizing the quality of anything with a single metric seems unfair. I want the rating system to be more expressive, capable of conveying the different aspects of a show that I find enjoyable. At the very minimum, an opinionated pick should be distinct from something with a more general appeal.</p>
<h2>Rating Methodology</h2>
<p>Enter the TIReD scale! The following uses anime/tv shows as the example here, but much of this methodology also applies to other art forms. A show is scored in the following categories, with sum of points forming the final rating:</p>
<table>
<thead>
<tr>
<th>Category</th>
<th>Range</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>T</strong>angible</td>
<td>0-2</td>
</tr>
<tr>
<td><strong>I</strong>ntangible</td>
<td>0-2</td>
</tr>
<tr>
<td><strong>Re</strong>visit-ability</td>
<td>0-1</td>
</tr>
<tr>
<td><strong>D</strong>iscretionary</td>
<td>0-1</td>
</tr>
</tbody>
</table>
<p>Tangible aspects of a show include visual style, animation, soundtrack, CG quality, special effect, etc. To put it simply, how physically well-made a show is. Starting from a score of 0, a show would be scored a</p>
<ul>
<li>+1 if the show is overall attractive to watch and either has consistent high quality with very few shortcoming (perfection) or utilizes unique ideas/techniques to great effects (ingenious);</li>
<li>+2 if its physical quality/way of expression alone would be sufficient reason to watch the show, even if it gets a 0 in all other categories.</li>
</ul>
<p>Intangible aspects include story, character building, plot pacing, cultural reference, etc. This quality should be relatively medium independent, i.e. I would enjoy a faithful recreation of the story in other art forms at least just as much. Criteria for scoring is similar except for remakes/adaptations with an clear intent to follow the original and when I have seen/read the source material: scoring would be based on the source material's intangible score adjusted downwards by 1 point, with at most extra 1 point adjustment based on quality/difficulty/effect of the remake/adaptation with in the range of 0-2. For instance, a mediocre retelling of a +2 story should only be awarded at most a +1. Remakes and adaptations probably have an easier starting point than original contents, so I wanted to adjust for &quot;how good the show could have been&quot;, provide an answer to &quot;should I still see this if I've seen the original&quot;, and pick out the &quot;watch this instead of the original&quot; or &quot;transcended and elevated the original story&quot; shows.</p>
<p>Revisit-ability, as the name indicates, represents whether I would want to revisit/rewatch the show later. This correlates more with my own taste or nostalgia: is this something that I would gladly jump into in an leisure afternoon. Longer shows tend to suffer a bit by this metric, so I would take into account of especially memorable segments/episodes. However, in event of remakes and adaptations, this point should generally only be rewarded to the best version of the work in my point of view.</p>
<p>Discretionary point should be awarded sparingly and only when a show doesn't already achieve full scores in all other categories, making the possible maximum score 5 instead of 6. This is used as an adjustment for shows that I feel the current rating system doesn't do it justice. Common situations where this applies include but are not limited to:</p>
<ul>
<li>categorical superiority: best of its kind;</li>
<li>a tight coupling between tangible and intangible aspects of the work: it simply won't be the same without one another;</li>
<li>quality in spite of objective limitations, especially for older shows or those with a tight budget.</li>
</ul>
<h2>Format</h2>
<p>A TIReD rating is recorded as <code>X=T/I/Re[+D]</code>. For instance:</p>
<ul>
<li>a show scoring 1 in tangible, 2 in intangible, 0 in revisit-ability, and 0 in discretionary would be recorded as <code>3=1/2/0</code>;</li>
<li>a show scoring 1 in tangible, 0 in intangible, 0 in revisit-ability, and 1 in discretionary would be recorded as <code>2=1/0/0+1</code>.</li>
</ul>
<p>Shows that I abandoned halfway, meaning I won't be able to give a rating, will be marked as <code>DNF</code> (did not finish).</p>
<h2>Self Q&amp;A</h2>
<p>Some fragments of thoughts that I came across when designing TIReD.</p>
<p>Q: How should tangible points for books be awarded?</p>
<p>A: I'd say it's how good the writing is at face value, i.e. is it &quot;literature&quot; worthy. While I not really confident in my ability of identifying great works, but a +2 should at least be something better than <em>Harry Potter</em>.</p>
<p>Q: How should world settings built up in previous/related works affect the rating?</p>
<p>A: World building actually fits into both revisit-ability (if the system/world is interesting and makes me want to read more about it) and intangible quality (whether the character actions are justified).</p>
<p>Q: How was the rule for discretionary point determined?</p>
<p>A: The best shows should always get full score regardless of the exact scale, so awarding them discretionary points is meaningless. However, there are seemingly not-so-impressive works that really show the passion/devotion/love/good faith of the production team/author and shows whose existence alone is a boon for its fans. I want to express my enjoyment in a way that still allows me to assess the tangible and intangible aspects of a show on an absolute scale, as any further complication can be taken account of as discretionary point.</p>
<p>Q: What happens to ratings for a remake before and after you watch the original?</p>
<p>A: I'll adjust score for the remake now that I have experienced the original.</p>
<p>Q: A lot of details could be lost in translation. How to deal with translated works?</p>
<p>A: For now I will treat these the same way as remakes: adjust the rating if someday I came across the original.</p>
<p>Q: How did you come up with the name &quot;TIReD&quot; (and name for the categories)?</p>
<p>A: The first category to have a concrete name is revisit-ability. From there on it's mostly just playing around with words and initials. I almost settled on &quot;TIRD&quot; thanks to <a href="https://www.urbandictionary.com/define.php?term=tird">Urban Dictionary</a>. Well, not everything is sh*t. 😜</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2020-07-17-tired-a-personal-rating-system/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2020-04-10-blog-9-from-outer-space/</id>
    <title type="html"><![CDATA[Blog 9 from Outer Space]]></title><updated>2020-04-10T01:27:00-05:00</updated>
    <content type="html"><![CDATA[<p>Recently, I've been thinking about ways to unify my micro blog entries with my current site, and I've been reconsidering the ideas from <a href="https://indieweb.org/">IndieWeb</a>: unlike <a href="https://activitypub.rocks/">ActivityPub</a> (the protocol Mastodon, Pleroma and the likes use for federation), which seems to want everything be done dynamically via server APIs and JSON responses, the various standards recommended by the IndieWeb community allows machine readable feed to be generated straight from a static HTML file correctly marked-up. A core idea that IndieWeb seem to implicitly rely on is the lifetime of the URIs, and to a greater extent, site owner's control over the domain name. Withe the recent <a href="https://www.eff.org/deeplinks/2020/03/members-congress-once-again-urge-icann-save-dot-org">drama</a> regarding the .ORG domain, I came to realize that a future in which domain names are too expensive to maintain (or are subject to seizures by various entities) may not actually be too distant, and this could seriously undermine the entire premise IndieWeb is built upon, not to mention the a lot more common link rots. Fortunately, I think the <a href="https://ipfs.io/">IPFS</a> (InterPlanetary File System) has the potential to solve both problems.</p>
<h2>A Crash Course on IPFS</h2>
<p>Now, now, I know when compared similar projects like the <a href="https://dat.foundation/">Dat protocol</a>, <a href="https://github.com/yarrick/pingfs">pingfs</a>, or even <a href="https://scuttlebutt.nz/">Scruttlebutt</a>, IPFS has a really buzz-wordy vibe (trust me, I was as skeptical as you are at the beginning) to it, and the various cryptocurrency start-ups that bundle IPFS and all kinds of acronyms in their marketing materials surely doesn't do it any favors, but it does seem like the most established and ready-to-use. Here's my best attempt at explaining IPFS, with information mostly obtained from the <a href="https://docs.ipfs.io/">official documentation</a> and <a href="https://www.youtube.com/watch?v=HUVmypx9HGI">this talk</a>. In case you are interested in further implementation details, <a href="https://www.youtube.com/watch?v=Z5zNPwMDYGg">this session from IPFS Camp 2019</a> is a great starting point.</p>
<p>A simplified interpretation of link to an web page is but a fancy way to point to a file on some server. Just like path to a file, the link would be unreachable if the server is down, even if someone sitting in the same room might have the contents cached. In IPFS, files (or data blocks) are addressed by corresponding cryptographic hashes of their contents, and stored in a distributed fashion across all peers. This means no centralized facility is required to access the files, file integrity can be easily verified, P2P sharing can be used to speed up access, and files stored this way are inherently immutable.</p>
<p>Not being able to change files seems like a rather large price to pay, but just like any other problem in computer science, this can be solved by adding a layer of abstraction. IPNS (InterPlanetary Name System) utilizes public-key cryptography to create immutable addresses that can point to different files. An IPNS address is basically the hash of a public key. An IPNS lookup would involve retrieval of the public key, searching for files (each containing an IPFS address) signed by the corresponding private keys, identifying the most recent one, and finally redirecting to the correct file. To utilize IPNS, the user would start by creating a public-private key pair, followed by uploading desired files into IPNS, and sign and upload a pointer file containing IPFS address to the uploaded content. When an update is desired, the user only need to sign and upload another pointer file to the new location.</p>
<p>A lot of ideas used in IPFS has been explored before by projects like BitTorrent (peer-to-peer sharing), <a href="https://en.wikipedia.org/wiki/Fossil%5F(file%5Fsystem)">Fossil</a> and <a href="https://en.wikipedia.org/wiki/Venti">Venti</a> from Plan9 (write-once data blocks and path redirection), git (Merkle tree/directed acyclic graph), etc. However, the killer feature is how easily IPFS integrates with existing infrastructure. Not only are there HTTP gateways that allows for accessing IPFS/IPNS from web browsers instead of IPFS clients, but also compatibility with FUSE (Filesystem in Userspace), which actually allows you to mount the entire IPFS as a read-only partition: sure this also makes hosting static websites possible, but you have to admit that having access to a global-scale (or should I say, interplanetary?) P2P shared drive is way cooler.</p>
<h2>Hosting Static Websites on IPFS</h2>
<p>The <a href="https://docs-beta.ipfs.io/how-to/command-line-quick-start/">official guide</a> already outlines the general usage pattern pretty well. Here's the TLDR:</p>
<ul>
<li>Run <code>ipfs init</code> and <code>ipfs daemon</code> to initialize and start the IPFS client.</li>
<li>Generate the website files and run <code>ipfs add -r &lt;website-root&gt;</code> to send its contents onto the IPFS. The last few lines of the output should tell you the hash for the root directory.</li>
<li>If you want to make use of IPNS, run <code>ipfs name publish &lt;website-root-hash&gt;</code> to direct the IPNS link to the folder you just uploaded. The IPNS public key hash can be obtained via <code>ipfs key list -l</code>.</li>
<li>Repeat the last two steps every time and the website files are updated or rebuilt. The process has little overhead due to the inherent deduplication in addressing, making it particularly suitable for static sites where larger files (like photos) tend to change less often.</li>
</ul>
<p>Once this is done, you can access your website at either <code>&lt;gatway-address&gt;/ipfs/&lt;website-root-hash&gt;</code> or <code>&lt;gatway-address&gt;/ipns/&lt;ipns-address&gt;</code> from any HTTP gateway: you can use the local one (likely at <code>127.0.0.1:8080</code>) started by the IPFS daemon, or any of <a href="https://ipfs.github.io/public-gateway-checker/">the public ones</a> (comes with extra risk of MITM attacks from the gateway owners as file retrieval is done on the gateway servers). In case you have multiple websites, you can generate more IPNS key pairs using <code>ipns key gen</code>, and specify <code>--key</code> when running <code>ipfs name publish</code> to a specific IPNS address.</p>
<p>Before IPFS <a href="https://github.com/ipfs/go-ipfs/issues/4240">supports import/export of the IPNS keys</a> though (so that we can backup keys and publish from multiple devices), <a href="https://docs.ipfs.io/guides/concepts/dnslink/">DNSLink</a> can be used to more conveniently maintain access to a site, albeit at the cost of depending on owning a domain name and trusting the DNS host provider. To allow access to the site from the gateways via <code>/ipns/&lt;domain-name&gt;</code>,
simply add a TXT record to the domain:</p>
<pre><code class="language-text">dnslink=/ipfs/&lt;website-root-hash&gt;
</code></pre>
<p>or</p>
<pre><code class="language-text">dnslink=/ipns/&lt;ipns-address&gt;
</code></pre>
<p>For instance, you can now access this site using at <a href="https://ipfs.io/ipns/shimmy1996.com/"><code>/ipns/shimmy1996.com</code></a> (this is a link using the ipfs.io gateway). While not flawless, to me this is a reasonable compromise for now. I find find IPFS to be generally faster than IPNS, so using IPFS address with DNSLink probably makes more sense. To avoid manually copy-pasting the IPFS address each time, I added to my blog build script the following to automatically upload website to IPFS and update DNS record (using <a href="https://developers.digitalocean.com/documentation/v2/#update-a-domain-record">DigitalOcean's API</a>):</p>
<pre><code class="language-sh">echo &quot;Uploading to IPFS...&quot;
hash=$(/usr/bin/ipfs add -Qr &quot;&lt;website-root&gt;&quot;)

echo &quot;Updating DNSLink record...&quot;
token=&quot;&lt;digitalocean-api-token&gt;&quot;
curl -X PUT \
     -H &quot;Content-Type: application/json&quot; \
     -H &quot;Authorization: Bearer $token&quot; \
     -d &quot;{\&quot;data\&quot;:\&quot;dnslink=/ipfs/$hash\&quot;}&quot; \
     &quot;https://api.digitalocean.com/v2/domains/&lt;domain&gt;/records/&lt;record-id&gt;&quot;
</code></pre>
<p>Record ID for DNS records on DigitalOcean can also be <a href="https://developers.digitalocean.com/documentation/v2/#list-all-domain-records">retrieved via their API</a>. You may need to add <code>?page=2</code> or later to the request to find the record you want.</p>
<p>Do note that like using any offline HTML files, we need to use relative URLs in the generated web pages. In Hugo, this can be achieved by setting</p>
<pre><code class="language-toml">relativeURLs = true
</code></pre>
<p>in <code>config.toml</code>.</p>
<p>Of course, being a P2P network, IPFS won't be able to retrieve the files if there is no copy to work with at all. By default, IPFS client would <a href="https://docs.ipfs.io/guides/concepts/pinning/">pin</a> anything you shared from the local machine: pinned contents won't get deleted, ensuring at least one copy of the shared content is available on IPFS. You can unpin outdated versions of the website, or if you want, find and pin the shared directory on multiple machines for some redundancy.</p>
<h2>The Stars, Like Dust</h2>
<p>Back to the issue with IndieWeb: the increasingly shady domain name system and link rots makes URI stability in HTTP hard to maintain. However, what if we use IPFS/IPNS addresses as URIs? It's a match made in heaven: we get robust distributed access to static web pages, gated by Mathematics instead of FBI warnings, that can theoretically last forever. Removing the need for maintaining a server also lowers the barrier of entry of owning a website. The HTTP protocol has existed for 29 years, and IPFS, only 5. I don't know if IPFS will continue to exist for the next 24 years to come, but if it does, I hope we will be looking at a perhaps more chaotic, but more robust, lively, and colorful, online world.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2020-04-10-blog-9-from-outer-space/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2020-04-04-static-alternatives-to-mastodon-and-gitea/</id>
    <title type="html"><![CDATA[Static Alternatives to Mastodon and Gitea]]></title><updated>2020-04-04T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>Like how I decided to switch off Wordpress, I think I've had enough running Mastodon and Gitea.</p>
<p>Keeping up with configuration changes with Gitea had been annoying, whereas with
Mastodon, breakages are common due the mismatching system library versions
(mostly protobuf) in the dependencies. While the latter is not a fault of
Mastodon itself, having to install two package managers (for Ruby and Node.js,
respectively) just to run a program is rather ridiculous to me.</p>
<p>I started hosting both applications in 2018: Mastadon first as a replacement for
Twitter, and Gitea later in reaction to Microsoft's acquisition of
Github. Looking back, they were probably overkill for my needs: my primary use
case for a git server and a micro blog are both very much single-user focused
and write-only, which means these content should be available in read-only form
for my site's visitors, making static pages the perfect replacement for both web
front ends.</p>
<p>Starting with Mastadon, I'm using the <a href="https://twtxt.readthedocs.io/en/latest/">twtxt</a> format to store and serve my micro
blog. The format has existed for some time now, but enjoyed a recent resurgence
in the tildeverse (a series of websites offering public access Unix-like
systems). While there is now a whole community supported ecosystem of various
syntax extensions and software seeking to add more features to the format, I
have found the barebone timestamp-tab-and-then-text syntax to be sufficient. The
write-and-forget cycle is really addicting, and even more so when using a
command line client (mine is aptly named <a href="https://git.shimmy1996.com/twixter/">twixter</a>).</p>
<p>As for Gitea, while an excellent Github replacement in my opinion, is more
suitable for community collaboration than as a personal project dumping
ground. I opted to manage the git repositories directly (see Chapter <a href="https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server">4.4</a> and <a href="https://git-scm.com/book/en/v2/Git-on-the-Server-Git-Daemon">4.5</a>
of <em>Pro Git</em>), and use <a href="https://git.codemadness.org/stagit/">stagit</a> to generate the corresponding HTML files. These
stagit-generated pages have replaced Gitea as the new <a href="https://git.shimmy1996.com/">Trantor Holocron</a>.</p>
<p>Now that I have found satisfactory solution for the write-only portion of my
online presence, I will continue to explore options for the remaining two
pillars: read-only (content consumption) and interaction (means of
communication). Web feeds and email are my best answers now, but they still
don't cover all the bases in my experience.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2020-04-04-static-alternatives-to-mastodon-and-gitea/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2020-03-31-march-goes-out-like-a-lion-too/</id>
    <title type="html"><![CDATA[March Goes out Like a Lion, Too]]></title><updated>2020-03-31T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>It was not until a few weeks ago (while watching Level1 News) that I learned about the complete version of the saying &quot;March comes in like a lion and goes out like a lamb.&quot; I knew the first half of the saying from manga series <em>March Comes in Like a Lion</em>, but I had no idea the saying was describing the weather in March.</p>
<p>What you have read so far was actually my entire motivation for starting this post, but it has indeed been a rather unusual March. Because of COVID-19, I'm spending time at home &quot;social distancing&quot;, or rather, indulging myself in the company of solitude. In preparation for (a.k.a. using as an excuse) extended periods of working from home, I went on an upgrade spree for electronics: I got a second monitor, a monitor stand, and larger hard drives for my NAS. In fact, I've been gradually expanding my arsenal of devices since last Fall, so look out for a potential setup post.</p>
<p>Amazon's Prime Now service has been keeping me fed for two out of the past three years during which I cooked for myself. It's a bit alarming that Amazon of all things has become literally something I can't live without. But until I have my underground bunker and algae farm, I'll have to make do with this symbiotic (or should I say parasitic) relationship. I'm not sure if I really enjoy cooking though, as least most of my efforts devoted to it has been on how to reduce the amount of time I spend in the kitchen. Fortunately I hardly ever get tired of eating the same dishes, so I just kept making the same ones, while gradually optimizing the preparation: I have yogurt and trail mix for breakfast, beef curry with rice for lunch, and pan-fried salmon with rice and stir-fried cabbage for dinner.</p>
<p>The pandemic also puts my running plans on hold: the trail I normally run on has been closed down. I did get plenty of mileages in before social distancing started (4 weeks ahead of schedule in terms of total mileage now), so I should still be on track to hit my 2020 target. Perhaps due to the snow and ice along the way, my running shoes (Mizuno Wave Rider 23) are wearing out faster than before: at 250-mile-mark, I'm already feeling arch discomfort in longer distance runs, while previous iterations of those shoes lasted until around 300 miles. Aside from shoe issues, shin pain also started to creep up as I've been doing longer runs, so this just might be the opportunity I needed to take some rest. I have converted myself to a morning runner as I plan to ultimately sneak a run or two on weekdays. So far I'm enjoying my morning routines, despite a few of snow-stormy days that were extra tough (but fun). Plus, I get to see sunrise instead of its less cheerful sibling.</p>
<p>Reading the news during the outbreak frequently struck me with an unreal feeling: because of both the things that are actually happening and the way news articles covers them in a deliberately divisive facade. To be fair, asking an organization that preys on human attention to report in a plain and down-to-earth way is an oxymoron in itself. It's probably hypocritical for me to pick on the news agencies though, as I am also guilty of deriving excitement from the current situation: the mere thought that what is ordinarily just an apartment is now my personal fortress against an uncured pathogen is enough to keep me up at night.</p>
<p>Should this indeed be the downfall of humanity, at least my blog and Emacs configuration will (assuming Microsoft means it) live on thanks to the <a href="https://archiveprogram.github.com/">Github Archive Program</a>. Before that, be safe, stay at your personal living pods, and prepare for the neon-colored Space-Age algae diet we've all been waiting for.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2020-03-31-march-goes-out-like-a-lion-too/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2020-01-09-becoming-pangu-with-gnu-sed/</id>
    <title type="html"><![CDATA[Becoming Pangu with GNU sed]]></title><updated>2020-01-09T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>In case you aren't familiar with Chinese mythology or blogosphere, there's an old meme aptly named &quot;Space of Pangu&quot;: a typesetting rule of thumb in favor of additional spacing between Chinese characters (but not punctuation marks) and Latin characters or numbers. My variant of the rule also includes additional spacing around any HTML elements like links and emphasis.</p>
<p>Up till now, I've been manually adding spaces in my source files (in Markdown or org), which is admittedly the worst way to do it. Aside from the additional chore, such a typesetting rule should, in my opinion, be implemented in the output/rendering format, not the source. Besides, manually fixing all the old posts I just brought back is not exactly a rewarding task. Unwilling to load additional <a href="https://github.com/vinta/pangu.js">JavaScript</a>, I turned to the all-mighty GNU sed. To add Space of Pangu to the final HTML and XML files that Hugo produces (normally in the <code>./public</code> directory), I used the following shell script:</p>
<pre><code class="language-sh">#! /usr/bin/env sh
# For punctuation marks to be recongnized correctly.
export LC_CTYPE=en_US.UTF-8
find . -path &quot;./public/*&quot; \( -name &quot;*.html&quot; -or -name &quot;*.xml&quot; \) -print -exec sed \
     -e 's/\([a-zA-Z0-9]\|&lt;\/[a-z]*&gt;\)\([^[:punct:][:space:]a-zA-Z0-9\s]\)/\1 \2/g' \
     -e 's/\([^[:punct:][:space:][:alnum:]]\)\([a-zA-Z0-9]\|&lt;[a-z]\)/\1 \2/g' \
     -i {} &quot;;&quot;
</code></pre>
<p>In case you are adamant about adhering to the recommendation by this <a href="https://www.w3.org/TR/clreq/#mixed%5Ftext%5Fcomposition%5Fin%5Fhorizontal%5Fwriting%5Fmode">W3C Working Draft</a> and wouldn't mind bloating up the resulting web page, using CSS to create the spacing should do the trick:</p>
<pre><code class="language-sh">find . -path &quot;./public/*&quot; \( -name &quot;*.html&quot; -or -name &quot;*.xml&quot; \) -print -exec sed \
     -e 's/\([a-zA-Z0-9]\|&lt;\/[a-z]*&gt;\)\([^[:punct:][:space:]a-zA-Z0-9\s]\)/\1&lt;span style=&quot;margin:0.25ch;&quot;&gt;&lt;\/span&gt;\2/g' \
     -e 's/\([^[:punct:][:space:]a-zA-Z0-9]\)\([a-zA-Z0-9]\|&lt;[a-z]\)/\1&lt;span style=&quot;margin:0.25ch;&quot;&gt;&lt;\/span&gt;\2/g' \
     -i {} &quot;;&quot;
</code></pre>
<p>If you are another one of those Space of Pangu disciples, just note that there's no need to worry about adding spaces when leaving comments here: thanks to <a href="https://git.shimmy1996.com/shimmy1996/hugo-hyperskip">Hyperskip</a> comments being inserted at Hugo's building stage, they are affected by those scripts as well. Just sit back, relax, and enjoy staring at the blank spaces.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2020-01-09-becoming-pangu-with-gnu-sed/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2020-01-06-staring-at-yesterday-in-one-eye/</id>
    <title type="html"><![CDATA[Staring at Yesterday in One Eye]]></title><updated>2020-01-06T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>The dead speak! The galaxy has heard a mysterious broadcast, a record of THE <strong>GREAT DIMENSIONAL FRACTURE</strong> in the familiar yet distant tone of <strong>MY PREVIOUS VESSEL</strong>.</p>
<h2>A Link to the Past</h2>
<p>Alright, that's enough puns and <em>The Rise of Skywalker</em> jokes from me. As mentioned before, my blog was originally using WordPress and switched to Hugo in 2017-09-01. To be more specific, I actually had two WordPress blogs: one named Pandora (because of <em>Borderlands 2</em>, but this is such an cliche name that I'm sure there's a million other imaginary planets using this name) hosted with WordPress.com, and another being Library of Trantor (because of Isaac Asimov's <em>Foundation</em> series) hosted on Bluehost, with the former written in English and latter in Chinese. Since I kept archives of both before taking them down, I was able to revive all those old posts from the grave using <a href="https://github.com/SchumacherFM/wordpress-to-hugo-exporter">this tool</a> and some elbow grease. I refrained myself from leaving out any of the old posts, as the main motivation of this effort is really just to be able to easily see and be reminded of my younger self. It's a strange yet familiar experience reading those old writings: I can see parts of me that has changed and parts that are still distinctively shimmy1996.</p>
<p>Handling images is tricky and my old posts made quite liberal uses of them unfortunately: I opted for the simplest way out and just kept the originals without any kind of fancy compression or styling. I still need to figure out a more efficient way to both store and serve those images. Even with Git LFS available, I was reluctant to add over 300 MB of images to my blog repository (so they are currently in untracked-land), and now my blog could definitely benefit from a CDN setup. Perhaps I could also do what Jupyter notebooks do—encode all images in Base64—to get a single HTML file.</p>
<p>For the regular visitors of my blog out there (if there are any), you might notice that the comment section looks different: that's right, the search for the ideal static site commenting system is finally over for me (until it starts again)! Through out the years, I've used WordPress, Duoshuo (now defunct), Disqus, and Isso as my comment systems. Now, my <a href="https://git.shimmy1996.com/hugo-hyperskip">Hyperskip</a> has superseded them all: taking inspiration from <a href="https://staticman.net/">Staticman</a>, I set up Hyperskip to store all the comments in a TOML file, and opted to use email as the submission method, simplifying the setup. Gone are the days of databases, queries, and external scripts, and I get to migrate and version control all the comments (including the ones from the WordPress era) in the same Git repository as my blog too.</p>
<h2>The Other Old Friend</h2>
<p>One week into the New Year and I have already switched color scheme of the website five times, with another dozen sitting in my folder (totally not because of how unsightly these RGB color codes are). Much like how I'm a bit burned-out from <a href="/en/posts/2019-12-01-fun-with-fonts-on-the-web/">getting fonts right for everything</a>, I have decided to remove all custom color choices from the website: no more syntax highlighting, fancy buttons, nor dark modes.</p>
<p>As long as there are little knobs that I can toy around with, I always find myself distracted and spending way too much time worrying about the most insignificant choice of words, colors, or spacing (as you can tell by how much of I blog about the blog). The only cure I found is to simply remove the opportunities of making those choices altogether, and stick with the default. This is why I replaced Isso (I spent too much time trying to make it not look so foreign) and tags and categories are now gone, too.</p>
<p>Completely contrast to how the saying normally goes, I hardly ever find myself missing the things I cut away. More often than not, I sympathize with the elephant that finally broke free from the rope, rather than the remorse after losing something cherished. I do occasionally ask myself whether maintaining all those babbling by my past self is just another such rope holding me back that I just haven't realized yet. Well, my response is: a cowboy could always use a lasso on the road.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2020-01-06-staring-at-yesterday-in-one-eye/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2020-01-01-2019-in-review/</id>
    <title type="html"><![CDATA[2019 in Review]]></title><updated>2020-01-01T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>Each New Year feels incrementally less special (see the relative length argument I wrote in review of 2018), although as an end to the laziness-inducing and overly noisy holiday season, having festival associated with new goals and resolutions is not too bad an idea.</p>
<p>Looking at the number 2020 does give me a bit more excitement as it always felt like such a distant time in the future: I don't even remember any sci-fi works referencing anything in the 2020s, as most of them either stopped at the 2010s or go way beyond to the 3000s. This new decade is stuck in what I call, an expectation limbo. Oh, fun fact from <a href="https://en.m.wikipedia.org/wiki/2020">Wikipedia</a>, 2020 will also see the beginning of the year of Metal Rat in Chinese calendar - such a punk name for a something rather traditional.</p>
<h2>2019 Rewind</h2>
<p>I'm glad to announce that everything went according to plan in 2019!</p>
<ul>
<li>☑ Run 400 miles. <code>[555/400]</code></li>
<li>☑ Write 10 blog posts. <code>[14/10]</code></li>
<li>☑ Stop using Gmail/Inbox app. <code>[2/2]</code></li>
<li>☑ Add <code>rel=me</code> links to blog.</li>
<li>☑ Dive into Rust and Julia. <code>[2/2]</code></li>
<li>☑ Record books, music, and shows I enjoyed.</li>
<li>☑ Clean my desktop computer.</li>
</ul>
<p>With some uncertainties in my life sorted out, I've been following my daily routines a lot better in 2019. I still procrastinate on blog posts from time to time, but at least I'm also publishing ever so more often. Learning Rust and Julia was fun, and I did get some uses out of them in real projects. I also attempted Advent of Code in both languages and got to the day 17 before each day's questions started taking too much time. I thought about finishing all the remaining ones after Christmas, but decided against it - I don't see myself learning more about the languages through these questions and the time could be better spent elsewhere.</p>
<p>I gave the blog a face-lift, writing a new Hugo theme in the process, with <a href="https://getkiss.org/blog/20191004a">this article</a> serving as an inspiration. I find the process of eliminating all the nice-to-haves and bells-and-whistles oddly satisfying: I enjoy having my blog as a lean, mean, killing machine. The website feed has been updated to use ATOM, with each post displayed in its entirety instead of the default broken summary. I started using web feeds for reading blogs after failing miserably at my last attempt to organize my web browser bookmarks and I've enjoyed it so far.</p>
<p>I went to the movies three times this year, for <em>Dragon Ball Super: Broly</em>, <em>Promare</em>, and <em>Star Wars: The Rise of Skywalker</em>, and I mostly enjoyed my time in all three occasions: trying to quantify this enjoyment using a rating is probably not doing them justice, as I enjoyed the three for vastly different reasons. Since I visit the theaters so scarcely, the time I spend on airplanes actually account for a large portion of my movie consumption, and <em>Spider-Man: Into to the Spider-Verse</em> was the stand out among those I watched while flying. On Christmas Eve, instead of <em>Toradora!</em>, an tradition of mine during college, I rewatched <em>Scott Pilgrim vs. the World</em>, which I also first saw on a flight years ago, and it was as geird (Good but in a weird way and weird but in a good way, like, you know, goodd? This is not a real word yet, but who cares? It's year of Metal Rat!) as I remembered.</p>
<p>As someone that have always lived at places that never snow until 2018, snow to me is such a distant concept that I'd consider any movie with snow scenes a Christmas movie. Even after moving to a snowing city mid 2018, I still haven't seen the stereotypical fluffy Christmas snow that almost seem warm to the touch: all I got were piles of dirty water-ice compound on roadsides (oh and they find their way into your shoes too) that reminds me more of fish market than Christmas. Meh, I bet all those snow in the movies are just props, just like the Moon landing.</p>
<p>Back in 2018, I set up a Mastodon instance, and I have since deleted my twitter account, but I never use Mastodon that much. At first I thought it's just that I'm not the microblogging type, but now I'm starting think it's all the cognitive overhead of logging in, editing, tagging, and translating that made posting a status update rather daunting for me. I have been microblogging in <a href="https://twtxt.readthedocs.io/en/latest/">twtxt</a> format for the last few months of 2019 and I did rack up a considerable status count (all 110 of them). Being one command away from dumping whatever silly one-liner I have in mind is quite addicting, and revisiting the twtxt file also gives me new post ideas at times. Separating a Twitter-like social media service into read-only (with feed reader), write-only (what I use twtxt for), and interactive (still figuring that one out) parts simply works better for me. My twtxt file will likely replace Mastodon in the footer this year, as keeping a behemoth (just one more pun, please?) of a web app happy and running has not been exactly pleasant for me.</p>
<p>Speaking of deleting accounts, I've setup forwarding from all my Gmail accounts to my self-hosted email and all my devices are Gmail and Inbox (RIP) free now. I'm still not quite ready to completely ditch the Google accounts yet, but I'm getting closer: I've been trying out registrars other than Google Domains, and using Youtube's built-in web feeds instead of relying on subscriptions. I did finally remove my Facebook account though, and the account purge will likely continue.</p>
<h2>Road to 2020</h2>
<p>Since it worked out really well for 2019, I'll continue to match previous year's numbers on blog posts and running. Donuts have been my guilty pleasure late night in 2019 (thanks to Dunkin'), and it's one of the few kinds of food I still willingly consume despite the detrimental effect to my health. Thus, no donuts in 2020, not under my watch!</p>
<p>I do want to set up a proper data backup workflow, following 3-2-1 strategy and all that. As for new languages to learn, Go has been creeping on my radar for a while and with the release of Go modules, it seems like the right time to jump in. There's also C++20 on the horizon.</p>
<p>2020 will also see the release of several Linux phones (Librem 5 and PinePhone), and I'm more than willing to try some of them out and explore ways of escaping the Apple ecosystem. PineTime, on the other hand, might be the perfect replacement for my aging Pebble Time Round.</p>
<p>Out side of technical ones, I haven't read any books in quite a while, at least not those that can be classified as proper literature, and I seek to change that in 2020.</p>
<p>Here's to the end of Skywalker saga, and whatever comes after generation Z!</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2020-01-01-2019-in-review/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2019-12-20-review-of-star-wars-the-rise-of-skywalker/</id>
    <title type="html"><![CDATA[Review of Star Wars: The Rise of Skywalker]]></title><updated>2019-12-20T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>Spoiler alert!</p>
<p>Just to get it out of the way: I watched the prequels before the original. I thought the prequels were fine - at first viewing, I felt it was as much an Obi-Wan story as it was Anakin's, and I didn't fully realize how good McGregor's performance was until I watched the old trilogy: they felt like the same person to my childhood self. After seeing full picture of the story, I can see how people who grew up with the original trilogy would view the prequels as an utter blasphemy of the original. Watching the prequels first did took out some thrill of the big reveal in <em>Empire Strikes Back</em>, but I was no less shocked when Anakin actually turned to the dark side in the prequels.</p>
<p>My very first encounter with Star Wars, however, were not the prequels, but a version of <em>Star Wars: The Visual Encyclopedia</em> I found in a local book store. It was all those weird weapons (including a lightwhip that I remembered distinctively), spaceships, and costumes that first enticed me to this world. I was more than rejoiced to find out that the prequels depicted exactly such an colorful yet exotic world. The tone of the original trilogy was a lot more bleak, more &quot;spacey&quot; than &quot;alieny&quot;, and as a child who just witnessed the downfall of Anakin, the transition felt natural to me.</p>
<p>Moving on to the sequel trilogy. I watched <em>The Force Awakens</em> on launch date at 19:00 with my college roommate on launch date and we spent half an hour searching for a parking spot, barely making it to the screening by the opening scroll (we still got a ticket though). As for <em>The Last Jedi</em>, I watched it at night a month after it launched. I went to see <em>The Rise of Skywalker</em> at 9:00 the day it was released, a surprisingly fitting time for the end to a trilogy. TFA was a decent start, nostalgia mixed with several intriguing leads made the experience quite enjoyable. TLJ left a really bad taste in my mouth in that it not only answered questions TFA raised in the poorest way possible, but also spent too much time trying to teach the old, established characters a lesson while neglecting the growth and development of the new characters. I still have an unpublished blog post full of my rants on TLJ (from 2018), so let's move on to TROS.</p>
<p>In short, I enjoyed watching TROS, despite it being a over-packed messy hodgepodge.</p>
<p>The beginning sequence revealing Kylo's encounter with the Emperor and the Falcon crew escaping First Order was succinct and exciting. As Finn, Rey, and Poe reunite though, the pacing dropped considerably, with meaningless arguments breaking out between the trio: I really hope team building is something the last movie of a trilogy shouldn't be worrying about, but the plots of TLJ left J. J. Abrams little choice here I guess.</p>
<p>Then the movie went nowhere for a good half an hour showing the trio wondering around different planets doing things, also &quot;sacrificing&quot; Chewbacca and C-3PO in the process. Even the revelation of Rey's healing powers seemed so intentional that they are bound to be plot devices. The only good scene out of all these is probably the Rey facing off Kylo. In fact, most of the dual scenes between the two are really enjoyable, and these are the only places I can see the slightest bit of human emotion from Rey (in contrast to Kylo, whose constant struggle and change of heart were expressed amazingly by Adam Driver). Rey being a Palpatine was interesting at first, but adds little to the her overall character: it was Kylo who felt the temptation from the dark side this whole time, and all of a sudden this becomes Rey's thing?</p>
<p>The dual on Death Star remains was visually stunning, but the way it ended could have been a bit less awkward: more mandatory plot device showoff, and an extra dose of Han Solo that I think was totally unnecessary given how good Adam Driver's portrayal is. Carrie Fisher's passing away was unfortunate, but I think that caused the rather rushed ending for her character. The entire self-exile sequence also felt corny, and uncharacteristic of Rey. Perhaps Leia being the one to give Rey the last guidance and her lightsaber would have worked better (either as she is passing away or as a Force ghost)?</p>
<p>Subsequent plot again splits Rey away from her supposed &quot;teammates&quot;, and sets the stage of the final showdown between the Resistance and the &quot;Final Order&quot; based on Finn and Poe's seemingly crazy idea (which Poe was specifically told not to do in TLJ). Lando appearing early in the plot and doing pretty much nothing feels like a missed opportunity: lack of screen time with the new crew in previous films left him with little ways to interact with them. I would much prefer if he just make a one-off appearance among the thousands of starships coming to the Resistance's aid in the end. I like the do Resistance' side of story here though: characters are shown to be working together with good chemistry, and they accomplished the impossible in a sensible way.</p>
<p>The fight with the Emperor though was a mixed bag: everything leading up to the final face down was amazing (the lightsaber passing scene was great), until Rey had to face the Emperor alone. There seems to be simply too little emotional connections between Rey and the Emperor for any confrontation between them to have any weight. If anyone, Kylo Ren should be the one allowed to show his resolution at the end of his long journey, not Rey being the same Rey she was in TFA. Having Kylo sacrificing himself in the fight, assuming the role Vader played in <em>Return of the Jedi</em>, would have been a much more fitting ending to him than crawling back to heal and kiss Rey (AKA showing off the plot device we spend 15 minutes foreshadowing). The thousand Sith vs. thousand Jedi bit felt forced (pun intended) and doesn't really even tie into the story that much. By the way, the Emperor looked SCARY, and in a entertaining way: the aesthetic resembles 80's horror film, and strangely felt right here (not to mention that the movie opened with &quot;THE DEAD SPEAK!&quot;). It's also funny that star destroyers are finally rightfully so with their shiny new canons.</p>
<p>Well, looks like I didn't really enjoy the movie now, do I? I'm also surprised that I can still pull out so many things I didn't like despite remembering walking out of the movie theater with a sense of relief and fulfillment. Looking back, the whole trilogy just felt poorly planned, with throw-away characters appearing here and there whose screen time fed to some new droid or alien creature every film presumably just to sell more toys, and broken plot lines that just didn't really make sense. Perhaps <em>The Rise of Skywalker</em> is a valiant attempt at responding to a trick question with no suitable answer and I appreciated the effort. I wonder what the generation growing up with the sequel trilogy would think about them though: would they look back on them fondly the same way I look at the prequels (or Spider-Man 3 for that matter), or is my feeling not entirely clouded by nostalgia after all?</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2019-12-20-review-of-star-wars-the-rise-of-skywalker/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2019-12-01-fun-with-fonts-on-the-web/</id>
    <title type="html"><![CDATA[Fun with Fonts on the Web]]></title><updated>2019-12-01T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>A more accurate version of the title probably should be &quot;Fun with Fonts in Web Browsers&quot;, but oh well, it sounds cooler that way. Text rendering is <a href="https://gankra.github.io/blah/text-hates-you/">hard</a>, and it certainly doesn't help that we have a plethora of different writing systems (blame the Tower of Babel for that, I guess) which cannot be elegantly fitted into a uniform system. Running a bilingual blog doubles the trouble in font picking, and here's a compilation of the various problems I encountered.</p>
<h2>Space Invaders</h2>
<p>Most browsers join consecutive lines of text in HTML to a single one with an added space in between, so</p>
<pre><code class="language-html">&lt;html&gt;Line one and
line two.&lt;/html&gt;
</code></pre>
<p>renders to</p>
<pre><code class="language-text">Line one and line two.
</code></pre>
<p>Such a simplistic rule doesn't work for CJK languages where no separators is used between words. The solution is to specify the <code>lang</code> attribute for the page (or any specific element on the page) like so:</p>
<pre><code class="language-html">&lt;html lang=&quot;zh&quot;&gt;第一行和
第二行。&lt;/html&gt;
</code></pre>
<p>If your browser is smart enough (like Firefox), it will join the lines correctly. All the Blink based browsers, however, still stubbornly shove in the extra space, so it looks like I will be stuck in unwrapped source files like a barbarian for a bit longer. While not a cure-all solution, specifying the <code>lang</code> attribute still have the added benefit of enabling language-specific CSS rules, which comes in handy later.</p>
<h2>Return of the Quotation Marks</h2>
<p>As mentioned in a <a href="https://www.shimmy1996.com/en/posts/2018-06-24-fun-with-fonts-in-emacs/">previous post</a>, CJK fonts would render quotation marks as full-width characters, different from Latin fonts. This won't be a problem as long as a web page doesn't try to mix-and-match fonts: just use language specific font-stack.</p>
<pre><code class="language-css">body:lang(en) {
    font-family: &quot;Oxygen Sans&quot;, sans-serif;
}

body:lang(zh) {
    font-family: &quot;Noto Sans SC&quot;, sans-serif;
}
</code></pre>
<p>Coupled with matching <code>lang</code> attributes, the story would have ended here. Firefox even allows you to specify default fonts on a per language basis, so you can actually get away with just the fallback values, like <code>sans-serif</code> or <code>serif</code>, and not even bother writing language specific CSS.</p>
<p>However, what if I want to use Oxygen Sans for Latin characters, Noto Sans SC for CJK characters? While seemingly an sensible solution, specifying font stack like so,</p>
<pre><code class="language-css">body:lang(zh) {
    font-family: &quot;Oxygen Sans&quot;, &quot;Noto Sans SC&quot;, sans-serif;
}
</code></pre>
<p>would cause the quotation marks to be rendered using Oxygen Sans, which displays them as half-width characters. The solution I found is to declare an override font with a specified <code>unicode-range</code> that covers the quotation marks,</p>
<pre><code class="language-css">@font-face {
    font-family: &quot;Noto Sans SC Override&quot;;
    unicode-range: U+2018-2019, U+201C-201D;
    src: local(&quot;NotoSansCJKsc-Regular&quot;);
}
</code></pre>
<p>and revise the font stack as</p>
<pre><code class="language-css">body:lang(zh) {
    font-family: &quot;Noto Sans SC Override&quot;, &quot;Oxygen Sans&quot;, &quot;Noto Sans SC&quot;, sans-serif;
}
</code></pre>
<p>Now we can enjoy the quotation marks in their full-width glory!</p>
<h2>Font Ninja</h2>
<p>Font files are quite significant in size, and even more so for CJK ones: the Noto Sans SC font just mentioned is <a href="https://github.com/googlefonts/noto-cjk/blob/master/NotoSansSC-Regular.otf">over 8MB</a> in size. No matter how determined I am to serve everything from my own server, this seems like an utter overkill considering the average HTML file size on my site is probably closer to 8KB. How does all the web font services handle this then?</p>
<p>Most web font services work by adding a bunch of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face"><code>@font-face</code></a> definitions into a website's style sheet, which pulls font files from dedicated servers. To reduce the size of files been served, Google Fonts slice the font file into smaller chunks, and declare corresponding <code>unicode-range</code> for each chunk under <code>@font-face</code> blocks (this is exactly how they handle <a href="https://fonts.googleapis.com/css?family=Noto+Sans+SC">CJK fonts</a>). They also compress the font files into WOFF2, further reducing file size. On the other hand, <a href="https://fonts.adobe.com/">Adobe Fonts</a> (previously known as Typekit) seem to have some JavaScript wizardry that dynamically determines which glyphs to load from a font file.</p>
<p>Combining best of both worlds, and thanks to the fact that this is a static site, it is easy to gather all the used characters and serve a font file containing just that. The tools of choice here would be pyftsubset (available as a component of <a href="https://pypi.org/project/fonttools/">fonttools</a>) and GNU AWK. Compressing font files into WOFF2 also requires Brotli, a compression library. Under Arch Linux, the required packages are <a href="https://www.archlinux.org/packages/community/any/python-fonttools/">python-fonttools</a>, <a href="https://www.archlinux.org/packages/core/x86%5F64/gawk/">gawk</a>, <a href="https://www.archlinux.org/packages/community/x86%5F64/brotli/">brotli</a>, and <a href="https://www.archlinux.org/packages/community/x86%5F64/python-brotli/">python-brotli</a>.</p>
<p>Here's a shell one-liner to collect all the used glyphs from generated HTML files:</p>
<pre><code class="language-sh">find . -type f -name &quot;*.html&quot; -printf &quot;%h/%f &quot; | xargs -l awk 'BEGIN{FS=&quot;&quot;;ORS=&quot;&quot;} {for(i=1;i&lt;=NF;i++){chars[$(i)]=$(i);}} END{for(c in chars){print c;} }' &gt; glyphs.txt
</code></pre>
<p>You may need to <code>export LANG=en_US.UTF-8</code> (or any other UTF-8 locale) for certain glyphs to be handled correctly. With the list of glyphs, we can extract the useful part of font files and compress them:</p>
<pre><code class="language-sh">pyftsubset NotoSansSC-Regular.otf --text-file=glyphs.txt --flavor=woff2 --output-file=NotoSansSC-Regular.woff2
</code></pre>
<p>Specifying <code>--no-hinting</code> and <code>--desubroutinize</code> can further reduce size of generated file at the cost of some aesthetic fine-tuning. A similar technique can be used to shrink down Latin fonts to include only ASCII characters (or keep the extended ASCII range with <code>U+0000-00FF</code>):</p>
<pre><code class="language-sh">pyftsubset Oxygen-Sans.ttf --unicodes=&quot;U+0000-007F&quot; --flavor=woff2 --output-file=Oxygen-Sans.woff2
</code></pre>
<p>Once this is done, available glyphs can be checked using most font manager software, or this <a href="http://torinak.com/font/lsfont.html">online checker</a> (no support for WOFF2 though, but you can convert into other formats first, such as WOFF).</p>
<p>I also played around the idea of actually dividing the glyphs into further chunks by popularity, so here's another one liner to get list of glyphs sorted by number of appearances</p>
<pre><code class="language-sh">find . -type f -name &quot;*.html&quot; -printf &quot;%h/%f &quot; | xargs -l awk 'BEGIN{FS=&quot;&quot;} {for(i=1;i&lt;=NF;i++){chars[$(i)]++;}} END{for(c in chars){printf &quot;%06d %s\n&quot;, chars[c], c;}}' | sort -r &gt; glyph-by-freq.txt
</code></pre>
<p>It turns out my blog has around 1000 different Chinese characters, with roughly 400 of them appearing more than 10 times. Since the file sizes I get from directly a single subsetting is already good enough, I didn't bother proceeding with another split.</p>
<h2>For Your Browsers Only</h2>
<p>With all the tricks in my bag, I was able to cut down the combined font file size to around 250KB, still magnitudes above that of an HTML file though. While it is nice to see my site appearing the same across all devices and screens, I feel the benefit is out of proportion compared to the 100-fold increase in page size.</p>
<p>Maybe it is just not worth it to force the choice of fonts. In case you want to see my site as I would like to see it, here are my go-to fonts:</p>
<ul>
<li>Proportional Latin font: <a href="https://github.com/KDE/oxygen-fonts">Oxygen Sans</a>. Note that the KDE version has nuanced differences from the <a href="https://fonts.google.com/specimen/Oxygen">Google Fonts version</a>, and I like the KDE version much more.</li>
<li>Proportional CJK font: <a href="https://www.google.com/get/noto/help/cjk/">Noto Sans CJK</a>.</li>
<li>Monospace font: <a href="https://typeof.net/Iosevka/">Iosevka</a>, the ss09 variant, to be more exact.</li>
</ul>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2019-12-01-fun-with-fonts-on-the-web/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2019-09-15-hello-darkness-my-old-friend/</id>
    <title type="html"><![CDATA[Hello Darkness, My Old Friend]]></title><updated>2019-09-15T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>With system wide dark modes becoming commonplace, I took the effort to tweak the color scheme of my blog and added a dark mode specific one using <code>prefers-color-scheme</code> in CSS. I also toyed around the idea of adding a user toggle using JavaScript per instructions <a href="https://flaviocopes.com/dark-mode/">here</a>, but ultimately decided against it because of my (totally unjustified and groundless) distaste towards the language.</p>
<table>
<thead>
<tr>
<th>Color Usage</th>
<th>Light Theme</th>
<th>Dark Theme</th>
</tr>
</thead>
<tbody>
<tr>
<td>Accent</td>
<td><code>#700000</code></td>
<td><code>#8fffff</code></td>
</tr>
<tr>
<td>Background</td>
<td><code>#f7f3e3</code></td>
<td><code>#080c1c</code></td>
</tr>
<tr>
<td>Text</td>
<td><code>#2e2d2b</code></td>
<td><code>#d1d2d4</code></td>
</tr>
<tr>
<td>Code Background</td>
<td><code>#e3dacb</code></td>
<td><code>#1c2534</code></td>
</tr>
<tr>
<td>Border 1</td>
<td><code>#e7e3d3</code></td>
<td><code>#181c2c</code></td>
</tr>
<tr>
<td>Border 2</td>
<td><code>#d7d3c3</code></td>
<td><code>#282c3c</code></td>
</tr>
</tbody>
</table>
<p>Writing CSS is a such tiring endeavor, but on the bright side, picking colors is a surprisingly relaxing activity. The light mode color scheme now has reduced contrast, and I updated the isso style sheets with matching colors. Yes, I only inverted the colors in dark mode and did not reduce the font weights because of the peculiar way in which human vision work. Part of me already screams heresy when I look at the color codes formed by three numbers that seem to have no connection whatsoever—they are like dissonant chords that cause itches in brain—so I <strong>need</strong> them to at least sum up to a nice number.</p>
<p>Wissen ist Nacht!</p>
<h2>Comments</h2>










<article class="e-content top-border" id="2bce4c4">
  <header>
    <nav>
      <span class="menu">
        <a class="entry" href="#2bce4c4">2019-09-16T04:52:34&#43;00:00</a>
        <span class="entry"> </span>
      </span>
    <b>aclef</b>&nbsp;<code>6dd1</code></header>
  <p>I've been using Manjaro exclusively for at least a year(yeah I'm not quite nerd enough to try Arch in its original taste or even Gentoo XD), One thing I love is I can easily invert the color of window with shortcuts. Together with many other pros I can finally say I love linux for its own sake but not out of my hatred for Microsoft. LOL.</p>
<p>How is LaTeX rendering implemented for your blog? Does it work well with dare mode?</p>

  </article>




<article class="e-content top-border" id="d565883">
  <header>
    <nav>
      <span class="menu">
        <a class="entry" href="#d565883">2019-09-16T05:10:41&#43;00:00</a>
        <span class="entry"> </span>
      </span>
    <b>shimmy1996</b>&nbsp;✦</header>
  <p>Interesting - is that a function of the desktop environment that you use? Does it handle images correctly?</p>
<p>For LaTeX rendering, I'm using <a href="https://katex.org/">KaTeX</a>, which is supposedly faster than the more popular MathJax. It respects the html color tags so it works fine in dark mode. I haven't figured out an efficient way to include my LaTeX macros so the only example of posts using LaTeX so far is the LaTeX logo <a href="https://www.shimmy1996.com/en/posts/2018-05-21-construction-finished/">here</a>.</p>

  </article>




<article class="e-content top-border" id="41c4021">
  <header>
    <nav>
      <span class="menu">
        <a class="entry" href="#41c4021">2019-09-16T05:35:43&#43;00:00</a>
        <span class="entry"> </span>
      </span>
    <b>aclef</b>&nbsp;<code>6dd1</code></header>
  <p>For KDE out of the box there's an invert option in desktop effect settings, you can specify different hot key for window inversion or global inversion.
For Cinnamon you can install a extension in it's own extension market that can do the same thing.</p>
<p>For other gnome derivatives, install xcalib and register a hot key to 'xcalib -i -c' can handle global inversion ,still don't know how to do window-wise inversion.
Because it's inversion on the level of window composition so images will also be inverted, it's okay for me though. For webpages there's a firefox plugin that can handle image aware inversion.</p>

  </article>




<article class="e-content top-border" id="94c59f4">
  <header>
    <nav>
      <span class="menu">
        <a class="entry" href="#94c59f4">2019-09-16T05:54:29&#43;00:00</a>
        <span class="entry"> </span>
      </span>
    <b>shimmy1996</b>&nbsp;✦</header>
  <p>Intriguing - I'm running i3/sway on my setup and use system-wide dark mode via <code>gtk-application-prefer-dark-theme</code> config. It's finicky in that its effectiveness depends on application support. In context of website dark modes, Firefox picks that setting up and loads the correct CSS but Chromium doesn't.</p>
  </article>



]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2019-09-15-hello-darkness-my-old-friend/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2019-04-27-enumerate-with-c-plus-plus/</id>
    <title type="html"><![CDATA[enumerate() with C&#43;&#43;]]></title><updated>2019-04-27T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>Quite a few programming languages provide ways to iterate through a container while keeping count of the number of steps taken, such as <code>enumerate()</code> in Python:</p>
<pre><code class="language-python">for i, elem in enumerate(v):
    print(i, elem)
</code></pre>
<p>and <code>enumerate()</code> under <code>std::iter::Iterator</code> trait in Rust:</p>
<pre><code class="language-rust">for (i, elem) in v.iter().enumerate() {
    println!(&quot;{}, {}&quot;, i, elem);
}
</code></pre>
<p>This is just a quick note about how to do similar things in C++17 and later without declaring extra variables out of the for loop's scope.</p>
<p>The first way is to use a mutable lambda:</p>
<pre><code class="language-c++">std::for_each(v.begin(), v.end(),
              [i = 0](auto elem) mutable {
                  std::cout &lt;&lt; i &lt;&lt; &quot;, &quot; &lt;&lt; elem &lt;&lt; std::endl;
                  ++i;
              });
</code></pre>
<p>This could be used with all the algorithms that guarantees in-order application of the lambda, but I don't like the dangling <code>++i</code> that could get mixed up with other logic.</p>
<p>The second way utilizes structured binding in for loops:</p>
<pre><code class="language-c++">for (auto [i, elem_it] = std::tuple{0, v.begin()}; elem_it != v.end();
     ++i, ++elem_it) {
    std::cout &lt;&lt; i &lt;&lt; &quot;, &quot; &lt;&lt; *elem_it &lt;&lt; std::endl;
}
</code></pre>
<p>We have to throw in <code>std::tuple</code> as otherwise compiler would try to create a <code>std::initializer_list</code>, which does not allow heterogeneous contents.</p>
<p>The third least fancy method is to just calculate the distance every time:</p>
<pre><code class="language-c++">for (auto elem_it = v.begin(); elem_it != v.end(); ++elem_it) {
    auto i = std::distance(v.begin(), elem_it);
    std::cout &lt;&lt; i &lt;&lt; &quot;, &quot; &lt;&lt; *elem_it &lt;&lt; std::endl;
}
</code></pre>
<p>Since we have to copy paste the starting point twice, I like other counter based approaches better.</p>
<p>In C++20, we have the ability to add an init-statement in ranged-based for loops, so we can write something like</p>
<pre><code class="language-c++">for (auto i = 0; auto elem : v) {
    std::cout &lt;&lt; i &lt;&lt; &quot;, &quot; &lt;&lt; elem &lt;&lt; std::endl;
    i++;
}
</code></pre>
<p>Meh, not that impressive. The new <code>&lt;ranges&gt;</code> library provides a more appealing way to achieve this:</p>
<pre><code class="language-c++">for (auto [i, elem] : v | std::views::transform(
         [i = 0](auto elem) mutable { return std::tuple{i++, elem}; })) {
    std::cout &lt;&lt; i &lt;&lt; &quot;, &quot; &lt;&lt; elem &lt;&lt; std::endl;
}
</code></pre>
<p>I like the structured binding method and the <code>&lt;ranges&gt;</code> based method the most. It would be even better though if we can get a <code>std::views::enumerate</code> to solve this problem once and for all.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2019-04-27-enumerate-with-c-plus-plus/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2019-02-28-trackpad-and-swollen-batteries/</id>
    <title type="html"><![CDATA[Trackpad and Swollen Batteries]]></title><updated>2019-02-28T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>For the last few weeks, the right click on my Dell XPS 13's trackpad is getting less responsive: the entire right half of the trackpad sunk around 2mm beneath the palm rest, making clicks hard to register. At first I dismissed it as normal wear, but it turned out that the swollen batteries lifted the left half of the trackpad to such a degree that the trackpad warped. I immediately ordered an OEM replacement (Dell JD25G) swapped out the swollen batteries. XPS 13 (9343) was a breeze to service. The screws that hold the bottom panel (a quite hefty hunk of aluminum) in place are all clearly visible and the component layout allows battery to be swapped with minimal disassembly. I also swapped out the WLAN card (Dell DW1560) for an Intel AC9560, whose drivers are in the mainline Linux kernel.</p>
<p>The trackpad felt normal after the battery swap, of course. However, the fact that average laptop battery starts to degrade around 18 months surprised me quite a bit. Mine lasting nearly four years is probably quite decent. Newer laptops uses prismatic cells (those slab shaped batteries also found in phones) instead of cylindrical ones, as can be found in my first laptop, Dell Vostro 3750. Roughly speaking, prismatic cells trade size for lifespan by emitting external casing and gas vents found on cylindrical cells. The battery swell is caused by gas build up, which might have been avoided in cylindrical cells with vents. It's interesting that (easily) removable batteries have largely disappeared in consumer laptops - even the large desktop replacements (to be fair, those spend most of the time plugged in anyways). The only consumer electronics that still almost always have removable batteries I can think of are cameras.</p>
<p>After the incident, I started to browse current laptops on the market as the new quad/hex core laptop CPUs are quite tempting an upgrade (my XPS 13 has a i5-5200U). I was not a huge fan of the latest XPS 13 (9380) mostly because of the port selection: I just don't have any USB Type-C devices, so the 1 Type-C plus 2 Type-A combination found on XPS 13 (9360) is superior in my opinion. Besides ports, the onboard WLAN card and removal of full-sized SD card slot also make the latest model less appealing.</p>
<p>I also came across the Let's Note line of laptops from Panasonic, which are reliable, lightweight business laptops that often comes with removable batteries and a wide spectrum of ports. If only they weren't so prohibitively expansive, doesn't have those ugly &quot;Wheel Pads&quot;, and come with US keyboard layout, they are quite the ideal laptops. I like the aesthetics of 2016 CF-MX5 series the most, but that won't make much of an upgrade.</p>
<p>More realistic choices include HP's EliteBook, Lenovo's ThinkPad T series, and Dell's Latitude/Precision lines. I vetoed EliteBook because all of them had a huge glaring proprietary docking port that I might never use. Latitude 5491 seem to have cooling issues due to the 45W TDP CPUs, while Latitude 7390 and 7490 both seem quite decent, with options to disable Intel ME and official Linux support. ThinkPad T480 pretty much ticks everything on my list, but it seems that the next iteration T490 will no longer have the bridge battery system and only one SODIMM slot, pretty much like T480s.</p>
<p>Hunting for second-handed machines is also an option, but it defeats the purpose of the upgrade since my primary motivation is the new quad core CPUs. Some may argue our laptops are overpowered already, and indeed my XPS 13 still feels pretty snappy though, so I'm not in urgent need for an upgrade. However, I did come up with a list of what I want in a laptop in case the ideal candidate shows up someday.</p>
<ul>
<li>Good Linux driver support.</li>
<li>Below 15 inch in size and low travel weight. XPS 13 converted me from a DTR enthusiast to an Ultrabook follower: it does feel nice to be able carry a laptop all day without feeling it.</li>
<li>Non-Nvidia graphics. Both AMD and Intel has better open source driver support and I use my desktop for tasks heavily reliant on GPU.</li>
<li>Reasonable battery life (6 hours or more) and removable battery.</li>
<li>Not-too-radical port selections, not until all mouses and flash drives default to USB Type-C at least.</li>
<li>Standard components and easy to upgrade, i.e. SODIMM slot for memory, PCIe for WLAN card/SSD.</li>
<li>A nice trackpad. I'm rather insensitive to quality of laptop keyboards so anything marginally decent would do. It would be really cool to have an ErgoDox laptop though.</li>
<li>Not-super-high-resolution display. I'm not too picky about screens either, but 4K feels like an utter overkill for laptops this size that provides marginal improvements while draining more power. I've always used 16:9 displays, but I'm open to trying out different ones.</li>
</ul>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2019-02-28-trackpad-and-swollen-batteries/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2019-01-27-installing-gentoo/</id>
    <title type="html"><![CDATA[Installing Gentoo]]></title><updated>2019-01-27T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>I finally bite the bullet and installed Gentoo on VirtualBox (totally not motivated by the front page wishlist), thereby achieving my ultimate digital @5c3n510n (or descent according to DistroWatch).</p>
<p>Jokes aside, the installation process is surprisingly pleasant: the <a href="https://wiki.gentoo.org/wiki/Handbook:Main%5FPage">Gentoo Handbook</a> is wonderfully written, and seems to have a plan for everything that might go wrong. I like the Handbook more than ArchWiki's <a href="https://wiki.archlinux.org/index.php/Installation%5Fguide">Installation Guide</a> as it also details the rationale behind each step I took, which is often a fun read in its own right. I would go as far as saying the Gentoo Handbook is actually more beginner friendly, as it carefully assembles bits of information that are normally scattered all over the place, providing a great starting point for learning how to tame the operating system. Besides, Gentoo Handbook covers more than installation: it also contains other necessary setup processes to set up a usable system. I will be gradually replicating my current desktop setup to decide if a migration is worth the time.</p>
<p>My very first encounter with GNU/Linux operating systems is Ubuntu 12.04: one of my classmates (vacuuny/A2Clef) was installing it in school's computer labs. There was a time when I would switch between various Ubuntu variants every few days. I dual booted Windows and Ubuntu for a while before switching entirely to Ubuntu in 2014. Much annoyed by the Amazon ads, I tried out Arch Linux as part of my New Year's resolution in 2015. Even with a second computer to look up instructions, it still took me quite a while to adapt to the new system. I ranted &quot;maybe I still haven't gotten the Arch way&quot; in my old blog, but never looked back once I got the knack of it.</p>
<p>I still try out other distributions from time to time in VirtualBox, but never find them to offer much improvements compared with Arch beyond the setup processes, and even more so when considering the excellent documentation on ArchWiki (well now we have a contender). Once I have my desktop environment set up, the experience between distributions is not that different, but the distinctions kicks in when problems occur and I search online for troubleshooting tips. Having more up-to-date packages is another charm Arch has. More recently, the <code>systemd</code> controversy caused me to start shopping around for a new distribution to try out, not so much because of the actual security concerns, but just to see what it is like to use different init system: my time in Ubuntu was spent mostly in GUIs (<code>apt-get</code> and <code>nano</code> was probably the only command I knew for the longest time) without knowing about init systems and Arch was already using <code>systemd</code> when I switched. Aside from Gentoo, the candidates include Void Linux and the BSDs. Void Linux was easy to set up with its installer wizard, yet I didn't feel compelled to move to it. Let's see if Gentoo would change my mind.</p>
<h2>Comments</h2>










<article class="e-content top-border" id="84175bd">
  <header>
    <nav>
      <span class="menu">
        <a class="entry" href="#84175bd">2019-09-16T05:23:07&#43;00:00</a>
        <span class="entry"> </span>
      </span>
    <b>aclef</b>&nbsp;<code>6dd1</code></header>
  <p>I don't really know I am the guy who introduced you to the Linux wonderland XD. I've been using all sorts of distributions along the way but eventually settled on Manjaro, before I completely ditched Win.</p>
<p>I still do distro/DE/WM jumping sometimes, but I have an inexplicable distaste for VMs so I installed them into SD cards(have to do some chainloading to boot into it but visually more appealing, without an USB dongle ) or USB drives, and they run very smoothly, which is quite unexpected.</p>

  </article>




<article class="e-content top-border" id="420e061">
  <header>
    <nav>
      <span class="menu">
        <a class="entry" href="#420e061">2019-09-16T06:25:09&#43;00:00</a>
        <span class="entry"> </span>
      </span>
    <b>shimmy1996</b>&nbsp;✦</header>
  <p>My primary use case for VMs is to run certain Win/Mac only programs (yes Adobe I'm looking at you and your stupid encrypted PDFs). For distro hopping, VM is nice in that it circumvents most driver issues, but I can see the appeal of SD card/USB drive approaches - much more portable if you want to run on different devices. Modern day flash memory are probably magnitudes faster than HDDs in random reads - good ol' technology!</p>
  </article>



]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2019-01-27-installing-gentoo/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2019-01-03-2018-in-review/</id>
    <title type="html"><![CDATA[2018 in Review]]></title><updated>2019-01-03T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>Before anything, happy New Year!</p>
<p>It's an interesting feeling when the time span of one year gradually becomes
shorter relative to the time that has already passed in one's life. If only the
actual length of one year also scales with one's age, perhaps we would feel more
of the excitement instead of anxiety during the New Year count down. That being
said, 2018 was a lot of fun for me, even without ray-tracing graphic cards.</p>
<h2>The Amazing 2018</h2>
<p>To quote my 2017 self:</p>
<blockquote>
<p>If I've learned anything from my past failed plans, it would be to always
underestimate my own capabilities when planning...</p>
</blockquote>
<p>Yeah, it's totally just that my estimates about the amount of free time I would
have was off, as can be seen from the status of my 2018 goals.</p>
<ul>
<li>☒ Run 1000 miles. <code>[405/1000]</code></li>
<li>☒ Finish a marathon.</li>
<li>☒ Write 20 blog posts. <code>[10/20]</code></li>
<li>☒ Get the first signature for my PGP key.</li>
<li>☒ Install Gentoo.</li>
</ul>
<p>Knowing that I can always change the 'publish date' of blog entries (thanks to
<code>hugo</code>), I grew into the bad habit of starting an article and just then shelving
it for months to come. When I finally remember that one unfinished article, I
frequently dismiss the idea as not really worth elaborating. Now that I think
about it, maybe this is exactly what blogs are for, providing a snapshot of
myself that I can look back later, whether my future self find it silly or 'not
really worth elaborating'.</p>
<p>The number of movie theater visits I had in 2018 probably accounts for 50% of my
lifetime total, and with double doses of disappointment from <em>Star Wars: The
Last Jedi</em> and <em>Incredibles 2</em>. By the way, 2018 also saw 90% of my lifetime
popcorn consumption. I've never realized those can be such addicting.</p>
<p>Although not a marathon, I did ran my first trail half marathon in May. It was
the first time I've ever hit the wall while running, due to bad pacing and
unpreparedness for the weather. The race started mid afternoon on a scorchingly
hot day. After witnessing quite a few people stopped to walk in the first 2
miles, I started off quite a bit faster than my intended pace fueled by a stupid
sense of superiority, and hit the wall right at the mark of 4 miles. Fortunately
the feeling faded away as I walked the next half of the race, gulping ice-cold
Gatorade at every hydration point. However, the ice-cold Gatorade was another
trap—temperature dropped rapidly as sun started to set and my stomach started
to complain about all the chilly liquid. As the finish line appeared within 400
meters of my sight, my legs were hit by the strongest cramps I've ever
had. After barely making it through while being surpassed by 3 people right
before finish line, I could only be happy to learn that I was still not the last
one: actually, I'm even the first one in my age group (<del>whose size is one</del>). The
somewhat illegitimate feeling of compliment, mixed with a bit of salt and guilt
made the race a wondrous experience.</p>
<h2>The Spectacular 2019</h2>
<p>Since Google is deprecating Inbox in the coming March, I've lost my last excuse
for clinging to Gmail. I'll try to gradually fade out my Gmail usage for my own
email server.</p>
<p>On the front of searching for best solution for blog comments, quite a few
bloggers I follow have started embracing <a href="https://indieweb.org/">IndieWeb</a> and <a href="https://webmention.net/">Webmention</a>. In a lot of ways, Webmention was the exact thing I wanted: federated
blog comments, posts, and more. Yet I'm reluctant to move further away from a
static site, not to mentioning most easy-to-follow Webmention solutions I have
found relies heavily on third-party services. The IndieWeb movement itself though is
fairly intriguing. I've never had much use for <a href="https://keybase.io/">Keybase</a> aside from it being a hub
linking most of my online presences (decryption and encryption does not work
without uploading PGP private keys, and I have no one to securely chat with),
perhaps I should just replace it with <code>rel=me</code> links.</p>
<p>Diving into C++17 was fairly enjoyable during the past year, so I'm looking into
learning other new programming languages. <a href="https://www.rust-lang.org/">Rust</a> and <a href="https://julialang.org/">Julia</a> have been on my radar
for a while, especially Rust. Having a full suite of officially supported tools
makes writing Rust a smooth and deeply satisfying experience. I'll try to dive
deeper into both languages and hopefully put them into some uses.</p>
<p>As for running and blog posts, I'll try to match 2018's numbers. On top of
those, I'm thinking about keeping a record of the books, music, and shows I've
read/listened/watched on this blog, along with my thoughts. I actually attempted
something similar during this blog's Wordpress days: I once setup a MediaWiki
instance for similar purposes, but lacked the motivation to continue maintaining
the entries. I'll keep it simple this time, and I should come up with a set of
rating system.</p>
<p>What should I do with the remaining 2018 goals? A separate wishlist is a pretty
good idea—let's go with that. As a stretch goal, I should probably clean my
desktop computer, which is stuffed with four-year-old dirt, cat hair, and dead
skin cells.</p>
<p>Here's to another spectacular 2.9e+17 radiation periods of Caesium-133!</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2019-01-03-2018-in-review/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2018-06-24-fun-with-fonts-in-emacs/</id>
    <title type="html"><![CDATA[Fun With Fonts in Emacs]]></title><updated>2018-06-24T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>I finally took some time to look at the my font configurations in Emacs and cleaned them up as much as possible. This dive into the rabbit hole have been tiring yet fruitful, revealing the cravat of typesetting that I didn't know before, especially for CJK characters.</p>
<p>I primarily use Emacs by running a daemon and connecting to it via a graphical
<code>emacsclient</code> frame, and I am attempting to tackle three major problems: I don't
have granular control over font mapping, glyph widths are sometimes inconsistent
with character widths, and emoji show up as weird blocks. Terminal Emacs doesn't
suffer as much from these problems, yet I don't want to give away the nice perks
like system clipboard access and greater key binding options, so here goes
nothing.</p>
<h2>Font Fallback Using Fontsets</h2>
<p>Ideally, I want to specify two sets of fonts, a default monospace font and a
CJK-specific font. Here's how I originally specified the font in Emacs:</p>
<pre><code class="language-emacs-lisp">(setq default-frame-alist '((font . &quot;Iosevka-13&quot;)))
</code></pre>
<p>The method above obviously leaves no ground for fallback fonts. However, it
turns out I can specify the <code>font</code> to be a fontset instead of an individual
font. According to <a href="https://www.gnu.org/software/emacs/manual/html%5Fnode/emacs/Fontsets.html">Emacs Manual</a>, a fontset is essentially a mapping from Unicode
range to a font or hierarchy of fonts and I can <a href="https://www.gnu.org/software/emacs/manual/html%5Fnode/emacs/Modifying-Fontsets.html">modify</a> one with relative ease.</p>
<p>Sounds like an easy job now? Not so fast. I don't really know which fontset to
modify: fontset behavior is quirky in that the fontset Emacs ends up using seems
to differ between <code>emacsclient</code> and normal <code>emacs</code>, between terminal and
graphical frames, and even between different locales. While there is a way to
get the current active fontset (<code>(frame-parameter nil 'font)</code>), this method is
unreliable and may cause errors like <a href="https://lists.gnu.org/archive/html/emacs-devel/2006-12/msg00285.html">this one</a>.</p>
<p>After all kinds of attempts and DuckDuckGoing (that really rolled right off the
tongue, and no, I am <a href="https://www.reddit.com/r/duckduckgo/comments/8cm51u/what%5Fing%5Fverb%5Fdo%5Fyou%5Fuse%5Ffor%5Fduckduckgo/">not the first one</a>), I finally found the <a href="https://stackoverflow.com/questions/17102692/using-a-list-of-fonts-with-a-daemonized-emacs">answer</a>: just define
a new fontset instead of modifying existing ones.</p>
<pre><code class="language-emacs-lisp">(defvar user/standard-fontset
  (create-fontset-from-fontset-spec standard-fontset-spec)
  &quot;Standard fontset for user.&quot;)

;; Ensure user/standard-fontset gets used for new frames.
(add-to-list 'default-frame-alist (cons 'font user/standard-fontset))
(add-to-list 'initial-frame-alist (cons 'font user/standard-fontset))
</code></pre>
<p>I won't bore you with the exact logic just yet, as I also made other changes to
the fontset.</p>
<h3>Displaying Emoji</h3>
<p>Solution to emoji display is similar—just specify a fallback font with emoji
support—or so I thought. I tried to use Noto Color Emoji as my emoji font,
only to find Emacs does not yet support colored emoji font. Emacs used to
support colored emoji on macOS, but this functionality was later <a href="https://github.com/emacs-mirror/emacs/blob/emacs-25.1/etc/NEWS#L1723">removed</a>.</p>
<p>I ended up using <a href="http://users.teilar.gr/~g1951d/">Symbola</a> as my emoji fallback font (actually I used it as a
fallback for all Unicode characters), which provided comprehensive coverage over
<a href="https://unicode.org/Public/emoji/11.0/emoji-test.txt">all the emoji</a> and special characters. Also note that since Emacs 25,
customization to the <code>symbols</code> <a href="https://www.gnu.org/software/emacs/manual/html%5Fnode/emacs/Charsets.html">charset</a>, which contains puncation marks, emoji,
etc., requires <a href="https://github.com/emacs-mirror/emacs/blob/emacs-25/etc/NEWS#L58">some extra work</a>:</p>
<pre><code class="language-emacs-lisp">(setq use-default-font-for-symbols nil)
</code></pre>
<p>There does exist a workaround for colored emoji though, not with fancy fonts,
but by replacing Unicode characters with images. <a href="https://github.com/iqbalansari/emacs-emojify"><code>emacs-emojify</code></a> is a package
that provides this functionality. I ultimately decided against it as it does
slow down Emacs quite noticeably and the colored emoji image library is not as
comprehensive.</p>
<h3>Quotation Marks</h3>
<p>I've always used full-width directional curly quotation marks (&quot;“”&quot; and
&quot;‘’&quot;) when typing in Chinese, and ASCII style ambidextrous straight quotation
marks (&quot;&quot;&quot; and &quot;'&quot;) when typing in English. Little did I know there really is no
such thing as full-width curly quotation marks: there is only one set of curly
quotation mark codepoints in Unicode (U+2018, U+2019, U+201C, and U+201D) and
the difference between alleged full-width and half-width curly quotation marks
is caused solely by fonts. There have been <a href="https://www.unicode.org/L2/L2014/14006-sv-western-vs-cjk.pdf">proposals</a> to standardize the two
distinct representations, but for now I'm stuck with this ambiguous mess.</p>
<p>It came as no surprise that these curly quotation marks are listed under
<code>symbols</code> charset, instead of a CJK one, thus using normal monospace font
despite the fact that I want them to show up as full-width characters. I don't
have a true solution for this—being consistent is the only thing I can do, so
I forced curly quotation marks to display as full width characters by overriding
these exact Unicode codepoints in my fontset. I'm not really sure how I feel
when I then realized ASCII style quotation marks also suffered from
<a href="https://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html">confusion</a>—maybe we are just really bad at this.</p>
<p>My fallback font configurations can be found on both <a href="https://github.com/shimmy1996/.emacs.d#fontset-with-cjk-and-unicode-fallback">GitHub</a> and <a href="https://git.shimmy1996.com/emacs.d/file/README.org.html#l158">Trantor Holocron</a>
and I'll list them here just for sake of completeness:</p>
<pre><code class="language-emacs-lisp">(defvar user/cjk-font &quot;Noto Sans CJK SC&quot;
  &quot;Default font for CJK characters.&quot;)

(defvar user/latin-font &quot;Iosevka Term&quot;
  &quot;Default font for Latin characters.&quot;)

(defvar user/unicode-font &quot;Symbola&quot;
  &quot;Default font for Unicode characters, including emojis.&quot;)

(defvar user/font-size 17
  &quot;Default font size in px.&quot;)

(defun user/set-font ()
  &quot;Set Unicode, Latin and CJK font for user/standard-fontset.&quot;
  ;; Unicode font.
  (set-fontset-font user/standard-fontset 'unicode
                    (font-spec :family user/unicode-font)
                    nil 'prepend)
  ;; Latin font.
  ;; Only specify size here to allow text-scale-adjust work on other fonts.
  (set-fontset-font user/standard-fontset 'latin
                    (font-spec :family user/latin-font :size user/font-size)
                    nil 'prepend)
  ;; CJK font.
  (dolist (charset '(kana han cjk-misc hangul kanbun bopomofo))
    (set-fontset-font user/standard-fontset charset
                      (font-spec :family user/cjk-font)
                      nil 'prepend))
  ;; Special settings for certain CJK puncuation marks.
  ;; These are full-width characters but by default uses half-width glyphs.
  (dolist (charset '((#x2018 . #x2019)    ;; Curly single quotes &quot;‘’&quot;
                     (#x201c . #x201d)))  ;; Curly double quotes &quot;“”&quot;
    (set-fontset-font user/standard-fontset charset
                      (font-spec :family user/cjk-font)
                      nil 'prepend)))

;; Apply changes.
(user/set-font)
;; For emacsclient.
(add-hook 'before-make-frame-hook #'user/set-font)
</code></pre>
<h2>CJK Font Scaling</h2>
<p>My other gripe is the width of CJK fonts does not always match up with that of
monospace font. Theoretically, full-width CJK characters should be exactly twice
of that half-width characters, but this is not the case, at least not in all
font sizes. It seems that CJK fonts provide less granularity in size, i.e. 16px
and 17px versions of CJK characters in Noto Sans CJK SC are exactly the same,
and does not increase until size is bumped up to 18px, while Latin characters
always display the expected size increase. This discrepancy means their size
would match every couple sizes, but different in between with CJK fonts being a
bit too small.</p>
<p>One solution is to specify a slightly larger default size for CJK fonts in the
fontset. However, this method would render <code>text-scale-adjust</code> (normally bound
to <kbd>C-x C-=</kbd> and <kbd>C-x C--</kbd>) ineffective against CJK fonts for some reason. A
better way that preserves this functionality is to scale the CJK fonts up by
customizing <code>face-font-rescale-alist</code>:</p>
<pre><code class="language-emacs-lisp">(defvar user/cjk-font &quot;Noto Sans CJK SC&quot;
  &quot;Default font for CJK characters.&quot;)

(defvar user/font-size 17
  &quot;Default font size in px.&quot;)

(defvar user/cjk-font-scale
  '((16 . 1.0)
    (17 . 1.1)
    (18 . 1.0))
  &quot;Scaling factor to use for cjk font of given size.&quot;)

;; Specify scaling factor for CJK font.
(setq face-font-rescale-alist
      (list (cons user/cjk-font
                  (cdr (assoc user/font-size user/cjk-font-scale)))))
</code></pre>
<p>bWhile the font sizes might still go out of sync after <code>text-scale-adjust</code>, I am
not too bothered. The exact scaling factor took me a few trial and error to find
out. I just kept adjusting the factor until these line up (I found <a href="https://websemantics.uk/articles/font-size-conversion/">this table</a>
really useful):</p>
<pre><code class="language-nil">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云云
雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲雲
ㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞㄞ
ああああああああああああああああああああああああああああああああああああああああ
가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가가
</code></pre>
<p>Unfortunately, the CJK font I used has narrower Hangul than other full-width CJK
characters, so this is still not perfect—the solution would be to specify a
Hangul specific font and scaling factor—but good enough for me.</p>
<p>It took me quite some effort to fix what may seem like a minor annoyance, but at
least Emacs did offer the appropriate tools. By the way, I certainly wish I had
found <a href="https://www.emacswiki.org/emacs/FontSets">this article</a> on Emacs Wiki sooner, as it also provides a neat write up of
similar workarounds.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2018-06-24-fun-with-fonts-in-emacs/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2018-05-21-construction-finished/</id>
    <title type="html"><![CDATA[Construction Finished]]></title><updated>2018-05-21T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>After eight months, my blog have finally reached a place where I feel comfortable taking down the &quot;under heavy construction&quot; notice on my home page. In stead of out right deleting the site road map though, I'm stashing it into a blog post.</p>
<h2>Site Road Map</h2>
<ul>
<li>☑ <del>Find new hosting location.</del> Currently using DigitalOcean.</li>
<li>☑ Install Arch Linux on server.</li>
<li>☑ <del>Search for WP replacement.</del> Hugo is pretty good.</li>
<li>☑ <del>Find a suitable theme.</del> Currently using <code>hugo-xmin</code> , may consider forking it and write my own ( <code>soresu</code> ).</li>
<li>☑ Server side config, like <code>post-receive</code> for git auto deploy.</li>
<li>☑ Language switcher that does more than redirecting to home page.</li>
<li>☑ Enable Disqus.</li>
<li>☑ Support \(\LaTeX\) expressions via <del>MathJax</del> KaTeX.</li>
<li>☑ Copy-paste fixed page contents from old site (and translate them).</li>
<li>☑ Enable https.</li>
<li>☑ Backup old WP site.</li>
<li>☑ Transfer domain to Google Domains and ensure DNS works as intended.</li>
<li>☑ Find out how to write with <code>org-mode</code> or R markdown.</li>
<li>☑ Configure multilingual support, including footer text, title, etc.</li>
<li>☑ Find out how to make <code>emacs</code> work with <code>fcitx</code> .</li>
<li>☑ Use <del>Google's Noto Sans font</del> Oxygen Sans and <del>Source Code Pro</del> Iosevka for code.</li>
<li>☑ Find a suitable icon/favicon.</li>
<li>☑ Improve templates for posts to display tags and categories.</li>
<li>☑ Cosmetic changes, i.e. no underlines for hyperlinks.</li>
<li>☑ Deal with some nuances in using <code>org-mode</code> with <code>hugo</code> , like how to get syntax highlighting to work properly.</li>
<li>☑ Host my own email.</li>
<li>☑ Customize <code>hugo new</code> to make it more useful, i.e. create multilingual versions directly.</li>
<li>☑ Self-host commenting system as a replacement of Disqus.</li>
<li>☑ Use Let's Encrypt's wildcard certificate.</li>
<li>☑ Restore/rewrite and translate some of the more valuable old posts.</li>
</ul>
<h2>What's on Home Page Now?</h2>
<p>I already have an about page and a contact page for whatever I think people might be interested in knowing about myself, so I have no clue what I should put on home page. Since I found the old site road map to be a great way of reminding myself the stuffs I need to get done, I'll replace the road map with another to-do list: my goals for 2018. I am definitely not the most motivated kind of person, but seeing an unfinished to-do list every once in a while does get on my nerves. Let's see how well this is gonna work.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2018-05-21-construction-finished/"/>
  </entry>
  
  <entry>
    <id>https://www.shimmy1996.com/en/posts/2018-03-18-my-keyboards-2018-edition/</id>
    <title type="html"><![CDATA[My Keyboards 2018 Edition]]></title><updated>2018-03-17T00:00:00&#43;00:00</updated>
    <content type="html"><![CDATA[<p>As part of my effort to tick off the last remaining item on my site roadmap, I read through some old keyboard-related posts from my WordPress blog and decided to give them an uplift to include more recent experiments.</p>
<h2>The First Crispy Clack</h2>
<p>My very first mechanical keyboard is a WASD v2 104 key with Cherry MX Blue switches that I got in 2014. I picked WASD mainly because of their keyboards' minimal look and keycap customization options. I also got my first 60% in 2014, a Poker II with Cherry MX Brown. Switch selection were more limited back then, seemingly because of potential issues with Cherry's patent. Of course, switch choices is only limited if we restrict ourselves to Cherry MX compatibles, but most alternatives (Matias, Topre, buckling spring to name a few) were even harder to come by in an commonly available package that I liked.</p>
<p>A GH60 based 60% that I frankensteined together became my main keyboard at first. I used Cherry MX Clear switches with 62g springs (ErgoClear) on them, mostly for the fun factor instead of preference. I also found myself tinkering with the layout a lot more often than when I had the Poker II. As great as Poker II's built-in macros mapping sounds, I could never remember all the steps without taking a moment to peruse the manual. I also found myself setting macros up and yet completely forget about them ever since. With GH60's firmware, at the very least I have the configuration files to remind me of the new bindings I set up. Even with this shiny new toy though, my early experiments with keyboard layouts still had only limited success. The layout of a 60% is too standard in my opinion to justify significant changes (while maintaining QWERTY layout), i.e. there isn't really a good location to move Enter to. The few tweaks I ended up making were numpad/function key mapping and swapping out Caps Lock for Control, which at best makes my GH60 on par with any random keyboard with <a href="https://www.x.org/wiki/XKB/">xkb</a>.</p>
<p>On a side note, I once aspired to collect keyboards of all form factors, but soon discovered it to be a highly impractical and expansive exercise. Thus far among the more common layouts, I either owned or tried 104 key, 96 key, 87 key, 75 key, 60 key, and 40 key keyboards. Majority of these differs very little experience wise for me, except for 60% or 40%, where a bit of creativity is required to fit all the desired keys.</p>
<h2>ErgoDox and Planck</h2>
<p>The first keyboard ever to trigger me to give deeper thoughts into my keyboard layout is the ErgoDox. The ErgoDox boasts a layout drastically different from traditional keyboards, and because of this, offers great flexibility over key placements: I can immediately spot seven sensible locations for the Enter key (original pinky location, four 2u keys at the thumb clusters and the lower two 1.5u vertical keys in the center). I've been using ErgoDox almost exclusively since 2015, and have grown to like it even more as I started using Emacs - having access to both Control and Alt/Meta key on the home row just feels awesome.</p>
<figure>
<img alt="" src="/img/posts/2018/my-keyboards-2018-edition-01.png"/><figcaption>My ErgoDox Base Layer Layout</figcaption></figure>


<p>I still feel I am under-utilizing the keyboard's capabilities though. As you might tell, I don't know what to do with some of the thumb cluster keys. I currently have three extra layers set up: one for function keys, one for numpad, and another for a modified Dvorak layout. I haven't spend too much time on the Dvorak layer yet, but I am curious about potential benefits of decreased finger motion. Speaking of ergonomics, a perhaps uninteded benefit of ErgoDox's design is that it frees up the center of my desk, so that I can still read and write normally without a super deep desk.</p>
<figure>
<img alt="" src="/img/posts/2018/my-keyboards-2018-edition-02.png"/><figcaption>My ErgoDox Dvorak Layer Layout</figcaption></figure>


<p>Planck is another keyboard that I've taken some thoughts designing layout for. It is pretty surprising what a 40% board is actually capable of. However, using Planck is a lot less comfortable just because of how small it is - ErgoDox on the other hand allows me to rest my arms in more natural positions, instead of cramming my hands together. That being said, I would imagine a Let's Split - basically a Planck split in halves - to work fairly well.</p>
<figure>
<img alt="" src="/img/posts/2018/my-keyboards-2018-edition-03.png"/><figcaption>My Planck Layout</figcaption></figure>


<h2>Keycap Craze</h2>
<p>Ever since I discovered Geekhack, I would routinely refresh the groupbuy or interest check section for new keycap sets that other users designed. I gradually went from sets with flashy colors to those with a more muted and uniform look. I also prefer uniform keycap profiles (like DSA) with text legends than those with height gradients and graphical legends, although I find it really hard to appreciate blank keycaps. Getting a full set of keycaps with matching legends for ErgoDox is certainly no easy task (unlike Planck which is almost entirely consisted of 1u keys), and all these quirks I have made keycap shopping increasingly difficult.</p>
<h2>My Own Keyboard/Layout</h2>
<p>I've thought about creating my own keyboard occasionally. As perfect as ErgoDox
may seem, it is somewhat bulky, and I find the thumb cluster a bit hard to
reach. For quite some time I used <kbd>C-Home</kbd> and <kbd>C-End</kbd> to move to top/bottom of a
file in Emacs, and that caused pain in my thumb joint as I need to stretch hard
to reach both keys (that went away when I found <kbd>M-&lt;</kbd> and <kbd>M-&gt;</kbd> though). A slim down version of ErgoDox with more compact thumb clusters might just be the perfect keyboard. By the way, I have never before find wireless keyboard necessary in any way, but since ErgoDox features a split design, a wireless version of it can be used while lying down Nintendo-Switch-style, which would be pretty awesome.</p>
<p>Since I started using Emacs as my main editor, I've been taking statistics of my key-presses with <code>keyfreq</code>. When I have gathered enough data, I might look into customizing my layout even further to suit my needs.</p>
<h2>Pixel Art</h2>
<p>Like many Geekhackers out there, I made a pixel art of my keyboards and used it as my Geekhack signature.</p>
<figure>
<img alt="" src="/img/posts/2018/my-keyboards-2018-edition-04.png"/><figcaption>Pixel Art of My Keyboards I, 2015</figcaption></figure>


<figure>
<img alt="" src="/img/posts/2018/my-keyboards-2018-edition-05.png"/><figcaption>Pixel Art of My Keyboards II, 2015</figcaption></figure>


<p>Drawing pixel art for keyboard is a fairly interesting exercise, since it is impossible to get the ratios exactly right, I needed to strike a balance between accuracy and simplicity. I will give this a long due update when I have time.</p>
<h2>Comments</h2>






<p>No comments yet.</p>


]]></content>
    <link href="https://www.shimmy1996.com/en/posts/2018-03-18-my-keyboards-2018-edition/"/>
  </entry>
  
</feed>
