<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Martin Frost</title>
    <description>The latest articles on Forem by Martin Frost (@frost).</description>
    <link>https://forem.com/frost</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F472873%2F0fe42bf1-b872-4d46-ac01-2e8412414115.png</url>
      <title>Forem: Martin Frost</title>
      <link>https://forem.com/frost</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/frost"/>
    <language>en</language>
    <item>
      <title>How I set up my Python projects using asdf and direnv</title>
      <dc:creator>Martin Frost</dc:creator>
      <pubDate>Fri, 30 Jun 2023 20:33:24 +0000</pubDate>
      <link>https://forem.com/frost/how-i-set-up-my-python-projects-using-asdf-and-direnv-4o67</link>
      <guid>https://forem.com/frost/how-i-set-up-my-python-projects-using-asdf-and-direnv-4o67</guid>
      <description>&lt;p&gt;I tend to do a lot of work in Python, and I think it can be mess to set up and fiddle with creating virtualenvs for each project, etc. For a long while, I used &lt;code&gt;pyenv&lt;/code&gt; and &lt;code&gt;pyenv-virtualenv&lt;/code&gt; to do this for me, but since I still used &lt;code&gt;asdf&lt;/code&gt; for a bunch of other things (like &lt;code&gt;nodejs&lt;/code&gt;, or other versions of other languages), I figured I should try to get their Python-plugin to play nicely with me and my setup as well.&lt;/p&gt;

&lt;p&gt;Here's what I ended up with.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Install &lt;code&gt;asdf&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;Go to the &lt;a href="https://asdf-vm.com/guide/getting-started.html" rel="noopener noreferrer"&gt;asdf getting started page&lt;/a&gt; and follow the instructions for your operating system. Basically, you need to install &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;curl&lt;/code&gt; in order to get &lt;code&gt;asdf&lt;/code&gt; working.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Install asdf plugins
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  asdf plugin-install python
  asdf plugin-install direnv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  3. Install and configure direnv
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;asdf direnv setup --shell bash --version latest&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Install a python version
&lt;/h1&gt;

&lt;p&gt;First, make sure to install the suggested build dependencies for your operating system. These are listed in &lt;a href="https://github.com/pyenv/pyenv/wiki#suggested-build-environment" rel="noopener noreferrer"&gt;the &lt;code&gt;pyenv&lt;/code&gt; README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After that, you can run the command to install a Python version: &lt;code&gt;asdf install python 3.11.4&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  5. Create a sample project
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  git init hello_world
  cd hello_world
  echo "layout python" &amp;gt; .envrc
  direnv allow
  asdf local python 3.11.4
  echo ".direnv/" &amp;gt;&amp;gt; .gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;python --version&lt;/code&gt; will now print &lt;code&gt;Python 3.11.4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;layout python&lt;/code&gt; part that went into your .envrc tells direnv to set up Python with a virtualenv and put that in the &lt;code&gt;.direnv/&amp;lt;python-version&amp;gt;&lt;/code&gt; directory (in this case &lt;code&gt;.direnv/python-3.11&lt;/code&gt;). This means that any packages you &lt;code&gt;pip install&lt;/code&gt; will end up in there. Therefore, make sure to add that directory to your &lt;code&gt;.gitignore&lt;/code&gt; file, so that you don't accidentally vendor all of your dependencies, unless that's what you want.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;direnv allow&lt;/code&gt; part is there to allow direnv to automatically load stuff when you switch to this directory. If you don't do this now, you will get a warning the next time you &lt;code&gt;cd hello_world&lt;/code&gt;, saying that you haven't allowed the &lt;code&gt;.envrc&lt;/code&gt; in this directory to run stuff locally. It's there as a security measure.&lt;/p&gt;

&lt;h1&gt;
  
  
  6. Commit your setup
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  git add .gitignore .tool-versions .envrc
  git commit -m "Initial python/direnv setup"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  7. Get this to work with your editor
&lt;/h1&gt;

&lt;p&gt;So, how to get this goodness picked up automatically by your editor/IDE then? I mean, if you can't automatically run tests from inside Emacs/(neo)vim/VSCode/whatever, then it's not much use anyway.&lt;/p&gt;

&lt;p&gt;Luckily, at least Visual Studio Code picks this up automatically, and even prompts you for the &lt;code&gt;direnv allow&lt;/code&gt; part separately, so if you only use VSCode as your daily driver, you can probably skip the manual &lt;code&gt;direnv allow&lt;/code&gt; step in the terminal. I imagine PyCharm and other more fully fleshed out IDEs also provide this luxury.&lt;/p&gt;

&lt;p&gt;For Emacs or (neo)vim, you will need to configure whatever plugin you are using to use a shell where you have direnv configured, so with the above example, it should work if you shell out using &lt;code&gt;bash&lt;/code&gt; rather than &lt;code&gt;sh&lt;/code&gt;. If you configured direnv to use &lt;code&gt;zsh&lt;/code&gt;, then maybe you should consider having your editor use &lt;code&gt;zsh&lt;/code&gt; when shelling out.&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>python</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Add a custom keyboard layout in Ubuntu using Ansible</title>
      <dc:creator>Martin Frost</dc:creator>
      <pubDate>Thu, 11 Nov 2021 09:54:10 +0000</pubDate>
      <link>https://forem.com/frost/add-a-custom-keyboard-layout-in-ubuntu-using-ansible-5235</link>
      <guid>https://forem.com/frost/add-a-custom-keyboard-layout-in-ubuntu-using-ansible-5235</guid>
      <description>&lt;p&gt;I have been using a slightly custom-modded version of the US Dvorak layout for years, and I like automating my computer setups.&lt;/p&gt;

&lt;p&gt;It has always seemed like a hassle trying to automate the keyboard layout setup, so I haven't gotten myself to do it until now.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to add a custom keyboard layout in Ubuntu?
&lt;/h2&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A functional xkb keyboard layout, placed under &lt;code&gt;/usr/share/X11/xkb/symbols/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;An entry in one of the *.lst files under &lt;code&gt;/usr/share/X11/xkb/rules/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;An entry in the corresponding *.xml file under the same rules directory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When all this is done, you need to run the &lt;code&gt;sudo dpkg-reconfigure xkeyboard-data&lt;/code&gt; command, to make your installation reload the configured keyboard layouts. This will enable your desktop environment or window manager (Gnome, KDE, i3, XMonad, etc.) to pick up on the changes and let you choose your custom keyboard layout so that it's available even at the login screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  XKB Layout
&lt;/h3&gt;

&lt;p&gt;My layout is basically that I modded the standard US Dvorak layout by adding some characters with umlauts and other stuff that's used in the Swedish language (å, ö, ä, é, and the very infrequently used ü). I access these by holding the altgr key and pressing &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;o&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;, &lt;code&gt;u&lt;/code&gt;, and &lt;code&gt;y&lt;/code&gt; keys respectively (i.e., for the people who don't know the Dvorak layout, that's the keys that usually have the letters &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;s&lt;/code&gt;, &lt;code&gt;d&lt;/code&gt;, &lt;code&gt;f&lt;/code&gt;, and &lt;code&gt;t&lt;/code&gt; on them).&lt;/p&gt;

&lt;p&gt;It looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// This is basically a US Dvorak with some (mostly) Swedish accented characters added
// å -&amp;gt; alt-gr a
// ä -&amp;gt; alt-gr e
// ö -&amp;gt; alt-gr o
// é -&amp;gt; alt-gr u
// ü -&amp;gt; alt-gr y

default partial alphanumeric_keys
xkb_symbols "dvorak" {
    include "us(dvorak)"
    include "level3(caps_switch)"
    include "level3(ralt_switch)"

    name[Group1] = "Swedish (Frost Dvorak)";

    //             Unmodified       Shift           AltGr            Shift+AltGr

    // // symbols row, left side
    key &amp;lt;AD05&amp;gt; { [ y,               Y,              udiaeresis,      Udiaeresis ] };

    // home row, left side
    key &amp;lt;AC01&amp;gt; { [ a,               A,              aring,           Aring      ] };
    key &amp;lt;AC02&amp;gt; { [ o,               O,              odiaeresis,      Odiaeresis ] };
    key &amp;lt;AC03&amp;gt; { [ e,               E,              adiaeresis,      Adiaeresis ] };
    key &amp;lt;AC04&amp;gt; { [ u,               U,              eacute,          Eacute     ] };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  *.lst entries
&lt;/h3&gt;

&lt;p&gt;Normally, there should be an &lt;code&gt;evdev.extras.lst&lt;/code&gt; file, and it &lt;em&gt;should&lt;/em&gt; be possible to add your entry there, but due to some bug, that doesn't work, and we have to add this to the &lt;code&gt;evdev.lst&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;You need to add &lt;em&gt;two&lt;/em&gt; different lines in this file, one under the &lt;code&gt;! layouts&lt;/code&gt; section, and one under the &lt;code&gt;! variants&lt;/code&gt; section.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;! layouts&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  frost           Swedish (Frost Dvorak)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;! variants&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  dvorak       frost: Swedish (Frost Dvorak)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  *.xml entry
&lt;/h3&gt;

&lt;p&gt;The XML entry gives pretty much the same information as the lst entry, but in a different format.&lt;/p&gt;

&lt;p&gt;It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;layout&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;configItem&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;frost&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;shortDescription&amp;gt;&lt;/span&gt;frost dvorak&lt;span class="nt"&gt;&amp;lt;/shortDescription&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;Swedish&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;languageList&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;iso639Id&amp;gt;&lt;/span&gt;swe&lt;span class="nt"&gt;&amp;lt;/iso639Id&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/languageList&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/configItem&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;variantList&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;variant&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;configItem&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;dvorak&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;Swedish (Frost Dvorak)&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/configItem&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/variant&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/variantList&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/layout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same bug-related thing goes here, so this needs to be added to the &lt;code&gt;evdev.xml&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating all of this using Ansible
&lt;/h2&gt;

&lt;p&gt;I was going through my setup scripts the other day and realized that I could probably be able to automate this entire thing as well, to remove a few more of the manual steps in setting up my computer. I've had some bad luck with work computers the past year and a half and so I've had to do this multiple times.&lt;/p&gt;

&lt;p&gt;After a little digging around and testing things, I found out that we can use the &lt;code&gt;lineinfile&lt;/code&gt; module for the &lt;code&gt;*.lst&lt;/code&gt; entries, and the &lt;code&gt;xml&lt;/code&gt; module for the XML entry.&lt;/p&gt;

&lt;p&gt;Not only that, but we can also tell Ansible to automatically run the &lt;code&gt;dpkg-reconfigure&lt;/code&gt; command, &lt;em&gt;AND&lt;/em&gt; tell it to configure my keyboard layouts for me, so I don't have to poke around in the menus at all!&lt;/p&gt;

&lt;p&gt;Here's the Playbook definition I use for this, task by task.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copy the keyboard layout file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Copy keyboard layout file&lt;/span&gt;
      &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frost.xkb&lt;/span&gt;
        &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/usr/share/X11/xkb/symbols/frost&lt;/span&gt;
        &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
        &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
        &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0644'&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add the &lt;code&gt;! layout&lt;/code&gt; entry to evdev.lst
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Add layout to evdev.lst&lt;/span&gt;
      &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
      &lt;span class="na"&gt;lineinfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/usr/share/X11/xkb/rules/evdev.lst&lt;/span&gt;
        &lt;span class="na"&gt;insertafter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;layout"&lt;/span&gt;
        &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;  &lt;/span&gt;&lt;span class="s"&gt;frost&lt;/span&gt;&lt;span class="nv"&gt;           &lt;/span&gt;&lt;span class="s"&gt;Swedish&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(Frost&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Dvorak)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add the &lt;code&gt;! variant&lt;/code&gt; entry to evdev.lst
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Add variant to evdev.lst&lt;/span&gt;
      &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
      &lt;span class="na"&gt;lineinfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/usr/share/X11/xkb/rules/evdev.lst&lt;/span&gt;
        &lt;span class="na"&gt;insertafter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;variant"&lt;/span&gt;
        &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;  &lt;/span&gt;&lt;span class="s"&gt;dvorak&lt;/span&gt;&lt;span class="nv"&gt;       &lt;/span&gt;&lt;span class="s"&gt;frost:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Swedish&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(Frost&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Dvorak)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add the &lt;code&gt;&amp;lt;layout&amp;gt;&lt;/code&gt; entry to evdev.xml
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Add layout to evdev.xml&lt;/span&gt;
      &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
      &lt;span class="na"&gt;xml&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/usr/share/X11/xkb/rules/evdev.xml&lt;/span&gt;
        &lt;span class="na"&gt;xpath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/xkbConfigRegistry/layoutList&lt;/span&gt;
        &lt;span class="na"&gt;backup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
        &lt;span class="na"&gt;input_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xml&lt;/span&gt;
        &lt;span class="na"&gt;add_children&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;&amp;lt;layout&amp;gt;&lt;/span&gt;
              &lt;span class="s"&gt;&amp;lt;configItem&amp;gt;&lt;/span&gt;
                &lt;span class="s"&gt;&amp;lt;name&amp;gt;frost&amp;lt;/name&amp;gt;&lt;/span&gt;
                &lt;span class="s"&gt;&amp;lt;shortDescription&amp;gt;frost dvorak&amp;lt;/shortDescription&amp;gt;&lt;/span&gt;
                &lt;span class="s"&gt;&amp;lt;description&amp;gt;Swedish&amp;lt;/description&amp;gt;&lt;/span&gt;
                &lt;span class="s"&gt;&amp;lt;languageList&amp;gt;&lt;/span&gt;
                  &lt;span class="s"&gt;&amp;lt;iso639Id&amp;gt;swe&amp;lt;/iso639Id&amp;gt;&lt;/span&gt;
                &lt;span class="s"&gt;&amp;lt;/languageList&amp;gt;&lt;/span&gt;
              &lt;span class="s"&gt;&amp;lt;/configItem&amp;gt;&lt;/span&gt;
              &lt;span class="s"&gt;&amp;lt;variantList&amp;gt;&lt;/span&gt;
                &lt;span class="s"&gt;&amp;lt;variant&amp;gt;&lt;/span&gt;
                  &lt;span class="s"&gt;&amp;lt;configItem&amp;gt;&lt;/span&gt;
                    &lt;span class="s"&gt;&amp;lt;name&amp;gt;dvorak&amp;lt;/name&amp;gt;&lt;/span&gt;
                    &lt;span class="s"&gt;&amp;lt;description&amp;gt;Swedish (Frost Dvorak)&amp;lt;/description&amp;gt;&lt;/span&gt;
                  &lt;span class="s"&gt;&amp;lt;/configItem&amp;gt;&lt;/span&gt;
                &lt;span class="s"&gt;&amp;lt;/variant&amp;gt;&lt;/span&gt;
              &lt;span class="s"&gt;&amp;lt;/variantList&amp;gt;&lt;/span&gt;
            &lt;span class="s"&gt;&amp;lt;/layout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reconfigure xkb-data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Reconfigure xkb-data&lt;/span&gt;
      &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
      &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dpkg-reconfigure xkb-data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set the GNOME keyboard layout(s)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set keyboard layout&lt;/span&gt;
      &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
      &lt;span class="na"&gt;become_user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frost&lt;/span&gt;
      &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dconf&lt;/span&gt;
      &lt;span class="na"&gt;dconf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/org/gnome/desktop/input-sources/sources"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[('xkb',&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'frost+dvorak'),&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;('xkb',&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'dvorak')]"&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;present&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Restart GNOME Shell without exiting all programs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Restart GNOME Shell&lt;/span&gt;
      &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;busctl --user call org.gnome.Shell /org/gnome/Shell org.gnome.Shell Eval s 'Meta.restart("Restarting…")'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Håppü Häcking!&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>ubuntu</category>
      <category>keyboardlayout</category>
    </item>
    <item>
      <title>Fish-style abbreviations in Zsh</title>
      <dc:creator>Martin Frost</dc:creator>
      <pubDate>Fri, 02 Oct 2020 16:10:01 +0000</pubDate>
      <link>https://forem.com/frost/fish-style-abbreviations-in-zsh-40aa</link>
      <guid>https://forem.com/frost/fish-style-abbreviations-in-zsh-40aa</guid>
      <description>&lt;p&gt;A few years ago, I tried using The &lt;a href="https://fishshell.com/" rel="noopener noreferrer"&gt;Friendly Interactive SHell&lt;/a&gt; as my default shell.&lt;/p&gt;

&lt;p&gt;It has a lot of nice things, like syntax highlighting on the command line, reverse-history-search by pressing the up/down arrows, and a few more things, but it kept rubbing me the wrong way that it is not POSIX compatible (like &lt;a href="https://www.gnu.org/software/bash/" rel="noopener noreferrer"&gt;bash&lt;/a&gt; or &lt;a href="https://www.zsh.org/" rel="noopener noreferrer"&gt;zsh&lt;/a&gt;), so I ended up going back to zsh.&lt;/p&gt;

&lt;p&gt;I did, however, bring a few features with me because they are awesome, and abbreviations is one of those features. They are sort of like aliases but better, at least in my opinion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Abbreviations vs aliases
&lt;/h2&gt;

&lt;p&gt;In all shells there is something called aliases.&lt;br&gt;
Aliases work like this, you define some alias, like &lt;code&gt;alias gst="git status"&lt;/code&gt;. After this, if I type &lt;code&gt;gst&lt;/code&gt; into my terminal and hit enter, the terminal will run the &lt;code&gt;git status&lt;/code&gt; command and display the output as expected.&lt;/p&gt;

&lt;p&gt;In fish, I can also define an abbreviation like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abbr -a -g gst git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works mostly the same way as an alias but with one very important exception: if I type &lt;code&gt;gst&lt;/code&gt; in my terminal and hit space, the terminal &lt;em&gt;will expand the abbreviation&lt;/em&gt;. If I hit enter instead of space, it will expand the abbreviation and run the command. &lt;/p&gt;

&lt;p&gt;This means that it's easier to see what commands have been run by looking at the history and seeing a bunch of lines with &lt;code&gt;git status&lt;/code&gt; instead of just &lt;code&gt;gst&lt;/code&gt;, and it also means that I can copy commands that I ran directly from my terminal, send them to a collegue, and they can just paste and run them directly if they want to. They don't need to know anything about what aliases I happen to have in my shell config.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to get this in Zsh?
&lt;/h2&gt;

&lt;p&gt;I simply add these functions in my &lt;code&gt;~/.zshrc&lt;/code&gt; and then I can start listing abbreviations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# declare a list of expandable aliases to fill up later
typeset -a ealiases
ealiases=()

# write a function for adding an alias to the list mentioned above
function abbrev-alias() {
    alias $1
    ealiases+=(${1%%\=*})
}

# expand any aliases in the current line buffer
function expand-ealias() {
    if [[ $LBUFFER =~ "\&amp;lt;(${(j:|:)ealiases})\$" ]]; then
        zle _expand_alias
        zle expand-word
    fi
    zle magic-space
}
zle -N expand-ealias

# Bind the space key to the expand-alias function above, so that space will expand any expandable aliases
bindkey ' '        expand-ealias
bindkey '^ '       magic-space     # control-space to bypass completion
bindkey -M isearch " "      magic-space     # normal space during searches

# A function for expanding any aliases before accepting the line as is and executing the entered command
expand-alias-and-accept-line() {
    expand-ealias
    zle .backward-delete-char
    zle .accept-line
}
zle -N accept-line expand-alias-and-accept-line
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I can start adding abbreviations like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abbrev-alias g="git"
abbrev-alias gst="git status"
abbrev-alias gcb="git checkout --branch"
abbrev-alias ll="ls -l"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>zsh</category>
      <category>abbreviations</category>
      <category>fish</category>
    </item>
  </channel>
</rss>
