<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<title></title>
	<link href="https://sburris.xyz/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="https://sburris.xyz"/>
	<generator uri="https://www.getzola.org/">Zola</generator>
	<updated>2024-03-31T00:00:00+00:00</updated>
	<id>https://sburris.xyz/atom.xml</id>
	<entry xml:lang="en">
		<title>NixOS&#x2F;Forgejo Migration: Fix for Missing Users&#x2F;Repos</title>
		<published>2024-03-31T00:00:00+00:00</published>
		<updated>2024-03-31T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/gitea-forgejo-migration/" type="text/html"/>
		<id>https://sburris.xyz/posts/gitea-forgejo-migration/</id>
		<content type="html">&lt;h2 id=&quot;migration&quot;&gt;Migration&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;tl-dr&quot;&gt;TL;DR&lt;&#x2F;h3&gt;
&lt;p&gt;If you were using sqlite (NixOS default), copy your Gitea database over the auto-generated blank Forgejo database with &lt;code&gt;cp &#x2F;var&#x2F;lib&#x2F;forgejo&#x2F;data&#x2F;gitea.db &#x2F;var&#x2F;lib&#x2F;forgejo&#x2F;forgejo.db&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;complete-instructions&quot;&gt;Complete Instructions&lt;&#x2F;h3&gt;
&lt;p&gt;I decided to switch from self-hosting Gitea to &lt;a href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;&quot;&gt;Forgejo&lt;&#x2F;a&gt; for &lt;a href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;compare-to-gitea&#x2F;&quot;&gt;reasons&lt;&#x2F;a&gt;.
To start, I followed &lt;a href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;docs&#x2F;latest&#x2F;admin&#x2F;installation&#x2F;#migration-from-gitea&quot;&gt;official migration instrucitons&lt;&#x2F;a&gt;
but did a few things differently on account of running NixOS:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;systemctl stop gitea&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Do NOT copy &lt;code&gt;app.ini&lt;&#x2F;code&gt; (it isn’t there, it’s part of your system nix config and will be built automatically)&lt;&#x2F;li&gt;
&lt;li&gt;Perform data migration &lt;a href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;docs&#x2F;latest&#x2F;admin&#x2F;installation&#x2F;#data-migration&quot;&gt;as noted&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Switch &lt;code&gt;services.gitea&lt;&#x2F;code&gt; section in your system config to &lt;code&gt;services.forgejo&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;nixos-rebuild switch&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;After doing this, I could access the interface but my existing users and repos were missing.
The reason I’m writing this article is to let you know that you &lt;strong&gt;need to copy &lt;code&gt;&#x2F;var&#x2F;lib&#x2F;forgejo&#x2F;data&#x2F;gitea.db&lt;&#x2F;code&gt; to &lt;code&gt;&#x2F;var&#x2F;lib&#x2F;forgejo&#x2F;data&#x2F;forgejo.db&lt;&#x2F;code&gt;.&lt;&#x2F;strong&gt;
There will be a &lt;code&gt;forgejo.db&lt;&#x2F;code&gt; file in place without your data.&lt;&#x2F;p&gt;
&lt;p&gt;To continue with the steps:&lt;&#x2F;p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;code&gt;systemctl stop forgejo&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;cp &#x2F;var&#x2F;lib&#x2F;forgejo&#x2F;data&#x2F;gitea.db &#x2F;var&#x2F;lib&#x2F;forgejo&#x2F;forgejo.db&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;systemctl start forgejo&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If your setup is the same as mine:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;you should be able to access the web UI &lt;&#x2F;li&gt;
&lt;li&gt;your Gitea username&#x2F;password should work&lt;&#x2F;li&gt;
&lt;li&gt;your previously existing repos should show up on the “Explore” page&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The last thing I did was select the default Forgejo theme in my users settings.&lt;&#x2F;p&gt;
&lt;p&gt;Hopefully this saves you a few minutes.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Tech Progress That I&#x27;m Excited About</title>
		<published>2024-03-22T00:00:00+00:00</published>
		<updated>2024-03-22T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/looking-forward-2024/" type="text/html"/>
		<id>https://sburris.xyz/posts/looking-forward-2024/</id>
		<content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s my rambly list of misc tech things I am excited about, it is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ordered from low-level to high-level&lt;&#x2F;li&gt;
&lt;li&gt;Full of future developments that are “on the horizon” for some definition of “the horizon”&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;hardware&quot;&gt;Hardware&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;processors&quot;&gt;Processors&lt;&#x2F;h3&gt;
&lt;p&gt;There’s been a lot of news about the semiconductor industry lately: &lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;CHIPS_and_Science_Act&quot;&gt;CHIPS act&lt;&#x2F;a&gt; has been enacted, allocating $52 billion to supporting semiconductor fabrication in the US.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tinygrad.org&#x2F;&quot;&gt;Tiny Corp&lt;&#x2F;a&gt; has been putting public pressure on AMD to open source components of their drivers&lt;&#x2F;li&gt;
&lt;li&gt;NVIDIA stock continues to rise, up 256% from one year ago&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I really want silent&#x2F;fanless computers that don’t get hot.
While we’re waiting for lead-apetite superconductors to get validated (I never stopped superconducting in my heart), RISC processors (RISC-V, ARM) are probably our best bet.
Apple has made solid progress towards this with their M-series processors, unfortunately they do not have an open standard.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;risc-v&quot;&gt;RISC-V&lt;&#x2F;h3&gt;
&lt;p&gt;I think the future is bright for RISC-V:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;SiFive and Intel Foundry Service (they manufacture other company’s chips now) released the &lt;a href=&quot;https:&#x2F;&#x2F;www.sifive.com&#x2F;boards&#x2F;hifive-pro-p550&quot;&gt;P550 development board&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;In 2022, Alibaba released the first &lt;a href=&quot;https:&#x2F;&#x2F;www.tomshardware.com&#x2F;news&#x2F;risc-v-laptop-world-first&quot;&gt;RISC-V laptop&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Alibaba announced that it plans to release a RISC-V processor intended for servers this year.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;operating-systems&quot;&gt;Operating Systems&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;linux&quot;&gt;Linux&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;atomic-consoles&quot;&gt;Atomic Consoles&lt;&#x2F;h4&gt;
&lt;p&gt;Linux developers are pursuing one of the last major obstacles to Real Time (RT) support: &lt;a href=&quot;https:&#x2F;&#x2F;www.phoronix.com&#x2F;news&#x2F;Linux-6.9-Printk-Cleanup&quot;&gt;atomic consoles&#x2F;threaded printing&lt;&#x2F;a&gt;.
Brief summary of real time operating systems: performance is usually worse but consistent, responses are guaranteed in a set amount of time or else an “alarm” is triggered.
RTOS are primarily found on embedded systems.
This needs some parallelism and blocking print functions get in the way.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;bcachefs&quot;&gt;Bcachefs&lt;&#x2F;h4&gt;
&lt;p&gt;I use ZFS quite a bit, but it is unlikely to ever be included in the Linux kernel for reasons related to licensing and IP.
&lt;a href=&quot;https:&#x2F;&#x2F;bcachefs.org&#x2F;&quot;&gt;Bcachefs&lt;&#x2F;a&gt; has similar functionality without legacy code from Solaris and includes several much-desired features that ZFS users have been waiting for forever.
It was merged into mainline Linux (with some drama) but once it’s had some time to mature, it may become the future of CoW file systems. &lt;&#x2F;p&gt;
&lt;h3 id=&quot;redox-os&quot;&gt;Redox OS&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.redox-os.org&#x2F;&quot;&gt;RedoxOS&lt;&#x2F;a&gt; (rust microkernel operating system) continues to progress quickly.
Microkernels have a number of benefits (security), but one of the big unknowns is how high the overhead cost of context switching really is, and how much is varies by specific implementation.
The list of Linux software that Redox can run is growing and my hope is that this will help us quantify that cost with more direct comparisons.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nixos&quot;&gt;NixOS&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;flakes-enabled-by-default&quot;&gt;Flakes Enabled by Default&lt;&#x2F;h4&gt;
&lt;p&gt;I have no idea when this will happen, but it must happen at some point, right?&lt;&#x2F;p&gt;
&lt;h4 id=&quot;service-abstraction-layer&quot;&gt;Service Abstraction Layer&lt;&#x2F;h4&gt;
&lt;p&gt;Calling NixOS an operating system or Linux distribution feels weird, because it’s more of a tool that builds ](inux distributions according to a supplied configuration.
One of the non-negotiables when building your system with NixOS is that it must use systemd.
I’m not going to debate the merits of systemd here, but I will note that with its prevalence, the linux ecosystem increasingly converges towards upon a monoculture and I appreciate having options.
There has been some discussion of creating a “Service Abstraction Layer” (SAL) in the NixOS community.&lt;&#x2F;p&gt;
&lt;p&gt;It’s hard to say how likely this is to actually happen.
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nix-community&#x2F;NixNG&quot;&gt;NixNG&lt;&#x2F;a&gt; is a fork that already allows for choice of init systems.
One of the primary developers chimed into a SAL discussion thread to recommend against a SAL on the grounds of the requisite complexity not being worth it. 
There have been many threads about this, as well as a few pull requests.&lt;&#x2F;p&gt;
&lt;p&gt;There are two other systems I’m aware of that are nix-like without systemd:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nixos-bsd&#x2F;nixbsd&quot;&gt;NixBSD&lt;&#x2F;a&gt;, a fork which runs the FreeBSD kernel and does not use systemd for init.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;guix.gnu.org&#x2F;&quot;&gt;GuixSD&lt;&#x2F;a&gt;, a fork which is committed to Free Software and uses GNU&#x2F;Guile (a lisp) rather than the Nix language for configuration. Init is handled by GNU Shepherd.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;what-comes-next&quot;&gt;What Comes Next&lt;&#x2F;h4&gt;
&lt;p&gt;Nix is unreasonably effective.
It solves many difficult problems and I use it wherever I can (except my router, for now).
I think its complexity gets to people, it was hard for me to learn some aspects of it and I’m still not comfortable with flakes.&lt;&#x2F;p&gt;
&lt;p&gt;In the future, there will likely be something similar that solves all of the same problem in a more elegant, simpler, user-friendly way.
I would like to see it also be a bit more general, leaning further away from Linux distribution and towards OS-building tool.
Support for different init systems fit this goal.
Another thought: using a preexisting&#x2F;familiar language for configuration could be nice, Guix has this going for it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;desktop-environments&quot;&gt;Desktop Environments&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;xfce-wayland&quot;&gt;XFCE - Wayland&lt;&#x2F;h3&gt;
&lt;p&gt;Wayland support on XFCE is being worked on, &lt;a href=&quot;https:&#x2F;&#x2F;wiki.xfce.org&#x2F;releng&#x2F;wayland_roadmap&quot;&gt;the roadmap&lt;&#x2F;a&gt; makes it sound not too far away; xfwm4 is the main component still needing to be ported.
I would seriously consider using XFCE once again when it works on Wayland.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cosmic-desktop&quot;&gt;COSMIC Desktop&lt;&#x2F;h3&gt;
&lt;p&gt;It’s been nearly a decade since I began using Linux.
During that time I’ve had nearly zero desktop environment experiences that felt stable, reliable, and not buggy.
XFCE has mostly been fine. 
GNOME and KDE have given me tons of issues even on officially targeted&#x2F;supported platforms such as KDE Neon and Fedora.
This has lead me to believe that desktop environments are simply too complex to be written in non-memory-safe languages.&lt;&#x2F;p&gt;
&lt;p&gt;COSMIC desktop is being developed in rust by System76, where the lead developer of RedoxOS works.
The developers at system76 clearly know what they are doing, given the success of &lt;a href=&quot;https:&#x2F;&#x2F;pop.system76.com&#x2F;&quot;&gt;Pop!_OS&lt;&#x2F;a&gt; which ships a heavily customized and extended GNOME desktop.
I’m excited to see if they are able to produce a desktop that feels solid and works reliably.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;desktop-applications&quot;&gt;Desktop Applications&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;helix-plugins&quot;&gt;Helix - Plugins&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helix-editor.com&#x2F;&quot;&gt;Helix&lt;&#x2F;a&gt; is my daily-driver text editor.
It’s basically snappier vim (more rust software) that I don’t have to configure pretty much ever, except to add my custom color scheme which syntax highlights ONLY comments.
Using Helix, I do miss some functionality that I got via extensions previously when I used neovim and emacs.
Luckily, Helix is getting plugin support in the future.&lt;&#x2F;p&gt;
&lt;p&gt;It sounds like plugins will be written in some sort of Scheme.
Not long after, I’m sure someone will create an org-mode plugin, which is what I want most.
Who knows, with proper keybind definitions, maybe it will even become a viable alternative to emacs.
Until then, markdown with the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;artempyanykh&#x2F;marksman&quot;&gt;marksman&lt;&#x2F;a&gt; language server makes Helix usable for notes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;appflowy-tauri&quot;&gt;Appflowy - Tauri&lt;&#x2F;h3&gt;
&lt;p&gt;Appflowy is a note-taking app (rust again).
It has two properties that set it apart from many similar apps: it’s open source (not just source-available, like anytype), and it doesn’t use electron for its UI (it uses flutter&#x2F;dart).
Additionally, the developers are working on a &lt;a href=&quot;https:&#x2F;&#x2F;tauri.app&#x2F;&quot;&gt;Tauri&lt;&#x2F;a&gt; frontend.&lt;&#x2F;p&gt;
&lt;p&gt;I run into some issues using Appflowy on Linux, probably because it’s not a priority deployment target for Flutter.
One example of this is that file picker dialogs don’t open.
I suspect using Tauri will fix many problems including this one, but if it doesn’t, I imagine they’ll get fixed otherwise as time goes on anyways.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Use Logarithms to Get Integer Length</title>
		<published>2024-03-01T00:00:00+00:00</published>
		<updated>2024-03-01T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/logarithms-string-conversions/" type="text/html"/>
		<id>https://sburris.xyz/posts/logarithms-string-conversions/</id>
		<content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;Doing math with logarithms can make your code ~6 OOM faster by preventing an integer -&amp;gt; string conversion in two cases.
This “trick” might be obvious to programmers with a math background but I suspect many people don’t realize that it is an option. 
These examples use rust, but translate directly to other languages.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;counting-digits&quot;&gt;Counting Digits&lt;&#x2F;h3&gt;
&lt;p&gt;The immediately obvious way to do this is as follows:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; num: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;98234812&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;;
num.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; =&amp;gt; 8
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, this method is much faster (~6 OOM &#x2F; ~1,000,000x faster):&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; num: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;i32 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;98234812&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; num.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;checked_ilog10&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;usize
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; =&amp;gt; 8
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;comparison&quot;&gt;Comparison&lt;&#x2F;h4&gt;
&lt;p&gt;Why is it so much faster?
Let’s have a look at the disassembled version on the Compiler Explorer &lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;1GMa9a5se&quot;&gt;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;1GMa9a5se&lt;&#x2F;a&gt; (normally you should run when somebody says that, but you trust me right?)&lt;&#x2F;p&gt;
&lt;p&gt;Look how many instructions that is!
The disassembled version of the version using &lt;code&gt;.to_string()&lt;&#x2F;code&gt; and &lt;code&gt;.len()&lt;&#x2F;code&gt; is nearly 2000k lines long!&lt;&#x2F;p&gt;
&lt;p&gt;Now check out the second version: &lt;a href=&quot;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;3Pz331co5&quot;&gt;https:&#x2F;&#x2F;godbolt.org&#x2F;z&#x2F;3Pz331co5&lt;&#x2F;a&gt;.
This one is only 108 lines.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>The Past Three Years</title>
		<published>2024-02-29T00:00:00+00:00</published>
		<updated>2024-02-29T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/past-three-years/" type="text/html"/>
		<id>https://sburris.xyz/posts/past-three-years/</id>
		<content type="html">&lt;h2 id=&quot;it-s-been-a-while&quot;&gt;It’s been a while&lt;&#x2F;h2&gt;
&lt;p&gt;Since my last post here nearly three years ago, much has changed. 
I got a job, moved halfway across the country alone, went to DEFCON, and learned many lessons (especially about myself).&lt;&#x2F;p&gt;
&lt;p&gt;Anyways, this blog isn’t very personal so I’ll skip most of the life update.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-happening-next&quot;&gt;What is happening next&lt;&#x2F;h2&gt;
&lt;p&gt;I’m bringing this blog back in some capacity.
I have some technical things I’d like to share, but I keep myself pretty busy these days.
I won’t say to expect more posts, but don’t &lt;em&gt;not&lt;&#x2F;em&gt; expect more posts.&lt;&#x2F;p&gt;
&lt;p&gt;This blog will remain tech-focused.
Future writing to be posted will revolve around a few topics: rust, NixOS, and ZFS.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Anyways, hope you’ve all been well.
If you’d like to be notified about new posts, there’s an RSS feed link in the sidebar.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>LaTeX Resume Formatting</title>
		<published>2021-04-30T00:00:00+00:00</published>
		<updated>2021-04-30T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/latex-resume-advice/" type="text/html"/>
		<id>https://sburris.xyz/posts/latex-resume-advice/</id>
		<content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;I recently overhauled my entire Computer Science resume using LaTeX.
While doing so, I found some useful tips that I’d like to share, some from &lt;a href=&quot;https:&#x2F;&#x2F;practicaltypography.com&#x2F;&quot;&gt;Butterick’s Practical Typography&lt;&#x2F;a&gt;, which I highly recommend looking through.
I’ll start at the top and work my way down.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;packages&quot;&gt;Packages&lt;&#x2F;h2&gt;
&lt;p&gt;My new resume uses five packages:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;geometry&lt;&#x2F;code&gt; to set a 0.5“ page margin.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;multicols&lt;&#x2F;code&gt; to create columns and use horizontal space more effectively&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;fontenc&lt;&#x2F;code&gt; to change the font&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;charter&lt;&#x2F;code&gt;, the font&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;microtype&lt;&#x2F;code&gt; for more natural hyphenation at the end of lines&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;formatting&quot;&gt;Formatting&lt;&#x2F;h2&gt;
&lt;p&gt;Out of the box, LaTeX has formatting well-suited for scientific literature, but not so much for resumes.
Here are some of the changes I made.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;font-size&quot;&gt;Font Size&lt;&#x2F;h3&gt;
&lt;p&gt;Most articles I read recommended a font-size between 10pt-12pt, so I went with 11pt: &lt;code&gt;\documentclass[11pt][article]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hiding-numbering&quot;&gt;Hiding Numbering&lt;&#x2F;h3&gt;
&lt;p&gt;To disable page numbers, use &lt;code&gt;\pagenumbering{gobble}&lt;&#x2F;code&gt;.
To hide section and subsection numbering, use &lt;code&gt;\section*{Title}&lt;&#x2F;code&gt; and &lt;code&gt;\subsection*{Title}&lt;&#x2F;code&gt; (with the asterisk).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;header-underlines&quot;&gt;Header Underlines&lt;&#x2F;h2&gt;
&lt;p&gt;Try using &lt;code&gt;\hrule&lt;&#x2F;code&gt;: &lt;code&gt;\section*{Experience\hrull}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;Professional summaries typically include years of experience in the form of &lt;code&gt;[positive adjective] [job title] with X years of experience doing something.&lt;&#x2F;code&gt;
For years of experience, you will likely have something like “4+” or “3½”.
Try &lt;code&gt;4\texttt{+}&lt;&#x2F;code&gt; for the former to prevent weird spacing and &lt;code&gt;3\textonehalf{}&lt;&#x2F;code&gt; for the latter.
The &lt;code&gt;\texttt{}&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.tutorialspoint.com&#x2F;tex_commands&#x2F;texttt.htm&quot;&gt;command&lt;&#x2F;a&gt; also works well for formatting “C++”.
Here is a comparison with &lt;code&gt;C++&lt;&#x2F;code&gt; on the left vs &lt;code&gt;C\texttt{++}&lt;&#x2F;code&gt; on the right:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;cpp_comparison.png&quot; alt=&quot;Comparison&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;education-experience&quot;&gt;Education &amp;amp; Experience&lt;&#x2F;h2&gt;
&lt;p&gt;For both of these sections, you might use a bulleted &lt;code&gt;\begin{itemize}&lt;&#x2F;code&gt; list and will want to display a time range.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bullets&quot;&gt;Bullets&lt;&#x2F;h2&gt;
&lt;p&gt;By default, itemized lists in LaTeX are quite expansive, taking up excessive space.
To compact them, try &lt;code&gt;\setlength\itemsep{-0.5em}&lt;&#x2F;code&gt; right after the &lt;code&gt;\begin{itemize}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dates&quot;&gt;Dates&lt;&#x2F;h3&gt;
&lt;p&gt;It’s good practice to include a range from a start month and year to an end month and year.
For months, I recommend using the &lt;a href=&quot;https:&#x2F;&#x2F;abbreviations.yourdictionary.com&#x2F;articles&#x2F;standard-month-and-days-of-the-week-abbreviations.html&quot;&gt;standard 3 letter abbreviations&lt;&#x2F;a&gt; for consistency and alignment: &lt;code&gt;Aug. 2019&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You may have something like &lt;code&gt;Aug. 2019 - Sep. 2020&lt;&#x2F;code&gt;, for which I have one nitpick: hyphens are not for ranges.
As &lt;a href=&quot;https:&#x2F;&#x2F;practicaltypography.com&#x2F;hyphens-and-dashes.html&quot;&gt;Practical Typography&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Dash#Ranges_of_values&quot;&gt;Wikipedia&lt;&#x2F;a&gt; will both tell you, the correct character is the “en dash”, produced in LaTeX with &lt;code&gt;\textendash{}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, most resumes float the date for degrees, job experience, awards, etc to the right.
In LaTeX, this may be emulated by &lt;code&gt;\hspace*{\fill}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This LaTeX: &lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Tex&quot; data-lang=&quot;Tex&quot;&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;\textbf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;{Company Name} - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;\emph&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;{Support Technician} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;\hspace&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;*{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;\fill&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;}Nov. 2018 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;\textendash&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;{} Jul. 2019
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Will produce this:
&lt;img src=&quot;&#x2F;img&#x2F;resume_experience.png&quot; alt=&quot;Experience example&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;multiple-columns&quot;&gt;Multiple Columns&lt;&#x2F;h2&gt;
&lt;p&gt;Add &lt;code&gt;\usepackage{multicol}&lt;&#x2F;code&gt; and then you can easily use multiple columns with &lt;code&gt;\begin{multicols}{3}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I used this to split my project list into two columns, and my technical proficiencies into three: “Languages&#x2F;Frameworks”, “DevOps”, and “Web&#x2F;Typesetting”.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Switching to Pipewire from Pulseaudio on Void Linux</title>
		<published>2021-04-06T00:00:00+00:00</published>
		<updated>2021-04-08T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/pipewire-void-linux/" type="text/html"/>
		<id>https://sburris.xyz/posts/pipewire-void-linux/</id>
		<content type="html">&lt;h2 id=&quot;pipewire&quot;&gt;Pipewire&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pipewire.org&#x2F;&quot;&gt;Pipewire&lt;&#x2F;a&gt; is a new multimedia processing framework being developed for Linux with potential to simplify the Linux audio stack.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-old-setup&quot;&gt;The Old Setup&lt;&#x2F;h3&gt;
&lt;p&gt;If you run Linux you probably use Pulseaudio, which sits atop ALSA.
If you are a musician or music producer, you also likely use &lt;a href=&quot;https:&#x2F;&#x2F;jackaudio.org&#x2F;&quot;&gt;JACK&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Pulseaudio is better for most applications, but JACK is great for low-latency audio processing.
Getting the two to play nicely together takes a bit of work.
Pipewire has the potential to replace both.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;switching-to-pipewire&quot;&gt;Switching to Pipewire&lt;&#x2F;h2&gt;
&lt;p&gt;There is an &lt;a href=&quot;https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;voidlinux&#x2F;comments&#x2F;lp5w87&#x2F;how_i_got_pipewire_working_on_void_as_a_pulse&#x2F;&quot;&gt;excellent post on r&#x2F;voidlinux&lt;&#x2F;a&gt; about this topic.
This is the process I used with great success.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;&#x2F;h2&gt;
&lt;p&gt;The intent of this post was the inform Void Linux users that Pipewire is now an option for most audio needs.
The main thing I have to add here is how to fix Pipewire breaking after updates.&lt;&#x2F;p&gt;
&lt;p&gt;Pipewire, being a newer project, has a frequently-changing configuration file format.
If you update your system and things stop working, you need to reset &lt;code&gt;&#x2F;etc&#x2F;pipewire&#x2F;pipewire.conf&lt;&#x2F;code&gt;.
This can be done by forcefully reinstalling the package:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# xbps-install pipewire -f
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After doing this, you will need to re-uncomment the line as you did earlier:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;&#x2F;usr&#x2F;bin&#x2F;pipewire&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt; = { args = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;-c pipewire-pulse.conf&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
	</entry>
	<entry xml:lang="en">
		<title>The Easiest and Cheapest Way to Prepare Agar at Home</title>
		<published>2021-03-09T00:00:00+00:00</published>
		<updated>2021-03-09T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/simple-agar-prep/" type="text/html"/>
		<id>https://sburris.xyz/posts/simple-agar-prep/</id>
		<content type="html">&lt;h2 id=&quot;what-is-agar&quot;&gt;What is Agar?&lt;&#x2F;h2&gt;
&lt;p&gt;Agar (pronounced “ay-gar”) is the nutrient-rich gel that goes in &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Petri_dish&#x2F;&quot;&gt;petri dishes&lt;&#x2F;a&gt; to culture&#x2F;cultivate yeast, bacteria, molds, fungi, etc.
Scientific equipment can be expensive, and if you prepare agar “the right way”, you’ll need a decent bit of money for equipment.
This method will probably cost you about $15 &lt;em&gt;if&lt;&#x2F;em&gt; you have access to a rice cooker or instant pot.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Please note: this procedure is not ideal, if your project is important then please consider doing it the standard way. I have no formal training in this sort of thing, but this method has worked for me.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;materials-and-equipment&quot;&gt;Materials and Equipment&lt;&#x2F;h2&gt;
&lt;p&gt;Here are all of the materials you will need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agar powder&lt;&#x2F;strong&gt;: ~56 grams (~50 condiment cups worth) of Malt Extract Agar (MEA) cost me about $8 on Amazon. Check to see what type is recommended for your type of project.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Condiment cups&lt;&#x2F;strong&gt;: available at virtually every restaurant or in huge packs for cheap online.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Medical tape&lt;&#x2F;strong&gt;: try your local drug store.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here is all of the equipment you will need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Instant Pot&#x2F;Pressure Cooker&lt;&#x2F;strong&gt;: if it is airtight and gets hot it will probably work.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Trivet&lt;&#x2F;strong&gt;: must fit inside pressure cooker to lift cups off the bottom.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A way to boil water&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Clean mixing vessel&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Something to mix with&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tupperware&lt;&#x2F;strong&gt;: for storage and cooling&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Thermometer (optional but recommended)&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;agar_materials.jpg&quot; alt=&quot;Agar supplies&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;procedure&quot;&gt;Procedure&lt;&#x2F;h2&gt;
&lt;p&gt;I highly recommend reading this entire section before starting to do it yourself.
The main thing that can go wrong is improper sterilization that can lead to contamination and ruin your plates.
Try to keep everything clean and wipe everything down before-hand.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;choose-an-amount&quot;&gt;Choose an Amount&lt;&#x2F;h3&gt;
&lt;p&gt;How much agar do you need?
Do the math and figure out how much water is needed based on the package’s instructions.
I only wanted 5 condiment cups so I used 2.3g of MEA powder and 50ml of water.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mix-agar&quot;&gt;Mix Agar&lt;&#x2F;h3&gt;
&lt;p&gt;Boil water then mix the calculated amounts of water and Agar powder in the mixing vessel.
You don’t want to pour it into the condiment cups until it has cooled a bit.
The package on my Agar says to do it at 50C, when it stops steaming should be fine though.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;condiment-cups&quot;&gt;Condiment Cups&lt;&#x2F;h3&gt;
&lt;p&gt;While you wait, lay out twice the number of condiment cups as you want to make.
&lt;strong&gt;Do not use the cup lids!&lt;&#x2F;strong&gt; They are made of a different type of plastic (PET or PETE) than the cups (PP) and will melt in the pressure cooker, &lt;strong&gt;you will have to restart.&lt;&#x2F;strong&gt;
This is why we will be using two cups taped together as I learned the hard way.
You will not need lids until you innoculate the agar.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pour-the-agar&quot;&gt;Pour the Agar&lt;&#x2F;h3&gt;
&lt;p&gt;Once the agar solution has cooled, it’s time to pour it into 1&#x2F;2 of the cups laid out.
Pour just enough to cover the bottom of each, it doesn’t have to be precise.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;prepare-for-sterilization&quot;&gt;Prepare for Sterilization&lt;&#x2F;h3&gt;
&lt;p&gt;Flip the unfilled cups onto the tops of the filled cups and then tape them together.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;agar_cups.jpg&quot; alt=&quot;Agar cups&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sterilize&quot;&gt;Sterilize&lt;&#x2F;h3&gt;
&lt;p&gt;Add trivet and water to the pressure cooker, such that the condiment cups will be completely above the water when on top of the trivet.
I use about a half inch of water, the steam is what does the sterilizing.
Load the cups onto the trivet, stacking a few &lt;em&gt;should&lt;&#x2F;em&gt; be fine.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;agar_cooker.jpg&quot; alt=&quot;Agar in Pressure Cooker&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;“Cook” at 15PSI for 15 minutes.
If you don’t know how, check the manual or the internet.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;agar_soup.jpg&quot; alt=&quot;Pressure cooker settings&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Very important: do not vent the pressure cooker.&lt;&#x2F;strong&gt;
Venting the pressure cooker creates a pressure change that will cause the cups to explode.
Instead, wait about 15-30 minutes for the temperature and pressure (which are inversely related, see &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Gay-Lussac%27s_law&quot;&gt;Gay-Lussac’s law&lt;&#x2F;a&gt;) to decrease.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;post-sterilization&quot;&gt;Post-sterilization&lt;&#x2F;h3&gt;
&lt;p&gt;Your agar plates are now sterilized.
The agar will be liquid still, this is to be expected.
However, the medical tape is wet from steam and I believe it is possible for contaminants to cross its barrier.
It is therefor imperative to minimize the time spent in the open air.
Clean some tupperware then load the cups and seal as fast as possible, try to keep the air still by not moving quickly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cooling&quot;&gt;Cooling&lt;&#x2F;h3&gt;
&lt;p&gt;Let the tupperware of plates sit for a bit, or place in the refridgerator.
When the agar has solidified, it is ready to use.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;&#x2F;h2&gt;
&lt;p&gt;Follow sterile procedure when using the agar plates, this means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Flame-sterilize &lt;del&gt;paperclips&lt;&#x2F;del&gt; inoculation loops and &lt;del&gt;x-acto knives&lt;&#x2F;del&gt; scalpels&lt;&#x2F;li&gt;
&lt;li&gt;Use a &lt;del&gt;plastic tub&lt;&#x2F;del&gt; Still Air Box (SAB) or a quiet corner with the AC off that is not a bathroom&lt;&#x2F;li&gt;
&lt;li&gt;Wear gloves&lt;&#x2F;li&gt;
&lt;li&gt;Wipe &lt;strong&gt;everything&lt;&#x2F;strong&gt; down with 70% isopropyl alcohol (90% can evaporate before killing contaminants), this includes the gloves&lt;&#x2F;li&gt;
&lt;li&gt;Move slowly to avoid drafts of air&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Inside the Still Air Box prepare a lid for every agar plate (close bag promptly, wipe down anything exposed to air).
Peel off the tape and remove the top cup.
As soon as whatever living thing you are growing has been introduced, quickly put the lid back on and label.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve done this a few times and have only seen two cases of contamination so far, which probably had more to do with my questionable SAB setup than anything.
I hope this has been useful, please let me know below if you have any questions.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Open Source Blog Comments with Cactus Comments</title>
		<published>2021-03-07T00:00:00+00:00</published>
		<updated>2021-03-07T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/cactus-comments/" type="text/html"/>
		<id>https://sburris.xyz/posts/cactus-comments/</id>
		<content type="html">&lt;h2 id=&quot;cactus-comments&quot;&gt;Cactus Comments&lt;&#x2F;h2&gt;
&lt;p&gt;I have been looking for a comment system for this blog for a while now, but could never find anything that met my needs.
Luckily I recently came across &lt;a href=&quot;https:&#x2F;&#x2F;cactus.chat&#x2F;&quot;&gt;Cactus Comments&lt;&#x2F;a&gt;.
It is open source, easy to set up, and allows anonymous comments.&lt;&#x2F;p&gt;
&lt;p&gt;Since I don’t trust systems such as Disqus with user privacy, Cactus being based on the &lt;a href=&quot;https:&#x2F;&#x2F;matrix.org&#x2F;&quot;&gt;Matrix&lt;&#x2F;a&gt; protocol is really nice, it means that:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It respects user privacy&lt;&#x2F;li&gt;
&lt;li&gt;The site owner doesn’t have to self-host&lt;&#x2F;li&gt;
&lt;li&gt;It’s free&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;cactus.chat&#x2F;docs&#x2F;getting-started&#x2F;quick-start&#x2F;&quot;&gt;Quick Start Guide&lt;&#x2F;a&gt; is very straightforward so I will not go into detail but the basic process is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Create a Matrix account&lt;&#x2F;li&gt;
&lt;li&gt;Message &lt;a href=&quot;https:&#x2F;&#x2F;matrix.to&#x2F;#&#x2F;@cactusbot:cactus.chat&quot;&gt;cactusbot&lt;&#x2F;a&gt; to register your site&lt;&#x2F;li&gt;
&lt;li&gt;Embed some CSS&#x2F;JS (you probably want to set &lt;code&gt;commentSectionId: &amp;quot;{{ page.slug }}&amp;quot;&lt;&#x2F;code&gt; or something similar)&lt;&#x2F;li&gt;
&lt;li&gt;Apply some custom styling&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;moderation&quot;&gt;Moderation&lt;&#x2F;h2&gt;
&lt;p&gt;It took me a bit to figure out how to moderate Cactus Comments, as it is not covered in the &lt;a href=&quot;https:&#x2F;&#x2F;cactus.chat&#x2F;docs&#x2F;getting-started&#x2F;introduction&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt;.
Let’s say someone said something unpleasant on your site, here’s how to remove their comment:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Go to your page with the comment&lt;&#x2F;li&gt;
&lt;li&gt;Click “Use a Matrix client” to go to the Matrix room associated with that specific post&lt;&#x2F;li&gt;
&lt;li&gt;Accept the invitation and join the room&lt;&#x2F;li&gt;
&lt;li&gt;Click the three dots on the right of the offending comment&lt;&#x2F;li&gt;
&lt;li&gt;Click “Remove” (or “Report Content” if appropriate)&lt;&#x2F;li&gt;
&lt;li&gt;Kick&#x2F;ban&#x2F;mute poster of the message by clicking their name and selecting an action from the sidebar&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;cactus_remove.png&quot; alt=&quot;Remove Cactus Comment&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Cactus Comments has so far been a great solution for comments.
If you are particularly concerned about privacy, you can also use it on your own &lt;a href=&quot;https:&#x2F;&#x2F;matrix.org&#x2F;docs&#x2F;guides&#x2F;installing-synapse&quot;&gt;Matrix homeserver&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to try out the comment below (within reason, obviously):&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Configuring Swaybar with MPD, Volume, and Weather Display</title>
		<published>2021-03-05T00:00:00+00:00</published>
		<updated>2021-03-08T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/swaybar-configuration/" type="text/html"/>
		<id>https://sburris.xyz/posts/swaybar-configuration/</id>
		<content type="html">&lt;h2 id=&quot;swaybar&quot;&gt;Swaybar&lt;&#x2F;h2&gt;
&lt;p&gt;Swaybar is the default bar that comes with &lt;a href=&quot;https:&#x2F;&#x2F;swaywm.org&#x2F;&quot;&gt;Sway&lt;&#x2F;a&gt;, a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Tiling_window_manager&quot;&gt;tiling window manager&lt;&#x2F;a&gt; for &lt;a href=&quot;https:&#x2F;&#x2F;wayland.freedesktop.org&#x2F;&quot;&gt;Wayland&lt;&#x2F;a&gt;.
By default it displays only the workspace indicator and time, it looks like this:
&lt;img src=&quot;&#x2F;img&#x2F;swaybar_default.png&quot; alt=&quot;Swaybar Default&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It’s functional but a little plain.
This is what mine looks like:
&lt;img src=&quot;&#x2F;img&#x2F;swaybar_customized.png&quot; alt=&quot;Customized Swaybar&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aesthetic-changes&quot;&gt;Aesthetic Changes&lt;&#x2F;h2&gt;
&lt;p&gt;There are main ways to make it look better:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fonts&quot;&gt;Fonts&lt;&#x2F;h3&gt;
&lt;p&gt;Fonts can be specified in &lt;code&gt;~&#x2F;.config&#x2F;sway&#x2F;config&lt;&#x2F;code&gt;: just add &lt;code&gt;font pango:Fira Sans SemiBold 9&lt;&#x2F;code&gt; or similar somewhere.
This font is also used for window titles, if you haven’t disabled them with &lt;code&gt;default_border pixel&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;colors&quot;&gt;Colors&lt;&#x2F;h3&gt;
&lt;p&gt;To change the bar colors, edit the &lt;code&gt;colors&lt;&#x2F;code&gt; subsection in the &lt;code&gt;bar&lt;&#x2F;code&gt; block:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;bar {
    colors {
        statusline &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#ebdbb2
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;        background &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#3c3836
        
        # Outline, Background, Foreground
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;        inactive_workspace &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#282828 #282828 #928374
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;        focused_workspace &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;#83a598 #458588 #eddbb2
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;}
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;functional-changes&quot;&gt;Functional Changes&lt;&#x2F;h2&gt;
&lt;p&gt;How do we add more useful things to the bar?&lt;&#x2F;p&gt;
&lt;p&gt;The first step is to move the &lt;code&gt;status_command&lt;&#x2F;code&gt; into its own file, replace the line with &lt;code&gt;status_command ~&#x2F;.config&#x2F;sway&#x2F;bar.sh&lt;&#x2F;code&gt; or whatever file you’d like, then create that file and make sure to run &lt;code&gt;chmod +x ~&#x2F;.config&#x2F;sway&#x2F;bar.sh&lt;&#x2F;code&gt; so it can be executed.
Inside this file you will need a &lt;code&gt;while&lt;&#x2F;code&gt; loop so that it always updates at a constant step:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;do
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;This will display on the bar&amp;#39;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;sleep 1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;done 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now adding things to the bar is simply &lt;code&gt;echo&lt;&#x2F;code&gt;ing output from the script.
For cleanliness, I put all of the components I want to display in their own variables just as shown above with &lt;code&gt;msg&lt;&#x2F;code&gt;.
To divide things up for readability, I separate my components with vertical pipe characters: &lt;code&gt;echo &amp;quot;$msg | $time&amp;quot;&lt;&#x2F;code&gt;, etc.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;custom-time-format&quot;&gt;Custom Time Format&lt;&#x2F;h3&gt;
&lt;p&gt;I didn’t like the default datetime format, so I split it up.
Inside the while loop I have the following:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# $(cmd) stores the output of cmd
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;date&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;date +&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;%A, %b %d&amp;#39;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;date +&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;%I%M %p&amp;#39;)

&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# =&amp;gt; Friday, Mar 05 | 03:47 PM
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;date&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt; | $&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;time&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;sleep 1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;volume&quot;&gt;Volume&lt;&#x2F;h3&gt;
&lt;p&gt;This will work for both pulseaudio and &lt;a href=&quot;https:&#x2F;&#x2F;pipewire.org&#x2F;&quot;&gt;pipewire&lt;&#x2F;a&gt;, which I recently switched to.
Install &lt;code&gt;pamixer&lt;&#x2F;code&gt; if you don’t have it already, then you can store the output of &lt;code&gt;pamixer --get-volume&lt;&#x2F;code&gt; in a variable, and &lt;code&gt;echo &amp;quot;$vol%&lt;&#x2F;code&gt; to suffix it with a percent sign.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mpd-music&quot;&gt;MPD Music&lt;&#x2F;h3&gt;
&lt;p&gt;The command to be stored and &lt;code&gt;echo&#x27;d&lt;&#x2F;code&gt; here is &lt;code&gt;mpc -f &amp;quot;%title% - %artist%&amp;quot; | head -n 1&lt;&#x2F;code&gt;.
&lt;code&gt;head&lt;&#x2F;code&gt; is used to remove unwanted lines from &lt;code&gt;mpc&lt;&#x2F;code&gt; (may need to be installed) output.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;weather&quot;&gt;Weather&lt;&#x2F;h3&gt;
&lt;p&gt;This took me a bit to get right.
We want a fast refresh rate (&lt;code&gt;sleep 1&lt;&#x2F;code&gt; = update every second) for time and music,  but making an HTTP request to get the current temperature every second is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;unnecessary&lt;&#x2F;li&gt;
&lt;li&gt;wasteful of power&lt;&#x2F;li&gt;
&lt;li&gt;likely to get your IP address rate-limited&#x2F;banned&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;My solution is to read from a temporary file every second, but only update the temporary file every 15 minutes.&lt;&#x2F;p&gt;
&lt;p&gt;In my &lt;code&gt;bar.sh&lt;&#x2F;code&gt; script, I have &lt;code&gt;temp=$(cat &#x2F;tmp&#x2F;weather)&lt;&#x2F;code&gt;.
In the Sway configuration file I have &lt;code&gt;exec ~&#x2F;.config&#x2F;sway&#x2F;weather.sh&lt;&#x2F;code&gt; to start the script to update the temporary file when Sway starts.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;weather.sh&lt;&#x2F;code&gt; is a bit more involved:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;do
    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# Get output silently, remove unwanted lines, reformat, output to temp file
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;curl -s wttr.in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;QT0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;grep -m 1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39; °F&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;perl -pe &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;s&#x2F;.*?\+(\d+2)(\(d+\))? °F.*$&#x2F;$1$2 °F&#x2F;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt; &#x2F;tmp&#x2F;weather
    sleep 900
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;done
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You may want to &lt;code&gt;curl wttr.in&lt;&#x2F;code&gt; to make sure it is getting weather data for the correct location.
If it isn’t, add &lt;code&gt;&#x2F;cityname&lt;&#x2F;code&gt; to the end of the URL.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;It’s easy to add any information you want to Swaybar.
Simply &lt;code&gt;echo&lt;&#x2F;code&gt; the data you want in a script pointed to by the Sway configuration file.
If Swaybar doesn’t meet your customization&#x2F;aesthetic needs, have a look at &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Alexays&#x2F;Waybar&quot;&gt;Waybar&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Useful Tools for Writing Python</title>
		<published>2021-02-03T00:00:00+00:00</published>
		<updated>2021-02-03T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/python-tools/" type="text/html"/>
		<id>https://sburris.xyz/posts/python-tools/</id>
		<content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve been writing Python for a long time now.
Here are some tools I’ve found to be more productive along the way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;poetry&quot;&gt;Poetry&lt;&#x2F;h2&gt;
&lt;p&gt;If you use &lt;a href=&quot;https:&#x2F;&#x2F;pipenv.pypa.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;Pipenv&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;pip.pypa.io&#x2F;en&#x2F;stable&#x2F;&quot;&gt;Pip&lt;&#x2F;a&gt;, or &lt;a href=&quot;https:&#x2F;&#x2F;virtualenv.pypa.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;Virtualenv&lt;&#x2F;a&gt; to manage your projects, I highly recommend you switch to &lt;a href=&quot;https:&#x2F;&#x2F;python-poetry.org&#x2F;&quot;&gt;Python Poetry&lt;&#x2F;a&gt;.
Poetry manages your virtual environments and dependencies on a per-project basis that yield reproducible builds.
It is similar to Pipenv but has a few advantages:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;johnfraney.ca&#x2F;posts&#x2F;2019&#x2F;03&#x2F;06&#x2F;pipenv-poetry-benchmarks-ergonomics&#x2F;&quot;&gt;Faster&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Can export &lt;code&gt;requirements.txt&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Pyproject.toml&lt;&#x2F;code&gt; is a &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0518&#x2F;&quot;&gt;PEP&lt;&#x2F;a&gt;, &lt;code&gt;Pipfile&lt;&#x2F;code&gt; is Pipenv-specific&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Poetry is a great way to install some of the other tools on this list as development dependencies with &lt;code&gt;poetry add -D [name]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mypy&quot;&gt;Mypy&lt;&#x2F;h2&gt;
&lt;p&gt;Since I’ve been writing Rust, I have missed static type-checking in Python.
It can catch a lot of errors before they happen.
&lt;a href=&quot;http:&#x2F;&#x2F;mypy-lang.org&#x2F;&quot;&gt;Mypy&lt;&#x2F;a&gt; is a way to actually do something useful with the &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0484&#x2F;&quot;&gt;type annotations&lt;&#x2F;a&gt; in Python.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;flake8&quot;&gt;Flake8&lt;&#x2F;h2&gt;
&lt;p&gt;Unlike many languages, Python has an &lt;a href=&quot;https:&#x2F;&#x2F;pep8.org&#x2F;&quot;&gt;official style guide&lt;&#x2F;a&gt; (please use it).
&lt;a href=&quot;https:&#x2F;&#x2F;flake8.pycqa.org&#x2F;en&#x2F;latest&#x2F;&quot;&gt;Flake8&lt;&#x2F;a&gt; is your guide to achieving PEP-8 compliance.
When you run &lt;code&gt;flake8&lt;&#x2F;code&gt;, it will point out where there are style issues.&lt;&#x2F;p&gt;
&lt;p&gt;If you don’t agree with some rules or find them a hinderance like I do, you can put a file called &lt;code&gt;.flake8&lt;&#x2F;code&gt; in your project root to disable them:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;[flake8]
ignore = E402, E501
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;isort&quot;&gt;isort&lt;&#x2F;h2&gt;
&lt;p&gt;Organized import statements can also make your code look better.
I use &lt;a href=&quot;https:&#x2F;&#x2F;pycqa.github.io&#x2F;isort&#x2F;&quot;&gt;isort&lt;&#x2F;a&gt; in pretty much all of my Python projects.
Just run &lt;code&gt;isort .&lt;&#x2F;code&gt; and it’ll sort your imports, it’s easy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bandit&quot;&gt;Bandit&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PyCQA&#x2F;bandit&quot;&gt;Bandit&lt;&#x2F;a&gt; is made by the same group as isort.
It checks your codebase for common security issues.
Bandit checks for many types of security errors, including this made using &lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;flask.palletsprojects.com&#x2F;en&#x2F;1.1.x&#x2F;&quot;&gt;Flask&lt;&#x2F;a&gt;.
Running a single command is a small price for some peace of mind.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gitignore-io&quot;&gt;Gitignore.io&lt;&#x2F;h2&gt;
&lt;p&gt;This one is a &lt;a href=&quot;https:&#x2F;&#x2F;sburris.xyz&#x2F;posts&#x2F;python-tools&#x2F;gitignore.io&quot;&gt;website&lt;&#x2F;a&gt;, not a program.
It’s an easy way to generate &lt;code&gt;.gitignore&lt;&#x2F;code&gt; files so that you don’t commit files that no one else cares about (or maybe too much about, such as private keys and passwords).
Just type in the languages, frameworks, libraries, editors you use and it will generate a nice &lt;code&gt;.gitignore&lt;&#x2F;code&gt; for you.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;other-things-your-project-should-have&quot;&gt;Other Things Your Project Should Have&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;README.md&lt;&#x2F;code&gt; with project info, installation instructions, setup notes, etc.&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;code&gt;LICENSE.md&lt;&#x2F;code&gt;, lack of a license means that users do not have permission to use, share, or modify your code (I like &lt;a href=&quot;https:&#x2F;&#x2F;opensource.org&#x2F;licenses&#x2F;ISC&quot;&gt;ISC&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;code&gt;.gitignore&lt;&#x2F;code&gt;, some things should not be commited. Check out &lt;a href=&quot;https:&#x2F;&#x2F;sburris.xyz&#x2F;posts&#x2F;python-tools&#x2F;gitignore.io&quot;&gt;gitignore.io&lt;&#x2F;a&gt; to generate one.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>How to Replace Sudo with Doas on Void Linux</title>
		<published>2021-01-27T00:00:00+00:00</published>
		<updated>2021-01-29T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/doas-void-linux/" type="text/html"/>
		<id>https://sburris.xyz/posts/doas-void-linux/</id>
		<content type="html">&lt;h2 id=&quot;why&quot;&gt;Why?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;sudo&lt;&#x2F;code&gt; is 40 years old and &lt;a href=&quot;http:&#x2F;&#x2F;cve.mitre.org&#x2F;cgi-bin&#x2F;cvename.cgi?name=CVE-2021-3156&quot;&gt;new CVEs&lt;&#x2F;a&gt; are still being found, perhaps because it’s ~412k (mostly plugins and tooling, more like ~15k lines which is still a lot) lines of code to let users switch accounts for a single command.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-four-steps&quot;&gt;The Four Steps&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Install the &lt;code&gt;doas&lt;&#x2F;code&gt; package: &lt;code&gt;sudo xbps-install opendoas&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Create &lt;code&gt;&#x2F;etc&#x2F;doas.conf&lt;&#x2F;code&gt; and add &lt;code&gt;permit your_username as root&lt;&#x2F;code&gt;, this is the last time you’ll be using &lt;code&gt;sudo&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;(optional) create a bash alias by adding &lt;code&gt;alias sudo=&#x27;doas&#x27;&lt;&#x2F;code&gt; to &lt;code&gt;~&#x2F;.bashrc&lt;&#x2F;code&gt; then run &lt;code&gt;source ~&#x2F;.bashrc&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Remove the &lt;code&gt;sudo package&lt;&#x2F;code&gt;: &lt;code&gt;sudo xbps-remove -F sudo&lt;&#x2F;code&gt; or &lt;code&gt;doas xbps-remove -F sudo&lt;&#x2F;code&gt; if you didn’t add an alias.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;don-t-things-depend-on-sudo&quot;&gt;Don’t Things Depend on Sudo?&lt;&#x2F;h3&gt;
&lt;p&gt;Yes.
The &lt;code&gt;-F&lt;&#x2F;code&gt; flag for &lt;code&gt;xbps-remove&lt;&#x2F;code&gt; is needed to force XBPS to ignore &lt;code&gt;base-system&lt;&#x2F;code&gt;’s dependency upon it.
Everything I’ve seen will fallback to &lt;code&gt;doas&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>How to Disable Audio in the Bevy Game Engine</title>
		<published>2021-01-22T00:00:00+00:00</published>
		<updated>2021-01-22T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/bevy-disable-audio/" type="text/html"/>
		<id>https://sburris.xyz/posts/bevy-disable-audio/</id>
		<content type="html">&lt;h2 id=&quot;why-disable-audio&quot;&gt;Why Disable Audio?&lt;&#x2F;h2&gt;
&lt;p&gt;You probably don’t want to disable audio.
Unless, that is, your audio setup is giving you issues and impeding development.&lt;&#x2F;p&gt;
&lt;p&gt;In my case, I get an error message from the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RustAudio&#x2F;rodio&quot;&gt;Rodio&lt;&#x2F;a&gt; crate that &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;Bevy&lt;&#x2F;a&gt; uses that looks like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;ALSA lib pcm_dmix.c:1108:(snd_pcm_dmix_open) unable to open slave
thread &amp;#39;main&amp;#39; panicked at &amp;#39;The device doesn&amp;#39;t support any format!?: DeviceNotAvailable&amp;#39;, &#x2F;home&#x2F;spencer&#x2F;code&#x2F;project&#x2F;audiofile.rs:10:10
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my case, it seems that Rodio is trying to connect to ALSA instead of Pulseaudio.
This is a problem because ALSA only supports one output, hence the need for Pulseaudio (which is probably using that single output and acting like a virtual splitter jack).
This specific issue is tracked on GitHub &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RustAudio&#x2F;rodio&#x2F;issues&#x2F;267&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cargo-features&quot;&gt;Cargo Features&lt;&#x2F;h2&gt;
&lt;p&gt;Bevy comes with a &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;features.html&quot;&gt;Cargo feature&lt;&#x2F;a&gt; that &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bevyengine&#x2F;bevy&#x2F;blob&#x2F;master&#x2F;docs&#x2F;cargo_features.md#bevy_audio&quot;&gt;enables audio&lt;&#x2F;a&gt; by default.
There is a full list of features in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bevyengine&#x2F;bevy&#x2F;blob&#x2F;master&#x2F;docs&#x2F;cargo_features.md&quot;&gt;docs&lt;&#x2F;a&gt; and in &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bevyengine&#x2F;bevy&#x2F;blob&#x2F;master&#x2F;Cargo.toml#L22&quot;&gt;Cargo.toml&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Anyways, go to your project’s &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;, remove the &lt;code&gt;bevy&lt;&#x2F;code&gt; line from under &lt;code&gt;[dependencies]&lt;&#x2F;code&gt; and add the following:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Toml&quot; data-lang=&quot;Toml&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;dependencies.bevy&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;version &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;0.4&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;default-features &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;false
&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;features &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;= [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;bevy_gltf&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;bevy_winit&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;bevy_wgpu&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;render&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;bevy_dynamic_plugin&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;png&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;hdr&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;x11&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This does three things:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Replaces the &lt;code&gt;bevy&lt;&#x2F;code&gt; line we just removed&lt;&#x2F;li&gt;
&lt;li&gt;Tells Cargo that we don’t want Bevy’s default features&lt;&#x2F;li&gt;
&lt;li&gt;Tells Cargo that we want every default feature except &lt;code&gt;bevy_audio&lt;&#x2F;code&gt; and &lt;code&gt;mp3&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Hope this helped.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Bevy Flycam Plugin Release</title>
		<published>2021-01-21T00:00:00+00:00</published>
		<updated>2021-01-21T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/bevy-flycam/" type="text/html"/>
		<id>https://sburris.xyz/posts/bevy-flycam/</id>
		<content type="html">&lt;h2 id=&quot;bevy-flycam&quot;&gt;Bevy Flycam&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve written a plugin for the &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;Bevy game engine&lt;&#x2F;a&gt; that enables basic 3D FPS-style player controls.
It is now available on &lt;a href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;bevy_flycam&quot;&gt;crates.io&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sburris0&#x2F;bevy_flycam&quot;&gt;GitHub&lt;&#x2F;a&gt;.
Usage instructions, features, and information on customization are all available on either website.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;demo&quot;&gt;Demo&lt;&#x2F;h3&gt;
&lt;p&gt;Usage can be seen in my article about &lt;a href=&quot;&#x2F;posts&#x2F;bevy-gravity&quot;&gt;physics in Bevy&lt;&#x2F;a&gt; and this video:&lt;&#x2F;p&gt;
&lt;video controls preload=&quot;metadata&quot;&gt;
    &lt;source src=&quot;&#x2F;video&#x2F;positive_gravity.mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;p&gt;All keyboard and mouse input is processed into movement by this plugin.
The cubes and gravity are not included.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Gravity and Physics in the Bevy Game Engine</title>
		<published>2021-01-20T00:00:00+00:00</published>
		<updated>2021-07-18T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/bevy-gravity/" type="text/html"/>
		<id>https://sburris.xyz/posts/bevy-gravity/</id>
		<content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;Bevy&lt;&#x2F;a&gt; is a really neat game engine for &lt;a href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;Rust&lt;&#x2F;a&gt;.
As of &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;news&#x2F;bevy-0-4&#x2F;&quot;&gt;version 0.4&lt;&#x2F;a&gt;, Bevy does not come with physics.
Luckily, the &lt;a href=&quot;https:&#x2F;&#x2F;rapier.rs&#x2F;&quot;&gt;Rapier physics engine&lt;&#x2F;a&gt; folks maintain an official &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dimforge&#x2F;bevy_rapier&quot;&gt;Rapier plugin&lt;&#x2F;a&gt; for Bevy with &lt;a href=&quot;https:&#x2F;&#x2F;rapier.rs&#x2F;docs&#x2F;user_guides&#x2F;rust_bevy_plugin&#x2F;getting_started&#x2F;&quot;&gt;helpful documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Throughout this post, the demos will be from one of my codebases (will be public soon), and will not match the minimal relevant code presented in this post.
I will be focusing on physics in a 3d context specifically, though most of this should also apply to 2d games.
If you want something similar, you can add my &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sburris0&#x2F;bevy_flycam&quot;&gt;flycam plugin&lt;&#x2F;a&gt; for controls.
Some familiarity with Bevy is assumed, try the &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;learn&#x2F;book&#x2F;introduction&#x2F;&quot;&gt;Bevy book&lt;&#x2F;a&gt; if you need help.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;basic-setup&quot;&gt;Basic Setup&lt;&#x2F;h2&gt;
&lt;p&gt;You will need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bevy&lt;&#x2F;code&gt; and &lt;code&gt;bevy_rapier3d&lt;&#x2F;code&gt; in &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;dependencies&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;bevy &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;0.4&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;bevy_rapier3d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;*&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;Some sort of ground object so that our objects will have something to fall onto in a &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;learn&#x2F;book&#x2F;getting-started&#x2F;ecs&#x2F;#your-first-components&quot;&gt;startup system&lt;&#x2F;a&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;bevy::prelude::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;;

&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; Runs on startup, adds a ground plane
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;setup_world&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;commands&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; Commands,
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;meshes&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;: ResMut&amp;lt;Assets&amp;lt;Mesh&amp;gt;&amp;gt;,
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;materials&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;: ResMut&amp;lt;Assets&amp;lt;StandardMaterial&amp;gt;&amp;gt;,
) {
    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; Spawns a white plane at one unit below the origin
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;    commands
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(PbrBundle {
            mesh: meshes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(Mesh::from(shape::Plane { size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;128.0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;})),
            material: materials.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(Color::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;WHITE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;()),
            transform: Transform::from_translation(Vec3::unit_y() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;),
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;::default()
        });
}

#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;bevy_main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;() {
    App::build()
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add_plugins&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(DefaultPlugins)
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add_startup_system&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(setup_world.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;system&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;())
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;();
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;A mechanism for creating objects that will be affected by physics and gravity.
For example you could spawn a cube 10 units above the origin in the above startup system or any other system:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; ...
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(PbrBundle {
        mesh: meshes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(Mesh::from(shape::Cube { size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;1.0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;})),
        transform: Transform::from_translation(Vec3::unit_y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;10.0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;)
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;::default()
    });
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my demo, cubes are spawned on right-click.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;physics&quot;&gt;Physics&lt;&#x2F;h2&gt;
&lt;p&gt;Before implementing physics there’s some basic physics terminology worth knowing.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;em&gt;rigid body&lt;&#x2F;em&gt; is an object modeled to undergo zero deformation in collisions (tungsten brick, diamond, etc).&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;em&gt;soft body&lt;&#x2F;em&gt; is much more complicated to simulate and does undergo deformation (pillows, aluminum ball, etc).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We’ll focus on rigid bodies because they are far more common in games, and Rapier does not support soft bodies.
Now there are three main types of rigid bodies:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;em&gt;static rigid body&lt;&#x2F;em&gt; is not subject to forces such as gravity or collisions making it ideal for ground objects that should not fall eternally through the abyss&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;em&gt;kinematic rigid body&lt;&#x2F;em&gt; generates and applies a force to other objects, typically either the player object or vehicles that generate force upon keyboard input&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;em&gt;dynamic rigid body&lt;&#x2F;em&gt; is subject to external gravity and collisions such as those from a kinematic rigid body&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;adding-gravity&quot;&gt;Adding Gravity&lt;&#x2F;h3&gt;
&lt;p&gt;To be considered in Rapier’s physics calculations, an object needs two things: a collider and a rigid body.
Let’s add both to the cube above the origin in our startup system:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;bevy_rapier3d::rapier::dynamics::RigidBodyBuilder;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;bevy_rapier3d::rapier::geometry::ColliderBuilder;

&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;commands
    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; spawn ground plane ...
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(PbrBundle {
        mesh: meshes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(Mesh::from(shape::Cube { size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;1.0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;})),
        transform: Transform::from_translation(Vec3::unit_y() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;10.0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;)
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;::default()
    })
    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; Needed for physics
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(RigidBodyBuilder::new_dynamic().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(Vec3::unit_y() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;10.0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;)
    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(ColliderBuilder::cuboid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We use &lt;code&gt;RigidBodyBuilder::new_dynamic()&lt;&#x2F;code&gt; to create a dynamic rigid body.
There is also &lt;code&gt;new_static()&lt;&#x2F;code&gt; and &lt;code&gt;new_kinematic()&lt;&#x2F;code&gt;.
If translation is not specified, the object will exist at the origin.&lt;&#x2F;p&gt;
&lt;p&gt;A collider is created with &lt;code&gt;ColliderBuilder::cuboid()&lt;&#x2F;code&gt; where collider size is more like a radius, &lt;code&gt;(0.5, 0.5, 0.5)&lt;&#x2F;code&gt; fits the &lt;code&gt;size: 1.0&lt;&#x2F;code&gt; cube perfectly.&lt;&#x2F;p&gt;
&lt;p&gt;Run the game and you should see behavior like this:
&lt;video controls preload=&quot;metadata&quot;&gt;
&lt;source src=&quot;&#x2F;video&#x2F;fall_through_ground.mp4&quot;&gt;
&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;collisions&quot;&gt;Collisions&lt;&#x2F;h3&gt;
&lt;p&gt;The cubes go straight through the floor!
Depending on your circumstances, you will probably find this behavior undesirable.
The cube doesn’t “see” that the plane exists because it has no rigid body or collider.
As mentioned earlier, adding a dynamic rigid body would be a bit strange:
&lt;video controls preload=&quot;metadata&quot;&gt;
&lt;source src=&quot;&#x2F;video&#x2F;ground_falling.mp4&quot;&gt;
&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To prevent this you should use a static rigid body, but it also works with dynamic rigid bodies if one of the collider’s dimensions is ≤ 0 because this means a density of 0 (ρ=&#x2F;mv).&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;    commands
        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; Spawn the ground plane
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(PbrBundle {
            mesh: meshes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(Mesh::from(shape::Plane { size: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;128.0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;})),
            material: materials.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(Color::rgb(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;()),
            transform: Transform::from_translation(Vec3::unit_y() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2.0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;),
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;::default()
        })
        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; Static rigid body, collider
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(RigidBodyBuilder::new_static().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;translation&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;))
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(ColliderBuilder::cuboid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;64.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;64.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Remember that collider dimensions are half of &lt;code&gt;size&lt;&#x2F;code&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Now this looks a lot better:
&lt;video controls preload=&quot;metadata&quot;&gt;
&lt;source src=&quot;&#x2F;video&#x2F;working_gravity.mp4&quot;&gt;
&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;customizing-physics&quot;&gt;Customizing Physics&lt;&#x2F;h3&gt;
&lt;p&gt;You might have noticed that my gravity looks a bit slower than yours.
This is because I configured mine like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;bevy::prelude::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;bevy_rapier3d::physics::{RapierPhysicsPlugin, RapierConfiguration};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;bevy_rapier3d::rapier::na::Vector;

#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;bevy_main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;() {
    App::build()
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add_plugins&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(DefaultPlugins)
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add_plugin&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(RapierPhysicsPlugin)
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add_startup_system&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(setup_world.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;system&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;())
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add_resource&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(RapierConfiguration {
            gravity: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;Vector::y(),
            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;::default()
        })
        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;();
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I’m setting gravity to a rate of -1 units here, whereas it is -9.81 by default as in the real world.
Note that &lt;code&gt;RapierConfiguration&lt;&#x2F;code&gt; does not accept Bevy’s &lt;code&gt;Vec3&lt;&#x2F;code&gt; type (for now?).
You can view all of the configuration options &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;bevy_rapier3d&#x2F;0.7.0&#x2F;bevy_rapier3d&#x2F;physics&#x2F;struct.RapierConfiguration.html&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s have some fun with positive gravity (&lt;code&gt;gravity: Vector::y()&lt;&#x2F;code&gt;):
&lt;video controls preload=&quot;metadata&quot;&gt;
&lt;source src=&quot;&#x2F;video&#x2F;positive_gravity.mp4&quot;&gt;
&lt;&#x2F;video&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;customizing-rigid-bodies&quot;&gt;Customizing Rigid Bodies&lt;&#x2F;h3&gt;
&lt;p&gt;Check the docs &lt;a href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rapier3d&#x2F;0.4.2&#x2F;rapier3d&#x2F;dynamics&#x2F;struct.RigidBodyBuilder.html&quot;&gt;here&lt;&#x2F;a&gt; for a list of things you can set with &lt;code&gt;RigidBodyBuilder&lt;&#x2F;code&gt;.
A few examples of things you can set are whether the rigid body should have translations or rotations locked, the mass of the body, and the initial velocity.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;It’s easy to add gravity to Bevy games, and can be fun to play around with.
Perhaps in the future I’ll update this guide to include adding a kinematic rigid body to the camera controller so that the player can knock things over.
As always, &lt;a href=&quot;&#x2F;#contact&quot;&gt;let me know&lt;&#x2F;a&gt; if you have any questions or feedback.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Fix Firefox Uploading Rainbow-Striped Images and Videos</title>
		<published>2021-01-07T00:00:00+00:00</published>
		<updated>2021-01-07T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/firefox-rainbow-uploads/" type="text/html"/>
		<id>https://sburris.xyz/posts/firefox-rainbow-uploads/</id>
		<content type="html">&lt;h2 id=&quot;the-problem-and-solution&quot;&gt;The Problem and Solution&lt;&#x2F;h2&gt;
&lt;p&gt;If you try to upload an image or video to a site via Firefox and see a weird striped-rainbow pattern instead of what you intended to upload then the fix is actually extremely easy:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Type &lt;code&gt;about:config&lt;&#x2F;code&gt; into the address bar and hit enter&lt;&#x2F;li&gt;
&lt;li&gt;Ignore spooky message and click big blue button&lt;&#x2F;li&gt;
&lt;li&gt;Search for &lt;code&gt;privacy.resistFingerPrinting&lt;&#x2F;code&gt; and set it to &lt;code&gt;false&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;What was happening?
When this setting is enabled Firefox randomizes HTML canvas data.
Instead of an image you get the ugliest plaid you’ve ever seen.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>How to Sandbox Zoom with Firejail</title>
		<published>2021-01-06T00:00:00+00:00</published>
		<updated>2021-01-09T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/zoom-firejail/" type="text/html"/>
		<id>https://sburris.xyz/posts/zoom-firejail/</id>
		<content type="html">&lt;h2 id=&quot;zoom&quot;&gt;Zoom&lt;&#x2F;h2&gt;
&lt;p&gt;It’s Winter of 2020 and COVID-19 is taking off.
Universities and schools announce that classes will be held online using Zoom, a video chat platform literally no one has heard of that becomes ubiquitous overnight that &lt;a href=&quot;https:&#x2F;&#x2F;arstechnica.com&#x2F;tech-policy&#x2F;2020&#x2F;11&#x2F;zoom-lied-to-users-about-end-to-end-encryption-for-years-ftc-says&#x2F;&quot;&gt;lies about encryption&lt;&#x2F;a&gt; and has &lt;a href=&quot;https:&#x2F;&#x2F;www.reuters.com&#x2F;article&#x2F;us-zoom-video-commn-privacy-idUSKBN23I3GP&quot;&gt;ties to the Chinese government&lt;&#x2F;a&gt; because it’s so well-made and truly innovative.
Just kidding.
I don’t buy it; there’s spooky shit afoot.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;security-recommendations&quot;&gt;Security Recommendations&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Don’t sign in to a Zoom account&lt;&#x2F;li&gt;
&lt;li&gt;Use a VPN (not free or US-based)&lt;&#x2F;li&gt;
&lt;li&gt;Use a virtual machine (preferred, I was having hardware issues) or firejail&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;&#x2F;h2&gt;
&lt;p&gt;Install &lt;code&gt;firejail&lt;&#x2F;code&gt; and &lt;code&gt;zoom&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;On Void Linux:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# Install needed software
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;sudo xbps-install -S firejail git

&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# Set up xbps-src
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;git clone https:&#x2F;&#x2F;github.com&#x2F;void-linux&#x2F;void-packages
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt; void-packages
.&#x2F;xbps-src binary-bootstrap

&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# Enable restricted packages
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;echo XBPS_ALLOW_RESTRICTED=yes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt; etc&#x2F;conf

&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# Build Zoom package
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;.&#x2F;xbps-src pkg zoom
sudo xi zooom
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Information on restricted packages can be found &lt;a href=&quot;https:&#x2F;&#x2F;docs.voidlinux.org&#x2F;xbps&#x2F;repositories&#x2F;restricted.html&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Since Zoom is so popular it shouldn’t be hard to find specific instructions to install it for your distribution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;&#x2F;strong&gt;: &lt;a href=&quot;https:&#x2F;&#x2F;ar.al&#x2F;2020&#x2F;06&#x2F;25&#x2F;how-to-use-the-zoom-malware-safely-on-linux-if-you-absolutely-have-to&#x2F;&quot;&gt;this&lt;&#x2F;a&gt; article is much better. 
It accounts for several problems I later found with Zoom being unable to connect properly or open the browser.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;no-longer-recommended&quot;&gt;No Longer Recommended&lt;&#x2F;h3&gt;
&lt;p&gt;To run an application in a firejail sandbox the command is simply &lt;code&gt;firejail [software]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;firejail zoom&lt;&#x2F;code&gt;, click “Sign in”, do an “SSO Sign-in” and then you’ll see a page like this:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;zoom_signin.png&quot; alt=&quot;Zoom sign-in page&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;p&gt;Right-click “Launch Zoom” and “Copy Link Location”.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Now create a bash alias, in &lt;code&gt;.bashrc&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;zoom&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;firejail xdg-open &amp;quot;[copied URL]&amp;quot; &amp;amp;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;If &lt;code&gt;xdg-open&lt;&#x2F;code&gt; isn’t found, install &lt;code&gt;xdg-utils&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;troublshooting&quot;&gt;Troublshooting&lt;&#x2F;h3&gt;
&lt;p&gt;You &lt;strong&gt;may&lt;&#x2F;strong&gt; have to run Zoom without firejail the first time if your browser doesn’t open after clicking “SSO Sign-in”, obviously this isn’t ideal.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Bevy 0.3 → 0.4 Update Guide</title>
		<published>2020-12-19T00:00:00+00:00</published>
		<updated>2020-12-20T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/bevy-update-0-4/" type="text/html"/>
		<id>https://sburris.xyz/posts/bevy-update-0-4/</id>
		<content type="html">&lt;h2 id=&quot;bevy-0-4&quot;&gt;Bevy 0.4&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;news&#x2F;bevy-0-4&#x2F;&quot;&gt;Version 0.4&lt;&#x2F;a&gt; of the &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;&quot;&gt;Bevy game engine&lt;&#x2F;a&gt; just came out this morning.
Here are some of the changes (likely not all) that you either should or need to make if you want to switch to the new version
Before that, I’d like to thank the other 65 contributors and Bevy’s helpful community for helping to make something so cool.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;components-bundles&quot;&gt;Components → Bundles&lt;&#x2F;h2&gt;
&lt;p&gt;The following have been &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bevyengine&#x2F;bevy&#x2F;commit&#x2F;7628f4a64e6f3eacfc4aad3bb6b3d54309722682&quot;&gt;renamed&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ButtonComponents&lt;&#x2F;code&gt; is now &lt;code&gt;ButtonBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Camera2dComponents&lt;&#x2F;code&gt; is now &lt;code&gt;Camera2dBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Camera3dComponents&lt;&#x2F;code&gt; is now &lt;code&gt;Camera3dBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ImageComponents&lt;&#x2F;code&gt; is now &lt;code&gt;ImageBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;LightComponents&lt;&#x2F;code&gt; is now &lt;code&gt;LightBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;MeshComponents&lt;&#x2F;code&gt; is now &lt;code&gt;MeshBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;NodeComponents&lt;&#x2F;code&gt; is now &lt;code&gt;NodeBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;PbrComponents&lt;&#x2F;code&gt; is now &lt;code&gt;PbrBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;SpriteComponents&lt;&#x2F;code&gt; is now &lt;code&gt;SpriteBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;SpriteSheetComponents&lt;&#x2F;code&gt; is now &lt;code&gt;SpriteSheetBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;TextComponents&lt;&#x2F;code&gt; is now &lt;code&gt;TextBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;UiCameraComponents&lt;&#x2F;code&gt; is now &lt;code&gt;CameraUiBundle&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;commands-syntax-change&quot;&gt;Commands syntax change&lt;&#x2F;h2&gt;
&lt;p&gt;If you see a cryptic error such as this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;error[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;E0599&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;]: no method named `system` found &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;item&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;&amp;#39;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(bevy::prelude::Commands, bevy::prelude::ResMut&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;&amp;#39;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, bevy::prelude::Assets&amp;lt;bevy::prelude::Mesh&amp;gt;&amp;gt;, bevy::prelude::ResMut&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, bevy::prelude::Assets&amp;lt;bevy::prelude::StandardMaterial&amp;gt;&amp;gt;) {world::setup_world}` &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; the current scope
  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;-&amp;gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;main.rs:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;15&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;41
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;15 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;|         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;add_startup_system&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(setup_world.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;system&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;())
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;|                                         ^^^^^^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; method not found &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;&amp;#39;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(bevy::prelude::Commands, bevy::prelude::ResMut&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;&amp;#39;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, bevy::prelude::Assets&amp;lt;bevy::prelude::Mesh&amp;gt;&amp;gt;, bevy::prelude::ResMut&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;&amp;#39;s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;, bevy::prelude::Assets&amp;lt;bevy::prelude::StandardMaterial&amp;gt;&amp;gt;) {world::setup_world}`
   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;|
   =&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; note: `setup_world` is a function, perhaps you wish to call it
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is probably because&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; commmands: Commands
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;should now be&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;commands: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; commands
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;vector-matrix-and-quaternion-changes&quot;&gt;Vector, Matrix, and Quaternion changes&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;components-are-now-fields&quot;&gt;Components are now fields&lt;&#x2F;h3&gt;
&lt;p&gt;If you were trying to access a specific component of one of these objects, perhaps the x-component with&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;Vec3::unit_x().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You simply need to remove the parenthesis because &lt;code&gt;.x()&lt;&#x2F;code&gt; is no longer a method:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;Vec3::unit_x().x
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The same goes for axes: &lt;code&gt;x_axis()&lt;&#x2F;code&gt; becomes &lt;code&gt;x_axis&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bitshifter&#x2F;glam-rs&#x2F;blob&#x2F;master&#x2F;CHANGELOG.md#changed-3&quot;&gt;Changelog&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;element-accessors-deprecated&quot;&gt;Element accessors deprecated&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;.x_mut()&lt;&#x2F;code&gt; and &lt;code&gt;.set_x()&lt;&#x2F;code&gt; are now accessed with &lt;code&gt;x()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bitshifter&#x2F;glam-rs&#x2F;blob&#x2F;master&#x2F;CHANGELOG.md#changed-2&quot;&gt;Changelog&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;removed-all&quot;&gt;Removed &lt;code&gt;.all()&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;my_vec.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;is_nan&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now suffices in the place of&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;my_vec.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;is_nan&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;all&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bitshifter&#x2F;glam-rs&#x2F;blob&#x2F;master&#x2F;CHANGELOG.md#changed-1&quot;&gt;Changelog&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reflection&quot;&gt;Reflection&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;Property&lt;&#x2F;code&gt; has been removed in favor of &lt;code&gt;Reflect&lt;&#x2F;code&gt;, if you see the error &lt;code&gt;error: cannot find derive macro Property in this scope&lt;&#x2F;code&gt;, then replace&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(Property)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Example&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;with&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(Reflect)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Example&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Bevy repo has &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bevyengine&#x2F;bevy&#x2F;tree&#x2F;master&#x2F;examples&#x2F;reflection&quot;&gt;reflection examples&lt;&#x2F;a&gt; that can be compared against the usage of &lt;code&gt;Property&lt;&#x2F;code&gt; in the 0.3 &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bevyengine&#x2F;bevy&#x2F;blob&#x2F;9afe196f1690a6a6e47bf67ac740b4edeffd97bd&#x2F;examples&#x2F;scene&#x2F;properties.rs&quot;&gt;scene example&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;news&#x2F;bevy-0-4&#x2F;#reflection&quot;&gt;Relevant release notes&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;portability&quot;&gt;Portability&lt;&#x2F;h2&gt;
&lt;p&gt;As the release post &lt;a href=&quot;https:&#x2F;&#x2F;bevyengine.org&#x2F;news&#x2F;bevy-0-4&#x2F;#cross-platform-main-function&quot;&gt;states&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;…
some platforms (currently Android and iOS) require additional boilerplate
…
&lt;strong&gt;Bevy 0.4&lt;&#x2F;strong&gt; adds a new &lt;code&gt;#[bevy_main]&lt;&#x2F;code&gt; proc-macro, which inserts the relevant boilerplate for you.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So if you want Android&#x2F;iOS support, just add the macro atop of your &lt;code&gt;main&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-Rust&quot; data-lang=&quot;Rust&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;#[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;bevy_main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;() {
    App::build().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;();
}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;additional-issues&quot;&gt;Additional issues&lt;&#x2F;h2&gt;
&lt;p&gt;If you’d like something added to this post to help others, just contact me (perhaps by &lt;a href=&quot;&#x2F;#contact&quot;&gt;email&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Linux and Vim with a 60% Keyboard</title>
		<published>2020-12-12T00:00:00+00:00</published>
		<updated>2020-12-12T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/linux-vim-60-keyboard/" type="text/html"/>
		<id>https://sburris.xyz/posts/linux-vim-60-keyboard/</id>
		<content type="html">&lt;h2 id=&quot;60-keyboards&quot;&gt;60% Keyboards&lt;&#x2F;h2&gt;
&lt;p&gt;If you’ve never seen one before, a 60% keyboard looks like this:
&lt;img src=&quot;&#x2F;img&#x2F;keyboard.png&quot; alt=&quot;Keyboard&quot; &#x2F;&gt;
This is the keyboard (DZ60) I built many months ago as my old one, an exposed circuit board susceptible to air drafts, stopped working.&lt;&#x2F;p&gt;
&lt;p&gt;Having unlabelled keycaps and using a tiling window manager (&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;baskerville&#x2F;bspwm&quot;&gt;bspwm&lt;&#x2F;a&gt;) greatly increases the security of my workstation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Few people know how to use a tiling window manager&lt;&#x2F;li&gt;
&lt;li&gt;I configure things in weird ways that will probably confuse everyone else&lt;&#x2F;li&gt;
&lt;li&gt;If you aren’t beyond proficient at typing, the keyboard is frustrating&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;linux&quot;&gt;Linux&lt;&#x2F;h2&gt;
&lt;p&gt;I was expecting to have to do some adjusting but didn’t need to.
Nothing actually changed here, except that now that key is also &lt;code&gt;ESC&lt;&#x2F;code&gt; and grave.
The layout looks this:
&lt;img src=&quot;&#x2F;img&#x2F;keyboard_layout.png&quot; alt=&quot;Keyboard Layout&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I also used the arrow keys to navigate shell history.
The layout I use has a “layer switch” key on the bottom row where the “context” key usually is.
If I want to type arrow keys, I hold that key and use &lt;code&gt;h,j,k,l&lt;&#x2F;code&gt; as if I were in Vim.
The same key turns the &lt;code&gt;ESC&lt;&#x2F;code&gt; key into grave.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vim&quot;&gt;Vim&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;ESC&lt;&#x2F;code&gt; is used frequently for switching modes in Vim.
Using a 60% keyboard is actually better for Vim in my opinion, because &lt;code&gt;ESC&lt;&#x2F;code&gt; is closer, being to the immediate right of 1.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I don’t have any problems with Vim or Linux using a 60% keyboard.
The only thing missing is a numpad, which I replace with the buttons on the side of a Logitech G600 using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;libratbag&#x2F;piper&#x2F;&quot;&gt;Piper&lt;&#x2F;a&gt; to configure its bindings.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Taking Notes and Writing Documents with mdBook</title>
		<published>2020-12-03T00:00:00+00:00</published>
		<updated>2021-07-18T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/mdbook-notes/" type="text/html"/>
		<id>https://sburris.xyz/posts/mdbook-notes/</id>
		<content type="html">&lt;h2 id=&quot;mdbook&quot;&gt;mdBook&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;mdBook&quot;&gt;mdBook&lt;&#x2F;a&gt; is an easy way to create modern online books using Markdown.
The program itself is written in Rust, and is used for the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;&quot;&gt;Rust Book&lt;&#x2F;a&gt; and many project’s &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt;.
It has a really nice search feature, a minimal interface, and is easy to use.
For courses that are a part of the Quaternion Institute, I recently decided to use mdBook.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;usage&quot;&gt;Usage&lt;&#x2F;h3&gt;
&lt;p&gt;If you don’t have Rust installed, get it from &lt;a href=&quot;https:&#x2F;&#x2F;rustup.rs&#x2F;&quot;&gt;Rustup&lt;&#x2F;a&gt;, then run &lt;code&gt;cargo install mdbook&lt;&#x2F;code&gt;.
Create a new book with &lt;code&gt;mdbook init book_name&lt;&#x2F;code&gt;, then edit &lt;code&gt;src&#x2F;SUMMARY.md&lt;&#x2F;code&gt; and describe your books structure in an outline as shown in the &lt;a href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;mdBook&#x2F;format&#x2F;summary.html&quot;&gt;user guide&lt;&#x2F;a&gt;.
Run &lt;code&gt;mdbook serve&lt;&#x2F;code&gt; or &lt;code&gt;mdbook build&lt;&#x2F;code&gt; and it will create all of the files that don’t exist that are linked to in the directory, and then you can start writing.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;notes&quot;&gt;Notes&lt;&#x2F;h3&gt;
&lt;p&gt;I was using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vimwiki&#x2F;vimwiki&quot;&gt;Vimwiki&lt;&#x2F;a&gt; for notes, but I have decided to switch (no effort required, really) to mdBook.
Many people prefer Vimwiki’s Markdown syntax (it’s objectively better) instead of its own Vimwiki syntax, but Vimwiki can only generate webpages from its own syntax.
mdBook is a good solution for this.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;preprocessors&quot;&gt;Preprocessors&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;mdbook-katex&quot;&gt;mdbook-katex&lt;&#x2F;h4&gt;
&lt;p&gt;mdBook supports &lt;a href=&quot;https:&#x2F;&#x2F;www.mathjax.org&#x2F;&quot;&gt;MathJax&lt;&#x2F;a&gt; out of the box, which is inferior to &lt;a href=&quot;https:&#x2F;&#x2F;katex.org&#x2F;&quot;&gt;KaTeX&lt;&#x2F;a&gt; for rendering math on webpages.
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lzanini&#x2F;mdbook-katex&quot;&gt;mdbook-katex&lt;&#x2F;a&gt; is a preprocessor that uses KaTeX to render all of your math to SVG at build-time.
If you want to have math in your HTML-based notes, I assure you this is the best way.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;mdbook-linkcheck&quot;&gt;mdbook-linkcheck&lt;&#x2F;h4&gt;
&lt;p&gt;I contribute to documentation on GitHub a lot because broken links bother me way more than they should.
Save your sanity (or atleast mine): &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Michael-F-Bryan&#x2F;mdbook-linkcheck&quot;&gt;mdbook-linkcheck&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;others&quot;&gt;Others&lt;&#x2F;h4&gt;
&lt;p&gt;There is an open GitHub &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;mdBook&#x2F;issues&#x2F;1278&quot;&gt;issue&lt;&#x2F;a&gt; to add a list of preprocessors to the user guide.
Until then, there is a list of them in the issue to which I have added many.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;my-setup&quot;&gt;My Setup&lt;&#x2F;h3&gt;
&lt;p&gt;Between the two, I have a nice way to write Markdown: &lt;a href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;&quot;&gt;Neovim&lt;&#x2F;a&gt; + &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;junegunn&#x2F;goyo.vim&quot;&gt;Goyo.vim&lt;&#x2F;a&gt; + Vimwiki, and a nice way to read it: Firefox + mdBook.
I use Goyo.vim to hide Neovim’s interface to eliminate distractions, and Vimwiki is pretty much installed only for the link navigation feature now.
Hover over a Markdown link such as &lt;code&gt;[link](file2.md)&lt;&#x2F;code&gt; and press enter, and Vimwiki switches you over to &lt;code&gt;file2.md&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;If you want searchable Markdown-formatted notes, try mdBook.
It’s simple and does everything I expect it to.
There is a &lt;code&gt;multilingual&lt;&#x2F;code&gt; option in my &lt;code&gt;book.toml&lt;&#x2F;code&gt; which makes me hope that support for multilingual books will be added soon.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>The Best Way to Compress PNG Images on Linux</title>
		<published>2020-11-13T00:00:00+00:00</published>
		<updated>2023-03-29T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/best-png-compression/" type="text/html"/>
		<id>https://sburris.xyz/posts/best-png-compression/</id>
		<content type="html">&lt;h2 id=&quot;image-compression&quot;&gt;Image Compression&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;&#x2F;strong&gt; I no longer stand by this methodology and the results obtained. If I were to redo this, I would use &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sharkdp&#x2F;hyperfine&quot;&gt;hyperfine&lt;&#x2F;a&gt; and include other compressors.&lt;&#x2F;p&gt;
&lt;p&gt;Image compression is an easy way to save storage space and bandwidth.
It makes webpages much smaller and faster, and is so easy there really isn’t a reason not to compress.
On this blog, I’ve been compressing my images with &lt;code&gt;optipng&lt;&#x2F;code&gt;, I haven’t been keeping track but I typically see a size reduction of about 20-25%.
This can add up fast for users with slow connections, or users using mobile data.
At the &lt;a href=&quot;https:&#x2F;&#x2F;quaternion.institute&#x2F;&quot;&gt;Quaternion Institute&lt;&#x2F;a&gt;, we have an &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;quaternion-inst&#x2F;branding&#x2F;-&#x2F;blob&#x2F;master&#x2F;Makefile&quot;&gt;automated build system&lt;&#x2F;a&gt; to take branding-related vector images, render them into PNGs for different purposes (such as social media avatars, favicons, general-purpose logos, etc), then compress them with &lt;code&gt;optipng&lt;&#x2F;code&gt; that works really nicely.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-small-question&quot;&gt;The Small Question&lt;&#x2F;h3&gt;
&lt;p&gt;Lately though, I’ve been wondering if &lt;code&gt;optipng&lt;&#x2F;code&gt; is really the best option.
I decided to do some yak-shaving and figure it out.
Searching through the &lt;a href=&quot;https:&#x2F;&#x2F;voidlinux.org&#x2F;&quot;&gt;Void Linux&lt;&#x2F;a&gt; software repositories, I found five pieces of software that I want to compare and chart the performance of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;optipng.sourceforge.net&#x2F;&quot;&gt;OptiPNG 0.7.7&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lib.rs&#x2F;crates&#x2F;oxipng&quot;&gt;Oxipng 3.0.1&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pmt.sourceforge.io&#x2F;pngcrush&#x2F;&quot;&gt;Pngcrush 1.8.13&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pngquant.org&#x2F;&quot;&gt;pngquant 2.13.0&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I’m going to only test lossless compression here.
Testing lossy compression would create many more variables and would produce different-looking images that could only be compared subjectively.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;notes&quot;&gt;Notes&lt;&#x2F;h4&gt;
&lt;p&gt;I did not test &lt;a href=&quot;http:&#x2F;&#x2F;www.advancemame.it&#x2F;comp-readme&quot;&gt;AdvanceCOMP 2.1&lt;&#x2F;a&gt; because it has several algorithms.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;criteria-and-methodology&quot;&gt;Criteria and Methodology&lt;&#x2F;h3&gt;
&lt;p&gt;I am comparing output size and compression time.
The whole reason I’m compressing images is to make them smaller, but if it takes a while then it might not actually be worth it.
I will create two graphs: one with the output size of each program, and another with the average time of 6 compression runs on my system with few programs running to eliminate fluctuation.
I will use &lt;code&gt;time $program&lt;&#x2F;code&gt; to get the run time, and &lt;code&gt;du -b output.png&lt;&#x2F;code&gt; to get the file size after compression, recording each in a CSV of format &lt;code&gt;software,image,bytes,time&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;system-specs&quot;&gt;System Specs&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Void Linux&lt;&#x2F;li&gt;
&lt;li&gt;AMD FX 6300 CPU&lt;&#x2F;li&gt;
&lt;li&gt;8GB RAM&lt;&#x2F;li&gt;
&lt;li&gt;AMD R9 280 GPU&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;test-images&quot;&gt;Test Images&lt;&#x2F;h4&gt;
&lt;p&gt;I mostly want to compress screenshots, so I will be testing using the following screenshots captured with &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;flameshot-org&#x2F;flameshot&quot;&gt;flameshot&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;img&#x2F;compression_desktop.png&quot;&gt;My desktop&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;img&#x2F;compression_wikipedia.png&quot;&gt;Image compression on Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;img&#x2F;compression_quaternion.png&quot;&gt;Part of quaternion.institute&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;hypothesis&quot;&gt;Hypothesis&lt;&#x2F;h3&gt;
&lt;p&gt;I predict either OptiPNG or Oxipng will do the best.
OptiPNG will likely do well because of its popularity, and Oxipng will likely do well because software written in Rust has a history of performance feats over ubiquitous software.&lt;&#x2F;p&gt;
&lt;p&gt;While on the topic of image efficiency, I’d like to mention &lt;a href=&quot;https:&#x2F;&#x2F;flif.info&#x2F;&quot;&gt;FLIF&lt;&#x2F;a&gt;, an interesting image format that beats most others but is not supported in many places.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;results&quot;&gt;Results&lt;&#x2F;h3&gt;
&lt;p&gt;I’ve collected the data and made some nice graphs using &lt;a href=&quot;https:&#x2F;&#x2F;plotly.com&#x2F;python&#x2F;plotly-express&#x2F;&quot;&gt;Plotly Express&lt;&#x2F;a&gt;.
Click either graph to see an interactive HTML version with the full data.
The data, images, and graph-generating scripts are on my &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;sburris&#x2F;png-compressor-benchmarks&quot;&gt;Gitlab&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;output-file-size&quot;&gt;Output File Size&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;files&#x2F;png_size.html&quot;&gt;&lt;img src=&quot;&#x2F;img&#x2F;png_size.svg&quot; alt=&quot;Compressor size graph&quot; &#x2F;&gt;&lt;&#x2F;a&gt;
We want small file sizes, lower is better.
In this test, optipng did better than oxipng by a very slight margin.
The two do much better than the others, so execution time will be the real tie-breaker.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;execution-time&quot;&gt;Execution Time&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;files&#x2F;png_time.html&quot;&gt;&lt;img src=&quot;&#x2F;img&#x2F;png_time.svg&quot; alt=&quot;Compressor time graph&quot; &#x2F;&gt;&lt;&#x2F;a&gt;
Pngquant was the fastest, followed by oxipng.
Optipng and pngcrush fall behind by a decent bit.
Oxipng is written in Rust, which is famous at this point for enabling developers to create efficient multithreading, I’m not that surprised that it did so well.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;Overall, I’m going to say Oxipng is the winner.
Optipng produced slightly smaller files, but was quite a bit slower.
If you really need to spare every byte possible, use Optipng, otherwise use Oxipng.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;further-testing&quot;&gt;Further Testing&lt;&#x2F;h4&gt;
&lt;p&gt;One issue I became aware of is that Flameshot (which I took the screenshots with) appears to be a frontend for other &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;flameshot-org&#x2F;flameshot&#x2F;issues&#x2F;506&quot;&gt;tools on the system&lt;&#x2F;a&gt;.
On my system, I believe it may have used &lt;code&gt;scrot&lt;&#x2F;code&gt;.
Using images created in a different way may provide more accurate testing.
For example, Kodak actually has a &lt;a href=&quot;http:&#x2F;&#x2F;r0k.us&#x2F;graphics&#x2F;kodak&#x2F;&quot;&gt;standard set of images&lt;&#x2F;a&gt; used for testing compression.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Customizing Django-allauth Templates the Easy Way</title>
		<published>2020-11-06T00:00:00+00:00</published>
		<updated>2021-07-18T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/allauth-custom-templates/" type="text/html"/>
		<id>https://sburris.xyz/posts/allauth-custom-templates/</id>
		<content type="html">&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;&#x2F;h2&gt;
&lt;p&gt;So you’ve installed &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pennersr&#x2F;django-allauth&quot;&gt;django-allauth&lt;&#x2F;a&gt; for the &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;&quot;&gt;Python&lt;&#x2F;a&gt;-based web framework &lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt; successfully and now all of your account-related pages are painful to look at.
Sure, you could customize each of allauth’s provided templates yourself, but I’ll show you an easier way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;overriding-the-base-template&quot;&gt;Overriding the Base Template&lt;&#x2F;h2&gt;
&lt;p&gt;Starting off, the sign-in page looks something like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;allauth_template_default.png&quot; alt=&quot;Allauth default template&quot; title=&quot;Allauth default template&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you open up the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pennersr&#x2F;django-allauth&#x2F;blob&#x2F;master&#x2F;allauth&#x2F;templates&#x2F;account&#x2F;login.html&quot;&gt;HTML file for this template&lt;&#x2F;a&gt; then you’ll notice that it extends &lt;code&gt;account&#x2F;base.html&lt;&#x2F;code&gt;.
This &lt;code&gt;base.html&lt;&#x2F;code&gt; really only does a few things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Sets the page title to what the child template says to&lt;&#x2F;li&gt;
&lt;li&gt;Displays messages if there are any&lt;&#x2F;li&gt;
&lt;li&gt;Asks the user or sign in or sign up if they are not logged in, or gives the option to sign out or change email if they are&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Your project’s base template probably already does all of these things like mine.
Therefore, we can get allauth to user our base templates instead of its own.
All of its templates are looking for &lt;code&gt;account&#x2F;base.html&lt;&#x2F;code&gt;?
Let’s give it one:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;First, create a new &lt;code&gt;accounts&lt;&#x2F;code&gt; directory inside your templates directory and go into it:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;mkdir templates&#x2F;accounts
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt; templates&#x2F;accounts
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Symlink your base template to &lt;code&gt;accounts&#x2F;base.html&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;ln -s ..&#x2F;main&#x2F;_base.html base.html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Check the result and see what still needs to be fixed&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If this didn’t work, make sure your app is higher on the list than &lt;code&gt;allauth&lt;&#x2F;code&gt; and its components in &lt;code&gt;INSTALLED_APPS&lt;&#x2F;code&gt; inside &lt;code&gt;settings.py&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cleaning-up&quot;&gt;Cleaning Up&lt;&#x2F;h2&gt;
&lt;p&gt;After overriding &lt;code&gt;base.html&lt;&#x2F;code&gt;, my work-in-progress site’s authentication-related pages looked like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;allauth_template_custom.png&quot; alt=&quot;Allauth custom template&quot; title=&quot;Allauth custom template&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The site may not be pretty yet, but at least it’s consistent now.
However, there a few things that still need attention.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;page-titles&quot;&gt;Page Titles&lt;&#x2F;h3&gt;
&lt;p&gt;Allauth’s page titles are set by children templates in a block called &lt;code&gt;head_title&lt;&#x2F;code&gt;, so if you had any other name you will see something like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;allauth_template_pagetitle.png&quot; alt=&quot;Allauth page titles&quot; title=&quot;Allauth page titles&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The fix is easy, you will just need to change whatever you were using (&lt;code&gt;title&lt;&#x2F;code&gt;, perhaps) to &lt;code&gt;head_title&lt;&#x2F;code&gt; in all of the template you have created.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;layout-differences&quot;&gt;Layout Differences&lt;&#x2F;h3&gt;
&lt;p&gt;Whereas I use &lt;a href=&quot;https:&#x2F;&#x2F;www.w3schools.com&#x2F;html&#x2F;html5_semantic_elements.asp&quot;&gt;semantic HTML&lt;&#x2F;a&gt; in my pages, allauth does not.
For this project, I centered my main content.
Because I did not put my &lt;code&gt;&amp;lt;main&amp;gt;&lt;&#x2F;code&gt; tags in my &lt;code&gt;base.html&lt;&#x2F;code&gt;, but rather each child template, allauth pages are not centered.
This is also an easy fix, any container tags that effect layout need to surround &lt;code&gt;{% blockcontent %}{% endblock %}&lt;&#x2F;code&gt; in &lt;code&gt;base.html&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Instead of copying all of allauth’s templates then editing every one of them as I’ve seen many tutorials suggest, you can make a single symlink and then make a few edits to clean things up a bit.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>[Part 3] Learning Russian: Another Change of Plans</title>
		<published>2020-10-28T00:00:00+00:00</published>
		<updated>2021-07-18T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/russian-part-three/" type="text/html"/>
		<id>https://sburris.xyz/posts/russian-part-three/</id>
		<content type="html">&lt;h2 id=&quot;the-russian-lessons-website&quot;&gt;The Russian Lessons Website&lt;&#x2F;h2&gt;
&lt;p&gt;I haven’t completed most of &lt;a href=&quot;https:&#x2F;&#x2F;sburris.xyz&#x2F;posts&#x2F;russian-part-three&#x2F;russianlessons.net&quot;&gt;russianlessons.net&lt;&#x2F;a&gt;’s lessons but the beginning few ignore grammar quite a bit, which I’ve found to actually be pretty disorienting.
It has been confusing when many roots of words are familiar but it isn’t clear why they are different and when they change.
The site recommends Nicholas Brown’s “The New Penguin Russian Course”, so I purchased a used copy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-new-penguin-russian-course&quot;&gt;The New Penguin Russian Course&lt;&#x2F;h2&gt;
&lt;p&gt;The first 2-3 chapters were mostly review, though I did learn a few things such as the pronounciation of the hard and soft marks.
I have found the book to be well written. 
Its chapters are brief and it does a good job of maintaining sight of the big picture while including details usually ommitted elsewhere.
The author gives good advice as to where the reader should spend their effort.
There are tips on places to cut corners that Russian speakers likely won’t notice, if you are in a hurry.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;grammatical-gender&quot;&gt;Grammatical Gender&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve learned to use personal pronouns such as он (he), она (she), оно (“it”, for nouns).
I’ve begun to understand how to tell what grammatical gender (masculine, feminine, neuter) nouns have.
Conjugation of verbs in the present tense reminds me of Spanish.
Like Spanish, there is a familiar and formal pronoun for “you”.
The words for “we”, “you (fam.)”, and “you (formal)” have some resemblance to Esperanto.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;questions&quot;&gt;Questions&lt;&#x2F;h2&gt;
&lt;p&gt;I can ask questions about where things are, what something is, and whether someone speaks Russian.
At this point, I can only really answer yes or no questions.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>How to Enable MPD Track Ratings on Void Linux</title>
		<published>2020-10-23T00:00:00+00:00</published>
		<updated>2021-07-18T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/mpd-track-ratings/" type="text/html"/>
		<id>https://sburris.xyz/posts/mpd-track-ratings/</id>
		<content type="html">&lt;h2 id=&quot;track-ratings&quot;&gt;Track Ratings&lt;&#x2F;h2&gt;
&lt;p&gt;Some &lt;a href=&quot;https:&#x2F;&#x2F;www.musicpd.org&#x2F;&quot;&gt;MPD&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.musicpd.org&#x2F;clients&#x2F;&quot;&gt;clients&lt;&#x2F;a&gt; such as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cdrummond&#x2F;cantata&quot;&gt;Cantata&lt;&#x2F;a&gt; support giving tracks ratings as seen below.
If you haven’t set up MPD yet, have a look at my other post &lt;a href=&quot;&#x2F;posts&#x2F;mpd-void-linux&quot;&gt;“How to Set up MPD on Void Linux”&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;cantata_ratings.png&quot; alt=&quot;Ratings in Cantata&quot; title=&quot;Track Ratings in Cantata&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;enabling-ratings-in-cantata&quot;&gt;Enabling Ratings in Cantata&lt;&#x2F;h3&gt;
&lt;p&gt;In Cantata, track ratings are enabled by going to the menu on the right or &lt;code&gt;Edit&lt;&#x2F;code&gt; in the toolbar, then &lt;code&gt;Preferences &amp;gt; Interface &amp;gt; Toolbar &amp;gt; Show Track Ratings&lt;&#x2F;code&gt;.
Upon enabling them, I got an error message saying that this version of MPD “does not support stickers”.
Here is how I fixed it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-and-installing-from-source&quot;&gt;Building and Installing from Source&lt;&#x2F;h2&gt;
&lt;p&gt;Void Linux’s MPD package does not support stickers because not everyone wants them, so making everyone install the &lt;a href=&quot;https:&#x2F;&#x2F;sqlite.org&#x2F;index.html&quot;&gt;SQLite&lt;&#x2F;a&gt; database on their system is unnecessary.
If we want track ratings, we need to enable SQLite support for MPD and then recompile it from source ourselves.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h3&gt;
&lt;p&gt;Void Linux uses &lt;code&gt;xbps-src&lt;&#x2F;code&gt; to build packages.
There is a &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;void-linux&#x2F;void-packages&#x2F;#quick-start&quot;&gt;quickstart&lt;&#x2F;a&gt; for setting up the build environment on Github.
As it says, you will need to clone the &lt;code&gt;void-packages&lt;&#x2F;code&gt; repository and then &lt;code&gt;cd&lt;&#x2F;code&gt; into it and run &lt;code&gt;.&#x2F;xbps-src binary-bootstrap&lt;&#x2F;code&gt;, which might take a few minutes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;templates&quot;&gt;Templates&lt;&#x2F;h3&gt;
&lt;p&gt;Once that finishes, the &lt;code&gt;srcpkgs&#x2F;&lt;&#x2F;code&gt; directory has the tools and recipes to build every piece of software available through &lt;code&gt;xbps&lt;&#x2F;code&gt; (plus a few more even).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;edit-the-template&quot;&gt;Edit the Template&lt;&#x2F;h4&gt;
&lt;p&gt;We are messing with the MPD package, so open &lt;code&gt;void-packages&#x2F;srcpkgs&#x2F;mpd&#x2F;template&lt;&#x2F;code&gt; in your text editor.
Now there are three lines we need to change:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;-Dsqlite=enabled&lt;&#x2F;code&gt; to the &lt;code&gt;configure_args&lt;&#x2F;code&gt; setting as follows:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;configure_args&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;-Dopus=enabled -Dmikmod=enabled -Dneighbor=true -Dsqlite=enabled
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This tells the build system that we want SQLite support.
The &lt;code&gt;-Dsqlite&lt;&#x2F;code&gt; flag is documented &lt;a href=&quot;https:&#x2F;&#x2F;www.musicpd.org&#x2F;doc&#x2F;html&#x2F;user.html?highlight=audio_buffer_size#the-sticker-database&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Add &lt;code&gt;sqlite-devel&lt;&#x2F;code&gt; to the &lt;code&gt;makedepends&lt;&#x2F;code&gt; option:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;makedepends&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;avahi-glib-libs-devel boost-devel faad2-devel ffmpeg-devel sqlite-devel
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Add &lt;code&gt;sqlite&lt;&#x2F;code&gt; to &lt;code&gt;depends&lt;&#x2F;code&gt;:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;depends&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;libcap-progs sqlite&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Having SQLite support won’t do much good without having SQLite installed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rebuilding-mpd&quot;&gt;Rebuilding MPD&lt;&#x2F;h3&gt;
&lt;p&gt;Now it’s time to actually compile MPD.
From the &lt;code&gt;void-packages&lt;&#x2F;code&gt; directory, run &lt;code&gt;.&#x2F;xbps-src pkg mpd&lt;&#x2F;code&gt;.
This may take a few minutes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;make-the-switch&quot;&gt;Make the Switch&lt;&#x2F;h3&gt;
&lt;p&gt;To switch to our version with SQLite support, uninstall the previous package with &lt;code&gt;sudo xbps-remove mpd&lt;&#x2F;code&gt;.
Next, install the version we just compiled with &lt;code&gt;sudo xbps-install --repository hostdir&#x2F;binpkgs mpd&lt;&#x2F;code&gt;.
The old version is still probably running on your system, so you may need to &lt;code&gt;pkill mpd&lt;&#x2F;code&gt; so that the new version starts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;As you have seen, Void Linux makes it easy to reconfigure packages and build them yourself.
If you ever run into a similar problem with a package not supporting an option you want, try a similar approach.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>The Gemini Protocol</title>
		<published>2020-10-15T00:00:00+00:00</published>
		<updated>2020-10-23T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/gemini/" type="text/html"/>
		<id>https://sburris.xyz/posts/gemini/</id>
		<content type="html">&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gemini.circumlunar.space&#x2F;&quot;&gt;Project Gemini&lt;&#x2F;a&gt; is a new internet protocol that is working to make the internet more private, efficient, and pleasant to use.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-internet-on-a-diet&quot;&gt;The Internet on a Diet&lt;&#x2F;h2&gt;
&lt;p&gt;Something I’ve come to lament about the internet is how little of it is actual content.
So much of every website is user-tracking JavaScript slowing everything down, popup messages whining about ad-blockers, filler content, and inaccessibly designed UI.
&lt;a href=&quot;https:&#x2F;&#x2F;idlewords.com&#x2F;talks&#x2F;website_obesity.htm&quot;&gt;The Website Obesity Crisis&lt;&#x2F;a&gt; is a real problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try It&lt;&#x2F;h2&gt;
&lt;p&gt;I will continue to tell you about Gemini, but I would also like to show it to you.
The first thing to know about accessing Gemini sites is that you can’t without either a Gemini &lt;a href=&quot;https:&#x2F;&#x2F;gemini.circumlunar.space&#x2F;clients.html&quot;&gt;client&lt;&#x2F;a&gt; or a Gemini-to-web proxy.
For clients, I like &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;MasterQ32&#x2F;kristall&quot;&gt;Kristall&lt;&#x2F;a&gt; but if you just want to have a quick look then go to the &lt;a href=&quot;https:&#x2F;&#x2F;proxy.vulpes.one&quot;&gt;proxy site&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pages&quot;&gt;Pages&lt;&#x2F;h3&gt;
&lt;p&gt;Now you can do some exploring and check out some pages (all proxy links):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;proxy.vulpes.one&#x2F;gemini&#x2F;gemini.circumlunar.space&#x2F;&quot;&gt;Main Gemini Site&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;proxy.vulpes.one&#x2F;gemini&#x2F;drewdevault.com&#x2F;&quot;&gt;Drew Devault’s Blog and Tools&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;proxy.vulpes.one&#x2F;gemini&#x2F;gemini.circumlunar.space&#x2F;capcom&#x2F;&quot;&gt;The CAPCOM Aggregator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;details&quot;&gt;Details&lt;&#x2F;h2&gt;
&lt;p&gt;Whereas the internet as we know it has HTML, CSS, and JavaScript, Gemini has a markup language resembling trimmed-down &lt;a href=&quot;https:&#x2F;&#x2F;learnxinyminutes.com&#x2F;docs&#x2F;markdown&#x2F;&quot;&gt;markdown&lt;&#x2F;a&gt; that is called gemtext.
This markup format is much more utilitarian and trims pages down to be only content.
In gemtext there is no JavaScript bloat, terrible layouts, or ugly colorschemes (unless you set one for yourself, as the end user).
From the &lt;a href=&quot;https:&#x2F;&#x2F;proxy.vulpes.one&#x2F;gemini&#x2F;gemini.circumlunar.space&#x2F;docs&#x2F;cheatsheet.gmi&quot;&gt;cheatsheet&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-md&quot; data-lang=&quot;md&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;...

Long lines get wrapped by the client to fit the screen
Short lines &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fdf4c1aa;&quot;&gt;*don&amp;#39;t*&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; get joined together
Write paragraphs as single long lines
Blank lines are rendered verbatim

You get three levels of heading:

# Heading

## Sub-heading

### Sub-subheading

You get one kind of list and you can&amp;#39;t nest them:

* Mercury
* Gemini
* Apollo

...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;my-plans&quot;&gt;My Plans&lt;&#x2F;h2&gt;
&lt;p&gt;I always try to keep my websites small in size and simple to navigate so it’s no surprise that I like Gemini.
Technology needs more minimalism as I will write about more in the future, and this protocol is a step in the right direction.
In an attempt to embrace the protocol, I have a few projects planned.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;conversion-of-markdown-to-gemtext&quot;&gt;Conversion of Markdown to Gemtext&lt;&#x2F;h3&gt;
&lt;p&gt;Pandoc is software which can convert most things to most other things as far as documents go.
You can use it to convert markdown to HTML, reStructuredText to PowerPoint, among many other &lt;a href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;diagram.jpg&quot;&gt;possibilities&lt;&#x2F;a&gt;.
I’ve opened an &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jgm&#x2F;pandoc&#x2F;issues&#x2F;6747&quot;&gt;issue&lt;&#x2F;a&gt; on &lt;a href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;&quot;&gt;pandoc&lt;&#x2F;a&gt; to try to get support for conversion to gemtext.
Conversion to gemtext from formats which literature is already available in will open the floodgates to more content available via gemini.
If this feature request is rejected, I plan to attempt something similar myself.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;this-blog&quot;&gt;This Blog&lt;&#x2F;h3&gt;
&lt;p&gt;A personal reason I want this conversion capability is so that I can make this blog available through gemini without having to maintain two versions of every post or have protocol-exclusive content.
For static sites, &lt;a href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;&quot;&gt;Hugo&lt;&#x2F;a&gt; supports custom output formats but &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; does not.
Because of this, I may set up a Makefile to convert my articles in markdown to gemtext and then run a gemini server such as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mbrubeck&#x2F;agate&quot;&gt;agate&lt;&#x2F;a&gt; in the same directory.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Sort Tags by Number of Tagged Posts in Zola</title>
		<published>2020-10-08T00:00:00+00:00</published>
		<updated>2020-10-08T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/sort-tags-in-zola/" type="text/html"/>
		<id>https://sburris.xyz/posts/sort-tags-in-zola/</id>
		<content type="html">&lt;h2 id=&quot;desired-result&quot;&gt;Desired Result&lt;&#x2F;h2&gt;
&lt;p&gt;I wanted the tags on this site (which was created with &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt;, an excellent static site generator written in Rust) to be sorted by number of tagged articles, not alphabetically.
The result can be seen on the &lt;a href=&quot;&#x2F;tags&quot;&gt;&#x2F;tags&lt;&#x2F;a&gt; page, and looks like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;tags.png&quot; alt=&quot;Sorted Tag List&quot; title=&quot;List of tags sorted by number of tagged articles&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;process&quot;&gt;Process&lt;&#x2F;h2&gt;
&lt;p&gt;To accomplish this, you will need to edit your site’s theme.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;templates&#x2F;tags&#x2F;list.html&lt;&#x2F;code&gt; or similar. There should be a directory for each type of &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;content&#x2F;taxonomies&#x2F;&quot;&gt;taxonomy&lt;&#x2F;a&gt; in &lt;code&gt;templates&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Inside &lt;code&gt;list.html&lt;&#x2F;code&gt;, find the &lt;a href=&quot;https:&#x2F;&#x2F;tera.netlify.app&#x2F;docs&#x2F;#for&quot;&gt;for loop&lt;&#x2F;a&gt; that iterates over &lt;code&gt;terms&lt;&#x2F;code&gt;. It should look something like this:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-html.j2&quot; data-lang=&quot;html.j2&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;{% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;terms &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;%}
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;gt;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;{% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;terms &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;%}
        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;href=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;{{ term.permalink | safe }}&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;{{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;term&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;}}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;{{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;term&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;pages &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;length &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;}}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;gt;
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;{% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;endfor &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;%}
    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;font-weight:bold;color:#8ec07c;&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span style=&quot;color:#83a598;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;{% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;endif &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;%}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Add a &lt;a href=&quot;https:&#x2F;&#x2F;tera.netlify.app&#x2F;docs&#x2F;#sort&quot;&gt;sort filter&lt;&#x2F;a&gt; with attribute set to &lt;code&gt;&amp;quot;pages&amp;quot;&lt;&#x2F;code&gt; (one of the &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;documentation&#x2F;templates&#x2F;taxonomies&#x2F;&quot;&gt;available fields&lt;&#x2F;a&gt; for each taxonomy) to the opening line of the for loop:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-html.j2&quot; data-lang=&quot;html.j2&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;{% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;terms &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;sort&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;attribute&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;pages&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;%}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now it should look like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;tags_backwards.png&quot; alt=&quot;Backwards Sorted Tag List&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The tags are sorted, but they are backwards.
As the documentation says, the &lt;code&gt;sort&lt;&#x2F;code&gt; filter always sorts items in ascending order.
Luckily, there is also the &lt;code&gt;reverse&lt;&#x2F;code&gt; filter.&lt;&#x2F;p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Change the opening line of the for loop to the following:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-html.j2&quot; data-lang=&quot;html.j2&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;{% &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;term &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;terms &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;sort&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;attribute&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;pages&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;) | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;reverse &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;%}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h3&gt;
&lt;p&gt;That’s it. Everything should work as intended now with the most commonly used tags at the top of the list.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>When to Use Flatpak</title>
		<published>2020-10-08T00:00:00+00:00</published>
		<updated>2020-10-08T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/when-to-use-flatpak/" type="text/html"/>
		<id>https://sburris.xyz/posts/when-to-use-flatpak/</id>
		<content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;One thing that might not be clear to many newer Linux users is when to use Flatpak as opposed to the built-in package manager.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;flatpak-vs-snapcraft&quot;&gt;Flatpak vs Snapcraft&lt;&#x2F;h3&gt;
&lt;p&gt;On the surface, &lt;a href=&quot;https:&#x2F;&#x2F;www.flatpak.org&#x2F;&quot;&gt;Flatpak&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;snapcraft.io&#x2F;&quot;&gt;Snapcraft&lt;&#x2F;a&gt; appear to serve a similar purpose, so what is the difference between them?
In short:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Snapcraft leaves software running in the background all the time, wasting resources (&lt;code&gt;snapd&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;The Snap Store backend is proprietary and controlled by Canonical (does not align with free software values)&lt;&#x2F;li&gt;
&lt;li&gt;Snap is being forced upon users by Canonical in new version of Ubuntu, and as a result is more popular and has more available software&lt;&#x2F;li&gt;
&lt;li&gt;Snap has much longer startup times in &lt;a href=&quot;https:&#x2F;&#x2F;www.ctrl.blog&#x2F;entry&#x2F;firefox-linux-flatpak-snap.html&quot;&gt;benchmarks&lt;&#x2F;a&gt;, though using either will negatively affect performance&lt;&#x2F;li&gt;
&lt;li&gt;Snap has poor theme integration (DPI&#x2F;fonts)&lt;&#x2F;li&gt;
&lt;li&gt;Snap relies on systemd, making it unusable on Void Linux, most Gentoo systems, many &lt;a href=&quot;https:&#x2F;&#x2F;sysdfree.wordpress.com&#x2F;2019&#x2F;10&#x2F;12&#x2F;135&#x2F;&quot;&gt;other Linux distros&lt;&#x2F;a&gt;, and the BSDs&lt;&#x2F;li&gt;
&lt;li&gt;Both have some &lt;a href=&quot;https:&#x2F;&#x2F;flatkill.org&#x2F;&quot;&gt;security issues&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Personally, I see almost no reason to use Snap over Flatpak, even if I could.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;flatpak-or-snapcraft-vs-appimage&quot;&gt;Flatpak or Snapcraft vs AppImage&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;appimage.org&#x2F;&quot;&gt;AppImage&lt;&#x2F;a&gt; is another option for installing software that I will not focus much on, the short version is that it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Does not take a performance hit nearly as large as Flatpak or Snap&lt;&#x2F;li&gt;
&lt;li&gt;Does not have a store or repositories and therefor cannot update unless update functionality is in the software itself&lt;&#x2F;li&gt;
&lt;li&gt;Without a store or repositories, it is possible to acquire malicious AppImages containing malware from sketchy websites&lt;&#x2F;li&gt;
&lt;li&gt;Does not require additional software to run&lt;&#x2F;li&gt;
&lt;li&gt;Does not have a middleman, because AppImages are easy to create, developers often create them themselves so there is no need to trust a third party&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;when-to-use-flatpaks&quot;&gt;When to Use Flatpaks&lt;&#x2F;h2&gt;
&lt;p&gt;For the most part, Flatpaks and Snaps solve a problem that doesn’t really exist (most of the time).
You should almost &lt;strong&gt;always try to use your distribution’s package manager instead&lt;&#x2F;strong&gt;, as it saves you from almost all of the problems listed above.
However, there are a few limited cases when a Flatpak might be useful…&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-software-not-in-repos&quot;&gt;1. Software not in Repos&lt;&#x2F;h3&gt;
&lt;p&gt;If you can’t get the software you need otherwise, use Flatpak (or see if there are AppImages).
Sometimes package managers don’t show you all of the available software. 
If you are trying to install proprietary software you may want to check if your package manager has repositories that are not enabled by default that might have the program you need.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;On Fedora, look into &lt;a href=&quot;https:&#x2F;&#x2F;rpmfusion.org&#x2F;Configuration&quot;&gt;enabling RPM Fusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;On Debian and its countless derivatives, add the non-free repository from the &lt;a href=&quot;https:&#x2F;&#x2F;wiki.debian.org&#x2F;SourcesList&quot;&gt;sources list&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;On Void Linux, enable the &lt;code&gt;nonfree&lt;&#x2F;code&gt; repo by installing the &lt;code&gt;void-repo-nonfree&lt;&#x2F;code&gt; package. Also check for &lt;a href=&quot;https:&#x2F;&#x2F;docs.voidlinux.org&#x2F;xbps&#x2F;repositories&#x2F;restricted.html&quot;&gt;restricted packages&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;2-software-outdated-in-repos&quot;&gt;2. Software Outdated in Repos&lt;&#x2F;h3&gt;
&lt;p&gt;If you dig a bit (or are running Debian), you might be able to find versions of software that were packaged while the World Trade Center was still standing.
After searching the internet for solutions to an annoying bug for a while and see that it has been fixed, but not in your distro’s version of the software it’s time to look for a Flatpak.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-software-keeps-crashing-and-or-is-made-by-the-kde-project&quot;&gt;3. Software Keeps Crashing (and&#x2F;or is made by the KDE project)&lt;&#x2F;h3&gt;
&lt;p&gt;Sometimes software is not tested against the specific versions of libraries that your system is running.
This can causes many weird issues that make software inoperable.
Flatpaks contain their own libraries, the same versions that the developers are running.
KDE makes some pretty great software but Krita and Kdenlive crash very frequently for me, using a Flatpak often solves the problem.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>[Part 2] Learning Russian: Change of Plans</title>
		<published>2020-09-20T00:00:00+00:00</published>
		<updated>2020-09-24T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/russian-part-two/" type="text/html"/>
		<id>https://sburris.xyz/posts/russian-part-two/</id>
		<content type="html">&lt;h2 id=&quot;rt-s-learn-russian&quot;&gt;RT’s Learn Russian&lt;&#x2F;h2&gt;
&lt;p&gt;RT’s Russian course does not have working audio anymore.
I wrote to their support email address to ask if it would be fixed and was told that the project is no longer maintained and will not be updated.
As a result, I have decided to go with the &lt;a href=&quot;https:&#x2F;&#x2F;sburris.xyz&#x2F;posts&#x2F;russian-part-two&#x2F;russianlessons.net&quot;&gt;RussianLessons.net&lt;&#x2F;a&gt; website instead.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;progress&quot;&gt;Progress&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;pronunciation&quot;&gt;Pronunciation&lt;&#x2F;h3&gt;
&lt;p&gt;I’ve become comfortable with most of the alphabet and can sound out Russian words written in Cyrillic, albeit slowly.
So far, emphasis and stress has been the hardest part of pronouncing words for me.
The letter ‘o’ always gets me as it is pronounced like the English ‘a’ when it is not stressed.
I am not comfortable with the hard and soft sign characters yet.
Otherwise, listening to Russian speech should help me find the rhythm of words.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;vocabulary&quot;&gt;Vocabulary&lt;&#x2F;h3&gt;
&lt;p&gt;I can now count to ten, and have learned a few words such as Спасибо (thank you), Привет (informal greeting), хорошо (good).
Before I began studying, I really only knew да (yes), нет (no), and товарищ (comrade, thanks &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hogan%27s_Heroes&quot;&gt;Hogan’s Heroes&lt;&#x2F;a&gt;).
I recognized the word спасибо (thanks) in a Батюшка (I can now pronounce that) song, but noticed that it sounds more like “спасубо” and I wonder if it’s just the manner of singing or if the word is slightly different in Old Church Slavonic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;observations&quot;&gt;Observations&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Though many letters are shared within English and Russian, only the letter ‘c’ is in the same place on both keyboards.&lt;&#x2F;li&gt;
&lt;li&gt;Zipf’s law of abbreviation doesn’t seem to apply as much to Russian as English. The law states that common words tend to be shorter, and Russian seems to have some &lt;em&gt;very&lt;&#x2F;em&gt; long common words such as Здравствуйте (hello). I get the feeling that the language may have been shaped more by writers than speakers comparatively. Alexander Pushkin, a poet&#x2F;playwright&#x2F;novelist credited with much of the development of Russian literature and had a large influence on the language as a whole.&lt;&#x2F;li&gt;
&lt;li&gt;Russian cursive is scary.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>How to Set up MPD on Void Linux</title>
		<published>2020-09-16T00:00:00+00:00</published>
		<updated>2020-10-23T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/mpd-void-linux/" type="text/html"/>
		<id>https://sburris.xyz/posts/mpd-void-linux/</id>
		<content type="html">&lt;h2 id=&quot;what-is-mpd&quot;&gt;What is MPD?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.musicpd.org&#x2F;&quot;&gt;Music Player Daemon&lt;&#x2F;a&gt; or MPD is a music server.
On Linux, several music players such as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;CDrummond&#x2F;cantata&quot;&gt;Cantata&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;rybczak.net&#x2F;ncmpcpp&#x2F;&quot;&gt;ncmpcpp&lt;&#x2F;a&gt; depend on it.
Why split a music player into a server and a client?
It enables you (and perhaps some family&#x2F;friends) to access your music on all of your devices, even while away from home.
MPD is supplemented greatly by using &lt;a href=&quot;http:&#x2F;&#x2F;beets.io&#x2F;&quot;&gt;Beets&lt;&#x2F;a&gt; in conjunction to properly organize, get album art for, and tag your music.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;cantata.png&quot; alt=&quot;Cantata&quot; title=&quot;Cantata playing music&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;void-linux&quot;&gt;Void Linux&lt;&#x2F;h3&gt;
&lt;p&gt;I’m making a guide for &lt;a href=&quot;https:&#x2F;&#x2F;voidlinux.org&#x2F;&quot;&gt;Void Linux&lt;&#x2F;a&gt; because most MPD setup guides on the internet are for Ubuntu, Fedora, or Arch Linux.
These Linux distributions and tutorials all use systemd to manage services, whereas Void uses runit, which changes things slightly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;&#x2F;h2&gt;
&lt;p&gt;First, install MPD:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# xbps-install -S mpd
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Open &lt;code&gt;&#x2F;etc&#x2F;mpd.conf&lt;&#x2F;code&gt; in a text editor, and find the &lt;code&gt;music_directory&lt;&#x2F;code&gt; setting.
Uncomment (remove leading &lt;code&gt;#&lt;&#x2F;code&gt;) if necessary and enter the path to your music collection.
For me this looks like &lt;code&gt;music_directory &amp;quot;~&#x2F;music&amp;quot;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I’d also recommend setting &lt;code&gt;playlist_directory&lt;&#x2F;code&gt; to somewhere easily accessible.
Set the address and port if you need to, but the default should work fine if you are using MPD on your home network or a single machine.&lt;&#x2F;p&gt;
&lt;p&gt;You can set a user for MPD to run as, but for use on a single computer I recommend leaving it commented so that you don’t have to worry about the MPD user not being able to access your music collection.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;running&quot;&gt;Running&lt;&#x2F;h2&gt;
&lt;p&gt;Now you just need to enable the MPD service, on Void Linux that is:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;# ln -s &#x2F;etc&#x2F;sv&#x2F;mpd &#x2F;var&#x2F;service
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you have any interest in song ratings, see my post &lt;a href=&quot;&#x2F;posts&#x2F;mpd-track-ratings&quot;&gt;“How to Enable MPD Track Ratings on Void Linux”&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;troubleshooting&quot;&gt;Troubleshooting&lt;&#x2F;h3&gt;
&lt;p&gt;If something goes wrong, try running &lt;code&gt;mpd&lt;&#x2F;code&gt; in the terminal.
If it complains about missing directories, create them manually.
If it has issues binding to the network port, make sure nothing else is running on the port specified or that there isn’t an instance of MPD already running.
Should you still have issues, the MPD manual has a &lt;a href=&quot;https:&#x2F;&#x2F;www.musicpd.org&#x2F;doc&#x2F;html&#x2F;user.html#troubleshooting&quot;&gt;troubleshooting chapter&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>[Part 1] Learning Russian: Strategy and Cyrillic</title>
		<published>2020-09-11T00:00:00+00:00</published>
		<updated>2020-09-11T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/russian-part-one/" type="text/html"/>
		<id>https://sburris.xyz/posts/russian-part-one/</id>
		<content type="html">&lt;h2 id=&quot;advice&quot;&gt;Advice&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve done some research into how to actually learn Russian, and have heard some surprising things.
The most surprising is the advice to almost completely ignore Russian grammar and focus on vocabulary.
Some say that even native speakers can barely manage proper Russian grammar and that most misunderstandings don’t come from grammar problems, but rather lack of vocabulary or mispronunciation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;progress&quot;&gt;Progress&lt;&#x2F;h2&gt;
&lt;p&gt;So far, I can pronounce most of the letters in the Russian alphabet. 
Learning Greek letters from math and physics has helped me learn several letters that are not derived from the Latin alphabet.
I’ve watched a few videos on the language’s history as well as the history of Russian for a bit more context.
From these videos I’ve learned that word order is flexible and that there are six cases (Nominative, Genitive, Dative, Accusative, Instrumental, Prepositional).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;strategy&quot;&gt;Strategy&lt;&#x2F;h2&gt;
&lt;p&gt;I will start by learning the remaining Russian letters and then trying &lt;a href=&quot;https:&#x2F;&#x2F;learnrussian.rt.com&#x2F;&quot;&gt;RT’s Russian course&lt;&#x2F;a&gt;.
As I learn words, I will add them to an &lt;a href=&quot;https:&#x2F;&#x2F;apps.ankiweb.net&#x2F;&quot;&gt;Anki&lt;&#x2F;a&gt; deck as spaced repetition is one of the most effective ways to memorise.
I’ll plan more when I’m better oriented within the language, but for now I plan on finding a book such as Lingua Latina Per Se Illustrata or Gerta Malaperdis (esperanto) to start reading easy Russian as soon as I can.
These books start out simple in their target language, intending to be accessible to monoglot English speakers and teach the language as each chapter progresses in linguistic complexity.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>[Part 0] Learning Russian: Motivation</title>
		<published>2020-06-09T00:00:00+00:00</published>
		<updated>2021-07-18T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/russian-part-zero/" type="text/html"/>
		<id>https://sburris.xyz/posts/russian-part-zero/</id>
		<content type="html">&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;&#x2F;h2&gt;
&lt;p&gt;I’ve decided to learn Russian and maintain a log of my learning.
I chose Russian after careful consideration for reasons which I will now explain.
My primary motive for learning another language is to access to literature that I wouldn’t be able to otherwise.
I am not particularly interested in being able to speak Russian well, but want to be capable of comprehending non-text media to a reasonable extent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;availability-of-media&quot;&gt;Availability of Media&lt;&#x2F;h2&gt;
&lt;p&gt;As I researched candidate languages to learn, I mainly was searching for an abundance of available media and literature.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-internet&quot;&gt;The Internet&lt;&#x2F;h3&gt;
&lt;p&gt;Russian is the second most used language on the internet as of September 10th 2020.
According to &lt;a href=&quot;https:&#x2F;&#x2F;w3techs.com&#x2F;technologies&#x2F;overview&#x2F;content_language&quot;&gt;W3Techs&lt;&#x2F;a&gt;, 59.9% of the internet’s content of known language is English, and 8.7% is Russian.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;literature&quot;&gt;Literature&lt;&#x2F;h3&gt;
&lt;p&gt;Many great mathematicians (Cantor, Chebyshev, Lobachevsky, Perelman), physicists (Cherenkov, Landau, Podolsky) and philosophers (Dostoevsky, Kropotkin, Tolstoy) came from modern day Russia.
Given how the Russian language is noted for its literature, I expect there will be no shortage of new material for me to read and ideas to learn about.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;alternative-perspectives&quot;&gt;Alternative Perspectives&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;number-of-speakers&quot;&gt;Number of Speakers&lt;&#x2F;h3&gt;
&lt;p&gt;Related to the availability of literature, I want a language that is spoken by a large number of people.
According to &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_languages_by_total_number_of_speakers&quot;&gt;Wikipedia&lt;&#x2F;a&gt;, the most widely spoken among the languages being considered is Arabic, followed by Russian.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;geographic-diversity&quot;&gt;Geographic Diversity&lt;&#x2F;h3&gt;
&lt;p&gt;Being an official language in 11 states, and a minority language in several others, Russian is spoken over a large geographic area.
This means that I will be able to access a large variety of perspectives all within the same language.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;time-in-use&quot;&gt;Time in Use&lt;&#x2F;h3&gt;
&lt;p&gt;Out of the languages I read considered, many of them have existed for a long time and have a large span of history in writing.
Russian has a large advantage over Latin here because Latin is now a dead language, whereas Russian is still extremely active.
Likewise, Hebrew &lt;em&gt;was&lt;&#x2F;em&gt; a dead language, but is one of the only languages to have been successfully revived.
This means that there is a large gap in history during which little to no works were produced in Hebrew.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dialects-and-other-languages&quot;&gt;Dialects and Other Languages&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;old-church-slavonic&quot;&gt;Old Church Slavonic&lt;&#x2F;h4&gt;
&lt;p&gt;Russian speakers understand 90% of Old Church Slavonic.
Old Church Slavonic (OCS) was used a liturgical language and was used in a large volume of religious texts.
I know very little and would like to learn more about the historical religious practices of the Russian-speaking nations.
My favorite album of all time, &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=URDWbv4miAQ&quot;&gt;Литоургия - Батюшка&lt;&#x2F;a&gt;, was written in Old Church Slavonic.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ukrainian-and-belarusian&quot;&gt;Ukrainian and Belarusian&lt;&#x2F;h4&gt;
&lt;p&gt;Russian speakers can understand an estimated 70% of Belarusian and Ukrainian, which will be nice should I ever visit either.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;difference-from-english&quot;&gt;Difference from English&lt;&#x2F;h3&gt;
&lt;p&gt;Language can change the way you think, and I would like to learn something that isn’t as similar to English as some languages that I’ve played with in the past.
I don’t exactly have a great justification for it, but I prefer to learn a language with a different alphabet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ease-of-learning&quot;&gt;Ease of Learning&lt;&#x2F;h2&gt;
&lt;p&gt;I would like to be able to use the language sooner rather than later, and though I am willing to put in more than a little bit of work, preference is given to languages that are quicker to learn while still differing from English.
According to the FSI (Foreign State Institute), which ranks &lt;a href=&quot;https:&#x2F;&#x2F;www.state.gov&#x2F;foreign-language-training&#x2F;&quot;&gt;difficulty to learn other languages&lt;&#x2F;a&gt;, Arabic requires 2,200 class hours to learn.
This is twice the number of hours than that listed for Greek, Russian and Hebrew.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I have chosen to learn Russian because it is quite different from English, has been in use for a long time, is used by many people today, is not as hard to learn as Arabic, and is closely related to other languages.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Using AsciiDoc with Hugo</title>
		<published>2020-05-08T00:00:00+00:00</published>
		<updated>2020-06-09T00:00:00+00:00</updated>
		<link href="https://sburris.xyz/posts/asciidoc-with-hugo/" type="text/html"/>
		<id>https://sburris.xyz/posts/asciidoc-with-hugo/</id>
		<content type="html">&lt;h2 id=&quot;initial-setup&quot;&gt;Initial Setup&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gohugo.io&quot;&gt;Hugo&lt;&#x2F;a&gt; has built-in support for AsciiDoc but cannot render AsciiDoc files to HTML on its own. 
To be able to write blog posts using AsciiDoc, install &lt;a href=&quot;https:&#x2F;&#x2F;asciidoctor.org&quot;&gt;Asciidoctor&lt;&#x2F;a&gt; (recommended) or &lt;a href=&quot;https:&#x2F;&#x2F;asciidoc.org&quot;&gt;AsciiDoc&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;$ gem install asciidoctor
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;$ pip install asciidoc3
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;netlify-continuous-deployment&quot;&gt;Netlify Continuous Deployment&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;netlify.com&quot;&gt;Netlify&lt;&#x2F;a&gt; uses &lt;code&gt;Gemfile&lt;&#x2F;code&gt; and &lt;code&gt;Gemfile.lock&lt;&#x2F;code&gt; to install Ruby dependencies automatically.
To use AsciiDoc, you will need to create a &lt;code&gt;Gemfile&lt;&#x2F;code&gt; in the project root directory with the following contents:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;source &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;https:&#x2F;&#x2F;rubygems.org&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;gem &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;asciidoctor&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To create a &lt;code&gt;Gemfile.lock&lt;&#x2F;code&gt;, install the &lt;code&gt;bundler&lt;&#x2F;code&gt; gem locally (&lt;code&gt;gem install bundler&lt;&#x2F;code&gt;) and then run &lt;code&gt;bundle install&lt;&#x2F;code&gt;.
Add the lock file to your git repository and push it.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;lock-files&quot;&gt;Lock Files&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;code&gt;.lock&lt;&#x2F;code&gt; file is primarily for keeping track of the last tested versions of your project’s dependencies.
The &lt;code&gt;Gemfile&lt;&#x2F;code&gt; is a list of package names, whereas &lt;code&gt;Gemfile.lock&lt;&#x2F;code&gt; specifies specific versions to prevent breakage due to updates in production.
&lt;a href=&quot;https:&#x2F;&#x2F;pipenv.pypa.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;Pipenv&lt;&#x2F;a&gt; works much to the same effect for Python projects, but also manages virtual environment and keeps track of dependency hashes for security, among other useful things.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;writing-posts&quot;&gt;Writing Posts&lt;&#x2F;h3&gt;
&lt;p&gt;The first difference to note is the file extension used, AsciiDoc files must end with &lt;code&gt;.adoc&lt;&#x2F;code&gt; or &lt;code&gt;.asciidoc&lt;&#x2F;code&gt;.
&lt;a href=&quot;https:&#x2F;&#x2F;asciidoctor.org&#x2F;docs&#x2F;asciidoc-syntax-quick-reference&quot;&gt;Read up&lt;&#x2F;a&gt; on the &lt;a href=&quot;https:&#x2F;&#x2F;learnxinyminutes.com&#x2F;docs&#x2F;asciidoc&#x2F;&quot;&gt;syntax&lt;&#x2F;a&gt; then create a new post with Hugo by running &lt;code&gt;hugo new posts&#x2F;post-name.adoc&lt;&#x2F;code&gt; and start writing.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;headers&quot;&gt;Headers&lt;&#x2F;h4&gt;
&lt;p&gt;Note that only one “level zero” (&lt;code&gt;h1&lt;&#x2F;code&gt;) header is allowed in any AsciiDoc document not specified to be a book.
Hugo already makes a &lt;code&gt;h1&lt;&#x2F;code&gt; element from the title sent in the front matter, so your post’s first header should be a “level one” (&lt;code&gt;h2&lt;&#x2F;code&gt;) header:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;&quot;&gt;
&lt;code&gt;&lt;span style=&quot;color:#fdf4c1aa;&quot;&gt;== Header title
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;notice the two equal signs, this is important.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;front-matter&quot;&gt;Front Matter&lt;&#x2F;h4&gt;
&lt;p&gt;Note that all types of &lt;a href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;content-management&#x2F;front-matter&#x2F;&quot;&gt;front matter&lt;&#x2F;a&gt; in Hugo are compatible with all supported &lt;a href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;content-management&#x2F;formats&#x2F;&quot;&gt;content formats&lt;&#x2F;a&gt;.
The &lt;code&gt;hugo new&lt;&#x2F;code&gt; command uses &lt;a href=&quot;https:&#x2F;&#x2F;yaml.org&#x2F;&quot;&gt;YAML&lt;&#x2F;a&gt; front matter formatting by default, but none of the other options (&lt;a href=&quot;https:&#x2F;&#x2F;www.json.org&#x2F;json-en.html&quot;&gt;JSON&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;toml.io&#x2F;en&#x2F;&quot;&gt;TOML&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;orgmode.org&#x2F;&quot;&gt;Org&lt;&#x2F;a&gt;) will cause issues with AsciiDoc.&lt;&#x2F;p&gt;
</content>
	</entry>
</feed>
