Smokes your problems, coughs fresh air.

Author: Rowan Rodrik (Page 1 of 25)

Rowan is mainly a writer. This blog here is a dumping ground for miscellaneous stuff that he just needs to get out of his head. He is way more passionate about the subjects he writes about on Sapiens Habitat: the connections between humans, each other, and to nature, including their human nature.

WordPress for my forest vacation home in Norg

For a decade and a half, my uncle had been maintaining the website for our vacation home in the forests of Drenthe in Dreamweaver. This worked fine, except that:

  1. it didn’t allow me to edit and add content and photos simultaneously;
  2. the website had started to look and feel dated;
  3. it wasn’t mobile-ready; and
  4. all this was affecting its ranking in Google.

That’s why I had been having a new WordPress website in the pipeline since forever. However, in true 80/20 fashion, I was postponing the final steps of copying over the last bits of content and the training of my uncle to edit the website in WordPress instead of in Dreamweaver.

Why WordPress?

The last few websites I built I built myself from scratch, like in the good old days, using a simple static site generation pipeline (basically a fancy Makefile). The reasoning is that comments are too much hassle to moderate anyway, and comments and trackbacks are what WordPress offered me. Apart from that I very much prefer authoring in vim.

But that’s me. Most people, my uncle included, are way more comfortable with WYSIWYG editors—in other words: WordPress its Gutenberg editor.

A mature developer has to be able to sidestep his preferences to deliver something that’s best for the “customer”. (Indeed this post will be me bragging of how mature a developer I am. I do turn 40 tomorrow after all.)

My main “design” goal was that I didn’t want to change too much at once. The site structure and site content had to remain mostly identical, so that we would have fewer points of discussion to surmount before going live.

At the same time, I did want to clean up the content and the formatting. The old website had a distinct lack of bullets, formal headings, use of bold text, etc. (No, I don’t have pictures.) That made the text a bit difficult to parse, especially when the visitor—a potential tenant of our forest home—was just trying to find a specific piece of information at a glance.

Proper formatting makes long page much more accessible.

The new website is not fancy. The theme is just one of WordPress its default themes, and I ended up not even using a graphical header to get the first version online. Important to me is that I can now easily add blog posts (like about a pretty yellow flower that I got to grow there abundantly). Also, whenever now I want to edit some text in one of the informational pages, I can.

The “page with booking information and booking availability gave me the most headaches and demanded the most from my maturity. The first thing to swipe off the table was the use of any type of booking plugin. This turned out to be the most important decision (and a very good call!). The old website (with light-yellow background) had one of those old-fashioned tables with big-ridged borders around every cell. I wanted to at least make this table look good and modern.

I gave the booking periods table a sticky header. That was something at least. What I did not do was giving the individual cells a border. But, as much as he tried liking it, my uncle hated that incarnation of the table. So I put back in some cell borders, which I had already done in the print CSS version.

Then there was the issue that my uncle had gotten used to printing out the booking schedule, and it now spanned a number of pages. Thus I did a lot of tinkering in the print CSS to make it all fit (and to make the table header repeat, just in case). And it turned that both cleaning ladies didn’t like the spacious table layout on the screen either. I had altogether forgot about them as consumers of the table, focusing instead on potential tenants. More squeezing followed, until everybody was happy, and I was … relieved.

The booking schedule of our vacation home in Norg, Drenthe, the Netherlands.

It deserves mentioning that I did all these CSS within WordPress its theme customizer. Normally, I would have preferred to use a child theme for this, but it felt to early to start a child-theme, as long as I haven’t fully committed to a particular parent theme. Also, the CSS for that booking schedule table is some of the worst you might have seen. After all, the HTML is not semantic at all. It’s not like I’m going to train my uncle to specify class names on each cell. Without proper classification, I had to use implicit classification, ending up with selectors such as the td:nth-child(4):not([colspan]):not(:empty) selector that I use to make the background of occupied periods black, but only if they are not some special multi-column note. To scare the CSS wizards out there, here’s the current CSS for the table:

@media screen {
table.wp-block-advgb-table.advgb-table-frontend {
	border-width: 0;
	border-spacing: 0;
	border-collapse: separate;
	table-layout: auto;
}
.wp-block-advgb-table > thead > tr {
	position: sticky;
	top: 0;
}
.wp-block-advgb-table > thead > tr > th {
	background-color: white;
	box-sizing: border-box;
	border-top: 1px solid black;
	border-left: none;
	border-right: 1px solid black;
	border-bottom: 2px solid black;
	padding: 2px 4px;
}
.wp-block-advgb-table > thead > tr > th {
	border-left: 1px solid black;
}
.wp-block-advgb-table > tbody > tr > td {
  border-top: none;
	border-left: none;
	border-right: 1px solid black;
	border-bottom: 1px solid black;
	padding: 2px 4px;
}
.wp-block-advgb-table > tbody > tr > td:first-child {
  border-left: 1px solid black;
}
.wp-block-advgb-table > tbody > tr > td:nth-child(4):not([colspan]) {
	width: 2em;
	font-size: 70%;
}
	.wp-block-advgb-table > tbody > tr > td:nth-child(4):not([colspan]):not(:empty) {
		background-color: black;
		color: white;
	}
.wp-block-advgb-table > tbody > tr > td[rowspan] {
}
}
@media screen and (max-width: 1000px) {
	table.wp-block-advgb-table.advgb-table-frontend {
		position: relative;
		left: -7.6923%;
		max-width: none;
	  font-size: 70%;
	}
	.wp-block-advgb-table > thead > tr > th, .wp-block-advgb-table > tbody > tr > td {
		padding: 0px 1px;
	}
	.wp-block-advgb-table > thead > tr > th {
		overflow-wrap: break-word;
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(3) {
		font-size: 0; /* ugly hack to hide regular text. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(3):after {
		content: 'Prijs';
		font-size: 12px; /* ugly override because percentage would be percentage of 0. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(4) {
		font-size: 0; /* ugly hack to hide regular text. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(4):after {
		content: 'Vrij?';
		font-size: 12px; /* ugly override because percentage would be percentage of 0. */
	}
	.wp-block-advgb-table > tbody > tr > td:first-child {
		min-width: 8ch;
		max-width: 12ch;
	}
	.wp-block-advgb-table > tbody > tr > td:nth-child(2) {
		word-spacing: -.2ch;
		min-width: 15ch;
		max-width: 20ch;
	}
}
@media screen and (min-width: 1001px) {	 .wp-block-advgb-table > thead > tr {
		top: 21px;  /* Space from the theme that somehow has a weird z-indexy effect. */
	}
	body.admin-bar .wp-block-advgb-table > thead > tr {
		top: calc(31px + 21px);
	}
	.wp-block-advgb-table > tbody > tr > td:nth-child(2) {
		white-space: nowrap;
		max-width: 20em;
  }
}
/* filter bypass hack */@media print {
  .wp-block-advgb-table.advgb-table-frontend {
		width: 100%;
	  border: 1pt solid black important!;
	  border-spacing: 0;
		border-collapse: collapse;
		font-size: 8pt;
		table-layout: auto;
  }
	.wp-block-advgb-table > thead > tr > th {
		border: 2pt solid black !important;
		padding: 2pt 4pt;
	}
	table.wp-block-advgb-table > tbody > tr > td {
		border: 1pt solid black !important;
		padding: 1pt 4pt;
	}
	.wp-block-advgb-table > tbody > tr > td:first-child {
		white-space: nowrap;
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(3) {
		font-size: 0; /* ugly hack to hide regular text. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(3):after {
		content: 'Prijs';
		font-size: 12px; /* ugly override because percentage would be percentage of 0. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(4) {
		font-size: 0; /* ugly hack to hide regular text. */
	}
	.wp-block-advgb-table > thead > tr > th:nth-child(4):after {
		content: 'Vrij?';
		font-size: 12px; /* ugly override because percentage would be percentage of 0. */
	}
	.wp-block-advgb-table > tbody > tr > td:nth-child(3) {
		max-width: 8ch;
	}
}

Which reminds me of something quite terrible about Gutenberg. Its table block doesn’t support merged cells, like—what the fuck?—why is this not considered a priority? Fucking hipsters and their having to reinvent the wheel every year and taking years to put all the spokes back into place. The “solution” was to install a plugin—PublishPress Blocks—that among other blocks that I don’t need (and could thankfully turn off) an “Advanced Table Block” that does support cell merging, but with such nasty bugs that it’s really hard to train my uncle to work around them. Sadly, there has been no activity yet to fix either one of them.

That’s it. This project didn’t make me more of a WordPress fan. (I’m no hater either. I think that WordPress its UX, specifically, has long been excellent, and exemplary in its non-nerdiness, quite the contrast with other popular open source CMSs.) But I chose the right tool for the right job and managed to make myself and the other “customers” happy. Since the go-live, I’ve added a number of blog posts already, and it’s great fun to now be able to contribute to this website’s content.


Did this get you interested? Feel free to book a stay in our idyllic vacation home in Norg, Drenthe, the Netherlands

Rapidly firing myself in the foot with C pointers

Now that I am dedicated to becoming a somewhat decent C programmer, I need to master pointers. Last week, I leveled up in my pointer usage by debugging a particularly nasty segfault. It took the help of gdb (the GNU Project Debugger) for me to notice that my segfault was accompanied by very weird values for some increment counters, while the pointer involved was a char* pointer, not a pointer to an int.

GDB

First, some notes on the GNU Project Debugger: it’s excellent! And … it’s easy to use. I have no idea why looong ago, when as a budding programmer I was trying to use it, I had so much trouble using it that it stuck into my memory as a very tough tool to use. Well, this is not the same brain anymore, so time to get rid of all these printf() statements everywhere (that I wouldn’t dare use in a programming language that I do have some fluency in, mind you!) [lines of shame: L45, L100, L101, L119 ].

With the help of gdb xjot-to-xml (and then, from within GDB, run < my-test-file.xjot), I noticed that some of the ints I used to track byte, line and column positiion had ridiculously high values for the input line, especially since I was pretty sure that my program crashed already on the first character.

In GDB, such things are easy to find out: you can very simply set a breakpoint anywhere:

break 109
run < tests/element-with-inline-content.xjot
Starting program: /home/bigsmoke/git/xjot/xjot-to-xml < tests/element-with-inline-content.xml
a
b

Breakpoint 1, _xjot_to_xml_with_buf (in_fd=537542260, out_fd=1852140901, buf=0x6c652d746f6f723c, buf_size=1024)
    at xjot_to_xml.c:109
109                 byte = ((char*)buf)[0];

From there, after hitting the breakpoint, I can check the content of the variable n that holds the number of bytes read by read() into buf.

print n
$1 = 130

So, the read() function had read 130 bytes into the buffer. Which makes sense, because element-with-inline-content.xjot was 128 characters, and the buffer, at 1024 bytes, is more than sufficient to hold it all.

But, then line_no and col_no variables:

(gdb) print line_no
$2 = 1702129263
(gdb) print col_no
$4 = 1092645999

It took me a while to realize that this must have been due to a buffer overrun. Finally, I noticed that I was feeding the address of the buf pointer to read() instead of the value of the pointer.

(I only just managed to fix it before Wiebe, out of curiosity to my C learning project, glanced at my code and immediately spotted the bug.)

The value of pointers

C is a typed language, but that doesn't mean that you cannot still very easily shoot yourself in the foot with types, and, this being C, it means that it's easiest to shoot yourself in the foot with the difference between pointers and non-pointers.

I initialized my buffer as a plain char array of size XJOT_TO_XML_BUFFER_SIZE_IN_BYTES. Then, the address of that array is passed to the _xjot_to_xml_with_buf() function. This function expects a buf parameter of type void*. (void* pointers can point to addresses of any type; I picked this “type”, because read() wants its buffer argument to be of that type.)

What went wrong is that I then took the address of void* buf, which is already a pointer. That is to say: the value of buf is the address of buffer which I passed to _xjot_to_xml_with_buf() from xjot_to_xml().

When I then took the address of the void* buf variable itself, and passed it to read(), read() started overwriting the memory in the stack starting at that address, thus garbling the values of line_no and col_no in the process.

The take-home message is: pointers are extremely useful, once you develop an intuition of what they're pointing at. Until that time, you must keep shooting yourself in the foot, because errors are, as Huberman says, the thing that triggers neuroplasticity.

WW challenge 1: learning better C by working on XJot

Since the beginning of this month (October 2021), I become officially jobless, after 6 years at YTEC. That’s not so much of a problem for a software developer in 2021—especially one in the Dutch IT industry, where there has been an enormous shortage of skilled developers for years. However… I don’t (yet) want a new job as a software developer, because: in the programming food pyramid, I’m a mere scripter. That is, the language in which I’m most proficient are all very high-level languages: Python, PHP, XSLT, Bash, JavaScript, Ruby, C# (in order of decreasing (recency of) experience. I have never mastered a so-called systems language: C, C++, Rust.

Now, because of the circumstances in which YTEC and I decided to terminate the contract, I am entitled to government support until I find a new job. During my last job, I’ve learned a lot, but almost all I learned made me even more high-level and business-leaning than I already was. I’ve turned into some sort of automation & integration consultant / business analyst / project manager. And, yes, I’ve sharpened some of my code organization, automated testing skills as well. Plus I now know how to do proper monitoring. All very nice and dandy. But, what I’m still missing are ① hardcore, more low-level technical skills, as well as ② front-end, more UX-oriented skills. Only with some of those skills under my belt will I be able to do the jobs I really want to do—jobs that involve ① code that has to actually work efficient on the hardware level—i.e., code that doesn’t eat up all the hardware resources and suck your battery (or your “green” power net) empty; and I’m interested in making (website) application actually pleasant (and accessible!) to use.

If I start applying for something resembling my previous job, I will surely find something soon enough. However, first I am to capture these new skills, if I also wish to continue to grow my skill-level, my self-respect, as well as my earning (and thus tax paying) potential. Hence, the WW challenge. WW is the abbreviation for Wet Werkeloosheid, a type of welfare that Dutchies such as myself get when they temporarily are without job, provided that you were either ⓐ fired or ⓑ went away in “mutual understanding” (as I was). If ⓒ you simply quit, you don’t have the right to WW (but there are other fallbacks in the welfare state of the NL).

Anyways, every month, I have to provide the UWV—the governmental organization overseeing people in the WW—with evidence of my job-seeking activities. Since I decided that I want to deepen my knowledge instead of jumping right back into the pool of IT minions, I will set myself challenges that require the new skills I desire.

My first goal is to become more comfortable with the C programming language. I have some experience with C, but my skill level is rudimentary at best. My most recent attempt to become more fluent in C was that I participated in the 2020 Advent of Code challenge. I didn’t finish that attempt, because, really, I’m a bread programmer. Meaning: before or after a 8+-hour day at the office, I have very little desire to spend my free time doing even more programming. To stay sane (and steer clear of burnout), that time is much-needed for non-digital activities in social space, in nature, and by inhabiting my physical body.

So now I do have time and energy to learn some new skills that really require sustained focus over longer periods of time to acquire. On the systems programming language level, besides C, I’m also interested in familiarizing myself with C++ and Rust. And it is a well-known facts that C knowledge transfers very well to these two languages.

Okay, instead of doing silly Christmas puzzles, this time I’ve resumed my practice by writing an actual program in C that is useful to me: xjot-to-xml. It will be a utility to convert XJot documents to regular XML. XJot is an abbreviated notation for XML, to make it more pleasant to author XML documents—especially articles and books.

Exhaling on YouTube

I’ve created a YouTube channel separate from my private account and branded it “BigSmoke”. The channel’s purpose is to breathe some fresh air into some online discussions that I follow(ed). Actually, the content is the sort of content that I used to want to put more of on BigSmoke, but which I now found to be better suited for long-form discussions than for laying down my views from some ivory tower.

The first three puffs of fresh air feature my brother Jorrit:

  1. In the first puff, recorded shortly after he (and me too for the nth time) quit caffeine. The cue for me to want to do that podcast (and stop putting off this creative endeavor indefinitely) was when he told me that quitting caffeine took a heavier toll on his body and mind than did quitting smoking and drinking at the same time a few months earlier. I though that that was a great story to put into perspective that yes, caffeine really is a serious, addictive drug that can interfere not just with your dreams but actually with your dreaming!

    Production-wise, the worst part of this first podcast is that my face is tiny, because I used Google Meet and neglected to install a browser extension to undo its limited layout support or to even just click my own face when I was talking.

  2. The 2nd puff of fresh air centered around meaning. Without the caffeine in my system, I was having more trouble than usual to find the meaning in my “mostly for money” job that’s really doing nothing to make the world a better, more beautiful place. Also, my self-discipline had declined to a long-time, leaving too little time and energy around work-work for more creative meaningful endeavors (such as doing podcasts).

    There was a bit of a production problem with my 2nd puff of fresh air. The one published is a re-iteration of the same discussion we had some days before that but for which I recorded an empty audio stream of my docking station’s unconnected microphone input instead of the audio stream of the laptop port in which my microphone was actually plugged in. At least I did find Jitsi, which allowed easier side-to-side video frames.

  3. In the 3rd puff of fresh air, we zoom in on some topics that we brushed past in the 2nd without really touching. I talk about my pain and shame of being mostly just another cooperating cog in the machine that is wreaking planetary-scale havoc and that is grinding ecosystems all over the world out of existence. Jorrit’s focus is on the harm that’s done to human happiness by our culture (and also the “away with us” culture of which I’m sometimes a part). We try to make our visions on self-discipline collide, but we end up finding more agreement than we expect. Most of our disagreement turns out to be superficially bound to societal structures which we both would rather see transformed than preserved in their current sickly form.

    We switched back to Google Meet for this 3rd recorded conversation, because the free Jitsi server we used was performing shakily that day.

Icinga 2 dependencies, downtimes and host/service unreachability

There are a few gotchas you have to be aware of when working with Icinga 2 dependencies and downtimes.

Gotcha 1a: Downtimes and dependencies are independent of each other

Intuitively, I had expected downtime to always traverse down the parent-child dependency tree. It doesn’t. It’s opt-in. The ScheduledDowntime.child_options attribute can be set to DowntimeTriggeredChildren or DowntimeNonTriggeredChildren to make it so. (These options are called “schedule triggered downtime for all child hosts” and “schedule non-triggered downtime for all child hosts”, respectively, in Icingaweb2.) With one of these options set, runtime downtime objects will also be created for (grand)child hosts (but not services; see Gotcha 1b).

Gotcha 1b: Downtimes never traverse to child hosts’ services

In Icingaweb2, when you’re scheduling downtime for a host and choose to also “schedule (non-)triggered downtime for all child hosts”, this excludes services on those child hosts. The “All Services” toggle applies only to the current host. There is an (open, as of May 5 2020) Icingaweb 2 feature request to address this. So far, the only attempt to implement the Icinga 2 side of this was shot down by the Icinga maintainers on the basis of making things too complex. @dnsmichi would prefer rethinking the current options.

If you want to make it easy to schedule downtime for dependency chain involving numerous hosts and/or services, I recommend using a single HostGroup and/or ServiceGroup to make it easy to Shift-select all dependent objects in Icingaweb2 and schedule the downtime in batch. In the worst case you than have to select all objects in each group separately to plan the bulk downtime twice. In some cases, just a HostGroup may do (because in Icingaweb2 you can include downtime for all of a hosts services), but this won’t be sufficient if you have services that depend directly on other services rather than hosts.

From the configuration, it’s not at all possible to include all of a host’s services in the ScheduledDowntime objects. But, here it’s not really an issue, because it’s enough to abstract your downtime particularities into a template and apply that to both the Host and the Service objects that are to be affected.

Gotcha 2a: Child hosts will (almost) never become UNREACHABLE when the parent host fails and Dependency.disable_checks == true

object Host "A" {
}

object Host "B" {
}

object Dependency "B-needs-A" {
  parent_host_name = "A"
  child_host_name = "B"
  disable_notifications = true
  disable_checks = true
}

In this example, when host A goes down, the B-needs-A dependency is activated and notifications about B are suppressed (because disable_notifications == True). However, because checks are also disabled, host B never becomes unreachable, unless if you manually/explicitly trigger a check via the Icingaweb2 interface.

The means that any service on the child host (B in this example) will still generate notifications, because the (default) host-service dependencies will not be activated until the child host becomes UNREACHABLE. (Of course, any other non-UP state of the child host would also activate the the host-service dependencies.) The same goes for grandchild hosts.

So, if you want a child host to become UNREACHABLE when the parent host fails, Dependency.disable_checks must be false. Only as soon as the check fails will the host become UNREACHABLE.

Gotcha 2b: Grandchild dependencies don’t become active until the child/parent in between them fails

Dependencies are always between a parent and a child. Icinga never traverses further along the tree to determine that a grandchild should be UNREACHABLE rather than DOWN.

Take the following setup:

object Host "A" {
}

object Host "B" {
}

object Host "C" {
}

object Dependency "B-needs-A" {
  parent_host_name = "A"
  child_host_name = "B"
  disable_notifications = true
}

object Dependency "C-needs-B" {
  parent_host_name = "B"
  child_host_name = "C"
  disable_notifications = true
}

If host A fails, host B doesn’t become UNREACHABLE until its check_command returns a not-OK status. The same goes for host B and C. And, despite disable_notifications = true, problems with host C will generate notifications as long as host B is Up. Therefore, to avoid needless notifications, you must always make sure that the hosts go down in the order of the dependency chain. You can do this by playing with check_interval, max_check_attempts, and retry_interval. And, make sure that disable_checks is always false for any intermediate host or service in the dependency chain!

New year’s resolutions

I updated my personal homepage at the beginning of the new year. Some of the changes were long overdue, like my university student status and the number of diving licenses. But, there were other changes that arose from a more recent insight: that, if I am to reach my goals, I need a plan. A bad plan is better than no plan. And too many goals are as useless as no goals.

Here is my plan as I published it in Januari in verbatim:

This has a plan: to become a happy little 🐷. His tech job at YTEC already keeps him warm and his belly full. (His family 💰 and the 🇳🇱 welfare state helped him along the way.) 🐷 2 + 2 little 🐱🐱 + some 🌿🌴 make 🏠 🏠. And, with all that comfort, ❄️🚿🚿, योगः, 中国武术 and มวยไทย keep the 🐷 from getting .

Homo sapiens is more homonid than sapiens, so the most sapient thing for this H. to do is to take good care of his 🐒-mind. This 🐒 wants (☑), and is very particular about who he keeps ✓ed in this —a ♀ who breaks out of the stupid , and climbs on top of it to 👙💃.

Outside this most private of private bubbles, there are friends and family on call to put into perspective the tribulations that flow from the oft-inflated need to earn societal respect and dominate other ♂♂. At his most ☮️ful, his work and hobbies (i.e., kickboxing & diving) afford him plenty of opportunity to ✓ this ☐, but sometimes he dreams of wider recognition, especially at times of narrow self-respect.

He used to want to grow 📈 indiscriminately in all directions at once (like a ), dreaming of universal admiration and acceptance, being unable to accept—let alone, love—himself. Having since undergone therapy, he can now make the 🐒 feel sufficiently secure to focus on more forms of self-improvement, as long as he pays conscious attention to his need for ♡.

2018’s goal is for him to learn to respect himself, which requires him to ⒜ be deserving of respect, and ⒝ to give himself credit when credit is due. To combat self-sabotage and improve his discipline, he has given himself 3 rules: ① consumption is production; ② the training schedule is sacred; and ③ meditate daily. This may sound harsh, and it is, if he will needlessly beat himself up over any failure to comply. These rules are fairly constant, but there’s also a maximum of 4 assignments, which will change when they’re finished or given up; currently, these 4 are: ⓐ publish 7 6 articles on Sapiens Habitat about PPPermaculture; ⓑ create an Angel prototype and share it with colleagues; ⓒ finish opschoot‘s Mint upgrade; and ⓓ remember 7 new lucid dreams.

Note that there’s no need to work on these assignments; they don’t have a deadline. Deadlines abound in the day job. It’s all about the rule of ④: no more than 4 private projects at the time, to avoid all that free energy from being scattered with purpose nor satisfaction.

Rule ①: consumption is production

My adherence to rule ① has been decent in the beginning but is somewhat mixed at the moment: I’ve tweeted most times that I caught myself scrolling Twitter, but I haven’t written something—even if it’s just a single line—every time I’ve been mindlessly losing myself in the newspaper. Definitely, I need to continue to be vigilant if I want to rid myself of my habit to numb myself with mindless information consumption.

Speaking of production: For some time, I’ve waited with writing more about Annemarie, Laurelin and Nils their permaculture adventures in Portugal ⓐ while making some adjustments to the layout of sapienshabitat.com. But, I am now nicely progressing ⓐ with the second article in the series on PPPermaculture: Tree Nurse Nils.

Rule ②: the training schedule is sacred

Rule ② has been somewhat more sacred to me than rule ①, and I’m proud to say that I’ve persisted through quite a bit of boredom. Interestingly, so far, I’ve found adhering to my training schedule easier than making changes to it. The only changes I made were rather minor.

Last week, I decided that I want to pursue some competitive kickboxing bouts. But, that’ll have to wait until I finished one of ⓐ through ⓓ. Otherwise, I’d be violating the rule of ④.

Rule ③: meditate daily

Being mindful instead of running around like a caffeinated chicken is still challenging, in so far as that I don’t feel that I’ve further progressed towards being sufficiently at ease during the day that it has improved my dream content. My dream recall, however, has kind of improved.

There have been days on which I violated rule ③, and these shouldn’t be allowed to multiple. But, it’s also important to remember the spirit of the rule rather than the letter. And that spirit would soar as soon as ⓓ I will have the first of those 7 new lucid dreams.

The rule of ④

The rule of ④ is great. It has already protected me from undertaking ⓔ and ⓕ before finishing ⓐ through ⓓ. It also has a motivating quality, because I’m really itching (literally) to try ⓔ a ketogenic diet again.

Rule-adherence

Rule ① Rule ② Rule ③
Week Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
17
18
19
20 ½ ½ ½ ½ ½ ½ ½
21 I can not nor want to remember all this shit throughout the week.

Status of auto-assignemts

ⓐ published 5 of first 7 articles about PPPermaculture on sapienshabitat.com
ⓑ create an Angel prototype and share it with colleagues
ⓒ finished opschoot‘s Mint upgrade ☑ on Feb. 22 2018
ⓓ remembered 7 of 7 new lucid dreams ☑ on Jun. 8 2018
ⓔ tried a ketogenic diet again for a week ☑ from Feb. 12–18 2018
ⓕ fight a kickboxing match started in the beginning Mar. 2018,
officially paused at the end of Apr.
ⓖ publish opinion piece about the annual winter-time population crash in the Oostvaardersplassen ☑ on Mar. 14 2018
ⓗ submit an entry for the NRC essay writing competition started on May 26 2018
☑ on Jun. 25 2018
ⓘ something something Magento started on Jun. 8 2018
ⓙ reviewing Myrna her open letter to the Dutch national Health Council embarked on Jun 25. 2018
☑ on Jul. 1 2018
ⓚ sand and paint my bicycle cart waiting for a slot
ⓛ read Annemarie her fairy tale
ⓜ get Hardwood wikis back online and put them up for sale waiting for a slot
ⓝ redesign www.bigsmoke.us accidentally started on Aug. 27

Worldwide Wilderness

A long, long time ago, when I still thought that Drupal would turn out be a good choice for a new website project, I founded www.worldwidewilderness.com. Well, actually I found www.world-wide-wilderness.com, because I didn’t know that ‘worldwide’ is spelled as one word. And, then I found www.worldwide-wilderness.com, because I thought that hyphens in domain names are really cool—so cool, in fact, that I was on the Dashing Domains fanlist for years. Apart from all the hyphens, I still like the Worldwide Wilderness, so much so that I’ve recently been considering building an interactive map of all the remaining wilderness areas in the world under the brand.

Because of Rule 4—the rule of 4—I will not work on this idea any time soon, and the best way to get an idea out of my head is to put it on paper (of sorts): the idea is to have an interactive map of the world in which wilderness areas are marked according to the threats and protections that are present. Vetted specialist users should be able to amend this information and every site should include information about all the actions that concerned visitors can take to improve the protection of the wildernesses.

For archival purposes, below is the blurb I used to describe the project on www.bigsmoke.us:

I’m a wild ape and civilization is a bad joke I didn’t get the punchline of. Somehow I’m supposed to be excited about all the freedom that my ancestors didn’t have because they were too busy staying alive. I have to be grateful for all the stuff that I can fill my life with in the absence of the struggle for survival. Instead of hunger and hungry predators we have gotten a pack of paper predators chasing us through life. The whole pack is being digitized so that we can run even faster.

Constantly, I feel threatened, because I am supposed to feel threatened for things that are simply not threatening, no matter how you turn them around or blow them out of proportion. As a social animal, nog taking these “threats” serious does feel seriously threatening to my social status. But I’m taking my chances. Fuck you and your self-imposed cages! I do not agree to be lifestock. I claim the right to be the wild animal that I will be regardless of your (and my) attempts to control me.

Self-control is a delusion. Self-improvement is masturbation. Because who would be doing the controlling and who would be doing the improving? Not me, that’s for sure.

Writing bootable disk images (.iso, .img, etc.) to a USB stick from Windows

Because Windows doesn’t have dd, and I want to write the latest Mint LTS release to a USB task, I had to face the unpleasant task of finding a Windows tool to perform what’s a basic Unix operation. The good news is that I found one, and it’s open source: Win32 Disk Imager. It even has a version ≥ 1, titled: “Holy cow, we made a 1.0 Release”.

A screenshot of Win32 Disk Imager at work, writing Linux Mint 18.3 MATE 64bit to my SanDisk USB stick.

Win32 Disk Imager at work, writing Linux Mint 18.3 MATE 64bit to my SanDisk USB stick.

I found another open source tool, UNetbootin, but that tool didn’t recognize my non-MS-format formatted USB stick (which already tauted the installer for a previous Mint release).

In the end, Win32 Disk Imager also choked on the funky partition table left by the previous boot image, so I had to find out how reset the USB disk’s partition table in Windows:

C:\WINDOWS\system32>diskpart

Microsoft DiskPart version 10.0.16299.15

Copyright (C) Microsoft Corporation.
On computer: YTHINK

DISKPART> list disk

  Disk ###  Status         Size     Free     Dyn  Gpt
  --------  -------------  -------  -------  ---  ---
  Disk 0    Online          238 GB      0 B        *
  Disk 1    Online           29 GB    28 GB

DISKPART> select disk 1

Disk 1 is now the selected disk.

DISKPART> list partition

  Partition ###  Type              Size     Offset
  -------------  ----------------  -------  -------
  Partition 1    Primary           1706 MB  1024 KB
  Partition 2    Primary           2368 KB  1707 MB

DISKPART> select partition 2

Partition 2 is now the selected partition.

DISKPART> delete partition

DiskPart successfully deleted the selected partition.

DISKPART> select partition 0

The specified partition is not valid.
Please select a valid partition.

There is no partition selected.

DISKPART> select partition 1

Partition 1 is now the selected partition.

DISKPART> delete partition

DiskPart successfully deleted the selected partition.

DISKPART> create partition primary

DiskPart succeeded in creating the specified partition.

DISKPART> exit

Leaving DiskPart...

C:\WINDOWS\system32>

Web print is still shit, even for CSS2 print features

Having spent ten yours out of the loop, I had somehow expected browser makers to take some time out of their favorite hobby—moving knobs and settings around—to implement CSS printing support. I’m all for saving paper and all, but requiring me to pipe my HTML through LaTeX to produce halfway decent documents doesn’t feel very 2017ish to me. In 2007, it already didn’t even feel very 2007is to me.

I’m trying to make the articles on www.sapiensthabitat.com nicely printable. The good news is that I can finally style my headings so that they do not end up all alone on the bottom of a page. page-break-after: avoid is finally supported, except that it isn’t in Firefox. Well, I’m still happy. Back in 2007, only Opera supported this.

Next stop: I wanted to replace the standard header and footer slapped on the page with something nicer. It turned out that, yes, @page {} is supported now, which makes this rather easy:

@page {
 : 0;
}

Except, then I wanted to add the page number, preferrable in the form n/N to the footer, which turned out to be impossible.

Then, I thought: since my publication pipeline starts with Markdown, I might as well convert that to PDF through LaTeX and then hint to the browser to use the PDF version for printing:

<link rel="alternate" media="print" type="application/pdf" href="print.pdf" />

Never mind. Why did I even for one second think that this would be supported?

« Older posts

© 2022 BigSmoke

Theme by Anders NorenUp ↑