Posts on Kim Grytøyrhttps://kim.grytoyr.io/posts/
Recent content in Posts on Kim GrytøyrHugo -- gohugo.ioen-usMon, 25 Nov 2019 18:24:00 +0200Visual Studio Code keybindingshttps://kim.grytoyr.io/posts/2019/11/visual-studio-code-keybindings/
Mon, 25 Nov 2019 18:24:00 +0200https://kim.grytoyr.io/posts/2019/11/visual-studio-code-keybindings/
<p>Here's a (growing) collection of useful keybindings for Visual Studio Code that I use or deem interesting. I've probably found most of them, if not all of them, on various sites on the internet. In those cases I've added a link to the source.</p>
<hr>
<h2 id="switching-between-editor-and-terminal">Switching between editor and terminal</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json"><span style="color:#960050;background-color:#1e0010">/</span><span style="color:#960050;background-color:#1e0010">/</span> <span style="color:#960050;background-color:#1e0010">T</span><span style="color:#960050;background-color:#1e0010">o</span><span style="color:#960050;background-color:#1e0010">g</span><span style="color:#960050;background-color:#1e0010">g</span><span style="color:#960050;background-color:#1e0010">l</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">b</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">w</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">n</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">m</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">l</span> <span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">d</span> <span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">d</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">o</span><span style="color:#960050;background-color:#1e0010">r</span> <span style="color:#960050;background-color:#1e0010">f</span><span style="color:#960050;background-color:#1e0010">o</span><span style="color:#960050;background-color:#1e0010">c</span><span style="color:#960050;background-color:#1e0010">u</span><span style="color:#960050;background-color:#1e0010">s</span>
{ <span style="color:#f92672">&#34;key&#34;</span>: <span style="color:#e6db74">&#34;ctrl+`&#34;</span>, <span style="color:#f92672">&#34;command&#34;</span>: <span style="color:#e6db74">&#34;workbench.action.terminal.focus&#34;</span>}<span style="color:#960050;background-color:#1e0010">,</span>
{ <span style="color:#f92672">&#34;key&#34;</span>: <span style="color:#e6db74">&#34;ctrl+`&#34;</span>, <span style="color:#f92672">&#34;command&#34;</span>: <span style="color:#e6db74">&#34;workbench.action.focusActiveEditorGroup&#34;</span>, <span style="color:#f92672">&#34;when&#34;</span>: <span style="color:#e6db74">&#34;terminalFocus&#34;</span>}
</code></pre></div><p>Source: [https://stackoverflow.com/questions/42796887/switch-focus-between-editor-and-integrated-terminal-in-visual-studio-code](Stack Overflow)</p>
<hr>
Sublime Text 3 – creating a pluginhttps://kim.grytoyr.io/posts/2019/02/sublime-text-3-creating-a-plugin/
Mon, 18 Feb 2019 21:50:00 +0200https://kim.grytoyr.io/posts/2019/02/sublime-text-3-creating-a-plugin/
<p>I've written <a href="https://src.grytoyr.io/kim/npaste">npaste</a>, a simple pastebin for text and images that supports encryption using GPG. After a while of using it via the command line I felt the need for a plugin for Sublime Text 3 and also Visual Studio Code. In this post I will explain how I created the plugin for Sublime Text 3.</p>
<h2 id="resources">Resources</h2>
<p>The ST3 plugin API is pretty well-documented, and there are also some resources available on the Package Control website that explains how to create a plugin. Despite this I had to do some research on my own, and the point of this post is to document the not so well documented aspects of creating and publishing an ST3 plugin.</p>
<ul>
<li><a href="https://packagecontrol.io/docs#Package_Developers">Package Control Documentation</a></li>
<li><a href="https://www.sublimetext.com/docs/3/api_reference.html">Sublime Text 3 Plugin API reference</a></li>
</ul>
<h2 id="create-the-plugin">Create the plugin</h2>
<p>The first thing I did was to create a default plugin file. You can easily do this from within Sublime Text 3 by choosing <code>Tools &gt; Developer &gt; New Plugin...</code> from the Main Menu.</p>
<p>The plugin file will look something along the lines of this:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#f92672">import</span> sublime
<span style="color:#f92672">import</span> sublime_plugin
<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ExampleCommand</span>(sublime_plugin<span style="color:#f92672">.</span>TextCommand):
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">run</span>(self, edit):
self<span style="color:#f92672">.</span>view<span style="color:#f92672">.</span>insert(edit, <span style="color:#ae81ff">0</span>, <span style="color:#e6db74"></span><span style="color:#e6db74">&#34;</span><span style="color:#e6db74">Hello, World!</span><span style="color:#e6db74">&#34;</span>)
</code></pre></div><p>ST3 treats these classes as commands without the <code>Command</code> part and in snake case. This <code>ExampleCommand</code> would be executed by telling ST3 to run the command <code>example</code>.</p>
<p>In my case, I named the class <code>NpasteUploadCommand</code> which can be executed by calling <code>npaste_upload</code>. More on that later.</p>
<p>The actual actions that the command will execute should be placed in the <code>run</code> method, but I'm not going to cover that in this post.</p>
<h2 id="saving-the-file">Saving the file</h2>
<p>I created an empty git repository at <code>~/dev/npaste-sublime</code> and saved the file as <code>npaste-upload.py</code> inside of this folder.</p>
<p>To be able to test the plugin as I developed it, I created a symbolic link inside of the <code>Packages</code> folder of ST3. Where this folder is located probably differs depending on which OS you're using, but in my case, as I'm using a Mac, it was located at <code>~/Library/Application Support/Sublime Text 3/Packages</code>. I basically did this:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">ln -s ~/dev/npaste-sublime ~/Library/Application<span style="color:#ae81ff">\ </span>Support/Sublime<span style="color:#ae81ff">\ </span>Text<span style="color:#ae81ff">\ </span>3/Packages/npaste
</code></pre></div><p>Now Sublime Text 3 will load this plugin and automatically reload it whenever I make changes to any files within that folder.</p>
<h2 id="keybindings">Keybindings</h2>
<p>ST3 allows you to easily configure default keybinding for each operating system it supports (Windows, Mac, Linux). To do this, simply create a file for each OS you want to support inside the package folder. The valid file names are:</p>
<ul>
<li>Default (Windows).sublime-keymap</li>
<li>Default (OSX).sublime-keymap</li>
<li>Default (Linux).sublime-keymap</li>
</ul>
<p>Inside of each file you can define keybindings by using the following syntax:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">[
{
<span style="color:#f92672">&#34;keys&#34;</span>: [<span style="color:#e6db74">&#34;ctrl+alt+shift+n&#34;</span>],
<span style="color:#f92672">&#34;command&#34;</span>: <span style="color:#e6db74">&#34;npaste_upload&#34;</span>
}
]
</code></pre></div><p>As you can see, the command that will be executed when you type <code>ctrl+alt+shift+n</code> is the previously mentioned <code>npaste_upload</code> command.</p>
<h2 id="dependencies">Dependencies</h2>
<p>My plugin depends on the <code>requests</code> package. To make sure that this package will be installed when installing the npaste plugin, I created a file in the root of the package folder called <code>dependencies.json</code>. The format of this file is documented in the Package Control Documentation, but in my case it is the following:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">{
<span style="color:#f92672">&#34;*&#34;</span>: {
<span style="color:#f92672">&#34;*&#34;</span>: [
<span style="color:#e6db74">&#34;requests&#34;</span>
]
}
}
</code></pre></div><h2 id="context-menu">Context Menu</h2>
<p>I wanted to have a menu entry when right clicking in a buffer, so I added a Context Menu entry. To do this, I created a folder called <code>menus</code> in the root of my package folder. Inside of this folder I placed a file called <code>Context.sublime-menu</code> with the following contents:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">[
{
<span style="color:#f92672">&#34;id&#34;</span> : <span style="color:#e6db74">&#34;npasteUpload&#34;</span>,
<span style="color:#f92672">&#34;caption&#34;</span> : <span style="color:#e6db74">&#34;Paste to npaste&#34;</span>,
<span style="color:#f92672">&#34;command&#34;</span> : <span style="color:#e6db74">&#34;npaste_upload&#34;</span>
}
]
</code></pre></div><h2 id="main-menu">Main Menu</h2>
<p>To be able to easily edit the settings of the npaste plugin, I wanted to add a menu entry to <code>Sublime Text &gt; Preferences &gt; Package Settings &gt; npaste</code> called <code>Settings</code>. To do so, I created a file inside of the <code>menus</code> folder called <code>Main.sublime-menu</code>. The contents of this file is as following:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">[
{
<span style="color:#f92672">&#34;id&#34;</span>: <span style="color:#e6db74">&#34;preferences&#34;</span>,
<span style="color:#f92672">&#34;children&#34;</span>: [
{
<span style="color:#f92672">&#34;id&#34;</span>: <span style="color:#e6db74">&#34;package-settings&#34;</span>,
<span style="color:#f92672">&#34;children&#34;</span>: [
{
<span style="color:#f92672">&#34;caption&#34;</span>: <span style="color:#e6db74">&#34;npaste&#34;</span>,
<span style="color:#f92672">&#34;children&#34;</span>: [
{
<span style="color:#f92672">&#34;caption&#34;</span>: <span style="color:#e6db74">&#34;Settings&#34;</span>,
<span style="color:#f92672">&#34;command&#34;</span>: <span style="color:#e6db74">&#34;edit_settings&#34;</span>,
<span style="color:#f92672">&#34;args&#34;</span>: {
<span style="color:#f92672">&#34;base_file&#34;</span>: <span style="color:#e6db74">&#34;${packages}/npaste/settings/npaste.sublime-settings&#34;</span>
}
}
]
}
]
}
]
}
]
</code></pre></div><h2 id="settings">Settings</h2>
<p>As you can see, the Main Menu entry points to a file called <code>settings/npaste.sublime-settings</code>. This file contains the default settings of the plugin. Since npaste relies on a remote server, the user must be able to set the hostname, username and password, along with some other settings. I created a folder in the root of the package folder called <code>settings</code>. Inside of this folder I created a file called <code>npaste.sublime-settings</code> with the following contents:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">{
<span style="color:#960050;background-color:#1e0010">/</span><span style="color:#960050;background-color:#1e0010">/</span> <span style="color:#960050;background-color:#1e0010">S</span><span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">c</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">f</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">s</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">h</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">U</span><span style="color:#960050;background-color:#1e0010">R</span><span style="color:#960050;background-color:#1e0010">L</span> <span style="color:#960050;background-color:#1e0010">o</span><span style="color:#960050;background-color:#1e0010">f</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">h</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">v</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">r</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">o</span> <span style="color:#960050;background-color:#1e0010">u</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">e</span>
<span style="color:#f92672">&#34;npaste.url&#34;</span>: <span style="color:#e6db74">&#34;https://localhost:3000/&#34;</span>,
<span style="color:#960050;background-color:#1e0010">/</span><span style="color:#960050;background-color:#1e0010">/</span> <span style="color:#960050;background-color:#1e0010">S</span><span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">c</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">f</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">s</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">h</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">A</span><span style="color:#960050;background-color:#1e0010">P</span><span style="color:#960050;background-color:#1e0010">I</span> <span style="color:#960050;background-color:#1e0010">u</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">m</span><span style="color:#960050;background-color:#1e0010">e</span>
<span style="color:#f92672">&#34;npaste.username&#34;</span>: <span style="color:#e6db74">&#34;username&#34;</span>,
<span style="color:#960050;background-color:#1e0010">/</span><span style="color:#960050;background-color:#1e0010">/</span> <span style="color:#960050;background-color:#1e0010">S</span><span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">c</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">f</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">s</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">h</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">A</span><span style="color:#960050;background-color:#1e0010">P</span><span style="color:#960050;background-color:#1e0010">I</span> <span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">w</span><span style="color:#960050;background-color:#1e0010">o</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">d</span>
<span style="color:#f92672">&#34;npaste.password&#34;</span>: <span style="color:#e6db74">&#34;password&#34;</span>,
<span style="color:#960050;background-color:#1e0010">/</span><span style="color:#960050;background-color:#1e0010">/</span> <span style="color:#960050;background-color:#1e0010">I</span><span style="color:#960050;background-color:#1e0010">f</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">u</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">,</span> <span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">s</span> <span style="color:#960050;background-color:#1e0010">w</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">l</span><span style="color:#960050;background-color:#1e0010">l</span> <span style="color:#960050;background-color:#1e0010">b</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">c</span><span style="color:#960050;background-color:#1e0010">h</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">v</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">d</span> <span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">d</span> <span style="color:#960050;background-color:#1e0010">o</span><span style="color:#960050;background-color:#1e0010">f</span> <span style="color:#960050;background-color:#1e0010">d</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">l</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">d</span> <span style="color:#960050;background-color:#1e0010">w</span><span style="color:#960050;background-color:#1e0010">h</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">n</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">h</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">y</span> <span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">x</span><span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">.</span>
<span style="color:#f92672">&#34;npaste.archive&#34;</span>: <span style="color:#66d9ef">true</span>,
<span style="color:#960050;background-color:#1e0010">/</span><span style="color:#960050;background-color:#1e0010">/</span> <span style="color:#960050;background-color:#1e0010">S</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">s</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">h</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">g</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">o</span><span style="color:#960050;background-color:#1e0010">f</span> <span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">s</span> <span style="color:#960050;background-color:#1e0010">(</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">,</span><span style="color:#960050;background-color:#1e0010">m</span><span style="color:#960050;background-color:#1e0010">,</span><span style="color:#960050;background-color:#1e0010">h</span><span style="color:#960050;background-color:#1e0010">,</span><span style="color:#960050;background-color:#1e0010">d</span><span style="color:#960050;background-color:#1e0010">,</span><span style="color:#960050;background-color:#1e0010">y</span><span style="color:#960050;background-color:#1e0010">)</span>
<span style="color:#f92672">&#34;npaste.age&#34;</span>: <span style="color:#e6db74">&#34;14d&#34;</span>,
<span style="color:#960050;background-color:#1e0010">/</span><span style="color:#960050;background-color:#1e0010">/</span> <span style="color:#960050;background-color:#1e0010">I</span><span style="color:#960050;background-color:#1e0010">f</span> <span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">u</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">,</span> <span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">a</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">s</span> <span style="color:#960050;background-color:#1e0010">w</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">l</span><span style="color:#960050;background-color:#1e0010">l</span> <span style="color:#960050;background-color:#1e0010">b</span><span style="color:#960050;background-color:#1e0010">e</span> <span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">c</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">y</span><span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">d</span> <span style="color:#960050;background-color:#1e0010">u</span><span style="color:#960050;background-color:#1e0010">s</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">g</span> <span style="color:#960050;background-color:#1e0010">G</span><span style="color:#960050;background-color:#1e0010">P</span><span style="color:#960050;background-color:#1e0010">G</span>
<span style="color:#f92672">&#34;npaste.encrypt&#34;</span>: <span style="color:#66d9ef">true</span>,
<span style="color:#960050;background-color:#1e0010">/</span><span style="color:#960050;background-color:#1e0010">/</span> <span style="color:#960050;background-color:#1e0010">E</span><span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">c</span><span style="color:#960050;background-color:#1e0010">r</span><span style="color:#960050;background-color:#1e0010">y</span><span style="color:#960050;background-color:#1e0010">p</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">i</span><span style="color:#960050;background-color:#1e0010">o</span><span style="color:#960050;background-color:#1e0010">n</span> <span style="color:#960050;background-color:#1e0010">k</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">y</span> <span style="color:#960050;background-color:#1e0010">l</span><span style="color:#960050;background-color:#1e0010">e</span><span style="color:#960050;background-color:#1e0010">n</span><span style="color:#960050;background-color:#1e0010">g</span><span style="color:#960050;background-color:#1e0010">t</span><span style="color:#960050;background-color:#1e0010">h</span>
<span style="color:#f92672">&#34;npaste.encryption_key_length&#34;</span>: <span style="color:#ae81ff">32</span>
}
</code></pre></div><p>Prepending all the keys with <code>npaste.</code> shouldn't be necessary and it's something I will improve in a later update.</p>
<h2 id="messages">Messages</h2>
<p>You've probably seen that some packages displays a text file after you've installed it or after an upgrade. I wanted this for my npaste plugin, so I created a new folder called <code>messages</code>. Inside of this folder I created two files: <code>install.txt</code> and <code>0.0.5.txt</code>. The contents of <code>install.txt</code> will be displayed when a user installs the package, and the contents of <code>0.0.5.txt</code> will be displayed when a user upgrades the package to version <code>0.0.5</code>. You can read more about this in the Package Control documentation.</p>
<p>Finally I created a file in the root of the package folder called <code>messages.json</code>. The contents of this file is the following:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">{
<span style="color:#f92672">&#34;install&#34;</span>: <span style="color:#e6db74">&#34;messages/install.txt&#34;</span>,
<span style="color:#f92672">&#34;0.0.5&#34;</span>: <span style="color:#e6db74">&#34;messages/0.0.5.txt&#34;</span>
}
</code></pre></div><h2 id="license-and-readme-files">LICENSE and README files</h2>
<p>You should add a <code>LICENSE</code> file to the root folder of your package. The Package Control bot will give you a warning if you don't have this file in your repository. It's also advisable to add a <code>README</code> file of some kind.</p>
<h2 id="folder-structure">Folder structure</h2>
<p>This is the structure of my package folder after doing all of the above steps:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-txt" data-lang="txt">.
├── Default (Linux).sublime-keymap
├── Default (OSX).sublime-keymap
├── Default (Windows).sublime-keymap
├── LICENSE
├── README.md
├── dependencies.json
├── menus
│ ├── Context.sublime-menu
│ └── Main.sublime-menu
├── messages
│ ├── 0.0.5.txt
│ └── install.txt
├── messages.json
├── npaste-upload.py
└── settings
└── npaste.sublime-settings
</code></pre></div><h2 id="publishing-the-package">Publishing the package</h2>
<p>This is well-documented in the <a href="https://packagecontrol.io/docs/submitting_a_package">Package Control Documentation</a>, so I'm not going to cover it here. The only thing that puzzled me was that there was no description below the package name when searching for the package within Package Control, so I had to do some research on this. It turns out that the description is fetched from the description of your repository, so be sure to add a short description to your repository.</p>
Pretty-print JSON on a Machttps://kim.grytoyr.io/posts/2018/10/pretty-print-json-on-a-mac/
Wed, 03 Oct 2018 08:50:00 +0200https://kim.grytoyr.io/posts/2018/10/pretty-print-json-on-a-mac/
<p>I've written <a href="https://src.grytoyr.io/kim/npaste">npaste</a>, a simple pastebin for text and images that supports encryption using GPG. My work involves a lot of JSON that I often need to share with others via Slack or other communication platforms. Sometimes the output is quite big and not very suitable for sharing inline. And in some cases the contents are sensitive and should not persist on the internet longer than necessary. In this post I'll collect and present some useful commands that can be used to paste, format and share pretty-printed JSON data.</p>
<blockquote>
<p>This post assumes you have the npaste-cli installed. Please see the <a href="https://src.grytoyr.io/kim/npaste">readme</a> for instructions on how to install it.</p>
</blockquote>
<p>Let's say you have the following unformatted JSON object in your clipboard:</p>
<pre><code>{&quot;id&quot;:1,&quot;type&quot;:&quot;object&quot;,&quot;name&quot;:&quot;Clipboard test&quot;,&quot;value&quot;:&quot;This is some random text&quot;}
</code></pre><p>Now, all you have to do is type the following:</p>
<pre><code>pbpaste | python -m json.tool | npaste --encrypt
</code></pre><blockquote>
<p>You could of course create an alias or a function for this so that you don't have to type in all this every time you want to paste something from your clipboard.</p>
</blockquote>
<p>The npaste client will encrypt and upload your formatted JSON and return the URL in your terminal. You can then share it with friends and collegaues, knowing that it is stored encrypted on the server. Here's a screenshot of how it looks on the npaste website:</p>
<figure>
<img src="https://kim.grytoyr.io/images/npaste-pretty-json.png"/>
</figure>
<p>If you're reading this before 2021-06-29 you can also view the output directly on my npaste website:</p>
<p><a href="https://paste.grytoyr.io/2f7cdb5647a6371b6393aa57#a7cde616472867fb0664853f6299dc572bd29b3ff51d8ce20ff6ba78b86f5a5b">Example output</a></p>
How I keep my inbox tidy and cleanhttps://kim.grytoyr.io/posts/2018/10/how-i-keep-my-inbox-tidy-and-clean/
Mon, 01 Oct 2018 05:50:00 +0200https://kim.grytoyr.io/posts/2018/10/how-i-keep-my-inbox-tidy-and-clean/
<p>I have two email accounts:</p>
<ul>
<li>Work</li>
<li>Private</li>
</ul>
<p>The one I use the most is by far my work email. This account mostly receives emails that are addressed to me directly. My private one, on the other hand, receives some spam, which is mostly being filtered out by my spam filters, and a lot of what I call «unimportant email».</p>
<blockquote>
<p><strong>«Unimportant email»</strong> are messages that I mostly don't care about and don't want to be notified about. I'd still like to receive them and be able to review them.</p>
</blockquote>
<h2 id="the-setup">The Setup</h2>
<p>I run my own mail server. This enables me to quite easily have all new email that I haven't specifically told the mail filter to put somewhere else, to go into a special temporary folder. Every now and then I get a summary of any new messages waiting for me in the temporary inbox delivered to my regular inbox. Only messages arriving in my regular inbox will trigger notifications and, as a result, disturb me.</p>
<p>I maintain a whitelist on the server, which I can easily add an address to remotely, that keeps track of senders that I want email from to arrive directly in my regular inbox.</p>
<hr>
<figure>
<img src="https://kim.grytoyr.io/images/mail-whitelist.png"/>
</figure>
<hr>
<p>By applying this technique I'm making sure that <strong>only important messages</strong> lands in my inbox. All the other cruft I can review and organize whenever I have the time and energy needed to do so.</p>
<p>Kudos to <a href="https://enpo.no">@enpo</a> for mentioning this technique to me and helping me with the bash one-liners that does all the dirty work.</p>
Change file encoding in Vimhttps://kim.grytoyr.io/posts/2018/06/change-file-encoding-in-vim/
Fri, 15 Jun 2018 09:41:00 +0200https://kim.grytoyr.io/posts/2018/06/change-file-encoding-in-vim/
<p>This is for my own reference, I always forget how to do this..</p>
<p><strong>Once</strong><br>
<code>:w[rite] ++enc=utf-8 [filename]</code></p>
<p><strong>Persistently</strong><br>
<code>:set fileencoding=utf-8</code></p>
Basic server setup (Ubuntu)https://kim.grytoyr.io/posts/2018/02/basic-server-setup-ubuntu/
Mon, 12 Feb 2018 20:51:00 +0200https://kim.grytoyr.io/posts/2018/02/basic-server-setup-ubuntu/
<blockquote>
<p><strong>Disclaimer:</strong> This short guide is basically just a reminder to myself, where most of the content is based on Digital Ocean's <a href="https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04">Initial Server Setup with Ubuntu 16.04</a> and my own memory. There are some important steps that aren't included in this guide. If you're new to Linux or Ubuntu, I suggest that you read Digital Ocean's guide instead.</p>
</blockquote>
<p>All commands in this guide (unless otherwise stated) assume you are currently logged in as root.</p>
<h2 id="add-a-user">Add a user</h2>
<p>We don't want to use the <em>root</em> user when logging in to our server, so we need to create a new user.</p>
<blockquote>
<p>If you're only using keys to log in to your server (which you should), you can choose to not create a password for the new user using the <code>--disabled-password</code> option. Please note that you'll be unable to use <code>sudo</code> with this user unless you also perform the steps in <a href="https://kim.grytoyr.io/posts/2018/02/disabling-password-for-sudo-in-ubuntu/">this post</a>.</p>
</blockquote>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">adduser &lt;user&gt; <span style="color:#f92672">[</span>--disabled-password<span style="color:#f92672">]</span>
</code></pre></div><h2 id="root-privileges">Root privileges</h2>
<p>Our newly created user will typically need root privileges:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">usermod -aG sudo &lt;user&gt;
</code></pre></div><p>Now, if you want this user to be able to use <code>sudo</code> without the need for a password, <a href="https://kim.grytoyr.io/posts/2018/02/disabling-password-for-sudo-in-ubuntu/">here's how to accomplish this</a>.</p>
<h2 id="public-key-authentication">Public Key Authentication</h2>
<p>At this point we're ready to copy the public keys to the newly created user's <em>.ssh</em> folder. I won't cover all the details of this process in this guide. Please refer to the previously mentioned Digital Ocean guide if you're uncertain of how to do this.</p>
<p>We will need to set the correct permissions:</p>
<blockquote>
<p><strong>Note:</strong> These commands assume you are logged in as your newly created user.</p>
</blockquote>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">chmod <span style="color:#ae81ff">700</span> ~/.ssh
chmod <span style="color:#ae81ff">600</span> ~/.ssh/authorized_keys
</code></pre></div><p>Also make sure that these files are owned by the user we just created.</p>
<h2 id="disable-password-authentication">Disable password authentication</h2>
<p>On new Digital Ocean droplets, this step is usually already done when creating the droplet. Just to make sure, we'll check to see if the file <code>/etc/ssh/sshd_config</code> contains the following lines and that none of them are commented out:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
</code></pre></div><p>If you did any changes, reload the SSH daemon:</p>
<pre><code class="language-shel" data-lang="shel">systemctl reload sshd
</code></pre><blockquote>
<p><strong>Note:</strong> Try connecting to your server in a separate tab/window before disconnecting.</p>
</blockquote>
<h2 id="firewall">Firewall</h2>
<p>We need to make sure that our server doesn't expose unnecessary ports and protocols, so lets configure UFW in the most basic way possible:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">ufw allow OpenSSH
ufw enable
</code></pre></div><blockquote>
<p><strong>Note:</strong> At this point you should once more verify that you're able to log in to your server.</p>
</blockquote>
<p>This concludes this short guide on how to perform the initial steps when creating a new Ubuntu (16.04) server.</p>
Disabling password for sudo in Ubuntuhttps://kim.grytoyr.io/posts/2018/02/disabling-password-for-sudo-in-ubuntu/
Fri, 09 Feb 2018 22:12:00 +0200https://kim.grytoyr.io/posts/2018/02/disabling-password-for-sudo-in-ubuntu/
<p>Disabling the password needed for <code>sudo</code> for a specific user is very easy in Ubuntu. This method applies to Ubuntu 16.04, but probably also other versions of Ubuntu and maybe even other distros.</p>
<p>First, run the following command:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">sudo visudo
</code></pre></div><blockquote>
<p><strong>Note:</strong> If this is the first time you're running this command, you'll most likely be presented with a list of editors to choose from. Choose the one you're most comfortable with.</p>
</blockquote>
<p>Then enter the following line <strong>at the end of the file</strong>:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">user ALL<span style="color:#f92672">=</span><span style="color:#f92672">(</span>ALL:ALL<span style="color:#f92672">)</span> NOPASSWD:ALL
</code></pre></div><p>Make sure to replace <em>user</em> with the username of the user you want to allow using <code>sudo</code> without entering a password.</p>
Ludum Dare 39: PowerClickhttps://kim.grytoyr.io/posts/2017/07/ludum-dare-39-powerclick/
Sun, 30 Jul 2017 22:44:04 +0200https://kim.grytoyr.io/posts/2017/07/ludum-dare-39-powerclick/
<p>I attended the online game compo <a href="http://ldjam.com/events/ludum-dare/39">Ludum Dare 39</a> this weekend. Because of things I wasn't able to start until saturday evening, so I decided to create a very simple game this time.</p>
<p>Last time I created my first 3D game, <a href="https://kim.grytoyr.io/posts/2017/04/ludum-dare-38-parking-zone/">Parking Zone</a>. I spent most of the time creating the 3D models and getting the wheel colliders to work the way I wanted to in Unity. For LD39, I decided to create a very simple UI based 2D game.</p>
<h2 id="running-out-of-power">«Running out of power»</h2>
<p>This time the theme was «Running out of power». The game only has one scene, and takes place on a virtual mobile phone. The phone's battery is draining constantly, and you can <strong>delay</strong> it from running out of power by clicking various-sized circles showing up at random locations on the screen. The battery level will never increase.</p>
<p>You get points based on various factors, including:</p>
<ul>
<li>The size of the circle</li>
<li>The distance from the previous click</li>
<li>The time you spend between clicks</li>
</ul>
<p>Once the battery level reaches 0%, the game is over. Your highscore is saved.</p>
<p>This Ludum Dare I spent most of the time in Photoshop, creating the mockup phone, the logo and the background.</p>
<h2 id="tools">Tools</h2>
<ul>
<li>Unity 5 Professional</li>
<li>Adobe Photoshop CC</li>
<li>Audacity</li>
<li>Evernote</li>
<li>LMMS (music)</li>
</ul>
<h2 id="summary">Summary</h2>
<p>Although I had less time to spend on this Ludum Dare, I very much enjoyed participating. Looking forward to LD40 already!</p>
<p><strong>Downloads:</strong></p>
<ul>
<li><a href="https://s3.eu-central-1.amazonaws.com/ramlefant-public-files/LudumDare/LD39/PowerClick_Windows.zip">Windows</a></li>
<li><a href="https://s3.eu-central-1.amazonaws.com/ramlefant-public-files/LudumDare/LD39/PowerClick_Mac.zip">Mac</a></li>
<li><a href="https://s3.eu-central-1.amazonaws.com/ramlefant-public-files/LudumDare/LD39/PowerClick_Linux.zip">Linux</a></li>
<li><a href="https://s3.eu-central-1.amazonaws.com/ramlefant-public-files/LudumDare/LD39/WebGL/index.html">WebGL version</a> (play in the browser)</li>
</ul>
<p>The source code is available in a <a href="https://github.com/kimgrytoyr/LD-39-Powerclick">Github repository</a>.</p>
Ludum Dare 38: Parking Zonehttps://kim.grytoyr.io/posts/2017/04/ludum-dare-38-parking-zone/
Mon, 24 Apr 2017 10:24:04 +0200https://kim.grytoyr.io/posts/2017/04/ludum-dare-38-parking-zone/
<figure>
<img src="https://kim.grytoyr.io/images/LD38/parking-zone.png"/> <figcaption>
<h4>The main menu of my game</h4>
</figcaption>
</figure>
<p><a href="https://ldjam.com">Ludum Dare</a> is a game jam/compo that happens three times every year.
The jam lasts for 72 hours and the compo for 48 hours. There are different <a href="https://ldjam.com/events/ludum-dare/rules">rules</a> for the two categories.</p>
<p>This was my first time participating in the event, and I submitted my game to the <strong>compo</strong>. The most important rules of the compo are:</p>
<ul>
<li>You have to work solo</li>
<li>Every asset in the game (code, graphics, sounds etc.) must be created by yourself during the 48 hours</li>
</ul>
<h2 id="a-small-world">&ldquo;A small world&rdquo;</h2>
<p>The theme of LD38 was &ldquo;A small world&rdquo;. I decided to make the game take place on a regular living room table. Here's a breakdown of the different 3D models I created for the game:</p>
<ul>
<li>The room itself</li>
<li>An empty bookshelf that is just standing in the viewport</li>
<li>A table</li>
<li>A car</li>
<li>A trailer</li>
</ul>
<p>I started with the table. It wasn't too hard to make. I created a wood-like texture and mapped the texture to the table. The room and the bookshelf was easy to make.</p>
<p>The car.. I spent probably at least 30% of my time creating the car and the wheels. Once I was finished with that, I spent probably almost the same amount of time making the tires work as they should with Unity's wheel collider. In the beginning they were rotatet 90 degrees once the game started. After placing each individual wheel in an empty game object, everything was working. There is probably an easier way to do this, but I didn't have time to figure it out.</p>
<p>The trailer was fairly simple to make in Blender. I attached it to a vehicle object in Unity and used a hinge joint to make the physics work more or less like in real life.</p>
<p>I've never used the wheel collider in Unity, and I spent a fair amount of time making it work as I wanted to. There are still a few things I have to work out, though. Right now I'm also applying torque to the trailer's wheels, which doesn't really make sense.</p>
<h2 id="tools">Tools</h2>
<p>Here's a breakdown of the different tools I used:</p>
<ul>
<li>Unity</li>
<li>Blender
<ul>
<li>Adobe Photoshop CC</li>
<li>Audacity (engine sound and game over voice)</li>
</ul>
</li>
<li>Audiotool.com (music)
<ul>
<li>Evernote</li>
</ul>
</li>
</ul>
<h2 id="summary">Summary</h2>
<p>It was a really fun and challenging experience. As a beginner with both Unity and Blender, I spent most of the time figuring out how to do some of the most basic things. Time spent in Blender was probably around 60%. I really wanted to spend more time making the game more exciting and fun to play, but I just couldn't fit it in. I probably should have submitted to the jam, which would have given me 24 hours more to work with the game, but since I had other plans for the next day, I didn't see any reason to do so.</p>
<p>I'm already looking forward to the next event.</p>
<h2 id="links">Links</h2>
<p><strong>Ludum Dare entry</strong><br>
<a href="https://ldjam.com/events/ludum-dare/38/parking-zone">https://ldjam.com/events/ludum-dare/38/parking-zone</a></p>
<p><strong>Source code</strong><br>
<a href="https://github.com/kimgrytoyr/LD38---Parking-Zone">https://github.com/kimgrytoyr/LD38---Parking-Zone</a></p>
<p><strong>Downloads</strong></p>
<ul>
<li><a href="https://kim.grytoyr.io/files/LD38/ParkingZone.exe">Windows</a></li>
<li><a href="https://kim.grytoyr.io/files/LD38/Parkingzone.app.zip">Mac</a></li>
<li><a href="https://kim.grytoyr.io/files/LD38/ParkingZone.x86">Linux</a></li>
</ul>
3D model of a bookhttps://kim.grytoyr.io/posts/2017/04/3d-model-of-a-book/
Fri, 14 Apr 2017 00:16:56 +0200https://kim.grytoyr.io/posts/2017/04/3d-model-of-a-book/
<p>I am currently learning how to create 3D models in Blender. My first creation is a simple book.</p>
<p>I started out with a simple cube and transformed it into the book in the pictures. At the moment, the book is just one object.
I'm planning on splitting it into several objects and at some point make an animation of opening the book.</p>
<p><figure>
<img src="https://kim.grytoyr.io/images/3D-book/Book1.png"/> <figcaption>
<h4>3D model of a book, top view</h4>
</figcaption>
</figure>
<figure>
<img src="https://kim.grytoyr.io/images/3D-book/Book2.png"/> <figcaption>
<h4>3D model of a book, bottom view</h4>
</figcaption>
</figure>
</p>
<p>The cover of the book is textured with a simple image I made in Photoshop. The pages are textured with a photo
I took of a real book:
<figure>
<img src="https://kim.grytoyr.io/images/3D-book/PaperPhoto.jpeg"/> <figcaption>
<h4>The origin of the texture used for the pages</h4>
</figcaption>
</figure>
</p>
<p>I am not planning to use this model for anything, my only objective is to learn how to use Blender. I will continue to work on
this book, and I have a list of things I want to accomplish:</p>
<ul>
<li>Smoothing of the back of the book</li>
<li>Adding some text using a texture and UV mapping</li>
<li>Splitting it into several objects</li>
<li>Make the cover texture look more natural</li>
<li>Create an animation of opening the book</li>
</ul>
<p>I may post an updated version of the model at some point.</p>
New website platformhttps://kim.grytoyr.io/posts/2017/04/new-website-platform/
Thu, 13 Apr 2017 01:45:56 +0200https://kim.grytoyr.io/posts/2017/04/new-website-platform/
<p>My website was previously built using <a href="https://jekyllrb.com/">Jekyll</a> and hosted on <a href="https://www.netlify.com/">Netlify</a>. Because of various problems I've had with my Jekyll setup, I decided to go for another static site generator: <a href="https://gohugo.io/">Hugo</a>.</p>
<p>I have been very happy with Netlify. Easy to deploy, integration with Github repos and automatic SSL certificates from <a href="https://letsencrypt.org/">Let's Encrypt</a> - all for free! Despite all this, I wanted to become more familiar with <a href="https://aws.amazon.com/">Amazon Web Services (AWS)</a> and all their products, so I changed my setup so that this site is now hosted in an S3 bucket and distributed using Cloudfront.</p>
<p>So far I'm very happy with the new setup. Hugo is lightning fast and easy to configure. I've created a simple bash script that automates the process of building the site, deploying it to S3 and invalidating the Cloudfront cache.</p>
Resizing windows on linuxhttps://kim.grytoyr.io/2016/01/31/resizing-windows-on-linux/
Sun, 31 Jan 2016 10:18:36 +0000https://kim.grytoyr.io/2016/01/31/resizing-windows-on-linux/
<p>Here’s an easy way to resize windows on Fedora 23 and probably most other Linux distributions:</p>
<ol>
<li>Hold ALT and right click (and hold) with your mouse</li>
<li>Move the mouse to resize</li>
</ol>
<p>Using this method the window will resize as if you hovered your mouse over the nearest corner and resized it manually.</p>
Creating a bootable USB stick on OS Xhttps://kim.grytoyr.io/2016/01/21/creating-a-bootable-usb-stick-on-os-x/
Thu, 21 Jan 2016 10:40:00 +0000https://kim.grytoyr.io/2016/01/21/creating-a-bootable-usb-stick-on-os-x/
<p>Here's a simple way to create a bootable USB stick from a downloaded .ISO file on OS X.</p>
<h2 id="convert-iso-to-img">Convert ISO to IMG</h2>
<p>Open the terminal and type the following command:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">hdiutil convert -format UDRW -o target.img source.iso
</code></pre></div><p>Remember to replace the paths in the previous example.</p>
<h2 id="transfer-to-usb-stick">Transfer to USB stick</h2>
<p><strong>Warning:</strong> This will erase all data on your USB stick.</p>
<p>First, find the correct device node:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">diskutil list
</code></pre></div><p>After you have successfully identified your USB stick, unmount the disk (replace <em>N</em> with the disk number):</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">diskutil unmountDisk /dev/diskN
</code></pre></div><p>Finally, transfer the image to the USB stick (again, replace <em>N</em> with the disk number):</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">sudo dd <span style="color:#66d9ef">if</span><span style="color:#f92672">=</span>target.img of<span style="color:#f92672">=</span>/dev/rdiskN bs<span style="color:#f92672">=</span>1m
</code></pre></div><p>After a short while, depending on the image size, your USB stick will be ready to use as a bootable media.</p>
<p>Source: <a href="http://www.ubuntu.com/download/desktop/create-a-usb-stick-on-mac-osx">http://www.ubuntu.com/download/desktop/create-a-usb-stick-on-mac-osx</a></p>
Trouble booting newer Linux kernels on Asus VivoPC VM42https://kim.grytoyr.io/2016/01/21/trouble-booting-newer-linux-kernels-on-asus-vivopc-vm42/
Thu, 21 Jan 2016 10:40:00 +0000https://kim.grytoyr.io/2016/01/21/trouble-booting-newer-linux-kernels-on-asus-vivopc-vm42/
<p>I recently bought an <a href="https://www.asus.com/Mini-PCs/VivoPC_VM42/">Asus VivoPC VM42</a>
because I wanted a small and simple desktop computer to play around with different
Linux distros. I was able to install Ubuntu 14.04 without problems, but when booting
it for the first time it got stuck with a message from NMI Watchdog saying that
CPU#1 had been stuck for 22 seconds.</p>
<p>I also tried booting Linux Mint and Fedora from a Live USB, but the same thing
happened.</p>
<p>The only thing that was working was booting Ubuntu with kernel 3.19.0-25.</p>
<p>I tried the following:</p>
<ol>
<li>Booting with <code>nomodeset</code></li>
<li>Booting with <code>noacpi</code></li>
<li>Updating the BIOS from version 1008 to 1203</li>
<li>Using legacy BIOS instead of UEFI</li>
<li>Disabling Secure Boot and Fast Boot</li>
<li>A bunch of other things</li>
</ol>
<p>Finally, after several days of searching for a solution, I tried disabling all
the on-board controllers:</p>
<ul>
<li>HD Audio</li>
<li>WLAN</li>
<li>Bluetooth</li>
</ul>
<p>Now I could boot everything, including newer kernels, Linux Mint and Fedora. I have yet to figure out which one was causing the problem, but I will update this post whenever I do.</p>
<p><strong>Update:</strong> Turned out it was the WLAN controller that caused this issue.</p>
<p>I should of course have tried this at an earlier stage, but since the older version
of the kernel was working, I figured it couldn't be because of those BIOS settings.</p>
<p>I was wrong.</p>
Useful git tipshttps://kim.grytoyr.io/2015/08/09/useful-git-tips/
Sun, 09 Aug 2015 17:03:00 +0000https://kim.grytoyr.io/2015/08/09/useful-git-tips/
<p>This is a collection of useful git commands, aliases, tips and tricks that I've come across or been using. Feel free to contribute to this collection by adding a comment below.</p>
<h2 id="aliases-for-ignoring-files">Aliases for ignoring files</h2>
<p>To prevent changes in already-commited files from being commited, you can update your index with the <code>--assume-unchaged</code> flag for the files that you don't want to commit. Here are a couple of useful aliases for dealing with this.</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">ignore <span style="color:#f92672">=</span> !git update-index --assume-unchanged
unignore <span style="color:#f92672">=</span> !git update-index --no-assume-unchanged
ignored <span style="color:#f92672">=</span> !git ls-files -v | grep ^<span style="color:#f92672">[</span>a-z<span style="color:#f92672">]</span>
</code></pre></div><p>With these aliases you can use <code>git ignore &lt;file&gt;</code> to ignore a file, <code>git unignore &lt;file&gt;</code> to unignore a file, and <code>git ignored</code> to list files that are currently being ignored.</p>
<p><strong>Warning:</strong> Adding a file directly with <code>git add &lt;file&gt;</code> will add the file regardless of this flag.</p>
<p>Source: <a href="http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html">http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html</a> (comments)</p>
<h2 id="commit-partial-changes">Commit partial changes</h2>
<p>If you want to only commit certain changes in a file, you can use the following command:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git add -p &lt;files&gt;
</code></pre></div>
Basic usage of git-svnhttps://kim.grytoyr.io/2015/08/09/basic-usage-of-git-svn/
Sun, 09 Aug 2015 15:13:36 +0000https://kim.grytoyr.io/2015/08/09/basic-usage-of-git-svn/
<p>This is a small guide I wrote for my own convenience when I recently was converting an SVN repository to a Git repository. I've published it here so that I can easily look up the things I need to remember..</p>
<p>I've found most of these examples in the excellent official <a href="http://git-scm.com/docs/git-svn">git-svn documentation</a>.</p>
<h2 id="cloning-the-svn-repository">Cloning the SVN repository</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git svn clone &lt;repo-url&gt;
</code></pre></div><h2 id="adding-another-remote">Adding another remote</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git remote add &lt;remote-name&gt; &lt;remote-url&gt;
</code></pre></div><h2 id="fetching-and-rebasing-changes-from-svn">Fetching and rebasing changes from SVN</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git svn fetch <span style="color:#f92672">&amp;&amp;</span> git svn rebase
</code></pre></div><p>Note that the git-svn documentation has a section discussing rebase vs pull/merge:</p>
<blockquote>
<p>Prefer to use git svn rebase or git rebase, rather than git pull or git merge to synchronize unintegrated commits with a git svn branch. Doing so will keep the history of unintegrated commits linear with respect to the upstream SVN repository and allow the use of the preferred git svn dcommit subcommand to push unintegrated commits back into SVN.</p>
</blockquote>
<h2 id="doing-work-and-pushing-to-svn">Doing work and pushing to SVN</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git add &lt;file&gt;
git commit -m <span style="color:#e6db74">&#34;&lt;commit message&gt;&#34;</span>
git svn dcommit <span style="color:#75715e"># This will push your changes to the SVN repository</span>
</code></pre></div><h2 id="pushing-to-other-remotes">Pushing to other remotes</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git push &lt;remote-name&gt;
</code></pre></div><h2 id="see-what-will-be-pushed-to-svn">See what will be pushed to SVN</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git diff git-svn HEAD <span style="color:#75715e"># Assuming your remote SVN branch is called git-svn</span>
</code></pre></div><p><a href="http://stackoverflow.com/a/9776318/1094451">http://stackoverflow.com/a/9776318/1094451</a></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git svn dcommit --dry-run
</code></pre></div><p><a href="http://stackoverflow.com/a/6040113/1094451">http://stackoverflow.com/a/6040113/1094451</a></p>
Deleting rows with a LEFT JOIN in MySQLhttps://kim.grytoyr.io/2015/08/09/deleteing-rows-with-a-left-join-in-mysql/
Sun, 09 Aug 2015 11:28:36 +0000https://kim.grytoyr.io/2015/08/09/deleteing-rows-with-a-left-join-in-mysql/
<p>This is something I don't do that often, and I always forget the correct syntax. Thus this post.</p>
<p>Let's say you have a table <strong>images</strong> and a table <strong>users</strong>. Now you want to delete all rows in table <strong>images</strong> that are associated with rows in the table <strong>users</strong> that are marked as deleted.</p>
<p>First, I usually do a visual inspection of the rows that will be deleted:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sql" data-lang="sql"><span style="color:#66d9ef">SELECT</span> i.<span style="color:#f92672">*</span> <span style="color:#66d9ef">FROM</span> images i <span style="color:#66d9ef">LEFT</span> <span style="color:#66d9ef">JOIN</span> users u <span style="color:#66d9ef">ON</span> i.user_id <span style="color:#f92672">=</span> u.id <span style="color:#66d9ef">WHERE</span> u.deleted <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</code></pre></div><p>The rows returned by this query are the rows that will be deleted when you run the following query:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sql" data-lang="sql"><span style="color:#66d9ef">DELETE</span> i <span style="color:#66d9ef">FROM</span> images i <span style="color:#66d9ef">LEFT</span> <span style="color:#66d9ef">JOIN</span> users u <span style="color:#66d9ef">ON</span> i.user_id <span style="color:#f92672">=</span> u.id <span style="color:#66d9ef">WHERE</span> u.deleted <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;
</code></pre></div><p>They key part here is to specify which table you want to delete from. In this case it's the table <code>i</code>, which is the <code>images</code> table.</p>
mutt tips & trickshttps://kim.grytoyr.io/2015/06/21/mutt-tips-and-tricks/
Sun, 21 Jun 2015 00:10:00 +0000https://kim.grytoyr.io/2015/06/21/mutt-tips-and-tricks/
<p>I've been using <a href="http://www.mutt.org/">mutt</a> <a href="https://kim.grytoyr.io/posts/email/2015/06/20/my-mutt-setup.html">with offlineimap and msmtp</a> (dead link, coming soon.) for a while now, and I want to use
this post to collect some features and tips that I've found myself often searching for.</p>
<ol>
<li><a href="#finding-messages">Finding messages in the current folder</a>
<ul>
<li><a href="#common-flags">Common flags</a></li>
</ul>
</li>
<li><a href="#tagging-messages">Tagging messages and doing bulk actions</a>
<ul>
<li><a href="#untagging">Untagging messages</a></li>
</ul>
</li>
<li><a href="#changing-pgp-signature-filename">Changing the filename of the PGP signature attachment</a></li>
<li><a href="#from-specific-signatures">&ldquo;From&rdquo;-specific signatures</a></li>
</ol>
<h2 id="a-namefinding-messagesa-finding-messages-in-the-current-folder"><a name="finding-messages"></a> Finding messages in the current folder</h2>
<p>The default keybinding for searching the current folder is <code>l</code>. After you've
entered search/limiting mode, you can use a wide variety of combinations of
flags and regular expressions to match messages:</p>
<blockquote>
<p>Note that limiting only matches the subject and the sender's name by default.</p>
</blockquote>
<h1 id="a-namecommon-flagsacommon-flags"><a name="common-flags"></a>Common flags</h1>
<p><code>~N</code> New/unread messages</p>
<p><code>~F</code> Flagged messages</p>
<p><code>~B</code> Search the whole message, not only subject and sender's name</p>
<p><code>~A</code> All messages (you can also use <code>all</code>)</p>
<p>See the <a href="http://www.mutt.org/doc/manual/manual-4.html#ss4.2">official mutt documentation</a> for a full list of available patterns.</p>
<h2 id="a-nametagging-messagesatagging-messages"><a name="tagging-messages"></a>Tagging messages</h2>
<p>A common thing to do is to tag/mark all messages meeting certain criterias.
This is very easy to do in <a href="http://www.mutt.org/">mutt</a> using the <code>tag-pattern</code> function. By
default, this function is bound to <code>T</code> (that's shift+t). You can then use the
same flags and regular expressions as you can when limiting messages.</p>
<blockquote>
<p>tag-pattern only selects messages in the current folder/mailbox</p>
</blockquote>
<p>After tagging messages, you'll most likely want to do something with them. This
is where the <code>tag-prefix</code> operator comes into play. This operator tells <a href="http://www.mutt.org/">mutt</a>
to apply the next operation to all tagged messages. The default keybinding for
<code>tag-prefix</code> is <code>;</code> (semicolon).</p>
<p>Here's an example of how to tag all unread messages and mark them as read:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">T <span style="color:#75715e"># Invokes the tag-pattern function</span>
~N <span style="color:#75715e"># Tags all unread messages</span>
; <span style="color:#75715e"># tag-prefix operator, next operation will be applied to all tagged messages</span>
W <span style="color:#75715e"># Clear flag</span>
N <span style="color:#75715e"># Clear the N (unread) flag</span>
</code></pre></div><h1 id="a-nameuntaggingauntagging-messages"><a name="untagging"></a>Untagging messages</h1>
<p>In the beginning I often found myself searching for how to untag messages. It can be done the same as you tag messages, except that you have to use CTRL instead of SHIFT: <code>^t &lt;pattern&gt;</code>. To untag all messages, type <code>^t all</code>.</p>
<h2 id="a-namechanging-pgp-signature-filenameachanging-the-pgp-signature-attachments-filename"><a name="changing-pgp-signature-filename"></a>Changing the PGP signature attachment's filename</h2>
<p>When using <a href="http://www.mutt.org/">mutt</a> with PGP, the default filename of the signature attachment
is <code>noname</code>. Although this is a commonly used filename, I personally want it to
be named <code>signature.asc</code>. To be able to do this, you'll need to install <a href="http://www.mutt.org/">mutt</a>
with the <code>pgp-verbose-mime-patch</code>. I've covered how to install <a href="http://www.mutt.org/">mutt</a> on Mac
OS X with this patch in the post <a href="https://kim.grytoyr.io/posts/email/2015/06/20/my-mutt-setup.html">My mutt setup</a> (dead link, coming soon).</p>
<p>After you've installed <a href="http://www.mutt.org/">mutt</a> with this patch, it's very simple to change the
signature attachment's filename. All you have to do is add the following line to
your <code>.muttrc</code>:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">set pgp_mime_signature_filename <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;signature.asc&#39;</span>
</code></pre></div><h2 id="a-namefrom-specific-signaturesafrom-specific-signatures"><a name="from-specific-signatures"></a>&quot;From&rdquo;-specific signatures</h2>
<p>I have different email addresses based on what &ldquo;role&rdquo; I have. One (with several aliases) is for personal stuff, one is for work related stuff and one is for my freelance company. I'd like <a href="http://www.mutt.org/">mutt</a> to change my signature based on which address I send the email from. This is also fairly easy to accomplish. Just add the following line to <code>.muttrc</code> for each account you would like a specific signature for:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">send-hook <span style="color:#e6db74">&#34;~f from@address1.com&#34;</span> <span style="color:#e6db74">&#39;set signature=~/.mutt/signature_for_address1&#39;</span>
</code></pre></div><p>This will tell <a href="http://www.mutt.org/">mutt</a> that <em>&ldquo;whenever I send a message from
<code>from@address1.com</code>, use the signature in the file
<code>~/.mutt/signature_for_address1</code>&rdquo;</em>.</p>
<p>That's it for now. I'll continue to add useful mutt tips to this post.</p>
locationpicker.jshttps://kim.grytoyr.io/2015/06/14/locationpicker.js/
Sun, 14 Jun 2015 16:40:00 +0000https://kim.grytoyr.io/2015/06/14/locationpicker.js/
<p>locationpicker.js is a simple-to-use jQuery plugin that allows you to select a location on a map and receive the coordinates using a callback function. It also supports searching for a location based on an address.</p>
<h2 id="repository">Repository</h2>
<p>To download the latest version of locationpicker.js, visit the repository:</p>
<p><a href="https://bitbucket.org/kimgrytoyr/locationpicker.js/src">https://bitbucket.org/kimgrytoyr/locationpicker.js/src</a></p>
<h2 id="examples">Examples</h2>
<p>Here are two live examples of how locationpicker.js works.</p>
<p><a href="http://dev.kimgrytoyr.com/locationpicker.js/example/">Modal window (with address search)</a></p>
<p><a href="http://dev.kimgrytoyr.com/locationpicker.js/example/index_fullscreen.html">Fullscreen</a></p>
<h2 id="requirements">Requirements</h2>
<p>locationpicker.js requires <a href="http://jquery.com/">jQuery</a> and the <a href="https://www.google.com/intx/en_uk/work/mapsearth/products/mapsapi.html">Google Maps API</a> to work.</p>
<h2 id="usage">Usage</h2>
<p>These are the scripts you need to include in your HTML file:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html">&lt;<span style="color:#f92672">script</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js&#34;</span>&gt;&lt;/<span style="color:#f92672">script</span>&gt;
&lt;<span style="color:#f92672">script</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;//maps.google.com/maps/api/js?sensor=false&amp;libraries=places&#34;</span>&gt;&lt;/<span style="color:#f92672">script</span>&gt;
&lt;<span style="color:#f92672">script</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;js/locationpicker.js&#34;</span>&gt;&lt;/<span style="color:#f92672">script</span>&gt;
</code></pre></div><p>In addition, you'll need to insert a container that will hold the actual map from Google Maps:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html">&lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;myMap&#34;</span>&gt;&lt;/<span style="color:#f92672">div</span>&gt;
</code></pre></div><p>The map container can be styled using CSS.</p>
<p>The last thing you need to do is to load the locationpicker.js plugin:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html">&lt;<span style="color:#f92672">script</span>&gt;
<span style="color:#a6e22e">$</span>(<span style="color:#e6db74">&#39;#myMap&#39;</span>).<span style="color:#a6e22e">locationpicker</span>({ <span style="color:#a6e22e">options</span> });
&lt;/<span style="color:#f92672">script</span>&gt;
</code></pre></div><h2 id="options">Options</h2>
<p>You can configure locationpicker.js with a few options. Here are the defaults:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#a6e22e">location</span><span style="color:#f92672">:</span> {
<span style="color:#a6e22e">latitude</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">69.675366</span>,
<span style="color:#a6e22e">longitude</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">18.975428</span>
},
<span style="color:#a6e22e">minRadius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">15</span>,
<span style="color:#a6e22e">maxRadius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">300</span>,
<span style="color:#a6e22e">radius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">150</span>,
<span style="color:#a6e22e">zoom</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">15</span>,
<span style="color:#a6e22e">zoomLevelAfterAddressResult</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">15</span>,
<span style="color:#a6e22e">markerTitle</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;Dra markøren til uteposten&#34;</span>,
<span style="color:#a6e22e">draggable</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span>,
<span style="color:#a6e22e">clickable</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span>,
<span style="color:#a6e22e">mapType</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">google</span>.<span style="color:#a6e22e">maps</span>.<span style="color:#a6e22e">MapTypeId</span>.<span style="color:#a6e22e">NORMAL</span>,
<span style="color:#a6e22e">mapTypeControl</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span>,
<span style="color:#a6e22e">zoomControl</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span>,
<span style="color:#a6e22e">panControl</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span>,
<span style="color:#a6e22e">streetViewControl</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">false</span>,
<span style="color:#a6e22e">circleOptions</span><span style="color:#f92672">:</span> {
<span style="color:#a6e22e">strokeColor</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;#0000FF&#34;</span>,
<span style="color:#a6e22e">strokeOpacity</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0.45</span>,
<span style="color:#a6e22e">strokeWeight</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">2</span>,
<span style="color:#a6e22e">fillColor</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;#0000FF&#34;</span>,
<span style="color:#a6e22e">fillOpacity</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0.10</span>,
<span style="color:#a6e22e">editable</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span>
},
<span style="color:#a6e22e">afterLoad</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">currentLocation</span>, <span style="color:#a6e22e">radius</span>) {},
<span style="color:#a6e22e">afterChange</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">currentLocation</span>, <span style="color:#a6e22e">radius</span>) {},
</code></pre></div><p><strong>location { latitude, longitude }</strong> (default: 69.675366, 18.975428)
The coordinates that will be loaded when the map is first displayed.</p>
<p><strong>minRadius</strong> (default: 15)
The minimum radius (in meters) that the user can set.</p>
<p><strong>maxRadius</strong> (default: 300)
The maximum radius (in meters) that the user can set.</p>
<p><strong>radius</strong> (default: 150)
The radius (in meters) that will be used when the map is first displayed.</p>
<p><strong>zoom</strong> (default: 15)
The zoom level that will be used when the map is first displayed.</p>
<p><strong>zoomLevelAfterAddressResult</strong> (default: same as <code>zoom</code>)
After a successful address search, the map's zoom level will be reset to the value of this parameter. To disable this behavior, set the value to <code>false</code>.</p>
<p><strong>draggable</strong> (default: true)
If set to false, dragging the map to pan will not be possible.</p>
<p><strong>clickable</strong> (default: true)
If set to true, the user will be able to change location only by clicking on the map. This will also change the location when double clicking to zoom in, so you can consider setting it to false.</p>
<p><strong>mapType</strong> (default: google.maps.MapTypeId.HYBRID)
The map type to use. Valid options:</p>
<ul>
<li>google.maps.MapTypeId.ROADMAP (normal map)</li>
<li>google.maps.MapTypeId.SATELITTE (satellite map)</li>
<li>google.maps.MapTypeId.HYBRID (normal + satellite)</li>
<li>google.maps.MapTypeId.TERRAIN (shows terrain info)</li>
</ul>
<p><strong>mapTypeControl</strong> (default: true)
If set to false, the user will not be able to change the mapType.</p>
<p><strong>zoomControl</strong> (default: true)
If set to false, the zoom controls will be hidden.</p>
<p><strong>panControl</strong> (default: true)
If set to false, the pan controls will be hidden.</p>
<p><strong>streetViewControl</strong> (default: false)
If set to true, street view control will be shown.</p>
<p><strong>circleOptions { .. }</strong>
Options:</p>
<ul>
<li>strokeColor: The color of the stroke around the radius circle.</li>
<li>strokeOpacity: The opacity of the stroke around the radius circle</li>
<li>strokeWeight: The weight/width of the stroke around the radius circle</li>
<li>fillColor: The color of the background fill of the radius circle</li>
<li>fillOpacity: The opacity of the background fill of the radius circle</li>
<li>editable: true|false (true will allow the user to change radius size by dragging the edges of the radius circle)</li>
</ul>
<p><strong>markerTitle</strong> (default: Dra markøren)
The title that will be displayed when the mouse is hovered over the marker.</p>
<p><strong>afterLoad:</strong> function(currentLocation, radius)
A callback function that is called after the initial load of the map. <code>currentLocation</code> is an object with the properties <code>latitude</code> and <code>longitude</code>. <code>radius</code> contains the current radius.</p>
<p><strong>afterChange:</strong> function(currentLocation, radius)
A callback function that is called every time the location or radius changes. <code>currentLocation</code> is an object with the properties <code>latitude</code> and <code>longitude</code>. <code>radius</code> contains the current radius.</p>
<h2 id="address-search">Address search</h2>
<p>The plugins also supports searching for a location by providing the address. Here's an example of how to do that:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#a6e22e">$</span>(<span style="color:#e6db74">&#39;#myMap&#39;</span>).<span style="color:#a6e22e">locationpicker</span>(<span style="color:#e6db74">&#39;address&#39;</span>, <span style="color:#e6db74">&#39;Karl Johans gate 1, Oslo, Norway&#39;</span>, <span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">e</span>) {
<span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">noResults</span>) {
<span style="color:#75715e">// No results found, alert the user.
</span><span style="color:#75715e"></span> }
});
</code></pre></div><p>If Google Maps&rsquo; geocoder is able to find a location, the first location returned from Google will be selected in the map. If not, the object <code>e</code> will have a property called <code>noResults</code> with the value <code>true</code>.</p>
<p><strong>Note:</strong> If a location is found, the map's zoom level will be reset to the value provided in the config parameter <code>zoomLevelAfterAddressResult</code> if it's not set to <code>false</code>.</p>
Using launchctl on Mac OSX 10.10 to run a script periodicallyhttps://kim.grytoyr.io/2015/06/14/using-launchctl-on-mac-osx-10-10/
Sun, 14 Jun 2015 15:26:36 +0000https://kim.grytoyr.io/2015/06/14/using-launchctl-on-mac-osx-10-10/
<p>Lately I've been playing around with <a href="http://www.mutt.org/">mutt</a>, a <em>&ldquo;small but
powerful text-based email client for Unix operating systems&rdquo;</em> and
<a href="http://offlineimap.org/">offlineimap</a>, a software that downloads your mailbox
as a local Maildir.</p>
<p>After I finally got everything set up (easier said than done), I needed a way to
make offlineimap synchronize my mailbox periodically. Apple recommends using <strong>launchctl</strong>
instead of crontab. The following example shows how to run <strong>offlineimap</strong> in quiet mode every two minutes:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#75715e">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
<span style="color:#75715e">&lt;!DOCTYPE plist PUBLIC &#34;-//Apple//DTD PLIST 1.0//EN&#34; &#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&#34;&gt;</span>
<span style="color:#f92672">&lt;plist</span> <span style="color:#a6e22e">version=</span><span style="color:#e6db74">&#34;1.0&#34;</span><span style="color:#f92672">&gt;</span>
<span style="color:#f92672">&lt;dict</span><span style="color:#f92672">&gt;</span>
<span style="color:#f92672">&lt;key</span><span style="color:#f92672">&gt;</span>Label<span style="color:#f92672">&lt;/key&gt;</span>
<span style="color:#f92672">&lt;string</span><span style="color:#f92672">&gt;</span>com.kimgrytoyr.offlineimap.plist<span style="color:#f92672">&lt;/string&gt;</span>
<span style="color:#f92672">&lt;key</span><span style="color:#f92672">&gt;</span>ProgramArguments<span style="color:#f92672">&lt;/key&gt;</span>
<span style="color:#f92672">&lt;array</span><span style="color:#f92672">&gt;</span>
<span style="color:#f92672">&lt;string</span><span style="color:#f92672">&gt;</span>/usr/local/bin/offlineimap<span style="color:#f92672">&lt;/string&gt;</span>
<span style="color:#f92672">&lt;string</span><span style="color:#f92672">&gt;</span>-u<span style="color:#f92672">&lt;/string&gt;</span>
<span style="color:#f92672">&lt;string</span><span style="color:#f92672">&gt;</span>quiet<span style="color:#f92672">&lt;/string&gt;</span>
<span style="color:#f92672">&lt;/array&gt;</span>
<span style="color:#f92672">&lt;key</span><span style="color:#f92672">&gt;</span>StartInterval<span style="color:#f92672">&lt;/key&gt;</span>
<span style="color:#f92672">&lt;integer</span><span style="color:#f92672">&gt;</span>120<span style="color:#f92672">&lt;/integer&gt;</span>
<span style="color:#f92672">&lt;/dict&gt;</span>
<span style="color:#f92672">&lt;/plist&gt;</span>
</code></pre></div><p>This file is basically an XML file, but the extension you must use is <code>.plist</code>. You would typically call it something like <em>com.yourname.scriptname.plist</em>. Place it in the folder <code>~/Library/LaunchAgents/</code>, and make sure you replace <em>yourname</em> and <em>scriptname</em> with something relevant.</p>
<p>When you've saved the file to the specified location, type the following to load it into launchctl:</p>
<p><code>launchctl load ~/Library/LaunchAgents/com.yourname.scriptname.plist</code></p>
<p>If you ever need to remove it from launchctl, you can type the following:</p>
<p><code>launchctl remove ~/Library/LaunchAgents/com.yourname.scriptname.plist</code></p>
Opening Sublime Text from the command linehttps://kim.grytoyr.io/2014/09/03/opening-sublime-text-from-the-command-line/
Wed, 03 Sep 2014 20:53:36 +0000https://kim.grytoyr.io/2014/09/03/opening-sublime-text-from-the-command-line/
<p>I'm using <a href="http://www.sublimetext.com/3">Sublime Text 3 beta</a> as my text editor. It's fast and lightweight, but at the same time it's very powerful.</p>
<p>Here's how you can open Sublime Text from the command line:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">ln -s /Applications/Sublime<span style="color:#ae81ff">\ </span>Text.app/Contents/SharedSupport/bin/subl /usr/local/bin/subl
</code></pre></div><p>(if you're using Sublime Text 2, just replace the path in the first argument)</p>
<p>If you would rather like to use another name for the command that opens Sublime Text, just change the last part (<code>subl</code>) of this command to whatever you want.</p>
<p>For this to work you must have <code>/usr/local/bin</code> in your $PATH environment variable. To check if it's already there, type this into your command line:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">echo $PATH | grep -q <span style="color:#e6db74">&#34;/usr/local/bin&#34;</span>
</code></pre></div><p>If nothing is returned, you must add <code>/usr/local/bin</code> to $PATH. I'm not going to cover how you do this, because there are probably hundreds of other sites that does.</p>
<p>When everything is set up, you can type any of the following in your terminal:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">subl &lt;filename&gt; <span style="color:#75715e"># Opens a file</span>
subl &lt;foldername&gt; <span style="color:#75715e"># Opens a folder</span>
subl . <span style="color:#75715e"># Opens the current folder</span>
</code></pre></div>
Case-sensitivity problem with Git in OS Xhttps://kim.grytoyr.io/2014/07/09/case-sensitivty-problem-with-git-in-os-x/
Wed, 09 Jul 2014 02:18:36 +0000https://kim.grytoyr.io/2014/07/09/case-sensitivty-problem-with-git-in-os-x/
<p>I've several times experienced problems with files and folders having incorrect case in Git repositories in OS X, so I decided to gather some possible fixes and solutions to this problem. If you have any suggestions or comments, please consider sharing it with me in a comment.</p>
<h2 id="hacks">Hacks</h2>
<p>First off, here's a solution published at <a href="https://coderwall.com/p/mgi8ja">Coderwall.com</a>:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git mv filename filename_tmp
git mv filename_tmp Filename
git commit -m <span style="color:#e6db74">&#34;Set correct case for filename&#34;</span>
</code></pre></div><p>The author mentions that this is a hack and that it could possibly mess up other users&rsquo; repositories, and that a <code>git pull</code> by other users won't include this change.</p>
<p>In a comment to that article, a user suggests the following approach instead:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">git mv --force filename Filename
git commit -m <span style="color:#e6db74">&#34;Set correct case for filename&#34;</span>
</code></pre></div><p>According to the comment, a <code>git pull</code> would now rename the file for other OS X users as well.</p>
<hr>
<h2 id="a-permanent-fix">A permanent fix</h2>
<p>As mentioned in both the article at <a href="https://coderwall.com/p/mgi8ja">Coderwall.com</a>, and by several users in this <a href="http://stackoverflow.com/questions/8904327/case-sensitivity-in-git">Stackexchange post</a>, OS X's filesystem uses a <em>case-preserving</em> format, not a <em>case-sensitive</em> format. There are ways to get around this when working with a repository, though. Both articles suggests creating a <strong>disk image</strong> with a <em>case-sensitive</em> format, more specifically the <strong>Mac OS Extended (Case-sensitive, Journaled)</strong> format.</p>
<p>Here's a slightly rewritten version of the step-by-step list found in the article at <a href="https://coderwall.com/p/mgi8ja">Coderwall.com</a>, explaining how to create such a disk image:</p>
<ol>
<li>Launch Disk Utility</li>
<li>Choose &ldquo;New Image&rdquo;</li>
<li>Enter a name for your volume, e.g &ldquo;Workspace&rdquo;</li>
<li>Set the size to something that will most likely fit your needs</li>
<li>Select <strong>Mac OS Extended (Case-sensitive, Journaled)</strong> in &ldquo;Format&rdquo;.</li>
<li>Select &ldquo;Single Partition - Apple Partition Map&rdquo; in &ldquo;Partitions&rdquo;</li>
<li>Ensure &ldquo;Sparse bundle disk image&rdquo; is set in &ldquo;Image Format&rdquo;.</li>
<li>Save it somewhere on your hard drive</li>
</ol>
<p>The final step is to move any Git repositories to this new disk image. Any problems you've had with case-sensitivity will now be history.</p>
Going statichttps://kim.grytoyr.io/2014/07/08/going-static/
Tue, 08 Jul 2014 23:13:00 +0000https://kim.grytoyr.io/2014/07/08/going-static/
<blockquote>
<p><strong>Update 2018-02-09:</strong> The information in this post is no longer current. Please read <a href="https://kim.grytoyr.io/posts/2017/04/new-website-platform/">this post</a> for information about my current setup.</p>
</blockquote>
<p>My personal homepage has been powered by <a href="https://wordpress.org">Wordpress</a> for several years. There's nothing wrong with Wordpress, it's a mature blogging platform with a plethora of plugins and themes to choose from. Nevertheless, lately I've been wanting to use a static site generator for my personal homepage. Here are some of the reasons why:</p>
<ul>
<li>I want to use Markdown</li>
<li>I want to use my favorite editor when writing</li>
<li>I can easily store my homepage source in a Git repository or in Dropbox</li>
<li>I can easily host it anywhere</li>
</ul>
<p>Now, most of these things can also be accomplished using Wordpress, but I find the concept of using a static site generator quite interesting, so I've decided to give it a go.</p>
<p>I ended up with <a href="http://jekyllrb.com">Jekyll</a>. It's a static site generator written in Ruby, and it seems to be very flexible and quite easy to configure and use. My homepage is now hosted as a Github Page, which means that all of the contents are stored in a public Git repository.</p>
<p>Come back later to learn more about my experience with using Jekyll, as I'll try to post useful articles about how I'm using it.</p>