<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Posts on Mostly Useful</title>
		<link>https://mostlyuseful.tech/posts/</link>
		<description>Recent content in Posts on Mostly Useful</description>
		<generator>Hugo -- gohugo.io</generator>
		<language>en-us</language>
		<copyright>This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.</copyright>
		<lastBuildDate>Mon, 15 Apr 2019 10:13:48 -0400</lastBuildDate>
		<atom:link href="https://mostlyuseful.tech/posts/index.xml" rel="self" type="application/rss+xml" />
		
		<item>
			<title>Electron and Vue Components</title>
			<link>https://mostlyuseful.tech/posts/electron-vue-components/</link>
			<pubDate>Mon, 15 Apr 2019 10:13:48 -0400</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/electron-vue-components/</guid>
			<description>In the previous post I covered how to get Electron and Vue set up, leaving the work of development fairly open ended. Now that you (and I) have had some time to consume the Vue documentation, let&amp;rsquo;s see how much we&amp;rsquo;ve actually retained.
Vue Basics Vue provides a system that splits the view from the data. You utilize this mechanism as far as you need, with a complete split, or continue to intersperse your HTML with code.</description>
			<content type="html"><![CDATA[<p>In the <a href="/posts/electron-vue-setup">previous post</a> I covered how to get Electron and Vue set up,
leaving the work of development fairly open ended. Now that you (and I) have had
some time to consume the <a href="https://vuejs.org/v2/guide/components.html">Vue documentation</a>, let&rsquo;s see how much we&rsquo;ve
actually retained.</p>
<h1 id="vue-basics">Vue Basics</h1>
<p>Vue provides a system that splits the view from the data. You utilize this
mechanism as far as you need, with a complete split, or continue to intersperse
your HTML with code.</p>
<p>Each <code>.vue</code> file contains both the HTML and code, which allows for some
thought-locality &ndash; all the code that directly deals with the HTML is nearby.
You can even use this mechanism internally in a source file, by breaking down
your model with &ldquo;local components&rdquo;.</p>
<p>Each &ldquo;Vue instance&rdquo; is created with pre-defined properties, as provided by the
<code>data</code> object provided to it. These properties (at instance creation time) are
what it will track. If any new properties are added later, they are not
&ldquo;reacted&rdquo; upon. Something to remember.</p>
<h1 id="populating-vue-components">Populating Vue Components</h1>
<p>In a component, you may want to display some data. This data can be populated in
various ways:</p>
<ul>
<li>the data directly &ndash; <code>{{ dataVariable }}</code></li>
<li>computed (and cached) &ndash; <code>{{ computeFunction }}</code></li>
<li>method (not cached) &ndash; <code>{{ methodFunction }}</code></li>
</ul>
<p>As expected, the three ways are from the corresponding part in the code:</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">...
  data: () =&gt; ({
    dataVariable: null,
  }),
  computed: {
    computeFunction: function () {
      ...
    },
  },
  methods: {
    methodFunction: function () {
      ...
    },
  },
</code></pre></div><h1 id="passing-data-to-components">Passing Data to Components</h1>
<p>When creating a &ldquo;dynamic component&rdquo; (my words), you may want to pass some
reactive data to it. While this seems like it should be trivial (as of Vue
2.6.11), it was not.</p>
<p>In the component, we will use both <code>props</code>, <code>computed</code>, and <code>watch</code>.</p>
<p>For example, if you want to control &ldquo;showing&rdquo; and &ldquo;hiding&rdquo; the component&hellip;</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">  &lt;v-dialog v-model=&#34;show&#34;&gt;
...


...
  props: {
    value: Boolean,
  },
  computed: {
    show: {
      get () {
        return this.value;
      },
      set (value) {
        this.$emit(&#39;input&#39;, value);
      }
    },
  },
  watch: {
    show (value) {
      if (value) {
        // ... &#39;this.value&#39; will be true, do work.
      }
    }
  },
</code></pre></div><p>And in the parent of the component&hellip;</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">  &lt;MyComponent v-model=&#34;showIt&#34;&gt;&lt;/MyComponent&gt;
</code></pre></div><p>So in the parent, if the <code>showIt</code> variable is toggled, the component will react
to the change and run some code, as well as trigger behaviors dependent on the
<code>show</code> variable.</p>
]]></content>
		</item>
		
		<item>
			<title>Getting Started with Electron and Vue</title>
			<link>https://mostlyuseful.tech/posts/electron-vue-setup/</link>
			<pubDate>Sat, 13 Apr 2019 22:17:53 -0400</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/electron-vue-setup/</guid>
			<description>There are a lot of boilerplates and blogs on how to set up Electron, Vue, Webpack, React, etc. But they all assume you know something about how they all relate and interact with each other.
Since I haven&amp;rsquo;t kept track of the changes in how development using JavaScript has come since the early days, hopefully this provides some insight from an old-timer.
Getting Started Since I want to build a standalone application, Electron is a very convenient way to go about it.</description>
			<content type="html"><![CDATA[<p>There are a lot of boilerplates and blogs on how to set up Electron, Vue,
Webpack, React, etc. But they all assume you know something about how they all
relate and interact with each other.</p>
<p>Since I haven&rsquo;t kept track of the changes in how development using JavaScript
has come since the early days, hopefully this provides some insight from an
old-timer.</p>
<h1 id="getting-started">Getting Started</h1>
<p>Since I want to build a standalone application, <a href="http://electronjs.org/">Electron</a> is a very
convenient way to go about it. This is a framework built upon Chromium so you
can develop an application using Node.js, HTML, CSS, and JavaScript.</p>
<p>Now you ask, what is wrong with using native SDKs like GTK and Qt? I would
rather not deal with the dependencies in building on multiple platforms, as well
as dealing with the intricacies of GUI widgets. By leveraging HTML+CSS, building
the front-end should be fairly cross-platform and straightforward.</p>
<p>So what are the problems I&rsquo;m going to cover in this write-up?</p>
<ul>
<li>How to set it up.</li>
<li>What do the parts all do?</li>
<li>How do you publish/distribute?</li>
<li>How do you run it?</li>
<li>What does development look like?</li>
</ul>
<p>We&rsquo;ll be using <a href="https://vuejs.org/">Vue.js</a> as the frontend framework. While there are many
frameworks available to select from (React, AngularJS, etc), this seemed to be
the best documented &ldquo;from the ground up&rdquo;. So here we are.</p>
<h1 id="installation">Installation</h1>
<p>There&rsquo;s no &ldquo;right&rdquo; way it seems to do all this, so let&rsquo;s go with the general
concensus and what seems easy so far.</p>
<p>First, get a Node.js environment set up, in whichever way you prefer.</p>
<h2 id="global-tools">Global Tools</h2>
<p>Next, install <a href="https://cli.vuejs.org/">Vue CLI</a> (version 3), which is not used as a component
in the project, but instead is used for setting up and building the project.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">$ npm install -g @vue/cli
</code></pre></div><p>Install <a href="https://pnpm.js.org/">pnpm</a>, which is a disk space efficient package manager.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">$ npm install -g pnpm
</code></pre></div><h2 id="vue">Vue</h2>
<p>With the prereqs installed, let&rsquo;s set up the project, using default settings. I
don&rsquo;t know enough about the customizations, to do anything special.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">$ vue create my-app
$ cd my-app
</code></pre></div><p>This will create the directory <code>my-app</code>, set it up as a git repository, and get
Node.js install and configured. How convenient.</p>
<p>Let&rsquo;s look at what&rsquo;s there&hellip;</p>
<ul>
<li><code>babel.config.js</code> &ndash; Babel is a transpiler, converting JavaScript into a
version that is backwards-compatible in various environments. This is the main
config file for the tool; no need to touch it.</li>
<li><code>package.json</code> &ndash; NPM package registry, which lists the packages necessary to
run the project or perform development. We&rsquo;ll be adding to this later.</li>
<li><code>public/</code> &ndash; Directory to store static assets for the project.</li>
<li><code>src/</code> &ndash; Directory to store &ldquo;the code&rdquo; for the project.</li>
</ul>
<p>If you <code>pnpm run serve</code> at this point, we can serve up default contents in
the &ldquo;development build&rdquo; environment, which can be accessed using your web
browser. There&rsquo;s not much to see here.</p>
<h2 id="electron-builder">Electron Builder</h2>
<p>Since we don&rsquo;t intend to host this application somewhere and access via a web
browser, we now integrate Electon into the Vue app. This is done by installing
the <a href="https://nklayman.github.io/vue-cli-plugin-electron-builder/">electron-builder</a> plugin.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">$ vue add electron-builder
</code></pre></div><p>This added a few more files. Take a peek at the changes, and commit them to git.</p>
<ul>
<li><code>src/background.js</code> &ndash; the source code for the Electron main thread.</li>
</ul>
<p>If you <code>pnpm run electron:serve</code> at this point, we get the same default app,
now in its own application context.</p>
<h2 id="vuetify">Vuetify</h2>
<p>Finally, lets add <a href="https://github.com/vuetifyjs/vue-cli-plugin-vuetify">Vuetify</a>, which is a UI toolkit for Vue, which
provides an implementation of the Material Design Specification.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">$ vue add vuetify
</code></pre></div><p>Again, this changed or added a few more files. Commit them.</p>
<p>If you <code>pnpm run electron:serve</code> now, the application has prettified a little
bit.</p>
<h2 id="build">Build</h2>
<p>Now, lets see what happens when we build this.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">$ pnpm run electron:build
</code></pre></div><p>After a bit of churning, a <code>dist_electron</code> directory should be generated. This
contains the binary packages that can be executed standalone. The
<code>linux-unpacked</code> directory is of most use to me right now; tar it up and we have
our application!</p>
<h1 id="development">Development</h1>
<p>Okay, now that we have the essentials out of the way, how do we turn this &ldquo;Hello
World&rdquo; Electron-based application into something real?</p>
<p>Here are the main files that you&rsquo;ll deal with first:</p>
<ul>
<li><code>src/background.js</code> &ndash; Electron main process code. This handles creating the
app and any non-rendering work you may be doing.</li>
<li><code>src/main.js</code> &ndash; App (renderer) process code. This is run in the application
window via <code>public/index.html</code>.</li>
<li><code>src/App.vue</code> &ndash; The main Vue component.</li>
<li><code>src/components/</code> &ndash; Additional Vue components.</li>
</ul>
<p>For example, if you want to muck with how Electron renders the application, you
would modify <code>src/background.js</code>.</p>
<p>In my application, I don&rsquo;t need the menu bar, so I set the <code>autoHideMenuBar</code>
option. I also wanted to save the window state, so I installed and hooked up the
<code>electron-window-state</code> module.</p>
<p>The things for Vue are a bit more complicated to describe; the tutorials and
examples are fairly well written, so use them before diving in. But some side
notes for the beginner into NodeJS and Vue&hellip;</p>
<h2 id="global-application-state">Global Application State</h2>
<p>You can create an object in <code>main.js</code> that can be referenced in other
components. This can make tracking global application state into one place.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback"># main.js

export const appData = {
  title: &#39;Foo&#39;,
  someVariable: false
}

# App.vue

export default {
  // ...
  data: () =&gt; {
    return appData
  }
</code></pre></div><p>Now that you have application state, you may want to poke at it in DevTools.
I haven&rsquo;t found a way that seems non-hacky, so here is the hacky:</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback"># main.js

global appData = appData
</code></pre></div><h2 id="vue-notes">Vue Notes</h2>
<p>As Vue is a framework, it obviously has some new syntax to go with.</p>
<ul>
<li>element <code>:property=&quot;method&quot;</code> &ndash; hook up <code>method()</code> to a property. The method
is defined in the <code>computed</code> section.</li>
<li>element <code>@click</code> &ndash; hook up some code to an action.</li>
<li><code>{{ ... }}</code> &ndash; execute some code</li>
</ul>
<h1 id="references">References</h1>
<ul>
<li><a href="https://developerlife.com/2018/08/22/vue-vueitfy-webpack/">https://developerlife.com/2018/08/22/vue-vueitfy-webpack/</a></li>
<li><a href="https://vuejs.org/v2/guide/">https://vuejs.org/v2/guide/</a></li>
<li><a href="https://electronjs.org/docs/api/browser-window">https://electronjs.org/docs/api/browser-window</a></li>
<li><a href="https://linustechtips.com/main/topic/922311-vuetifyjs-conditionally-disabling-components/">https://linustechtips.com/main/topic/922311-vuetifyjs-conditionally-disabling-components/</a></li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Building deb Package Using Docker</title>
			<link>https://mostlyuseful.tech/posts/docker-deb-package-build/</link>
			<pubDate>Mon, 18 Mar 2019 22:00:27 -0400</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/docker-deb-package-build/</guid>
			<description>While you can build deb packages by installing the necessary requirements and running the commands on your local machine, I prefer not to as it litters the system with random dev packages.
In the past, I used a debootstrab schroot. But that&amp;rsquo;s a ton of configuration steps that can be easily avoided by using Docker!
Assuming you have Docker already installed&amp;hellip; (make sure your user is in the docker group)</description>
			<content type="html"><![CDATA[<p>While you can build deb packages by installing the necessary requirements and
running the commands on your local machine, I prefer not to as it litters the
system with random dev packages.</p>
<p>In the past, I used a debootstrab schroot. But that&rsquo;s a ton of configuration
steps that can be easily avoided by using Docker!</p>
<p>Assuming you have Docker already installed&hellip;
(make sure your user is in the <code>docker</code> group)</p>
<p>First, install the <code>debocker</code> package. It&rsquo;s a helper tool to run all the
necessary commands.</p>
<p>Next, download the sources you need (dsc, orig.tar.gz, debian.tar.xz, etc) for
your package. In my case, I wanted to build the latest experimental <code>yosys</code>
for 18.04.</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">$ <span class="nb">cd</span> testbuild

$ wget http://archive.ubuntu.com/ubuntu/pool/universe/y/yosys/yosys_0.8-1build1.dsc
$ wget http://archive.ubuntu.com/ubuntu/pool/universe/y/yosys/yosys_0.8.orig.tar.gz
$ wget http://archive.ubuntu.com/ubuntu/pool/universe/y/yosys/yosys_0.8-1build1.debian.tar.xz

$ dpkg-source -x yosys_0.8-1build1.dsc

$ <span class="nb">cd</span> yosys-0.8

<span class="c1"># may need to fix the debian/changelog file</span>

$ debocker build --image ubuntu:18.04
</code></pre></div><p>Assuming everything went okay, you should have a bunch of <code>.deb</code> files built!</p>
]]></content>
		</item>
		
		<item>
			<title>Printing Source Code</title>
			<link>https://mostlyuseful.tech/posts/trueprint-pdf/</link>
			<pubDate>Fri, 15 Feb 2019 21:32:07 -0500</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/trueprint-pdf/</guid>
			<description>There are times when you want to print out some source code onto paper to make it easier to review. However, source code tends to be full of whitespace, so printing it as-is wastes a lot of the page.
Using trueprint and ps2pdf, we can generate something a little more convenient without sacrificing too much readability.
$ trueprint -C --I --n -G2 -2 filename.c | ps2pdf - output.pdf There&amp;rsquo;s probably better ways these days, but this has held up over time.</description>
			<content type="html"><![CDATA[<p>There are times when you want to print out some source code onto paper to make
it easier to review. However, source code tends to be full of whitespace, so
printing it as-is wastes a lot of the page.</p>
<p>Using <code>trueprint</code> and <code>ps2pdf</code>, we can generate something a little more
convenient without sacrificing too much readability.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">$ trueprint -C --I --n -G2 -2 filename.c | ps2pdf - output.pdf
</code></pre></div><p>There&rsquo;s probably better ways these days, but this has held up over time.</p>
]]></content>
		</item>
		
		<item>
			<title>Making Hard Apple Cider</title>
			<link>https://mostlyuseful.tech/posts/making-hard-apple-cider/</link>
			<pubDate>Wed, 13 Feb 2019 12:17:37 -0500</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/making-hard-apple-cider/</guid>
			<description>Notes from making a 1 gallon batch of hard cider (from scratch).
Following the instructions at How to Make Hard Cider, and the 1G Big Mouth jar and carboy, the wife and I (mostly me) started our experiment&amp;hellip;
Picked up a gallon of apple cider (juice) at Market Basket, making sure it was only pasteurized and had no preservatives. Also a can of frozen concentrate apple juice, and some &amp;ldquo;Whole Earth Stevia and Monkfruit&amp;rdquo; sweetener.</description>
			<content type="html"><![CDATA[<p>Notes from making a 1 gallon batch of hard cider (from scratch).</p>
<p>Following the instructions at <a href="https://howtomakehardcider.com/making-your-cider/">How to Make Hard Cider</a>, and the 1G
Big Mouth jar and carboy, the wife and I (mostly me) started our experiment&hellip;</p>
<p>Picked up a gallon of apple cider (juice) at Market Basket, making sure it
was only pasteurized and had no preservatives. Also a can of frozen concentrate
apple juice, and some &ldquo;Whole Earth Stevia and Monkfruit&rdquo; sweetener.</p>
<p>Found a stash of Red Star &ldquo;Pasteur Champagne&rdquo; wine yeast in the fridge, which
had a best by date of Dec 2016. Figured it would still work, just not quite as
active initially.</p>
<p>Remember to look in the random homebrew stuff storage bin for the other stuff.</p>
<h1 id="primary-fermentation">Primary Fermentation</h1>
<p>Mix per the instructions,</p>
<ul>
<li>1G bottle of juice.</li>
<li>1/2 can of frozen juice concentrate.</li>
<li>1/4 tsp of Wyeast yeast nutrient.</li>
<li>whole packet of yeast.</li>
</ul>
<p>Put the jug in the corner; wrapped it in a blanket to block light.</p>
<h1 id="secondary-fermentation">Secondary Fermentation</h1>
<p>After 2 weeks, transferred into the carboy, with no special additions. We
wanted to have a baseline flavor profile for this batch.</p>
<h1 id="bottling">Bottling</h1>
<p>After 3 weeks (the beer going in parallel wasn&rsquo;t stable yet), prepped for
bottling. (Note: didn&rsquo;t take a hydrometer reading; just assumed.)</p>
<p>Put ~25 packets of the sweetener (2g per packet) for the 1G batch. This was done
by scaling up a 1oz taste measurement to the full 1G.</p>
<p>Added 1/4 can of frozen juice contentrate for carbonation priming.</p>
<h1 id="afterward">Afterward</h1>
<p>After 4 weeks, tasting time! Okay, well we forgot about it for a bit&hellip; So after
~8 weeks, we cracked open a bottle. It had nice carbination, tart and not that
sweet. And hazy.</p>
<p>Next time,</p>
<ul>
<li>add pectic enzyme to make it clear</li>
<li>first mix the sweetener packets in hot water to dissolve better; will try this
first instead of adding more sweetener</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>Automated LetsEncrypt on GitLab Pages</title>
			<link>https://mostlyuseful.tech/posts/gitlab-pages-letsencrypt/</link>
			<pubDate>Fri, 11 Jan 2019 19:13:14 -0500</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/gitlab-pages-letsencrypt/</guid>
			<description>Edit 2020-03-17: This has been obsolete for a while now. GitLab has baked-in LetsEncrypt infrastructure, so go use that!
  https://andrewsempere.org/blog/2018/11/01/Gitlab-LetsEncrypt.html https://github.com/tezcatlipoca/gitlab-letsencrypt  The two links above describe how to set up an auto-renewing LetsEncrypt SSL Certificate on gitlab pages. The instructions were easy to follow, and worked without any major fuss.
Since we&amp;rsquo;re using Hugo here, make sure the .gitlab-ci.yml file references the output path static/.well-known/acme-challenge.
The CI environment variables where you will configure CERT_DOMAINS, CERT_OPTIONS, and CERT_TOKEN is located in the project settings, under &amp;ldquo;CI / CD&amp;rdquo;.</description>
			<content type="html"><![CDATA[<blockquote>
<p><em><strong>Edit 2020-03-17</strong></em>: This has been obsolete for a while now. GitLab has baked-in
LetsEncrypt infrastructure, so go use that!</p>
</blockquote>
<ul>
<li><a href="https://andrewsempere.org/blog/2018/11/01/Gitlab-LetsEncrypt.html">https://andrewsempere.org/blog/2018/11/01/Gitlab-LetsEncrypt.html</a></li>
<li><a href="https://github.com/tezcatlipoca/gitlab-letsencrypt">https://github.com/tezcatlipoca/gitlab-letsencrypt</a></li>
</ul>
<p>The two links above describe how to set up an auto-renewing LetsEncrypt SSL
Certificate on gitlab pages. The instructions were easy to follow, and worked
without any major fuss.</p>
<p>Since we&rsquo;re using Hugo here, make sure the <code>.gitlab-ci.yml</code> file references the
output path <code>static/.well-known/acme-challenge</code>.</p>
<p>The CI environment variables where you will configure <code>CERT_DOMAINS</code>,
<code>CERT_OPTIONS</code>, and <code>CERT_TOKEN</code> is located in the project settings, under &ldquo;CI /
CD&rdquo;. Make sure to set <code>CERT_TOKEN</code> as Protected!</p>
<p>Create a &ldquo;Scheduling Pipeline&rdquo;. In theory if I ever had multiple scheduled
jobs, then each should have a <code>JOBNAME</code> variable to check against in the
<a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/34328#note_74946093">job configuration</a>?</p>
<p>Lastly, create the &ldquo;User Access Token&rdquo;, with <code>api</code> scope. Make sure to save the
token somewhere safe in case you accidentally lose it.</p>
]]></content>
		</item>
		
		<item>
			<title>Multiboot USB Notes</title>
			<link>https://mostlyuseful.tech/posts/multiboot-usb/</link>
			<pubDate>Fri, 11 Jan 2019 09:12:22 -0500</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/multiboot-usb/</guid>
			<description>Since I needed to build a new USB stick, a quick Googling was in order to see if the state-of-the-art had changed, since I scratched the UEFI+MBR multiboot itch. And people have! With colours!
It looks like aguslr&amp;rsquo;s multibootusb project has taken the generalization much farther than I ever would have; GRUB is pretty flexible&amp;hellip;
Note these steps are NOT compatible with Secure Boot! Make sure you disable it before using the drive.</description>
			<content type="html"><![CDATA[<p>Since I needed to build a new USB stick, a quick Googling was in order to see if
the state-of-the-art had changed, since I scratched the UEFI+MBR multiboot itch.
And people have! With colours!</p>
<p>It looks like <a href="https://github.com/aguslr/multibootusb">aguslr&rsquo;s multibootusb</a> project has taken the
generalization much farther than I ever would have; GRUB is pretty flexible&hellip;</p>
<p><strong>Note</strong> these steps are <strong>NOT</strong> compatible with Secure Boot! Make sure you
disable it before using the drive. (It&rsquo;ll bootload into grub, look okay, but
nothing is functional!)</p>
<h1 id="automatic">Automatic</h1>
<p>If you trust a script to do it all for you, the <code>makeUSB.sh</code> script will do it
all. If you don&rsquo;t, then read on&hellip;</p>
<h1 id="manual-steps">Manual Steps</h1>
<p>Since the instructions rely on the ArchWiki to get a proper <a href="https://wiki.archlinux.org/index.php/Multiboot_USB_drive#Hybrid_UEFI_GPT_.2B_BIOS_GPT.2FMBR_boot">bootable USB</a>
set up, and those instructions are fairly lousy&hellip;</p>
<h2 id="set-up-the-usb-drive">Set Up the USB Drive</h2>
<p>We&rsquo;ll need the following Ubuntu packages. They should already be installed.</p>
<ul>
<li>gdisk</li>
<li>grub-pc-bin</li>
<li>grub-efi-amd64-bin</li>
</ul>
<p>First, wipe the USB drive to make sure we&rsquo;re on a clean slate:</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">$ sudo dd <span class="k">if</span><span class="o">=</span>/dev/zero <span class="nv">of</span><span class="o">=</span>/dev/sdc <span class="nv">bs</span><span class="o">=</span>1M <span class="nv">count</span><span class="o">=</span><span class="m">512</span>
512+0 records in
512+0 records out
<span class="m">536870912</span> bytes <span class="o">(</span><span class="m">537</span> MB, <span class="m">512</span> MiB<span class="o">)</span> copied, 0.134964 s, 4.0 GB/s
$ sync
</code></pre></div><p>Unplug and replug the drive.</p>
<p>On running <code>gdisk</code>, it&rsquo;ll probably complain, as we just &ldquo;corrupted&rdquo; the disk&hellip;</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash"> sudo gdisk /dev/sdc
 GPT fdisk <span class="o">(</span>gdisk<span class="o">)</span> version 1.0.3

 Caution: invalid main GPT header, but valid backup<span class="p">;</span> regenerating main header
 from backup!

 Caution! After loading partitions, the CRC doesn<span class="s1">&#39;t check out!
</span><span class="s1"> Warning! Main partition table CRC mismatch! Loaded backup partition table
</span><span class="s1"> instead of main partition table!
</span><span class="s1">
</span><span class="s1"> Warning! One or more CRCs don&#39;</span>t match. You should repair the disk!

 Partition table scan:
   MBR: not present
   BSD: not present
   APM: not present
   GPT: damaged

Found invalid MBR and corrupt GPT. What <span class="k">do</span> you want to <span class="k">do</span>? <span class="o">(</span>Using the
GPT MAY permit recovery of GPT data.<span class="o">)</span>
 <span class="m">1</span> - Use current GPT
 <span class="m">2</span> - Create blank GPT

Your answer: <span class="m">2</span>
</code></pre></div><p>Create three partitions. The values taken are as suggested on the ArchWiki.</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: n
Partition number <span class="o">(</span>1-128, default 1<span class="o">)</span>: <span class="m">1</span>
First sector <span class="o">(</span>34-15794126, <span class="nv">default</span> <span class="o">=</span> 2048<span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>:
Last sector <span class="o">(</span>2048-15794126, <span class="nv">default</span> <span class="o">=</span> 15794126<span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>: +1M
Current <span class="nb">type</span> is <span class="s1">&#39;Linux filesystem&#39;</span>
Hex code or GUID <span class="o">(</span>L to show codes, <span class="nv">Enter</span> <span class="o">=</span> 8300<span class="o">)</span>: EF02
Changed <span class="nb">type</span> of partition to <span class="s1">&#39;BIOS boot partition&#39;</span>

Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: n
Partition number <span class="o">(</span>2-128, default 2<span class="o">)</span>: <span class="m">2</span>
First sector <span class="o">(</span>34-15794126, <span class="nv">default</span> <span class="o">=</span> 4096<span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>:
Last sector <span class="o">(</span>4096-15794126, <span class="nv">default</span> <span class="o">=</span> 15794126<span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>: +50M
Current <span class="nb">type</span> is <span class="s1">&#39;Linux filesystem&#39;</span>
Hex code or GUID <span class="o">(</span>L to show codes, <span class="nv">Enter</span> <span class="o">=</span> 8300<span class="o">)</span>: EF00
Changed <span class="nb">type</span> of partition to <span class="s1">&#39;EFI System&#39;</span>

Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: n
Partition number <span class="o">(</span>3-128, default 3<span class="o">)</span>: 
First sector <span class="o">(</span>34-15794126, <span class="nv">default</span> <span class="o">=</span> 106496<span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>: 
Last sector <span class="o">(</span>106496-15794126, <span class="nv">default</span> <span class="o">=</span> 15794126<span class="o">)</span> or <span class="o">{</span>+-<span class="o">}</span>size<span class="o">{</span>KMGTP<span class="o">}</span>: 
Current <span class="nb">type</span> is <span class="s1">&#39;Linux filesystem&#39;</span>
Hex code or GUID <span class="o">(</span>L to show codes, <span class="nv">Enter</span> <span class="o">=</span> 8300<span class="o">)</span>: <span class="m">0700</span>
Changed <span class="nb">type</span> of partition to <span class="s1">&#39;Microsoft basic data&#39;</span>
</code></pre></div><p>This should leave us with the following partitions:</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: p
Disk /dev/sdc: <span class="m">15794160</span> sectors, 7.5 GiB
Model: USB Flash Drive 
Sector size <span class="o">(</span>logical/physical<span class="o">)</span>: 512/512 bytes
Disk identifier <span class="o">(</span>GUID<span class="o">)</span>: EAA36968-DD45-467C-815E-EE433EF4B872
Partition table holds up to <span class="m">128</span> entries
Main partition table begins at sector <span class="m">2</span> and ends at sector <span class="m">33</span>
First usable sector is 34, last usable sector is <span class="m">15794126</span>
Partitions will be aligned on 2048-sector boundaries
Total free space is <span class="m">2014</span> sectors <span class="o">(</span>1007.0 KiB<span class="o">)</span>

Number  Start <span class="o">(</span>sector<span class="o">)</span>    End <span class="o">(</span>sector<span class="o">)</span>  Size       Code  Name
   <span class="m">1</span>            <span class="m">2048</span>            <span class="m">4095</span>   1024.0 KiB  EF02  BIOS boot partition
   <span class="m">2</span>            <span class="m">4096</span>          <span class="m">106495</span>   50.0 MiB    EF00  EFI System
   <span class="m">3</span>          <span class="m">106496</span>        <span class="m">15794126</span>   7.5 GiB     <span class="m">0700</span>  Microsoft basic data
</code></pre></div><p>Okay, lets get the partitions set up properly&hellip;</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">Command <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: r

Recovery/transformation <span class="nb">command</span> <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: h

WARNING! Hybrid MBRs are flaky and dangerous! If you decide not to use one,
just hit the Enter key at the below prompt and your MBR partition table will
be untouched.

Type from one to three GPT partition numbers, separated by spaces, to be
added to the hybrid MBR, in sequence: <span class="m">1</span> <span class="m">2</span> <span class="m">3</span>
Place EFI GPT <span class="o">(</span>0xEE<span class="o">)</span> partition first in MBR <span class="o">(</span>good <span class="k">for</span> GRUB<span class="o">)</span>? <span class="o">(</span>Y/N<span class="o">)</span>: N

Creating entry <span class="k">for</span> GPT partition <span class="c1">#1 (MBR partition #1)</span>
Enter an MBR hex code <span class="o">(</span>default EF<span class="o">)</span>: 
Set the bootable flag? <span class="o">(</span>Y/N<span class="o">)</span>: N

Creating entry <span class="k">for</span> GPT partition <span class="c1">#2 (MBR partition #2)</span>
Enter an MBR hex code <span class="o">(</span>default EF<span class="o">)</span>: 
Set the bootable flag? <span class="o">(</span>Y/N<span class="o">)</span>: N

Creating entry <span class="k">for</span> GPT partition <span class="c1">#3 (MBR partition #3)</span>
Enter an MBR hex code <span class="o">(</span>default 07<span class="o">)</span>: 0B
Set the bootable flag? <span class="o">(</span>Y/N<span class="o">)</span>: Y

Recovery/transformation <span class="nb">command</span> <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: x

Expert <span class="nb">command</span> <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: h

Expert <span class="nb">command</span> <span class="o">(</span>? <span class="k">for</span> <span class="nb">help</span><span class="o">)</span>: w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? <span class="o">(</span>Y/N<span class="o">)</span>: Y
OK<span class="p">;</span> writing new GUID partition table <span class="o">(</span>GPT<span class="o">)</span> to /dev/sdc.
The operation has completed successfully.
</code></pre></div><p>Finally it&rsquo;s time to format the partitions:</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">$ sudo mkfs.fat -F32 /dev/sdc2
mkfs.fat 4.1 <span class="o">(</span>2017-01-24<span class="o">)</span>

$ sudo mkfs.fat -F32 /dev/sdc3
mkfs.fat 4.1 <span class="o">(</span>2017-01-24<span class="o">)</span>
</code></pre></div><p>And install GRUB on the data partition (sdc3), and EFI on the ESP partition (sdc2)</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">$ mkdir /tmp/usbdat /tmp/usbefi

$ sudo mount /dev/sdc2 /tmp/usbefi

$ sudo mount /dev/sdc3 /tmp/usbdat

$ sudo mkdir /tmp/usbdat/boot

$ sudo grub-install --target<span class="o">=</span>i386-pc --recheck --boot-directory<span class="o">=</span>/tmp/usbdat/boot /dev/sdc
Installing <span class="k">for</span> i386-pc platform.
Installation finished. No error reported.

$ sudo grub-install --target<span class="o">=</span>x86_64-efi --removable --recheck --boot-directory<span class="o">=</span>/tmp/usbdat/boot --efi-directory<span class="o">=</span>/tmp/usbefi
Installing <span class="k">for</span> x86_64-efi platform.
Installation finished. No error reported.

$ sudo umount /tmp/usbefi

$ sudo umount /tmp/usbdat

$ sudo rmdir /tmp/usbefi /tmp/usbdat
</code></pre></div><p>Whew. Now that GRUB is installed, we can deal with installing a GRUB config
and getting ISOs onto the disk.</p>
<h2 id="install-multiboot-usb">Install MultiBoot USB</h2>
<p>Unplug and replug the USB drive, to make sure the partitions are all loaded
properly. If you have automounting, the data partition should mount.</p>
<p>Follow the steps on <a href="https://mbusb.aguslr.com/install.html">aguslr&rsquo;s GRUB config</a> install page.</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash">$ git clone https://github.com/aguslr/multibootusb
Cloning into <span class="s1">&#39;multibootusb&#39;</span>...
remote: Enumerating objects: 5227, <span class="k">done</span>.
remote: Total <span class="m">5227</span> <span class="o">(</span>delta 0<span class="o">)</span>, reused <span class="m">0</span> <span class="o">(</span>delta 0<span class="o">)</span>, pack-reused <span class="m">5227</span>
Receiving objects: 100% <span class="o">(</span>5227/5227<span class="o">)</span>, 4.22 MiB <span class="p">|</span> 7.76 MiB/s, <span class="k">done</span>.
Resolving deltas: 100% <span class="o">(</span>3254/3254<span class="o">)</span>, <span class="k">done</span>.

$ <span class="nb">export</span> <span class="nv">mntusb</span><span class="o">=</span>/media/usb <span class="nv">partusb</span><span class="o">=</span>/dev/sdc3
$ mkdir -p <span class="nv">$mntusb</span>/boot/<span class="o">{</span>grub/mbusb.d/,isos<span class="o">}</span>
$ <span class="nb">cd</span> multibootusb <span class="o">&amp;&amp;</span> cp -rf mbusb.cfg mbusb.d <span class="nv">$mntusb</span>/boot/grub/
$ <span class="nb">cd</span> multibootusb <span class="o">&amp;&amp;</span> cp -f grub.cfg.example <span class="nv">$mntusb</span>/boot/grub/grub.cfg
</code></pre></div><p>At this point I also modified <code>mbusb.cfg</code> to put <code>/isos</code> at the top level.</p>
<h1 id="isos">ISOs</h1>
<p>Now download all the ISOs you desire into <code>boot/isos</code>, no cfg changes needed!</p>
]]></content>
		</item>
		
		<item>
			<title>Overlay Mounting as non-root</title>
			<link>https://mostlyuseful.tech/posts/overlay-mounting/</link>
			<pubDate>Wed, 09 Jan 2019 20:34:26 -0500</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/overlay-mounting/</guid>
			<description>Note: This information has only been tested on Ubuntu 16.04 and 18.04.
There are times when you want to not modify the contents of a directory directly when working within it. For example, when dealing with some projects that litter the working directory with object and temporary files.
In the past, I would have sudo mount an overlayfs (or unionfs). This would then require entering a password on mount and unmount, which was less than ideal.</description>
			<content type="html"><![CDATA[<p><em>Note: This information has only been tested on Ubuntu 16.04 and 18.04.</em></p>
<p>There are times when you want to not modify the contents of a directory
directly when working within it. For example, when dealing with some projects
that litter the working directory with object and temporary files.</p>
<p>In the past, I would have <code>sudo mount</code> an overlayfs (or unionfs). This would
then require entering a password on <code>mount</code> and <code>unmount</code>, which was less than
ideal.</p>
<p>With the addition of &ldquo;user namespaces&rdquo; (and some permissions), we can do this
as a non-privileged user.</p>
<h1 id="the-steps-described">The Steps Described</h1>
<p>To enter a namespace, use the <code>unshare</code> command. For the first stage, we need to
create a namespace that hides mounts and provides root-like permissions.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">unshare -rm
</code></pre></div><p>Once we&rsquo;re in this namespace&rsquo;d shell, we can run our <code>mount</code> command, whereas
previously we would have to <code>sudo mount</code> it.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">mount -t overlay overlay -o lowerdir=/path/to/lower,upperdir=/path/to/upper,workdir=/path/to/workdir /path/to/mnt
</code></pre></div><p>For reference,</p>
<ul>
<li>lowerdir &ndash; the (read-only) directory that is the basis for the content</li>
<li>upperdir &ndash; the directory to write changes into</li>
<li>workdir &ndash; a (empty) directory that overlayfs uses as a working area</li>
</ul>
<p>At this point, you can do all your work in the mounted directory and be sure
that changes are only reflected in the upperdir once you&rsquo;re done with the mount.</p>
<p>Note: if the <code>mount</code> command generates a &ldquo;special device overlay does not exist&rdquo;
error, check if you&rsquo;ve typed the options and paths correctly. The message is a
complete red herring&hellip;</p>
<p>However, there are cases where you do not want to run commands as fake-root, so
you can create another (nested) namespace to put you back as your user.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">unshare -U
</code></pre></div><p>After you&rsquo;re all done, just back out of the (now two) shells, to get you back to
the original shell. The mount is automatically cleaned up, and you can access
see all the changes in the upperdir &ndash; and delete them all.</p>
<h1 id="automating-the-steps">Automating the Steps</h1>
<p>While running things manually is nice and all, I do this <a href="https://xkcd.com/1205/">sufficiently</a>
that scripting it all is beneficial to my sanity.</p>
<p>First, we need a script that gets run under the fake-root namespace:</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash"><span class="cp">#!/bin/bash
</span><span class="cp"></span>mount -t overlay overlay -o <span class="nv">lowerdir</span><span class="o">=</span><span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">&#34;</span>,upperdir<span class="o">=</span><span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">.upper&#34;</span>,workdir<span class="o">=</span><span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">.workdir&#34;</span> <span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">&#34;</span>
<span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> -ne <span class="m">0</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
  <span class="nb">exit</span> <span class="m">2</span>
<span class="k">fi</span>

<span class="nb">cd</span> <span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">&#34;</span>
unshare -U bash --init-file &lt;<span class="o">(</span><span class="nb">echo</span> <span class="s2">&#34;PS1=&#39;overlay|\w&gt; &#39;&#34;</span><span class="o">)</span>
</code></pre></div><p>And then you start it all by running <code>unshare -rm overlay.sh</code>, which leaves you
with a shell in the mounted directlry.</p>
<h1 id="more-automation">More Automation</h1>
<p>Is that not <a href="https://xkcd.com/1319/">enough</a>? Of course not &ndash; I had to run the first <code>unshare</code> command! I
don&rsquo;t want to remember that&hellip;</p>
<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash"><span class="cp">#!/bin/bash
</span><span class="cp"></span>
<span class="c1"># create working directory</span>
rm -rf <span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">.workdir&#34;</span>
mkdir <span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">.workdir&#34;</span>

<span class="c1"># wipe out any upper directory if it&#39;s already there!</span>
rm -rf <span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">.upper&#34;</span>
mkdir <span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">.upper&#34;</span>

cat <span class="s">&lt;&lt; EOM &gt; &#34;$PWD.script&#34;
</span><span class="s">mount -t overlay overlay -o lowerdir=&#34;$PWD&#34;,upperdir=&#34;$PWD.upper&#34;,workdir=&#34;$PWD.workdir&#34; &#34;$PWD&#34;
</span><span class="s">if [ \$? -ne 0 ]; then
</span><span class="s">  exit 2
</span><span class="s">fi
</span><span class="s">
</span><span class="s">cd &#34;$PWD&#34;
</span><span class="s">if [ -z &#34;$@&#34; ]; then
</span><span class="s">  unshare -U bash --init-file &lt;(echo &#34;PS1=&#39;overlay|\w&gt; &#39;&#34;)
</span><span class="s">else
</span><span class="s">  unshare -U $@
</span><span class="s">fi
</span><span class="s">EOM</span>

<span class="k">function</span> finish <span class="o">{</span>
  rm -rf <span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">.workdir&#34;</span>
  rm -rf <span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">.script&#34;</span>
  <span class="c1"># keep upper around in case I want to poke at it</span>
<span class="o">}</span>
<span class="nb">trap</span> finish EXIT

unshare -rm bash <span class="s2">&#34;</span><span class="nv">$PWD</span><span class="s2">.script&#34;</span>
</code></pre></div><p>And then you run the script from the directory you want to overlay, providing an
optional set of parameters in case you want to just execute things directly.</p>
]]></content>
		</item>
		
		<item>
			<title>Ubuntu 18.04 on Dell Precision 5520</title>
			<link>https://mostlyuseful.tech/posts/ubuntu-1804-dell-5520/</link>
			<pubDate>Sat, 05 Jan 2019 14:40:45 -0500</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/ubuntu-1804-dell-5520/</guid>
			<description>The &amp;ldquo;new&amp;rdquo; work laptop was pre-built with Windows 10 instead of LDE. So it&amp;rsquo;s time to have some fun with a fresh install of Ubuntu (18.04) on a nvidia laptop. As usual, going to start with a dual-boot setup first to kick the tires.
Sorry (to myself) if this is a bit rushed; didn&amp;rsquo;t write it all down (on mobile) during the install&amp;hellip;
TL;DR  Resized the Windows partition inside Windows.</description>
			<content type="html"><![CDATA[<p>The &ldquo;new&rdquo; work laptop was pre-built with Windows 10 instead of LDE. So it&rsquo;s time
to have some fun with a fresh install of Ubuntu (18.04) on a nvidia laptop. As
usual, going to start with a dual-boot setup first to kick the tires.</p>
<p>Sorry (to myself) if this is a bit rushed; didn&rsquo;t write it all down (on mobile)
during the install&hellip;</p>
<h1 id="tldr">TL;DR</h1>
<ul>
<li>Resized the Windows partition inside Windows.</li>
<li>No grub/conf changes were needed to boot the ISO (in UEFI mode).</li>
<li>Ubuntu installed using normal &ldquo;alongside Windows&rdquo; option.</li>
<li>When &ldquo;MOK Management&rdquo; screen comes up, make sure to &ldquo;enroll&rdquo;.</li>
<li>Follow post-install instructions for better power management.</li>
</ul>
<h1 id="reduce-windows-partition-size">Reduce Windows partition size</h1>
<p>Used the <a href="https://superuser.com/a/1060508">notes</a> from the internet about fully resizing the Windows
partition:</p>
<ol>
<li>Disable hibernation using <code>powercfg /h off</code></li>
<li>Disable pagefile</li>
<li>Disable system protection</li>
</ol>
<p>(Remember to reverse the steps after resizing.)</p>
<h1 id="install-ubuntu">Install Ubuntu</h1>
<p>Create a USB stick version of the Ubuntu Desktop 18.04 ISO, using the Ubuntu
built-in creator tool.</p>
<p>Using F12 during system boot, trigger the &ldquo;one-time boot&rdquo; menu. Select the UEFI
USB option. Installed as normal, with all the options: 3rd party software,
updates during install, etc.</p>
<p>On the parititioning screen, selected the &ldquo;alongside Windows&rdquo; option. Installer
properly configured a partition in the free space.</p>
<p>Note the Secure Boot instructions; wasn&rsquo;t clear to me at first&hellip;</p>
<h1 id="restart-and-first-configuration">Restart and First Configuration</h1>
<p>The first boot, the &ldquo;MOK Management&rdquo; screen will show up. Make sure to enroll
your key.</p>
<p>Make sure both Ubuntu and Windows both boot properly from the GRUB screen.</p>
<p>Remember to fix Windows to use store the system time as <a href="http://ubuntuhandbook.org/index.php/2016/05/time-differences-ubuntu-1604-windows-10/">UTC</a> instead of
local time:</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">Reg add HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation /v RealTimeIsUniversal /t REG_QWORD /d 1
</code></pre></div><h1 id="configure-ubuntu">Configure Ubuntu</h1>
<p>Follow the <a href="https://github.com/JackHack96/dell-xps-9570-ubuntu-respin#post-install-script">post-install script</a> to make sure power management runs
well. (Went from ~2h to ~6h battery life.)</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">sudo add-apt-repository ppa:linrunner/tlp
sudo add-apt-repository ppa:graphics-drivers/ppa

sudo apt update

sudo apt install thermald tlp tlp-rdw powertop

sudo ubuntu-drivers autoinstall

sudo prime-select intel
</code></pre></div><p>Create <code>/etc/modprobe.d/i915.conf</code> with the following contents, then run <code>sudo update-initramfs -u</code>:</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">options i915 enable_fbc=1 enable_guc_loading=1 enable_guc_submission=1 disable_power_well=0 fastboot=1
</code></pre></div><p>Modify <code>/etc/default/tlp</code> and set <code>RESTORE_DEVICE_STATE_ON_STARTUP=1</code>.</p>
<p>Update grub options in <code>/etc/default/grub</code>, then run <code>sudo update-grub</code>:</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">GRUB_CMDLINE_LINUX_DEFAULT=quiet acpi_rev_override=1 acpi_osi=Linux nouveau.modeset=0 pcie_aspm=force drm.vblankoffdelay=1 scsi_mod.use_blk_mq=1 nouveau.runpm=0 mem_sleep_default=deep
</code></pre></div><p>Install <a href="https://github.com/bulletmark/libinput-gestures">libinput-gestures</a> to get additional touchpad gestures
support. Decided not to install the <a href="https://gitlab.com/cunidev/gestures">GUI</a>, as the config file
defaults (<code>/etc/libinput-gestures.conf</code>) was sufficient.</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">sudo apt install libinput-tools xdotool wmctrl
git clone https://github.com/bulletmark/libinput-gestures.git
cd libinput-gestures
sudo make install
</code></pre></div><p>Fix up fonts <a href="http://blog.wxm.be/2014/08/29/increase-font-in-grub-for-high-dpi.html">on GRUB</a> and <a href="https://askubuntu.com/a/173221">the console</a> so it&rsquo;s not so tiny (HiDPI screen).</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">sudo grub-mkfont --output=/boot/grub/fonts/DejaVuSansMono24.pf2 \
  --size=24 /usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf
</code></pre></div><p>Then modify <code>/etc/default/grub</code> and change <code>GRUB_FONT</code>:</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">GRUB_FONT=/boot/grub/fonts/DejaVuSansMono24.pf2
</code></pre></div><p>For the console,</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">sudo dpkg-reconfigure console-setup
</code></pre></div><p>and select a font that is NOT &lsquo;Fixed&rsquo;, e.g. Terminus. When asked about font
size, select &lsquo;16x32&rsquo;.</p>
<h1 id="ubuntu-packages-and-stuff">Ubuntu Packages and Stuff</h1>
<p>Finally, configure dotfiles and install packages&hellip;</p>
<ul>
<li>git</li>
<li>gnome-tweaks</li>
<li>htop</li>
<li>jsonlint</li>
<li>libxml2-utils</li>
<li>lighttpd</li>
<li>moreutils</li>
<li>net-tools</li>
<li>network-manager-openconnect-gnome</li>
<li>p7zip-full</li>
<li>slack-desktop</li>
<li>sshfs</li>
<li>steam-launcher</li>
<li>typora</li>
<li>vim-nox</li>
<li>xsltproc</li>
<li>wireshark</li>
</ul>
<p>And gnome extensions&hellip;</p>
<ul>
<li>Alternatetab</li>
<li>Drop down terminal</li>
<li>Lock keys</li>
</ul>
<p>And gnome tweaks&hellip;</p>
<ul>
<li>Fonts &gt; Window Title &gt; Cantarell Bold 10</li>
<li>Fonts &gt; Interface &gt; Cantarell Regular 9</li>
<li>Fonts &gt; Document &gt; Sans Regular 10</li>
<li>Fonts &gt; Monospace &gt; Monospace Regular 9</li>
<li>Top Bar &gt; Activities Overview Hot Corner &gt; Off</li>
<li>Top Bar &gt; Date &gt; On</li>
</ul>
]]></content>
		</item>
		
		<item>
			<title>VIM macros</title>
			<link>https://mostlyuseful.tech/posts/vim-macros/</link>
			<pubDate>Tue, 05 Jun 2018 12:12:16 -0500</pubDate>
			
			<guid>https://mostlyuseful.tech/posts/vim-macros/</guid>
			<description>VIM macros are very handy for repetitive tasks. For example, when you are resolving lots of changes between two files.
So assuming the commands that are being performed are:
 Go to the next difference, ]c Copy from the other pane, do, or put to the other pane, dp Repeat&amp;hellip;  Though since you won&amp;rsquo;t know what to do about the next difference until you see it, it is probably better to swap the command order&amp;hellip;</description>
			<content type="html"><![CDATA[<p><a href="http://vim.wikia.com/wiki/Macros">VIM macros</a> are very handy for repetitive tasks. For example, when you are
resolving lots of changes between two files.</p>
<p>So assuming the commands that are being performed are:</p>
<ol>
<li>Go to the next difference, <code>]c</code></li>
<li>Copy from the other pane, <code>do</code>, or put to the other pane, <code>dp</code></li>
<li>Repeat&hellip;</li>
</ol>
<p>Though since you won&rsquo;t know what to do about the next difference until you see
it, it is probably better to swap the command order&hellip;</p>
<p>So you&rsquo;d record the macro (live) using the <code>q</code> command to register <code>a</code>&hellip;</p>
<div class="highlight"><pre class="chroma"><code class="language-fallback" data-lang="fallback">qa
do
]c
q
</code></pre></div><p>Now that you have the macro recorded, use <code>@a</code> to run the macro, and <code>@@</code> to
repeat the macro. If you can see ahead, save yourself some repetitive typing and
repeat the command (e.g. <code>3@@</code>).</p>
<p>To save/load the macro, see the URL; I haven&rsquo;t needed it yet&hellip;</p>
]]></content>
		</item>
		
	</channel>
</rss>
