JeffComputes - Jeff Rimkohttps://www.jeffcomput.es/2022-09-05T00:00:00-04:00website and blog of Jeff Rimkowebsite and blog of Jeff RimkoWindows Bluetooth Add/Remove Device Fix2022-09-05T00:00:00-04:002022-09-05T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2022-09-05:/posts/2022/09/windows-bluetooth-addremove-device-fix/<p>Another entry in the miscellaneous fixes blog series. This fix should help with the following strange behavior on Windows 10 (and possibly 11) under the "Bluetooth & other devices" settings:</p>
<ul>
<li>Clicking on the "Add Bluetooth or other device" causes the "Add a device" window to appear normally but clicking on any option in the window causes it to immediately close without warning.</li>
<li>Attempting to remove a Bluetooth device fails.</li>
</ul>
<p>This behavior may also be accompanied by …</p><p>Another entry in the miscellaneous fixes blog series. This fix should help with the following strange behavior on Windows 10 (and possibly 11) under the "Bluetooth & other devices" settings:</p>
<ul>
<li>Clicking on the "Add Bluetooth or other device" causes the "Add a device" window to appear normally but clicking on any option in the window causes it to immediately close without warning.</li>
<li>Attempting to remove a Bluetooth device fails.</li>
</ul>
<p>This behavior may also be accompanied by an error log entry similar to the following in the Windows Event View under "Windows Logs -> Application":</p>
<div class="highlight"><pre><span></span><code>Faulting application name: ShellExperienceHost.exe, version: 10.0.19041.1865, time stamp: 0xbbdb3e51
Faulting module name: KERNELBASE.dll, version: 10.0.19041.1889, time stamp: 0xe9ede6d6
Exception code: 0xc0000409
Fault offset: 0x000000000010fb62
Faulting process id: 0x4550
Faulting application start time: 0x01d8b897318f0a86
Faulting application path: C:\Windows\SystemApps\ShellExperienceHost_cw5n1h2txyewy\ShellExperienceHost.exe
Faulting module path: C:\Windows\System32\KERNELBASE.dll
Report Id: 0735e762-f2ac-4ca6-8327-a783d9f3b450
Faulting package full name: Microsoft.Windows.ShellExperienceHost_10.0.19041.1320_neutral_neutral_cw5n1h2txyewy
Faulting package-relative application ID: App
</code></pre></div>
<p>The fix for this behavior is to check the "Device Association Service" under Services and make sure it is running. This service is sometimes disabled to optimize video game performance.</p>Acer Aspire VX 15 Shutdown Fix2020-04-18T00:00:00-04:002020-04-18T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2020-04-18:/posts/2020/04/acer-aspire-vx-15-shutdown-fix/<p>Recently ran into an issue where an Acer VX 15 laptop would occasionally shut down. And I don't mean like going through the Windows shutdown process, I mean the laptop would be on one second then immediately off the next. This issue occurred while running on battery and never happened while plugged into the AC adapter.</p>
<p>The only official troubleshooting information I could find were <a href="https://us.answers.acer.com/app/answers/detail/a_id/34843/~/acer-internal-battery-reset">these instructions for resetting the battery</a>. Following these instructions had …</p><p>Recently ran into an issue where an Acer VX 15 laptop would occasionally shut down. And I don't mean like going through the Windows shutdown process, I mean the laptop would be on one second then immediately off the next. This issue occurred while running on battery and never happened while plugged into the AC adapter.</p>
<p>The only official troubleshooting information I could find were <a href="https://us.answers.acer.com/app/answers/detail/a_id/34843/~/acer-internal-battery-reset">these instructions for resetting the battery</a>. Following these instructions had no effect on the issue.</p>
<p>After a bit more searching, found some people that fixed similar issues on different Acer laptop models by tightening the screws on the bottom of the laptop, e.g. <a href="https://www.youtube.com/watch?v=i9rIo2Kj5YM">this YouTube video</a>. Sure enough, every single screw on the bottom of the laptop was loose. Apparently, there is a switch installed on some Acer laptops that detects if the laptop bottom is in place. This switch will disconnect power if the bottom is removed while running on battery. The problem is that the screws will slowly loosen over time due to heating/cooling cycles from normal laptop use. When these screws get loose enough, the switch will trigger the power disconnection. Yikes!</p>
<p>So don't fret if your Acer laptop is suddenly shutting down. You might just have a few screws loose.</p>Python File Iterator Performance2019-10-21T00:00:00-04:002019-10-21T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2019-10-21:/posts/2019/10/python-file-iterator-performance/<p>Often I find myself writing Python scripts to iterate over the files in a directory for fun and profit. This is so common that I wrote a simple helper function in Auxly called <a href="https://auxly.readthedocs.io/en/latest/#auxly.filesys.walkfiles"><code>walkfiles()</code></a>. The performance of <code>walkfiles()</code> always felt kinda sluggish, especially when compared to blazing fast utilities like <a href="https://github.com/sharkdp/fd">fd</a>. Only recently did I learn about <a href="https://docs.python.org/3/library/os.html#os.scandir"><code>os.scandir()</code></a> in the Python standard library which is essentially a more performant <code>os.listdir()</code>. After some benchmarks …</p><p>Often I find myself writing Python scripts to iterate over the files in a directory for fun and profit. This is so common that I wrote a simple helper function in Auxly called <a href="https://auxly.readthedocs.io/en/latest/#auxly.filesys.walkfiles"><code>walkfiles()</code></a>. The performance of <code>walkfiles()</code> always felt kinda sluggish, especially when compared to blazing fast utilities like <a href="https://github.com/sharkdp/fd">fd</a>. Only recently did I learn about <a href="https://docs.python.org/3/library/os.html#os.scandir"><code>os.scandir()</code></a> in the Python standard library which is essentially a more performant <code>os.listdir()</code>. After some benchmarks, the speed improvement from <code>os.scandir()</code> is impressive. Here's the results using Python 3.7.2 on a decently spec'd Windows 10 laptop:</p>
<ul>
<li>Recursively iterating though all 107,000 files under a directory using <code>walkfiles()</code> from Auxly 0.6.4 which was implemented using <code>os.walk()</code>:<ul>
<li>Five samples (seconds) = 9.96875, 9.796875, 9.421875, 9.453125, 9.8125</li>
<li>Average (seconds) = 9.690625</li>
</ul>
</li>
<li>Same test using refactored <code>walkfiles()</code> implemented using <code>os.scandir()</code>:<ul>
<li>Five samples (seconds) = 2.359375, 1.90625, 1.859375, 1.71875, 1.734375</li>
<li>Average (seconds) = 1.915625</li>
</ul>
</li>
<li>Using fd to iterate over the same 107,000 files:<ul>
<li>Five samples (seconds) = 0.46875, 0.5, 0.46875, 0.515625, 0.484375</li>
<li>Average (seconds) = 0.4875</li>
</ul>
</li>
<li>Using same file set with regex to iterate over only the 3,600 <code>.txt</code> files using <code>walkfiles()</code> from Auxly 0.6.4 (before refactor):<ul>
<li>Five samples (seconds) = 3.5625, 3.0625, 3.109375, 3.109375, 3.078125</li>
<li>Average (seconds) = 3.184375</li>
</ul>
</li>
<li>Iterating over the 3,600 <code>.txt</code> files with refactored <code>walkfiles()</code>:<ul>
<li>Five samples (seconds) = 2.109375, 1.953125, 1.78125, 1.796875, 1.8125</li>
<li>Average (seconds) = 1.890625</li>
</ul>
</li>
<li>Using fd to iterate over the 3,600 <code>.txt</code> files:<ul>
<li>Five samples (seconds) = 0.03125, 0.03125, 0.0625, 0.078125, 0.046875</li>
<li>Average (seconds) = 0.05</li>
</ul>
</li>
</ul>
<p>Wow, some big differences there. To summarize:</p>
<ul>
<li>Iterating over 107,000 files:<ul>
<li>Auxly 0.6.4 <code>walkfiles()</code> = 9.690625 seconds</li>
<li>Auxly refactored <code>walkfiles()</code> = 1.915625 seconds</li>
<li>fd = 0.4875 seconds</li>
</ul>
</li>
<li>Iterating over 3,600 <code>.txt</code> files in the original 107,000:<ul>
<li>Auxly 0.6.4 <code>walkfiles()</code> = 3.184375 seconds</li>
<li>Auxly refactored <code>walkfiles()</code> = 1.890625 seconds</li>
<li>fd = 0.05 seconds</li>
</ul>
</li>
</ul>
<p>The takeaways here are that <code>os.scandir()</code> is fast. Not fd fast but still not bad. This refactored <code>walkfiles()</code> will be included in an upcoming <a href="https://github.com/jeffrimko/Auxly">Auxly</a> release.</p>Fzf And Windows File Explorer2019-03-02T00:00:00-05:002019-03-02T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2019-03-02:/posts/2019/03/fzf-and-windows-file-explorer/<p>As mentioned in <a href="https://www.jeffcomput.es/posts/2018/03/fzf-to-clipboard-on-windows/">previous</a> <a href="https://www.jeffcomput.es/posts/2019/02/weekly-picks-fzf/">posts</a>, I really like <a href="https://github.com/junegunn/fzf">fzf</a>. If you are a Windows user, here's how you can use <a href="https://www.autohotkey.com/">AutoHotKey</a> and <a href="https://www.launchy.net/">Launchy</a> to search files and folders with fzf directly from File Explorer. The absolute path of the result file/folder will be copied to the system clipboard so it can be pasted into any application.</p>
<p>This AutoHotKey script will open an fzf file/folder search starting at the current File Explorer path:</p>
<div class="highlight"><pre><span></span><code><span class="o">;;</span> <span class="nt">This …</span></code></pre></div><p>As mentioned in <a href="https://www.jeffcomput.es/posts/2018/03/fzf-to-clipboard-on-windows/">previous</a> <a href="https://www.jeffcomput.es/posts/2019/02/weekly-picks-fzf/">posts</a>, I really like <a href="https://github.com/junegunn/fzf">fzf</a>. If you are a Windows user, here's how you can use <a href="https://www.autohotkey.com/">AutoHotKey</a> and <a href="https://www.launchy.net/">Launchy</a> to search files and folders with fzf directly from File Explorer. The absolute path of the result file/folder will be copied to the system clipboard so it can be pasted into any application.</p>
<p>This AutoHotKey script will open an fzf file/folder search starting at the current File Explorer path:</p>
<div class="highlight"><pre><span></span><code><span class="o">;;</span> <span class="nt">This</span> <span class="nt">script</span> <span class="nt">sends</span> <span class="nt">the</span> <span class="nt">currently</span> <span class="nt">File</span> <span class="nt">Explorer</span> <span class="nt">folder</span> <span class="nt">to</span> <span class="nt">fzf</span><span class="o">.</span>
<span class="o">;;</span> <span class="nt">Selected</span> <span class="nt">file</span> <span class="nt">in</span> <span class="nt">fzf</span> <span class="nt">is</span> <span class="nt">has</span> <span class="nt">the</span> <span class="nt">path</span> <span class="nt">copied</span> <span class="nt">to</span> <span class="nt">the</span> <span class="nt">clipboard</span><span class="o">.</span>
<span class="o">;;</span> <span class="nt">NOTE</span><span class="o">:</span> <span class="nt">Runs</span> <span class="nt">once</span> <span class="nt">then</span> <span class="nt">exits</span><span class="o">.</span>
<span class="o">;;</span> <span class="nt">NOTE</span><span class="o">:</span> <span class="nt">Intended</span> <span class="nt">to</span> <span class="nt">be</span> <span class="nt">used</span> <span class="nt">with</span> <span class="nt">Launchy</span><span class="o">.</span>
<span class="o">;;==============================================================;</span>
<span class="o">;;</span> <span class="nt">SECTION</span><span class="o">:</span> <span class="nt">Main</span> <span class="nt">Body</span> <span class="o">;</span>
<span class="o">;;==============================================================;</span>
<span class="nt">if</span> <span class="nt">not</span> <span class="o">(</span><span class="nt">WinActive</span><span class="o">(</span><span class="s2">"ahk_class CabinetWClass"</span><span class="o">))</span> <span class="p">{</span>
<span class="err">Exit</span>
<span class="p">}</span>
<span class="o">;</span> <span class="nt">Copy</span> <span class="nt">the</span> <span class="nt">folder</span> <span class="nt">path</span> <span class="nt">from</span> <span class="nt">explorer</span><span class="o">.</span>
<span class="nt">Send</span> <span class="p">{</span><span class="err">Esc</span><span class="p">}</span>
<span class="nt">Send</span> <span class="o">!</span><span class="nt">d</span>
<span class="nt">Send</span> <span class="o">^</span><span class="nt">c</span>
<span class="nt">Send</span> <span class="p">{</span><span class="err">Esc</span><span class="p">}</span>
<span class="nt">Send</span> <span class="p">{</span><span class="err">Tab</span><span class="p">}</span>
<span class="nt">Send</span> <span class="p">{</span><span class="err">Tab</span><span class="p">}</span>
<span class="o">;</span> <span class="nt">Delay</span> <span class="nt">in</span> <span class="nt">milliseconds</span><span class="o">,</span> <span class="nt">allows</span> <span class="nt">Windows</span> <span class="nt">to</span> <span class="nt">catch-up</span> <span class="nt">since</span> <span class="nt">sometimes</span> <span class="nt">the</span>
<span class="o">;</span> <span class="nt">folder</span> <span class="nt">will</span> <span class="nt">not</span> <span class="nt">be</span> <span class="nt">correct</span> <span class="nt">without</span> <span class="nt">this</span> <span class="nt">delay</span><span class="o">.</span>
<span class="nt">Sleep</span><span class="o">,</span> <span class="nt">333</span>
<span class="o">;</span> <span class="nt">Open</span> <span class="nt">cmd</span><span class="o">,</span> <span class="nt">navigate</span> <span class="nt">to</span> <span class="nt">folder</span> <span class="nt">and</span> <span class="nt">run</span> <span class="nt">fzf</span><span class="o">.</span>
<span class="nt">run</span><span class="o">,</span> <span class="o">%</span><span class="nt">comspec</span><span class="o">%</span> <span class="o">/</span><span class="nt">k</span> <span class="nt">cd</span> <span class="o">/</span><span class="nt">d</span> <span class="s2">"%Clipboard%"</span> <span class="o">&</span> <span class="nt">fzf</span> <span class="o">|</span> <span class="nt">clip</span> <span class="o">&</span> <span class="nt">exit</span><span class="o">,,</span> <span class="nt">max</span>
</code></pre></div>
<p>Configure Launchy so that this script (or a shortcut to the script) will be scanned. Now open up File Explorer to somewhere you'd like to search and trigger the script. Here is an example of searching through the CPython source code and then opening the search result file in gVim:</p>
<div class="responsive-container">
<iframe src="//www.youtube.com/embed/kEUOPUzC0Is" frameborder="0" allowfullscreen></iframe>
</div>Weekly Picks - Fzf2019-02-24T00:00:00-05:002019-02-24T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2019-02-24:/posts/2019/02/weekly-picks-fzf/<p>A super useful software utility is this week's pick.</p>
<h4>Software:</h4>
<ul>
<li><em><a href="https://github.com/junegunn/fzf">Fzf</a></em> - Been using this utility a lot recently and it is a game changer for working in command-line terminals. I frequently use it for searching files/folders and searching through utility help output (e.g. <code>rg --help | fzf</code>). It's great for searching files too, especially in cases where the immediate feedback is helpful (as opposed to using something like grep).</li>
</ul>Weekly Picks - Jump Rope2019-02-17T00:00:00-05:002019-02-17T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2019-02-17:/posts/2019/02/weekly-picks-jump-rope/<p>It's been a while! Hope everyone had a great holiday season and New Year!</p>
<h4>Misc:</h4>
<ul>
<li><em>Taking Time Off</em> - Sometimes you just need to take some time off. Rest, relax, and enjoy life!</li>
<li><em>Jump Rope</em> - When you're done taking some time off, why not try some exercise? Cardio has been the bane of my exercise world forever but I'm hoping to change that this year. After a few weeks of jumping rope everyday, I'm seeing results …</li></ul><p>It's been a while! Hope everyone had a great holiday season and New Year!</p>
<h4>Misc:</h4>
<ul>
<li><em>Taking Time Off</em> - Sometimes you just need to take some time off. Rest, relax, and enjoy life!</li>
<li><em>Jump Rope</em> - When you're done taking some time off, why not try some exercise? Cardio has been the bane of my exercise world forever but I'm hoping to change that this year. After a few weeks of jumping rope everyday, I'm seeing results. The time until I collapse into a sweaty wheezing heap has doubled so that's something, right. Allegedly, each minute of jumping rope is equivalent to three minutes of jogging so you gotta love the time efficiency of it.</li>
</ul>Weekly Picks - Hollow Knight2018-12-02T00:00:00-05:002018-12-02T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2018-12-02:/posts/2018/12/weekly-picks-hollow-knight/<p>Haven't had a video game pick in a while. Let's change that :-)</p>
<h4>Games:</h4>
<ul>
<li><em><a href="http://hollowknight.com/">Hollow Knight</a></em> - Still playing through this game but really enjoying it. This game has a beautiful art style and solid Metroidvania gameplay. Definitely worth a try for any fans of the genre.</li>
</ul>Weekly Picks - Hill House2018-11-25T00:00:00-05:002018-11-25T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2018-11-25:/posts/2018/11/weekly-picks-hill-house/<p>Single pick for this week.</p>
<h4>Shows:</h4>
<ul>
<li><em><a href="https://www.netflix.com/title/80189221">The Haunting Of Hill House</a></em> - Recently binged through this show with my wife and we absolutely loved it! The story is engaging and well paced. There is an impressive amount of detail and clever moments in this show and it really feels like a labor of love.</li>
</ul>Nexus 6P Battery Replacement2018-11-14T00:00:00-05:002018-11-14T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2018-11-14:/posts/2018/11/nexus-6p-battery-replacement/<p>Recently replaced the battery in my Nexus 6P smartphone. The process is kind of a pain and there is a lot of great info out there if you plan to try this on your own. Here are a few quick tips from my experience:</p>
<ul>
<li>The most difficult part for me was removing the glass piece that is glued over the camera. Several videos I watched recommended using an X-Acto knife but I ended up breaking …</li></ul><p>Recently replaced the battery in my Nexus 6P smartphone. The process is kind of a pain and there is a lot of great info out there if you plan to try this on your own. Here are a few quick tips from my experience:</p>
<ul>
<li>The most difficult part for me was removing the glass piece that is glued over the camera. Several videos I watched recommended using an X-Acto knife but I ended up breaking the blade tips off. Instead, a simple 1.5 inch razor blade (e.g. <a href="https://www.amazon.com/Stanley-28-510-Razor-Blade-Dispenser/dp/B000BPNP7O">these Stanely blades</a>) worked much better. I placed the entire blade in the groove so that is was perpendicular to the phone and gently worked it under the glass. Work slowly along the length of the piece. A heat gun is handy for softening the glue. Be careful not to crack the glass. Eventually the blade will be able to cut away enough glue to lift the piece.</li>
<li>To remove the back cover of the phone, use the same razor blade and insert it along the case edge near the screen. Look closely at the edges of the screen and notice that there is a thin black gasket or trim piece between the edge of the screen and the case body. Be certain to insert the blade on the outside of the trim piece, closest to the phone body and away from the screen. I have read that doing this wrong can break your screen.</li>
</ul>
<p>Here are some helpful videos I watched before tackling this project:</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=jQOPPF2Fo_Q">Battery replacement video from YouTube channel AkBKukU</a></li>
<li><a href="https://www.youtube.com/watch?v=k6_HrOsQaSQ">Battery replacement video from YouTube channel techguyz708</a></li>
</ul>
<p>Here is the replacement battery I purchased:</p>
<ul>
<li><a href="https://www.ebay.com/itm/2017-NEW-Original-Battery-HB416683ECW-For-Huawei-Google-Nexus-6P-H1512-tools/173279077022?ss">Nexus 6P battery from eBay seller battery_expert</a></li>
</ul>
<p>It's been about a month since replacing my battery and I am happy with the results. My phone easily lasts a day with moderate use where before it would barely last a few hours. My phone no longer shuts down at 30% battery or when taking photos. The replacement process is challenging but well worth it if you have a steady hand and some patience.</p>Weekly Picks - How To Make Everything2018-09-16T00:00:00-04:002018-09-16T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-09-16:/posts/2018/09/weekly-picks-how-to-make-everything/<p>Excellent YouTube channel this week.</p>
<h4>Videos:</h4>
<ul>
<li><em><a href="https://www.youtube.com/channel/UCfIqCzQJXvYj9ssCoHq327g">How To Make Everything</a></em> - Andy, the host of this channel, shows how various everyday objects are made from raw materials. He tries to recreate the objects with varying degrees of success. The videos are funny and educational.</li>
</ul>TV Repair And Heartbreak2018-09-07T00:00:00-04:002018-09-07T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-09-07:/posts/2018/09/tv-repair-and-heartbreak/<p>Ugh. So I tried to repair a large screen LED TV recently. I've never worked on a TV before so this was definitely uncharted territory. The issue was that the LED backlight would not stay on, they would briefly flash when starting the TV and the logo would show but then the screen would go dark.</p>
<p>Ultimately, I was able to repair the backlight but did end up breaking the screen in the process.</p>
<p>:-(</p>
<p>You …</p><p>Ugh. So I tried to repair a large screen LED TV recently. I've never worked on a TV before so this was definitely uncharted territory. The issue was that the LED backlight would not stay on, they would briefly flash when starting the TV and the logo would show but then the screen would go dark.</p>
<p>Ultimately, I was able to repair the backlight but did end up breaking the screen in the process.</p>
<p>:-(</p>
<p>You can watch all of the YouTube videos in the world but none will prepare you for how fragile a 50 inch LCD really is. They are about the thickness of a credit card and will crack internally with the slightest amount of bending. The worst part is that the break might not be visible until a backlight is applied to the screen. The screen will otherwise look normal when dark.</p>
<p>The most heartbreaking part: it turns out I didn't need to remove the screen (which resulted in it breaking).</p>
<p>Now that I've gotten that off my chest, here is some info that might help others who run into the same issue.</p>
<p>The TV is a Proscan PLDED5068A-C. This TV has a TP.MS3393.PC822 main board that handles the LED power supply as well as all the video functions. While researching the problem before disassembling the TV, some sources mentioned that the flashing backlight might be due to a malfunction on one of the LED strips. Supposedly, the LED power supply will shut off if the current draw is not correct.</p>
<p>So I initially suspected that the LED power supply might have been the problem. Unfortunately, I didn't have a easy way to confirm this. The only bench top DC power supply I own only goes up to 30V and these LED arrays require 100V. I couldn't find a service manual for the board either. I thought it would be fairly easy to remove the screen and access the LEDs to test for issues. Removing the screen on a TV is a pain. There many fasteners and spacers involved that must be tracked. After carefully removing the screen, the white reflective backing material around the LEDs must be removed which is effectively glued to the base. Once the LEDs are exposed, there are test points that can be used to apply voltage either to an entire strip or to a single LED. Each LED strip requires 20V and consumes about 80mA. Once I tested all 10 of the LED strips, it was clear that none were malfunctioning and the power supply was the culprit.</p>
<p>After ordering a new board online and installing it, the LEDs did work properly but I learned that the screen was damaged:</p>
<p><img alt="TV Screen" src="/images/tv_screen.jpg" title="TV Screen"></p>
<p>Oh well, live and learn. Ultimately, I don't really know what I could have done differently in hindsight. If I repair another TV, I'll definitely try to test the backlight without remove the screen first.</p>Introducing Ubuild2018-08-29T00:00:00-04:002018-08-29T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-08-29:/posts/2018/08/introducing-ubuild/<p>I recently added a new project to GitHub: <a href="https://github.com/jeffrimko/Ubuild">Ubuild</a></p>
<p>This project addresses something I've wanted for a long time: a way to unify the build process for various software projects. It shouldn't matter if the project is a C++ native application or a web app, there should be a simple interface that takes the guess-work out of the build process. Ubuild provides this unified interface.</p>
<p>A user can review the build options by running the …</p><p>I recently added a new project to GitHub: <a href="https://github.com/jeffrimko/Ubuild">Ubuild</a></p>
<p>This project addresses something I've wanted for a long time: a way to unify the build process for various software projects. It shouldn't matter if the project is a C++ native application or a web app, there should be a simple interface that takes the guess-work out of the build process. Ubuild provides this unified interface.</p>
<p>A user can review the build options by running the <code>_Build.py</code> script alone. Additionally, the script can be run from any child directory using the <code>ubuild</code> command. To run just a specific build option, the user can skip the menu by passing the option to the command (e.g. <code>ubuild c</code>).</p>
<p>I started using Ubuild on a few of my personal projects (including this blog) and love it! I plan on slowly adding more features as appropriate and hope others may find it useful!</p>Weekly Picks - Naddpod2018-08-26T00:00:00-04:002018-08-26T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-08-26:/posts/2018/08/weekly-picks-naddpod/<p>One of my favorite podcasts is the pick this week.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="https://headgum.com/not-another-dandd-podcast">Not Another D&D Podcast</a></em> - An excellent comedy D&D podcast with great characters and an intriguing story. This quickly became one of my all time favorite podcasts after listening to a few episodes. I introduced it to my wife and we are both hooked.</li>
</ul>Weekly Picks - HospitalRun2018-08-19T00:00:00-04:002018-08-19T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-08-19:/posts/2018/08/weekly-picks-hospitalrun/<p>The pick this week is a project with great intentions.</p>
<h4>Software:</h4>
<ul>
<li><em><a href="http://hospitalrun.io/">HospitalRun</a></em> - Free and open source software intended to help administrate hospitals in developing countries. This project is currently looking for maintainers!</li>
</ul>Weekly Picks - Life And Kayaks2018-08-12T00:00:00-04:002018-08-12T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-08-12:/posts/2018/08/weekly-picks-life-and-kayaks/<p>Some random picks this week.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://podcasts.joerogan.net/podcasts/kevin-smith-2">JRE #1123 - Kevin Smith</a></em> - Great talk covering various topics from owning pets to ancient Egypt. Kevin shares some interesting views on life and death following his recent heart attack.</li>
</ul>
<h4>Products:</h4>
<ul>
<li><em>Intex Challenger K1 Inflatable Kayak</em> - Admittedly, I was super skeptical about inflatable kayaks but these things are awesome! My wife and I bought two when they were on sale for about $50 each. They are light, portable, and durable …</li></ul><p>Some random picks this week.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://podcasts.joerogan.net/podcasts/kevin-smith-2">JRE #1123 - Kevin Smith</a></em> - Great talk covering various topics from owning pets to ancient Egypt. Kevin shares some interesting views on life and death following his recent heart attack.</li>
</ul>
<h4>Products:</h4>
<ul>
<li><em>Intex Challenger K1 Inflatable Kayak</em> - Admittedly, I was super skeptical about inflatable kayaks but these things are awesome! My wife and I bought two when they were on sale for about $50 each. They are light, portable, and durable. We've had ours for about 3 years and use them frequently.</li>
</ul>Weekly Picks - Aliens And Doom2018-07-29T00:00:00-04:002018-07-29T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-07-29:/posts/2018/07/weekly-picks-aliens-and-doom/<p>Took a short summer break from picks but I'm back with two goodies.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="https://www.dotnetrocks.com/?show=1548">.NET Rocks!, Episode 1548, Life on Other Planets Geek Out</a></em> - Interesting episode covering the science of detecting life on other planets and the current status of the field.</li>
</ul>
<h4>Videos:</h4>
<ul>
<li><em><a href="https://youtu.be/eBU34NZhW7I">DOOM's Development: A Year of Madness</a></em> - Great talk given by John Romero summarizing the year of development for the original DOOM.</li>
</ul>Debugging Godot With Visual Studio Code2018-07-23T00:00:00-04:002018-07-23T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-07-23:/posts/2018/07/debugging-godot-with-visual-studio-code/<div class="paragraph">
<p>I’ve been playing around with <a href="https://github.com/godotengine/godot">Godot</a> a bit recently, a promising 2D/3D game engine that is completely open source. What most impressed me is that the entire engine is distributed as a 50MB binary. Compared to the 1GB+ installation size for Unity, this is pretty amazing.</p>
</div>
<div class="paragraph">
<p>Here are some quick instructions for debugging the Godot engine itself (i.e. rather than a game created in Godot) using VS Code:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Make sure you have …</p></li></ol></div><div class="paragraph">
<p>I’ve been playing around with <a href="https://github.com/godotengine/godot">Godot</a> a bit recently, a promising 2D/3D game engine that is completely open source. What most impressed me is that the entire engine is distributed as a 50MB binary. Compared to the 1GB+ installation size for Unity, this is pretty amazing.</p>
</div>
<div class="paragraph">
<p>Here are some quick instructions for debugging the Godot engine itself (i.e. rather than a game created in Godot) using VS Code:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Make sure you have all the build requirements. Refer to the build documentation <a href="http://docs.godotengine.org/en/3.0/development/compiling/index.html">available here</a>.</p>
<div class="ulist">
<ul>
<li>
<p>I ran into an issue with the <code>scons</code> command which would throw this error:</p>
<div class="openblock">
<div class="content">
<div class="literalblock">
<div class="content">
<pre>Fatal Python error: Py_Initialize: unable to load the file system codec
ModuleNotFoundError: No module named 'encodings'</pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>To fix, open <code>scons.bat</code> (mine was in <code>C:\Python36\Scripts</code>) and remove/comment the following line: <code>set path=%<sub>dp0;%</sub>dp0..;%path%</code></p>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Clone/download the Godot engine source code from <a href="https://github.com/godotengine/godot">GitHub here</a>.</p>
</li>
<li>
<p>Open a terminal at the root directory of the source code and build using the following command: <code>scons platform=windows target=debug</code></p>
</li>
<li>
<p>In VS Code, open the source code root directory as the project folder.</p>
</li>
<li>
<p>Go to <code>Debug → Open Configurations</code> and enter the following:</p>
<div class="listingblock">
<div class="content">
<pre>{
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) Attach",
"type": "cppvsdbg",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}</pre>
</div>
</div>
</li>
<li>
<p>Set a breakpoint somewhere in the code that you know will be hit. For example, <code>Main::iteration()</code> in <code>main/main.cpp</code>.</p>
</li>
<li>
<p>Run <code>bin/godot.windows.tools.exe</code>.</p>
</li>
<li>
<p>Go to <code>Debug → Start Debugging</code> then type in <code>godot</code> to find the running process and press ENTER.</p>
</li>
<li>
<p>The debugger should now be attached to <code>godot.windows.tools.exe</code> and the breakpoint should be hit.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p><span class="image"><img src="/images/godot_debug.png" alt="godot debug"></span></p>
</div>Weekly Picks - Avengers2018-05-13T00:00:00-04:002018-05-13T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-05-13:/posts/2018/05/weekly-picks-avengers/<p>Big blockbuster movie for this week's pick.</p>
<h4>Movies:</h4>
<ul>
<li><em><a href="https://www.imdb.com/title/tt4154756">Avengers: Infinity War</a></em> - Was massively impressed by this movie. Marvel has really done something special with their cinematic universe and this movie is a remarkable feat.</li>
</ul>Weekly Picks - Jamie King2018-05-07T00:00:00-04:002018-05-07T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-05-07:/posts/2018/05/weekly-picks-jamie-king/<p>Got a YouTube channel for this week's picks.</p>
<h4>Videos:</h4>
<ul>
<li><em><a href="https://www.youtube.com/channel/UCda_RJU9-xB0Hswcrjn4SKw">Jamie King</a></em> - This guy has some great instructional videos on the C# programming language and other computer science topics. I found his channel which searching for C# LINQ videos.</li>
</ul>Easy To Remember Unit Estimates2018-04-30T00:00:00-04:002018-04-30T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-04-30:/posts/2018/04/easy-to-remember-unit-estimates/<p>Here is a short list of ballpark equivalents that are fairly easy to remember. Keep in mind these are only ballpark estimates and are purposefully kept to round numbers. So only use these for quick mental calculations and don't go building spaceships or anything with them.</p>
<ul>
<li>1 cup of water ~ 0.5 pounds</li>
<li>1 pound ~ 0.5 kilograms</li>
<li>1 kilometer ~ 0.5 mile</li>
<li>1 gallon ~ 5 liter</li>
<li>1 liter ~ 5 cups</li>
<li>1 teaspoon ~ 5 milliliters …</li></ul><p>Here is a short list of ballpark equivalents that are fairly easy to remember. Keep in mind these are only ballpark estimates and are purposefully kept to round numbers. So only use these for quick mental calculations and don't go building spaceships or anything with them.</p>
<ul>
<li>1 cup of water ~ 0.5 pounds</li>
<li>1 pound ~ 0.5 kilograms</li>
<li>1 kilometer ~ 0.5 mile</li>
<li>1 gallon ~ 5 liter</li>
<li>1 liter ~ 5 cups</li>
<li>1 teaspoon ~ 5 milliliters</li>
<li>1 meter ~ 1 yard</li>
<li>1 centimeter ~ 0.5 inch</li>
<li>1 atmosphere ~ 10 psi</li>
<li>1 horsepower ~ 1000 Watts</li>
<li>1 BTU ~ 1000 Joules</li>
<li>1 food calorie ~ 5000 Joules</li>
<li>1 gallon gas ~ 100 million Joules</li>
<li>1 square meter of solar light ~ 1000 Watts</li>
<li>1 Joule ~ lift 1 pound 1 foot</li>
<li>1 Joules heat ~ heat 1 gram air +1'C</li>
<li>5 Joules heat ~ heat 1 gram water +1'C</li>
<li>10 Joules ~ lift 1 kilogram 1 meter</li>
<li>speed of sound ~ 1000 feet per second</li>
<li>speed of light ~ 1 billion feet per second</li>
</ul>Weekly Picks - Savage Worlds2018-04-29T00:00:00-04:002018-04-29T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-04-29:/posts/2018/04/weekly-picks-savage-worlds/<p>Something a bit different this week.</p>
<h4>Games:</h4>
<ul>
<li><em><a href="https://en.wikipedia.org/wiki/Savage_Worlds">Savage Worlds</a></em> - This is a generic tabletop role-playing game system that is a lot of fun! Savage Worlds provides the toolkit for a wide variety of scenarios. The rules are fairly simple and the core rule book can be picked up for $10. This system is well suited for one-shots or longer campaigns.</li>
</ul>Weekly Picks - The Ocean Cleanup2018-04-22T00:00:00-04:002018-04-22T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-04-22:/posts/2018/04/weekly-picks-the-ocean-cleanup/<p>Picking a great cause this week.</p>
<h4>Documents:</h4>
<ul>
<li><em><a href="http://podcasts.joerogan.net/podcasts/boyan-slat">JRE #1104 - Boyan Slat</a></em> - Joe interviews Boyan who is leading an effort to clean up the plastic polluting the ocean. Really admire Boyan's dedication and vision.</li>
</ul>
<h4>Organizations:</h4>
<ul>
<li><em><a href="https://www.theoceancleanup.com/">The Ocean Cleanup</a></em> - Boyan's organization dedicated to cleaning the ocean.</li>
</ul>Weekly Picks - Web Systems2018-04-15T00:00:00-04:002018-04-15T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-04-15:/posts/2018/04/weekly-picks-web-systems/<p>Helpful resource for web developers for this week's pick.</p>
<h4>Documents:</h4>
<ul>
<li><em><a href="https://github.com/donnemartin/system-design-primer">The System Design Primer</a></em> - This GitHub document is an amazing resource for getting up to speed on common techniques used when building web systems. For people like me who are fairly new to the web-side of development, resources like this are a godsend since they condense a ton of practical knowledge into a fairly quick read.</li>
</ul>Weekly Picks - Vimium2018-04-08T00:00:00-04:002018-04-08T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-04-08:/posts/2018/04/weekly-picks-vimium/<p>Another useful Chrome extension for this week's pick.</p>
<h4>Software:</h4>
<ul>
<li><em><a href="https://vimium.github.io/">Vimium</a></em> - This Chrome extension adds Vim-like keybindings for common navigation actions. For example, <code>j</code> and <code>k</code> allow for horizontal scrolling. It's effective and fun to use! The <code>f</code> "open link" functionality is amazing!</li>
</ul>Weekly Picks - Finance Podcasts2018-04-01T00:00:00-04:002018-04-01T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-04-01:/posts/2018/04/weekly-picks-finance-podcasts/<p>Couple of finance related podcasts for this week's picks.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://freakonomics.com/podcast/everything-always-wanted-know-money-afraid-ask/">Freakonomics, Episode 298, Everything You Always Wanted to Know About Money (But Were Afraid to Ask)</a></em> - Great episode from last year that was recently re-released. Covers basic finance topics like compound interest and inflation.</li>
<li><em><a href="https://www.theinvestorspodcast.com/episodes/jesse-felder-report-fang-stocks-crypto-bitcoin/">The Investor Podcast, Episode 169, FANG Stocks, Crypto, Central Banks, & Inflation</a></em> - This episode is packed with expert advice. The Netflix discussion near the beginning provides great insight into fundamental analysis of …</li></ul><p>Couple of finance related podcasts for this week's picks.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://freakonomics.com/podcast/everything-always-wanted-know-money-afraid-ask/">Freakonomics, Episode 298, Everything You Always Wanted to Know About Money (But Were Afraid to Ask)</a></em> - Great episode from last year that was recently re-released. Covers basic finance topics like compound interest and inflation.</li>
<li><em><a href="https://www.theinvestorspodcast.com/episodes/jesse-felder-report-fang-stocks-crypto-bitcoin/">The Investor Podcast, Episode 169, FANG Stocks, Crypto, Central Banks, & Inflation</a></em> - This episode is packed with expert advice. The Netflix discussion near the beginning provides great insight into fundamental analysis of a company.</li>
</ul>Italian Verbs2018-03-31T00:00:00-04:002018-03-31T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-03-31:/posts/2018/03/italian-verbs/<p>Here are some word associations that might be helpful to remember some common Italian Verbs:</p>
<ul>
<li><strong>CADERE</strong> - Cady <strong>falls</strong> catlike. - <em>Cady </em><em>cade</em><em> come un gatto.</em></li>
<li><strong>CHIAMARE</strong> - Key-Mary <strong>calls</strong> midday. - <em>Key-Mary </em><em>chiama</em><em> mezzogiorno.</em></li>
<li><strong>CHIEDERE</strong> - Key-Eddy <strong>asks</strong> keenly. - <em>Key-Eddy </em><em>chiede</em><em> acutamente.</em></li>
<li><strong>CHIUDERE</strong> - Key-Eustace <strong>closes</strong> juices. - <em>Key-Eustace </em><em>chiude</em><em> i succhi.</em></li>
<li><strong>DARE</strong> - Darin <strong>gives</strong> dozens. - <em>Darin </em><em>dà</em><em> dozzine.</em></li>
<li><strong>DIVENTARE</strong> - Dante <strong>becomes</strong> dainty. - <em>Dante </em><em>diventa</em><em> delicato.</em></li>
<li><strong>DOVERE</strong> - Dove <strong>owes</strong> two dollars. - <em>Dove </em><em>deve</em><em> due dollari.</em></li>
<li><strong>FARE</strong> - Farah <strong>makes</strong> fairings. - <em>Farah </em><em>fa …</em></li></ul><p>Here are some word associations that might be helpful to remember some common Italian Verbs:</p>
<ul>
<li><strong>CADERE</strong> - Cady <strong>falls</strong> catlike. - <em>Cady </em><em>cade</em><em> come un gatto.</em></li>
<li><strong>CHIAMARE</strong> - Key-Mary <strong>calls</strong> midday. - <em>Key-Mary </em><em>chiama</em><em> mezzogiorno.</em></li>
<li><strong>CHIEDERE</strong> - Key-Eddy <strong>asks</strong> keenly. - <em>Key-Eddy </em><em>chiede</em><em> acutamente.</em></li>
<li><strong>CHIUDERE</strong> - Key-Eustace <strong>closes</strong> juices. - <em>Key-Eustace </em><em>chiude</em><em> i succhi.</em></li>
<li><strong>DARE</strong> - Darin <strong>gives</strong> dozens. - <em>Darin </em><em>dà</em><em> dozzine.</em></li>
<li><strong>DIVENTARE</strong> - Dante <strong>becomes</strong> dainty. - <em>Dante </em><em>diventa</em><em> delicato.</em></li>
<li><strong>DOVERE</strong> - Dove <strong>owes</strong> two dollars. - <em>Dove </em><em>deve</em><em> due dollari.</em></li>
<li><strong>FARE</strong> - Farah <strong>makes</strong> fairings. - <em>Farah </em><em>fa</em><em> le carene.</em></li>
<li><strong>LASCIARE</strong> - Lacie <strong>leaves</strong> last. - <em>Lacie </em><em>lascia</em><em> l'ultima.</em></li>
<li><strong>METTERE</strong> - Matt <strong>places</strong> mats. - <em>Matt </em><em>mette</em><em> le stuoie.</em></li>
<li><strong>PRENDERE</strong> - Preston <strong>takes</strong> pretzels. - <em>Preston </em><em>prende</em><em> i pretzel.</em></li>
<li><strong>TENERE</strong> - Terence <strong>keeps</strong> tents. - <em>Terence </em><em>tiene</em><em> le tende.</em></li>
<li><strong>TROVARE</strong> - Trevor <strong>finds</strong> treasure. - <em>Trevor </em><em>trova</em><em> il tesoro.</em></li>
<li><strong>VENIERE</strong> - Vinny <strong>comes</strong> to Venice. - <em>Vinny </em><em>viene</em><em> a Venezia.</em></li>
</ul>Weekly Picks - Video Speed Controller2018-03-25T00:00:00-04:002018-03-25T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-03-25:/posts/2018/03/weekly-picks-video-speed-controller/<p>Been a while since the last picks post. I've been watching a lot of instructional videos on YouTube recently which inspired this pick.</p>
<h4>Software:</h4>
<ul>
<li><em><a href="https://github.com/igrigorik/videospeed">Video Speed Controller</a></em> - This Chrome extension allows you to quickly increase or decrease the speed of an HTML5 video. Yeah, many sites have similar features built-in to their video players but this extension ramps it up a notch. Try it and you'll see how helpful the keyboard shortcuts are when watching …</li></ul><p>Been a while since the last picks post. I've been watching a lot of instructional videos on YouTube recently which inspired this pick.</p>
<h4>Software:</h4>
<ul>
<li><em><a href="https://github.com/igrigorik/videospeed">Video Speed Controller</a></em> - This Chrome extension allows you to quickly increase or decrease the speed of an HTML5 video. Yeah, many sites have similar features built-in to their video players but this extension ramps it up a notch. Try it and you'll see how helpful the keyboard shortcuts are when watching videos!</li>
</ul>Fzf To Clipboard On Windows2018-03-24T00:00:00-04:002018-03-24T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2018-03-24:/posts/2018/03/fzf-to-clipboard-on-windows/<p>Been using the great <a href="https://github.com/junegunn/fzf">fzf</a> CLI utility lately. Here's a neat trick to copy the search result to the Windows clipboard:</p>
<div class="highlight"><pre><span></span><code><span class="err">fzf | clip</span>
</code></pre></div>
<p>The resulting copied text tends to include a carriage return however. To remove it, either add the <code>--print0</code> option to the <code>fzf</code> command or permanently make it a default option using the <code>FZF_DEFAULT_OPTS</code> environment variable.</p>
<p>The use case for this trick is to quickly find a file within a project, copy the …</p><p>Been using the great <a href="https://github.com/junegunn/fzf">fzf</a> CLI utility lately. Here's a neat trick to copy the search result to the Windows clipboard:</p>
<div class="highlight"><pre><span></span><code><span class="err">fzf | clip</span>
</code></pre></div>
<p>The resulting copied text tends to include a carriage return however. To remove it, either add the <code>--print0</code> option to the <code>fzf</code> command or permanently make it a default option using the <code>FZF_DEFAULT_OPTS</code> environment variable.</p>
<p>The use case for this trick is to quickly find a file within a project, copy the path to the clipboard, and then paste the path into a utility (e.g. text editor) to open it.</p>
<p>The fzf utility can easily be installed on Windows using <a href="https://chocolatey.org/packages/fzf">Chocolatey</a>.</p>Speed Up Ctrlp With Fd2018-03-10T00:00:00-05:002018-03-10T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2018-03-10:/posts/2018/03/speed-up-ctrlp-with-fd/<p><strong>NOTE</strong>: This was originally posted <a href="https://www.reddit.com/r/vim/comments/83h31q/speed_up_ctrlp_with_fd/">on the Vim subreddit here</a>.</p>
<p>Just learned aboug <a href="https://github.com/sharkdp/fd">fd</a> today and was impressed by its speed. Tried using it for ctrlp and it works great! Didn't take any precise measurements but for the CPython code base, stock ctrlp loaded in about 2 seconds, ctrlp+ripgrep about 1 second, and ctlp+fd about 0.5 seconds.</p>
<p>I'm running gVim 8.0.586 on Windows 10 and used the following in my …</p><p><strong>NOTE</strong>: This was originally posted <a href="https://www.reddit.com/r/vim/comments/83h31q/speed_up_ctrlp_with_fd/">on the Vim subreddit here</a>.</p>
<p>Just learned aboug <a href="https://github.com/sharkdp/fd">fd</a> today and was impressed by its speed. Tried using it for ctrlp and it works great! Didn't take any precise measurements but for the CPython code base, stock ctrlp loaded in about 2 seconds, ctrlp+ripgrep about 1 second, and ctlp+fd about 0.5 seconds.</p>
<p>I'm running gVim 8.0.586 on Windows 10 and used the following in my vimrc file:</p>
<div class="highlight"><pre><span></span><code><span class="err">" Use fd for ctrlp.</span>
<span class="err">if executable('fd')</span>
<span class="err"> let g:ctrlp_user_command = 'fd -c never "" "%s"'</span>
<span class="err"> let g:ctrlp_use_caching = 0</span>
<span class="err">endif</span>
</code></pre></div>
<p>For other Windows users, fd can be <a href="https://chocolatey.org/packages/fd">installed with Chocolatey</a>.</p>Another Quick Update2018-02-12T00:00:00-05:002018-02-12T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2018-02-12:/posts/2018/02/another-quick-update/<p>Another quick update of random stuff I've been up to lately:</p>
<ul>
<li>Released a new version of <a href="https://github.com/jeffrimko/archiver">gArchiver</a>. This is the first new release in nearly two years. It is now built with Python 3.6 and wxPython 4.0.1.</li>
<li><a href="https://github.com/jeffrimko/PopPage">PopPage</a> has some cool features like the <code>run</code> command and default files.</li>
<li>Learning a lot about C# and the .NET framework. Microsoft has done a great job with the tooling centered around Visual Studio!</li>
<li>Finally …</li></ul><p>Another quick update of random stuff I've been up to lately:</p>
<ul>
<li>Released a new version of <a href="https://github.com/jeffrimko/archiver">gArchiver</a>. This is the first new release in nearly two years. It is now built with Python 3.6 and wxPython 4.0.1.</li>
<li><a href="https://github.com/jeffrimko/PopPage">PopPage</a> has some cool features like the <code>run</code> command and default files.</li>
<li>Learning a lot about C# and the .NET framework. Microsoft has done a great job with the tooling centered around Visual Studio!</li>
<li>Finally put the source code for <a href="https://github.com/jeffrimko/Doctrine2">Doctrine2 up on GitHub here</a>. This project was a proof-of-concept for rewriting the <a href="https://github.com/jeffrimko/Doctrine">original Doctrine</a> application in Electron.</li>
<li>Still slowly working on the next Question Drilldown article.</li>
</ul>The Number e And Compound Interest2017-12-09T00:00:00-05:002017-12-09T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2017-12-09:/posts/2017/12/the-number-e-and-compound-interest/<div class="paragraph">
<p>The number <code>e</code> is one of those things in mathematics that appears mysterious at first glance. It has a seemingly random value and occasionally pops up in various contexts. Today, let’s take a closer look at this important number and understand it in the context of one of the most powerful forces known to man: compound interest.</p>
</div>
<div class="paragraph">
<p>The number <code>e</code> is essentially the growth multiple of something increasing at 100% over one time unit …</p></div><div class="paragraph">
<p>The number <code>e</code> is one of those things in mathematics that appears mysterious at first glance. It has a seemingly random value and occasionally pops up in various contexts. Today, let’s take a closer look at this important number and understand it in the context of one of the most powerful forces known to man: compound interest.</p>
</div>
<div class="paragraph">
<p>The number <code>e</code> is essentially the growth multiple of something increasing at 100% over one time unit when compounding continuously. That may sound a bit confusing so let’s break it down.</p>
</div>
<div class="paragraph">
<p>Consider a scenario where we could double our money every year and receive our new profit on the last day of the year. Starting with $1, we would have $2 at the end of year one. At the end of the second year, we would have $4. At the end of the third year, $8.</p>
</div>
<div class="paragraph">
<p>This scenario could be modeled with the following formula:</p>
</div>
<div class="paragraph">
<div class="title">Formula 1</div>
<p><code><strong><span class="red">1</span> * (<span class="orange">1</span> + <span class="purple">1</span>) ^ <span class="green">3</span> = <span class="blue">8</span></strong></code></p>
</div>
<div class="paragraph">
<p><strong><em><span class="red">starting amount</span>, <span class="orange">constant used when calculating the new total at a given rate</span>, <span class="purple">rate (1 = 100%)</span>, <span class="green">number of years</span>, <span class="blue">final value</span></em></strong></p>
</div>
<div class="paragraph">
<p>In this scenario, compounding only occurs once per year i.e. we only receive our new profit once per year. What if we kept the rate the same but increased the number of compounding periods per year?</p>
</div>
<div class="paragraph">
<p>Consider another example where our money compounded monthly instead of yearly. Instead of one compounding period per time unit, we would have 12 compounding periods. <strong>The new profit received at each compounding period would contribute to future compounding!</strong> Starting again with $1, at the end of the first month we would have $1.08. This is modeled by the following:</p>
</div>
<div class="paragraph">
<div class="title">Formula 2</div>
<p><code><strong><span class="red">1</span> * (<span class="orange">1</span> + (<span class="purple">1/12</span>)) = <span class="green">1.08</span></strong></code></p>
</div>
<div class="paragraph">
<p><strong><em><span class="red">starting amount</span>, <span class="orange">constant</span>, <span class="purple">rate (1 i.e. 100%) divided by the compounding periods (12)</span>, <span class="green">final value</span></em></strong></p>
</div>
<div class="paragraph">
<p>Now during the second month, that extra $0.08 will contribute to the compounding. At the end of month two we will have $1.17. This continues until we end up with $2.61 at the end of the year. This is modeled by the following:</p>
</div>
<div class="paragraph">
<div class="title">Formula 3</div>
<p><code><strong><span class="red">1 * (1 + (1/12))</span> ^ <span class="orange">12</span> = <span class="purple">2.61</span></strong></code></p>
</div>
<div class="paragraph">
<p><strong><em><span class="red">formula 2</span>, <span class="orange">number of compounding periods</span>, <span class="purple">final value</span></em></strong></p>
</div>
<div class="paragraph">
<p>By the end of the three years, we will have $17.84. Pretty big difference from our original $8! This is the magic of compound interest and is modeled by the following:</p>
</div>
<div class="paragraph">
<div class="title">Formula 4</div>
<p><code><strong><span class="red">1 * (1 + (1/12)) ^ (12</span> * <span class="orange">3</span>) = <span class="purple">17.84</span></strong></code></p>
</div>
<div class="paragraph">
<p><strong><em><span class="red">formula 3</span>, <span class="orange">total time units (3 years)</span>, <span class="purple">final value</span></em></strong></p>
</div>
<div class="paragraph">
<p>Now let’s look back at the result of formula 3 for a moment. We went from increasing our money by a factor of 2 to a factor of 2.61 just by increasing the compounding periods per time unit. Does that number look familiar? What happens if we further increase the compounding period? Let’s take a look:</p>
</div>
<div class="paragraph">
<p><code><strong>1 * (1 + (1/12)) ^ 12 = 2.61</strong></code> ← compounding monthly</p>
</div>
<div class="paragraph">
<p><code><strong>1 * (1 + (1/52)) ^ 52 = 2.69</strong></code> ← compounding weekly</p>
</div>
<div class="paragraph">
<p><code><strong>1 * (1 + (1/365)) ^ 365 = 2.71</strong></code> ← compounding daily</p>
</div>
<div class="paragraph">
<p>Woah, 2.71 is very close to the value of <code>e</code> (2.7182…​)! As we reduce the compounding period, we approach the value of <code>e</code>. This is because <code>e</code> is calculated from this same formula except that there are an infinite number of compounding periods per time unit, i.e. continuous (analog) compounding.</p>
</div>
<div class="paragraph">
<p>For more information, check out <a href="https://betterexplained.com/articles/an-intuitive-guide-to-exponential-functions-e/">this great article from the BetterExplained site</a>.</p>
</div>Weekly Picks - The Kingkiller Chronicle2017-10-28T00:00:00-04:002017-10-28T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-10-28:/posts/2017/10/weekly-picks-the-kingkiller-chronicle/<p>It's been a while since the last picks! This round includes the first two books in The Kingkiller Chronicle which is a planned trilogy of fantasy novels telling the life story of one of the most famous/infamous characters in their world, Kvothe. Author Patrick Rothfuss has done something truly special in these books. His story is unique yet familiar and masterfully crafted. My quick blurbs below won't do these books justice. If you are …</p><p>It's been a while since the last picks! This round includes the first two books in The Kingkiller Chronicle which is a planned trilogy of fantasy novels telling the life story of one of the most famous/infamous characters in their world, Kvothe. Author Patrick Rothfuss has done something truly special in these books. His story is unique yet familiar and masterfully crafted. My quick blurbs below won't do these books justice. If you are a fan of the genre, reads these books!</p>
<h4>Books:</h4>
<ul>
<li><em><a href="https://en.wikipedia.org/wiki/The_Name_of_the_Wind">The Name Of The Wind</a></em> - Focuses on Kvothe's early years and his journey to become a student at the University.</li>
<li><em><a href="https://en.wikipedia.org/wiki/The_Wise_Man%27s_Fear">The Wise Man's Fear</a></em> - Focuses on Kvothe's adventures as a young student.</li>
</ul>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="https://soundcloud.com/pageofthewind">Page Of The Wind</a></em> - Podcast where the hosts read a page from the books each day and discuss.</li>
</ul>Installing HospitalRun On Arch Linux2017-09-30T00:00:00-04:002017-09-30T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-09-30:/posts/2017/09/installing-hospitalrun-on-arch-linux/<p>I recently installed <a href="http://hospitalrun.io/">HospitalRun</a> on Arch Linux using the <a href="https://github.com/HospitalRun/hospitalrun-frontend#installation">official instructions available here</a>. Everything went well except for step 5 involving <code>script/bootstrap</code> which required the following changes:</p>
<ol>
<li>Add the <code>--ignore-scripts</code> option to the end of the line <code>npm install -g phantomjs-prebuilt</code>.</li>
<li>Add the <code>--allow-root</code> option to the end of the line <code>bower install</code>.</li>
</ol>
<p>Now run the script with <code>sudo script/bootstrap</code> and all should be good!</p>Removing A Suzuki SV650 Gas Tank2017-09-24T00:00:00-04:002017-09-24T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-09-24:/posts/2017/09/removing-a-suzuki-sv650-gas-tank/<p>Today, I had to remove the gas tank from a 2000 Suzuki SV650. While it is pretty straightforward, maybe someone can benefit from a documented process:</p>
<ol>
<li>Just below the seat on both sides there are small triangle shaped decorative fairings. Each are held on by an exposed hex bolt and a hidden plastic fastener. Remove the hex bolt and rotate the fairings away from the body of the bike.</li>
<li>The driver seat is held on …</li></ol><p>Today, I had to remove the gas tank from a 2000 Suzuki SV650. While it is pretty straightforward, maybe someone can benefit from a documented process:</p>
<ol>
<li>Just below the seat on both sides there are small triangle shaped decorative fairings. Each are held on by an exposed hex bolt and a hidden plastic fastener. Remove the hex bolt and rotate the fairings away from the body of the bike.</li>
<li>The driver seat is held on by two hex bolts that were hidden behind the fairings. Remove the bolts and the seat.</li>
<li>Remove the two hex bolts at the front of the gas tank by the handlebars. Be careful not to drop the large washers.</li>
<li>Lift the front of the tank and rotate it away from the handlebars and toward the back of the bike. Carefully prop up the gas tank. A 2x2 cut to about 1 foot works well.</li>
<li>There are four things that need to be disconnected underneath the tank (see picture):<ol>
<li>Two hoses to the petcock. The one without the clip is easiest to remove. The one with the clip may require some gentle prying with round nose pliers, i.e. pry from the end of the hose to seperate it from the connector. Note that some gas may come out of the hoses upon removal.</li>
<li>Near the end of the tank is a breather hose.</li>
<li>An electrical connector.</li>
</ol>
</li>
<li>There are two bolts under the driver seat that hold the rear of the tank in place as well as a plate that secures the battery in place. Remove the two bolts and the tank should lift off.</li>
</ol>
<p><img alt="SV650 Tank" src="/images/sv650_tank.jpg" title="SV650 Tank"></p>Quick Update2017-09-10T00:00:00-04:002017-09-10T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-09-10:/posts/2017/09/quick-update/<p>Just a quick update on some stuff I've been up to lately:</p>
<ul>
<li><a href="https://github.com/jeffrimko/QuickWin">QuickWin</a> now has better multi-monitor support. Been thinking about adding it to Chocolatey.</li>
<li>Been slowly hacking at <a href="https://github.com/jeffrimko/PopPage">PopPage</a> to improve overall functionality and cookiecutter template compatibility.</li>
<li>Started a new job that is outside of the embedded systems industry (a first for me). Been learning the Microsoft .NET stack and have been impressed so far. The Visual Studio debugger is amazing!</li>
<li>Slowly researching the …</li></ul><p>Just a quick update on some stuff I've been up to lately:</p>
<ul>
<li><a href="https://github.com/jeffrimko/QuickWin">QuickWin</a> now has better multi-monitor support. Been thinking about adding it to Chocolatey.</li>
<li>Been slowly hacking at <a href="https://github.com/jeffrimko/PopPage">PopPage</a> to improve overall functionality and cookiecutter template compatibility.</li>
<li>Started a new job that is outside of the embedded systems industry (a first for me). Been learning the Microsoft .NET stack and have been impressed so far. The Visual Studio debugger is amazing!</li>
<li>Slowly researching the next Question Drilldown topic. Hope to publish the post by the end of September.</li>
<li>Been thinking about updating the <a href="/prog-lang-popularity">Programming Language Popularity</a> data since it was originally posted last October.</li>
</ul>Changelog Structure2017-07-31T00:00:00-04:002017-07-31T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-07-31:/posts/2017/07/changelog-structure/<p>I recently changed my preferred structure for changelog files. Examples of the old structure are shown in the <a href="https://github.com/jeffrimko/Qprompt/blob/master/CHANGELOG.adoc">Qprompt changelog</a> while the new structure is shown in the <a href="https://github.com/jeffrimko/PopPage/blob/master/CHANGELOG.adoc">PopPage changelog</a>.</p>
<p>The new structure is based on suggestions from <a href="http://keepachangelog.com/">Keep A Changelog</a>. Liking the clarity and brevity of this style, I updated the <a href="https://github.com/jeffrimko/UnifiedStyleGuide/blob/master/doc/special_files/main.adoc#changelog-files">changelog section in the Unified Style Guide</a> to incorporate their suggestions.</p>
<p>While I don't plan to update old changelogs, new changelogs will definitely …</p><p>I recently changed my preferred structure for changelog files. Examples of the old structure are shown in the <a href="https://github.com/jeffrimko/Qprompt/blob/master/CHANGELOG.adoc">Qprompt changelog</a> while the new structure is shown in the <a href="https://github.com/jeffrimko/PopPage/blob/master/CHANGELOG.adoc">PopPage changelog</a>.</p>
<p>The new structure is based on suggestions from <a href="http://keepachangelog.com/">Keep A Changelog</a>. Liking the clarity and brevity of this style, I updated the <a href="https://github.com/jeffrimko/UnifiedStyleGuide/blob/master/doc/special_files/main.adoc#changelog-files">changelog section in the Unified Style Guide</a> to incorporate their suggestions.</p>
<p>While I don't plan to update old changelogs, new changelogs will definitely adopt this new style.</p>
<p>So do yourself and everyone else a favor: keep a changelog!</p>PopPage Demo2017-07-31T00:00:00-04:002017-07-31T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-07-31:/posts/2017/07/poppage-demo/<p><a href="https://github.com/jeffrimko/PopPage">PopPage</a> is a small side project I started a few years but haven't really updated much until recently. PopPage was originally a simple static HTML generator; at the time I just needed a utility to apply content to <a href="http://jinja.pocoo.org/">Jinja2</a> templates. However, recent updates have effectively made it a <a href="https://github.com/audreyr/cookiecutter">cookiecutter</a> clone with a few neat features. Unlike cookiecutter, PopPage information is supplied from YAML files rather than JSON files. As of PopPage <code>0.3.1</code>, there …</p><p><a href="https://github.com/jeffrimko/PopPage">PopPage</a> is a small side project I started a few years but haven't really updated much until recently. PopPage was originally a simple static HTML generator; at the time I just needed a utility to apply content to <a href="http://jinja.pocoo.org/">Jinja2</a> templates. However, recent updates have effectively made it a <a href="https://github.com/audreyr/cookiecutter">cookiecutter</a> clone with a few neat features. Unlike cookiecutter, PopPage information is supplied from YAML files rather than JSON files. As of PopPage <code>0.3.1</code>, there are two custom YAML tags: <code>!file</code> and <code>!cmd</code>. The <code>!file</code> tag will populate the associated key with content read from a file while <code>!cmd</code> will use the output of a CLI command.</p>
<p>The next planned update for PopPage is the ability to render templates supplied via URL. This is a really cool and useful feature provided by cookiecutter that I would like to replicate.</p>
<p>A repository of PopPage templates is <a href="https://github.com/jeffrimko/PopPageTemplates">available here</a>.</p>
<p>Here is a quick demo of PopPage in action:</p>
<div class="responsive-container">
<iframe src="//www.youtube.com/embed/955GwxbDx2k" frameborder="0" allowfullscreen></iframe>
</div>Superhot Unity Demo2017-07-23T00:00:00-04:002017-07-23T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-07-23:/posts/2017/07/superhot-unity-demo/<p>Having recently played through <a href="https://superhotgame.com/">Superhot</a>, I thought it would be a fun exercise to implement the time/movement mechanic in <a href="https://unity3d.com/">Unity</a>. Turns out to be fairly easy to do and I threw together a simple demo which is <a href="https://github.com/jeffrimko/Unity-SuperhotDemo">available on GitHub here</a>.</p>
<p>Here's the demo in action:</p>
<p><img alt="Superhot Demo" src="/images/superhot_demo.gif" title="Superhot Demo"></p>DevLog - Qprompt2017-06-15T00:00:00-04:002017-06-15T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-06-15:/posts/2017/06/devlog-qprompt/<p><a href="https://github.com/jeffrimko/Qprompt">Qprompt</a> is a simple CLI library for Python that I have slowly working on for about two years now. It provides basic typed prompts and menus in a CLI environment along with some additional convenience functions. Recently, I added a feature that allows prompt inputs to be automatically entered via stdin; I have found this feature to be enormously helpful. Let's look at an example use case.</p>
<h3>Use Case - QuickWin Build Menu</h3>
<p><a href="https://github.com/jeffrimko/quickwin">QuickWin</a> is another …</p><p><a href="https://github.com/jeffrimko/Qprompt">Qprompt</a> is a simple CLI library for Python that I have slowly working on for about two years now. It provides basic typed prompts and menus in a CLI environment along with some additional convenience functions. Recently, I added a feature that allows prompt inputs to be automatically entered via stdin; I have found this feature to be enormously helpful. Let's look at an example use case.</p>
<h3>Use Case - QuickWin Build Menu</h3>
<p><a href="https://github.com/jeffrimko/quickwin">QuickWin</a> is another project of mine. It is a GUI window switching application written in C++/Qt.</p>
<p>I have a fairly opinionated view on how software projects should be structured and how files should be named (<a href="https://github.com/jeffrimko/UnifiedStyleGuide">more info here</a>). When a script is solely intended for user interaction, I like naming conventions like <code>_Build_App.py</code> and <code>_Cleanup.py</code> and similar. I find this style helps make user scripts stand out from scripts that would otherwise be named like <code>build.py</code> and similar.</p>
<p>That being said, Qprompt works wonders for user scripts. Here is an excerpt from the <a href="https://github.com/jeffrimko/QuickWin/blob/master/app/_Build_App.py">build script for QuickWin</a>:</p>
<div class="highlight"><pre><span></span><code><span class="n">menu</span> <span class="o">=</span> <span class="n">qprompt</span><span class="o">.</span><span class="n">Menu</span><span class="p">()</span>
<span class="n">menu</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"b"</span><span class="p">,</span> <span class="s2">"Build release"</span><span class="p">,</span> <span class="n">build</span><span class="p">,</span> <span class="p">[</span><span class="n">config</span><span class="p">,</span> <span class="s2">"release"</span><span class="p">])</span>
<span class="n">menu</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"d"</span><span class="p">,</span> <span class="s2">"Build debug"</span><span class="p">,</span> <span class="n">build</span><span class="p">,</span> <span class="p">[</span><span class="n">config</span><span class="p">,</span> <span class="s2">"debug"</span><span class="p">])</span>
<span class="n">menu</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"r"</span><span class="p">,</span> <span class="s2">"Run app"</span><span class="p">,</span> <span class="n">run</span><span class="p">)</span>
<span class="n">menu</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"k"</span><span class="p">,</span> <span class="s2">"Kill app"</span><span class="p">,</span> <span class="n">kill</span><span class="p">)</span>
<span class="n">menu</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"c"</span><span class="p">,</span> <span class="s2">"Cleanup"</span><span class="p">,</span> <span class="n">cleanup</span><span class="p">)</span>
<span class="n">menu</span><span class="o">.</span><span class="n">main</span><span class="p">(</span><span class="n">loop</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</code></pre></div>
<p>This puppy shows the user the following when run:</p>
<div class="highlight"><pre><span></span><code><span class="err">-- MENU --</span>
<span class="err"> (b) Build release</span>
<span class="err"> (d) Build debug</span>
<span class="err"> (r) Run app</span>
<span class="err"> (k) Kill app</span>
<span class="err"> (c) Cleanup</span>
<span class="err"> (q) Quit</span>
<span class="err">[!] Menu loops until quit.</span>
<span class="err">[?] Enter menu selection:</span>
</code></pre></div>
<p>The menu provides the user with the basic actions required during development. The build process may change but the menu stays the same. Additionally the script can be run from the shell with automatic inputs, for example:</p>
<div class="highlight"><pre><span></span><code>$ _Build_App.py k c b r q
</code></pre></div>
<p>This will run all of the given menu commands in the given order. Couple items of note:</p>
<ul>
<li>The menu needs to be run by calling the <code>menu.main()</code> method.</li>
<li>To run multiple commands automatically, the <code>loop=True</code> flag needs to be set.</li>
<li>While not required, it is recommended to end the sequence of commands with <code>q</code>; this will exit the script gracefully.</li>
<li>On Windows, add <code>start</code> before the script call to run it asynchronously.</li>
</ul>
<p>So give Qprompt a try! I hope you find it as useful as I do!</p>Question Drilldown - Kalman Filter2017-06-08T00:00:00-04:002017-06-08T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-06-08:/posts/2017/06/question-drilldown-kalman-filter/<div class="sect2">
<h3 id="_the_topic">The Topic</h3>
<div class="paragraph">
<p>For this drilldown, we will take a very high-level look at a technique used in robotics, control systems, and any other applications involving sensors: the Kalman Filter.</p>
</div>
<div class="paragraph">
<p><strong>NOTE</strong>: No math will be covered in this article. There are plenty of great resources for learning the math behind the Kalman Filter. Think of this article as a primer.</p>
</div>
</div>
<div class="sect2">
<h3 id="_the_qa">The Q&A</h3>
<div class="dlist">
<dl>
<dt class="hdlist1">What is a Kalman Filter (KF)?</dt>
<dd>
<p>The KF is an algorithm used to …</p></dd></dl></div></div><div class="sect2">
<h3 id="_the_topic">The Topic</h3>
<div class="paragraph">
<p>For this drilldown, we will take a very high-level look at a technique used in robotics, control systems, and any other applications involving sensors: the Kalman Filter.</p>
</div>
<div class="paragraph">
<p><strong>NOTE</strong>: No math will be covered in this article. There are plenty of great resources for learning the math behind the Kalman Filter. Think of this article as a primer.</p>
</div>
</div>
<div class="sect2">
<h3 id="_the_qa">The Q&A</h3>
<div class="dlist">
<dl>
<dt class="hdlist1">What is a Kalman Filter (KF)?</dt>
<dd>
<p>The KF is an algorithm used to estimate the state of a system (e.g. vehicle speed) based on periodic predictions and sensor measurements. The estimation is a weighted average of the predictions/measurements while also factoring in the uncertainty associated with each. The goal of the KF is to provide the best possible estimate with the least amount of uncertainty by using all available state information.</p>
</dd>
<dt class="hdlist1">What applications are well suited for a KF?</dt>
<dd>
<p>The KF works well for applications where the system’s future state can be reasonably predicted and at least one measurement of the state is made periodically. The sensors and state predictor are not expected to be perfect and include a quantifiable amount of uncertainty in the values they produce. The KF will help reduce state estimation uncertainty in situations where predictions can be made or when multiple sensor readings can be fused together. Additionally, the KF is well suited for memory constrained applications as it only requires the previous state estimate to be stored.</p>
</dd>
<dt class="hdlist1">How does the future state prediction work?</dt>
<dd>
<p>This highly depends on the system of interest. For a vehicle, the future speed can be estimated reasonably well if the current speed and acceleration are known; perhaps the acceleration is measured or perhaps the acceleration is even managed using a control system. In either case, the future speed could be estimated with fairly low uncertainty. In some situations, it may be necessary to simply use the previous estimate as the prediction; in this case, the uncertainty would be based on the maximum amount of possible state change between iterations of the algorithm loop. The model used to predict the future state and its associated uncertainty are important inputs to the KF.</p>
</dd>
<dt class="hdlist1">How is uncertainty handled?</dt>
<dd>
<p>Uncertainty is modeled using Gaussian distributions. For example, the value returned by a sensor would be represented by the distribution mean and the possible error range in the reading would be represented by the distribution variance. The prediction model and each sensor has an associated Gaussian distribution which represents the uncertainty for each.</p>
</dd>
<dt class="hdlist1">How are the predictions, measurements, and uncertainties used by the KF?</dt>
<dd>
<p>The KF weighs all available state information based on the associated uncertainty; this is called the Kalman Gain. Since the KF is essentially a weighted average, the Kalman Gain is used as the weights; for example, a sensor reading with a large amount of uncertainty will be weighted less than a prediction/measurement with lower uncertainty.</p>
</dd>
</dl>
</div>
</div>
<div class="sect2">
<h3 id="_the_recap">The Recap</h3>
<div class="paragraph">
<p>The KF is an algorithm used to estimate system state.</p>
</div>
<div class="paragraph">
<p>The KF combines state information from predictions and measurements.</p>
</div>
<div class="paragraph">
<p>The predictions/measurements have an associated amount of uncertainty.</p>
</div>
<div class="paragraph">
<p>The uncertainty is modeled as Gaussian distributions.</p>
</div>
<div class="paragraph">
<p>The KF estimate is calculated by averaging the predictions/measurements with weights based on the uncertainty associated with each.</p>
</div>
</div>
<div class="sect2">
<h3 id="_the_resources">The Resources</h3>
<div class="paragraph">
<p>There are a lot of resources available on this subject but I found the following to be the best:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python" class="bare">https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python</a></p>
</li>
<li>
<p><a href="http://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/" class="bare">http://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=18TKA-YWhX0" class="bare">https://www.youtube.com/watch?v=18TKA-YWhX0</a></p>
</li>
</ul>
</div>
</div>Weekly Picks - A Strange Trio2017-05-13T00:00:00-04:002017-05-13T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-05-13:/posts/2017/05/weekly-picks-a-strange-trio/<p>The picks this week all involve a group of friends dealing with a supernatural foe. While the premise of each is different, they share similar tones and pay homage to 80's era horror.</p>
<h4>Games:</h4>
<ul>
<li><em><a href="http://store.steampowered.com/app/388880/Oxenfree/">Oxenfree</a></em> - A group of friends are tormented by a supernatural presence on an abandoned island. Fun, engaging, and only takes a few hours to play through.</li>
</ul>
<h4>Movies:</h4>
<ul>
<li><em><a href="http://www.imdb.com/title/tt3235888/">It Follows</a></em> - A girl is hunted by an unstoppable shape-shifting creature. Good execution of …</li></ul><p>The picks this week all involve a group of friends dealing with a supernatural foe. While the premise of each is different, they share similar tones and pay homage to 80's era horror.</p>
<h4>Games:</h4>
<ul>
<li><em><a href="http://store.steampowered.com/app/388880/Oxenfree/">Oxenfree</a></em> - A group of friends are tormented by a supernatural presence on an abandoned island. Fun, engaging, and only takes a few hours to play through.</li>
</ul>
<h4>Movies:</h4>
<ul>
<li><em><a href="http://www.imdb.com/title/tt3235888/">It Follows</a></em> - A girl is hunted by an unstoppable shape-shifting creature. Good execution of an interesting premising.</li>
</ul>
<h4>Shows:</h4>
<ul>
<li><em><a href="https://www.netflix.com/title/80057281">Stranger Things</a></em> - A boy goes missing, his friends investigate, and a mysterious creature torments a town. Really fun Netflix show!</li>
</ul>Better Task Lists In AsciiDoc2017-04-23T00:00:00-04:002017-04-23T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-04-23:/posts/2017/04/better-task-lists-in-asciidoc/<p><strong>NOTE</strong>: This is an update to a <a href="https://www.jeffcomput.es/posts/2014/02/task-lists-in-asciidoc/">previous post</a>.</p>
<p>Okay, it's been a while since the last post on this topic. Since then, I've switched from using the <a href="http://asciidoc.org/">original AsciiDoc utility</a> to <a href="http://asciidoctor.org/">Asciidoctor</a>. This along with some minor tweaking has changed how my task lists look.</p>
<p>Here is the basic structure:</p>
<div class="highlight"><pre><span></span><code>= My Task List
[NOTE]
========
.Category Tags
[horizontal]
`code`::
Code related tasks.
`doc`::
Documentation related tasks.
========
== Current Tasks
.Updated 2017-01-06
********
NOTE: Arranged by priority.
- [ ] `2017-01-05 …</code></pre></div><p><strong>NOTE</strong>: This is an update to a <a href="https://www.jeffcomput.es/posts/2014/02/task-lists-in-asciidoc/">previous post</a>.</p>
<p>Okay, it's been a while since the last post on this topic. Since then, I've switched from using the <a href="http://asciidoc.org/">original AsciiDoc utility</a> to <a href="http://asciidoctor.org/">Asciidoctor</a>. This along with some minor tweaking has changed how my task lists look.</p>
<p>Here is the basic structure:</p>
<div class="highlight"><pre><span></span><code>= My Task List
[NOTE]
========
.Category Tags
[horizontal]
`code`::
Code related tasks.
`doc`::
Documentation related tasks.
========
== Current Tasks
.Updated 2017-01-06
********
NOTE: Arranged by priority.
- [ ] `2017-01-05`: [[Xbe421]] `code` Write code.
- [ ] `2017-01-05`: [[Xf7125]] `code` `doc` Write unit tests and document them.
********
== Planned Tasks
- [ ] `2017-01-05`: [[Xf33d9]] `doc` Write user manual.
* `2017-01-07`: [[Xf33d9-1]] Manual started; first draft ready for review.
== Finshed Tasks
- [x] `2017-01-05`: [[Xcfd25]] `doc` Write design docs.
* `2017-01-07`: [[Xcfd25-1]] Docs started, first draft ready.
* `2017-01-10`: [[Xcfd25-2]] Design docs have been written, reviewed, and baselined.
</code></pre></div>
<p>First, let's review the task item structure:</p>
<ul>
<li>Each task is a list item using the following format: <code><DATE>: <UNIQUE-ID> <[TAGS...]> <TASK-DESCRIPTION></code>.</li>
<li>The DATE uses YYYY-MM-DD format and is formatted inside <a href="http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#source-code">backticks</a> which render to HTML <code><code></code> tags.</li>
<li>The UNIQUE-ID is used as an anchor to each task; I use the format <code>X<5-char-hex></code> but any unique text will work. The UNIQUE-ID is formatted inside <a href="http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#links">double square brackets</a> which renders to HTML anchors.</li>
<li>The category TAGS are optional and are formatted inside <a href="http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#source-code">backticks</a> which render to HTML <code><code></code> tags.</li>
<li>The TASK-DESCRIPTION is just the task text.</li>
<li>I like to use <a href="http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#lists">checklist items</a> since it fits the theme well.</li>
</ul>
<p>Task item follow-ups use a similar format with the following exceptions:</p>
<ul>
<li>The category TAGS can be omitted.</li>
<li>The UNIQUE-ID should be the same as the main item's with an integer incremented for each new follow-up.</li>
</ul>
<p>The current tasks section uses a <a href="http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#more-delimited-blocks">sidebar</a> block. The block title shows when the tasks were last prioritized.</p>
<p>Well, that's about it. No need to overcomplicate things, right? Here's <a href="/misc/task_example.html">an example of a rendered task list</a>.</p>Question Drilldown - Processes, Threads2017-04-20T00:00:00-04:002017-04-20T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-04-20:/posts/2017/04/question-drilldown-processes-threads/<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This is the first post using a format that I have been wanting to try out for a long time. The idea is to catalog the questions that might be asked when first learning about a topic. By reviewing these questions, hopefully newcomers can learn a great deal and the more experienced can brush up a bit. The goal is not to exhaustively review every detail on the topic but rather provide just enough information …</p></div></div></div><div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This is the first post using a format that I have been wanting to try out for a long time. The idea is to catalog the questions that might be asked when first learning about a topic. By reviewing these questions, hopefully newcomers can learn a great deal and the more experienced can brush up a bit. The goal is not to exhaustively review every detail on the topic but rather provide just enough information to be dangerous.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_the_topic">The Topic</h3>
<div class="paragraph">
<p>For this drilldown, let’s take a look at an important aspect of operating systems: processes and threads.</p>
</div>
</div>
<div class="sect2">
<h3 id="_the_qa">The Q&A</h3>
<div class="dlist">
<dl>
<dt class="hdlist1">What is a process?</dt>
<dd>
<p>A process is an instance of a software program in main memory which is able to be run by the operating system. Processes are essentially isolated environments which contain all of the code and data necessary for the system to execute the program.</p>
</dd>
<dt class="hdlist1">How are processes created?</dt>
<dd>
<p>Processes are created via system calls from other processes. When the operating system is started, a top-level process is created. All other processes are descendants (either directly or through lineage) of this top-level process.</p>
</dd>
<dt class="hdlist1">Is the operating system a process?</dt>
<dd>
<p>The operating system kernel itself is not a process. The kernel is the main operating system logic which (among other things) is responsible for running processes. The kernel is loaded into a special region of main memory (called the kernel space) at startup.</p>
</dd>
<dt class="hdlist1">How are processes run?</dt>
<dd>
<p>Processes consist of one or more threads of execution. If a process has multiple threads, they all share the resources (code, data) provided in the isolated environment. A thread is essentially the information associated with the execution state of a program. The kernel scheduler allocates a slice of time for a thread to execute on a CPU core. The previously executing thread state is saved and the new thread is loaded; this is called a context switch. The old and new threads could be in the same process (a thread switch) or in separate processes (a process switch). The difference between the two switches is that a process switch requires additional work to change between the isolated environments specific to each process.</p>
</dd>
<dt class="hdlist1">What triggers a thread/process context switch?</dt>
<dd>
<p>There are two basic types of switches: voluntary and involuntary. Before the execution of a thread is started or resumed, the kernel scheduler prepares a timer interrupt to occur once the thread’s execution time slice has elapsed. Voluntary switches typically occur when a thread makes a system call requesting access to a resource that is currently unavailable; in this case, the kernel will stop the thread’s execution early. Involuntary switches occur when the thread’s time slice elapses and the interrupt is handled; this technique is called pre-emption.</p>
</dd>
<dt class="hdlist1">How are processes isolated?</dt>
<dd>
<p>Processes are isolated through a main memory management technique called virtual memory. This allows each process to appear as if it has full access to the entire system address space. However, the virtual memory is actually composed of groups called pages which can be mapped to main memory or stored to disk when not immediately needed.</p>
</dd>
<dt class="hdlist1">Can processes communicate to each other?</dt>
<dd>
<p>Yes, the operating system typically provides various inter-process communication (IPC) methods such as shared memory, queues, sockets, pipes, files, etc.</p>
</dd>
<dt class="hdlist1">What are CPU cores?</dt>
<dd>
<p>In simplest terms, a core is the hardware required to execute a thread. For each instruction in a thread, the core must perform several actions such as fetching the instruction from main memory, decoding the instruction, executing the instruction (using hardware called execution units), and finally storing any results. Cores are typically organized to allow each of these actions to occur in separate stages. For example, the fetching of the next instruction will start immediately as the previous instruction moves on to decoding. This effectively allows multiple instructions to be executed in quick succession which increases the core’s throughput. This technique is called pipelining. Some CPUs have multiple cores allowing for simultaneous execution of multiple threads.</p>
</dd>
<dt class="hdlist1">Can one core only execute one thread at a time?</dt>
<dd>
<p>It depends on the core. The most basic core is only capable of executing a single thread at once. Some cores have hardware which increases the number of instructions that can be acted upon at each pipeline stage, increasing the core throughput for that single thread. This type of core is called a superscalar. Techniques which allow multiple threads to execute per core are generally referred to as simultaneous multi-threading (SMT, sometimes referred to as hardware threading). For example, Intel’s Hyper-Threading is an SMT technology which essentially provides a core with two pipelines sharing a single set of execution units. This allows a single core to execute two separate threads.</p>
</dd>
<dt class="hdlist1">How do the terms concurrent and parallel relate?</dt>
<dd>
<p>Concurrency is multi-tasking however each task is not necessarily being performed at the exact same time. For example, a single core non-SMT CPU relies upon the kernel scheduler to juggle running threads; by rapidly switching between threads and allowing each a time slice to execute on the core, concurrency is achieved. Parallelism is multi-tasking where multiple tasks are being performed at the exact same time. For example, a two-core non-SMT CPU can execute two threads at once.</p>
</dd>
<dt class="hdlist1">What are lightweight threads (green threads/greenlets/coroutines/etc)?</dt>
<dd>
<p>These are software techniques that provide concurrency within a single thread. So rather than spawning multiple threads, tasks can be divided up into lightweight threads which execute a portion of their work and then yields execution to other tasks. This loop of executing then yielding continues until the tasks are complete. The kernel scheduler is not involved with the scheduling of the individual lightweight threads within the context of the host thread.</p>
</dd>
<dt class="hdlist1">What is thread safety?</dt>
<dd>
<p>If a process spawns multiple threads, it is possible for those threads to execute the same code. Thread safe code will behave correctly and without problematic side effects when multiple threads execute it.</p>
</dd>
</dl>
</div>
</div>
<div class="sect2">
<h3 id="_the_recap">The Recap</h3>
<div class="paragraph">
<p>A process is an isolated environment in main memory used to execute a software program.</p>
</div>
<div class="paragraph">
<p>A process has at least one thread although more can be spawned.</p>
</div>
<div class="paragraph">
<p>A thread is information associated with the execution state of a program.</p>
</div>
<div class="paragraph">
<p>Processes are isolated from one another using virtual memory.</p>
</div>
<div class="paragraph">
<p>Threads in the same process can share data and code while threads in different processes cannot.</p>
</div>
<div class="paragraph">
<p>IPC methods are provided by the operating system.</p>
</div>
<div class="paragraph">
<p>The operating system is responsible for scheduling threads to be executed on a CPU core.</p>
</div>
<div class="paragraph">
<p>A context switch is when the operating system changes the currently executing thread on a CPU core.</p>
</div>
<div class="paragraph">
<p>If context switch threads are in different processes, more work is required during the switch.</p>
</div>
<div class="paragraph">
<p>Each CPU core can execute at least one thread.</p>
</div>
<div class="paragraph">
<p>CPU cores use instruction pipelining to increase the execution throughput for a thread.</p>
</div>
<div class="paragraph">
<p>CPU cores with SMT technology can execute more than one thread.</p>
</div>
<div class="paragraph">
<p>Concurrency is multi-tasking but each task (e.g. thread) is not necessarily being performed at the exact same time.</p>
</div>
<div class="paragraph">
<p>Parallelism is multi-tasking but multiple tasks (e.g. threads) are being performed at the exact same time.</p>
</div>
<div class="paragraph">
<p>Lightweight threads provide concurrency within a single thread.</p>
</div>
<div class="paragraph">
<p>Thread safe code will behave correctly when executed by multiple threads.</p>
</div>
</div>
<div class="sect2">
<h3 id="_the_resources">The Resources</h3>
<div class="paragraph">
<p>I reviewed quite a bit of material while preparing this post. The following is a portion of the resources used and may make for good further reading:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="http://docs.oracle.com/cd/E19455-01/806-5257/6je9h032b/index.html" class="bare">http://docs.oracle.com/cd/E19455-01/806-5257/6je9h032b/index.html</a></p>
</li>
<li>
<p><a href="http://stackoverflow.com/questions/1050222/concurrency-vs-parallelism-what-is-the-difference" class="bare">http://stackoverflow.com/questions/1050222/concurrency-vs-parallelism-what-is-the-difference</a></p>
</li>
<li>
<p><a href="http://stackoverflow.com/questions/18698502/hyperthreading-intel-processors-and-c" class="bare">http://stackoverflow.com/questions/18698502/hyperthreading-intel-processors-and-c</a></p>
</li>
<li>
<p><a href="http://stackoverflow.com/questions/1934715/difference-between-a-coroutine-and-a-thread" class="bare">http://stackoverflow.com/questions/1934715/difference-between-a-coroutine-and-a-thread</a></p>
</li>
<li>
<p><a href="http://stackoverflow.com/questions/200469/what-is-the-difference-between-a-process-and-a-thread" class="bare">http://stackoverflow.com/questions/200469/what-is-the-difference-between-a-process-and-a-thread</a></p>
</li>
<li>
<p><a href="http://stackoverflow.com/questions/261683/what-is-meant-by-thread-safe-code" class="bare">http://stackoverflow.com/questions/261683/what-is-meant-by-thread-safe-code</a></p>
</li>
<li>
<p><a href="http://stackoverflow.com/questions/5201852/what-is-a-thread-really" class="bare">http://stackoverflow.com/questions/5201852/what-is-a-thread-really</a></p>
</li>
<li>
<p><a href="http://www.tldp.org/LDP/tlk/kernel/processes.html" class="bare">http://www.tldp.org/LDP/tlk/kernel/processes.html</a></p>
</li>
<li>
<p><a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms684841(v=vs.85).aspx" class="bare">https://msdn.microsoft.com/en-us/library/windows/desktop/ms684841(v=vs.85).aspx</a></p>
</li>
<li>
<p><a href="https://www.cise.ufl.edu/~mssz/CompOrg/CDA-pipe.html" class="bare">https://www.cise.ufl.edu/~mssz/CompOrg/CDA-pipe.html</a></p>
</li>
<li>
<p><a href="https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Memory/virtual.html" class="bare">https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Memory/virtual.html</a></p>
</li>
<li>
<p><a href="https://www.quora.com/How-does-thread-switching-differ-from-process-switching" class="bare">https://www.quora.com/How-does-thread-switching-differ-from-process-switching</a></p>
</li>
<li>
<p><a href="https://www.slideshare.net/ppkvinu/amp-57549174" class="bare">https://www.slideshare.net/ppkvinu/amp-57549174</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/user/daveXbang" class="bare">https://www.youtube.com/user/daveXbang</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>While I have tried to keep terms consistent through this post, please note that some people may use terms differently.</p>
</div>
</div>Second Game Jam2017-04-07T00:00:00-04:002017-04-07T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-04-07:/posts/2017/04/second-game-jam/<p>The <a href="http://youngstowngamedevelopers.com/">Youngstown Game Developers</a> had our second annual game jam this past weekend. It was a great time and I learned a ton. It had been several months since doing any game dev stuff so I did spend a fair amount of time relearning Unity.</p>
<p>During <a href="https://www.youtube.com/watch?v=AKMe0oIH6u4">the keynote</a>, we were advised to avoid games with common mechanics like jumping. So of course I made a game about... jumping in the dark! Yeah, I know, not …</p><p>The <a href="http://youngstowngamedevelopers.com/">Youngstown Game Developers</a> had our second annual game jam this past weekend. It was a great time and I learned a ton. It had been several months since doing any game dev stuff so I did spend a fair amount of time relearning Unity.</p>
<p>During <a href="https://www.youtube.com/watch?v=AKMe0oIH6u4">the keynote</a>, we were advised to avoid games with common mechanics like jumping. So of course I made a game about... jumping in the dark! Yeah, I know, not very original but I really wanted to do something that incorporated light in a semi-meaningful way.</p>
<p>The game I developed is called Spotlight.</p>
<p><img alt="Spotlight - YSU Game Jam 2017" src="/images/spotlight.jpg" title="Spotlight - YSU Game Jam 2017"></p>
<p>It is a very simple level-based game where your objective is to reach a glowing goal marker. The game world is completely dark but there is a spotlight around your character (a blue box) which narrows as you move closer to the goal. Because it is essentially a 3D platformer, the reduced visibility makes navigating the level increasingly difficult. Also, the go with the theme of "decpetion", some of the platforms will move or fall away when touched or approached.</p>
<p>The game is not publicly available yet but I plan to put it on GitHub soon.</p>Weekly Picks - Jesse Schell2017-04-07T00:00:00-04:002017-04-07T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-04-07:/posts/2017/04/weekly-picks-jesse-schell/<p>This week's pick is a legend of the video game industry: Jesse Schell.</p>
<h4>Companies:</h4>
<ul>
<li><em><a href="https://www.schellgames.com/">Schell Games</a></em> - Jesse founded this Pittsburgh based company in 2002. It is the largest game studio in Pennsylvania. They make great games like <a href="http://www.enemymindgame.com/">Enemy Mind</a> and <a href="https://iexpectyoutodie.schellgames.com/">I Expect You To Die</a>.</li>
</ul>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://thedebuglog.com/2016/09/21/episode-50-the-art-of-game-design-with-jesse-schell/">The Debug Log, Episode 50, The Art Of Game Design With Jesse Schell</a></em> - Excellent interview with Jesse covering topics inspired by <a href="https://www.amazon.com/Art-Game-Design-Book-Lenses/dp/0123694965">his book</a>.</li>
</ul>
<h4>Videos:</h4>
<ul>
<li><em><a href="https://www.youtube.com/watch?v=AKMe0oIH6u4">April Fools' Game Jam Keynote …</a></em></li></ul><p>This week's pick is a legend of the video game industry: Jesse Schell.</p>
<h4>Companies:</h4>
<ul>
<li><em><a href="https://www.schellgames.com/">Schell Games</a></em> - Jesse founded this Pittsburgh based company in 2002. It is the largest game studio in Pennsylvania. They make great games like <a href="http://www.enemymindgame.com/">Enemy Mind</a> and <a href="https://iexpectyoutodie.schellgames.com/">I Expect You To Die</a>.</li>
</ul>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://thedebuglog.com/2016/09/21/episode-50-the-art-of-game-design-with-jesse-schell/">The Debug Log, Episode 50, The Art Of Game Design With Jesse Schell</a></em> - Excellent interview with Jesse covering topics inspired by <a href="https://www.amazon.com/Art-Game-Design-Book-Lenses/dp/0123694965">his book</a>.</li>
</ul>
<h4>Videos:</h4>
<ul>
<li><em><a href="https://www.youtube.com/watch?v=AKMe0oIH6u4">April Fools' Game Jam Keynote by Jesse Schell</a></em> - Jesse gave an excellent keynote talk for our <a href="http://youngstowngamedevelopers.com/game-jams/april-fools-game-jam-2017-youngstown-game-developers/">YGD 2017 game jam</a>!</li>
</ul>Weekly Picks - Podcasts2017-03-18T00:00:00-04:002017-03-18T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2017-03-18:/posts/2017/03/weekly-picks-podcasts/<p>Couple of random podcast episodes for this round of picks.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://cppcast.com/2017/03/odin-holmes/">CppCast, 13 March 2017, emBO++ With Odin Holmes</a></em> - Good discussion of how C++ is evolving in the embedded systems field.</li>
<li><em><a href="http://embedded.fm/episodes/190">Embedded FM, Episode 190, Trust Me I'm Right</a></em> - Great interview with the creator of <a href="https://godbolt.org/">Compiler Explorer</a>. Smart guy with an interesting background.</li>
<li><em><a href="http://www.npr.org/podcasts/510313/how-i-built-this">How I Built This, 13 March 2017, 5 Hour Energy</a></em> - Interview with the founder, he is not what I expected. Super humble …</li></ul><p>Couple of random podcast episodes for this round of picks.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://cppcast.com/2017/03/odin-holmes/">CppCast, 13 March 2017, emBO++ With Odin Holmes</a></em> - Good discussion of how C++ is evolving in the embedded systems field.</li>
<li><em><a href="http://embedded.fm/episodes/190">Embedded FM, Episode 190, Trust Me I'm Right</a></em> - Great interview with the creator of <a href="https://godbolt.org/">Compiler Explorer</a>. Smart guy with an interesting background.</li>
<li><em><a href="http://www.npr.org/podcasts/510313/how-i-built-this">How I Built This, 13 March 2017, 5 Hour Energy</a></em> - Interview with the founder, he is not what I expected. Super humble guy with an unconventional approach to business.</li>
<li><em><a href="http://freakonomics.com/podcast/why-is-my-life-so-hard/">Freakonomics, Episode 279, Why Is My Life So Hard</a></em> - Insightful exploration of a mental trap we all fall into.</li>
</ul>Weekly Picks - Foreign Language Learning2017-03-11T00:00:00-05:002017-03-11T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2017-03-11:/posts/2017/03/weekly-picks-foreign-language-learning/<p>Ciao friends! Been a while since the last "weekly" picks but here are some to help you learn a new (spoken) language.</p>
<h4>Software:</h4>
<ul>
<li><em><a href="https://apps.ankiweb.net/">Anki</a></em> - Great flashcard application! Lots of pre-made decks available to help build vocab.</li>
</ul>
<h4>Websites:</h4>
<ul>
<li><em><a href="http://duolingo.com/">Duolingo</a></em> - Free and amazing language learning site. The mobile app is quite good too.</li>
<li><em><a href="http://www.forvo.com/">Forvo</a></em> - Not sure how a word is supposed to be pronounce? Forvo's got your back!</li>
<li><em><a href="https://translate.google.com/">Google Translate</a></em> - Essential for those unknown words!</li>
</ul>DevLog - Doctrine Updates And Electron2017-01-31T00:00:00-05:002017-01-31T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2017-01-31:/posts/2017/01/devlog-doctrine-updates-and-electron/<p>In a <a href="https://www.jeffcomput.es/posts/2016/07/devlog-doctrine-updates/">previous post</a>, I was kicking around some ideas for updating a pet project of mine called <a href="https://github.com/jeffrimko/doctrine">Doctrine</a>. Here's a quick update on the progress of the second iteration of the project.</p>
<p>I decided to go the JavaScript/Electron route. Electron is easy to work with, it does what is expected (<a href="https://www.jeffcomput.es/posts/2016/09/strange-electron-webview-behavior/">usually</a>) and haven't run into too many surprises. The functionality of Doctrine2 is coming together nicely and I hope to make the code …</p><p>In a <a href="https://www.jeffcomput.es/posts/2016/07/devlog-doctrine-updates/">previous post</a>, I was kicking around some ideas for updating a pet project of mine called <a href="https://github.com/jeffrimko/doctrine">Doctrine</a>. Here's a quick update on the progress of the second iteration of the project.</p>
<p>I decided to go the JavaScript/Electron route. Electron is easy to work with, it does what is expected (<a href="https://www.jeffcomput.es/posts/2016/09/strange-electron-webview-behavior/">usually</a>) and haven't run into too many surprises. The functionality of Doctrine2 is coming together nicely and I hope to make the code public soon. The following GIF shows the basic functionality:</p>
<ul>
<li>Rendering an AsciiDoc file, relative links work correctly (e.g. images).</li>
<li>If a zip file or directory is opened, all render-able files will be shown.</li>
<li>Zip files correctly handle embedded content correctly.</li>
</ul>
<p><a href="/images/doctrine2_demo.gif"><img alt="Doctrine2 Demo" src="/images/doctrine2_demo.gif" title="Doctrine2 Demo"></a></p>V-REP Remote API Demo2017-01-24T00:00:00-05:002017-01-24T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2017-01-24:/posts/2017/01/v-rep-remote-api-demo/<p>While looking over robot simulator options, ran across <a href="http://www.coppeliarobotics.com/">V-REP</a> which looked interesting. After reading through some of <a href="http://www.coppeliarobotics.com/helpFiles/index.html">the great documentation</a>, I wanted to give the remote API a try so I threw together a basic demo of a line following robot with logic implemented in Python. The demo is <a href="https://github.com/jeffrimko/Vrep-RemoteApiDemo">available on GitHub here</a>. Hoping to try some more complex projects in V-REP soon!</p>Advice From The 10 Year Point2016-12-30T00:00:00-05:002016-12-30T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-12-30:/posts/2016/12/advice-from-the-10-year-point/<p>A quick look back on 10 years of professional software/hardware development and some advice for new developers and engineers.</p>
<p>Some generalizations on how the first 10 years of your career might look. Years 1 to 5 will be spent learning as much as possible; it's very likely you will learn more in the first two years on the job than you did in all of college. Years 6 to 10 will be spent niching …</p><p>A quick look back on 10 years of professional software/hardware development and some advice for new developers and engineers.</p>
<p>Some generalizations on how the first 10 years of your career might look. Years 1 to 5 will be spent learning as much as possible; it's very likely you will learn more in the first two years on the job than you did in all of college. Years 6 to 10 will be spent niching down on specific skills.</p>
<p>During those first five years, some advice:</p>
<ul>
<li>There are many domains in software/hardware. Explore as many as possible. If your job forces you into one domain, spend some free time looking into others. For example, if you are a embedded software developer, learn about web application development.</li>
<li>Learn to use many different tools but avoid vendor lock-in when possible.</li>
<li>Avoid reinventing the wheel. Spend some time researching existing solutions and build upon them. Alternatively, reinventing the wheel can sometimes be a fun and educational exercise.</li>
<li>Learn how to break complex tasks down into simple steps. Rome wasn't built in a day nor all at once.</li>
</ul>
<p>The next five years will be built on your foundation of skills and experience. Never stop learning, it's easier now than ever. Good luck!</p>Easy Custom Parts Experiment - Update 12016-11-30T00:00:00-05:002016-11-30T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-11-30:/posts/2016/11/easy-custom-parts-experiment-update-1/<p>In a <a href="https://www.jeffcomput.es/posts/2016/11/easy-custom-parts-experiment/">previous post</a>, I brainstormed about applying masking tape to one side of a wire mesh part then fiberglass cloth to the other side. Tried it out and the results are encouraging. The only downside I ran into was the cloth tends to move around a bit when applying the resin. Also, this method may require some additional steps if the cloth cannot be applied as a single piece.</p>
<p>Here is a video showing …</p><p>In a <a href="https://www.jeffcomput.es/posts/2016/11/easy-custom-parts-experiment/">previous post</a>, I brainstormed about applying masking tape to one side of a wire mesh part then fiberglass cloth to the other side. Tried it out and the results are encouraging. The only downside I ran into was the cloth tends to move around a bit when applying the resin. Also, this method may require some additional steps if the cloth cannot be applied as a single piece.</p>
<p>Here is a video showing the results:</p>
<div class="responsive-container">
<iframe src="//www.youtube.com/embed/su3iXLA5vYQ" frameborder="0" allowfullscreen></iframe>
</div>Easy Custom Parts Experiment2016-11-26T00:00:00-05:002016-11-26T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-11-26:/posts/2016/11/easy-custom-parts-experiment/<p>Been experimenting with a few methods of using wire mesh to create custom parts. Mesh is cheap and easy to work with. I wanted to figure out a quick method of treating the mesh so that it would retain its shape and seal the openings in the wire. Here is what I have tried so far:</p>
<ul>
<li><strong>Method 1</strong> - Apply FibaTape over the mesh then apply Bondo over the tape.</li>
<li><strong>Method 2</strong> - Apply masking tape over …</li></ul><p>Been experimenting with a few methods of using wire mesh to create custom parts. Mesh is cheap and easy to work with. I wanted to figure out a quick method of treating the mesh so that it would retain its shape and seal the openings in the wire. Here is what I have tried so far:</p>
<ul>
<li><strong>Method 1</strong> - Apply FibaTape over the mesh then apply Bondo over the tape.</li>
<li><strong>Method 2</strong> - Apply masking tape over the mesh then apply fiberglass resin to the tape.</li>
</ul>
<p>Here is a video showing the results of the two methods:</p>
<div class="responsive-container">
<iframe src="//www.youtube.com/embed/El33EZ6CFEY" frameborder="0" allowfullscreen></iframe>
</div>
<p>Method 1 produces the best results by far. The part is very rigid and strong. The only downside is that applying the Bondo neatly can be time consuming.</p>
<p>Method 2 shows promise but the masking tape is not rigid enough alone. Perhaps applying masking tape to one side of the mesh then fiberglass mat or cloth to the other side would produce better results. Might try this idea out and post the results.</p>Windows Explorer Undo Is Scary2016-11-17T00:00:00-05:002016-11-17T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-11-17:/posts/2016/11/windows-explorer-undo-is-scary/<p>The undo feature built into Windows Explorer is scary. Let me preface this statement by saying I have not yet moved pass Windows 7 so maybe the behavior has changed in newer releases. That being said, accidentally hitting Ctrl-Z while in Windows Explorer can be nerve wracking because depending on the action being undone, there may not be any prompt displayed. For example, a file that was renamed an hour ago might be undone without …</p><p>The undo feature built into Windows Explorer is scary. Let me preface this statement by saying I have not yet moved pass Windows 7 so maybe the behavior has changed in newer releases. That being said, accidentally hitting Ctrl-Z while in Windows Explorer can be nerve wracking because depending on the action being undone, there may not be any prompt displayed. For example, a file that was renamed an hour ago might be undone without any warning! When a prompt is displayed, it only shows the name of the file/directory and gives no indication as to the location. Grrr!</p>
<p>For a less anxiety inducing user experience, it would be nice to see a prompt that provides the following:</p>
<ul>
<li>The type of action about to be performed (rename/move/delete/etc).</li>
<li>The target files/directories including the full path.</li>
<li>The result files/directories including the full path.</li>
<li>An OK/CANCEL confirmation.</li>
</ul>
<p>We have the technology! For the most part, Windows is a great environment to work in. However, keep in mind that disaster is just a CTRL-Z away.</p>Quick Thought On GDEX2016-11-01T00:00:00-04:002016-11-01T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-11-01:/posts/2016/11/quick-thought-on-gdex/<p>Couple of quick thoughts on <a href="https://www.thegdex.com/">GDEX</a> this year:</p>
<ul>
<li>Big shout out to the <a href="http://www.fatesecho.com/">Fate's Echo</a> team! These guys are awesome and there game looks great! Just happened to meet them on the same day they met each other in person for the first time!</li>
<li>Of all the games at the show, Collapsis from <a href="http://www.wraithgames.com/">Wraith Games</a> stood out with its simple, fun gameplay.</li>
<li>The talk on arcade first development was very interesting. Enjoyed talking with the …</li></ul><p>Couple of quick thoughts on <a href="https://www.thegdex.com/">GDEX</a> this year:</p>
<ul>
<li>Big shout out to the <a href="http://www.fatesecho.com/">Fate's Echo</a> team! These guys are awesome and there game looks great! Just happened to meet them on the same day they met each other in person for the first time!</li>
<li>Of all the games at the show, Collapsis from <a href="http://www.wraithgames.com/">Wraith Games</a> stood out with its simple, fun gameplay.</li>
<li>The talk on arcade first development was very interesting. Enjoyed talking with the <a href="http://www.griffinaerotech.com/skycurser/">Skycursor</a> team!</li>
<li>Meeting <a href="https://twitter.com/daemzero">Daemon Hatfield</a> and attending his dance party was a blast! Been a fan of <a href="http://feeds.ign.com/ignfeeds/podcasts/gamescoop/">Game Scoop</a> for many years.</li>
</ul>Programming Language Popularity2016-10-22T00:00:00-04:002016-10-22T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-10-22:/posts/2016/10/programming-language-popularity/<p><strong>UPDATE</strong>: Complete data is now <a href="https://www.jeffcomput.es/prog-lang-popularity">available here</a>.</p>
<p>The following is some programming language popularity and average salary data collected from <a href="http://www.indeed.com/">Indeed</a> and the <a href="http://www.bls.gov/">US Bureau of Labor Statistics</a>.</p>
<p>The collected data included about 50 of the top programming languages in regular use. The popularity value is how a given language compares against all other languages. The employment number is an estimate for all of the US. The salary number is averaged over all the US …</p><p><strong>UPDATE</strong>: Complete data is now <a href="https://www.jeffcomput.es/prog-lang-popularity">available here</a>.</p>
<p>The following is some programming language popularity and average salary data collected from <a href="http://www.indeed.com/">Indeed</a> and the <a href="http://www.bls.gov/">US Bureau of Labor Statistics</a>.</p>
<p>The collected data included about 50 of the top programming languages in regular use. The popularity value is how a given language compares against all other languages. The employment number is an estimate for all of the US. The salary number is averaged over all the US. Please note this data is only an estimate.</p>
<p>Below are two tables showing the top 10 languages organized by popularity/employment and by salary. Interestingly, there is no overlap between the two. Maybe it is due to supply/demand or maybe just error in the data.</p>
<h4>Top 10 Programming Languages By Employment</h4>
<table>
<thead>
<tr>
<th>Language</th>
<th>Employment</th>
<th>Popularity (%)</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Java</td>
<td>688,388</td>
<td>20.40</td>
<td>$71,764</td>
</tr>
<tr>
<td>JavaScript</td>
<td>619,728</td>
<td>18.36</td>
<td>$88,169</td>
</tr>
<tr>
<td>C#</td>
<td>355,773</td>
<td>10.54</td>
<td>$82,156</td>
</tr>
<tr>
<td>Python</td>
<td>258,496</td>
<td>7.66</td>
<td>$87,581</td>
</tr>
<tr>
<td>C++</td>
<td>228,179</td>
<td>6.76</td>
<td>$106,928</td>
</tr>
<tr>
<td>C</td>
<td>226,932</td>
<td>6.72</td>
<td>$84,457</td>
</tr>
<tr>
<td>PHP</td>
<td>143,466</td>
<td>4.25</td>
<td>$74,627</td>
</tr>
<tr>
<td>Ruby</td>
<td>127,593</td>
<td>3.78</td>
<td>$92,856</td>
</tr>
<tr>
<td>Go</td>
<td>126,039</td>
<td>3.73</td>
<td>$99,392</td>
</tr>
<tr>
<td>Perl</td>
<td>104,544</td>
<td>3.09</td>
<td>$83,352</td>
</tr>
</tbody>
</table>
<h4>Top 10 Programming Languages By Salary</h4>
<table>
<thead>
<tr>
<th>Language</th>
<th>Employment</th>
<th>Popularity (%)</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Clojure</td>
<td>5,694</td>
<td>0.16</td>
<td>$183,705</td>
</tr>
<tr>
<td>D</td>
<td>70,847</td>
<td>2.10</td>
<td>$149,794</td>
</tr>
<tr>
<td>Erlang</td>
<td>2,639</td>
<td>0.07</td>
<td>$135,225</td>
</tr>
<tr>
<td>Dart</td>
<td>2,060</td>
<td>0.06</td>
<td>$115,843</td>
</tr>
<tr>
<td>Elm</td>
<td>1,355</td>
<td>0.04</td>
<td>$115,843</td>
</tr>
<tr>
<td>R</td>
<td>41,018</td>
<td>1.21</td>
<td>$115,235</td>
</tr>
<tr>
<td>Scala</td>
<td>33,914</td>
<td>1.00</td>
<td>$113,431</td>
</tr>
<tr>
<td>Elixir</td>
<td>1,518</td>
<td>0.04</td>
<td>$110,921</td>
</tr>
<tr>
<td>Swift</td>
<td>32,106</td>
<td>0.95</td>
<td>$108,588</td>
</tr>
<tr>
<td>Ada</td>
<td>10,882</td>
<td>0.32</td>
<td>$108,254</td>
</tr>
</tbody>
</table>Strange Electron Webview Behavior2016-09-10T00:00:00-04:002016-09-10T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-09-10:/posts/2016/09/strange-electron-webview-behavior/<p>Noticed some strange <a href="http://electron.atom.io/docs/api/web-view-tag/">Electron <code><webview></code></a> behavior while working on a proof-of-concept for the next version of <a href="https://github.com/jeffrimko/Doctrine">Doctrine</a>.</p>
<p>I have a simple page with a <code><webview></code> tag displaying a local HTML file. If the local HTML file contains a link and the user clicks on it, the default browser should open the URL instead of the <code><webview></code>.</p>
<p>The following code produces the expected results:</p>
<div class="highlight"><pre><span></span><code><span class="nx">webview</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'will-navigate'</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">=></span> <span class="p">{</span>
<span class="c1">// Order is important or URL will open in …</span></code></pre></div><p>Noticed some strange <a href="http://electron.atom.io/docs/api/web-view-tag/">Electron <code><webview></code></a> behavior while working on a proof-of-concept for the next version of <a href="https://github.com/jeffrimko/Doctrine">Doctrine</a>.</p>
<p>I have a simple page with a <code><webview></code> tag displaying a local HTML file. If the local HTML file contains a link and the user clicks on it, the default browser should open the URL instead of the <code><webview></code>.</p>
<p>The following code produces the expected results:</p>
<div class="highlight"><pre><span></span><code><span class="nx">webview</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'will-navigate'</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">=></span> <span class="p">{</span>
<span class="c1">// Order is important or URL will open in both external browser and webview!</span>
<span class="nx">shell</span><span class="p">.</span><span class="nx">openExternal</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">url</span><span class="p">);</span> <span class="c1">// Must be first!</span>
<span class="nx">webview</span><span class="p">.</span><span class="nx">stop</span><span class="p">();</span> <span class="c1">// Must be second!</span>
<span class="c1">// event.preventDefault(); // Has no effect...</span>
<span class="p">});</span>
</code></pre></div>
<p>The following is odd about this code:</p>
<ul>
<li>The <code>event.preventDefault()</code> call seems to have no effect no matter where it is placed. Would think that this call should prevent the <code><webview></code> from loading the URL but it does not.</li>
<li>The <code>webview.stop()</code> call <em>must</em> be after the <code>shell.openExternal()</code> call. This seems weird; no mention of such behavior in <a href="http://electron.atom.io/docs/api/shell/#shellopenexternalurl-options">the documentation</a>.</li>
</ul>
<p>Thinking this may warrant opening a bug report...</p>
<p>For context, here is the output of <code>console.log(process.versions)</code> for my development environment:</p>
<div class="highlight"><pre><span></span><code><span class="err">ares : "1.10.1-DEV"</span>
<span class="err">atom-shell : "1.3.0"</span>
<span class="err">chrome : "52.0.2743.82"</span>
<span class="err">electron : "1.3.0"</span>
<span class="err">http_parser : "2.7.0"</span>
<span class="err">modules : "49"</span>
<span class="err">node : "6.3.0"</span>
<span class="err">openssl : "1.0.2h"</span>
<span class="err">uv : "1.9.1"</span>
<span class="err">v8 : "5.2.361.43"</span>
<span class="err">zlib : "1.2.8"</span>
</code></pre></div>Weekly Picks - Soft Skills2016-08-26T00:00:00-04:002016-08-26T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-08-26:/posts/2016/08/weekly-picks-soft-skills/<p>Just a single pick this time but it is quite exceptional.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="https://talkpython.fm/episodes/show/71/soft-skills-the-software-developer-s-life-manual">Talk Python To Me, Episode 71, Soft Skills</a></em> - This episode has everything: solid advice for entrepreneurs, info on being a good employee, tips for interviewing. This podcast is excellent well worth a listen. I have not read John Sonmez's book yet but can't wait to after listening to this podcast.</li>
</ul>Quick Thoughts On Abstraction Conference2016-08-23T00:00:00-04:002016-08-23T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-08-23:/posts/2016/08/quick-thoughts-on-abstraction-conference/<p>Recently attended <a href="http://abstractions.io/">Abstractions Conference</a> in Pittsburgh. This was my first software-only conference. A few quick highlights from the convention:</p>
<ul>
<li>While I have no particular application in mind yet, <a href="http://elixir-lang.org/">Elixir</a> sounds intriguing. For embedded systems, <a href="http://nerves-project.org/">Nerves</a> sound neat but maybe not quite ready for prime time.</li>
<li>Joe Armstrong's idea of ubiquitous solar powered computing devices is quite interesting.</li>
<li>Scott Hanselman gave a highly entertaining talk on the Cloud, JavaScript, and the evolution of web technologies. Think …</li></ul><p>Recently attended <a href="http://abstractions.io/">Abstractions Conference</a> in Pittsburgh. This was my first software-only conference. A few quick highlights from the convention:</p>
<ul>
<li>While I have no particular application in mind yet, <a href="http://elixir-lang.org/">Elixir</a> sounds intriguing. For embedded systems, <a href="http://nerves-project.org/">Nerves</a> sound neat but maybe not quite ready for prime time.</li>
<li>Joe Armstrong's idea of ubiquitous solar powered computing devices is quite interesting.</li>
<li>Scott Hanselman gave a highly entertaining talk on the Cloud, JavaScript, and the evolution of web technologies. Think <a href="https://vimeo.com/153120762">this may be the same talk</a>, definitely worth a watch. <a href="http://hanselminutes.com/">His podcast</a> is excellent as well.</li>
<li>Ingy döt Net gave a great talk on YAML (which he invented). Really enjoyed his presentation style.</li>
<li>Lara Schenck gave a insightful talk on WordPress consulting. Took away some solid advise from her talk.</li>
<li>Laurie Voss gave a talk which was basically a whirlwind tour of npm. I really appreciate the cumulative problem-solving that went into npm; it's a great package manager.</li>
<li>Brad Frost gave a great talk on design. Atomic Design is a neat philosophy!</li>
<li>While a bit outside my wheelhouse, Kubernetes looks cool :)</li>
<li>I met at least two people using Haskell in production!</li>
</ul>Weekly Picks - Software Developer Showcase2016-07-31T00:00:00-04:002016-07-31T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-07-31:/posts/2016/07/weekly-picks-software-developer-showcase/<p>Something a little different this week. Picking a single software developer this week and showcasing a few of his/her projects.</p>
<p>The developer this week is <strong>Lu Wang</strong>, <a href="https://github.com/coolwanglu">coolwanglu on GitHub</a>.</p>
<h4>Software:</h4>
<ul>
<li><em><a href="https://github.com/coolwanglu/pdf2htmlEX">pdf2htmlEX</a></em> - Fantastic PDF to HTML converter. I've tried a few similar utilities and this one produces the best results by far.</li>
<li><em><a href="https://github.com/coolwanglu/neovim-e">neovim-e</a></em> - Electron-based GUI for Neovim.</li>
<li><em><a href="https://github.com/coolwanglu/vim.js">vim.js</a></em> - Port of VIM to JavaScript. Looks like <a href="https://github.com/kripken/emscripten">Emscripten</a> is being used for the transpilation.</li>
<li><em><a href="https://github.com/coolwanglu/OK">OK …</a></em></li></ul><p>Something a little different this week. Picking a single software developer this week and showcasing a few of his/her projects.</p>
<p>The developer this week is <strong>Lu Wang</strong>, <a href="https://github.com/coolwanglu">coolwanglu on GitHub</a>.</p>
<h4>Software:</h4>
<ul>
<li><em><a href="https://github.com/coolwanglu/pdf2htmlEX">pdf2htmlEX</a></em> - Fantastic PDF to HTML converter. I've tried a few similar utilities and this one produces the best results by far.</li>
<li><em><a href="https://github.com/coolwanglu/neovim-e">neovim-e</a></em> - Electron-based GUI for Neovim.</li>
<li><em><a href="https://github.com/coolwanglu/vim.js">vim.js</a></em> - Port of VIM to JavaScript. Looks like <a href="https://github.com/kripken/emscripten">Emscripten</a> is being used for the transpilation.</li>
<li><em><a href="https://github.com/coolwanglu/OK">OK</a></em> - Fun little browser-based memorization game.</li>
</ul>DevLog - Doctrine Updates2016-07-26T00:00:00-04:002016-07-26T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-07-26:/posts/2016/07/devlog-doctrine-updates/<p>I have been thinking over some updates for <a href="https://github.com/jeffrimko/doctrine">Doctrine</a>. In it's current state, Doctrine is a functional proof-of-concept of an application that renders AsciiDoc files while also applying some <a href="https://github.com/jeffrimko/UnifiedStyleGuide/blob/master/doc/special_files/main.adoc">Unified Style Guide (USG)</a> concepts. In the next iteration, my goal is to further integrate USG ideas to help set Doctrine apart from other AsciiDoc tools and also promote a standardized USG toolchain.</p>
<p>Here's an example of a USG idea that is currently implemented in <a href="https://github.com/jeffrimko/Doctrine/releases/tag/doctrine-0.1.0-alpha">Doctrine …</a></p><p>I have been thinking over some updates for <a href="https://github.com/jeffrimko/doctrine">Doctrine</a>. In it's current state, Doctrine is a functional proof-of-concept of an application that renders AsciiDoc files while also applying some <a href="https://github.com/jeffrimko/UnifiedStyleGuide/blob/master/doc/special_files/main.adoc">Unified Style Guide (USG)</a> concepts. In the next iteration, my goal is to further integrate USG ideas to help set Doctrine apart from other AsciiDoc tools and also promote a standardized USG toolchain.</p>
<p>Here's an example of a USG idea that is currently implemented in <a href="https://github.com/jeffrimko/Doctrine/releases/tag/doctrine-0.1.0-alpha">Doctrine <code>0.1.0-alpha</code></a>: if a zip file is opened in Doctrine, it will attempt to locate/render/display the archive info file (<code>__arc_info__.txt</code>, more info <a href="https://github.com/jeffrimko/UnifiedStyleGuide/blob/master/doc/special_files/main.adoc">here</a>). If the info file cannot be found, the first file that can be rendered will be displayed.</p>
<p>In the next iteration of Doctrine, I would like to at least like to start using <a href="http://asciidoctor.org/">Asciidoctor</a> since the original implementation of AsciiDoc is no longer being updated. Ideally, both implementations would be available in Doctrine.</p>
<p>Currently, I'm considering two options:</p>
<ol>
<li>Use C++ and Qt. Python and Ruby interpreters will be embedded to handle AsciiDoc rendering.</li>
<li>Use JavaScript and Electron. AsciiDoctor.js will be embedded to handle AsciiDoc rendering.</li>
</ol>
<p>Originally, I was leaning towards option 1 but it turns out Ruby is a pain to embed. Also, I've been interested in trying out Electron. I am almost certain option 2 will be much easier; the only potential drawback is the application size will be quite large compared to option 1. Might try to get a quick proof-of-concept running in Electron just see what is involved.</p>Weekly Picks - Video Games2016-07-22T00:00:00-04:002016-07-22T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-07-22:/posts/2016/07/weekly-picks-video-games/<p>Couple of video game related picks for this week.</p>
<h4>Games:</h4>
<ul>
<li><em><a href="http://ska-studios.com/salt/salt2.php">Salt and Santuary</a></em> - I recently finished this on PC but it is available on PS4 also. This game is basically 2D Dark Souls and does not shy away from that fact. It is well made and quite fun!</li>
</ul>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://www.ign.com/articles/2016/06/30/ign-unfiltered-08-xbox-co-creator-ed-fries">IGN Unfiltered Episode 8 - Ed Fries</a></em> - Excellent interview with Xbox co-creator Ed Fries. I had not heard of him previously but he is very fascinating. He …</li></ul><p>Couple of video game related picks for this week.</p>
<h4>Games:</h4>
<ul>
<li><em><a href="http://ska-studios.com/salt/salt2.php">Salt and Santuary</a></em> - I recently finished this on PC but it is available on PS4 also. This game is basically 2D Dark Souls and does not shy away from that fact. It is well made and quite fun!</li>
</ul>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://www.ign.com/articles/2016/06/30/ign-unfiltered-08-xbox-co-creator-ed-fries">IGN Unfiltered Episode 8 - Ed Fries</a></em> - Excellent interview with Xbox co-creator Ed Fries. I had not heard of him previously but he is very fascinating. He gives an interesting and insightful recount of early Microsoft and the creation of the Xbox.</li>
</ul>
<h4>Software:</h4>
<ul>
<li><em><a href="http://unity3d.com/">Unity</a></em> - Powerful, easy to learn game engine. I used it to develop my first game, <a href="https://play.google.com/store/apps/details?id=com.JeffRimko.Rollout">Rollout</a>.</li>
</ul>Rollout Released2016-07-02T00:00:00-04:002016-07-02T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-07-02:/posts/2016/07/rollout-released/<p>Yesterday marked the release of my first video game. <a href="https://play.google.com/store/apps/details?id=com.JeffRimko.Rollout">Rollout</a> is an Android port of <a href="https://www.jeffcomput.es/posts/2016/04/first-game-jam/">the project I started during the YSU game jam in April</a>. Releasing the game on Android was an exercise in bringing an idea to completion and learning Unity. Big thanks to the <a href="http://youngstowngamedevelopers.com/">Youngstown Game Developers group</a> and all the wonderful artists that provided assets free of charge (see the credits screen for more info).</p>
<p>Overall, I am pretty happy with …</p><p>Yesterday marked the release of my first video game. <a href="https://play.google.com/store/apps/details?id=com.JeffRimko.Rollout">Rollout</a> is an Android port of <a href="https://www.jeffcomput.es/posts/2016/04/first-game-jam/">the project I started during the YSU game jam in April</a>. Releasing the game on Android was an exercise in bringing an idea to completion and learning Unity. Big thanks to the <a href="http://youngstowngamedevelopers.com/">Youngstown Game Developers group</a> and all the wonderful artists that provided assets free of charge (see the credits screen for more info).</p>
<p>Overall, I am pretty happy with the results. There are still some issues with the game which might get addressed at some point. For instance, despite being <em>very</em> graphically simple, the game runs surprisingly slow on older Samsung Galaxy tablets. After sinking some hours into this issue, I am still not certain what causes the slowdown. Maybe I'll investigate more someday.</p>
<p>In the meantime, give Rollout a try! I hope to make a few more simple games soon. Let me know if you have any feedback.</p>Unified Style Guide - Syntax Brainstorming2016-06-18T00:00:00-04:002016-06-18T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-06-18:/posts/2016/06/unified-style-guide-syntax-brainstorming/<p>The <a href="https://github.com/jeffrimko/UnifiedStyleGuide">Unified Style Guide</a> (aka USG) is a side project I've been slowly piecing together over the past few years. It started mainly as an effort to document my personal preferences for structuring files and folders. A special file reserved in the style guide is the <a href="https://github.com/jeffrimko/UnifiedStyleGuide/blob/master/doc/special_files/main.adoc#13-directory-information">directory information file</a> which simply provides a plain text description of the directory contents. When necessary, I have been using these files to describe the naming convention of the …</p><p>The <a href="https://github.com/jeffrimko/UnifiedStyleGuide">Unified Style Guide</a> (aka USG) is a side project I've been slowly piecing together over the past few years. It started mainly as an effort to document my personal preferences for structuring files and folders. A special file reserved in the style guide is the <a href="https://github.com/jeffrimko/UnifiedStyleGuide/blob/master/doc/special_files/main.adoc#13-directory-information">directory information file</a> which simply provides a plain text description of the directory contents. When necessary, I have been using these files to describe the naming convention of the files contained within the parent directory.</p>
<p>I've been mulling over the idea of creating a utility to help with various items related to the USG such as style validation. One thought is to include a section in the directory info files which will provide the utility with file naming conventions. This would allow the utility to extract meta information from file names. For example, the following is one possible format of a directory info file:</p>
<div class="highlight"><pre><span></span><code><span class="err">=</span> <span class="nf">Example</span> <span class="no">Directory</span>
<span class="err">:</span><span class="nl">date:</span> <span class="err">18</span> <span class="nf">June</span> <span class="mi">2016</span>
<span class="nf">This</span> <span class="no">directory</span> <span class="no">contains</span> <span class="no">photos</span> <span class="no">and</span> <span class="no">text</span> <span class="no">files</span> <span class="no">with</span> <span class="no">a</span> <span class="no">short</span> <span class="no">description</span> <span class="no">about</span> <span class="no">each</span> <span class="no">photo.</span>
<span class="na">.Naming</span> <span class="no">Format</span>
<span class="err">--------</span>
<span class="nf">Photo</span> <span class="err">=</span> <span class="err"><</span><span class="no">YYYYMMDD</span><span class="err">></span><span class="p">-</span><span class="err"><</span><span class="no">Description</span><span class="err">></span><span class="p">(-</span><span class="err"><</span><span class="no">Extra</span><span class="err">></span><span class="p">).</span><span class="no">jpg</span>
<span class="nf">Notes</span> <span class="err">=</span> <span class="err"><</span><span class="no">YYYYMMDD</span><span class="err">></span><span class="p">-</span><span class="err"><</span><span class="no">Description</span><span class="err">></span><span class="p">(-</span><span class="err"><</span><span class="no">Extra</span><span class="err">></span><span class="p">).</span><span class="no">txt</span>
<span class="err">--------</span>
</code></pre></div>
<p>Consider a directory with the following contents:</p>
<div class="highlight"><pre><span></span><code><span class="err">MyPhotos/</span>
<span class="err">|-- 20160618-beach-sunset.jpg</span>
<span class="err">|-- 20160618-beach-sunset.txt</span>
<span class="err">|-- 20160617-forest.jpg</span>
<span class="err">|-- 20160617-forest.txt</span>
</code></pre></div>
<p>The JSON parsed from this directory might look like the following:</p>
<div class="highlight"><pre><span></span><code><span class="p">{</span><span class="nt">"Photo"</span><span class="p">:</span>
<span class="p">[{</span><span class="nt">"YYYYMMDD"</span><span class="p">:</span><span class="s2">"20160618"</span><span class="p">,</span><span class="nt">"Description"</span><span class="p">:</span><span class="s2">"beach"</span><span class="p">,</span><span class="nt">"Extra"</span><span class="p">:</span><span class="s2">"sunset"</span><span class="p">,</span><span class="nt">"Extension"</span><span class="p">:</span><span class="s2">"jpg"</span><span class="p">},</span>
<span class="p">{</span><span class="nt">"YYYYMMDD"</span><span class="p">:</span><span class="s2">"20160617"</span><span class="p">,</span><span class="nt">"Description"</span><span class="p">:</span><span class="s2">"forest"</span><span class="p">,</span><span class="nt">"Extension"</span><span class="p">:</span><span class="s2">"jpg"</span><span class="p">}],</span>
<span class="nt">"Notes"</span><span class="p">:</span>
<span class="p">[{</span><span class="nt">"YYYYMMDD"</span><span class="p">:</span><span class="s2">"20160618"</span><span class="p">,</span><span class="nt">"Description"</span><span class="p">:</span><span class="s2">"beach"</span><span class="p">,</span><span class="nt">"Extra"</span><span class="p">:</span><span class="s2">"sunset"</span><span class="p">,</span><span class="nt">"Extension"</span><span class="p">:</span><span class="s2">"txt"</span><span class="p">},</span>
<span class="p">{</span><span class="nt">"YYYYMMDD"</span><span class="p">:</span><span class="s2">"20160617"</span><span class="p">,</span><span class="nt">"Description"</span><span class="p">:</span><span class="s2">"forest"</span><span class="p">,</span><span class="nt">"Extension"</span><span class="p">:</span><span class="s2">"txt"</span><span class="p">}]}</span>
</code></pre></div>
<p>Now scripts could be written to use this meta information. The concept is still in the early phases and no code has been written yet but I have come across a few use cases for this type of functionality. Might make a good hack night project someday...</p>Weekly Picks - Python Gotcha Awareness2016-05-14T00:00:00-04:002016-05-14T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-05-14:/posts/2016/05/weekly-picks-python-gotcha-awareness/<p>While mostly straightforward and simple, Python still has its share of gotchas and gremlins, one such explored <a href="https://www.jeffcomput.es/posts/2015/02/python-gotcha-globals-and-namespaces/">in this post</a>. Familiarizing yourself with common gotchas can help avoid issues and aid debugging.</p>
<h4>Articles:</h4>
<ul>
<li><em><a href="https://www.toptal.com/python/top-10-mistakes-that-python-programmers-make">The 10 Most Common Mistakes That Python Developers Make</a></em> - Earlier versions of <a href="https://github.com/jeffrimko/Qprompt">my Qprompt library</a> suffered from mistake #1 (facepalm!). In my defense, there may be a violation of the <a href="https://en.wikipedia.org/wiki/Principle_of_least_astonishment">principle of least astonishment</a> here. However, I also understand that changing the …</li></ul><p>While mostly straightforward and simple, Python still has its share of gotchas and gremlins, one such explored <a href="https://www.jeffcomput.es/posts/2015/02/python-gotcha-globals-and-namespaces/">in this post</a>. Familiarizing yourself with common gotchas can help avoid issues and aid debugging.</p>
<h4>Articles:</h4>
<ul>
<li><em><a href="https://www.toptal.com/python/top-10-mistakes-that-python-programmers-make">The 10 Most Common Mistakes That Python Developers Make</a></em> - Earlier versions of <a href="https://github.com/jeffrimko/Qprompt">my Qprompt library</a> suffered from mistake #1 (facepalm!). In my defense, there may be a violation of the <a href="https://en.wikipedia.org/wiki/Principle_of_least_astonishment">principle of least astonishment</a> here. However, I also understand that changing the behavior of a well established technology is difficult.</li>
</ul>First Game Jam2016-04-05T00:00:00-04:002016-04-05T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-04-05:/posts/2016/04/first-game-jam/<p>This past weekend, I participated in my first game jam. It was a lot of fun and a great learning opportunity; I learned more about game development in that 48 hours than in the past year. Here is a screenshot of my game in development:</p>
<p><img alt="YSU Game Jam 2016" src="/images/game_jam_1.jpg" title="YSU Game Jam 2016"></p>
<p>Pretty sweet, right? Here are a few links related to this event:</p>
<ul>
<li><a href="http://youngstowngamedevelopers.com/game-jams/april-game-jam-2016/">Game Jam Event Page</a></li>
<li><a href="https://github.com/jeffrimko/GameJam-YSU2016">GitHub Repo For My Game</a></li>
<li><a href="https://jeffrimko.itch.io/breakout">Itch.io Page For My Game</a></li>
</ul>
<p>If you are …</p><p>This past weekend, I participated in my first game jam. It was a lot of fun and a great learning opportunity; I learned more about game development in that 48 hours than in the past year. Here is a screenshot of my game in development:</p>
<p><img alt="YSU Game Jam 2016" src="/images/game_jam_1.jpg" title="YSU Game Jam 2016"></p>
<p>Pretty sweet, right? Here are a few links related to this event:</p>
<ul>
<li><a href="http://youngstowngamedevelopers.com/game-jams/april-game-jam-2016/">Game Jam Event Page</a></li>
<li><a href="https://github.com/jeffrimko/GameJam-YSU2016">GitHub Repo For My Game</a></li>
<li><a href="https://jeffrimko.itch.io/breakout">Itch.io Page For My Game</a></li>
</ul>
<p>If you are at all interested in video game development, definitely consider attending a jam. They are a great opportunity to learn and meet like-minded people. To find a jam near you, check out <a href="https://itch.io/jams">this schedule from itch.io</a>.</p>Unified Style Guide Thoughts - Doctrine And Archiver2016-03-18T00:00:00-04:002016-03-18T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-03-18:/posts/2016/03/unified-style-guide-thoughts-doctrine-and-archiver/<p>The <a href="https://github.com/jeffrimko/UnifiedStyleGuide">Unified Style Guide</a> (USG) is a project that I have been slowly piecing together to better organize files and directories. The premise of the project (and all style guide projects) is to provide a straightforward guide that is well thought-out and takes the guesswork out of most use cases. I will anguish over all the trivial, mundane details so you don't have too!</p>
<p>The two utilities that support the USG are <a href="https://github.com/jeffrimko/Doctrine">Doctrine</a> and <a href="https://github.com/jeffrimko/Archiver">Archiver …</a></p><p>The <a href="https://github.com/jeffrimko/UnifiedStyleGuide">Unified Style Guide</a> (USG) is a project that I have been slowly piecing together to better organize files and directories. The premise of the project (and all style guide projects) is to provide a straightforward guide that is well thought-out and takes the guesswork out of most use cases. I will anguish over all the trivial, mundane details so you don't have too!</p>
<p>The two utilities that support the USG are <a href="https://github.com/jeffrimko/Doctrine">Doctrine</a> and <a href="https://github.com/jeffrimko/Archiver">Archiver</a>. While functional, I am always thinking about updates that would make them better.</p>
<p>Archiver has a few bugs that need ironed out such as occasional freezes and issues with too many input files. I've kicked around the idea of adding functionality to guess a <a href="https://github.com/jeffrimko/UnifiedStyleGuide/blob/master/doc/files_and_dirs/main.adoc#2-file-naming">USG compliant filename</a>. Otherwise, the feature set is fairly stable. One certain change that will be made in the next release is <code>__archive_info__.txt</code> files will now be <code>__arc_info__.txt</code> and setext-style titles will no longer be used.</p>
<p>Doctrine in its current state is a decent proof-of-concept but I believe it has a lot more potential. Ultimately, I would like the ability to chose how the file is rendered; this would require embedding various utilities such as Asciidoc (already embedded), Asciidoctor, and perhaps Pandoc. When opening an archive, it would be nice to choose which file is rendered (currently it guesses). While conceptually not quite flushed out, the ability to browse directories while viewing the associated <code>__dir_info__.txt</code> files would be neat. Overall, there is a lot that could be added to improve the user experience.</p>Weekly Picks - Unusual Drinks2016-03-18T00:00:00-04:002016-03-18T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2016-03-18:/posts/2016/03/weekly-picks-unusual-drinks/<p>Been trying out a few unusual drinks (for me at least).</p>
<h4>Food:</h4>
<ul>
<li><em>Coffee with butter</em> - After listening to <a href="http://www.jamesaltucher.com/2016/02/ep-153-dave-asprey/">Dave Asprey on the James Altucher Show</a>, I had to try this. Not because of the potentially over-hyped medicinal benefits, but for two simple facts: coffee is delicious, butter is delicious. Turns out a mug of coffee with about 1 tablespoon of butter blended into it is pretty delicious! While still nutritionally skeptical of this combination, I …</li></ul><p>Been trying out a few unusual drinks (for me at least).</p>
<h4>Food:</h4>
<ul>
<li><em>Coffee with butter</em> - After listening to <a href="http://www.jamesaltucher.com/2016/02/ep-153-dave-asprey/">Dave Asprey on the James Altucher Show</a>, I had to try this. Not because of the potentially over-hyped medicinal benefits, but for two simple facts: coffee is delicious, butter is delicious. Turns out a mug of coffee with about 1 tablespoon of butter blended into it is pretty delicious! While still nutritionally skeptical of this combination, I have noticed that the associated coffee buzz seems much mellower and is no longer accompanied by sudden onset sleepiness a few hours later.</li>
<li><em>Milk with turmeric, ginger, pepper, and honey</em> - While coffee and butter sounded like a good combination, this drink sounded like crazy sauce. I mostly followed <a href="http://www.freshbitesdaily.com/turmeric-milk/">this recipe</a> but microwaved the milk then blended everything together. Overall, it is not bad and I find it oddly comforting. The spicy bitterness of turmeric may be a little overwhelming for some people.</li>
</ul>QuickWin 0.3.0 Preview And Thoughts2016-03-04T00:00:00-05:002016-03-04T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-03-04:/posts/2016/03/quickwin-030-preview-and-thoughts/<p>Been working on some updates to <a href="https://github.com/jeffrimko/QuickWin">QuickWin</a> recently. QuickWin was ultimately developed to scratch a productivity itch that had been bugging me for a while. There are some similar projects available such as <a href="https://github.com/christianrondeau/GoToWindow">GoToWindow</a> and <a href="https://github.com/studgeek/AltTabAHK">AltTabAHK</a> but nothing quite hit the feature set I wanted. Overall, I am happy with how functional QuickWin has proven to be; it has quickly integrated into my workflow over the past few months of usage.</p>
<h4>New Feature Examples</h4>
<p>The …</p><p>Been working on some updates to <a href="https://github.com/jeffrimko/QuickWin">QuickWin</a> recently. QuickWin was ultimately developed to scratch a productivity itch that had been bugging me for a while. There are some similar projects available such as <a href="https://github.com/christianrondeau/GoToWindow">GoToWindow</a> and <a href="https://github.com/studgeek/AltTabAHK">AltTabAHK</a> but nothing quite hit the feature set I wanted. Overall, I am happy with how functional QuickWin has proven to be; it has quickly integrated into my workflow over the past few months of usage.</p>
<h4>New Feature Examples</h4>
<p>The command syntax has been refined. Commands are still separated by semicolons but substrings will be matched to the proper command.</p>
<p><a href="/images/qw030_cmdsub.gif" title="QuickWin Commands"><img alt="GIF" src="/images/qw030_cmdsub.gif" title="QuickWin Commands"></a></p>
<p>Can now filter windows by simple regex expressions (wildcards and ranges).</p>
<p><a href="/images/qw030_wildcard.gif" title="QuickWin Wildcard"><img alt="GIF" src="/images/qw030_wildcard.gif" title="QuickWin Wildcard"></a></p>
<p>Can now filter windows by number and executable name.</p>
<p><a href="/images/qw030_numexe.gif" title="QuickWin Filter Num/Exe"><img alt="GIF" src="/images/qw030_numexe.gif" title="QuickWin Filter Num/Exe"></a></p>
<p>Can now chain together some commands together. For example, filter on executable then set alias.</p>
<p><a href="/images/qw030_filterset.gif" title="QuickWin Filter Then Set"><img alt="GIF" src="/images/qw030_filterset.gif" title="QuickWin Filter Then Set"></a></p>
<h4>Some Thoughts</h4>
<p>One additional feature that might be useful is to filter on multiple columns; e.g. filter on an executable then on a title. I was not able to find an easy way to do this and need to use the new version for a while to see if this feature seems necessary. Also, the codebase is sort of a mess right now. This project resulted from a few hour hackathon; functionality was held in higher regard than cleanliness. Someday I will get around to cleaning it. Someday...</p>
<p>Oh, an installer would be nice. And cross-platform builds too. Need to build up a user base before tackling these items.</p>Vim Tips - Helpful Leader Key Mappings2016-02-29T00:00:00-05:002016-02-29T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-02-29:/posts/2016/02/vim-tips-helpful-leader-key-commands/<p>The leader key is a useful way of creating custom mappings in Vim. While browsing code in normal mode, it can be useful to quickly toggle settings on and off or execute other commands. By defining mappings with the leader key, a short sequence of keys can be used to quickly execute commands. Check out <code>:help <Leader></code> for more information on the leader key and defining mappings.</p>
<p>This post contains some examples from my vimrc …</p><p>The leader key is a useful way of creating custom mappings in Vim. While browsing code in normal mode, it can be useful to quickly toggle settings on and off or execute other commands. By defining mappings with the leader key, a short sequence of keys can be used to quickly execute commands. Check out <code>:help <Leader></code> for more information on the leader key and defining mappings.</p>
<p>This post contains some examples from my vimrc file that are frequently helpful. These mappings should work on gVim 7.3 (probably other Vim/gVim versions too but not tested) without additional dependencies.</p>
<p><strong>UPDATE</strong>: Simplified toggle commands thanks to suggestion from Reddit user <a href="https://www.reddit.com/user/Elessardan">Elessardan</a>. Updated use case info and "mapping" verbage thanks to suggestion from Reddit user <a href="https://www.reddit.com/user/-romainl-">-romainl-</a>. Various simplifications and updates thanks to suggestions from <a href="https://www.reddit.com/r/vim/comments/48n2ap/helpful_leader_key_commands_with_gifs/">this Reddit thread</a>. Please note the GIFs still show the original mappings.</p>
<hr>
<h4>Toggle Line Wrap</h4>
<p>Useful when working with long lines or small windows.</p>
<div class="highlight"><pre><span></span><code><span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>wr :<span class="k">set</span> <span class="nb">wrap</span><span class="p">!</span> <span class="nb">wrap</span>?<span class="p"><</span>CR<span class="p">></span>
</code></pre></div>
<p><img alt="Vim Wrap Toggle" src="/images/vim_wrap.gif" title="Vim Wrap Toggle"></p>
<hr>
<h4>Highlight Word Under Cursor</h4>
<p>Useful for quickly identifying instances of a word. Use <code>n</code> or <code>SHIFT-n</code> to jump between matches and <code>:noh</code> to turn off highlighting.</p>
<div class="highlight"><pre><span></span><code><span class="c">" Case sensitive, partial match inclusive.</span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span><span class="k">hi</span> :<span class="k">set</span> <span class="nb">hlsearch</span><span class="p"><</span>CR<span class="p">></span>:<span class="k">let</span> @/<span class="p">=</span><span class="s1">'<C-r><C-w>'</span><span class="p"><</span>CR<span class="p">></span>
<span class="c">" Case sensitive, no partial match.</span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>ho :<span class="k">set</span> <span class="nb">hlsearch</span><span class="p"><</span>CR<span class="p">></span>:<span class="k">let</span> @/<span class="p">=</span><span class="s1">'\<<C-r><C-w>\>'</span><span class="p"><</span>CR<span class="p">></span>
<span class="c">" Case insensitive, partial match inclusive.</span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>hu :<span class="k">set</span> <span class="nb">hlsearch</span><span class="p"><</span>CR<span class="p">></span>:<span class="k">let</span> @/<span class="p">=</span><span class="s1">'<C-r><C-w>\c'</span><span class="p"><</span>CR<span class="p">></span>
<span class="c">" Case insensitive, no partial match.</span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>hy :<span class="k">set</span> <span class="nb">hlsearch</span><span class="p"><</span>CR<span class="p">></span>:<span class="k">let</span> @/<span class="p">=</span><span class="s1">'\<<C-r><C-w>\>\c'</span><span class="p"><</span>CR<span class="p">></span>
</code></pre></div>
<p><img alt="Vim Highlight" src="/images/vim_highlight.gif" title="Vim Highlight"></p>
<hr>
<h4>Toggle List (Whitespace) Display</h4>
<p>Can be useful depending on your Vim setup. I typically use 4 spaces for indentation but some people prefer tabs. My <code>listchars</code> variable is set to display tabs as <code>>·</code> but sometimes it is nice to quickly hide the list characters (especially if editing a file where someone mixed tabs and spaces, the savage).</p>
<div class="highlight"><pre><span></span><code><span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>li :<span class="k">set</span> <span class="nb">list</span><span class="p">!</span> <span class="nb">list</span>?<span class="p"><</span>CR<span class="p">></span>
</code></pre></div>
<p><img alt="Vim List Toggle" src="/images/vim_list.gif" title="Vim List Toggle"></p>
<hr>
<h4>Zoom (Sorta)</h4>
<p>Zooming out can be useful for navigation (like the minimap in Sublime Text). Zooming in can be useful for presentations. Keep in mind this is not really a zoom, it is just changing the font size. This can cause some strange side-effects such as changing window size and position.</p>
<div class="highlight"><pre><span></span><code><span class="c">" Simple zoom hacks; Ultra, Extra, Normal, Out.</span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>zu :<span class="k">set</span> <span class="nb">guifont</span><span class="p">=</span>courier_new:h24<span class="p"><</span>CR<span class="p">></span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>ze :<span class="k">set</span> <span class="nb">guifont</span><span class="p">=</span>courier_new:h18<span class="p"><</span>CR<span class="p">></span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>zn :<span class="k">set</span> <span class="nb">guifont</span><span class="p">=</span>courier_new:h10<span class="p"><</span>CR<span class="p">></span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>zo :<span class="k">set</span> <span class="nb">guifont</span><span class="p">=</span>courier_new:h4<span class="p"><</span>CR<span class="p">></span>
</code></pre></div>
<p><img alt="Vim Zoom" src="/images/vim_zoom.gif" title="Vim Zoom"></p>
<hr>
<h4>Cursor Highlight</h4>
<p>Highlighting the cursor line is pretty standard but there is a known issue in Vim which causes slowdown when long lines are highlighted; quickly toggling line highlighting can be useful. Toggling column toggling can be occasionally useful too.</p>
<div class="highlight"><pre><span></span><code><span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span><span class="k">cl</span> :<span class="k">set</span> <span class="nb">cursorline</span><span class="p">!<</span>CR<span class="p">></span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span><span class="k">cc</span> :<span class="k">set</span> <span class="nb">cursorcolumn</span><span class="p">!<</span>CR<span class="p">></span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>cx :<span class="k">set</span> <span class="nb">cursorcolumn</span> <span class="nb">cursorline</span><span class="p"><</span>CR<span class="p">></span>
<span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span><span class="k">cn</span> :<span class="k">set</span> <span class="nb">nocursorline</span> <span class="nb">nocursorcolumn</span><span class="p"><</span>CR<span class="p">></span>
</code></pre></div>
<p><img alt="Vim Cursor Toggling" src="/images/vim_cursor.gif" title="Vim Cursor Toggling"></p>
<hr>
<h4>Fix Spelling</h4>
<p>Use this to quickly fix spelling mistakes. Use <code>]s</code> and <code>[s</code> to jump between flagged mistakes.</p>
<div class="highlight"><pre><span></span><code><span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span><span class="nb">fs</span> <span class="m">1</span>z<span class="p">=</span>
</code></pre></div>
<p><img alt="Vim Fix Spelling" src="/images/vim_spell.gif" title="Vim Fix Spelling"></p>
<hr>
<h4>Open VIMRC</h4>
<p>Use this to quickly open your vimrc file.</p>
<div class="highlight"><pre><span></span><code><span class="nb">nnoremap</span> <span class="p"><</span>Leader<span class="p">></span>rc :<span class="k">e</span> $MYVIMRC<span class="p"><</span>CR<span class="p">></span>
</code></pre></div>
<p><img alt="Vim VIMRC" src="/images/vim_vimrc.gif" title="Vim VIMRC"></p>Automate Stdin For Python Tests (Updated)2016-02-25T00:00:00-05:002016-02-25T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-02-25:/posts/2016/02/automate-stdin-for-python-tests-updated/<p><strong>NOTE:</strong> This is an update to a <a href="https://www.jeffcomput.es/posts/2016/01/automate-stdin-for-python-tests/">previous post</a>.</p>
<p>The following can be used to programmatically set stdin for testing under Python 3.x:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">io</span> <span class="kn">import</span> <span class="n">StringIO</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdin</span> <span class="o">=</span> <span class="n">StringIO</span><span class="p">()</span>
<span class="n">setinput</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="p">[</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">x</span><span class="p">),</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">)]</span>
</code></pre></div>
<p>Here is a quick example of using <code>setinput()</code> in Python 3.x:</p>
<div class="highlight"><pre><span></span><code><span class="n">setinput</span><span class="p">(</span><span class="s2">"Jeff"</span><span class="p">)</span>
<span class="n">name</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">"Enter name:"</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
</code></pre></div>Vim/Python Compatibility Issue2016-02-25T00:00:00-05:002016-02-25T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-02-25:/posts/2016/02/vimpython-compatibility-issue/<p>Found out the hard way that certain versions of Vim are not compatible with certain versions of Python. I keep my installation of Vim 7.3.712 on Dropbox so I can use it across multiple computers. While trying to run gVim on a new PC with Python 2.7.11 installed, gVim would close without warning or an error message when trying to open files.</p>
<p>Found out the cause was the one plugin I …</p><p>Found out the hard way that certain versions of Vim are not compatible with certain versions of Python. I keep my installation of Vim 7.3.712 on Dropbox so I can use it across multiple computers. While trying to run gVim on a new PC with Python 2.7.11 installed, gVim would close without warning or an error message when trying to open files.</p>
<p>Found out the cause was the one plugin I use that requires Python.</p>
<p>After a Google search, I found <a href="http://stackoverflow.com/questions/32025090/vim-for-windows-python-doesnt-load-properly-crashes">this StackOverflow thread</a> that mentions newer versions of Python 2.7 may not work properly with Vim. Downgrading Python to 2.7.7 fixed the issue.</p>Weekly Picks - Systems2016-01-20T00:00:00-05:002016-01-20T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-01-20:/posts/2016/01/weekly-picks-systems/<p>Some system related picks this week.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://johnackley.com/systemsmarts/">System Smarts</a></em> - New podcast focusing on all aspects of systems.</li>
</ul>
<h4>Software:</h4>
<ul>
<li><em><a href="http://www.graphviz.org/">Graphviz</a></em> - Diagramming and visualization tool that uses a text-based markup. Works well for documenting system design.</li>
<li><em><a href="http://www.mcternan.me.uk/mscgen/">Mscgen</a></em> - Message diagramming tool that uses a text-based markup. Great for documenting any system that has intercommunicating components.</li>
</ul>Automate Stdin For Python Tests2016-01-09T00:00:00-05:002016-01-09T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-01-09:/posts/2016/01/automate-stdin-for-python-tests/<p><strong>NOTE:</strong> The information in this post applies to Python 2.x only. See <a href="https://www.jeffcomput.es/posts/2016/02/automate-stdin-for-python-tests-updated/">this post</a> for Python 3.x support.</p>
<p>While working on Qprompt (a Python CLI based user input libary), I wanted to write some tests to check for regressions. The following lambda function allows stdin to be programmatically set:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">StringIO</span><span class="o">,</span> <span class="nn">sys</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdin</span> <span class="o">=</span> <span class="n">StringIO</span><span class="o">.</span><span class="n">StringIO</span><span class="p">()</span>
<span class="n">setinput</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="p">[</span><span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">)]</span>
</code></pre></div>
<p>The following …</p><p><strong>NOTE:</strong> The information in this post applies to Python 2.x only. See <a href="https://www.jeffcomput.es/posts/2016/02/automate-stdin-for-python-tests-updated/">this post</a> for Python 3.x support.</p>
<p>While working on Qprompt (a Python CLI based user input libary), I wanted to write some tests to check for regressions. The following lambda function allows stdin to be programmatically set:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">StringIO</span><span class="o">,</span> <span class="nn">sys</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdin</span> <span class="o">=</span> <span class="n">StringIO</span><span class="o">.</span><span class="n">StringIO</span><span class="p">()</span>
<span class="n">setinput</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="p">[</span><span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">)]</span>
</code></pre></div>
<p>The following is an example test scenario that checks the <code>ask_int()</code> function:</p>
<div class="highlight"><pre><span></span><code><span class="n">setinput</span><span class="p">(</span><span class="s2">"42"</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">ask_int</span><span class="p">()</span>
<span class="nb">print</span> <span class="n">result</span> <span class="c1"># 42</span>
<span class="nb">print</span> <span class="nb">type</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="c1"># <type 'int'></span>
</code></pre></div>Python Pattern Matching, Sorta2016-01-07T00:00:00-05:002016-01-07T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-01-07:/posts/2016/01/python-pattern-matching-sorta/<p>This trick is neat and potentially useful although maybe not very Pythonic:</p>
<div class="highlight"><pre><span></span><code><span class="n">txt</span> <span class="o">=</span> <span class="s2">"two"</span>
<span class="n">val</span> <span class="o">=</span> <span class="p">(</span>
<span class="mi">1</span> <span class="k">if</span> <span class="n">txt</span> <span class="o">==</span> <span class="s2">"one"</span> <span class="k">else</span>
<span class="mi">2</span> <span class="k">if</span> <span class="n">txt</span> <span class="o">==</span> <span class="s2">"two"</span> <span class="k">else</span>
<span class="mi">3</span> <span class="k">if</span> <span class="n">txt</span> <span class="o">==</span> <span class="s2">"three"</span> <span class="k">else</span>
<span class="mi">0</span><span class="p">)</span>
<span class="nb">print</span> <span class="n">val</span>
</code></pre></div>
<p>The following form can be used instead:</p>
<div class="highlight"><pre><span></span><code><span class="n">txt</span> <span class="o">=</span> <span class="s2">"three"</span>
<span class="n">val</span> <span class="o">=</span> \
<span class="mi">1</span> <span class="k">if</span> <span class="n">txt</span> <span class="o">==</span> <span class="s2">"one"</span> <span class="k">else</span> \
<span class="mi">2</span> <span class="k">if</span> <span class="n">txt</span> <span class="o">==</span> <span class="s2">"two"</span> <span class="k">else</span> \
<span class="mi">3</span> <span class="k">if</span> <span class="n">txt</span> <span class="o">==</span> <span class="s2">"three"</span> <span class="k">else</span> \
<span class="mi">0</span>
<span class="nb">print</span> <span class="n">val</span>
</code></pre></div>Resolutions That Work2016-01-03T00:00:00-05:002016-01-03T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2016-01-03:/posts/2016/01/resolutions-that-work/<p>Last January, I made a resolution to walk 3 million steps during the year. With the help of a cheap step counter and a spreadsheet, I am happy to say it may have been the first New Years resolution that I actually completed! While preparing a list of resolutions for 2016, the following criteria will help guarantee success:</p>
<ul>
<li><em>Progress must be measurable!</em> - Keep track of your progress periodically to make sure you will hit your …</li></ul><p>Last January, I made a resolution to walk 3 million steps during the year. With the help of a cheap step counter and a spreadsheet, I am happy to say it may have been the first New Years resolution that I actually completed! While preparing a list of resolutions for 2016, the following criteria will help guarantee success:</p>
<ul>
<li><em>Progress must be measurable!</em> - Keep track of your progress periodically to make sure you will hit your goal.</li>
<li><em>Goals must be realistic!</em> - My goal of 3 million steps means I had to average 8000 steps per day, about 80 minutes of walking. Anything more than that would have been difficult to achieve.</li>
<li><em>You cannot hate the activity!</em> - Reaching your goal will be difficult if you dread putting in the time or effort.</li>
</ul>
<p>Good luck, stay on target, and you will definitely hit all of your 2016 resolutions!</p>Wordless - A Better Document Toolchain2015-11-22T00:00:00-05:002015-11-22T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2015-11-22:/posts/2015/11/wordless-a-better-document-toolchain/<p>I was raised during a generation where writing on a computer was virtually synonymous with using Microsoft Word (little has changed since). However, as I grew versed in the landscape of software development utilities, I knew there had to be a better way to write. For me, the perfect writing toolchain needed the following qualities:</p>
<ul>
<li>Content should be portable.</li>
<li>Content should play nice with version control and diff tools.</li>
<li>Content should be grep-able.</li>
<li>Structure emphasized …</li></ul><p>I was raised during a generation where writing on a computer was virtually synonymous with using Microsoft Word (little has changed since). However, as I grew versed in the landscape of software development utilities, I knew there had to be a better way to write. For me, the perfect writing toolchain needed the following qualities:</p>
<ul>
<li>Content should be portable.</li>
<li>Content should play nice with version control and diff tools.</li>
<li>Content should be grep-able.</li>
<li>Structure emphasized over presentation.</li>
<li>Automation should be straightforward.</li>
</ul>
<p>Some common themes can be picked out from these qualities:</p>
<ul>
<li>Plain text is preferable to binary formats.</li>
<li>Battling WYSIWYG nuances should not impede writing.</li>
</ul>
<p>Luckily, many software developers share a similar philosophy for writing and a wealth of high-quality utilities are now available. Having tried several solutions, I have found the following use case/software pairings to work well for my needs:</p>
<ul>
<li>Simply formatted notes/articles/posts - Markdown/Pandoc (or similar).</li>
<li>More detailed notes/documents - AsciiDoc/AsciiDoctor.</li>
<li>Formal, page-oriented documents - LaTeX.</li>
<li>Heavily formatted single-page documents - LibreOffice/InkScape.</li>
</ul>
<p>In the following sections, let's take a closer look at the four solutions and answer the follow questions for each:</p>
<ul>
<li>What is it?</li>
<li>How is it used?</li>
<li>What software is used?</li>
</ul>
<p>First, some terminology should be cleared up. For me there are two common types of documents:</p>
<ul>
<li><strong>page-oriented</strong> - These documents are intended to be physically printed onto paper. The page size greatly influences the presentation and structure of the document. Typical file format is PDF.</li>
<li><strong>screen-oriented</strong> - These documents are intended to be viewed on a screen (via web browser or similar). Typical file format is HTML.</li>
</ul>
<h2>Markdown</h2>
<h3>What is it?</h3>
<p>Markdown is a text-based markup that has become wildly popular. It has a simple, easy to understand and remember syntax that provides the bare formatting essentials.</p>
<h3>How is it used?</h3>
<p>Primarily for blog posts. Occasionally for quick notes. Sometimes for documentation that accompanies software projects (e.g. readme and changelog files).</p>
<h3>What software is used?</h3>
<p>For blogging, practically all static website generates support Markdown. I use <a href="http://docs.getpelican.com/">Pelican</a> for this blog but there are numerous other options available.</p>
<p>Outside of blogging, <a href="http://pandoc.org/">Pandoc</a> is the go-to utility for all things Markdown.</p>
<p>Like all plain-text markups, your text editor of choice can be used to actually write the documents. I prefer <a href="http://www.vim.org/">Vim</a> and there is great support for Markdown syntax highlighting and folding.</p>
<h2>AsciiDoc</h2>
<h3>What is it?</h3>
<p>AsciiDoc is essentially a supercharged version of Markdown. It provides a wide variety of formatting options which allows for expressive, well designed documents.</p>
<h3>How is it used?</h3>
<p>I use AsciiDoc whenever possible, especially for screen-oriented documents. Most things I write on a regular basis are done with AsciiDoc. To be completely honest, the other utilities in this writing toolchain are only employed because they are slightly better suited for their use case than AsciiDoc.</p>
<h3>What software is used?</h3>
<p>While no longer actively developed, the original Python implementation of <a href="http://asciidoc.org/">AsciiDoc</a> is still my utility of choice. It is simple to use and provides all the functionality I need for now.</p>
<p><a href="http://asciidoctor.org/">AsciiDoctor</a> is a newer implementation that will likely succeed the original. There are some synatical changes that are not backwards compatible which may be an issue for existing documents.</p>
<p>Additionally, Pandoc can be used to output a file to AsciiDoc but it cannot directly read AsciiDoc. The workaround is to first convert an AsciiDoc file to DocBook which can be read directly by Pandoc.</p>
<h2>LaTeX</h2>
<h3>What is it?</h3>
<p>LaTeX is a highly configurable markup and typesetting system. It excels at generating formal page-oriented documents.</p>
<h3>How is it used?</h3>
<p>When the need arises for formal documents with a sharp professional look, LaTeX is the way to go. While there is a bit of a time investment getting the initial packages and styling configured, reusing the settings for other documents is simple.</p>
<h3>What software is used?</h3>
<p>On Windows, <a href="http://miktex.org/">MiKTeX</a> is the best LaTeX implementation around. If the document will need to be displayed on the web, I highly recommend running the LaTeX generated PDF file through the exceptionally awesome <a href="https://github.com/coolwanglu/pdf2htmlEX">pdf2htmlEX</a> utility.</p>
<h2>LibreOffice/InkScape</h2>
<h3>What is it?</h3>
<p>LibreOffice is an open-source alternative to Microsoft Office. InkScape is an open-source vector graphics suite.</p>
<h3>How is it used?</h3>
<p>Sometimes the need for a heavily formatted single page document is necessary (e.g. a resume or flyer). For this use case, WYSIWYG comes in handy as there can be no question about how the final product will look.</p>
<h3>What software is used?</h3>
<p>Well <a href="https://www.libreoffice.org/">LibreOffice</a> and <a href="https://inkscape.org/">InkScape</a> of course!</p>Introducing Qprompt2015-10-31T00:00:00-04:002015-10-31T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-10-31:/posts/2015/10/introducing-qprompt/<p>Python is an excellent multipurpose language. However, when writing scripts (in the shell script sense), a decent command-line user interface is necessary. Qprompt is a library of simple command-line interface functions that should simplify common tasks. For example, to ask the user for an integer between 1 and 100, simply use the following:</p>
<div class="highlight"><pre><span></span><code><span class="err">qprompt.ask_int(vld=range(1,101))</span>
</code></pre></div>
<p>Menus are straightforward as well:</p>
<div class="highlight"><pre><span></span><code><span class="err">menu = qprompt.Menu()</span>
<span class="err">menu.add("1", "Item 1")</span>
<span class="err">menu.add("2 …</span></code></pre></div><p>Python is an excellent multipurpose language. However, when writing scripts (in the shell script sense), a decent command-line user interface is necessary. Qprompt is a library of simple command-line interface functions that should simplify common tasks. For example, to ask the user for an integer between 1 and 100, simply use the following:</p>
<div class="highlight"><pre><span></span><code><span class="err">qprompt.ask_int(vld=range(1,101))</span>
</code></pre></div>
<p>Menus are straightforward as well:</p>
<div class="highlight"><pre><span></span><code><span class="err">menu = qprompt.Menu()</span>
<span class="err">menu.add("1", "Item 1")</span>
<span class="err">menu.add("2", "Item 2")</span>
<span class="err">selection = menu.show()</span>
</code></pre></div>
<p>Currently only Python 2.x is supported but it should be fairly easy to port to Python 3.x. Check out the project on GitHub <a href="https://github.com/jeffrimko/Qprompt">here</a>.</p>Properly Plural Python Printing2015-10-31T00:00:00-04:002015-10-31T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-10-31:/posts/2015/10/properly-plural-python-printing/<p>This one is kind of silly but sometimes you just want messages to use the proper plural case. Here is an example in Python 2 (with a little help from <a href="https://github.com/jeffrimko/Qprompt">Qprompt</a>):</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">qprompt</span>
<span class="n">num</span> <span class="o">=</span> <span class="n">qprompt</span><span class="o">.</span><span class="n">ask_int</span><span class="p">(</span><span class="s2">"How many beers?"</span><span class="p">,</span> <span class="n">vld</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
<span class="nb">print</span> <span class="s2">"Okay, </span><span class="si">%u</span><span class="s2"> </span><span class="si">%s</span><span class="s2">."</span> <span class="o">%</span> <span class="p">(</span>
<span class="n">num</span><span class="p">,</span>
<span class="s2">"beer"</span> <span class="k">if</span> <span class="n">num</span> <span class="o">==</span> <span class="mi">1</span> <span class="k">else</span> <span class="s2">"beers"</span><span class="p">)</span>
</code></pre></div>Introducing The Unified Style Guide2015-08-30T00:00:00-04:002015-08-30T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-08-30:/posts/2015/08/introducing-the-unified-style-guide/<p>Style guides are an important part of the software development process. They keep code consistent across projects and help maintain a level of cleanliness and professionalism. A few years ago, I realized there were no (to my knowledge) guides for general file and directory naming so I started one. Over time, I gradually updated it and eventually named it the Unified Style Guide with the lofty goal of one day expanding it to programming languages …</p><p>Style guides are an important part of the software development process. They keep code consistent across projects and help maintain a level of cleanliness and professionalism. A few years ago, I realized there were no (to my knowledge) guides for general file and directory naming so I started one. Over time, I gradually updated it and eventually named it the Unified Style Guide with the lofty goal of one day expanding it to programming languages and other areas where opinionated guidelines for naming could be useful. The project now lives on GitHub <a href="https://github.com/jeffrimko/UnifiedStyleGuide">here</a> and is still being updated. The guide can be read on this site <a href="/projects/unified-style-guide/">here</a>. Keep in mind that it is still very much a work in progress and feedback is welcome!</p>Weekly Picks - Python2015-06-20T00:00:00-04:002015-06-20T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-06-20:/posts/2015/06/weekly-picks-python/<p>Just a couple of Python related picks this week.</p>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://www.talkpythontome.com/">Talk Python To Me</a></em> - Relatively new podcast all about Python. Excellent and informative!</li>
</ul>
<h4>Software Development:</h4>
<ul>
<li><em><a href="http://www.lfd.uci.edu/~gohlke/pythonlibs/">Unofficial Windows Binaries for Python Extension Packages</a></em> - This site is an occasional lifesaver! Sometimes it can be tricky getting a third-party Python library running on a PC. This site provides pre-built libraries that are ready to install.</li>
</ul>Weekly Picks - Automate The Boring Stuff2015-05-03T00:00:00-04:002015-05-03T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-05-03:/posts/2015/05/weekly-picks-automate-the-boring-stuff/<p>This week's pick is a great book for those interested in practical applications and automation using Python.</p>
<h4>Books:</h4>
<ul>
<li><em><a href="http://automatetheboringstuff.com/">Automate the Boring Stuff (online)</a></em> - The free book website.</li>
<li><em><a href="http://www.amazon.com/gp/product/1593275994/ref=as_li_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1593275994&linkCode=as2">Automate the Boring Stuff (paperback)</a></em> - Physical book from Amazon.</li>
</ul>Weekly Picks - Reddit2015-04-26T00:00:00-04:002015-04-26T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-04-26:/posts/2015/04/weekly-picks-reddit/<p>Picks are a bit late this week but the theme will be "Reddit". I spend arguably too much time browsing and reading interesting articles on various sub-reddits.</p>
<h4>Websites:</h4>
<ul>
<li><em><a href="http://www.reddit.com/">Reddit</a></em> - The main site.</li>
<li><em><a href="http://www.reddit.com/r/programming">/r/Programming</a></em> - Discussion about programming in general.</li>
<li><em><a href="http://www.reddit.com/r/todayilearned">/r/TodayILearned</a></em> - Learn something interesting? Post it here.</li>
<li><em><a href="http://www.reddit.com/r/explainlikeimfive">/r/ExplainLikeImFive</a></em> - Request simple explanations for any questions.</li>
</ul>Weekly Picks - Meetups And Makerspaces2015-04-16T00:00:00-04:002015-04-16T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-04-16:/posts/2015/04/weekly-picks-meetups-and-makerspaces/<p>People in big cities are spoiled. Cities tend to offer numerous interesting meetups with dozens of members. Additionally, local makerspaces (or hackerspaces) are fairly common in larger areas.</p>
<p>Lately I have been involved in a few meetup groups around the Shenango and Mahoning Valley area. The experience has been very fulfilling and it is great to see smaller cities getting some interesting groups organized.</p>
<h4>Events:</h4>
<ul>
<li><em><a href="http://hackysu.com/">HackYSU</a></em> - YSU's first official meetup is this weekend. Only students …</li></ul><p>People in big cities are spoiled. Cities tend to offer numerous interesting meetups with dozens of members. Additionally, local makerspaces (or hackerspaces) are fairly common in larger areas.</p>
<p>Lately I have been involved in a few meetup groups around the Shenango and Mahoning Valley area. The experience has been very fulfilling and it is great to see smaller cities getting some interesting groups organized.</p>
<h4>Events:</h4>
<ul>
<li><em><a href="http://hackysu.com/">HackYSU</a></em> - YSU's first official meetup is this weekend. Only students may participate but anyone may volunteer to be a mentor.</li>
</ul>
<h4>Groups:</h4>
<ul>
<li><em><a href="http://www.meetup.com/Shenango-Valley-Entrepreneur-Community/">Shenango Valley Entrepreneur Community</a></em> - Local group for people interested in owning and operating their own business.</li>
<li><em><a href="http://www.meetup.com/Youngstown-Video-Game-Development-Meetup/">Youngstown Video Game Development Meetup</a></em> - A fun meetup for people interested in video game development, hobbyist or pro.</li>
<li><em><a href="http://www.techshop.ws/pittsburgh.html">TechShop Pittsburgh</a></em> - Makerspace in Pittsburgh.</li>
<li><em><a href="http://engineering.case.edu/thinkbox/">think[box]</a></em> - Makerspace in Cleveland associated with Case Western Reserve University.</li>
</ul>
<h4>Websites:</h4>
<ul>
<li><em><a href="http://www.meetup.com/">Meetup</a></em> - Provides a nice platform for organizing local groups.</li>
</ul>Weekly Picks - Headphones2015-04-09T00:00:00-04:002015-04-09T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-04-09:/posts/2015/04/weekly-picks-headphones/<p>The theme for the picks this week is "headphones". I frequently listen to podcasts and music so good headphones are a must.</p>
<h4>Products:</h4>
<ul>
<li><em>Audio-Technica ATH-M50s</em> - Hands down the best sounding headphones I have owned. The only downside is the cable length which can sometimes be a nuisance as I tend to be only a foot or two away from the audio source. Consider the newer ATH-M50x model with removable cable.</li>
<li><em>Motorola MOTOROKR S305</em> - Simple design …</li></ul><p>The theme for the picks this week is "headphones". I frequently listen to podcasts and music so good headphones are a must.</p>
<h4>Products:</h4>
<ul>
<li><em>Audio-Technica ATH-M50s</em> - Hands down the best sounding headphones I have owned. The only downside is the cable length which can sometimes be a nuisance as I tend to be only a foot or two away from the audio source. Consider the newer ATH-M50x model with removable cable.</li>
<li><em>Motorola MOTOROKR S305</em> - Simple design yet functional with exceptional sound quality for Bluetooth headphones.</li>
<li><em>MEElectronics AF52 Venture</em> - Just got a pair of these today and really enjoying them so far. Sound quality is sufficient and the design is well thought out.</li>
</ul>Weekly Picks - Initial2015-04-02T00:00:00-04:002015-04-02T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-04-02:/posts/2015/04/weekly-picks-initial/<p><a href="https://twitter.com/cmaxw">Charles Max Wood</a> produces some excellent programming-related podcasts. All his podcasts have a similar format which include a picks section near the end of each episode. During this section, a participant can suggest anything (not just programming related) that they have enjoyed or found useful. I am going to try something similar with this blog and post a list of picks weekly (or as close to weekly as possible).</p>
<h4>Articles:</h4>
<ul>
<li><em><a href="https://medium.com/@fogleman/i-made-an-nes-emulator-here-s-what-i-learned-about-the-original-nintendo-2e078c9b28fe">I made an NES emulator …</a></em></li></ul><p><a href="https://twitter.com/cmaxw">Charles Max Wood</a> produces some excellent programming-related podcasts. All his podcasts have a similar format which include a picks section near the end of each episode. During this section, a participant can suggest anything (not just programming related) that they have enjoyed or found useful. I am going to try something similar with this blog and post a list of picks weekly (or as close to weekly as possible).</p>
<h4>Articles:</h4>
<ul>
<li><em><a href="https://medium.com/@fogleman/i-made-an-nes-emulator-here-s-what-i-learned-about-the-original-nintendo-2e078c9b28fe">I made an NES emulator</a></em> - Provides a quick overview of the NES hardware. Writing an NES game (not emulator although that would be interesting too) is on my bucket list; learning a bit about the hardware was fun.</li>
</ul>
<h4>Food:</h4>
<ul>
<li><em>Giant Eagle pistachio muffins</em> - Sadly, these may only be available during March. They are amazing and worth all 10,000+ calories.</li>
</ul>
<h4>Podcasts:</h4>
<ul>
<li><em><a href="http://devchat.tv/">DevChat.tv</a></em> - Not a single podcast but rather a group of programming related shows. My favorites are Adventures In Angular, Freelancer's Show, and JavaScript Jabber.</li>
</ul>
<h4>Products:</h4>
<ul>
<li><em>Eneloop Batteries</em> - The best rechargeable batteries I have used. Reliable and well priced.</li>
</ul>
<h4>Software:</h4>
<ul>
<li><em><a href="http://nim-lang.org/">Nim</a></em> - Interesting compiled language with syntax reminiscent of Python and Ada. Still under development so probably not suitable yet for business-level development.</li>
<li><em><a href="https://peewee.readthedocs.org/en/latest/">Peewee</a></em> - Python ORM for Sqlite, MySQL, and PostgreSQL. Powerful and easy to use.
-<em><a href="http://xlwings.org/">XLWings</a></em> - Neat Python library for interacting with Excel, still under development but functional.</li>
</ul>
<h4>Videos:</h4>
<ul>
<li><em><a href="https://www.youtube.com/watch?v=DovunOxlY1k">AT&T Archives: Similiarities of Wave Behavior</a></em> - Excellent video explaining and visually demonstrating common behavior of waves.</li>
<li><em><a href="https://www.youtube.com/playlist?list=PLUMWjy5jgHK3j74Z5Tq6Tso1fSfVWZC8L">Control System Lecture by Brian Douglas</a></em> - These videos are remarkable! Brian does a great job at quickly reviewing and explaining material.</li>
</ul>
<h4>Websites:</h4>
<ul>
<li><em><a href="http://www.techbargains.com/">Techbargains</a></em> - Good site for finding deals. The previously mentioned Eneloop batteries can sometimes be found here.</li>
</ul>Testing Embedded Systems With Python2015-03-15T00:00:00-04:002015-03-15T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2015-03-15:/posts/2015/03/testing-embedded-systems-with-python/<p>Testing embedded systems with Python (or at all, really) is an extensive topic. This post is not going to dive too deep into the subject but instead suggest one potential approach from a high level as well as cover a few third party libraries that might make life a bit easier.</p>
<p>Before going any further, let's take a look at why you might want to incorporate Python into your test solution. Including a high-level scripting …</p><p>Testing embedded systems with Python (or at all, really) is an extensive topic. This post is not going to dive too deep into the subject but instead suggest one potential approach from a high level as well as cover a few third party libraries that might make life a bit easier.</p>
<p>Before going any further, let's take a look at why you might want to incorporate Python into your test solution. Including a high-level scripting interface to your tester affords a great deal of flexibility but is not appropriate in all cases. The following are a few reasons you may want to go down the Python route:</p>
<ul>
<li>The device under test (DUT) is complex enough to require a variety of test cases to be written.</li>
<li>The components of the test system may change and the details can be hidden under the scripting interface.</li>
<li>Higher-level applications (e.g. GUI applications written in PyQt) could be implemented using the scripting interface.</li>
</ul>
<p>The following is a rough progression for rapidly developing a test solution:</p>
<ol>
<li>Evaluate your requirements.</li>
<li>Draft a solution.</li>
<li>Develop a mock API and example script.</li>
<li>Implement a proof-of-concept (POC).</li>
<li>Iterate on the POC until functionality is covered.</li>
<li>Stabilize the design and update if necessary.</li>
</ol>
<p>Let's take a further look at each item of this progression.</p>
<h4>Evaluate your requirements</h4>
<p>The obvious first step when developing any solution. Determine what you need to achieve with the test system and whether Python is a good fit. A few questions to ask during this phase:</p>
<ul>
<li>What IO will be handled?</li>
<li>How is power handled?</li>
<li>What measurements need to be taken?</li>
<li>Are there timing requirements?</li>
</ul>
<h4>Draft a solution</h4>
<p>After answering the questions raised in the requirements phase, you should have a pretty good idea of what sort of test hardware is needed. Draw a diagram of the test system and show all the interfaces that will need to be handled. Research your equipment choices and see what protocols you might be working with; look into existing Python libraries to help you out. Here are a few useful libraries when working with test equipment:</p>
<ul>
<li><a href="https://pypi.python.org/pypi/MinimalModbus">MinimalModbus</a> - Easy to use Modbus library.</li>
<li><a href="https://pypi.python.org/pypi/pyserial">PySerial</a> - Essential for basic serial interface work.</li>
<li><a href="https://pypi.python.org/pypi/PyVISA">PyVisa</a> - Useful for talking to common test equipment.</li>
</ul>
<h4>Develop a mock API and example script</h4>
<p>Without having any hardware in place, sit down and write an example of what a test script might look like. Try to identify anything you may have overlooked during the previous steps. During this process begin laying out the test system API. Keep it generalized to the functionality that is being tested and plan on hiding implementation details. See if the standard library <a href="https://docs.python.org/2/library/unittest.html">unittest</a> framework suites your needs, otherwise look into other offerings such as <a href="https://pypi.python.org/pypi/nose">nose</a>.</p>
<h4>Implement a proof-of-concept (POC)</h4>
<p>Start assembling hardware and coding. Try to get functionality up and running quickly, verify it works properly, then develop the associated API calls. Look for anything that may impede progress and refactor if necessary.</p>
<h4>Iterate on the POC until functionality is covered</h4>
<p>Verify that the POC functions as expected and clean up the code and hardware as necessary. Try writing additional test scripts to make sure everything is covered.</p>
<h4>Stabilize the design and update if necessary</h4>
<p>Put the finishing touches on the design. Document the API and hardware design, check out <a href="http://sphinx-doc.org/">Sphinx</a> for a possible documentation toolchain. Consider the tester in beta until proven.</p>
<h4>Final thoughts</h4>
<p>This article barely scratches the surface of the topic. Test solutions for embedded systems are very specialized projects and the process covered in this post is a generalization of one approach when very little existing resources are available. Just remember that the addition of a Python scripting interface can dramatically increase the capabilities of your next test system.</p>Python Data Serialization Comparison2015-02-21T00:00:00-05:002015-02-21T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2015-02-21:/posts/2015/02/python-data-serialization-comparison/<p>Did a quick comparison of some data serialization options for Python. My requirements for the serialization format were the following:</p>
<ul>
<li>Input data is typically either a list or a dictionary.</li>
<li>Interoperability is important and must be compatible with at least C.</li>
<li>A human readable format is desirable but not necessary.</li>
</ul>
<p>Based on the requirements, I took a look at the following Python packages:</p>
<ul>
<li><a href="https://pypi.python.org/pypi/PyYAML">PyYaml</a></li>
<li><a href="https://pypi.python.org/pypi/python-cjson">python-cjson</a></li>
<li><a href="https://pypi.python.org/pypi/ujson">ujson</a></li>
<li><a href="https://pypi.python.org/pypi/u-msgpack-python">u-msgpack-python</a></li>
<li><a href="https://pypi.python.org/pypi/msgpack-python">msgpack-python</a> <strong>NOTE: Disqualified since had trouble running on …</strong></li></ul><p>Did a quick comparison of some data serialization options for Python. My requirements for the serialization format were the following:</p>
<ul>
<li>Input data is typically either a list or a dictionary.</li>
<li>Interoperability is important and must be compatible with at least C.</li>
<li>A human readable format is desirable but not necessary.</li>
</ul>
<p>Based on the requirements, I took a look at the following Python packages:</p>
<ul>
<li><a href="https://pypi.python.org/pypi/PyYAML">PyYaml</a></li>
<li><a href="https://pypi.python.org/pypi/python-cjson">python-cjson</a></li>
<li><a href="https://pypi.python.org/pypi/ujson">ujson</a></li>
<li><a href="https://pypi.python.org/pypi/u-msgpack-python">u-msgpack-python</a></li>
<li><a href="https://pypi.python.org/pypi/msgpack-python">msgpack-python</a> <strong>NOTE: Disqualified since had trouble running on Windows.</strong></li>
</ul>
<p>The following Python script was used to test out the various packages:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">umsgpack</span>
<span class="kn">import</span> <span class="nn">yaml</span>
<span class="kn">import</span> <span class="nn">cjson</span>
<span class="kn">import</span> <span class="nn">ujson</span>
<span class="n">DATA</span> <span class="o">=</span> <span class="p">[{</span><span class="s1">'val1'</span><span class="p">:</span><span class="mi">12345</span><span class="p">,</span> <span class="s1">'val2'</span><span class="p">:[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">],</span> <span class="s1">'val3'</span><span class="p">:</span><span class="s2">"12345"</span><span class="p">}</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10000</span><span class="p">)]</span>
<span class="k">def</span> <span class="nf">test_serialization</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">encode</span><span class="p">,</span> <span class="n">decode</span><span class="p">):</span>
<span class="nb">print</span> <span class="n">name</span>
<span class="nb">print</span> <span class="s2">" Encoding..."</span>
<span class="n">t_start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">clock</span><span class="p">()</span>
<span class="n">packed</span> <span class="o">=</span> <span class="n">encode</span><span class="p">(</span><span class="n">DATA</span><span class="p">)</span>
<span class="nb">print</span> <span class="s2">" time = </span><span class="si">%f</span><span class="s2"> seconds"</span> <span class="o">%</span> <span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">clock</span><span class="p">()</span> <span class="o">-</span> <span class="n">t_start</span><span class="p">)</span>
<span class="nb">print</span> <span class="s2">" size = </span><span class="si">%u</span><span class="s2"> kilobytes"</span> <span class="o">%</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">packed</span><span class="p">)</span> <span class="o">/</span> <span class="mi">1024</span><span class="p">)</span>
<span class="nb">print</span> <span class="s2">" Decoding..."</span>
<span class="n">t_start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">clock</span><span class="p">()</span>
<span class="n">unpacked</span> <span class="o">=</span> <span class="n">decode</span><span class="p">(</span><span class="n">packed</span><span class="p">)</span>
<span class="nb">print</span> <span class="s2">" time = </span><span class="si">%f</span><span class="s2"> seconds"</span> <span class="o">%</span> <span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">clock</span><span class="p">()</span> <span class="o">-</span> <span class="n">t_start</span><span class="p">)</span>
<span class="nb">print</span> <span class="s2">" same = </span><span class="si">%r</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">DATA</span> <span class="o">==</span> <span class="n">unpacked</span><span class="p">)</span>
<span class="n">test_serialization</span><span class="p">(</span><span class="s2">"umsgpack"</span><span class="p">,</span> <span class="n">umsgpack</span><span class="o">.</span><span class="n">packb</span><span class="p">,</span> <span class="n">umsgpack</span><span class="o">.</span><span class="n">unpackb</span><span class="p">)</span>
<span class="n">test_serialization</span><span class="p">(</span><span class="s2">"yaml"</span><span class="p">,</span> <span class="n">yaml</span><span class="o">.</span><span class="n">dump</span><span class="p">,</span> <span class="n">yaml</span><span class="o">.</span><span class="n">load</span><span class="p">)</span>
<span class="n">test_serialization</span><span class="p">(</span><span class="s2">"cjson"</span><span class="p">,</span> <span class="n">cjson</span><span class="o">.</span><span class="n">encode</span><span class="p">,</span> <span class="n">cjson</span><span class="o">.</span><span class="n">decode</span><span class="p">)</span>
<span class="n">test_serialization</span><span class="p">(</span><span class="s2">"ujson"</span><span class="p">,</span> <span class="n">ujson</span><span class="o">.</span><span class="n">encode</span><span class="p">,</span> <span class="n">ujson</span><span class="o">.</span><span class="n">decode</span><span class="p">)</span>
</code></pre></div>
<p>The result of running this script on my laptop (Intel Core i7 2670QM) is the following:</p>
<div class="highlight"><pre><span></span><code>umsgpack
Encoding...
time = 0.390241 seconds
size = 341 kilobytes
Decoding...
time = 0.430256 seconds
same = True
yaml
Encoding...
time = 8.266586 seconds
size = 527 kilobytes
Decoding...
time = 15.943908 seconds
same = True
cjson
Encoding...
time = 0.030977 seconds
size = 576 kilobytes
Decoding...
time = 0.022119 seconds
same = True
ujson
Encoding...
time = 0.013703 seconds
size = 478 kilobytes
Decoding...
time = 0.018000 seconds
same = True
</code></pre></div>
<p>For my particular application, speed is more important than size of the serialized data. The clear winner for speed is <code>ujson</code>. For size, <code>msgpack</code> is slightly better than <code>ujson</code> which makes sense since it is a binary format.</p>
<p>Overall, I am very impressed by the performance of <code>ujson</code>. Given the ubiquity of JSON for web-based data, it makes sense that ultra optimized libraries would exist for it. While I love YAML as a data format, the performance of the PyYAML library is not suitable for applications requiring fast encoding/decoding times.</p>Python Gotcha - Globals And Namespaces2015-02-01T00:00:00-05:002015-02-01T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2015-02-01:/posts/2015/02/python-gotcha-globals-and-namespaces/<p>After several years of regular Python use, I really admire that things work how I expect about 90% of the time. To be fair, the other 10% is typically user error. It is easy to overlook nuances in a language, even if you should know better.</p>
<p>I ran into this gotcha in Python recently: when importing a global variable from a module explicitly by name, that variable will be bound to the local namespace. If …</p><p>After several years of regular Python use, I really admire that things work how I expect about 90% of the time. To be fair, the other 10% is typically user error. It is easy to overlook nuances in a language, even if you should know better.</p>
<p>I ran into this gotcha in Python recently: when importing a global variable from a module explicitly by name, that variable will be bound to the local namespace. If that bound global is of immutable type (such as the built-in integer type), changes to that variable will not be reflected in the original namespace. Whew, that was an exhausting explanation, an example demonstrates the issue nicely.</p>
<p>Consider the following three Python files, <code>mymod.py</code>, <code>main1.py</code>, and <code>main2.py</code>:</p>
<hr>
<p><strong><code>mymod.py</code></strong></p>
<div class="highlight"><pre><span></span><code><span class="n">foo</span> <span class="o">=</span> <span class="mi">10</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">():</span>
<span class="nb">print</span> <span class="s2">"info5:"</span><span class="p">,</span> <span class="n">foo</span>
</code></pre></div>
<p>Our example module (<code>mymod.py</code>) defines a global variable and function that uses that global.</p>
<hr>
<p><strong><code>main1.py</code></strong></p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">mymod</span> <span class="kn">import</span> <span class="n">foo</span><span class="p">,</span> <span class="n">func</span>
<span class="n">_</span> <span class="o">=</span> <span class="kc">None</span><span class="p">;</span> <span class="nb">print</span> <span class="s2">"info1:"</span><span class="p">,</span> <span class="p">[</span><span class="n">_</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">globals</span><span class="p">()</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">_</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"_"</span><span class="p">)]</span>
<span class="nb">print</span> <span class="s2">"info2:"</span><span class="p">,</span> <span class="n">foo</span><span class="p">,</span> <span class="nb">id</span><span class="p">(</span><span class="n">foo</span><span class="p">)</span>
<span class="n">func</span><span class="p">()</span>
<span class="n">foo</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nb">print</span> <span class="s2">"info3:"</span><span class="p">,</span> <span class="n">foo</span><span class="p">,</span> <span class="nb">id</span><span class="p">(</span><span class="n">foo</span><span class="p">)</span>
<span class="n">func</span><span class="p">()</span>
</code></pre></div>
<p>Our first example of using <code>mymod</code> imports the global and function by name. The global is updated by <code>main1.py</code> and then the function is called. However, because the imported <code>foo</code> was updated, it no longer points to the same object as <code>foo</code> in the <code>mymod</code> namespace. The output of this script is the following:</p>
<div class="highlight"><pre><span></span><code>info1: ['func', 'foo']
info2: 10 11159084
info5: 10 11159084
info3: 11 11159072
info5: 10 11159084
</code></pre></div>
<hr>
<p><strong><code>main2.py</code></strong></p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">mymod</span>
<span class="n">_</span> <span class="o">=</span> <span class="kc">None</span><span class="p">;</span> <span class="nb">print</span> <span class="s2">"info1:"</span><span class="p">,</span> <span class="p">[</span><span class="n">_</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">globals</span><span class="p">()</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">_</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"_"</span><span class="p">)]</span>
<span class="nb">print</span> <span class="s2">"info2:"</span><span class="p">,</span> <span class="n">mymod</span><span class="o">.</span><span class="n">foo</span><span class="p">,</span> <span class="nb">id</span><span class="p">(</span><span class="n">mymod</span><span class="o">.</span><span class="n">foo</span><span class="p">)</span>
<span class="n">mymod</span><span class="o">.</span><span class="n">func</span><span class="p">()</span>
<span class="n">mymod</span><span class="o">.</span><span class="n">foo</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nb">print</span> <span class="s2">"info3:"</span><span class="p">,</span> <span class="n">mymod</span><span class="o">.</span><span class="n">foo</span><span class="p">,</span> <span class="nb">id</span><span class="p">(</span><span class="n">mymod</span><span class="o">.</span><span class="n">foo</span><span class="p">)</span>
<span class="n">mymod</span><span class="o">.</span><span class="n">func</span><span class="p">()</span>
</code></pre></div>
<p>Our second example of using <code>mymod</code> imports only the module. Since the <code>foo</code> global is updated and accessed via the <code>mymod</code> namespace, the changes will be reflected both in <code>main2</code> and <code>mymod</code>. The output of this script is the following:</p>
<div class="highlight"><pre><span></span><code>info1: ['mymod']
info2: 10 32982572
info5: 10 32982572
info3: 11 32982560
info5: 11 32982560
</code></pre></div>
<hr>
<p>Please note that this gotcha only applies if the global variable is of immutable type. If the variable is mutable, such as a list or dictionary, this particular issue would not be expressed.</p>Thoughts On Writing BakeScale2015-01-21T00:00:00-05:002015-01-21T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2015-01-21:/posts/2015/01/thoughts-on-writing-bakescale/<p>Recently, I wrote a simple web app called <a href="http://bakescale.info">BakeScale</a> which converts common cooking and baking ingredients between weight and volume. I am not a web developer by profession so rather than using the new hotness I used slightly older versions of <a href="http://getbootstrap.com/">Bootstrap</a> and <a href="http://jquery.com/">jQuery</a> since I have some prior experience with both; just a few quick thoughts on these two web development tools.</p>
<p>While jQuery seems to be falling out of favor with the web …</p><p>Recently, I wrote a simple web app called <a href="http://bakescale.info">BakeScale</a> which converts common cooking and baking ingredients between weight and volume. I am not a web developer by profession so rather than using the new hotness I used slightly older versions of <a href="http://getbootstrap.com/">Bootstrap</a> and <a href="http://jquery.com/">jQuery</a> since I have some prior experience with both; just a few quick thoughts on these two web development tools.</p>
<p>While jQuery seems to be falling out of favor with the web development community at large, it is tough to beat for simple DOM manipulation tasks. It is a mature library that works consistently across browsers and has great documentation. Usually, stuff just works the way I expect and that is the exact experience a mature library should provide.</p>
<p>Bootstrap is a pleasure to work with as well. I took a quick look at some of the other similar frameworks and could not find a reason to use anything else. For making websites look pretty quickly, Bootstrap is a solid choice.</p>
<p>All this being said, I haven't used either tool enough to uncover any rough edges or quirks. Scaling jQuery is probably not for the faint of heart; even after writing a small app I can definitely see how things can get messy quickly. However, for small focused applications, these two are a powerful combination.</p>Directory Information Please2015-01-05T00:00:00-05:002015-01-05T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2015-01-05:/posts/2015/01/directory-information-please/<p>Sometimes a directory structure needs a little extra information. Even the most well thought-out directory names lack the expressiveness of a few short remarks. My solution for these cases has been to add a file named <code>__dir_info__.txt</code> to a directory requiring additional details. This file provides an explanation of the directory's purpose, which typically starts with <code>This directory contains ...</code>, and is formatted using <a href="http://asciidoc.org/">AsciiDoc</a>.</p>
<p>Let's look at an example:</p>
<div class="highlight"><pre><span></span><code>= foobar
:date: 5 January 2015 …</code></pre></div><p>Sometimes a directory structure needs a little extra information. Even the most well thought-out directory names lack the expressiveness of a few short remarks. My solution for these cases has been to add a file named <code>__dir_info__.txt</code> to a directory requiring additional details. This file provides an explanation of the directory's purpose, which typically starts with <code>This directory contains ...</code>, and is formatted using <a href="http://asciidoc.org/">AsciiDoc</a>.</p>
<p>Let's look at an example:</p>
<div class="highlight"><pre><span></span><code>= foobar
:date: 5 January 2015
This directory contains files related to foo-ing and bar-ing.
</code></pre></div>
<p>The title is always the current name of the directory, in this case <code>foobar</code>. The date is when the file was created or last modified. An author tag or other metadata can be added if desired. The body should be concise, no more than a few sentences. If a file naming convention is used in the directory, be sure to provide the details.</p>
<p>There are other options for documenting directories such as using the project readme file or the traditional <code>FILES</code> file. However, the explicitness of <code>__dir_info__.txt</code> is a great advantage.</p>Generating Documents With Jinja2 and YAML2014-11-22T00:00:00-05:002014-11-22T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-11-22:/posts/2014/11/generating-documents-with-jinja2-and-yaml/<p>Quick example of generating documents by rendering data from a YAML file through a <a href="http://jinja.pocoo.org/docs/dev/">Jinja2</a> template. The target output is Latex <a href="http://www.ctan.org/tex-archive/macros/latex/contrib/vhistory">vhistory</a> data (<code>revs.tex</code>) which will be included in main document (<code>main.tex</code>). The output is generated by a Python script (<code>create_revs_tex.py</code>) from YAML data (<code>revs.yaml</code>).</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">yaml</span>
<span class="kn">from</span> <span class="nn">jinja2</span> <span class="kn">import</span> <span class="n">Template</span>
<span class="c1"># For this example, assume that stdout will be redirected to `revs.tex`.</span>
<span class="c1"># In the template, the `{#--#}` entries are used to …</span></code></pre></div><p>Quick example of generating documents by rendering data from a YAML file through a <a href="http://jinja.pocoo.org/docs/dev/">Jinja2</a> template. The target output is Latex <a href="http://www.ctan.org/tex-archive/macros/latex/contrib/vhistory">vhistory</a> data (<code>revs.tex</code>) which will be included in main document (<code>main.tex</code>). The output is generated by a Python script (<code>create_revs_tex.py</code>) from YAML data (<code>revs.yaml</code>).</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">yaml</span>
<span class="kn">from</span> <span class="nn">jinja2</span> <span class="kn">import</span> <span class="n">Template</span>
<span class="c1"># For this example, assume that stdout will be redirected to `revs.tex`.</span>
<span class="c1"># In the template, the `{#--#}` entries are used to eat unwanted whitespace.</span>
<span class="nb">print</span> <span class="n">Template</span><span class="p">(</span><span class="sa">r</span><span class="s2">"""</span>
<span class="s2">{#--#}</span>
<span class="s2">\begin</span><span class="si">{versionhistory}</span><span class="s2"></span>
<span class="s2">{</span><span class="si">%- f</span><span class="s2">or r in revs %}</span>
<span class="s2"> \vhEntry {#- -#}</span>
<span class="s2"> { {{- r.number -}} } {#--#}</span>
<span class="s2"> { {{- r.date -}} } {#--#}</span>
<span class="s2"> { {{- r.author -}} } {#--#}</span>
<span class="s2"> { {{- r.comments -}} }</span>
<span class="s2">{</span><span class="si">%- e</span><span class="s2">ndfor %}</span>
<span class="s2">\end</span><span class="si">{versionhistory}</span><span class="s2"></span>
<span class="s2">"""</span><span class="p">)</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">revs</span><span class="o">=</span><span class="n">yaml</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s2">"revs.yaml"</span><span class="p">)))</span>
</code></pre></div>gArchiver Demo2014-11-15T00:00:00-05:002014-11-15T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-11-15:/posts/2014/11/garchiver-demo/<p>Made a quick video to demonstrate some of the features of <a href="https://github.com/jeffrimko/Archiver">gArchiver</a>:</p>
<div class="responsive-container">
<iframe src="//www.youtube.com/embed/TW-0b3iVl1k" frameborder="0" allowfullscreen></iframe>
</div>
<p>I use gArchiver frequently and it has proven invaluable. The ability to quickly add metadata to a zip file is handy. Here are a couple of typical use cases:</p>
<ul>
<li><strong>Keeping track of where files came from.</strong> When I need to keep a local copy of a received file, its useful to make a quick note of who sent it.</li>
<li><strong>Grouping files together as …</strong></li></ul><p>Made a quick video to demonstrate some of the features of <a href="https://github.com/jeffrimko/Archiver">gArchiver</a>:</p>
<div class="responsive-container">
<iframe src="//www.youtube.com/embed/TW-0b3iVl1k" frameborder="0" allowfullscreen></iframe>
</div>
<p>I use gArchiver frequently and it has proven invaluable. The ability to quickly add metadata to a zip file is handy. Here are a couple of typical use cases:</p>
<ul>
<li><strong>Keeping track of where files came from.</strong> When I need to keep a local copy of a received file, its useful to make a quick note of who sent it.</li>
<li><strong>Grouping files together as a record.</strong> Some files never need to be modified and are kept only as records. Grouping related files together in an archive makes sense.</li>
<li><strong>Making quick backups before changing something.</strong> Version control software is awesome but it can be overkill for small tasks. Before tempting fate by restyling a Word document, make a quick backup and note the current state of the file.</li>
<li><strong>Storing a directory of infrequently used file.</strong> Have an old project directory sitting around your filesystem? Archive the whole thing and make a few notes.</li>
</ul>
<p>The archive log can be read by simply opening the <code>__archive_info__.txt</code> Additionally, the rendered version can be viewed by opening the zip file with <a href="https://github.com/jeffrimko/Doctrine">Doctrine</a>.</p>Comment Groups2014-11-06T00:00:00-05:002014-11-06T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-11-06:/posts/2014/11/comment-groups/<p>Sometimes normal leading comments just aren't enough, instead a visual method of grouping blocks of code together is needed. The following pattern seems to work very well:</p>
<div class="highlight"><pre><span></span><code><span class="err"><comment-symbol>{-- <group-text> --</span>
<span class="err"><code-here></span>
<span class="err"><comment-symbol>----}</span>
</code></pre></div>
<p>Here is an example in C:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*{-- Some grouped variables. --*/</span>
<span class="cm">/* Maintains foo-y stuff. */</span>
<span class="kt">int</span> <span class="n">foo</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="cm">/* Maintains bar-y stuff. */</span>
<span class="kt">int</span> <span class="n">bar</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="cm">/*----}*/</span>
</code></pre></div>
<p>Here is an example in Python:</p>
<div class="highlight"><pre><span></span><code><span class="c1">#{-- Some cool code here. --</span>
<span class="n">foo</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">bar</span> <span class="o">=</span> <span class="mi">2</span>
<span class="c1">#----}</span>
</code></pre></div>
<p>Multi-line example in JavaScript:</p>
<div class="highlight"><pre><span></span><code><span class="c1">//{-- Big long explanation of a …</span></code></pre></div><p>Sometimes normal leading comments just aren't enough, instead a visual method of grouping blocks of code together is needed. The following pattern seems to work very well:</p>
<div class="highlight"><pre><span></span><code><span class="err"><comment-symbol>{-- <group-text> --</span>
<span class="err"><code-here></span>
<span class="err"><comment-symbol>----}</span>
</code></pre></div>
<p>Here is an example in C:</p>
<div class="highlight"><pre><span></span><code><span class="cm">/*{-- Some grouped variables. --*/</span>
<span class="cm">/* Maintains foo-y stuff. */</span>
<span class="kt">int</span> <span class="n">foo</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="cm">/* Maintains bar-y stuff. */</span>
<span class="kt">int</span> <span class="n">bar</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="cm">/*----}*/</span>
</code></pre></div>
<p>Here is an example in Python:</p>
<div class="highlight"><pre><span></span><code><span class="c1">#{-- Some cool code here. --</span>
<span class="n">foo</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">bar</span> <span class="o">=</span> <span class="mi">2</span>
<span class="c1">#----}</span>
</code></pre></div>
<p>Multi-line example in JavaScript:</p>
<div class="highlight"><pre><span></span><code><span class="c1">//{-- Big long explanation of a</span>
<span class="c1">// really cool thing this next</span>
<span class="c1">// block of code will do. --</span>
<span class="kd">var</span> <span class="nx">foo</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">bar</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="c1">//----}</span>
</code></pre></div>
<p>A nice feature this format provides is that matching bracket jumping will work. Therefore if your editor supports jumping, you can quickly move between the start and end of the code block. For example, in Vim use <code>%</code> while in normal mode, in SublimeText use <code>CTRL-M</code>.</p>Doctrine Goals2014-10-22T00:00:00-04:002014-10-22T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2014-10-22:/posts/2014/10/doctrine-goals/<p>This past weekend, I started a side project named Doctrine. It is a desktop application that simplifies viewing the rendered output of an <a href="http://asciidoc.org/">AsciiDoc</a> text file. A quick demo video is shown below:</p>
<div class="responsive-container">
<iframe src="//www.youtube.com/embed/LfnmNqXEiFg" frameborder="0" allowfullscreen></iframe>
</div>
<p>The motivation behind Doctrine is to streamline the user experience when writing documents in plain text markup. Currently I am only focusing on AsciiDoc but compatibility with other formats (Markdown, ReStructuredText, etc) could be added in the future (integration with <a href="http://johnmacfarlane.net/pandoc/">Pandoc</a> is …</p><p>This past weekend, I started a side project named Doctrine. It is a desktop application that simplifies viewing the rendered output of an <a href="http://asciidoc.org/">AsciiDoc</a> text file. A quick demo video is shown below:</p>
<div class="responsive-container">
<iframe src="//www.youtube.com/embed/LfnmNqXEiFg" frameborder="0" allowfullscreen></iframe>
</div>
<p>The motivation behind Doctrine is to streamline the user experience when writing documents in plain text markup. Currently I am only focusing on AsciiDoc but compatibility with other formats (Markdown, ReStructuredText, etc) could be added in the future (integration with <a href="http://johnmacfarlane.net/pandoc/">Pandoc</a> is one option).</p>
<p>Doctrine does not require the user to have AsciiDoc installed nor does it require any command-line knowledge. The user only needs to be familiar with the AsciiDoc syntax (cheatsheet available <a href="http://powerman.name/doc/asciidoc">here</a>) and know how to use a text editor. Hopefully, projects like this will make plain text documentation accessible to a wider audience.</p>Hacking Together HTML With YAML And Mustache2014-09-15T00:00:00-04:002014-09-15T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2014-09-15:/posts/2014/09/hacking-together-html-with-yaml-and-mustache/<p>Forewarning, this is a hack and an ugly one too. Without getting into the backstory, the idea was to see if it is possible to render <a href="http://www.yaml.org/">YAML</a> data to HTML using a <a href="http://mustache.github.io/">Mustache</a> template, all locally (i.e. no server, just a single local HTML file). Turns out it is possible... sort of.</p>
<p>Before getting to the code, a few notes:</p>
<ul>
<li>This probably shouldn't be used for anything ever (although it was a fun experiment …</li></ul><p>Forewarning, this is a hack and an ugly one too. Without getting into the backstory, the idea was to see if it is possible to render <a href="http://www.yaml.org/">YAML</a> data to HTML using a <a href="http://mustache.github.io/">Mustache</a> template, all locally (i.e. no server, just a single local HTML file). Turns out it is possible... sort of.</p>
<p>Before getting to the code, a few notes:</p>
<ul>
<li>This probably shouldn't be used for anything ever (although it was a fun experiment).</li>
<li>To read the local files, <code>iframe</code> elements are used; I feel like there is probably a library or some more elegant way to do this but didn't take the time to look.</li>
<li>This example only worked on Firefox 32 for me.</li>
<li>Chrome 37 has security features that prevents the local files from being read (supposedly they can be disabled but I didn't have any luck).</li>
<li>Internet Explorer 8 complained about security as well and rendered nothing.</li>
</ul>
<p>The results of this experiment are three files:</p>
<ul>
<li><code>data.yaml</code> - Contains the information that will be rendered.</li>
<li><code>template.txt</code> - Contains the Mustache template used to render the YAML data.</li>
<li><code>page.html</code> - Handles rendering the output to the browser.</li>
</ul>
<p>The contents of the files are the following:</p>
<h4><code>data.yaml</code></h4>
<div class="highlight"><pre><span></span><code><span class="nt">items</span><span class="p">:</span>
<span class="p p-Indicator">-</span> <span class="nt">date</span><span class="p">:</span> <span class="s">"2014-09-15"</span>
<span class="nt">note</span><span class="p">:</span> <span class="s">"foo"</span>
<span class="p p-Indicator">-</span> <span class="nt">date</span><span class="p">:</span> <span class="s">"2014-09-20"</span>
<span class="nt">note</span><span class="p">:</span> <span class="s">"bar"</span>
<span class="p p-Indicator">-</span> <span class="nt">date</span><span class="p">:</span> <span class="s">"2014-09-25"</span>
<span class="nt">note</span><span class="p">:</span> <span class="s">"baz"</span>
</code></pre></div>
<h4><code>template.txt</code></h4>
<div class="highlight"><pre><span></span><code><h1>Interesting Stuff</h1>
{{#items}}
{{date}}
</br>
{{note}}
<p>
{{/items}}
</code></pre></div>
<h4><code>page.html</code></h4>
<div class="highlight"><pre><span></span><code><span class="p"><</span><span class="nt">html</span><span class="p">></span>
<span class="p"><</span><span class="nt">head</span><span class="p">></span>
<span class="p"><</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/javascript"</span> <span class="na">src</span><span class="o">=</span><span class="s">"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
<span class="p"><</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/javascript"</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://raw.githubusercontent.com/nodeca/js-yaml/master/dist/js-yaml.min.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
<span class="p"><</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">"text/javascript"</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://raw.githubusercontent.com/janl/mustache.js/master/mustache.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
<span class="p"></</span><span class="nt">head</span><span class="p">></span>
<span class="p"><</span><span class="nt">body</span><span class="p">></span>
<span class="p"><</span><span class="nt">iframe</span> <span class="na">id</span><span class="o">=</span><span class="s">'yloader'</span> <span class="na">src</span><span class="o">=</span><span class="s">'data.yaml'</span><span class="p">></</span><span class="nt">iframe</span><span class="p">></span>
<span class="p"><</span><span class="nt">iframe</span> <span class="na">id</span><span class="o">=</span><span class="s">'tloader'</span> <span class="na">src</span><span class="o">=</span><span class="s">'template.txt'</span><span class="p">></</span><span class="nt">iframe</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"container"</span><span class="p">></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">script</span><span class="p">></span>
<span class="nb">window</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">$</span><span class="p">(</span><span class="s1">'#yloader'</span><span class="p">).</span><span class="nx">hide</span><span class="p">();</span> <span class="nx">$</span><span class="p">(</span><span class="s1">'#tloader'</span><span class="p">).</span><span class="nx">hide</span><span class="p">();</span> <span class="cm">/* Hide loader iframes. */</span>
<span class="kd">var</span> <span class="nx">yaml</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s1">'#yloader'</span><span class="p">).</span><span class="nx">contents</span><span class="p">().</span><span class="nx">find</span><span class="p">(</span><span class="s1">'pre'</span><span class="p">).</span><span class="nx">text</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">template</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s1">'#tloader'</span><span class="p">).</span><span class="nx">contents</span><span class="p">().</span><span class="nx">find</span><span class="p">(</span><span class="s1">'pre'</span><span class="p">).</span><span class="nx">text</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">jsyaml</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="nx">yaml</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">output</span> <span class="o">=</span> <span class="nx">Mustache</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="nx">template</span><span class="p">,</span> <span class="nx">data</span><span class="p">);</span>
<span class="nx">$</span><span class="p">(</span><span class="s1">'#container'</span><span class="p">).</span><span class="nx">append</span><span class="p">(</span><span class="nx">output</span><span class="p">);</span>
<span class="p">}</span>
<span class="p"></</span><span class="nt">script</span><span class="p">></span>
<span class="p"></</span><span class="nt">body</span><span class="p">></span>
<span class="p"></</span><span class="nt">html</span><span class="p">></span>
</code></pre></div>Thoughts On Script Naming2014-08-11T00:00:00-04:002014-08-11T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2014-08-11:/posts/2014/08/thoughts-on-script-naming/<p>For a while now, I have had the mindset that any high-level operation related to a software project should be captured as an OS-native script kept either in the repo's root directory or an appropriate subdirectory. For example, the following scripts are located in the root directory of my blog repo:</p>
<ul>
<li><code>_Build_HTML.bat</code></li>
<li><code>_Cleanup.bat</code></li>
<li><code>_Deploy_SSH.bat</code></li>
<li><code>_Run_Test_Server.bat</code></li>
</ul>
<p>A few things worth noting about the filenames alone:</p>
<ul>
<li>The scripts are Windows-native batch files since …</li></ul><p>For a while now, I have had the mindset that any high-level operation related to a software project should be captured as an OS-native script kept either in the repo's root directory or an appropriate subdirectory. For example, the following scripts are located in the root directory of my blog repo:</p>
<ul>
<li><code>_Build_HTML.bat</code></li>
<li><code>_Cleanup.bat</code></li>
<li><code>_Deploy_SSH.bat</code></li>
<li><code>_Run_Test_Server.bat</code></li>
</ul>
<p>A few things worth noting about the filenames alone:</p>
<ul>
<li>The scripts are Windows-native batch files since Windows is my primary OS.</li>
<li>The operations performed by each script should be clear from the name alone.</li>
<li>The leading underscore allows all scripts to be easily grouped together.</li>
<li>The <code>Mixed_Case_With_Underscores</code> convention should set the scripts apart from other files.</li>
</ul>
<p>At the very least, many of my projects have a <code>_Build_All.bat</code> (or similar) and <code>_Cleanup.bat</code> script in the root directory. These tend to be a bit more user-friendly than makefiles alone. The ability to run the scripts directly from Windows Explorer or the command shell is also helpful. Even if the scripts simply call a makefile, I would rather have them there.</p>
<p>Originally, I limited this naming convention to only OS-native scripts. However, recently I started adopting the convention to scripts written in other languages such as Python. It makes identifying standalone (i.e. not a library or part of a larger application) scripts easy; guess which of these scripts performs a standalone operation: <code>foobar.py</code> or <code>_Do_Something_Cool.py</code>.</p>
<p>Some guidelines I follow for naming these scripts:</p>
<ul>
<li>One leading underscore.</li>
<li>First word should be a strong verb that describes the action of the script (e.g. build, copy, cleanup, move, etc).</li>
<li>The first letter of each word should be capitalized.</li>
<li>Acronyms should be capitalized appropriately.</li>
<li>Keep the script name short; no more than three words.</li>
<li>Separate words with underscores.</li>
</ul>
<p>I have a structured template for what these types of scripts typically contain but those details will have to wait for another post.</p>C Polymorphism2014-05-04T00:00:00-04:002014-05-04T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2014-05-04:/posts/2014/05/c-polymorphism/<p>Polymorphism, when done right, is a powerful method of simplifying software implementation. There are multiple <a href="http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Types_of_polymorphism">types of polymorphism</a>, here is a simple example of runtime (aka dynamic) polymorphism in C:</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp"></span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="n">animal_s</span> <span class="p">{</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">speak</span><span class="p">)(</span><span class="kt">void</span><span class="p">);</span>
<span class="p">}</span> <span class="n">animal_t</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">speak_like_a_duck</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"quack!</span><span class="se">\r\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">speak_like_a_dog</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"woof!</span><span class="se">\r\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="nf">create_duck</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="n">duck</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">animal_t</span><span class="p">));</span>
<span class="n">duck</span><span class="o">-></span><span class="n">speak</span> <span class="o">=</span> <span class="o">&</span><span class="n">speak_like_a_duck</span><span class="p">;</span>
<span class="k">return</span><span class="p">(</span><span class="n">duck</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="nf">create_dog</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="n">dog …</span></code></pre></div><p>Polymorphism, when done right, is a powerful method of simplifying software implementation. There are multiple <a href="http://en.wikipedia.org/wiki/Polymorphism_(computer_science)#Types_of_polymorphism">types of polymorphism</a>, here is a simple example of runtime (aka dynamic) polymorphism in C:</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf"><stdlib.h></span><span class="cp"></span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="n">animal_s</span> <span class="p">{</span>
<span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">speak</span><span class="p">)(</span><span class="kt">void</span><span class="p">);</span>
<span class="p">}</span> <span class="n">animal_t</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">speak_like_a_duck</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"quack!</span><span class="se">\r\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">speak_like_a_dog</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"woof!</span><span class="se">\r\n</span><span class="s">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="nf">create_duck</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="n">duck</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">animal_t</span><span class="p">));</span>
<span class="n">duck</span><span class="o">-></span><span class="n">speak</span> <span class="o">=</span> <span class="o">&</span><span class="n">speak_like_a_duck</span><span class="p">;</span>
<span class="k">return</span><span class="p">(</span><span class="n">duck</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="nf">create_dog</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="n">dog</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">animal_t</span><span class="p">));</span>
<span class="n">dog</span><span class="o">-></span><span class="n">speak</span> <span class="o">=</span> <span class="o">&</span><span class="n">speak_like_a_dog</span><span class="p">;</span>
<span class="k">return</span><span class="p">(</span><span class="n">dog</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">speak</span><span class="p">(</span><span class="n">animal_t</span> <span class="o">*</span><span class="n">animal</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">animal</span><span class="o">-></span><span class="n">speak</span><span class="p">();</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="n">howard</span> <span class="o">=</span> <span class="n">create_duck</span><span class="p">();</span>
<span class="n">animal_t</span> <span class="o">*</span><span class="n">snoopy</span> <span class="o">=</span> <span class="n">create_dog</span><span class="p">();</span>
<span class="n">speak</span><span class="p">(</span><span class="n">howard</span><span class="p">);</span>
<span class="n">speak</span><span class="p">(</span><span class="n">snoopy</span><span class="p">);</span>
<span class="k">return</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>Output:</p>
<div class="highlight"><pre><span></span><code><span class="err">quack!</span>
<span class="err">woof!</span>
</code></pre></div>
<p>Too cool, right!</p>C Moving Average2014-04-26T00:00:00-04:002014-04-26T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2014-04-26:/posts/2014/04/c-moving-average/<p>Moving averages are useful since they do not require a buffer of samples to be maintained. Here is a simple implementation in C:</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
<span class="kt">float</span> <span class="nf">ave</span><span class="p">(</span><span class="kt">float</span> <span class="n">num</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">static</span> <span class="kt">float</span> <span class="n">fAve</span> <span class="o">=</span> <span class="mf">0.0f</span><span class="p">;</span>
<span class="k">static</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">fSmp</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">float</span> <span class="n">weight</span> <span class="o">=</span> <span class="mf">0.0f</span><span class="p">;</span>
<span class="n">fSmp</span><span class="o">++</span><span class="p">;</span>
<span class="n">weight</span> <span class="o">=</span> <span class="mf">1.0f</span> <span class="o">/</span> <span class="n">fSmp</span><span class="p">;</span>
<span class="n">fAve</span> <span class="o">=</span> <span class="p">(</span><span class="n">weight</span> <span class="o">*</span> <span class="n">num</span><span class="p">)</span> <span class="o">+</span> <span class="p">((</span><span class="mi">1</span> <span class="o">-</span> <span class="n">weight</span><span class="p">)</span> <span class="o">*</span> <span class="n">fAve</span><span class="p">);</span>
<span class="k">return</span><span class="p">(</span><span class="n">fAve</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="n">str</span><span class="p">[</span><span class="mi">100</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="kt">float</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="cm">/* Run until user enters …</span></code></pre></div><p>Moving averages are useful since they do not require a buffer of samples to be maintained. Here is a simple implementation in C:</p>
<div class="highlight"><pre><span></span><code><span class="cp">#include</span> <span class="cpf"><stdio.h></span><span class="cp"></span>
<span class="kt">float</span> <span class="nf">ave</span><span class="p">(</span><span class="kt">float</span> <span class="n">num</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">static</span> <span class="kt">float</span> <span class="n">fAve</span> <span class="o">=</span> <span class="mf">0.0f</span><span class="p">;</span>
<span class="k">static</span> <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">fSmp</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">float</span> <span class="n">weight</span> <span class="o">=</span> <span class="mf">0.0f</span><span class="p">;</span>
<span class="n">fSmp</span><span class="o">++</span><span class="p">;</span>
<span class="n">weight</span> <span class="o">=</span> <span class="mf">1.0f</span> <span class="o">/</span> <span class="n">fSmp</span><span class="p">;</span>
<span class="n">fAve</span> <span class="o">=</span> <span class="p">(</span><span class="n">weight</span> <span class="o">*</span> <span class="n">num</span><span class="p">)</span> <span class="o">+</span> <span class="p">((</span><span class="mi">1</span> <span class="o">-</span> <span class="n">weight</span><span class="p">)</span> <span class="o">*</span> <span class="n">fAve</span><span class="p">);</span>
<span class="k">return</span><span class="p">(</span><span class="n">fAve</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="n">str</span><span class="p">[</span><span class="mi">100</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="kt">float</span> <span class="n">num</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="cm">/* Run until user enters invalid number. */</span>
<span class="k">for</span><span class="p">(;;)</span>
<span class="p">{</span>
<span class="n">fputs</span><span class="p">(</span><span class="s">"Enter number: "</span><span class="p">,</span> <span class="n">stdout</span><span class="p">);</span>
<span class="n">fflush</span><span class="p">(</span><span class="n">stdout</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">fgets</span><span class="p">(</span><span class="n">str</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">str</span><span class="p">),</span> <span class="n">stdin</span><span class="p">))</span>
<span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="mi">1</span> <span class="o">==</span> <span class="n">sscanf</span><span class="p">(</span><span class="n">str</span><span class="p">,</span> <span class="s">"%f"</span><span class="p">,</span> <span class="o">&</span><span class="n">num</span><span class="p">))</span>
<span class="n">printf</span><span class="p">(</span><span class="s">" average = %f</span><span class="se">\r\n</span><span class="s">"</span><span class="p">,</span> <span class="n">ave</span><span class="p">(</span><span class="n">num</span><span class="p">));</span>
<span class="k">else</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div>
<p>Example output:</p>
<div class="highlight"><pre><span></span><code><span class="err">Enter number: 1.23</span>
<span class="err"> average = 1.230000</span>
<span class="err">Enter number: -4.56</span>
<span class="err"> average = -1.665000</span>
<span class="err">Enter number: q</span>
</code></pre></div>Python Geometric Mean2014-03-06T00:00:00-05:002014-03-06T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-03-06:/posts/2014/03/python-geometric-mean/<p>Need to calculate a geometric mean in Python? You could use <a href="http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.mstats.gmean.html">Numpy</a> or this one-liner:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># NOTE: This import is only needed for Python3.</span>
<span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">reduce</span>
<span class="c1"># Geometric mean of list `n`:</span>
<span class="n">geomean</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">reduce</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">:</span> <span class="n">x</span><span class="o">*</span><span class="n">y</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="o">**</span> <span class="p">(</span><span class="mf">1.0</span> <span class="o">/</span> <span class="nb">len</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
<span class="nb">print</span><span class="p">(</span><span class="n">geomean</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]))</span>
<span class="c1"># Result: 2.2133638394</span>
</code></pre></div>PhysicsJS Control Sandbox2014-03-04T00:00:00-05:002014-03-04T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-03-04:/posts/2014/03/physicsjs-control-sandbox/<p>Here is a neat little control sandbox put together using <a href="http://wellcaffeinated.net/PhysicsJS/">PhysicsJS</a> and <a href="http://jsfiddle.net/Jr5G4/13/light/">JSFiddle</a>. Try implementing your own <code>stepController()</code> to see if you can balance the circle above the square.</p>
<!-- <iframe width="100%" height="300" src="http://jsfiddle.net/Jr5G4/16/embedded/js%2Cresult" allowfullscreen="allowfullscreen" frameborder="0"></iframe> -->
<!-- <script async src="//jsfiddle.net/Jr5G4/17/embed/js,result/"></script> -->
<iframe width="100%" height="300" src="//jsfiddle.net/Jr5G4/17/embedded/js,result/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>Python String Index Replace2014-03-01T00:00:00-05:002014-03-01T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-03-01:/posts/2014/03/python-string-index-replace/<p>Python does not allow string to be modified via indexed assignment. For example, <code>a = "hello"; a[1] = "x"</code> will produce a <code>TypeError: 'str' object does not support item assignment</code> error. Grr!</p>
<p>The following one-liner <code>stridxrep()</code> can be used if the need ever arises:</p>
<div class="highlight"><pre><span></span><code><span class="n">a</span> <span class="o">=</span> <span class="s2">"hello"</span>
<span class="c1"># Python doesn't allow the following:</span>
<span class="c1"># a[1] = "x"</span>
<span class="c1"># A 'string index replace' function.</span>
<span class="n">stridxrep</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">r</span><span class="p">:</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">([(</span><span class="n">s</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="k">if</span> <span class="n">x</span> <span class="o">!=</span> <span class="n">i</span> <span class="k">else</span> <span class="n">r</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in …</span></code></pre></div><p>Python does not allow string to be modified via indexed assignment. For example, <code>a = "hello"; a[1] = "x"</code> will produce a <code>TypeError: 'str' object does not support item assignment</code> error. Grr!</p>
<p>The following one-liner <code>stridxrep()</code> can be used if the need ever arises:</p>
<div class="highlight"><pre><span></span><code><span class="n">a</span> <span class="o">=</span> <span class="s2">"hello"</span>
<span class="c1"># Python doesn't allow the following:</span>
<span class="c1"># a[1] = "x"</span>
<span class="c1"># A 'string index replace' function.</span>
<span class="n">stridxrep</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">r</span><span class="p">:</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">([(</span><span class="n">s</span><span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="k">if</span> <span class="n">x</span> <span class="o">!=</span> <span class="n">i</span> <span class="k">else</span> <span class="n">r</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">))])</span>
<span class="nb">print</span> <span class="n">stridxrep</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"x"</span><span class="p">)</span>
<span class="c1"># Result: hxllo</span>
<span class="nb">print</span> <span class="n">stridxrep</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">chr</span><span class="p">(</span><span class="mi">42</span><span class="p">))</span>
<span class="c1"># Result: *ello</span>
</code></pre></div>Four Technologies for 20142014-02-10T00:00:00-05:002014-02-10T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-02-10:/posts/2014/02/four-technologies-for-2014/<p>Technology moves fast. Really fast. The following are some software technologies that I will be keeping an eye on in 2014:</p>
<ol>
<li><strong><a href="https://www.docker.io/">Docker</a></strong> - Brilliant container manager.</li>
<li><strong><a href="http://www.rust-lang.org/">Rust</a></strong> - Promising systems language.</li>
<li><strong><a href="https://github.com/kripken/emscripten/wiki">Emscripten</a></strong> - Mind-bending JavaScript compiler.</li>
<li><strong><a href="http://d3js.org/">D3.js</a></strong> - Beautiful data visualization.</li>
</ol>
<p>While these technologies are not necessarily new, my prior experience with them is limited.</p>Task Lists In AsciiDoc2014-02-06T00:00:00-05:002014-02-06T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-02-06:/posts/2014/02/task-lists-in-asciidoc/<p><strong>NOTE</strong>: An update to this post is <a href="https://www.jeffcomput.es/posts/2017/04/better-task-lists-in-asciidoc/">available here</a>.</p>
<p>Task lists are great! Need to do something eventually but don't have the time or motivation to do it now? Add it to a task list (think of it as procrastination management)!</p>
<p>When managing task lists on a computer, I prefer a file-based plain-text approach. As a software developer and avid Vim user, I have found this method to be the most flexible, reliable, and easy …</p><p><strong>NOTE</strong>: An update to this post is <a href="https://www.jeffcomput.es/posts/2017/04/better-task-lists-in-asciidoc/">available here</a>.</p>
<p>Task lists are great! Need to do something eventually but don't have the time or motivation to do it now? Add it to a task list (think of it as procrastination management)!</p>
<p>When managing task lists on a computer, I prefer a file-based plain-text approach. As a software developer and avid Vim user, I have found this method to be the most flexible, reliable, and easy; your mileage may vary. Some benefits of a plain-text task list are the following:</p>
<ul>
<li>Easily view and update lists with text editor of choice.</li>
<li>Text files are easy to synchronize between multiple devices.</li>
<li>Many markup syntaxes can be directly rendered to HTML. This allows lists to be published and viewed on the web or an intranet.</li>
</ul>
<p>There are some established methods for maintaining a plain-text task list (<a href="http://orgmode.org/">Org Mode</a> immediately comes to mind). My preferred method is to use <a href="http://asciidoc.org/">AsciiDoc</a> formatted files for managing the content. Vim (of course) is used for the editing and Dropbox (<a href="https://db.tt/1FjFwYx">referral link</a>) keeps everything synced. Here is a basic file template:</p>
<div class="highlight"><pre><span></span><code>My Task List
============
- '2014-02-01': Fix leaky plumbing.
- '2014-02-02': Paint front porch.
</code></pre></div>
<p>The basic idea is to create a single bullet list entry for each open task. The task creation date is appended to the entry using a timestamp ('YYYY-MM-DD'); the single quotes around the timestamp are an aesthetic convention.</p>
<p>For some lists, it may be useful to organize tasks as either open (unfinished) or finished. Sections work well for this:</p>
<div class="highlight"><pre><span></span><code>== Open Tasks
- '2014-02-13': Order flowers.
== Finished Task
- '2014-02-13': Make reservations at fancy restaurant.
</code></pre></div>
<p>Another option is to organize tasks as either Current, Planned, or Finished. Using this method, new tasks are added to the "Planned Tasks" section and moved into the "Current Tasks" section as they are addressed. When complete, tasks are moved into the "Finished Tasks" section and a sub-note can be added with addition information:</p>
<div class="highlight"><pre><span></span><code>== Current Tasks
- '2014-01-05': Write code.
== Planned Tasks
- '2014-01-05': Write user manual.
== Finshed Tasks
* '2014-01-05': Write design docs.
** '2014-01-10': Design docs have been written and baselined.
</code></pre></div>
<p>Note that I like using an asterisk to denote that a task is complete. There is no synatical difference between a bullet item with a hyphen or an asterisk; it is simply an aesthetic convention. Notes added to a finished task use the double asterisk syntax in order to make them a sub-bullet item.</p>
<p>If you are a Vim user and decide to employ this method of managing task lists, I highly recommend the excellent <a href="https://github.com/garbas/vim-snipmate">SnipMate</a> plugin for quickly entering timestamps. This plugin is a huge timesaver when editing task files and is just awesome in general (so go get it).</p>
<p>There are several optional improvements that can be made to your list including tagging, referencing, and short-lists. These will be covered in future posts. Additionally, since AsciiDoc natively renders to a beautiful HTML format, it is very easy to publish a list for viewing from a web browser; we can explore some of the options for publishing task lists (either statically or dynamically). For now, happy tasking!</p>Introducing CsvPal2014-01-19T00:00:00-05:002014-01-19T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-01-19:/posts/2014/01/introducing-csvpal/<p>When picking a simple but useful data format, CSV is tough to beat. However, looking through large files can be cumbersome. For this reason, I threw together <a href="https://github.com/jeffrimko/CsvPal">CsvPal</a>, a simple command-line utility for filtering out columns of interest. Check it out if you frequently work with large CSV files.</p>My Blogging Workflow2014-01-09T00:00:00-05:002014-01-09T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2014-01-09:/posts/2014/01/my-blogging-workflow/<p>I recently switched from Blogger to this new blog (JeffComputes). Blogger is competent and feature-rich however I wanted a bit more control over my blogging platform. The blog is now powered by <a href="http://www.getpelican.com/">Pelican</a>, a great static website generator written in Python. The theme is a <a href="https://github.com/jeffrimko/fresh-jeffcomputes">customized version</a> of <a href="https://github.com/jsliang/pelican-fresh">fresh</a> by Jui-Shan Liang. The hosting is provided by <a href="http://ramnode.com/">RamNode</a> and their great VPS lineup. The workflow for writing a post looks like this:</p>
<ol>
<li>All of the …</li></ol><p>I recently switched from Blogger to this new blog (JeffComputes). Blogger is competent and feature-rich however I wanted a bit more control over my blogging platform. The blog is now powered by <a href="http://www.getpelican.com/">Pelican</a>, a great static website generator written in Python. The theme is a <a href="https://github.com/jeffrimko/fresh-jeffcomputes">customized version</a> of <a href="https://github.com/jsliang/pelican-fresh">fresh</a> by Jui-Shan Liang. The hosting is provided by <a href="http://ramnode.com/">RamNode</a> and their great VPS lineup. The workflow for writing a post looks like this:</p>
<ol>
<li>All of the blog content is maintained in a <a href="http://fossil-scm.org/">Fossil</a> repository (I prefer Fossil over Git for smaller projects) in my Dropbox folder; the customized theme is also maintained on GitHub (Git and Fossil play well together).</li>
<li>New posts are typically written in Markdown but could instead be written in ReStructuredText or AsciiDoc if more expressive markup is needed.</li>
<li>A series of scripts are used to generate and test the website locally.</li>
<li>Once the new post is reviewed via the local test server, a script handles uploading the content to the VPS.</li>
</ol>
<p>That's it! It's a pretty straightforward process once everything has been set up. The only minor gripe with Pelican is that it's category based. I wanted to keep all the blog posts together in a single category and use tags to organize them. This is doable with Pelican but does require a bit of modification (hence the custom theme).</p>Quickly Render AsciiDoc Notes2013-12-30T00:00:00-05:002013-12-30T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2013-12-30:/posts/2013/12/quickly-render-asciidoc-notes/<p><a href="http://asciidoc.org/">AsciiDoc</a> is a great markup format for writing notes. In fact, almost all computer-based notes I write are in AsciiDoc; it is simple yet expressive, portable, and most importantly, grepable.</p>
<p>While Vim is my primary tool for viewing AsciiDoc files, looking through the raw text can leave a bit to be desired. Longing for the beautifully rendered output that only an AsciiDoc file can provide, I threw together the following simple (and ugly) Python script …</p><p><a href="http://asciidoc.org/">AsciiDoc</a> is a great markup format for writing notes. In fact, almost all computer-based notes I write are in AsciiDoc; it is simple yet expressive, portable, and most importantly, grepable.</p>
<p>While Vim is my primary tool for viewing AsciiDoc files, looking through the raw text can leave a bit to be desired. Longing for the beautifully rendered output that only an AsciiDoc file can provide, I threw together the following simple (and ugly) Python script:</p>
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">tempfile</span><span class="o">,</span> <span class="nn">webbrowser</span>
<span class="n">tmpf</span> <span class="o">=</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">mktemp</span><span class="p">(</span><span class="s2">".html"</span><span class="p">,</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">-"</span><span class="o">%</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])))</span>
<span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s2">"asciidoc -o </span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">tmpf</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
<span class="n">webbrowser</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">tmpf</span><span class="p">)</span>
</code></pre></div>
<p>This script takes an AsciiDoc file path as an argument, renders it to HTML as a temporary file, then views the HTML file using the default browser. One downside to this script is that the temporary file is not automatically deleted.</p>
<p>If Windows happens to be your OS of choice, you can easily add this script to the <a href="http://msdn.microsoft.com/en-us/library/cc144171(v=vs.85).aspx">Explorer context menu</a>. Using <code>regedit</code>, find the registry key of the file extension typically associated with AsciiDoc; I use <code>.txt</code> but some common alternatives are <code>.asc</code> and <code>.asciidoc</code>. Add a new static verb named "View as AsciiDoc" (or something similar) and make the command <code>python <PATH_TO_SCRIPT> %1</code>. Now when right-clicking on AsciiDoc files within the Windows Explorer, you will have an option like the one show here:</p>
<p><img alt="Windows Context Menu Option" src="/images/view_as_asciidoc.png" title="Windows Context Menu Option"></p>New Blog2013-12-26T00:00:00-05:002013-12-26T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2013-12-26:/posts/2013/12/new-blog/<p>Welcome to my new blog, JeffComputes. All previous posts have been imported from my old blog, Audiodidactic. This blog is powered by <a href="http://blog.getpelican.com/">Pelican</a>, allowing me to write content directly as <a href="http://daringfireball.net/projects/markdown/">Markdown</a> or <a href="http://asciidoc.org/">AsciiDoc</a> files. I will post a writeup with more information about my blogging process soon. Thanks for reading!</p>Vim Highlight Shortcuts2013-12-14T00:00:00-05:002013-12-14T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2013-12-14:/posts/2013/12/vim-highlight-shortcuts/<p>Highlighting in Vim is super useful when trying to quickly see where something is being used. The following commands can be added to your vimrc file to make highlighting a breeze:</p>
<div class="highlight"><pre><span></span><code>"{-- Commands to highlight the word under the cursor without moving the buffer view or cursor. --
" Case sensitive, partial match inclusive.
noremap hi :set hlsearch:let @/=''
" Case sensitive, no partial match.
noremap ho :set hlsearch:let @/='\<\>'
" Case insensitive, partial match inclusive.
noremap hu :set hlsearch …</code></pre></div><p>Highlighting in Vim is super useful when trying to quickly see where something is being used. The following commands can be added to your vimrc file to make highlighting a breeze:</p>
<div class="highlight"><pre><span></span><code>"{-- Commands to highlight the word under the cursor without moving the buffer view or cursor. --
" Case sensitive, partial match inclusive.
noremap hi :set hlsearch:let @/=''
" Case sensitive, no partial match.
noremap ho :set hlsearch:let @/='\<\>'
" Case insensitive, partial match inclusive.
noremap hu :set hlsearch:let @/='\c'
" Case insensitive, no partial match.
noremap hy :set hlsearch:let @/='\<\>\c'
"----}
" Command to remove highlighting.
noremap noh :noh
</code></pre></div>Podcasts For Software Developers2013-11-24T00:00:00-05:002013-11-24T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2013-11-24:/posts/2013/11/podcasts-for-software-developers/<p>Some great podcasts covering topics related to software development:</p>
<ul>
<li><a href="http://rubyrogues.com/">Ruby Rogues</a> - The topics covered by this show are fairly broad and are applicable even if you are not a Ruby or even a web developer. For example, a recent episode discussed how to learn new skills as a developer. Conversational format; new episodes weekly.</li>
<li><a href="http://www.jupiterbroadcasting.com/show/coderradio/">Coder Radio</a> - Topics tend to be fairly non-technical and mainly revolve around recent news, mobile development and contracting. Conversational format; new …</li></ul><p>Some great podcasts covering topics related to software development:</p>
<ul>
<li><a href="http://rubyrogues.com/">Ruby Rogues</a> - The topics covered by this show are fairly broad and are applicable even if you are not a Ruby or even a web developer. For example, a recent episode discussed how to learn new skills as a developer. Conversational format; new episodes weekly.</li>
<li><a href="http://www.jupiterbroadcasting.com/show/coderradio/">Coder Radio</a> - Topics tend to be fairly non-technical and mainly revolve around recent news, mobile development and contracting. Conversational format; new episodes weekly.</li>
<li><a href="http://hanselminutes.com/">Hanselminutes</a> - Scott Hanselman (well known Microsoft developer) interviews other developers in this podcast that covers a wide variety of topics. Interview format; new episodes weekly.</li>
<li><a href="http://twit.tv/floss">FLOSS Weekly</a> - Each episode focuses on a single open source project. The majority of each episode consists of an interview with a programmer or lead associated with the project. Interview format; new episodes weekly.</li>
<li><a href="http://programmingthrowdown.blogspot.com/">Programming Throwdown</a> - Each episode covers a single topic such as a specific programming language or technology. The discussion is kept fairly high-level and provides a good overview of the topic. Conversational format; new episodes monthly.</li>
</ul>Vim Plugin Picks2013-11-09T00:00:00-05:002013-11-09T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2013-11-09:/posts/2013/11/vim-plugin-picks/<p>The following are a few Vim plugins that really boost productivity with this fantastic editor:</p>
<ul>
<li><a href="https://github.com/Lokaltog/vim-easymotion">EasyMotion</a> - Makes moving to a specific location a breeze; see it in action <a href="http://www.youtube.com/watch?v=Dmv6-dguS3g">here</a>.</li>
<li><a href="https://github.com/sandeepcr529/Buffet.vim">Buffet</a> - My favorite plugin for moving between open buffers.</li>
<li><a href="https://github.com/kien/ctrlp.vim">CtrlP</a> - Quickly open files within a project directory structure via fuzzy search.</li>
<li><a href="https://bitbucket.org/ns9tks/vim-fuzzyfinder/">FuzzyFinder</a> - Fuzzy searching for buffers, files, tags, etc.</li>
<li><a href="https://github.com/vim-scripts/mru.vim">MRU</a> - Simple plugin that shows a list of the most recently used files.</li>
</ul>
<p>Quick note on using …</p><p>The following are a few Vim plugins that really boost productivity with this fantastic editor:</p>
<ul>
<li><a href="https://github.com/Lokaltog/vim-easymotion">EasyMotion</a> - Makes moving to a specific location a breeze; see it in action <a href="http://www.youtube.com/watch?v=Dmv6-dguS3g">here</a>.</li>
<li><a href="https://github.com/sandeepcr529/Buffet.vim">Buffet</a> - My favorite plugin for moving between open buffers.</li>
<li><a href="https://github.com/kien/ctrlp.vim">CtrlP</a> - Quickly open files within a project directory structure via fuzzy search.</li>
<li><a href="https://bitbucket.org/ns9tks/vim-fuzzyfinder/">FuzzyFinder</a> - Fuzzy searching for buffers, files, tags, etc.</li>
<li><a href="https://github.com/vim-scripts/mru.vim">MRU</a> - Simple plugin that shows a list of the most recently used files.</li>
</ul>
<p>Quick note on using CtrlP with <a href="http://www.fossil-scm.org/">Fossil</a>, modify the g:ctrlp_root_markers variable to include '_FOSSIL_' (and '*.fossil' if repos are kept locally with that extension). Now you can easily jump to any file in the open repo.</p>Parsing With Parsimonious2013-05-08T00:00:00-04:002013-05-08T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2013-05-08:/posts/2013/05/parsing-with-parsimonious/<p>Recently I have been playing around with a parsing library for Python called <a href="https://github.com/erikrose/parsimonious">Parsimonious</a>. So far, I have been very impressed with it. Examples can be a bit hard to find; the following is a simple CSV parser:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">parsimonious.grammar</span> <span class="kn">import</span> <span class="n">Grammar</span>
<span class="kn">from</span> <span class="nn">parsimonious.nodes</span> <span class="kn">import</span> <span class="n">NodeVisitor</span>
<span class="k">class</span> <span class="nc">EntryParser</span><span class="p">(</span><span class="n">NodeVisitor</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">grammar</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">entry</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">ast</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">visit</span><span class="p">(</span><span class="n">ast</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">visit_name</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">vc</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">entry</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="o">=</span> <span class="n">n …</span></code></pre></div><p>Recently I have been playing around with a parsing library for Python called <a href="https://github.com/erikrose/parsimonious">Parsimonious</a>. So far, I have been very impressed with it. Examples can be a bit hard to find; the following is a simple CSV parser:</p>
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">parsimonious.grammar</span> <span class="kn">import</span> <span class="n">Grammar</span>
<span class="kn">from</span> <span class="nn">parsimonious.nodes</span> <span class="kn">import</span> <span class="n">NodeVisitor</span>
<span class="k">class</span> <span class="nc">EntryParser</span><span class="p">(</span><span class="n">NodeVisitor</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">grammar</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">entry</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">ast</span> <span class="o">=</span> <span class="n">Grammar</span><span class="p">(</span><span class="n">grammar</span><span class="p">)</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">visit</span><span class="p">(</span><span class="n">ast</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">visit_name</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">vc</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">entry</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="o">=</span> <span class="n">n</span><span class="o">.</span><span class="n">text</span>
<span class="k">def</span> <span class="nf">visit_gender</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">vc</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">entry</span><span class="p">[</span><span class="s1">'gender'</span><span class="p">]</span> <span class="o">=</span> <span class="n">n</span><span class="o">.</span><span class="n">text</span>
<span class="k">def</span> <span class="nf">visit_age</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">vc</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">entry</span><span class="p">[</span><span class="s1">'age'</span><span class="p">]</span> <span class="o">=</span> <span class="n">n</span><span class="o">.</span><span class="n">text</span>
<span class="k">def</span> <span class="nf">generic_visit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">vc</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">grammar</span> <span class="o">=</span> <span class="s2">"""</span><span class="se">\</span>
<span class="s2">entry = name sep gender? (sep age)?</span>
<span class="s2">sep = ws "," ws</span>
<span class="s2">ws = " "*</span>
<span class="s2">name = ~"[A-z]*"</span>
<span class="s2">gender = "male" / "female"</span>
<span class="s2">age = ~"[0-9]*"</span>
<span class="s2">"""</span>
<span class="n">text</span> <span class="o">=</span> <span class="s2">"""</span><span class="se">\</span>
<span class="s2">Bob, male, 26</span>
<span class="s2">Kim,female,30</span>
<span class="s2">Joe,male</span>
<span class="s2">"""</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">text</span><span class="o">.</span><span class="n">splitlines</span><span class="p">():</span>
<span class="nb">print</span> <span class="n">EntryParser</span><span class="p">(</span><span class="n">grammar</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span><span class="o">.</span><span class="n">entry</span>
</code></pre></div>
<p>The resulting output is the following:</p>
<div class="highlight"><pre><span></span><code>{'gender': 'male', 'age': '26', 'name': 'Bob'}
{'gender': 'female', 'age': '30', 'name': 'Kim'}
{'gender': 'male', 'name': 'Joe'}
</code></pre></div>Hidden Fossil Features2013-04-19T00:00:00-04:002013-04-19T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2013-04-19:/posts/2013/04/hidden-fossil-features/<p>The <a href="http://fossil-scm.org/">Fossil</a> version control software has a few cool features that are somewhat hidden:</p>
<ul>
<li><strong>RSS Timeline</strong> - Add <code>.rss</code> after a projects timeline URL to get an RSS feed; <a href="http://fossil-scm.org/index.html/timeline.rss">example</a>.</li>
<li><strong>Link To Line Number</strong> - Add <code>?ln=</code> to an artifacts URL to link directly to a given line number; <a href="http://fossil-scm.org/index.html/artifact/e09a3a97c8a7c06a3007180d3ee68e08d7efdaf9?ln=116">example</a>.</li>
</ul>Furnace Debugging2013-02-17T00:00:00-05:002013-02-17T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2013-02-17:/posts/2013/02/furnace-debugging/<p>A few days ago, the blower motor on my Carrier Weathermaker 9200 furnace stopped working. Luckily, this model of furnace provides quite a bit of debugging information printed on the inside of the door. It was very straightforward to test the blower motor and confirm that it was not the source of the problem. After a bit of poking around with a multimeter, the only remaining possibility was the blower motor relay.</p>
<p><img alt="Resoldered Relay Trace on Control PCB" src="/images/relay_fix.png" title="Resoldered Relay Trace on Control PCB"></p>
<p>This furnace is …</p><p>A few days ago, the blower motor on my Carrier Weathermaker 9200 furnace stopped working. Luckily, this model of furnace provides quite a bit of debugging information printed on the inside of the door. It was very straightforward to test the blower motor and confirm that it was not the source of the problem. After a bit of poking around with a multimeter, the only remaining possibility was the blower motor relay.</p>
<p><img alt="Resoldered Relay Trace on Control PCB" src="/images/relay_fix.png" title="Resoldered Relay Trace on Control PCB"></p>
<p>This furnace is equipped with a HK42FZ008 control board. This board holds the <a href="http://www.newark.com/te-connectivity-potter-brumfield/t9as1d12-22/relay-spst-no-22vdc-30a-pcb/dp/48M8324">blower motor relay</a> along with the control circuitry. There is a clamshell style case that snaps in place around the board; the relay is not accessible without removing this case. Once removed, the source of the issue was obvious. It appeared as if the solder around one of the legs of the relay burned up. The damage was enough to burn the PCB copper around the leg so that there was no electrical connection between the board and the relay. After testing the relay to make sure it still function properly, the solution was to expose enough copper of the trace leading up to the relay so that a large amount of solder could be added. Hopefully, the solder will be enough to handle the large motor currents that likely caused the issue in the first place.</p>
<p>The blower motor has been running fine ever since the repair. It is possible that an issue with the motor resulted in an unusually large amount of current draw causing the relay connection to fail. However, there is a 3 amp fuse on the motor supply line that was still intact. To my knowledge, the control board is original to the furnace which is about 20 years old. It may simply be a case of failure over time.</p>Vim For Health2013-02-05T00:00:00-05:002013-02-05T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2013-02-05:/posts/2013/02/vim-for-health/<p>Today I was watching a video on using Vim as a Python IDE when <a href="https://www.youtube.com/watch?v=YhqsjUUHj6g#t=2m50s">a
comment about the health benefits of
Vim</a> caught my
attention. Oddly enough, one of the reasons I decided to learn Vim was
because of hand pain. After switching to Vim full-time, I have
experienced less pain and could not imagine going back.</p>
<p>One additional step I took was to remap the left Ctrl key to Caps Lock.
This has made …</p><p>Today I was watching a video on using Vim as a Python IDE when <a href="https://www.youtube.com/watch?v=YhqsjUUHj6g#t=2m50s">a
comment about the health benefits of
Vim</a> caught my
attention. Oddly enough, one of the reasons I decided to learn Vim was
because of hand pain. After switching to Vim full-time, I have
experienced less pain and could not imagine going back.</p>
<p>One additional step I took was to remap the left Ctrl key to Caps Lock.
This has made a huge impact since I use the Ctrl key frequently and find
the position of the key to be awkward. Hitting the normal key requires
either a left hand movement or curling up the pinky finger; it is a
recipe for hand cramps! The Caps Lock key being on the home row feels
more natural. I use <a href="http://sharpkeys.codeplex.com/">SharpKeys</a> to
handle the remapping on my Windows machines.</p>Qt 4.8.4 And MinGW Quick Start2012-12-30T00:00:00-05:002012-12-30T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2012-12-30:/posts/2012/12/qt-484-and-mingw-quick-start/<p>The following are instructions for installing <a href="http://qt-project.org/">Qt</a> and compiling a demo application using the <a href="http://www.mingw.org/">MinGW</a> toolchain:</p>
<ol>
<li>Download the Qt 4.8.4 libraries installer <a href="http://releases.qt-project.org/qt4/source/qt-win-opensource-4.8.4-mingw.exe">here</a>.</li>
<li>Run the installer. If a warning message about the version of the <code>w32api.h</code> file appears ignore it and continue the installation (my install is version 3.17 and appears to work fine).</li>
<li>By default, the installer does not add the Qt toolchain to the PATH. Instead, it provides a …</li></ol><p>The following are instructions for installing <a href="http://qt-project.org/">Qt</a> and compiling a demo application using the <a href="http://www.mingw.org/">MinGW</a> toolchain:</p>
<ol>
<li>Download the Qt 4.8.4 libraries installer <a href="http://releases.qt-project.org/qt4/source/qt-win-opensource-4.8.4-mingw.exe">here</a>.</li>
<li>Run the installer. If a warning message about the version of the <code>w32api.h</code> file appears ignore it and continue the installation (my install is version 3.17 and appears to work fine).</li>
<li>By default, the installer does not add the Qt toolchain to the PATH. Instead, it provides a custom command prompt environment called the "Qt 4.8.4 Command Prompt"; launch this command prompt from the Start menu.</li>
<li>Now we can try compiling an example; from the Qt command prompt, navigate to <code>C:\Qt\4.8.4\demos\textedit</code>.</li>
<li>Execute the command <code>qmake</code>; this should generate a makefile.</li>
<li>Build the example using the command <code>make</code>.</li>
<li>If everything goes correctly, <code>textedit.exe</code> should now exist in the <code>debug</code> directory; launch the demo application.</li>
</ol>
<p>That’s it! Your machine is now ready to build Qt apps using MinGw.</p>Vim Zoom Hack2012-12-22T00:00:00-05:002012-12-22T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2012-12-22:/posts/2012/12/vim-zoom-hack/<p>When writing large documents with a text editor, it is sometimes useful to zoom out and get a high-level view of the file (I believe Sublime Text has a feature called minimap that does this). This functionality can be added to gVim with a simple vimrc addition (to my knowledge, this will not work with regular Vim).</p>
<p>Add the zoom out command with the following: <code>noremap <Leader>zo :set guifont=courier_new:h4<CR></code></p>
<p>Add the …</p><p>When writing large documents with a text editor, it is sometimes useful to zoom out and get a high-level view of the file (I believe Sublime Text has a feature called minimap that does this). This functionality can be added to gVim with a simple vimrc addition (to my knowledge, this will not work with regular Vim).</p>
<p>Add the zoom out command with the following: <code>noremap <Leader>zo :set guifont=courier_new:h4<CR></code></p>
<p>Add the zoom in command with the following: <code>noremap <Leader>zi :set guifont=courier_new:h10<CR></code></p>
<p>Adjust the font type and normal size as desired. Not the most elegant method but it works. Please note that split window sizes may be affected during the zooming process (it is a hack after all).</p>Docopt2012-12-01T00:00:00-05:002012-12-01T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2012-12-01:/posts/2012/12/docopt/<p>While browsing YouTube recently, I stumbled upon <a href="http://www.youtube.com/watch?v=pXhcPJK5cMc">a video</a> about a great third-party Python module called <a href="http://www.docopt.org/">Docopt</a>. It greatly simplifies writing command-line utilities; instead of writing custom logic using the standard library <code>optparse</code> or <code>argparse</code> modules, you simply write the usage docs for the utility and Docopt handles the parsing. Check out the documentation; there are some great examples that really showcase the power of this module.</p>PopPage2012-12-01T00:00:00-05:002012-12-01T00:00:00-05:00Jeff Rimkotag:www.jeffcomput.es,2012-12-01:/posts/2012/12/poppage/<p>Recently, I had a need for a very lightweight static website generator. The idea was to have <a href="http://www.methods.co.nz/asciidoc/">AsciiDoc</a> and <a href="http://johnmacfarlane.net/pandoc/">Pandoc</a> handle the markup to HTML conversions while the generator would simply apply the HTML content to a <a href="http://jinja.pocoo.org/docs/">Jinja2</a> template. The result was <a href="http://github.com/jeffrimko/PopPage">PopPage</a>, a simple command-line driven website generator. It plays nicely with native Windows batch scripting and I plan on providing a few examples in the GitHub repo shortly.</p>Raspberry Pi First Impressions2012-08-19T00:00:00-04:002012-08-19T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2012-08-19:/posts/2012/08/raspberry-pi-first-impressions/<p>Received my first <a href="http://www.raspberrypi.org/">Raspberry Pi</a> the other day. I ordered two <a href="http://www.newark.com/raspberry-pi/raspbrry-pcba/raspberry-pi-model-b-board-only/dp/83T1943">Model B devices from Newark</a> and, despite the high demand, received them in about a week.
My intended use for the first R-Pi was to serve as a mini-HTPC for my basement TV. I tried both <a href="http://elinux.org/Omxplayer">Omxplayer</a> running on <a href="http://www.raspbian.org/">Raspbian</a> and <a href="http://www.raspbmc.com/">Raspbmc</a>. I was very please with the performance of both; they were able to stream videos from my NAS with no issue. Unfortunately …</p><p>Received my first <a href="http://www.raspberrypi.org/">Raspberry Pi</a> the other day. I ordered two <a href="http://www.newark.com/raspberry-pi/raspbrry-pcba/raspberry-pi-model-b-board-only/dp/83T1943">Model B devices from Newark</a> and, despite the high demand, received them in about a week.
My intended use for the first R-Pi was to serve as a mini-HTPC for my basement TV. I tried both <a href="http://elinux.org/Omxplayer">Omxplayer</a> running on <a href="http://www.raspbian.org/">Raspbian</a> and <a href="http://www.raspbmc.com/">Raspbmc</a>. I was very please with the performance of both; they were able to stream videos from my NAS with no issue. Unfortunately <a href="http://www.mplayerhq.hu/">mplayer</a> on Raspian currently does not support GPU acceleration on the R-Pi and lacks the horsepower to be of any use. For now, Raspbmc will likely remain the frontend of choice for the HTPC.
Overall, the value of the R-Pi is amazing! For \$35, this device is an absolute bargain and a must have for any tech DIYer.</p>Vim Scratch Buffer2012-08-15T00:00:00-04:002012-08-15T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2012-08-15:/posts/2012/08/vim-scratch-buffer/<p>Opening a scratch buffer in Vim can come in handy. The following vimrc addition works well: <code>nnoremap <Leader>sc :e scratch<CR>:setlocal readonly<CR></code></p>
<p>It is especially useful in combination with the <a href="http://jeffrimko.blogspot.com/2012/08/fossil-command-line-tips_8883.html">run shell command shortcut</a> once Vim is configured to change to the directory of the current file with the following vimrc addition: <code>autocmd BufEnter * execute "chdir ".escape(expand("%:p:h"), ' ')</code></p>
<p>The advantage this named buffer has over the <code>[No Name]</code> buffers created …</p><p>Opening a scratch buffer in Vim can come in handy. The following vimrc addition works well: <code>nnoremap <Leader>sc :e scratch<CR>:setlocal readonly<CR></code></p>
<p>It is especially useful in combination with the <a href="http://jeffrimko.blogspot.com/2012/08/fossil-command-line-tips_8883.html">run shell command shortcut</a> once Vim is configured to change to the directory of the current file with the following vimrc addition: <code>autocmd BufEnter * execute "chdir ".escape(expand("%:p:h"), ' ')</code></p>
<p>The advantage this named buffer has over the <code>[No Name]</code> buffers created by <code>:enew</code> is that newly created scratch buffers will not affect the path of existing buffers. This can be useful if you later want to save the contents of your scratch buffer.</p>Fossil Command-Line Tips2012-08-05T00:00:00-04:002012-08-05T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2012-08-05:/posts/2012/08/fossil-command-line-tips/<p>For small projects, <a href="http://www.fossil-scm.org/">Fossil</a> is a great choice for version control. Fossil's command-line interface is very easy to use and plays nice with utilities like <code>grep</code>, <code>gawk</code> and <code>xargs</code>. The following are examples of common operations:</p>
<ul>
<li>
<p>Check in only edited files: <code>fossil changes | grep EDITED | gawk '{print $2}' | xargs fossil commit -m "Added feature X."</code></p>
</li>
<li>
<p>Add only files with name containing "pattern" to repo: <code>fossil extras | grep pattern | xargs fossil add</code></p>
</li>
<li>
<p>Move files in repo …</p></li></ul><p>For small projects, <a href="http://www.fossil-scm.org/">Fossil</a> is a great choice for version control. Fossil's command-line interface is very easy to use and plays nice with utilities like <code>grep</code>, <code>gawk</code> and <code>xargs</code>. The following are examples of common operations:</p>
<ul>
<li>
<p>Check in only edited files: <code>fossil changes | grep EDITED | gawk '{print $2}' | xargs fossil commit -m "Added feature X."</code></p>
</li>
<li>
<p>Add only files with name containing "pattern" to repo: <code>fossil extras | grep pattern | xargs fossil add</code></p>
</li>
<li>
<p>Move files in repo to match move on filesystem: <code>fossil changes | grep MISSING | gawk '{print "fossil mv " $2 " subdir/" $2}' | sh</code></p>
</li>
</ul>Vim Run Shell Command2012-08-05T00:00:00-04:002012-08-05T00:00:00-04:00Jeff Rimkotag:www.jeffcomput.es,2012-08-05:/posts/2012/08/vim-run-shell-command/<p>Here is a nice simple vimrc file addition that will execute a line as a shell command and read back the output into the buffer: <code>nnoremap <Leader>rl yy:r!<C-r>"<CR></code></p>