How to vote in the Madrid elections on 4 May 2021

I was originally going to post this on Twitter but their web UI only lets you prepare 25 tweets in a thread before posting. I’d rather not cut this one short, so here it is as a blog post. My goal here is to explain my thought process for deciding who to vote for, starting from the basis that my main goal is to prevent the (likely) outcome of Ayuso returning to power.

Ayuso became president in 2019 despite her party, the PP (Partido Popular), only securing 30 seats in the election, out of the 132 total seats in the Asamblea de Madrid. It was the PP’s worst performance ever in Madrid in their 26 years of uninterrupted government, coming as it did after a string of corruption scandals afflicting the party. This ultimately brought to an end the presidency of the leader of the PP at the national level, Mariano Rajoy, in 2018, via a motion of no confidence.

The PSOE (socialist) party had 37 seats in comparison, having won more votes than any other party by a large margin (28.67% of the vote compared with 16.69% for the PP), but couldn’t form a majority coalition government. Together with the two other parties on the left, they had 64 seats. On the right, Ayuso was able to form a majority in conjunction with the (only nominally) centrist Ciudadanos party, and the far-right Vox, totalling 68 seats in all. Now, if you like Ayuso or tend to vote to the right, I doubt a Twitter thread or a blog post is likely to change your mind, but I’m at least going to have a shot at explaining why I want to see her and the PP out the door.

Madrid has had right-wing governments continuously since about 1991. Decades of cutbacks and privatization have left public schools and hospitals in a sorry state. On the flip side, Madrid has become somewhat of a fiscal paradise for the rich, with many forms of taxation eliminated or reduced. Inequality is significant in Spain, and Madrid is no exception. If you’re a centrist who believes that an occasional political "changing of hands" from one party to another is a useful way to prevent the excesses of either side from playing out too far, then it is clearly time for a change in Madrid.

And if you’re consistently left-leaning, you’re horrified at the effects of sustained, regressive spending cuts, and can’t figure out why so many Madrileños seem so happy voting for politicians who very obviously represent the interests of only the richest sliver of society. Voting is optional in Spain, and the wealthier, right-leaning classes tend to vote much more actively, allowing them to have an outsized impact in the election results despite their status as a privileged minority. I guess the less wealthy classes have just lost faith in politicians and political parties in general, or they don’t believe that their vote can make a difference. Making matters worse, this year, left-leaning voters face an additional obstacle: Ayuso called the election to take place on a normal working Tuesday, which means that school classes are cancelled. If you don’t have a private nanny, or an idle family member to look after your kids in order for you to vote, voting in 2021 is going to be harder than ever. Postal voting is an option, but the window for that has now closed.

I explained my overall political stance in a post a while back, but the "TL;DR" is basically that I am left-libertarian motivated by a concern for social justice and fairness, and I’ve been in that place for about 25 years now, even as the fringes of the left and the right have adopted ever more radical positions, and the political "mainstream" on both sides of the aisle has become increasingly neoliberal pretty much everywhere in the developed world that you might care to look.

And yet, as much as I am personally persuaded by leftist thinking, I can also appreciate that there are reasonable arguments to be made in defense of conservative politics. My go-to example of a conservative proponent doing the latter would be Douglas Murray (not a politician but rather a "public intellectual"). There are many things he says that I don’t agree with, but I have deep respect for the way his arguments come from a position of "good faith". Sadly, I find far too few examples of his ilk out there in the public space, and even fewer actively involved in politics or journalism.

So — out of the kindness of my heart — let me try to make the most favorable interpretation that I can of Ayuso’s politics, assuming that she is acting in good faith out of a set of sincerely held beliefs. Ayuso believes in small government. She believes the most efficient mechanism for deploying assets in service of the public good is through private enterprise. She and her predecessors in the PP have engaged in a sustained program of privatizations and cutbacks designed to transfer the management of public health into the private realm. Fundamentally, I think Ayuso (in common with her fellow party members) trusts the market, she believes in the power of individual initiative, individual responsibility. She probably considers "all men to be created equal", and attributes differential outcomes to differential levels of effort, of different moral fiber, grit, and determination.

The dark side of all this is that there is an implied (and sometimes explicitly stated) set of complementary beliefs. That the poor are somehow responsible for their own fate, just as how the wealthy and successful must be enjoying the well-earned rewards of their effort and personal merits. Not just that a large public sector is a sign of waste, but that the people who rely on it present a parasitic drain on society, on the fruits of the hard-working and morally superior ruling classes. Ayuso is on the record saying that people in desperate need of food hand-outs are "mantenidos", a word with distinctly negative connotations and implications of being a unproductive drain on the rest of society. Her campaign message is an emotional appeal to the value of "getting up at the crack of dawn" (implying hard work), traditional values and customs (going to church mass and bull fighting), and personal freedom.

She has very little to say about what she plans to do if she gets her wish of being able to govern "alone", with out the bothersome impediment of having to cooperate with Cuidadanos. Incredibly, the letter she sent to all registered voters in Madrid consisted of a single portrait photo accompanied by the word "Liberty" in large type on an otherwise blank page. Even the far-right party, Vox, whose program is more about drumming up fear of "communism" than elaborating policy, spelled out a list of things they wanted to do and why in their letter. At first I thought this was an insult to the intelligence of her supporters, to think that they should be so easily manipulated by such an obviously content-free, emotional appeal (I mean, who doesn’t like "freedom"?). You might think that Ayuso’s advisers have told her that it’s best if she keeps her mouth shut (perhaps that’s why she agreed to appear in only one debate), because she’s in a good position and there’s only one way to go from here (down); but the real truth is that most of the people who vote for the PP already have their mind made up — it’s quite simply unnecessary for Ayuso to persuade them. They know they subscribe to the same ideological beliefs as Ayuso’s party. The details simply don’t matter.

If all of this weren’t concerning enough, the polls suggest that, if Ayuso wins, it will be via a coalition with the far-right Vox, something that the vast majority of PP supporters are apparently perfectly happy with (basically, they don’t care who’s in power, as long as it isn’t those nasty "communists" who are going to raise taxes, strip people of their freedom, and rack up a mountain of economy-destroying public debt).

At this point I’ve established some basis for why I don’t want to see Ayuso getting reelected. Like I said earlier, I don’t really know if a post like this is going to change anybody’s mind, but I still feel compelled to share it. The way I see it, the reason why the left sometimes wins and the right sometimes wins (in general, not in Madrid) is that the answers aren’t actually indisputably clear. If there weren’t any grounds for dispute, we wouldn’t have well over a century of modern political struggle played out in this subtle and changing thing we call "the political spectrum". While it is easy to find the unthinking and uninformed almost anywhere in that landscape, there are also examples of intelligent, well-intentioned human beings who can articulate their positions in a reasonable form all over the place. In short, it’s complicated. It’s all well and good to have an opinion, but you have to admit that their must be at least a seed of truth in a wide variety of political positions, even if they’re not right all the time. And a corollary to that is that, whatever your beliefs are, they’re probably not reflective or reality 100% of the time. I just know that, if I’m going to be wrong, I’d rather be wrong in the direction of trying too hard to defend fairness, to protect the disadvantaged, and to combat structural inequality, even if it isn’t all that we think it might be.

So with that out the way, let’s get into the details of how elections actually work in Madrid.

Madrid uses a proportional voting system. You vote for parties, and each party has a list of candidates. The more votes a party gets, the more seats they win, which means more people from their party go in to occupy places in the assembly. These electoral lists that the parties have are effectively ordered choices. The presidential candidate is at the top of the list, the list itself contains more than enough names to cover even the best-case scenarios that might occur in landslide wins. Often, as a symbolic gesture, the final person on the list (who will never actually enter the assembly in any kind of realistic scenario) is chosen on the basis of propaganda value. For example, it might be an influential person already in government at another level. This year, the PP announced that its list would be closed out by José Luis Martínez-Almeida, the current Mayor of Madrid. Obviously, he’s busy being Mayor and has no intention of leaving that role. His presence on the list is a symbolic gesture of solidarity and support.

There are two big gotchas to this system of proportional representation using electoral lists. The first is that there is a "5% rule"; any party that doesn’t get at least 5% of the vote is excluded from consideration. This is presumably to stop the Assembly from splintering into an ineffective mess of tiny parties or individuals incapable of making legislative progress. But there is a real risk for voters and for parties here. A voter voting for a party that does not make the threshold is effectively throwing away their vote. And for parties which suffer this fate, it is basically a death knell. They are unlikely ever to make a comeback from this kind of electoral ignominy. At the time of writing, it seems like Ciudadanos is going to suffer this fate, as the electorate effectively punishes them for their perceived political opportunism (wherein they seem willing to switch their "bets" and arbitrarily cross ideological boundaries in the name of accessing power).

The second big gotcha with this system is that there are rounding errors. It’s nigh on impossible that the distribution of votes will line up in such a way as to allow integral allocation of seats. The mechanism used in Madrid is "the D’Hondt system". The direction of rounding tends to favor large parties and coalitions. That is to say, voting for a smaller party may bring the downside risk that your vote is somehow less powerful than the vote of a citizen voting for a larger party. The algorithm is described as "the least proportional of all proportional voting systems, but also the most stable one". Whatever, it is what it is, and its parameters are the ones we have to work within.

In practical terms as a voter on the left, you have three options. These are the PSOE (socialists), Unidas Podemos (a newer party, and much farther left), and Más Madrid (newer still, a spin-off of Podemos with a more pragmatic/green tilt). All else being equal, given the nature of the D’Hondt system, a vote for the PSOE is "safer". Safer in the sense that the distortion in the D’Hondt system is likely to make a vote for the PSOE weigh ever so slightly more than a vote for Podemos or Más Madrid. Given that the overall tendency of Madrid is to vote for the right, you don’t want to dilute your left vote. We’re kind of tired of losing here! You might not like the PSOE’s policies, but if your goal is to maximize your chances of getting rid of Ayuso, it makes sense to vote for the PSOE.

But things got weird before and after the election was called. It’s not quite so simple as all that.

First of all, the election was called with great haste to preempt an incoming motion of no confidence. It seems that Ciudadanos was on the brink of teaming up with the PSOE to throw Ayuso out before her term ended, but it backfired on them tremendously when she beat them to it by calling the election first. All the polls indicate that Ciudadanos is going to get punished in the elections as a result of this perceived betrayal and act of opportunistic politicking. It seems likely that they’ll basically get wiped out. Many who voted for them will switch their vote to Ayuso.

As much as I would have loved to see Ayuso thrown out in the middle of her term, I think that these hijinks seldom achieve any useful effect. They often do more harm than good, serving only to further polarize and radicalize the debate. (Just look at all the good not one but two Trump impeachments did.) Unless the leader in question did something scandalously bad, and you have a bullet-proof case for it, a motion of no confidence is probably a bad idea. A rare counterexample in which it actually worked is the already cited motion of no confidence that put an end to Rajoy’s national government in 2018.

The next thing that happened was that the leader of Unidas Podemos, Pablo Iglesias, announced that he was — no shit — quitting the vice-presidency which he held in the national government in order to take the fight to Madrid. Geez. In general, I find him to be articulate, and his arguments to be intelligent and persuasive, but I don’t think I could ever cast a vote to somebody who quits an elected position a little after year into the job. It simply doesn’t matter how important he might allege that the fight for Madrid may be. It seems transparently clear that the real reason he’s getting out of the federal government is that he has been frustrated and disappointed by the amount of power that Podemos has been able to wield as a minority partner in the coalition government. Nobody ever said it was going to be easy.

In response to this, Ángel Gabilondo says, "con este Iglesias, no" ("not with this Iglesias"). Obviously overplaying his hand there. Just because he might want to keep all the power for the PSOE doesn’t mean that he can turn his back on a necessary ally. The only way the left is going to end two-and-a-half decades of conservative rule is going to be by acting in unison. Of course, things change quickly in politics, and he has since softened his posture, but it’s really disappointing that he made an unforced error like that.

So, D’Hondt tells me I should be voting for the PSOE, but I’ve just seen their candidate make a royal fuck-up before the campaign has even started, and furthermore, he is focusing his message on the notion of "serious government" and continuity (ie. a promise to make no changes to the tax system after until the next election, if he wins it, two years from now). I find this utterly lukewarm, like tepid bath water. Of course, I’d be thrilled to see Gabilondo as president if it meant getting rid of Ayuso, but I cannot be excited about him, and at 72 years of age and with the measured tones of the university professor that he is, I can’t see the rest of the public getting all that excited either. (In comparison, Ayuso and Iglesias are both 42 years old, while Mónica García — the Más Madrid candidate — and Rocío Monasterio — the Vox candidate — are both 47.)

Gabilando has since changed his posture about teaming up with Iglesias, which unfortunately just makes him weak in the eyes of his opponents, even if it is a necessary and good thing for the left. And such an easily avoided error. Sigh… He could easily have done exactly what Íñigo Errejón, spokesperson for Más País (the sibling party of Más Madrid, but operating at the national level), did, which is to say that he was open to dialog with anybody at all "with no red-lines and no vetoes", in the name of forming a government that avoided a right-plus-far-right coalition. Simple pragmatism! That’s what I want to see in my political representatives: a get-it-done attitude and a commitment to multi-party dialog in the name of benefiting the people; a refreshing change from the ultimatums, the hostage-taking, the rage-quitting, and the threats.

I start listening to more things from Errejón, of whom I already knew a bit from his time in the national congress. And I start learning more about Mónica García, the candidate in Madrid. It soon becomes clear to me that the party farthest to the left (that of Iglesias) is spending its time hurling accusations of "fascism" against the right, and the parties on the right are hurling back accusations of "communism" in return. And just about everybody is engaged in a vacuous debate about how their side is the guardian of "democracy" or "liberty", or any of a number of abstract words with strong emotive connotations. Meanwhile, the PSOE is really closer to being a centrist party than anything else (in contrast to Ciudadanos, which is "centrist" in name only, and really more like a watered-down version of the PP; let’s call it "PP Light"). Among the entire political spectrum, Más Madrid is the only one that is consistently talking about concrete issues that will make a difference in people’s lives. It’s the only one not spending most of its time engaged in political circus.

Now, you’re probably never going to find a party whose platform you agree with 100% in every aspect, and Más Madrid is no exception. I think in some senses they may be trying to do too much. Their program, for example, includes no fewer than 876 proposed measures(!), ranging from improvements to universal public health care and education, environmental initiatives, investments in research and investigation, and many, many others, in 13 categories. I honestly don’t have time to review them all, but as I scan through the ones that matter most to me, and sample others, I get a sense that this party comes about as close as I could reasonably expect to embodying my political preferences, even though there are surely things in there somewhere that I don’t consider to be optimal.

As such, even though D’Hondt tells me I should vote for the PSOE, I figure it’s also important to use your vote to send a message to the others parties on the left. In this case, a vote for Más Madrid is telling the PSOE that its offer of continuity and "seriousness" just doesn’t cut it. We want more. And it’s telling Podemos that their fervent commitment to an intellectually pure form of leftism isn’t compelling either, because they spend more time getting into fights with their political enemies than making a case for why their policies would benefit the majority. So, Más Madrid it is.

And I made this decision before it was cool to like Más Madrid. Just sayin’. Mónica did pretty well in the debates and the polls now show clear movement towards her party as people get to know her and hear more about the program. Meanwhile, the PSOE’s share of the voting pie continues to shrink. Whatever happens, I have a feeling that this election will be Gabilondo’s last as presidential candidate, unless, by some kind of miracle, he actually wins. Next time around, he’ll be 74.

Now, the left has a long uphill battle to fight if they’re going to win against the right in a community that seems to vote so consistently for Ayuso’s party, but we mustn’t give up hope. It’s easy to say "the right always wins in Madrid", but that would be a mistake. It’s the kind of statement that seems like an inevitable truth until one day the sun rises and it ceases to be true. I don’t know if 2021 is the year that it is going to happen, but I sure hope it is, and I’m going to do my best to make it happen. Obviously, I only get one vote (shame, that, isn’t it?) but I’m volunteering for Más Madrid in a small way, and one of the things I’m doing will be to represent Más Madrid as an "apoderado" (ie. somebody who monitors the voting process at a voting station on election day).

I hope this was helpful, and if you want to talk about any of this, come find me on Twitter; it seems like a lovely place to have a chat.

Building a PC

Back in the late 90s I was making plans to build a PC based on the original AMD Athlon processor, basically because I wanted a better game-playing experience than I was getting on my Mac. I regularly read AnandTech and Tom’s Hardware. I knew about northbridge and southbridge chipsets, about Intel codenames like "Willamette", "Northwood", and "Prescott" (fun fact: these chips used 180 nm, 130 nm, 90 nm processes, respectively, which is kind of mind-blowing when you think that AMD is currently using a 7 nm process in its current Zen architecture), and about rumors and future roadmaps.

In the end, I never followed-through on it. If I had been flush with cash I surely would have run out and done it, but I was pretty busy completing my undergraduate studies (and failing to complete my postgraduate studies). And I wasn’t flush with cash: I’d sunk a significant chunk of my meagre student savings into a series of Apple machines, so found myself slowly becoming more heavily "invested" — quite literally — in that ecosystem.

The arrival of Mac OS X and pushed me further along that path. It wedded the power and flexibility of UNIX with the thoughtful and delightful UX of Apple’s once-great Human Interface Guidelines. Apple enjoyed a brief moment of performance parity or even superiority with the G3 processor, reducing the incentive to get a PC. By 2006 Apple had released its first Intel iMac, solving the performance deficit that had developed by that time, and I didn’t think about wanting a PC for a long time. Not until Apple had shown itself to be hopelessly committed to thinness at any cost and started pumping out laptops with garbage keyboards, useless Touch Bars, and crippling thermal throttling issues.

So here we are in 2020 and I am at last putting together a Linux PC, finally fulfilling a 20-year-old wish. I had an outsized amount of fun today setting up case fans and doing cable management. I don’t even have all the pieces at this time, so I’m just doing what I can. Some people say building a PC is like "Lego for adults", and I can see why. I’m sure it wouldn’t be so fun if I had to do it every day as a job, but when it’s a once-a-decade thing, or even rarer than that, it’s quite interesting and therapeutic.

I’m not switching to Linux, I’m just relaxing the "one machine at a time" limit that I’ve stuck to for the last 15 years. I’m keeping my mid-2015 MacBook Pro (still my favorite Mac laptop ever) running macOS 10.13 High Sierra (sticking to the oldest supported version of macOS that I can, because I feel like Apple has lost its way with the subsequent releases). There’s too much software on the Mac that I’m not in a position to walk away from yet. But I’m complementing that with a beefy desktop machine that will be great for doing development work because — unlike my Apple machine — I can load it up with RAM at non-extortionate prices, and it won’t labor under the burden of devastating thermal throttling. You can put together a very high-end self-built PC for prices that barely get you admission into the Apple store.

Here’s the thing though: when I started to look into the state of the PC world, I was horrified to discover just how complicated everything had become in the 20 years since I was last up-to-date. I mean, I don’t know if it really is more complicated, but it’s true that pretty much everything I once knew has been rendered utterly irrelevant.

Let’s talk numbers. If you’re going to build your own PC you need to pick 7 "main" components (CPU, motherboard, case, memory, GPU, disk, power supply) and the number of combinations is staggering. This is not to speak of equally essential "extras" like keyboards, mice and displays. The decision tree fans out with alarming rapidity: you pick AMD or Intel, which leads you to choose a generation and a model within that generation, which implies a socket choice but then you need to pick a motherboard and therefore a chipset and vendor. So there are two CPU vendors, but dozens of CPUs, and many more motherboard vendors. Even when you’ve locked in a CPU vendor (eg. AMD, because you want a Ryzen CPU) and therefore a socket type (eg. AM4), as well as a motherboard vendor (say, Gigabyte) and chipset (say, X570), you still have about 17 AM4 X570 motherboard choices from that vendor alone. Maybe this 80-minute-long analysis of all just those boards will help you navigate the various tradeoffs between cost, feature-set, build quality, and son on…

A similarly bewildering array of choices remains with respect to RAM, GPUs, cases, and every other category listed above, as well as some additional "auxilliary" things that I didn’t even mention, like CPU coolers and case fans. One of the reasons why desktop PCs are so much more powerful than laptops is that the larger form factor permits some incredibly effective (and large) cooling systems that mostly make thermal throttling a non-concern, as well as providing you with the tools to push into over-clocking territory if that kind of things floats your bloat. Do you want to go with air-cooling or water-cooling? If air-cooling, which vendor and model do you want to go with for your CPU cooler? How many case fans do you want? What size? From what vendor? Are you going to go with 3-pin or 4-pin connectors? What’s the difference? Which ones will be intake and which ones will be exhaust fans? What’s your stance on negative vs positive pressure? What do you think about filtering? If you go with water-cooling, do you want an "all-in-one" thing or a custom loop? From what vendor? How big do you want your radiator to be? Do you want more than one? What kind of thermal paste will you use? And how much? Will you go with "liquid metal" or something non-conductive?

And I’m only scratching the surface here. You probably don’t only care about thermals and pricing, but probably noise too. So what kind of case should you get? Want something relatively closed and sound-insulated, or something relatively open which maximizes airflow and allows you to run fans slower and quieter? Choices like these proliferate everywhere you look.

You watch some YouTube videos to guide you on your way, but that doesn’t necessarily help at first, because it just overwhelms you with evidence of how much you don’t know yet and may never know. And even when you see expert PC builders that have literally millions of subscribers, and whose full-time job consists of building PC from components and reviewing them, there is no shortage of mishaps where you get to see how their newly built machines won’t boot, or the components prove to be incompatible, or they commit a human error that ends up frying or breaking some fragile component. Visit a forum like the "buildapc" subreddit and you’ll find yourself in the company of countless confused others who are trying to fix a screwup or dig themselves out of a hole.

My advice here would be to take it slowly if you can. I’ve gone from feeling horrified and extremely doubtful that I’d be able to select a compatible set of components at a good price and successfully assemble it, to being relatively comfortable with the idea. The key element has been that I am not in a hurry: I’ve been able to immerse myself into the PC subculture on YouTube over a period of months, to the point where not only are the names and numbers familiar to me, but I’m also aware of most of the things that could go wrong and what to do to mitigate the risk. I’m not saying I’m an expert yet — I probably never will be; I’m just saying that I feel comfortable now with the idea of trying this.

The good news is that there is a reason why channels like JayzTwoCents, Gamers Nexus, Bitwit, Linus Tech Tips, and Paul’s Hardware all have north of a million subscribers (and in some cases much more). And those aren’t even the only ones, there are many technology channels that have multiple millions of subscribers, and a host of others with hundreds of thousands. YouTube won’t hestitate to recommend them to you once you get started.

One of the reasons why these channels are so popular is that human beings love getting themselves all worked up about new stuff, but in addition to that, the content on these channels is often quite entertaining, usually interesting, always rich in information, and sometimes packed with wisdom, insight, or humor. All of which is to say that if you’re not in a hurry to learn how to build a PC, you can go deep into this content over a lengthy period, to the point where you can navigate a site like PCPartPicker without feeling utterly lost.

So I’m doing a slow build of a PC, ordering parts when the price is right and the availability is there. Nobody can get their hands on AMD’s new Ryzen 5000 series CPUs (or their new GPUs), and to be honest, that’s totally fine, at least for me. It seems that lots of components are in short supply now anyway, partly because these big product launches trigger demand for all other components as people build and upgrade systems, but also because of the pandemic, which has led people to make investments in systems for working and being entertained from home.

Looking on the bright side then, the constrained supply helps spread out the cost over weeks or months, and gives you an extra buffer in which to learn more about building a PC; you even have time to read the manual that comes with your components with a level of patience and attention to detail that you probably wouldn’t have if you had a screwdriver in your hand, surrounded by a wall of boxed components, on a mission to complete your first PC build in a day.

This long baking process has definitely helped me steer clear of some potential issues. For example, letting the decision about which case to buy simmer for several weeks gave me the time I needed to change my mind a few times and eventually settle on case that is not only versatile enough to let me explore the trade-offs between sound isolation and air-flow, but also to find something discrete that doesn’t have any of the tempered glass side panel and RGB nonsense that seems to be all the rage nowadays, but which I find totally absurd (and which would make my partner want to kill me if I ever brought something so garish and unsightly into our house).

Right now I’m probably about 50% of the way towards a finished system, and having to work towards it like this for so long is going to make me appreciate it in a way that I have never appreciated the Macs that I’ve owned. It’s not that I didn’t appreciate those; it’s just that I appreciated them in a different way. I treasured them like beautiful, fragile, works of art. One of the reasons is that when something goes wrong with them, you can’t really fix them — at least, you can’t fix them easily. Apple doesn’t want you to open the case. They deliberately go out of their way to make them nigh on impossible for mere lay people to repair, ostensibly in devotion to the Church of Thinness.

The PC, on the other hand, is like a pickup truck. The power supply has a 10-year warranty on it. The case is brutishly ugly, placing functionality and build quality above aesthetics. If I need to upgrade the PC in 5 or more years from now, I know the case will still be totally adequate. In short, the PC brings to the hardware a large part of the freedom to maintain and modify that I’ve enjoyed on the software plain since forever (despite Apple’s efforts to circumscribe that freedom over the years).

Sharpening the axe

Transcript from my talk at VimConf 2020 (video, slides).

1

Hi everybody, it’s a pleasure to be here. Can somebody please confirm for me in the chat that they can hear me?

Ok, I think we’re ready to get started. I’m going to shut off my camera now so that we have maximum screen real estate for the slides. At the end I’ll be sharing links to a high quality pre-recorded version of this talk, as well as a transcript.

2

This talk started with a joke on Twitter a few months back.

Lincoln: "Give me six hours to chop down a tree and I will spend the first four sharpening the axe."

Me: "Give me a series of simple programming tasks to do and I will spend 10 years of my life tweaking my dotfiles repo."

Now, President Lincoln almost certainly didn’t actually say this, but even though the attribution is dubious, the appeal of the argument is clear. The idea is that you can be more effective by making sure you are prepared and have the right tools. So effective, in fact, that you’ll get the job done sooner, even when you include the "off task" time spent preparing.

Now, when I tweeted about President Lincoln and sharpening the axe, I was only half-joking. The bit about spending 10 years tweaking my dotfiles is actually a somewhat of an understatement.

3

I switched full-time to Vim at the beginning of 2009, and have had my dotfiles in a Git repo since around the same time.

From this graph of commits over that time span you can conclude that I am either:

  1. A relentless optimizer.
  2. Somebody who’s probably got a pretty tuned toolkit by now.
  3. A master procrastinator.

I’d like to think that it’s mostly about the first two, but the reality is that there is probably some truth in them all.

4

But there’s another factor beyond my penchant for tinkering that explains some of this activity. It’s that Vim itself and its surrounding ecosystem have changed quite dramatically over the last decade. What might have been a "state of the art" Vim set-up in 2010 would probably seem quite antiquated if we looked at in 2020.

Now, in 2010, Vim version 7 was the latest and greatest incarnation of Vim. It was about half-way through its decade-long reign. Version 7 retained its crown as the latest version for around 10 years. Vim was already about 20 years old at that point, and its ultimate predecessor, vi, was approaching its 35th birthday.

Things moved more slowly back then. Vim, a single-threaded editor, only had support for blocking, synchronous jobs. It was possible to write plug-ins in other languages such as Python and Ruby and so on, but most plug-ins were written in Vimscript, which is a capable but awkward language, and a slow one.

This meant that IDE features tended to be pretty modest back then, with projects like Ctags representing the peak of "intelligent" IDE-like code navigation features.

If you fast forward a decade, so much has changed. Neovim brought a host of improvements, and the competitive pressure spurred Vim’s own maintainer, Bram Moolenaar, to roll out equivalent (but unfortunately not compatible) analogs in Vim itself. The advent of asynchronous jobs and the Language Server Protocol have led to a burgeoning of sophisticated IDE-like functionality.

And while Neovim charges forward, Vim 9 is under development too, including some changes that would’ve been unimaginable in the past: things like a new version of Vimscript which is compiled for better performance and which eliminates many puzzling idiosyncrasies of the older version.

5

One of the ironic things about this evolution is that with each passing year Vim has become a little bit more like Emacs.

You’ve probably heard the old joke about Emacs being "a great operating system, lacking only a decent editor". While it’s fun to poke fun at Emacs for being huge and sprawling, the value proposition is obvious.

You can live inside Emacs if you want. If we think in terms of composing tools together, Emacs tends to be one of the outermost layers. Emacs is a container for other processes. You can stay inside Emacs not only to edit text, but to send and read emails, debug computer programs, browse the web, manage your calendar or todo list, and much more.

6

For most of its life, the mental model for Vim was the exact opposite. Rather than something you lived inside, Vim was a scalpel for editing text. You would pick it up when you needed it, call it from other places. For example, Mutt, the email client, or Git, the version control system, would spawn a copy of Vim whenever you needed to edit something. Vim was so small and light that the startup cost was imperceptible.

In fact, the concrete incarnation of the program itself retreated into the background almost to the point of invisibility, leaving behind only the abstract idea of a minimal set of editing tools for manipulating text modally. So browsers and IDEs and email clients would borrow the idea of modal editing and implement "vi modes" in a way that they would never have contemplated for an "Emacs mode", unless you could call some basic Emacs-style bindings a "mode". Such bindings don’t fundamentally change anything about the editing paradigm, they just provide some common shortcuts for people with their muscle memory configured a certain way. But modal editing is an entirely distinct modality.

7

So, Vim has changed a lot, and the ecosystem has grown and matured. If you want, you can now, to a large extent, "live inside" Vim the way Emacs users can live inside Emacs. If you want, you can use Vim as a container for other processes instead of as a mere process to be stuck inside another container.

But at its heart, fortunately, despite the proliferation of increasingly sophisticated plug-ins that you can install, Vim at its core is still minimal and fast, and can still be used as a lightweight tool that you pick up when needed.

It preserves the defining value proposition that has drawn so many people to it over the years. Most obviously, it’s that Vim’s implementation of modal editing is just sublime, no pun intended. When it comes to manipulating text, it is just obscenely good at it.

And I think it’s a journey that all of us who choose Vim and stick with it go through. There are three "epiphanies" that you arrive at, sooner or later, that explain all of the magical appeal of Vim.

8

The first is that Vim is fast, and not just fast to start-up, but fast to respond in terms of keyboard latency, and, even more importantly, fast in the sense of minimizing the distance between the intentions of the human at the keyboard, and the actions they must carry out in the editor to get it to do what they want.

The second epiphany, is that Vim is easy to learn, despite all the jokes about being stuck in Vim for multiple years unable to exit.

And finally, the third epiphany is that Vim is powerful, like a lever, because once you learn the core principals and patterns, you can combine them in predictable ways to do many additional things without a steep learning curve.

Let me give some examples.

9

Vim is fast, and one of the main reasons is that it explicitly optimizes for the common tasks that you find yourself doing dozens or even hundreds of times a day when editing text.

For example, normal mode commands like "o" and "Shift-o", which "open" a new line for editing below or above the current line.

In other editors, in order to carry out this action, you find yourself doing extraneous things that aren’t actually directly related to the thing you’re wanting to do, which is start inserting text on the line below. Instead, you find yourself doing things like pressing "Command-Right Arrow" to jump to the end of the current line, which has nothing to do with your business on the next line, and then pressing "Enter" to get to where you can actually start doing what you want.

In Vim, this operation is a single key-press away, and very close to where your hands rest on the keyboard home row (closer still on keyboard layouts like Colemak, or Dvorak, which I don’t know how to pronounce).

This kind of thoughtful optimization is pervasive in the standard normal mode mappings, starting with the famous "h"/"j"/"k"/"l" quartet for cursor movement, and extending to pretty much every available key on the keyboard.

Just in terms of simple mechanical advantage, here indeed is an axe worth sharpening. Practice the normal mode commands like a Jazz musician would practice scales and improvisation.

10

Next point: Vim is actually, surprisingly, easy to learn. Almost all of the core operations can be remembered using mnemonic tricks, like "cit" standing for "change inside tag", which is trivially easy to remember, or via intuition and pattern-matching; for example, an uppercase version of some key usually does the logical extension or inverse of the lowercase version. Or prefixing a key with "g" often does an augmented version or a variant of an operation.

Compared to other things I’ve learned in my life, Vim really wasn’t all that bad. It was definitely easier than learning a new keyboard layout, for instance; I felt quite productive after mere days of switching to Vim, whereas learning the Colemak keyboard layout required weeks of intensive effort before I really felt comfortable.

11

And the final point, about Vim being powerful. Vim’s power is the power of composability. You learn the component pieces and you can combine them to multiply their value.

Once you’ve understood the general grammar of repeat counts, verbs, motions and so on, you can assemble together operations to do some very powerful things without having to individually learn all the permutations. If you know N verbs, and M motions, that means you know N-times-M combinations. That’s almost quadratic growth right there, and for once, that’s a good thing.

12

So they say "practice makes perfect", and the good news is that the core design of Vim is so fundamentally good, that it rewards focused practice. The effort you invest in improving your basic text-editing skills will pay you dividends from now onwards, every time you edit text.

And focused practice is one path towards mastery. It is a way to sharpen the axe. But the other way, and the thing that I want to spend the rest of this talk on, is the task of refining your set-up, to turn Vim into a tool that fits you like a glove, so that it becomes more like an extension of your will than an external object.

13

And that brings us back to why I have a dotfiles repo with nearly 4,000 commits in it (so far…). Vim and its ecosystem have changed a lot, but keeping up-to-date with those changes only goes some of the way to explaining my activity.

Let’s talk a little bit then about what that means in terms of "Sharpening the axe".

14

I think Zach Holman was very close to having it right when he said, ten years ago, that "dotfiles are meant to be forked".

He’s saying that dotfiles should be promiscuously shared, and customized to suit each developer’s needs and taste. In the end, your dotfiles become a unique expression of your preferences, needs, habits, and in a way, even your identity. Given time and freedom, no two developers’ dotfile set-ups will be alike. They’ll be as unique as fingerprints.

I mostly agree with that, but with a disclaimer. I don’t think you should base your dotfiles on somebody else’s by forking.

15

Instead of forking, start with git init, an empty slate. That means an empty directory inside of which you are going to carefully construct over time your ideal development set-up.

Once you’ve got this empty directory, and started populating it with configuration files, there are a number of tools that you can use to actually put these files in the right places and keep them up to-date. I’ve listed a few here.

  • A common choice is GNU Stow, which describes itself as a "symlink farm manager". In practice what that actually means is that you can keep your dotfiles neatly organized in a Git repo, and then make them appear appropriately elsewhere on the filesystem (such as in your home directory) via symlinking.
  • One that I used for a while was Ansible which is a full-blown system configuration tool. This can be used to do much more than just symlink dotfiles, such as installing packages, scheduling cron jobs, applying tweaks to shared system files, and so on. But it is complicated, and the tool isn’t really optimized for this use case; it’s really intended to do large-scale infrastructure management, such as deploying and maintaining fleets of machines across the network. Using it for dotfile management is kind of like driving in a nail with a 10,000-pound hammer.
  • At the opposite end of the spectrum, you could use a simple script written in Ruby, Python, Bash, or any other scripting language. There are many examples of such scripts online (here is one that I used in the past).
  • There are also tools and frameworks especially built just for dotfile management (one example made by a former colleague of mine is called Dot).
  • Finally, I’ll mention Fig which is what I am using nowadays. I basically took the idea of Ansible, the 10,000-pound hammer, ignored most of the 3,400 modules that come with it, and wrote from scratch a tiny little tool that does nothing more than I need to set up a machine and keep it up to date.

16

So you have a Git repo now, and a way of plugging it in to a working system. What should you do next?

I like the idea of starting from scratch. Literally from a blank .vimrc file (or a blank Neovim init.vim file). And then we build up from there line by line.

Nothing goes in without understanding exactly what it does. Not only do you make the editor behave the way you want it to, but you gain an understanding of both the default behavior, and the modifications necessary to change that behavior.

Here’s an early example from my repo.

17

commit 18162960b6119d5cf49b9ffaa92e1e430a176252
Author: Greg Hurrell <greg@hurrell.net>
Date:   Wed May 20 23:53:14 2009 +0200

    Vim: set low ttimeoutlen

    MacVim isn't affected but "vim" in the Terminal is: typing a command
    like "O" will result in a noticeable delay because it might be the first
    character of a multibyte keycode (an arrow key, for instance).

    This can be observed in the form of a noticeable delay between pressing
    "O" and actually entering Insert mode. By default 'ttimeoutlen' is -1
    and that means that default 'timeoutlen' value of 1000 milliseconds is
    used for the detection of multibyte keycodes (ie. there is a 1 second
    delay between pressing the "O" key and actually entering Insert mode).

    Set 'ttimeoutlen' to a fast value (50 milliseconds) to make the delay
    less noticeable. This should be fast enough to not cause any problems,
    even when working over an SSH connection with some latency.

This one is from May 2009, when I’d been using Vim for about five months. In this commit I’m adjusting the value of the 'ttimeoutlen' setting to improve responsiveness. Now, when I make a change like this, I don’t really hold much hope of remembering the details of why; with so many settings, and some of them quite subtle, I know that I have to record the rationale for making the change, or it will be lost in the sands of time.

But if it is in the commit message, then it is only ever a quick git-blame away.

18

set scrolloff=3                       " start scrolling 3 lines before edge of viewport
set shell=sh                          " shell to use for `!`, `:!`, `system()` etc.
set noshiftround                      " don't always indent by multiple of shiftwidth
set shiftwidth=2                      " spaces per tab (when shifting)
set shortmess+=A                      " ignore annoying swapfile messages
set shortmess+=I                      " no splash screen
set shortmess+=O                      " file-read message overwrites previous
set shortmess+=T                      " truncate non-file messages in middle
set shortmess+=W                      " don't echo "[w]"/"[written]" when writing
set shortmess+=a                      " use abbreviations in messages eg. `[RO]` instead of `[readonly]`
if has('patch-7.4.314')
  set shortmess+=c                    " completion messages
endif
set shortmess+=o                      " overwrite file-written messages
set shortmess+=t                      " truncate file messages at start

And after doing this over many years, I end up with a self-documenting .vimrc file that contains these short comments to remind me what each setting is for. And if I need more info, I can dive into Vim’s excellent help with :h, and if I need even more context, I can git-blame or look at the log to see when and why I changed a particular setting.

19

commit 84a48540b6f10095ba0fe25dc359060e71804a2e
Author: Greg Hurrell <greg@hurrell.net>
Date:   Sun May 24 01:42:32 2020 +0200

    feat(vim): set up TextYankPost

    This is going to be a great little speed-up. Instead of visually
    selecting things and then yanking them (to be sure you got he right
    thing), you can just blindly yank with the same level of confidence
    because if you get it wrong, you'll see it in the highlighting.

    Thanks to: https://github.com/neovim/neovim/pull/12279

    Screenshot: https://twitter.com/wincent/status/1264340870322675713

I have maintained this habit all along, because experience has shown me again and again the value of externalizing a record of my thought processes and activity into an archive that I can search at a later time.

Here’s some proof; this one is a commit message I wrote 11 years later, and you can see that I’m still explaining what I’m doing and why. In this case, it’s leveraging a new Neovim feature to highlight the yanked region using an autocmd. As always, I explain what the change is, my rationale for making it, and I include whatever information or links I’ll need to make sense of it if I look at it again in the future.

Not only is it useful to have a record like this for me, but there are two other benefits.

  1. I know that other people who look into my dotfiles repo, can use the extra context to help them make informed decisions as they craft their own environments, as opposed to blindly copying from one place into another.
  2. It’s liberating for me, mentally speaking, to know that I don’t have to agonize about remembering all the details of every decision I make, because there is a part of my memory which resides in a distributed fashion across multiple hosts in the form of an immutable commit history. I don’t need to remember the answers themselves; just that they exist in a place that I can find them again.

20

So that’s a little bit about the value of discipline, of doing things in a rigorous and consistent way. I call it "tweaking", but the truth is, done with care it starts to resemble software engineering.

But discipline is just a question of how we do things. It doesn’t speak to what we should do. What can we do to go beyond tweaking, and follow a path that leads us towards "mastery"?

Now, I’m being very careful about the language I use here. I want to emphasize that mastery is a journey more than a destination. I still learn new things about Vim every single week. And I forget some of the things that I previously learned. So if mastery is a destination, I don’t know if I’ll ever arrive there. I feel much more comfortable talking about it as a process.

On my YouTube channel, I’ve posted almost a 100 Vim screencasts over the last 4 years, and I’ve seen again and again how information that I shared one week, and which reflected at the time my best understanding of things, was later superseded by new understanding. When you’re constantly changing and growing, and the environment is changing around you, it is hard to feel any sense of mastery; rather than feeling like an expert, studying Vim makes you feel like a perpetual student, and is a quite satisfying state to be in, when you think about it.

21

The primary tool that will drive you towards mastery will be seeking out solutions for your own pain points. When you start from an empty .vimrc, these might be simple things like figuring out how to show line numbers, or use spaces instead of tabs, or turn hard-wrapping on or off.

It might end up being things like how to get italics rendering properly or have the mouse working properly in the terminal, or how to use autocomplete or snippets. Maybe you want to figure out how to use Vim for writing email, or managing your wiki or todo list. As your knowledge of Vim grows, so to will your awareness of little edge cases that you’d like smooth out, and your appetite for taking on bigger and bigger challenges will increase.

In my decade with Vim, I’ve built plug-ins, and used it for email, blogging, to manage a wiki, for note-taking, and obviously for programming. And just like the myth that most humans only use 10% of their brain, I still feel like I’m only using about 10% of what Vim has to offer. This makes it a pretty exciting platform to learn about, because there’s this sense of vast untapped potential waiting to be unleashed all the time.

And if you run out of obvious ways to sharpen your axe, you can take inspiration from other people’s set-ups and ways of working. Go on fishing expeditions in other people’s dotfiles looking for ideas. Observe other people at work. You might be in a work environment where pair-programming takes place, and even if you aren’t, there are always screencasts and streams to look at. Seeing what other people can do with Vim may expand your horizons in ways that inspire you and give you ideas for continued improvement.

Just don’t forget the golden rule of never copy-pasting without understanding. Keep up your discipline of understanding every change, document your process, and whenever you need your context it will be waiting for you there in the Git history.

22

Another path to improvement is through plug-ins

Now, when I make a plug-in it isn’t out of a desire to make something popular. It is fundamentally because I have a need that isn’t currently fulfilled to my satisfaction. This is the primary driver along the path to mastery, again: solve specific problems.

So, you do this, you make a plug-in, and you end up sharpening the axe. If the result seems useful, then you share it.

"If you build it, they will come"… or they won’t. It doesn’t matter. The important part is that you improved your environment and probably learned something along the way.

23

if has('folding')
  if has('windows')
    set fillchars=diff:∙               " BULLET OPERATOR (U+2219, UTF-8: E2 88 99)
    set fillchars+=fold" MIDDLE DOT (U+00B7, UTF-8: C2 B7)
    set fillchars+=vert:" BOX DRAWINGS HEAVY VERTICAL (U+2503, UTF-8: E2 94 83)
  endif

  if has('nvim-0.3.1')
    set fillchars+=eob:\              " suppress ~ at EndOfBuffer
  endif

  set foldmethod=indent               " not as cool as syntax, but faster
  set foldlevelstart=99               " start unfolded
  set foldtext=wincent#settings#foldtext()
endif

if v:version > 703 || v:version == 703 && has('patch541')
  set formatoptions+=j                " remove comment leader when joining comment lines
endif

One of the things about releasing something as a plug-in is that people may use it in contexts that do not match your own. This means that you may have to do feature detection, to make the plug-in compatible with a broader range of environments. This is a good habit that you can "backport" to your own .vimrc. For example, it can help you make a single .vimrc that will work for both Vim and Neovim, and will degrade gracefully if you find yourself on a machine with an older version. That’s what you can see in this screenshot, with the if statements that check for the existence of features. For occasions where you can’t directly detect a feature, you can resort to checking for a specific version or even a patch (which is useful, for example, if you want to conditionally execute a workaround for a bug that was fixed in a particular Vim patch).

24

Here’s a little case study. I created a plugin called "Scalpel" that streamlines a common use case I have of moving through a file substituting a word. Neovim in particular has some nice features to preview changes so that you can make them en masse without fear of breaking anything, but the use case I’m talking about here is where the buffer may be large, and you want to pause and evaluate the site of each potential change before actually performing it.

So, this starts as a few lines in my .vimrc because I’m not entirely happy with the alternatives.

I could use a mapping like the one shown here — to *Ncgn — which allows you to jump from word to word replacing each one.

  • * jumps to the next occurrence of the word under the cursor; this effectively puts it in the search register.
  • (Shift) N puts us back where we started.
  • c starts a change; and:
  • gn indicates the motion over which we wish to make the change, which in this case means the next match.

The overall effect is to change the current word, and if I hit . after leaving insert mode the change will be made to the next match, and the next as I continue to hit ..

This mapping works, but I don’t like the way it’s blind. I can’t see where the cursor is going to land in order to preview the change before making it. By the time I get there, the substitution has already been made. And it pollutes my jump list too, because I am jumping through the buffer.

So, I end up using the :substitute command instead.

  • % defines a range, and says we want to operate over the entire buffer.
  • s is short for substitute.
  • I specify a pattern and a replacement.
  • g says to do the substitution globally, which means for all matches on any given line instead of just the first; finally:
  • c tells Vim to prompt me for confirmation before making each change.

This command doesn’t suffer from the problems of the mapping, but it is annoying in other ways. For example, if I am in the middle of the file it’s going to jump all the way to top and then work down to the bottom. I’d much rather start from the middle, work down from there, and then loop around to the top and continue back down to the middle, ending where I started.

So I make a little custom function to do what I want. After using it for while it seems solid enough to extract into a plugin.

25

commit 00c80650a97b058aeda61d63a574597fda353c31
Author: Greg Hurrell <greg@hurrell.net>
Date:   Fri Apr 29 08:38:05 2016 -0700

    vim: extract and cut over to Scalpel plug-in

    * roles/dotfiles/files/.vim/pack/bundle/start/scalpel 9fc9050...672c2a>
      > Ignore release archives
      > Add README
      > Rename ScalpelSubstitute to Scalpel
      > Denest
      > Rename :Substitute to :Scalpel
      > Add validation of command name
      > Add basic configuration
      > Add standard plug-in boilerplate
      > Add LICENSE.md
      > Add license headers
      > Carry "a" flag around when looping back to top of buffer
      > Drop empty trailing comment
      > Rename autoloaded functions to match directory structure
      > Import base from dotfiles

As you can see, it’s a little over 40 lines of Vimscript all up.

Making something into a plug-in applies a constructive kind of pressure, for the same reasons that making anything open source can increase its quality. It doesn’t matter if nobody ever uses it; the mere fact that they might is an incentive to pay attention to edge cases, provide documentation and so on.

26

From then on it’s a case of relentlessly improving the snippet until there is nothing left to fix, or you run into some insurmountable barrier that stops further progress.

What we’re looking at here is the entire commit history for the Scalpel project over the course of four years. Most of the commits are just chores, but I’ve highlighted the actual substantive improvements and fixes using arrows. They’re just small things, like:

  • Fixing a Vimscript edge case.
  • Adding configuration options.
  • Adding ability to work VISUAL mode.
  • Following best practices for autocmds.
  • Suppressing unwanted messages.
  • Adding support for pattern delimiters other than slashes.
  • Fixing a bug with replacement sequences.
  • Fixing compatibility with old Vim versions.
  • Respecting the 'gdefault' setting.
  • Hardening the code to guard against nested :redir commands.
  • Adding some missing escaping.

That’s all of them. Some are little things that I noticed from using the plugin. Others came in from user reports for bugs that I never would have run into on my own. And there are one or two things that result from pressure from users to support new use cases; nothing that takes us into the territory of "bloat", just little things. But without a doubt the code is better for having been exposed to community usage, and it taught me something along the way. For example, that 'gdefault' setting, which I’d never heard of until a user brought it up.

27

So at the end of this process, what happened to my 40 lines of Vimscript? The bulk of the plug-in is actually comments now (308 lines). Those are extracted and transformed into documentation. The non-comment source lines tally up to 135 in all, so it’s still small.

       2 text files.
classified 2 files
       2 unique files.
       0 files ignored.

github.com/AlDanial/cloc v 1.84  T=0.06 s (33.4 files/s, 7795.0 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
vim script                       2             24            308            135
-------------------------------------------------------------------------------
SUM:                             2             24            308            135
-------------------------------------------------------------------------------

28

So the story of Scalpel is just one example of axe-sharpening taken from a decade of dotfile tweaking and workflow optimization.

I want to close with this XKCD comic which may well have been hovering around in the back of your mind ever since the beginning. It seeks to answer the question of how much optimization is too much? You wouldn’t work for a day to optimize a minute-long task that you rarely perform, but you might do it if the task was frequent enough or costly enough. The point is, there actually is an objective guideline that you can follow to ensure that your investment in axe-sharpening is appropriate and proportional to the expected benefit. Being aware of the trade-off here can keep us away from obsessively refactoring, or polishing our tools as a way of procrastinating.

If we’re pragmatic, axe-sharpening can be not only a lot fun, but a great productivity booster as well. I hope you’re all feeling motivated to continue the good work of refining your set-ups.

29

Before I go, I’m going to leave you with some links to those famous dotfiles of mine (to be stolen from, not forked), as well as my blog, where I will be posting a transcript of this talk, and my YouTube channel, where I will upload a high-quality version of for posterity.

Thanks for listening and good luck!