dammIT - howtohttps://dammit.nl/2023-12-06T16:40:02+01:00A rantboxNerdFonts on ChromeOS2023-12-06T16:40:02+01:002023-12-06T16:40:02+01:00Michiel Scholtentag:dammit.nl,2023-12-06:/chromeos-nerdfonts.html<p><img alt="ChromeOS hterm with NerdFonts-enabled vim" src="https://shuttereye.org/images/49/4941616121616125_2000-2000.png"></p>
<p>I get way too much 'kick' out of a <a href="https://dammit.nl/monaspaced.html">good font</a>, and the <a href="https://www.nerdfonts.com/">Nerd Fonts</a> project has been doing an awesome job at combining about every monospace font with glyphs/icons from FontAwesome, Devicons etc, for use in vim, terminal prompts and more. Of course I combine my frequent use …</p><p><img alt="ChromeOS hterm with NerdFonts-enabled vim" src="https://shuttereye.org/images/49/4941616121616125_2000-2000.png"></p>
<p>I get way too much 'kick' out of a <a href="https://dammit.nl/monaspaced.html">good font</a>, and the <a href="https://www.nerdfonts.com/">Nerd Fonts</a> project has been doing an awesome job at combining about every monospace font with glyphs/icons from FontAwesome, Devicons etc, for use in vim, terminal prompts and more. Of course I combine my frequent use of terminals with the lovely fonts above and my wielding of a variety of gadgets, among which two ChromeOS-based 2-in-1 tablets, which means the default configuration of the terminal on these devices falls short of expectations.</p>
<p>The built-in monospace fonts in the so-called <code>hterm</code> terminal on Chromebooks has some extra glyphs, but by far not the complete set of icons that we have grown to expect from the likes of NerdFonts.</p>
<p>How to fix?</p>
<p>Start with opening the extended terminal/SSH preferences by pasting (or typing) this URL in Chrome: <code>chrome-untrusted://terminal/html/nassh_preferences_editor.html</code> and point the 'Custom CSS (URI)' field to a URL hosting a CSS file with content this one:</p>
<pre><code class="language-css">@font-face {
font-family: "Hack Sans Mono Nerd";
src: url("https://cdn.example.com/chromeos/HackNerdFontMono-Regular.ttf");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "JetBrains Sans Mono Nerd";
src: url("https://cdn.example.com/chromeos/JetBrainsMonoNerdFontMono-Regular.ttf");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "DejaVu Sans Mono Nerd";
src: url("https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/patched-fonts/DejaVuSansMono/Regular/complete/DejaVu%20Sans%20Mono%20Nerd%20Font%20Complete%20Mono.ttf");
font-weight: normal;
font-style: normal;
}
</code></pre>
<p>This of course assumes you have access to a webserver to host such a file on, preferably with some of the fonts too. We'll skip over that part here for scope's sake.</p>
<p>In the 'Text font family' input field, type the name of the font you'd like to use, for example <code>'Hack Sans Mono Nerd', monospace</code> (this falls back to the default <code>monospace</code>).</p>
<p>Now comes the fun part, as serving this file is pretty easy, but the <code>hterm</code> ChromeOS terminal does not load the styling or the font files if the relevant cross-origin headers are not set correctly on the webserver; this would mean that the server would tell the client (generally the browser, in our case the terminal-that's-really-just-a-browser-window) that it is not allowed to load the content when it is not from the same domain name/server/location. As the ChromeOS terminal loads from a local resource on the Chromebook, of course it will never match your webserver's location, so we will have to take that into account.</p>
<p>Thankfully, the mentioned headers are there to tell the webserver what to - er, well - tell the client. <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin">Access-Control-Allow-Origin</a> is needed to accept loading the files from any location, and the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">Cross-Origin-Embedder-Policy</a> ('COEP') related headers are there to tell the client that it is allowed to use the files as resources in whatever it is trying to show. This latter one would normally prevent the loading of the stylesheet file with a line about 'COEP'; you can check that by typing <kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>j</kbd> to open the dev tools while having a terminal window opened. The messages show up in the Console.</p>
<p>Now, to configure the webserver.</p>
<p>nginx config, for example:</p>
<pre><code> location / {
root /srv/www/cdn.example.com/;
location ~* \.(css|eot|ttf|woff|woff2)$ {
# Allow remote loading of fonts, e.g., when developing
add_header Access-Control-Allow-Origin *;
add_header Cross-Origin-Resource-Policy cross-origin;
add_header Cross-Origin-Embedder-Policy require-corp;
add_header Cross-Origin-Opener-Policy same-origin;
}
}
</code></pre>
<p>Apache config, for example:</p>
<pre><code> DocumentRoot /srv/www/cdn.example.com
<Directory />
# Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Origin *
Header set Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type,Authorization,X-Requested-With"
Header set Access-Control-Allow-Credentials "true"
Header add Cross-Origin-Resource-Policy "cross-origin"
Header add Cross-Origin-Embedder-Policy "require-corp"
Header add Cross-Origin-Opener-Policy "same-origin"
</Directory>
</code></pre>
<p>Restart the webserver software, close all terminal windows on your Chromebook, and try the font by opening a fresh ChromeOS terminal.</p>
<p><img alt="starship.rs prompt" src="https://dammit.nl/images/content/20231206_chromeos_terminal_starship_prompt.png"></p>
<h2>Other ways, not always working</h2>
<p><kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>j</kbd> to open the dev tools while having a terminal window opened. Go to the Javascript Console. Paste these commands, first adjusting to your wishes:</p>
<pre><code class="language-javascript">term_.prefs_.set('font-family', 'JetBrains Mono Nerd Font, monospace');
term_.prefs_.set('user-css-text', '@font-face {font-family: "JetBrains Mono Nerd Font"; src: url("https://cdn.example.com/chromeos/JetBrainsMonoNerdFontMono-Regular.ttf)"); font-weight: normal; font-style: normal;} x-row {text-rendering: optimizeLegibility;font-variant-ligatures: normal;}')
// or:
term_.prefs_.set('user-css-text', '@font-face {font-family: "JetBrains Mono Nerd Font"; src: url("https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/patched-fonts/JetBrainsMono/Ligatures/Regular/JetBrainsMonoNerdFont-Regular.ttf)"); font-weight: normal; font-style: normal;} x-row {text-rendering: optimizeLegibility;font-variant-ligatures: normal;}')
term_.prefs_.set('font-family', 'DejaVu Sans Mono Nerd');
term_.prefs_.set('user-css-text', '@font-face {font-family: "DejaVu Sans Mono Nerd"; src: url("https://raw.githubusercontent.com/ryanoasis/nerd-fonts/master/patched-fonts/DejaVuSansMono/Regular/complete/DejaVu%20Sans%20Mono%20Nerd%20Font%20Complete%20Mono.ttf"); font-weight: normal; font-style: normal;}')
</code></pre>
<p>This method should work too, but might need re-applying after a reboot. It has as pre that you do not need to host a stylesheet somewhere.</p>Playing audio/music on Steam Deck from other device2023-12-05T21:42:04+01:002023-12-05T21:42:04+01:00Michiel Scholtentag:dammit.nl,2023-12-05:/steamdeck-bluetooth-audio.html<p><img alt="Steam Deck playing Ori and the Blind Forest" src="https://shuttereye.org/images/e4/e4e4e86969f04fc6_2000-2000.jpg"></p>
<p>Recently I acquired the Linux gaming handheld better known as the Valve Steam Deck, pictured above sitting on top of a cozy plaid as winter is here. Getting one was kind of a gamble for me, as I was not entirely sure I would be into handheld gaming, but I …</p><p><img alt="Steam Deck playing Ori and the Blind Forest" src="https://shuttereye.org/images/e4/e4e4e86969f04fc6_2000-2000.jpg"></p>
<p>Recently I acquired the Linux gaming handheld better known as the Valve Steam Deck, pictured above sitting on top of a cozy plaid as winter is here. Getting one was kind of a gamble for me, as I was not entirely sure I would be into handheld gaming, but I really like it so far. One of the objectives for me was to finally play some of the games that have been gathering dust in my Steam library, and force myself to play some platformers - a genre I've been pretty bad at since forever. It makes it easy for me to play for a bit on the couch instead of having to go upstairs to my home office where The Workstation resides.</p>
<p>A great thing is that it plays pretty much everything I throw at it, often better than expected. The OLED screen (of course I got the newly revised edition) looks amazing too, even though it's "only" 1280x800 pixels. This is perfectly fine for its 7.4" size, and the great colours and inky blacks make for a mighty fine visual experience.</p>
<p>It courageously has a jackplug for headphones (the USB-C cable pictured at the right above is used for charging, and data if you like), so I happily use my headphones with it to enjoy the musical soundscapes of the games. While playing around, I discovered that when I paired my phone with the Deck, the Deck showed up as a target for playing audio too, and lo and behold, it mixes whatever I play on my phone right through whatever I'm doing on the Deck! This means that I can play music from my phone (or other device), or listen to the audio of some YouTube clip or similar, while seamlessly using the headphone plugged into the gaming device in my lap.</p>
<p>But Mike, you say, how in the Light did you do accomplish that magical feat?!</p>
<p>Press the <kbd>Steam</kbd> button to the left of the screen, choose <kbd>Power</kbd> and '<kbd>Switch to Desktop</kbd>'. Find the Bluetooth settings next to the clock or in the settings, and check the 'Show all devices' option to ensure it also shows phones and similar devices. Pair, then try playing something from your other device. Neat ey? Now tap the shortcut on the desktop to go back to gaming mode and enjoy your enhanced audio experience.</p>
<p>I use Arch btw.</p>Transplanting files and directories to other repository keeping Git history2023-01-12T10:26:47+01:002023-01-12T10:26:47+01:00Michiel Scholtentag:dammit.nl,2023-01-12:/transplanting-files-keeping-git-history.html<p>Recently, I wanted to split off a few files from a Git repository in which I keep notes to a repository of their own. Reason was that they served an entirely different purpose than the rest, so it made more sense to separate the two sets.</p>
<p>However, they had quite …</p><p>Recently, I wanted to split off a few files from a Git repository in which I keep notes to a repository of their own. Reason was that they served an entirely different purpose than the rest, so it made more sense to separate the two sets.</p>
<p>However, they had quite some commit history in the original repository, and I didn't want to lose that. Thankfully, I found a neat way of doing just that.</p>
<p>If your history is sane, you can take the commits out as patch and apply them in the new repository:</p>
<pre><code class="language-bash">cd repository
git log --pretty=email --patch-with-stat --reverse --full-index --binary -m --first-parent -- path/to/file_or_folder > patch
cd ../another_repository
git am --committer-date-is-author-date < ../repository/patch
</code></pre>
<p>In the <code>patch</code> file (which you can of course name however you like), you can edit the paths if you like before importing again in the other repository; it is just a text file with all the commits in email format. Editing paths is for example useful when you have files in some subdirectory, and now want them in the root of the new repository, or in another subdirectory, or rename the files altogether.</p>
<p>Alternatively, you can do it in one line (of course skipping any renaming this way):</p>
<pre><code class="language-bash">git log --pretty=email --patch-with-stat --reverse --full-index --binary -m --first-parent -- path/to/file_or_folder | (cd /path/to/new_repository && git am --committer-date-is-author-date)
</code></pre>
<p><a href="https://stackoverflow.com/a/11426261">source</a></p>Fixing CS:GO on Ubuntu 21.102021-11-18T10:36:51+01:002021-11-18T10:36:51+01:00Michiel Scholtentag:dammit.nl,2021-11-18:/fixing-csgo-ubuntu2110.html<p>Yesterday evening, my little gaming group came together online to play some Counter Strike: Global Offence (CS:GO), as a deviation from our regular battles in <a href="https://www.openra.net/">OpenRA</a> (which is great fun by the way).</p>
<p>We played CS:GO before, but for some reason when I launched it from Steam now …</p><p>Yesterday evening, my little gaming group came together online to play some Counter Strike: Global Offence (CS:GO), as a deviation from our regular battles in <a href="https://www.openra.net/">OpenRA</a> (which is great fun by the way).</p>
<p>We played CS:GO before, but for some reason when I launched it from Steam now, it would show a black screen (or window when launched with the <code>-windowed</code> option) for some seconds, then crash to desktop. The output when run from a terminal (just launch <code>steam</code> there, it's easiest) was not particularly helpful and first sent me on a red herring chase that cost me way too much time, as I saw a bunch of mentions of messages like <code>from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32)</code> which means issues with 32-bit libraries. I thought that updating to Ubuntu 21.10 a while ago had hosed the 32-bit libraries needed to run games.</p>
<p>Turned out, that was just fine. Portal 2 ran fine too, which was a good sign, as it is also a native version on Linux, and basically using the same engine. So... that was odd. I had already tried switching to the Windows version by manually setting Compatibility to some Proton version, but that didn't help either.</p>
<p>I proceeded to uninstall the game and reinstall, which meant re-downloading about 13GB of data (while the others were having fun being killed by too many bots in our server). Of course I then stumbled upon mentions on <a href="https://www.protondb.com/app/730">ProtonDB</a> that this was a problem for a lot of others too, so - er - yeah. Thankfully <a href="https://www.protondb.com/app/730#3sdJcdGT5K">there was a fix</a>:</p>
<pre><code class="language-bash"># Go to the CS:GO dir in your steam library; this might be located somewhere else, check
# 'Local files' in the game's properties ('Browse')
cd ~/.steam/steamapps/common/Counter-Strike Global Offensive/bin
ln -s /usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4.5.9 libtcmalloc_minimal.so.0
# or:
cp /usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4.5.9 libtcmalloc_minimal.so.0
</code></pre>
<p>This will cause CS:GO to use the right tcmalloc library, which apparently was the problem. Presto, game time!</p>
<p><em>N.B.:</em> I already was using the <code>-nojoy</code> launch option, as without that, CS:GO would not launch either (this let it ignore the joystick/controller stuff from Steam). Also of help might be the <code>-novid</code> launch option to skip some videos.</p>Presenting presenting2021-03-20T08:48:45+01:002021-03-20T08:48:45+01:00Michiel Scholtentag:dammit.nl,2021-03-20:/link-presenting-presenting.html<p>Tips and thoughts on preparing and giving engaging presentations.</p>
<p>As a person who does not give presentations often (lots of reasons), the points and pointers in this article sound really helpful.</p>
<p>Also, one of the better explanations about why a full, information dense slide is unhelpful:</p>
<blockquote>
<p>Now imagine the audience …</p></blockquote><p>Tips and thoughts on preparing and giving engaging presentations.</p>
<p>As a person who does not give presentations often (lots of reasons), the points and pointers in this article sound really helpful.</p>
<p>Also, one of the better explanations about why a full, information dense slide is unhelpful:</p>
<blockquote>
<p>Now imagine the audience when one of these dense slides comes up. I start explaining how things work, but the audience is busy trying to parse what’s in the slide. They’ve completely tuned me out because that’s what happens. (Have you ever noticed that when you start reading an email when your spouse is talking you completely lose track of what they’re saying until they clap you across the side of the head? The same thing happens in presentations (minus the head shot); we process language in a single thread and can’t possibly maintain concentration on the speaker’s words when there are a lot of other words to process on a slide.)</p>
</blockquote>A question about statically generated websites2021-01-10T10:22:26+01:002021-01-10T10:22:26+01:00Michiel Scholtentag:dammit.nl,2021-01-10:/question-about-statically-generated-websites.html<p>When <a href="https://dammit.nl/isso-comments-are-up-again.html">I made a remark that my commenting system is working again</a>, a reader asked a simple enough question: how does one build a site like this?</p>
<p>I realised there is no simple answer to this.</p>
<p>Well, there is, but it takes a bunch of knowledge (and skills) one has …</p><p>When <a href="https://dammit.nl/isso-comments-are-up-again.html">I made a remark that my commenting system is working again</a>, a reader asked a simple enough question: how does one build a site like this?</p>
<p>I realised there is no simple answer to this.</p>
<p>Well, there is, but it takes a bunch of knowledge (and skills) one has to have before starting, like knowing how to use Git, knowing a bit about hosting, about Python and its virtualenvs, some experience with the command line, and likely some minor-but-important details I'm forgetting now. Oh, and how about a commenting system?</p>
<p>The dammIT website is generated by software called <a href="https://docs.getpelican.com/en/latest/">Pelican</a> and its html files, stylesheets etc are located on one of my webservers.</p>
<p>A good <a href="https://medium.com/@acalamea/step-by-step-guide-to-setup-a-web-site-using-pelican-and-gitpages-5de976ae44cb">quickstart about using Pelican on for example GitHub pages</a> (a quick way of letting GitHub host your website) goes a long way into setting up something similar, but it assumes knowledge about using the <a href="https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control">Git versioning system</a>, the command line, and <a href="https://pypi.org/project/pip/">Python pip</a>, which not everyone is familiar with (yet). This is totally fine, one can learn, but it provides some hoops to jump through.</p>
<p>This is true for every way you can setup a website of your own nowadays, apart from using some hosted, turn-key solution like <a href="https://www.squarespace.com/">Squarespace</a> in which all the magic is hidden and you only have to fill in the blanks.</p>
<p>There are few shortcuts to take to go from zero knowledge to have a website of your own running, so it will always take some learning, and I think that is part of the fun. So what I want to do, is write a few posts/articles:</p>
<ul>
<li>a technical one, with detailed insight in how my weblog, this site called dammIT, is set up, how things are generated, and how comments are made possible</li>
<li>an article in which I will explore possibilities to make it easier to set up a statically generated site yourself, referring to and extending guides like the above mentioned quickstart</li>
</ul>
<p>These are likely going to be pretty long ones, so it will take a bit to write them. Still, they might be of help for someone :)</p>isso comments are up again2021-01-08T11:45:48+01:002021-01-08T11:45:48+01:00Michiel Scholtentag:dammit.nl,2021-01-08:/isso-comments-are-up-again.html<p>Commenting had been broken since the 19th of December because of the host having upgraded to Python 3.9 and <a href="https://github.com/posativ/isso">isso</a> breaking. I tried installing it anew from pip, but there is still a really old version on there; installing it as egg directly from its Git repository<sup id="fnref:1"><a class="footnote-ref" href="#fn:1">1</a></sup> kind …</p><p>Commenting had been broken since the 19th of December because of the host having upgraded to Python 3.9 and <a href="https://github.com/posativ/isso">isso</a> breaking. I tried installing it anew from pip, but there is still a really old version on there; installing it as egg directly from its Git repository<sup id="fnref:1"><a class="footnote-ref" href="#fn:1">1</a></sup> kind of works, but the Javascript needs to be compiled, otherwise it will not work. <code>require.js</code> and such have been removed from the codebase, so just linking to the regular JS files does not work. Also, on my Ubuntu 20.10 machine, somehow <code>make js</code> does not want to build the minified Javascript files either.</p>
<p>Instead, I borrowed the <a href="https://raw.githubusercontent.com/redradishtech/isso/master/isso/js/embed.min.js">embed.min.js</a> from jefft linked from <a href="https://github.com/posativ/isso/issues/656">this isso bug</a>. Now comments are back, to not be used like before ;)</p>
<div class="footnote">
<hr>
<ol>
<li id="fn:1">
<p><code>pip install git+https://github.com/posativ/isso.git@master#egg=isso</code> <a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text">↩</a></p>
</li>
</ol>
</div>YouCompleteMe requiring a rather new vim2021-01-08T10:16:38+01:002021-01-08T10:16:38+01:00Michiel Scholtentag:dammit.nl,2021-01-08:/vim-youcompleteme-requirement.html<p>If you are even remotely using the same workflows as me, you will be using vim quite a bunch, and not limited to one machine with a given operating system. You might also have taken a liking to YouCompleteMe to serve as the code/word completion solution of choice.</p>
<p>The …</p><p>If you are even remotely using the same workflows as me, you will be using vim quite a bunch, and not limited to one machine with a given operating system. You might also have taken a liking to YouCompleteMe to serve as the code/word completion solution of choice.</p>
<p>The <a href="https://github.com/ycm-core/YouCompleteMe">YouCompleteMe project</a> has a policy to support the Vim version that's in the latest LTS of Ubuntu. That's currently Ubuntu 20.04 which contains vim-nox at v8.1.2269. Which is fine, and enables their codebase to move forward and not be burdened with a lot of if-else's for older versions of vim and such.</p>
<p>However.</p>
<p>I am also using Debian 10 and CentOS machines, which are not as fly as the latest Ubuntu release. Debian 10 Buster for example (among other places used as the Linux VM on Chrome OS), has 8.1.0875 which is an amount of patch levels below the minimal requirement set by YCM. Commit '<a href="https://github.com/ycm-core/YouCompleteMe/commit/d98f896">d98f896</a>' of YCM is the latest compatible with this version, so I could pin the plugin on that revision with a <code>Plug 'Valloric/YouCompleteMe', { 'commit':'d98f896' }</code>. On the other hand, as mentioned, I'm using multiple devices, quite some actually having a more recent vim, so on those I want the latest and greatest YCM available to me.</p>
<p>Enter the patch-level/version check available to be used in vim config files. In <code>~/.vimrc</code> I changed my regular <code>Plug</code> line into the following:</p>
<pre><code>if has('patch-8.1.2269')
" Latest YCM needs at least this version of vim
Plug 'ycm-core/YouCompleteMe'
else
" Version compatible with the vim in Debian 10 buster
Plug 'ycm-core/YouCompleteMe', { 'commit':'d98f896' }
endif
</code></pre>
<p>And done :)</p>
<p>On the older machines, manually check out the relevant YCM commit, or just remove <code>~/.vim/plugged/YouCompleteMe</code> and update your vim plugins (<code>:PlugUpdate</code> with <a href="https://github.com/junegunn/vim-plug">vim-plug</a>).</p>
<p><a href="https://github.com/ycm-core/YouCompleteMe/issues/3764">Relevant bugreport</a>.</p>Ripping a DVD, Linux style2020-12-06T19:56:54+01:002020-12-06T19:56:54+01:00Michiel Scholtentag:dammit.nl,2020-12-06:/ripping-dvd.html<p>Recently we got a DVD. After turning it around in our hands a few times and giggling at our reflections, we ordered an external USB DVD/CD eater so we actually could ingest some of its contents.</p>
<p>As the hip techy people we are, having this material available to us …</p><p>Recently we got a DVD. After turning it around in our hands a few times and giggling at our reflections, we ordered an external USB DVD/CD eater so we actually could ingest some of its contents.</p>
<p>As the hip techy people we are, having this material available to us in a less physical way made me look up the exact <code>dd</code> usage to dump the contents of the disk to an image file.</p>
<p>As a wise person on the internet said:</p>
<blockquote>
<p>You should really use <code>isoinfo -d -i /dev/cdrom</code> (ed: or <code>/dev/sr0</code> or whatever your device is) to find out the logical block size (almost always 2048) and the number of blocks ("Volume size is" line) on the volume to pass as arguments to dd. Which makes the dd command look like <code>dd if=/dev/cdrom bs=2048 count=1621535 of=filename.iso</code></p>
</blockquote>
<p>[<a href="https://askubuntu.com/questions/147800/ripping-dvd-to-iso-accurately">source of those pointers</a>]</p>
<p>Be advised that the <code>if=</code> and <code>of=</code> parameters do not expand file paths, so using <code>of=~/Videos/interesting_dvd.iso</code> will not work; use the full path in that case.</p>About feeds (RSS, Atom)2020-08-16T10:23:50+02:002020-08-16T10:23:50+02:00Michiel Scholtentag:dammit.nl,2020-08-16:/link-aboutfeeds.html<p>Use web feeds to subscribe to websites and get the latest content in one place.</p>
<p>Feeds put you in control. It’s like subscribing to a podcast, or following a company on Facebook. You don’t need to pay or hand over your email address. You get the latest content …</p><p>Use web feeds to subscribe to websites and get the latest content in one place.</p>
<p>Feeds put you in control. It’s like subscribing to a podcast, or following a company on Facebook. You don’t need to pay or hand over your email address. You get the latest content without having to visit lots of sites, and without cluttering up your inbox. Had enough? Easy: unsubscribe from the feed.</p>
<p>You just need a special app called a newsreader.</p>
<p>This site explains how to get started.</p>
<p><a href="https://rix.si/">Via Ryan Rix</a></p>
<p>Source: <a href="https://aboutfeeds.com/">About Feeds</a></p>projectM on Ubuntu2020-04-25T14:41:37+02:002020-04-25T14:41:37+02:00Michiel Scholtentag:dammit.nl,2020-04-25:/projectm-ubuntu.html<p><img alt="projectM on external monitor next to laptop" src="https://shuttereye.org/images/7d/7d6c6c3e91998d1c_2000-2000.jpg"></p>
<p>Lately, I was thinking back to the time when I had my 15" CRT monitor (and later my whopping 19" flat CRT) tuned to the beats that Winamp was playing for me. It was a famous plugin called <a href="https://en.wikipedia.org/wiki/MilkDrop">Milkdrop</a>, and it provided nicely psychedelic looking visuals based on the audio …</p><p><img alt="projectM on external monitor next to laptop" src="https://shuttereye.org/images/7d/7d6c6c3e91998d1c_2000-2000.jpg"></p>
<p>Lately, I was thinking back to the time when I had my 15" CRT monitor (and later my whopping 19" flat CRT) tuned to the beats that Winamp was playing for me. It was a famous plugin called <a href="https://en.wikipedia.org/wiki/MilkDrop">Milkdrop</a>, and it provided nicely psychedelic looking visuals based on the audio and beats that Winamp was playing at that moment. I often had it just running during music playback while doing homework, reading or otherwise just chilling in my room.</p>
<p>I knew about <a href="https://github.com/projectM-visualizer/projectm">projectM</a>, which is an opensource re-implementation of all of this, with support for the original presets and visualisations. It both provides libraries to include in a music application, as some stand-alone binaries that plug into PulseAudio or Jack. The fun part of the latter is that you can use whatever audio source you want (including Youtube and such), run projectM and have it all work seamlessly together. Count me in!</p>
<p>After some digging around, I came to the conclusion that pre-built binaries in Debian and Ubuntu were ancient, and basically only Arch had up-to-date stuff. No worries, lets build from source. Oh, that has a few gotcha's, as the various <a href="https://livingthelinuxlifestyle.wordpress.com/2019/06/03/how-to-install-projectm-audio-visualizations/">howto</a>'s I found online were already outdated, or tried to do too much (I do not need Jack integration, PulseAudio will suffice).</p>
<p>I successfully built and used the visualisations on Ubuntu 19.10 and the new 20.04, with the same steps.</p>
<p>So here goes:</p>
<pre><code># Install the packages that are needed for building; Qt5 for the GUI, PulseAudio as the audio server.
sudo apt install libtool pkg-config libglm-dev qt5-default qtdeclarative5-dev libgles2-mesa-dev libpulse-dev
</code></pre>
<p>Then clone <a href="https://github.com/projectM-visualizer/projectm">the project</a> or <a href="https://github.com/projectM-visualizer/projectm/releases">download the latest release</a>, and <code>cd</code> into the directory. From there, do:</p>
<pre><code>autoreconf --install # only needed if this is a git clone
./configure --enable-pulseaudio --enable-qt --enable-gles LIBS="-lQt5Gui -lQt5OpenGL"
</code></pre>
<p>This will list the things that will be enabled in this build. Make sure both Qt and PulseAudio have a <code>yes</code> behind them, like here:</p>
<pre><code>Applications:
=====
libprojectM: yes
Threading: yes
SDL: no
Qt: yes
Pulseaudio: yes
Jack: no
OpenGLES: yes
Emscripten: no
llvm: no
Preset subdirs: no
</code></pre>
<p>This means the <a href="https://www.qt.io/">Qt</a> frontend will be built, and Pulseaudio support will be included.</p>
<p>Now do:</p>
<pre><code>make
sudo make install
</code></pre>
<p>The first command will take a while, the second will take care of installing the binaries, libraries and all the plugins, and will be done a tad faster. You might see some warnings during the <code>make</code>, especially in the Qt code, but as long as it's just warnings, you will be fine.</p>
<p>You can now start projectM by launching <code>projectM-pulseaudio</code>. Right click the window that appears and fiddle with the settings as you please. Play some music and ensure the right Pulseaudio output is selected. Enjoy!</p>
<p>PS: if you get a message about the presets not being found in <code>/usr/share/projectM/presets</code>, close projectM, open <code>~/.projectM/config.inp</code> in a text editor and change the <code>Preset Path</code> to <code>/usr/local/share/projectM/presets</code>.</p>Roundcube webmail and Google contacts2020-01-25T13:48:00+01:002020-01-25T13:48:00+01:00Michiel Scholtentag:dammit.nl,2020-01-25:/roundcube-google-contacts.html<p>Draft digging time! Something I've had in my drafts since the 25th of October, 2014, apparently:</p>
<p>Roundcube is a decent self-hosted webmail solution, which benefits from integrating Google Contacts so you do not have to duplicate your address books (assuming you use Google for yours).</p>
<p>Luckily someone wrote a plugin …</p><p>Draft digging time! Something I've had in my drafts since the 25th of October, 2014, apparently:</p>
<p>Roundcube is a decent self-hosted webmail solution, which benefits from integrating Google Contacts so you do not have to duplicate your address books (assuming you use Google for yours).</p>
<p>Luckily someone wrote a plugin:</p>
<ul>
<li><a href="https://github.com/stwa/google-addressbook">Google Addressbook for Roundcube</a></li>
<li><a href="http://plugins.roundcube.net/packages/stwa/google-addressbook">Plugin in Roundcube's plugin library</a></li>
</ul>
<p>The <a href="http://plugins.roundcube.net">howto for installing plugins in Roundcube</a> tells you how to install those plugin bundles. It works with <a href="https://getcomposer.org/download/">Composer</a>, which uses a really bad anti-pattern to install: <code>curl -sS https://getcomposer.org/installer | php</code>, so piping code straight from the internet through an interpreter. This is <em>NOT</em> something you want to do, really.</p>
<p>See the plugin page for further install instructions.</p>
<p>Now enable a repeated sync, so open the relevant crontab and enter a line like this:</p>
<pre><code>0 */8 * * * /srv/www/example.com/roundcube/plugins/google_addressbook/sync-cli.sh
</code></pre>
<p>The above example downloads your Google Contacts to the Roundcube address book every 8 hours.</p>vim reloaded2020-01-15T12:56:00+01:002020-01-25T14:16:00+01:00Michiel Scholtentag:dammit.nl,2020-01-15:/vim-reloaded.html<p><img alt="Screenshot of vim with its logo in ascii art" src="https://shuttereye.org/galleries/various/screenshots/20200115_vim_logo_asciiart.png"></p>
<p>An update about what I do with vim, making it more powerful and taking away some of the envy I have for the excellent IDE's out there (for example PyCharm and the rest of the IntelliJ family by JetBrains - try it, it's awesome). Also, it makes vim look a lot …</p><p><img alt="Screenshot of vim with its logo in ascii art" src="https://shuttereye.org/galleries/various/screenshots/20200115_vim_logo_asciiart.png"></p>
<p>An update about what I do with vim, making it more powerful and taking away some of the envy I have for the excellent IDE's out there (for example PyCharm and the rest of the IntelliJ family by JetBrains - try it, it's awesome). Also, it makes vim look a lot better in the progress.</p>
<p>I will be talking about my vim configuration as <a href="https://github.com/aquatix/dotfiles/blob/b8a69a86ec39d1585399523ad75256a1413001f0/.vimrc">it is currently in my dotfiles repository</a>. You can always find <a href="https://github.com/aquatix/dotfiles/blob/master/.vimrc">the latest version here</a> and maybe have some inspiration from <a href="https://github.com/aquatix/dotfiles">the rest of my dotfiles</a>.</p>
<p>To get an impression how things currently look, take a look at this example:</p>
<p><a href="https://shuttereye.org/various/screenshots/20200113_vim_nerdtree_tagbar.png/view/"><img alt="Current vim as python IDE" src="https://shuttereye.org/galleries/various/screenshots/20200113_vim_nerdtree_tagbar.png"></a></p>
<p>In the years since the <a href="https://dammit.nl/20140301-making-vim-even-more-cool.html">first time I showed my vim setup</a>, I went through:</p>
<p><a href="https://shuttereye.org/various/screenshots/20170519_vim_python.png/view/"><img alt="vim as python IDE" src="https://shuttereye.org/images/da/dad25a53d293b7d2_2000-2000.png"></a></p>
<p>and</p>
<p><a href="https://shuttereye.org/various/screenshots/20170519_vim_ctrlp.png/view/"><img alt="vim with ctrl+p quick lookup" src="https://shuttereye.org/images/88/88a1a1a18185a8d0_2000-2000.png"></a></p>
<p>to arrive at the above.</p>
<h2>Vundle as plugin manager</h2>
<p>There are various plugin managers, and I settled on <a href="https://github.com/VundleVim/Vundle.vim">Vundle</a>, like <a href="https://dammit.nl/20140301-making-vim-even-more-cool.html">I mentioned in 2014</a> for a long time. This served me well, but recently I switched to <a href="https://github.com/junegunn/vim-plug">vim-plug</a>. Both accomplish the same thing (with slightly different syntax), but vim-plug downloads and updates the plugins in parallel, which is a lot faster. It also makes loading vim a tad faster, which is always good. A fun extra feature is that after a <code>:PlugUpdate</code> of all plugins, you can press <kbd>D</kbd> and get a neat overview of all the updates in your plugins, which can be rather handy to see what's new and changed.</p>
<p><a href="https://shuttereye.org/various/screenshots/20200114_vim-plug_updates.png/view/"><img alt="vim-plug after an update" src="https://shuttereye.org/galleries/various/screenshots/20200114_vim-plug_updates.png"></a></p>
<p>You can even revert updates with <kbd>X</kbd>.</p>
<h2>Theming</h2>
<p>After having used Zenburn for many years, I went to <a href="">falcon</a> for a bit, and lately settled on <a href="https://github.com/kristijanhusak/vim-hybrid-material">vim-hybrid-material</a> in the 'reverse' variant, which has nicer gray accents. <a href="https://github.com/vim-airline/vim-airline">vim-airline</a> integrates nicely, and provides an informative bar at the bottom. It can also show a tab bar at the top with open buffers and/or tabs, but I can see those already with a press of <kbd>;</kbd> and I prefer having the extra line available for code.</p>
<p>Additionally, to make airline and nerdtree (see below) look even better, I use <a href="https://github.com/ryanoasis/vim-devicons">vim-devicons</a> for icons. My terminals all use the <a href="https://github.com/source-foundry/Hack">Hack font</a> in the <a href="https://www.nerdfonts.com/">Nerd fonts</a> <a href="https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/Hack">variant</a>, which ensures that the glyphs used are available in the monospaced font of the 'GUI'. <a href="https://github.com/tiagofumo/vim-nerdtree-syntax-highlight">vim-nerdtree-syntax-highlight</a> makes the icons show up in different colours, depending on the file formats.</p>
<pre><code>" Nice colour scheme
Plug 'kristijanhusak/vim-hybrid-material'
" Nice statusbar, alternative for powerline. Get powerline font for best
" looking result
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
let g:airline_theme = "hybrid"
" Disable showing current function in airline
let g:airline#extensions#tagbar#enabled = 0
" Better showing of open buffers (open files), integrates with airline
" Plug 'bling/vim-bufferline'
" Plug 'alisnic/vim-bufferline'
" Ensure 256 colour support if the terminal supports it
if &term == "xterm" || &term == "xterm-256color" || &term == "screen-bce" || &term == "screen-256color" || &term == "screen" || &term == "tmux-256color-italic"
set background=dark
let g:enable_bold_font = 1
let g:enable_italic_font = 1
let g:hybrid_transparent_background = 1
colorscheme hybrid_reverse
" create a bar for airline
set laststatus=2
let g:airline_powerline_fonts = 1
endif
" This is what sets vim to use 24-bit colors. It will also work for any version of neovim
" newer than 0.1.4.
if exists('+termguicolors')
let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
set termguicolors
endif
" Toggle paste and autoindent mode (enable paste so no indention weirdness
" happens when pasting into the current file)
set pastetoggle=<F10>
" Web Development/Filetype icons
" Needs a font like found at
" https://github.com/ryanoasis/nerd-fonts
Plug 'ryanoasis/vim-devicons'
" Set guifont when using gvim:
"set guifont=Droid\ Sans\ Mono\ for\ Powerline\ Plus\ Nerd\ File\ Types\ 11
" reload file when changes happen in other editors
set autoread
" hide buffers instead of closing them (so no saving is needed and undo and
" marks are preserved)
set hidden
</code></pre>
<p>To help with reading code, <a href="https://github.com/Yggdroot/indentLine">indentLine</a> and <a href="https://github.com/luochen1990/rainbow">rainbow brackets</a> is used:</p>
<p><a href="https://shuttereye.org/various/screenshots/20200115_vim_rainbow-brackets_indentline.png/view/"><img alt="vim with matching rainbow brackets and indentLine for indentation guides" src="https://shuttereye.org/galleries/various/screenshots/20200115_vim_rainbow-brackets_indentline.png"></a></p>
<pre><code>" Show indentation marks, enables conceallevel 2, so for example hides quotes
" in json files
Plug 'Yggdroot/indentLine'
let g:indentLine_char = '┊'
"let g:indentLine_setConceal = 0
let g:indentLine_conceallevel = 1
" Colour-match brackets
Plug 'luochen1990/rainbow'
let g:rainbow_active = 1 "set to 0 if you want to enable it later via :RainbowToggle
" Do not use rainbow parentheses in these file types:
let g:rainbow_conf = {
\ 'separately': {
\ 'todo': 0
\ },
\}
</code></pre>
<h2>fzf</h2>
<p>I bound looking through buffers to <kbd>;</kbd>, as I use buffers quite a lot. This way I can quickly switch to another file I have open.</p>
<p>Find more tricks to do with fzf and vim in this article: <a href="http://tilvim.com/2016/01/06/fzf.html">Fuzzy finding with FZF.vim</a>.</p>
<p>Quickly opening files is done through <kbd>leader</kbd>+<kbd>o</kbd>, and looking through the content of files is bound to <kbd>leader</kbd>+<kbd>f</kbd>. This file search leverages the awesome grepping powers of <a href="https://github.com/BurntSushi/ripgrep">ripgrep</a>:</p>
<pre><code>" Find term where term is the string you want to search, this will open up a
" window similar to :Files but will only list files that contain the term
" searched
" https://medium.com/@crashybang/supercharge-vim-with-fzf-and-ripgrep-d4661fc853d2
command! -bang -nargs=* Find call fzf#vim#grep('rg --column --line-number --no-heading --fixed-strings --ignore-case --hidden --follow --color "always" '.shellescape(<q-args>).'| tr -d "\017"', 1, <bang>0)
" Search contents of files with ripgrep
" https://sidneyliebrand.io/blog/how-fzf-and-ripgrep-improved-my-workflow
command! -bang -nargs=* Rg
\ call fzf#vim#grep(
\ 'rg --column --line-number --hidden --smart-case --no-heading --color=always '.shellescape(<q-args>), 1,
\ <bang>0 ? fzf#vim#with_preview({'options': '--delimiter : --nth 4..'}, 'up:60%')
\ : fzf#vim#with_preview({'options': '--delimiter : --nth 4..'}, 'right:50%:hidden', '?'),
\ <bang>0)
" Files command with preview window
command! -bang -nargs=? -complete=dir FilesPreview
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)
" Simply type ; to search through buffers, leader-o to search through file
" names, leader-O to search through file names, showing a preview window,
" \t for tags, \c for (Git) commits and \f to search through contents of files
nmap ; :Buffers<CR>
nmap <Leader>o :Files<CR>
nmap <Leader>O :FilesPreview<CR>
nmap <Leader>t :Tags<CR>
nmap <Leader>c :Commits<CR>
" nmap <Leader>f :Find<CR>
nmap <Leader>f :Rg<CR>
nmap <Leader>l :Lines<CR>
</code></pre>
<p><a href="https://shuttereye.org/various/screenshots/20200115_vim_fzf.png/view/"><img alt="vim with fzf quick lookup" src="https://shuttereye.org/galleries/various/screenshots/20200115_vim_fzf.png"></a></p>
<h2>ctrl+p</h2>
<p>Alternatively, one can still quickly find and open files through the trusty ol' <kbd>ctrl</kbd>+<kbd>p</kbd>:</p>
<pre><code>" Full path fuzzy file, buffer, mru, tag, ... finder
" Quickly open files, fuzzy search on name
Plugin 'ctrlpvim/ctrlp.vim'
"let g:ctrlp_map = '<Leader>t'
let g:ctrlp_map = '<c-p>'
" Search in Files, Buffers and MRU files at the same time:
let g:ctrlp_cmd = 'CtrlPMixed'
let g:ctrlp_match_window_bottom = 1
let g:ctrlp_match_window_reversed = 0
let g:ctrlp_custom_ignore = '\v\~$|\.(o|swp|pyc|wav|mp3|ogg|blend)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])|__init__\.py'
let g:ctrlp_working_path_mode = 0
let g:ctrlp_dotfiles = 0
let g:ctrlp_switch_buffer = 0
</code></pre>
<p><a href="https://shuttereye.org/various/screenshots/20200115_vim_ctrl-p.png/view/"><img alt="vim with ctrl+p quick lookup" src="https://shuttereye.org/galleries/various/screenshots/20200115_vim_ctrl-p.png"></a></p>
<h2>nerdtree</h2>
<p>Yet another way of navigating through files is <a href="https://github.com/preservim/nerdtree">nerdtree</a>, which provides a tree view with directories and files, like in a file manager. <a href="https://github.com/Xuyuanp/nerdtree-git-plugin">nerdtree-git-plugin</a> provides Git status information about the files being listed.</p>
<pre><code>" Quick file system tree, mapped to Ctrl+n for quick toggle
Plug 'preservim/nerdtree'
Plug 'Xuyuanp/nerdtree-git-plugin'
map <C-n> :NERDTreeToggle<CR>
let NERDTreeIgnore = ['\.pyc$', 'tags']
" close vim if the only window left open is a NERDTree
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif
Plug 'tiagofumo/vim-nerdtree-syntax-highlight'
</code></pre>
<h2>Auto-completion</h2>
<p>I keep returning to <a href="https://github.com/ycm-core/YouCompleteMe">YouCompleteMe</a>. I tried <a href="https://github.com/Shougo/deoplete.nvim">deoplete</a> and some others, but somehow YCM works best for me and my fingers. <a href="https://github.com/davidhalter/jedi-vim">jedi-vim</a> provides the magic for Python (together with ctags as mentioned below).</p>
<p>In text, this can even suggest words for you, which makes typing even faster.</p>
<p>The daemon running in the background (ycmd) to do the work for YouCompleteMe needs to be compiled, which basically is running a Python script in <code>~/.vim/plugged/YouCompleteMe/</code>: <code>python3 install.py</code>.</p>
<p><a href="https://shuttereye.org/various/screenshots/20200115_vim_autocomplete.png/view/"><img alt="vim with auto complete from YCM" src="https://shuttereye.org/galleries/various/screenshots/20200115_vim_autocomplete.png"></a></p>
<p>The <code>_3</code> in the margin here means that three lines have been removed.</p>
<h2>Sanity checking of your projects (code quality etc)</h2>
<p><a href="https://github.com/scrooloose/syntastic">Syntastic</a> is fantastic. Sorry, I had to say it that way :) It uses all kinds of tools to check your code for errors, code conventions and more. For Python, you can do PEP-8 checking and such, for example.</p>
<p>However, I since moved on to <a href="https://github.com/dense-analysis/ale">ale</a>, which is even better. It's asynchronous and just has great support for a lot of linters and checkers, like pylint, flake-8, and bandit (security checking) for Python.</p>
<p>You can see the hints in the above screenshot (red x's); these are errors, which get shown in the message bar at the bottom if you navigate the cursor to that line. Warnings get shown too, with different glyphs and colours, all to your liking.</p>
<p>My choice for Python and Django is to use pylint and the <a href="https://github.com/landscapeio/pylint-django">pylint-django plugin</a>:</p>
<pre><code>pip install pylint
pip install pylint-django
</code></pre>
<p>Installing both in the virtualenv of your project will make vim pick up the right modules, so imports get recognised (very useful for imports from modules in your virtualenv, otherwise pylint will get <em>really</em> chatty).</p>
<p>Two other good checkers are flake8 and bandit. Flake8 does a lot of similar things to pylint, and bandit does security checking, notifying you of potentially unsafe ways of Doing Things™.</p>
<pre><code>pip install flake8
pip install bandit
</code></pre>
<p>To have this all play nice with virtualenvs and such, I wrote an <a href="https://github.com/aquatix/dotfiles/blob/master/.vim/after/ftplugin/python.vim">ftplugin file for Python</a>.</p>
<p>Another interesting plugin in this context is <a href="https://github.com/python-mode/python-mode">python-mode</a>. I do not use this myself, but it integrates a lot of the above linters and other very useful Python development stuff. It conflicted a bit with ale and my linters, so I disabled it again (also, it was at places redundant with config I already had and was happy with).</p>
<p><a href="https://github.com/majutsushi/tagbar">vim-tagbar</a> and the keybinding <kbd>ctrl</kbd> + <kbd>]</kbd> (with its reverse <kbd>ctrl</kbd> + <kbd>o</kbd> for 'jump to definition' and 'jump back') make navigating through tags inside your code possible. This is done through the magic of <a href="https://github.com/universal-ctags/ctags">ctags</a>, and I use the <a href="https://github.com/airblade/vim-rooter">vim-rooter</a> plugin to make sure ctags and other lookups, like the one from <code>fzf</code> mentioned above, work from the root of a project. It looks for version repository hints and such.</p>
<h3>ctags is missing</h3>
<p>You need exuberant-ctags installed, otherwise there will be an error. You can do this with <code>sudo apt install exuberant-ctags</code> or <code>brew install ctags</code>.</p>
<h2>Spell checking</h2>
<p>When writing text, having some checks on your spelling can be useful, especially when you are getting tired, writing long pieces and/or not even using your native tongue. I can toggle through various languages using <kbd>F7</kbd> and vim will highlight misspelled words accordingly.</p>
<p>To move to a misspelled word, use <kbd>]s</kbd> and <kbd>[s</kbd>. The <kbd>]s</kbd> command will move the cursor to the next misspelled word, the <kbd>[s</kbd> command will move the cursor back through the buffer to previous misspelled words.</p>
<p>Once the cursor is on the word, use <kbd>z=</kbd>, and Vim will suggest a list of alternatives that it thinks may be correct. With the numbers, you can then quicly replace the word with that suggestion. If you like to add the word to your local dictionary instead, use <kbd>zg</kbd> for 'good'. It will add it to the relevant word lists in <code>~/.vim/spell/</code>.</p>
<p>I found a neat trick to quickly try to fix misspellings with <kbd>ctrl</kbd> + <kbd>l</kbd> on <a href="https://castel.dev/post/lecture-notes-1/">this blogpost</a>. The author has a lot more gems in that article and on others on his site.</p>
<pre><code>" Spell Check (http://vim.wikia.com/wiki/Toggle_spellcheck_with_function_keys)
" Loop through various languages to select the one to spellcheck with
let b:myLang=0
let g:myLangList=["nospell","nl","en_gb","en_us"]
function! ToggleSpell()
if !exists( "b:myLang" )
let b:myLang=0
endif
let b:myLang=b:myLang+1
if b:myLang>=len(g:myLangList) | let b:myLang=0 | endif
if b:myLang==0
setlocal nospell
else
execute "setlocal spell spelllang=".get(g:myLangList, b:myLang)
endif
echo "spell checking language:" g:myLangList[b:myLang]
endfunction
" Map <F7> to toggle the language with
nmap <silent> <F7> :call ToggleSpell()<CR>
" In case the spelling language was set by other means than ToggleSpell() (a filetype autocommand say):
if !exists( "b:myLang" )
if &spell
let b:myLang=index(g:myLangList, &spelllang)
else
let b:myLang=0
endif
endif
" Correct previous spelling error with Ctrl+l. jumps to the previous
" spelling mistake [s, then picks the first suggestion 1z=, and then
" jumps back `]a. The <c-g>u in the middle make it possible to undo
" the spelling correction quickly.
" https://castel.dev/post/lecture-notes-1/
inoremap <C-l> <c-g>u<Esc>[s1z=`]a<c-g>u
</code></pre>
<p><a href="https://shuttereye.org/various/screenshots/20200115_vim_editing_dammit.png/view/"><img alt="vim editing dammIT" src="https://shuttereye.org/galleries/various/screenshots/20200115_vim_editing_dammit.png"></a></p>
<p>The red and underlined words here are marked by the spell checker.</p>
<h2>Distraction-free writing</h2>
<p>Speaking of writing longer pieces, you might want to do so in a less distracting environment. Numerous text editors have popped up, providing a window or fullscreen writing canvas with basically just your text. With vim, you do not need a separate editor, as it has you covered. Well, with some help from <a href="https://github.com/junegunn/goyo.vim">goyo</a>, <a href="https://github.com/junegunn/limelight.vim">limelight</a>, and <a href="https://github.com/reedes/vim-pencil">vim-pencil</a>, which take care of removing all unnecessary chrome, removing unnecessary highlighting (focussing on the current paragraph), and things like soft returns respectively:</p>
<pre><code>" Distraction-free writing, start with <Leader>V (\V or ,V in this config)
Plug 'junegunn/goyo.vim'
let g:goyo_width = 120
" Help focus on text by dimming other parts a bit
Plug 'junegunn/limelight.vim'
let g:limelight_conceal_ctermfg = 'Grey69'
let g:limelight_conceal_ctermfg = 145
" Color name (:help gui-colors) or RGB color
let g:limelight_conceal_guifg = '#b0b0b0'
" Helps with writing prose (better line breaks, agnostic on soft line wraps vs
" hard line breaks etc)
Plug 'reedes/vim-pencil'
" Disable automatic formatting, as this automatically merges lines devided by
" 1 hard enter only, which can be annoying
let g:pencil#autoformat = 0
" Do not insert hard line breaks in the middle of a sentence
let g:pencil#wrapModeDefault = 'soft' " default is 'hard'
" Toggle Gogo with Limelight and Pencil together with ,V
nmap <leader>V :Goyo <bar> :Limelight!! <bar> :TogglePencil <CR>
</code></pre>
<p><a href="https://shuttereye.org/various/screenshots/20200115_vim_distraction_free.png/view/"><img alt="vim in distraction free mode with ,V" src="https://shuttereye.org/galleries/various/screenshots/20200115_vim_distraction_free.png"></a></p>
<h2>Further reading</h2>
<p>Another good read is <a href="https://statico.github.io/vim3.html">Vim After 15 Years</a>, in which Ian Langworth describes his own setup. We have some similarities, and of course some differences.</p>
<p>I do not do much LaTeX writing at the moment, but if you do, you should check out the <a href="https://github.com/lervag/vimtex">vimtex plugin</a>.</p>
<p>This weblog has a <a href="https://dammit.nl/tag/vim.html">vim tag</a>, which binds my vim musings together.</p>
<p>Also, I did not talk about all the plugins in <a href="https://github.com/aquatix/dotfiles/blob/master/.vimrc">my .vimrc</a>, so make sure to browse through it, and check out the various highlight plugins and other hidden gems.</p>
<p>You might also have noted a bar completely at the bottom in the screenshots in this article. This is from <a href="https://github.com/tmux/tmux/wiki">tmux</a>, which I can highly recommend if you are doing any work in terminals. I think another article highlighting some useful features and tweaks for this terminal multiplexer will follow soonish(tm).</p>
<p><a href="https://github.com/romainl">romainl</a> has <a href="https://gist.github.com/romainl/4b9f139d2a8694612b924322de1025ce">some interesting</a> <a href="https://www.reddit.com/r/vim/comments/7iy03o/you_aint_gonna_need_it_your_replacement_for/dr2qo4k/?st=jc832ora">links</a> to do all kinds of nifty vim stuff without plugins, or with at least as possible.</p>
<h2>Changes</h2>
<p>On 2020-01-25, I added a <code>:Rg</code> command for fuzzy finding text inside files; this is a better version of the <code>:Find</code> that's already in the snippet, as the <code>:Find</code> variant also searches the text in the filenames, which is already done with <code>:Files</code> <kbd>leader</kbd>+<kbd>o</kbd>).</p>Unzip a bunch of zips in a oneliner2019-12-22T15:21:42+01:002019-12-22T15:21:42+01:00Michiel Scholtentag:dammit.nl,2019-12-22:/unzip-zips-oneliner.html<p>Ever needed to unzip a bunch of zip files into their own directory and you don't want to do so one by one? No? Well, here I have a oneliner for you anyway:</p>
<pre><code>ls -1 *.zip | while read zf; do echo ${zf::-4}; unzip "$zf" -d "${zf::-4}"; done
</code></pre>
<p>This …</p><p>Ever needed to unzip a bunch of zip files into their own directory and you don't want to do so one by one? No? Well, here I have a oneliner for you anyway:</p>
<pre><code>ls -1 *.zip | while read zf; do echo ${zf::-4}; unzip "$zf" -d "${zf::-4}"; done
</code></pre>
<p>This lists all the zip files in the current directory, and pipes them to unzip, which creates a directory with their filenames without the <code>.zip</code> extension in the process with the <code>-d</code> command line argument. <code>${zf::-4}</code> here echoes the contents of the <code>$zf</code> variable without its last four characters (the <code>.zip</code> in this case).</p>
<p>Piping the results of <code>ls</code> this way also takes care of the issues that bash has with spaces in file names. Be sure to double quote the <code>$zf</code> variable though when using it so no space escapes.</p>
<p>This command is especially useful when the zips do not contain a toplevel directory themselves, so they would uncompress in your current working directory, creating a nice little mess (looking at you, Bandcamp).</p>
<p>Of course, when you have a bunch of zips that actually behave, it could be simplified to:</p>
<pre><code>ls -1 *.zip | while read zf; unzip "$zf"; done
</code></pre>
<p>Done :)</p>Wallpapers with Gimp mosaic2019-12-02T15:28:53+01:002019-12-02T15:28:53+01:00Michiel Scholtentag:dammit.nl,2019-12-02:/gimp-mosaic.html<p><img alt="Photo of heathland with a mosaic effect applied with Gimp" src="https://shuttereye.org/images/d9/d9d994e81a6c2db8_2000-2000.jpg"></p>
<p>I like taking pictures, and having some of the nicer ones as a background to my daily computer shenanigans is a nice extension of this.</p>
<p>Lately, I've been playing around a bit with having pictures show up differently (more abstractly, with less details so they distract less, like those nice …</p><p><img alt="Photo of heathland with a mosaic effect applied with Gimp" src="https://shuttereye.org/images/d9/d9d994e81a6c2db8_2000-2000.jpg"></p>
<p>I like taking pictures, and having some of the nicer ones as a background to my daily computer shenanigans is a nice extension of this.</p>
<p>Lately, I've been playing around a bit with having pictures show up differently (more abstractly, with less details so they distract less, like those nice clean material designs), and in Gimp I found a way that pleased me, resulting in the images shown here.</p>
<p>Open the image in Gimp, then go to menu <code>Filters > Distort > Mosaic</code>, and tweak the settings to:</p>
<ul>
<li>Tile size 15 or 20.</li>
<li>Tile height 2,000</li>
<li>Tile neatness 0,650</li>
<li>Tile color variation 0,100</li>
<li>Tile spacing 0,000</li>
<li>Joints color: HTML notation 666666</li>
<li>Light color: ffffff</li>
<li>Light direction 135,00</li>
<li>Random seed 0</li>
</ul>
<p>Of course, play around with the settings to your own liking.</p>
<p><a href="https://shuttereye.org/wallpapers/">Gallery of wallpapers of pictures I made</a></p>
<p><a href="https://shuttereye.org/wallpapers/IMG_0396_mosaic-hexagons-less-deep-lighter-less-colour-variance-20px.jpg/view/"><img alt="Heath" src="https://shuttereye.org/images/c2/c268e8d226aacc51_2000-2000.jpg"></a></p>
<p><a href="https://shuttereye.org/wallpapers/IMG_20191120_084011-tile15.jpg/view/"><img alt="Winter light" src="https://shuttereye.org/images/bd/bd7931b1fdfcf41c_2000-2000.jpg"></a></p>darktable and opencl in Ubuntu 19.042019-08-17T12:43:26+02:002019-08-17T12:43:26+02:00Michiel Scholtentag:dammit.nl,2019-08-17:/darktable-opencl-ubuntu1904.html<p>Editing and even viewing (raw) photographs can be a bit taxing on your CPU. If you have an Nvidia GPU, you can supercharge your photo editor by using its OpenCL extensions to offload operations to. Using <a href="https://www.darktable.org/">darktable</a> myself, I had to do a minor bit of research before it worked …</p><p>Editing and even viewing (raw) photographs can be a bit taxing on your CPU. If you have an Nvidia GPU, you can supercharge your photo editor by using its OpenCL extensions to offload operations to. Using <a href="https://www.darktable.org/">darktable</a> myself, I had to do a minor bit of research before it worked, as package names have changed in recent Ubuntu.</p>
<p>Assuming you already have nvidia-driver-390 and nvidia-prime installed and switched to use nvidia using <code>prime-select nvidia</code> (when relevant if you switch between using the built-in Intel GPU and your Nvidia chip for example), there's some packages that need installing before OpenCL works with darktable:</p>
<pre><code>sudo apt install nvidia-headless-390 nvidia-modprobe opencl-headers ocl-icd-libopencl1
</code></pre>
<p>Now reboot (or restart X), start darktable and check its settings (little cog icon, 'preferences'). In the 'core options' tab you will now see a checkbox next to 'activate OpenCL support'. Enable and engage :)</p>Git-based versioning2019-02-13T20:09:09+01:002019-02-13T20:09:09+01:00Michiel Scholtentag:dammit.nl,2019-02-13:/git-based-versioning.html<p>So you have this (web) application and you are growing a bit tired of having to manually bump the version number it tells to its users. Also, you would like to see if you are using an up-to-date edition of said app.</p>
<p>Enter your Git repository. When you are running …</p><p>So you have this (web) application and you are growing a bit tired of having to manually bump the version number it tells to its users. Also, you would like to see if you are using an up-to-date edition of said app.</p>
<p>Enter your Git repository. When you are running your application from a Git repository (which is fine in my opinion as long as you of course do <em>not</em> expose the .git directory to the world), you can leverage (<em>cringe</em>) Git to create the version number for you.</p>
<p>Try it yourself: in a terminal, enter a directory in a project that is checked out from Git, then enter the following command:</p>
<pre><code>git describe --always --tags
</code></pre>
<p>This will return a string that is based on the latest tag it could find, the amount of commits following that tag (if any) and the short commit hash of the latest revision. For example <code>20190213a-3-abc42def</code>.</p>
<p>Now, you would like to use that in your Python program:</p>
<pre><code>import os
import subprocess
# Make sure the working directory is our project
cwd = os.path.dirname(os.path.realpath(__file__))
try:
version = subprocess.check_output(["git", "describe", "--always", "--tags"], stderr=None, cwd=cwd).strip()
except subprocess.CalledProcessError:
version = ''
try:
# byte string needs to be converted to a string
version = version.decode("utf-8")
except AttributeError:
# version already was a str
pass
</code></pre>
<p>This snippet runs Git in a sub process, makes sure it uses the directory your program resides in as the working directory (web applications and such can have a completely different cwd than you expect), and makes sure the resulting <code>version</code> is a proper string.</p>
<p>This code is tested under Python 3 on several Linux distributions.</p>isso commenting system in a subdirectory on nginx2018-12-17T13:58:11+01:002018-12-17T13:58:11+01:00Michiel Scholtentag:dammit.nl,2018-12-17:/isso-subdirectory-nginx.html<p>I very recently moved this weblog to a new host, and in the process finally changed from Apache running mod_wsgi to nginx with uWSGI and supervisor (well, at least for the Python based web apps, as dammIT is a flat site). I'm using <a href="https://posativ.org/isso/">isso</a> as commenting system, which runs as …</p><p>I very recently moved this weblog to a new host, and in the process finally changed from Apache running mod_wsgi to nginx with uWSGI and supervisor (well, at least for the Python based web apps, as dammIT is a flat site). I'm using <a href="https://posativ.org/isso/">isso</a> as commenting system, which runs as an application in uWSGI, using a socket, and is managed by uWSGI. This is all fine, dandy, and documented by their documentation, but running it in a subdirectory (in the URL) is not. After some hair pulling and numerous web searches, I arrived at this working configuration:</p>
<pre><code>location /comments {
include uwsgi_params;
uwsgi_param HTTP_X_SCRIPT_NAME /comments;
uwsgi_pass unix:/var/local/socket/isso.sock;
}
</code></pre>
<p>Mind the line with <code>HTTP_X_SCRIPT_NAME</code> here, as that's what tells isso it runs under that subdirectory instead of in the webroot.</p>
<p>For completeness, the uWSGI configuration I use is as follows:</p>
<pre><code>[uwsgi]
# use Python 3.7 plugin; change to python36 or similar, depending on the Python version in your venv
plugins = python37
project = isso
base = /srv/www/isso
# the virtualenv (full path), in which isso is installed through `pip install isso`
home = %(base)/venv
# wsgi file
module = isso.run
env = ISSO_SETTINGS=/srv/www/isso/dammit.nl.ini
#spooler = %d/mail
master = true
# maximum number of worker processes
processes = 4
socket = /var/local/socket/%(project).sock
chmod-socket = 666
# clear environment on exit
vacuum = true
# make sure that uWSGI doesn't hard kill the app on termination
die-on-term = true
</code></pre>Fixing the 'unix_listener too long for Unix domain socket' problem2018-08-03T09:26:23+02:002018-08-03T09:26:23+02:00Michiel Scholtentag:dammit.nl,2018-08-03:/ssh-unix-socket.html<p>In my <code>~/.ssh/config</code> file, I have been using a socket file for every host that I connect to, so TCP sessions can be re-used for faster connecting to a host I already am connected to. I had several iterations of the exact filename for this, as with longer hostnames …</p><p>In my <code>~/.ssh/config</code> file, I have been using a socket file for every host that I connect to, so TCP sessions can be re-used for faster connecting to a host I already am connected to. I had several iterations of the exact filename for this, as with longer hostnames, the filename becomes too long.</p>
<p>So after <code>ControlPath ~/.ssh/sockets/%r@%h-%p</code> and <code>ControlPath ~/.ssh/sockets/%r@%h</code> I still ran into problems. Luckily, I came across <a href="https://gist.github.com/andyvanee/bcf95b1044b80e72b4a42933549a079b">this helpful gist</a> which mentioned the <code>%C</code> formatting option to generate a hash of <code>%l%h%p%r</code> instead of printing the whole hostname including fully qualified domain name and such. The following snippet works wonders:</p>
<pre><code>Host *
ControlPath ~/.ssh/control/%C
ControlMaster auto
</code></pre>Andromeda, Substratum and a Chromebook2018-06-21T11:02:20+02:002018-06-21T11:02:20+02:00Michiel Scholtentag:dammit.nl,2018-06-21:/andromeda-chromebook.html<p><a href="https://forum.xda-developers.com/apps/substratum/andromeda-desktop-clients-release-notes-t3668682">Andromeda</a> is a way to theme an Android device with <a href="https://play.google.com/store/apps/details?id=projekt.substratum">Substratum</a> without needing root. You need <code>adb</code> though, so a desktop or laptop computer is needed to initiate the connection between the Andromeda app and Substratum.</p>
<p>On regular machines this is not much of an issue, but Chromebooks are both …</p><p><a href="https://forum.xda-developers.com/apps/substratum/andromeda-desktop-clients-release-notes-t3668682">Andromeda</a> is a way to theme an Android device with <a href="https://play.google.com/store/apps/details?id=projekt.substratum">Substratum</a> without needing root. You need <code>adb</code> though, so a desktop or laptop computer is needed to initiate the connection between the Andromeda app and Substratum.</p>
<p>On regular machines this is not much of an issue, but Chromebooks are both nifty little tools as a bit restricted in what you can run there. Thankfully, even running <code>adb</code> is a breeze now, at least if you have put the Chromebook in dev mode (not dev channel). ChromeOS has been shipping an <code>adb</code> binary for quite some time already, but it's an outdated one (why?!), so it for example does not work with my Pixel 2XL running Android 8.1 Oreo.</p>
<p>However, the world would not be right if some enterprising developer would not create a way of updating both <code>adb</code> and <code>fastboot</code> on ChromeOS. That's exactly what <a href="https://forum.xda-developers.com/hardware-hacking/chromebooks/guide-setting-adb-fastboot-x8664-t3806428">Nathan Chance did</a>. <a href="https://raw.githubusercontent.com/nathanchance/chromeos-adb-fastboot/master/install.sh">Download his installer script</a> and run it from the terminal:</p>
<p><kbd>ctrl</kbd>+<kbd>alt</kbd>+<kbd>t</kbd> <code>shell</code> <code>bash ~/Downloads/install.sh</code> and enter your sudo password. Of course substitute the path to install.sh if you saved it somewhere else.</p>
<p><code>source ~/.bashrc</code> to activate the aliases so you have a working <code>adb</code> and <code>fastboot</code>.</p>
<p>You now have an up-to-date <code>adb</code>, but the script that's linked from the Andromeda thread for use on Linux uses a mix of its own bundles <code>adb</code> and the system binary.</p>
<p>I created a fixed version of this script to always use the up-to-date system <code>adb</code> that Nathan's script downloads (and can update). Download the following and save as start_andromeda.sh then use as advertised in the Andromeda thread:</p>
<pre><code>#!/usr/bin/env bash
echo "Andromeda Start Shell Script by [projekt.] development team"
echo ""
echo "This requires projekt.andromeda to be installed on the device"
echo "Make sure the device is connected and ADB option enabled"
echo "Please only have one device connected at a time to use this!"
echo ""
read -n 1 -s -r -p "Press any key to continue..."
echo ""
echo ""
export USER_HOME=${HOME}
function adb() {
sudo su --preserve-environment -c "HOME=${USER_HOME} /usr/local/bin/adb ${*}"
}
# Get the current directory of the device running this script
ROOT=$(dirname $0)
# ADB specific commands for termination
adb kill-server
adb start-server
# Device configuration of the testing rack
ADB="adb shell"
# Let's first grab the location where Andromeda is installed
pkg=$($ADB pm path projekt.andromeda)
echo "$pkg"
# Due to the way the output is formatted, we have to strip 10 chars at the start
pkg=$(echo $pkg | cut -d : -f 2 | sed s/\\r//g)
# Now let's kill the running Andromeda services on the mobile device
kill=$($ADB pidof andromeda)
# Check if we need to kill the existing pids, then kill them if need be
if [[ "$kill" == "" ]]
then echo
$ADB << EOF
am force-stop projekt.substratum
appops set projekt.andromeda RUN_IN_BACKGROUND allow
appops set projekt.substratum RUN_IN_BACKGROUND allow
CLASSPATH=$pkg app_process /system/bin --nice-name=andromeda projekt.andromeda.Andromeda &
echo "You can now remove your device from the computer!"
exit
EOF
else echo
$ADB << EOF
am force-stop projekt.substratum
kill -9 $kill
appops set projekt.andromeda RUN_IN_BACKGROUND allow
appops set projekt.substratum RUN_IN_BACKGROUND allow
CLASSPATH=$pkg app_process /system/bin --nice-name=andromeda projekt.andromeda.Andromeda &
echo "You can now remove your device from the computer!"
exit
EOF
fi
# We're done!
adb kill-server
</code></pre>