<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexandru Bucur</title>
    <description>The latest articles on DEV Community by Alexandru Bucur (@coolgoose).</description>
    <link>https://dev.to/coolgoose</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F7888%2F9267160d-dc0d-4f73-b653-3eb83ca4d5fd.jpeg</url>
      <title>DEV Community: Alexandru Bucur</title>
      <link>https://dev.to/coolgoose</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/coolgoose"/>
    <language>en</language>
    <item>
      <title>Simple UUID wrapper for MySQL in Go that covers UUID to BIN conversion</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Sun, 20 Aug 2023 18:08:51 +0000</pubDate>
      <link>https://dev.to/coolgoose/simple-uuid-wrapper-for-mysql-in-go-that-covers-uuid-to-bin-conversion-445h</link>
      <guid>https://dev.to/coolgoose/simple-uuid-wrapper-for-mysql-in-go-that-covers-uuid-to-bin-conversion-445h</guid>
      <description>&lt;p&gt;Here's a quick snippet you can use to create a custom type that maps an UUID to a Binary(16) representation in MySQL.&lt;/p&gt;

&lt;p&gt;I assume this is not present in &lt;code&gt;gofrs/uuid&lt;/code&gt; since it's database specific, but having NullUUID available is an easy 'inspiration' opportunity ;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"database/sql/driver"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gofrs/uuid/v5"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;NullBinaryUUID&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;UUID&lt;/span&gt;  &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;
    &lt;span class="n"&gt;Valid&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="c"&gt;// Valid is true if UUID is not NULL&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Value implements the driver.Valuer interface.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;NullBinaryUUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Valid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Delegate to UUID Value function&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Scan implements the sql.Scanner interface.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;NullBinaryUUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Delegate to UUID Scan function&lt;/span&gt;
    &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>go</category>
      <category>mysql</category>
      <category>beginners</category>
      <category>tips</category>
    </item>
    <item>
      <title>Are Dev Containers the future for local development environments?</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Wed, 02 Aug 2023 18:08:51 +0000</pubDate>
      <link>https://dev.to/coolgoose/are-dev-containers-the-future-for-local-development-environments-3c5c</link>
      <guid>https://dev.to/coolgoose/are-dev-containers-the-future-for-local-development-environments-3c5c</guid>
      <description>&lt;p&gt;What are Dev Containers you might ask?&lt;br&gt;
Elementary, my dear Watson* / fellow developer.&lt;/p&gt;

&lt;p&gt;It's a fancy way of using container images as a full blown development environment. You can read &lt;a href="https://containers.dev/"&gt;containers.dev&lt;/a&gt; for more details, but the key IMHO that is missing on the homepage, is that it can run actual &lt;a href="https://compose-spec.io/"&gt;compose.yaml&lt;/a&gt; (popularised by docker-compose) as an entry point.&lt;/p&gt;

&lt;p&gt;You can consider this post a follow up &lt;a href="https://dev.to/tech/2023/a-golang-journey-in-live-reload-and-pretty-panics/"&gt;A Go(lang) journey in live reload and pretty panics&lt;/a&gt;.&lt;br&gt;
As I was writing tests, I realised that by just starting docker compose, there's no easy way to have the tests also run in the container while also allowing the usage of the built in debugger in vscode.&lt;/p&gt;

&lt;p&gt;I decided to give devcontainers a go, and see how they would work. &lt;br&gt;
The idea as mentioned in the intro is pretty nice since it allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use a compose.yaml as your actual entry point to the system&lt;/li&gt;
&lt;li&gt;setup the required extensions in vscode (not strictly in the spec, but a nice to have)&lt;/li&gt;
&lt;li&gt;have the tests run in the actual container, so you don't need to worry about different golang versions (or any other problems you might have with project specific packages)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could argue that compared to the old-school setup of setting up your images, and then using them in something like Vagrant, this is a newer approach in which composability (ha, the puns) helps you build your development environment from various pieces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1R1lwt6B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2tvftmvu3p6wh6ryg2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1R1lwt6B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2tvftmvu3p6wh6ryg2i.png" alt="Devcontainers Development" width="677" height="632"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your database has different dependencies and packages from your queue system this makes it an non issue as each runs in its own container. Same goes for your test mailing system, queue system and whatever other dependency you will add in the future.&lt;/p&gt;

&lt;p&gt;That brings us to the following config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"API"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dockerComposeFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"../compose.yml"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"workspaceFolder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/go/src/app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"initializeCommand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./scripts/devcontainer.sh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"shutdownAction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stopCompose"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remoteUser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"devuser:devuser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"customizations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"vscode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"terminal.integrated.shell.linux"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/bin/bash"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"extensions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ms-azuretools.vscode-docker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"golang.Go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"eamodio.gitlens"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"timonwong.shellcheck"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"tamasfe.even-better-toml"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you take a quick look at the config, you'll notice an interesting key called &lt;code&gt;initializeCommand&lt;/code&gt; .&lt;br&gt;
That is being used to actually solve a thing / bug / annoyance or whatever you want to call it.&lt;/p&gt;

&lt;p&gt;Usually when you run inside a container, you mount your application code and then the user that container image is built with is the root user.&lt;br&gt;
That makes it annoying for a very simple reason, the owner of the file in WSL is going to be root, making it a pita to do cleanup and/or editing of the vscode workspace when the docker engine (in my case) doesn't work.&lt;/p&gt;

&lt;p&gt;To fix that, I'm semi abusing the functionality provided by compose.yaml to provide build arguments to the base image.&lt;br&gt;
The devcontainer.sh looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Get the current user and group ID in WSL&lt;/span&gt;
&lt;span class="nv"&gt;PROJECT_DOCKER_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;PROJECT_DOCKER_GROUPNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# The comment to add to the .env file&lt;/span&gt;
&lt;span class="nv"&gt;COMMENT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"# The following two environment variables are needed for container to host permission interoperability"&lt;/span&gt;

&lt;span class="c"&gt;# If the .env file exists&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; .env &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;

    &lt;span class="c"&gt;# If the variables exist in the .env file, remove them&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"PROJECT_DOCKER_USERNAME="&lt;/span&gt; .env&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"/PROJECT_DOCKER_USERNAME=/d"&lt;/span&gt; .env
    &lt;span class="k"&gt;fi

    if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"PROJECT_DOCKER_GROUPNAME="&lt;/span&gt; .env&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"/PROJECT_DOCKER_GROUPNAME=/d"&lt;/span&gt; .env
    &lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="c"&gt;# If the comment exists in the .env file, remove it&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-qF&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$COMMENT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; .env&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="nv"&gt;$COMMENT&lt;/span&gt;&lt;span class="s2"&gt;|d"&lt;/span&gt; .env
    &lt;span class="k"&gt;fi
fi&lt;/span&gt;

&lt;span class="c"&gt;# Add the comment and variables to the .env file&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$COMMENT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"PROJECT_DOCKER_USERNAME=&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_DOCKER_USERNAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"PROJECT_DOCKER_GROUPNAME=&lt;/span&gt;&lt;span class="nv"&gt;$PROJECT_DOCKER_GROUPNAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the creation / reuse of the local .env file that gets automatically used by docker as a source for your ENV variables making the usage in compose.yaml painless.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Pass the user and group id as build arguments&lt;/span&gt;
      &lt;span class="na"&gt;USER_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${PROJECT_DOCKER_USERNAME:-1000}&lt;/span&gt; &lt;span class="c1"&gt;# default wsl initial user in case we mess it up&lt;/span&gt;
      &lt;span class="na"&gt;GROUP_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${PROJECT_DOCKER_GROUPNAME:-1000}&lt;/span&gt;
  &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service_healthy&lt;/span&gt; &lt;span class="c1"&gt;# secret db :P&lt;/span&gt;
  &lt;span class="na"&gt;working_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/go/src/app&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8080:8080&lt;/span&gt;
  &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./:/go/src/app&lt;/span&gt;
  &lt;span class="na"&gt;cap_add&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SYS_PTRACE&lt;/span&gt;
  &lt;span class="na"&gt;security_opt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;seccomp:unconfined&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${PROJECT_DOCKER_USERNAME}:${PROJECT_DOCKER_GROUPNAME}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we get to the &lt;code&gt;Dockerfile&lt;/code&gt; itself. It's technically a container image, but for all intents and purposes you shouldn't treat it different than a normal VM.&lt;br&gt;
This is a development environment, so it is going to need all kinds of packages, especially for support tools like git.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.20-bookworm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;api&lt;/span&gt;

&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; USER_ID&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; GROUP_ID&lt;/span&gt;

&lt;span class="c"&gt;# let's add the group / user based on the ARG's passed by compose.yaml&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;addgroup &lt;span class="nt"&gt;--gid&lt;/span&gt; &lt;span class="nv"&gt;$GROUP_ID&lt;/span&gt; devuser
&lt;span class="k"&gt;RUN &lt;/span&gt;adduser &lt;span class="nt"&gt;--uid&lt;/span&gt; &lt;span class="nv"&gt;$USER_ID&lt;/span&gt; &lt;span class="nt"&gt;--gid&lt;/span&gt; &lt;span class="nv"&gt;$GROUP_ID&lt;/span&gt; &lt;span class="nt"&gt;--disabled-password&lt;/span&gt; &lt;span class="nt"&gt;--gecos&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; devuser

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    git &lt;span class="c"&gt;# and other packages you might need&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /go/src/app&lt;/span&gt;

&lt;span class="c"&gt;# A bunch of golang tools needed by vscode and our app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/cosmtrek/air@latest &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/maruel/panicparse/v2@latest &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go &lt;span class="nb"&gt;install &lt;/span&gt;golang.org/x/tools/gopls@latest &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/go-delve/delve/cmd/dlv@latest &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; go &lt;span class="nb"&gt;install &lt;/span&gt;honnef.co/go/tools/cmd/staticcheck@latest

&lt;span class="c"&gt;# Copy Go modules and dependencies to image&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.mod ./&lt;/span&gt;

&lt;span class="c"&gt;# Download Go modules and dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go mod download

&lt;span class="c"&gt;# Copy directory files&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . ./&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chown &lt;/span&gt;devuser. ./

&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; devuser # finally let's switch to the devuser&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/bin/bash", "scripts/dev.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After all is set and done, it is a pretty nifty and useful setup, since it makes the onboarding in your application a lot more approachable, and developers can just open it in vscoode and have a fully working environment.&lt;/p&gt;

&lt;p&gt;With additional support from &lt;a href="https://containers.dev/supporting"&gt;Jetbrains and other tools&lt;/a&gt; it will become hopefully more wide spread and used in other editors and ides, making the life of a DX (developer experience) engineer a lot easier (or however your organisation calls the hard working people that work on allowing your developers to focus on you know... development).&lt;/p&gt;

&lt;p&gt;If this doesn't work for you, you can buy me a beer and tell me how to improve it ;-).&lt;/p&gt;

&lt;p&gt;&lt;small id="watson"&gt;* Yes, Sherlock never said that, but it's pop culture :P.&lt;/small&gt;&lt;/p&gt;

</description>
      <category>dx</category>
      <category>developers</category>
      <category>docker</category>
      <category>containers</category>
    </item>
    <item>
      <title>Simple Script to Generate Color Scheme Switchable Css</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Wed, 03 May 2023 19:05:51 +0000</pubDate>
      <link>https://dev.to/coolgoose/simple-script-to-generate-color-scheme-switchable-css-2l6o</link>
      <guid>https://dev.to/coolgoose/simple-script-to-generate-color-scheme-switchable-css-2l6o</guid>
      <description>&lt;p&gt;While I was working at yet another secret project that will probably never see the light of day, I wanted to blog about the experience on bootstrapping the project.&lt;br&gt;
As any developer, that means that instead of writing that blog post, I had to dust off my website theme, update hugo, and do other fixes.&lt;/p&gt;

&lt;p&gt;I've settled on &lt;a href="https://github.com/adityatelange/hugo-PaperMod/"&gt;PaperMod&lt;/a&gt; as the theme, since it's simple and to the point, and it also changes the style based on the preferred color scheme.&lt;/p&gt;

&lt;p&gt;However, by default there's no way to have the code highlight theme change based on the preferred color scheme, but since I hopefully still know my css, and with the help of &lt;a href="https://phind.com"&gt;phind&lt;/a&gt; to generate some shell scripting, we now got this nifty script that can help you do just that, be it in a hugo theme, or any other kind of system as long as you "abuse" hugo for the generation of the theme only.&lt;/p&gt;

&lt;p&gt;You see, hugo uses &lt;a href="https://github.com/alecthomas/chroma"&gt;chroma&lt;/a&gt; for its theme support, so that makes it pretty flexible to generate the theme css using &lt;code&gt;hugo gen chromastyles --style=your_style_here_from_the_big_list&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After picking the two &lt;a href="https://xyproto.github.io/splash/docs/longer/all.html"&gt;color schemes&lt;/a&gt; I wanted, namely tango and nord (and fixing &lt;a href="https://github.com/alecthomas/chroma/pull/787"&gt;one of them&lt;/a&gt;, &lt;a href="https://github.com/alecthomas/chroma/pull/786"&gt;twice&lt;/a&gt;) I've set up to ... instruct my lovely assistant to help me build what I need. &lt;/p&gt;

&lt;p&gt;After some back and forth, and some suggestions on what's wrong on the generated script based on &lt;a href="https://www.shellcheck.net/"&gt;ShellCheck&lt;/a&gt;, since Phind has an obsession it seems with escaping &lt;code&gt;$&lt;/code&gt;, we got to this lovely code (&lt;a href="https://gist.github.com/CoolGoose/a0a868738b01f1d564c900c81326698a"&gt;Github Gist&lt;/a&gt; for convenience).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail

&lt;span class="c"&gt;# Default values&lt;/span&gt;
&lt;span class="nv"&gt;light_theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nv"&gt;dark_theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nv"&gt;destination_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"assets/css/extended/syntax.css"&lt;/span&gt;

&lt;span class="c"&gt;# Help message&lt;/span&gt;
usage&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="sh"&gt; [options] [--] [light-theme] [dark-theme]

Options:
  -h, --help                Show this help message and exit
  --light-theme=LIGHT_THEME Set the light theme
  --dark-theme=DARK_THEME   Set the dark theme
  --destination-path=PATH   Set the destination path for the output file

Positional arguments:
  light-theme              Light theme (alternative to --light-theme)
  dark-theme               Dark theme (alternative to --dark-theme)
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;positional_arg_counter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0

&lt;span class="c"&gt;# Parse options and arguments&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$# &lt;/span&gt;&lt;span class="nt"&gt;-gt&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  case&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="nt"&gt;-h&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="nt"&gt;--help&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      usage
      &lt;span class="nb"&gt;exit &lt;/span&gt;0
      &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="nt"&gt;--light-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;light_theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;{1#*=}"&lt;/span&gt;
      &lt;span class="nv"&gt;positional_arg_counter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;positional_arg_counter &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="nt"&gt;--dark-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;dark_theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;{1#*=}"&lt;/span&gt;
      &lt;span class="nv"&gt;positional_arg_counter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;positional_arg_counter &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="nt"&gt;--destination-path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;destination_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;{1#*=}"&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$positional_arg_counter&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;light_theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$positional_arg_counter&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 1 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;dark_theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;else
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Too many arguments"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
        usage
        &lt;span class="nb"&gt;exit &lt;/span&gt;1
      &lt;span class="k"&gt;fi
      &lt;/span&gt;&lt;span class="nv"&gt;positional_arg_counter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;positional_arg_counter &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
      &lt;span class="nb"&gt;shift&lt;/span&gt;
      &lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done

if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$light_theme&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$dark_theme&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: Missing arguments"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
  usage
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;hugo gen chromastyles &lt;span class="nt"&gt;--style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$light_theme&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$destination_path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"@media (prefers-color-scheme: dark) {"&lt;/span&gt;
    hugo gen chromastyles &lt;span class="nt"&gt;--style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$dark_theme&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'s/(^\/\*[^*]*\*\/)?(.+)/\1 .dark\2/'&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"}"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$destination_path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The script does add &lt;code&gt;.dark&lt;/code&gt; as an extra class in front of all the classes from the "dark-theme" setup to match the class that's added by PaperMod.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For PaperMod specifically I had to do a few tweaks. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update config.yml|toml|xml
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;pygmentsUseClasses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;markup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;highlight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;codeFences&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;guessSyntax&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;lineNos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;noClasses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nord&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Update the css with some custom overwrites to make sure we're not overwriting the theme background color and fix a few rounded margins
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.post-content&lt;/span&gt; &lt;span class="nc"&gt;.highlight&lt;/span&gt; &lt;span class="nt"&gt;table&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--code-bg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-content&lt;/span&gt; &lt;span class="nc"&gt;.highlight&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.chroma&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hljs-bg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;ltr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-content&lt;/span&gt; &lt;span class="nc"&gt;.highlight&lt;/span&gt; &lt;span class="nc"&gt;.lntable&lt;/span&gt; &lt;span class="nc"&gt;.lntd&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt; &lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-top-right-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom-right-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-content&lt;/span&gt; &lt;span class="nc"&gt;.highlight&lt;/span&gt; &lt;span class="nc"&gt;.lntable&lt;/span&gt; &lt;span class="nc"&gt;.lntd&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt; &lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-top-left-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-bottom-left-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.post-content&lt;/span&gt; &lt;span class="nc"&gt;.highlight&lt;/span&gt; &lt;span class="nc"&gt;.lntable&lt;/span&gt; &lt;span class="nc"&gt;.lntd&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:first-child&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;:last-child&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Needed changes might be slightly different for your theme!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How are you handling code highlights in your theme ?&lt;/p&gt;

</description>
      <category>hugo</category>
      <category>css</category>
      <category>script</category>
    </item>
    <item>
      <title>A Go(lang) journey in live reload and pretty panics</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Wed, 03 May 2023 19:05:51 +0000</pubDate>
      <link>https://dev.to/coolgoose/a-golang-journey-in-live-reload-and-pretty-panics-5kh</link>
      <guid>https://dev.to/coolgoose/a-golang-journey-in-live-reload-and-pretty-panics-5kh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;TLDR: Use docker + cosmtrek/air + &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of my passions is DX, and while I'm not always getting it right, the enjoyment is there to make people's lives a little bit more productive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some context
&lt;/h2&gt;

&lt;p&gt;Coming from a predominantly PHP background, at least in my bubble, having "pretty" error messages when doing development is pretty much a given.&lt;/p&gt;

&lt;p&gt;Regardless of the framework you might be using all of them use &lt;a href="https://www.php.net/set_error_handler"&gt;php.net/set_error_handler &lt;/a&gt; in one way shape or form.&lt;/p&gt;

&lt;p&gt;For example, using &lt;a href="https://github.com/nunomaduro/collision"&gt;nunomaduro/collision&lt;/a&gt; is at easy as doing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nc"&gt;NunoMaduro\Collision\Provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iJ4fRsdz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27ckw8h2z8ll2uh4wwes.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iJ4fRsdz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/27ckw8h2z8ll2uh4wwes.png" alt="PHP Collision Error Handling" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://github.com/symfony/error-handler"&gt;symphony/error-handler&lt;/a&gt; is also easy peasy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\ErrorHandler\Debug&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\ErrorHandler\ErrorHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\ErrorHandler\DebugClassLoader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Debug&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--paph-VkK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rfmnaha68p6mnla742p2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--paph-VkK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rfmnaha68p6mnla742p2.png" alt="PHP Symfony Error Handling" width="800" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Although the Go compiler is generally pretty good on catching errors, you won't always get around runtime errors. That brings me to the fact that in Go, panics are just ugly (personal preference).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nH9bUHxa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nnol17r2s3ptu1fkzzs5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nH9bUHxa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nnol17r2s3ptu1fkzzs5.png" alt="Default Golang panic handler" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since google, bing, ddg and other lovely search engines let me down in finding an equivalent in Go that I can use as a defered panic recover system, I did what everybody would do, and asked my &lt;del&gt;new ai overlords&lt;/del&gt; lovely randomly selected large language model (LLM) (in my case &lt;a href="https://www.phind.com/"&gt;phind&lt;/a&gt;) to whip me up something that gets closer to the PHP Examples above. &lt;/p&gt;

&lt;p&gt;After some back and forth, we got to this lovely sample, which works awesome as a POC.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E7SdbLVH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mnohx6mqqbd0j2uklam2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E7SdbLVH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mnohx6mqqbd0j2uklam2.png" alt="Custom Golang panic handler" width="800" height="303"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;errorhandler&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"bufio"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"runtime"&lt;/span&gt;
    &lt;span class="s"&gt;"runtime/debug"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&lt;/span&gt;
    &lt;span class="s"&gt;"strings"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;red&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;33[31m"&lt;/span&gt;
    &lt;span class="n"&gt;green&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;33[32m"&lt;/span&gt;
    &lt;span class="n"&gt;yellow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;33[33m"&lt;/span&gt;
    &lt;span class="n"&gt;cyan&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;33[36m"&lt;/span&gt;
    &lt;span class="n"&gt;reset&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;\0&lt;/span&gt;&lt;span class="s"&gt;33[0m"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;CustomPanicHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;recover&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Use colored output for the panic message and add an error type&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;%sError: %s%s&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;stackBytes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stackBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;stackLines&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stackBuffer&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;lastRealFilename&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
        &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;lastRealLineNum&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;stackLines&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"runtime/debug.Stack()"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GetFunctionName&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;stackBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stackBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  %s%s%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cyan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;stackBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stackBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;fileAndLine&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;":"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileAndLine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;fileName&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileAndLine&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="n"&gt;lineNum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileAndLine&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;lastRealFilename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fileName&lt;/span&gt;
            &lt;span class="n"&gt;lastRealLineNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lineNum&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Display the offending line only for the last real file found&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lastRealFilename&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fileContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;readFileLines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastRealFilename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error reading file:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;printOffendingLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastRealFilename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastRealLineNum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Print the buffered stack trace&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Panic occurred:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;stackBuffer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// Exit the program with a non-zero status code&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;readFileLines&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;scanner&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bufio&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewScanner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;scanner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;printOffendingLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fileContent&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lineNum&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;startLine&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;lineNum&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;startLine&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;startLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;endLine&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;lineNum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;endLine&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;endLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;%sOffending line: %s%s:%d%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lineNum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;fileContent&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;startLine&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;endLine&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;startLine&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;lineNum&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  %s%d: %s%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;startLine&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  %d: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;startLine&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;GetFunctionName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Caller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FuncForPC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that the above code didn't work correctly when trying to implement a simple http handler, reason being panic / recover happen per goroutine, and there's no generic catch all setup.&lt;/p&gt;

&lt;p&gt;Because of that, even though you could make something it will be a pain in the ass to implement since you need to manually wrap each goroutine with the custom panic handler and it won't catch panics in goroutines created by third-party packages or the Go standard library.&lt;/p&gt;

&lt;p&gt;But Alex, why didn't you just use &lt;a href="https://github.com/maruel/panicparse"&gt;panicparse&lt;/a&gt; ?&lt;br&gt;
Answer: I did, but I wanted to understand why panicparse pipes the Go stacktrace to panicparse, and it's not implemented as an SDK.&lt;/p&gt;
&lt;h2&gt;
  
  
  Perfect solution?
&lt;/h2&gt;

&lt;p&gt;Generally in life, there are no perfect solutions, just perfect compromises :) &lt;/p&gt;

&lt;p&gt;At the end of all, my solution for having live reload and nice panics, that I can click in vscode to link to the file that caused the problem, was to use the following setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.20-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;api&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; bash
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; coreutils

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /go/src/app&lt;/span&gt;

&lt;span class="c"&gt;# Install Air and panicparse&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/cosmtrek/air@latest
&lt;span class="k"&gt;RUN &lt;/span&gt;go &lt;span class="nb"&gt;install &lt;/span&gt;github.com/maruel/panicparse/v2@latest

&lt;span class="c"&gt;# Copy Go modules and dependencies to image&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; go.mod ./&lt;/span&gt;

&lt;span class="c"&gt;# Download Go modules and dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go mod download

&lt;span class="c"&gt;# Copy directory files&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . ./&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/bin/bash", "scripts/dev.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And have the following startup script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GOTRACEBACK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;all

&lt;span class="nb"&gt;stdbuf&lt;/span&gt; &lt;span class="nt"&gt;-oL&lt;/span&gt; air &lt;span class="nt"&gt;-c&lt;/span&gt; .air.toml 2&amp;gt;&amp;amp;1 | &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;stdbuf&lt;/span&gt; &lt;span class="nt"&gt;-oL&lt;/span&gt; panicparse &lt;span class="nt"&gt;-force-color&lt;/span&gt; &lt;span class="nt"&gt;-rel-path&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;stdbuf&lt;/span&gt; &lt;span class="nt"&gt;-oL&lt;/span&gt; &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/\(app\/[^ ]*\)/\1    /g'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;stdbuf&lt;/span&gt; &lt;span class="nt"&gt;-oL&lt;/span&gt; &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/\(app\/\)//g'&lt;/span&gt;              
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the reason on why I used &lt;a href="https://github.com/cosmtrek/air"&gt;cosmtrek/air&lt;/a&gt;, and not &lt;a href="https://github.com/githubnemo/CompileDaemon"&gt;CompileDaemon&lt;/a&gt;, was pretty easy, but at the same time pretty dumb, I couldn't make CompileDaemon send the correct SIGTERM signal to my app in order to gracefully stop the net/http server.&lt;/p&gt;

&lt;p&gt;Sed is there purely for making the links clickable in vscode, since otherwise panicparse keeps app/ at the start of the path even if it's in &lt;code&gt;-rep-path&lt;/code&gt; mode.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You do need to use stdbuf -oL since otherwise sed does block buffered, not line buffered, and docker's default log output doesn't like it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This brings us from the generic panic handler:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hmdi39jb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/230qt4xsjp3q2kdzm4yi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hmdi39jb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/230qt4xsjp3q2kdzm4yi.png" alt="Golang Default Panic" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To this output panic parse output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VIsBmGqV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ikc5lstem87von9csdwe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VIsBmGqV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ikc5lstem87von9csdwe.png" alt="Golang Panic Parse" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>livereload</category>
      <category>debugging</category>
    </item>
    <item>
      <title>50 Shades of Gray - Are Standups Good or Not</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Sun, 03 Oct 2021 14:29:46 +0000</pubDate>
      <link>https://dev.to/coolgoose/50-shades-of-gray-are-standups-good-or-not-i8k</link>
      <guid>https://dev.to/coolgoose/50-shades-of-gray-are-standups-good-or-not-i8k</guid>
      <description>&lt;p&gt;I’ve noticed that a few articles are arguing about how useful standups are or aren’t on a day-by-day basis, making it a white or black decision. But the situation is a bit more complicated than that.&lt;/p&gt;

&lt;p&gt;To make it clear, I &lt;strong&gt;100% agree&lt;/strong&gt; that if your standup is a quick recap of &lt;em&gt;Alex is working on feature X&lt;/em&gt; and &lt;em&gt;Bob the sailor man&lt;/em&gt; is working on feature Y, tasks that are in your task management system then it brings &lt;strong&gt;zero value&lt;/strong&gt; to the table.&lt;/p&gt;

&lt;p&gt;But it doesn’t need to be that way and I’ll try being the devil’s advocate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don’t need to do standups if your team/squad/cell/happy family is all spread across the world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It should be possible to better isolate projects and have smaller 3–5-man team in each time zone (+/- 2 hours)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check a standup’s team composition, you might not need your managers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Call them Morning Sunshine Chat, or Brainfart Session, or whatever name you want.&lt;br&gt;
  Why might you ask? Because it’s good to have engineers staying together for a few minutes, rant off about what they’re bothered about and increase the team cohesion. This might sound like a cliche (and it is) but for me, so far interaction with my fellow peers is high on my list of nice things to have.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It might trigger some unexpected domain knowledge sessions:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it this way, you might have a perfectly documented system with 100% test coverage and CI/CD, with updated 3’rd party components that magically don’t break anything, or you might admit you had a nice dream and wake up.&lt;/p&gt;

&lt;p&gt;The reason is that the bigger the project, and the varied the feature set, there just might be things that fell between the cracks. That’s normal, there’s no magical fix-it button for a system.&lt;/p&gt;

&lt;p&gt;A quick chat about an engineer’s issues with a task in your sprint/Kanban board/email list/cookie template might just remind somebody else in your team that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They worked on something similar before in the project&lt;/li&gt;
&lt;li&gt;They worked on something similar before in another company&lt;/li&gt;
&lt;li&gt;They might want to pair up or offer to pair up. The reason is since they know this is a convoluted piece of code in which 100% test coverage means nothing since you could introduce new exceptions that might or might not be covered by tests.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>management</category>
      <category>organisation</category>
    </item>
    <item>
      <title>Golang Datetime Cheatsheet from strftime*</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Sun, 25 Jul 2021 11:31:31 +0000</pubDate>
      <link>https://dev.to/coolgoose/golang-datetime-cheatsheet-from-strftime-3j5</link>
      <guid>https://dev.to/coolgoose/golang-datetime-cheatsheet-from-strftime-3j5</guid>
      <description>&lt;p&gt;When I initially started working with Go the &lt;a href="https://pkg.go.dev/time#Parse"&gt;time format &lt;/a&gt; it seemed a bit clunky.&lt;/p&gt;

&lt;p&gt;Maybe it's because it's a departure from the normal &lt;code&gt;strftime&lt;/code&gt;, but also maybe it's also because there's no simple cheatsheet for the various date formatting options like you would see for example in the &lt;a href="https://www.php.net/manual/en/datetime.format.php"&gt;PHP documentation&lt;/a&gt; or in the &lt;a href="https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes"&gt;Python documentation&lt;/a&gt; or to use the fancy language of the day, the &lt;a href="https://docs.rs/chrono/0.4.19/chrono/format/strftime/index.html#specifiers"&gt;Rust Chrono crate documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The alternative is to read the source code, specifically the &lt;a href="https://cs.opensource.google/go/go/+/refs/tags/go1.16.6:src/time/format.go;l=92"&gt;private constants&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That being said, here is a simple cheatsheet between the golang time format and php datetime format to make it easier to switch.&lt;br&gt;
No two &lt;code&gt;strftime&lt;/code&gt; implementations are identical on what they support across various languages (especially if you look at 0 prefixed minutes or seconds), but most of the basic things like &lt;code&gt;Y&lt;/code&gt; for full year are present.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;code&gt;golang&lt;/code&gt; character&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;php&lt;/code&gt; character&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example returned values&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Day&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Day&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Day of the month, 2 digits with leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;01&lt;/code&gt; to &lt;code&gt;31&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Mon&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;D&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A textual representation of a day, three letters&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Mon&lt;/code&gt; through &lt;code&gt;Sun&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;j&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Day of the month without leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt; to &lt;code&gt;31&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Monday&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;l&lt;/code&gt; (lowercase 'L')&lt;/td&gt;
&lt;td&gt;A full textual representation of the day of the week&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Sunday&lt;/code&gt; through &lt;code&gt;Saturday&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Month&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Month&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;January&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;F&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A full textual representation of a month, such as January or March&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;January&lt;/code&gt; through &lt;code&gt;December&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Numeric representation of a month, with leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;01&lt;/code&gt; through &lt;code&gt;12&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Jan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;M&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A short textual representation of a month, three letters&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Jan&lt;/code&gt; through &lt;code&gt;Dec&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Numeric representation of a month, without leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt; through &lt;code&gt;12&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Year&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Year&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2006&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A full numeric representation of a year, 4 digits&lt;/td&gt;
&lt;td&gt;Examples: &lt;code&gt;1999&lt;/code&gt; or &lt;code&gt;2003&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;06&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A two digit representation of a year&lt;/td&gt;
&lt;td&gt;Examples: &lt;code&gt;99&lt;/code&gt; or &lt;code&gt;03&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Time&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Time&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lowercase Ante meridiem and Post meridiem&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;am&lt;/code&gt; or &lt;code&gt;pm&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Uppercase Ante meridiem and Post meridiem&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;AM&lt;/code&gt; or &lt;code&gt;PM&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;g&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12-hour format of an hour without leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1&lt;/code&gt; through &lt;code&gt;12&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;15&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;G&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;24-hour format of an hour without leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0&lt;/code&gt; through &lt;code&gt;23&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;03&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;h&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12-hour format of an hour with leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;01&lt;/code&gt; through &lt;code&gt;12&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;N/A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;H&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;24-hour format of an hour with leading zeros - not possible in Golang&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;00&lt;/code&gt; through &lt;code&gt;23&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;i&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minutes with leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;00&lt;/code&gt; to &lt;code&gt;59&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;04&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;N/A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minutes without leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0&lt;/code&gt; to &lt;code&gt;59&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Seconds with leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;00&lt;/code&gt; through &lt;code&gt;59&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;05&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;N/A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Seconds without leading zeros&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;00&lt;/code&gt; through &lt;code&gt;59&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Timezone&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Timezone&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Timezone identifier&lt;/td&gt;
&lt;td&gt;Examples: &lt;code&gt;UTC&lt;/code&gt;, &lt;code&gt;GMT&lt;/code&gt;, &lt;code&gt;Atlantic/Azores&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-0700&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;O&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Difference to Greenwich time (GMT) without colon between hours and minutes&lt;/td&gt;
&lt;td&gt;Example: &lt;code&gt;+0200&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Z07:00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Difference to Greenwich time (GMT) with colon between hours and minutes&lt;/td&gt;
&lt;td&gt;Example: &lt;code&gt;+02:00&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;T&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Timezone abbreviation&lt;/td&gt;
&lt;td&gt;Examples: &lt;code&gt;EST&lt;/code&gt;, &lt;code&gt;MDT&lt;/code&gt; ...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-070000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Timezone offset in seconds. The offset for timezones west of UTC is always negative, and for those east of UTC is always positive.&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-43200&lt;/code&gt; through &lt;code&gt;50400&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>go</category>
      <category>beginners</category>
      <category>datetime</category>
    </item>
    <item>
      <title>How to read metadata easily in powershell with TagLibSharp</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Sun, 21 Mar 2021 11:56:24 +0000</pubDate>
      <link>https://dev.to/coolgoose/how-to-read-metadata-easily-in-powershell-with-taglibsharp-1896</link>
      <guid>https://dev.to/coolgoose/how-to-read-metadata-easily-in-powershell-with-taglibsharp-1896</guid>
      <description>&lt;p&gt;Doing my quarterly phone image cleanup and backup on onedrive I noticed that &lt;a href="https://gist.github.com/CoolGoose/75462ff5cfd6355153f4526746e09e2b/revisions#diff-e162f571070996842f69bb345df3949ac5e415fad0aca772bc18d59efdef3e2d"&gt;the script&lt;/a&gt; I was using wasn't quite consistent on the folder year and month generation.&lt;/p&gt;

&lt;p&gt;If you think of it it does make sense, since it's basically doing a smart workaround on using &lt;code&gt;LastWriteTime&lt;/code&gt; for its date source, but that isn't always good enough.&lt;/p&gt;

&lt;p&gt;After some hours googling around (not yet on a 'binge' :D) I got two options that looked great.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reading the &lt;strong&gt;Date Taken&lt;/strong&gt; from the file using &lt;code&gt;ComObject&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Reading it using &lt;strong&gt;&lt;a href="https://github.com/mono/taglib-sharp"&gt;TagLibSharp&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Reading the &lt;strong&gt;Date Taken&lt;/strong&gt; from the file using &lt;em&gt;ComObject&lt;/em&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;$shellObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;New-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ComObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Shell.Application&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;$directoryObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$shellObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Directory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;$fileObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$directoryObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ParseName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Date taken'&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="kr"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$index&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$directoryObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetDetailsOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$directoryObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-ne&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$property&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$index&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nv"&gt;$dateString&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$directoryObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetDetailsOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fileObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem for me was that I couldn't parse that date string to an actual DateTime object no matter what I tried (&lt;code&gt;[datetime]::Parse&lt;/code&gt; / &lt;code&gt;[datetime]::ParseExact&lt;/code&gt; with various formatting, even if &lt;code&gt;g&lt;/code&gt; should have been a match, various cultures etc (including just sending &lt;code&gt;$null&lt;/code&gt;)).&lt;/p&gt;

&lt;p&gt;If anyone has any ideas on how to fix this I'm really curious.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading it using &lt;em&gt;[TagLibSharp]&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;The tricky part for me here was understanding how to load a c# dll in powershell.&lt;br&gt;
If you install the package using &lt;em&gt;nuget&lt;/em&gt; the easiest way to figure out where the package is installed is to run &lt;code&gt;Get-Package TagLibSharp | Format-List -Property Source&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Your output should be similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ Get-Package TagLibSharp | Format-List -Property Source

Source : C:\Program Files\PackageManagement\NuGet\Packages\TagLibSharp.2.2.0\TagLibSharp.2.2.0.nupkg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we know that we can use the following code to load the dll in our powershell script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;$TagLib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\Program Files\PackageManagement\NuGet\Packages\TagLibSharp.2.2.0\lib\netstandard2.0\TagLibSharp.dll"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Add-Type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TagLib&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System.Reflection.Assembly&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;LoadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$TagLib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reading part is really easy, and for images the property you want to look for is &lt;code&gt;ImageTag&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;TagLib.File&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ImageTag&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few nice things to gain once using TagLibSharp.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ImageTag&lt;/code&gt; has a &lt;code&gt;DateTime&lt;/code&gt; object directly available.&lt;/li&gt;
&lt;li&gt;You have full access to the image metadata so you could for eg create folders automatically based on the latitude and longitude with the closest city name. In case this sounds interesting please let me know and I'll try doing an updated version that does just that.&lt;/li&gt;
&lt;li&gt;We can implement a fallback to the simple &lt;code&gt;Tag&lt;/code&gt; for videos for eg.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Full version can be found below and in the &lt;a href="https://gist.github.com/CoolGoose/75462ff5cfd6355153f4526746e09e2b"&gt;gist&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;$TagLib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\Program Files\PackageManagement\NuGet\Packages\TagLibSharp.2.2.0\lib\netstandard2.0\TagLibSharp.dll"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Add-Type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TagLib&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System.Reflection.Assembly&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;LoadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$TagLib&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# Get the files which should be moved, without folders&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-ChildItem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'X:\OneDrive\Pictures'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Recurse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PSIsContainer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# List Files which will be moved&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# Target Filder where files should be moved to. The script will automatically create a folder for the year and month.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$targetPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'X:\OneDrive\Photos'&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;TagLib.File&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="c"&gt;# Get year and Month of the file&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ImageTag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nv"&gt;$year&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ImageTag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Year&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="c"&gt;# add 0 prefix to month&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nv"&gt;$month&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ImageTag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Month&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"00"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="kr"&gt;elseif&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nv"&gt;$year&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Year&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="c"&gt;# add 0 prefix to month&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nv"&gt;$month&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Month&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"00"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="kr"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="c"&gt;# I used LastWriteTime since this are synced files and the creation day will be the date when it was synced&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nv"&gt;$year&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LastWriteTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Year&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="c"&gt;# add 0 prefix to month&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nv"&gt;$month&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LastWriteTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Month&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"00"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="c"&gt;# Out FileName, year and month&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nv"&gt;$year&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nv"&gt;$month&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="c"&gt;# Set Directory Path , change as wanted&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nv"&gt;$Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$targetPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$year&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$year&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$month&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="c"&gt;# Create directory if it doesn't exists&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Directory&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="c"&gt;# Move File to new location, remove -Force if you might have files with the same name, i've used it since i knew that duplicates are ok to overwrite&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Move-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Destination&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>beginners</category>
      <category>powershell</category>
    </item>
    <item>
      <title>Why developers should be "lazy"</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Mon, 30 Nov 2020 22:32:36 +0000</pubDate>
      <link>https://dev.to/coolgoose/why-developers-should-be-lazy-4010</link>
      <guid>https://dev.to/coolgoose/why-developers-should-be-lazy-4010</guid>
      <description>&lt;p&gt;Looking back to all the years I've been developing and all the developers I worked with, the best developers were always the "lazy" ones.&lt;/p&gt;

&lt;p&gt;What do you mean by "lazy" you might ask, or why do I think that "lazy" developers are great?  &lt;/p&gt;

&lt;p&gt;It's rather simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A "lazy" developer is going to write less code to get the job done.
Since he wants to have things working, not tinker with overcomplicated abstractions or feel the need ro fill lines of code to justify work.&lt;/li&gt;
&lt;li&gt;A "lazy" developer is going to have more readable code.
Since he knows that 80% of the time you're reading code, not writing it.&lt;/li&gt;
&lt;li&gt;A "lazy" developer doesn't want to do support or extra work.
So that's why he's extra careful in testing and writing tests so he can have minimal downtime.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's pretty much it :)&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tips</category>
      <category>management</category>
    </item>
    <item>
      <title>Simple JSON:API plugin for Nuxt.js</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Sun, 11 Aug 2019 17:41:18 +0000</pubDate>
      <link>https://dev.to/coolgoose/simple-json-api-plugin-for-nuxt-js-3p04</link>
      <guid>https://dev.to/coolgoose/simple-json-api-plugin-for-nuxt-js-3p04</guid>
      <description>&lt;p&gt;Hi all,&lt;/p&gt;

&lt;p&gt;So far I am keeping myself on track to work a bit every weekend on my side projects.&lt;/p&gt;

&lt;p&gt;That being said, I am a big fan on JSON:API and in my search for streamlining the consumption on the front-end I've finally settled on a nifty JSON:API client called &lt;a href="https://github.com/twg/devour"&gt;Devour&lt;/a&gt;. It has the right amount of magic to make it worthwile and not be over the top 'magical'.&lt;/p&gt;

&lt;p&gt;For that, I've made a small nuxt.js plugin that allows me to use it regardless if it's in a component or in the vuex store.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;JsonApi&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;devour-client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;apis&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;~/api/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// eslint-disable-next-line no-undef&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsonApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;JsonApi&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apis&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;jsonApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;apis&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;modelName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;apis&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apis&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// eslint-disable-next-line no-undef&lt;/span&gt;
    &lt;span class="nx"&gt;apiMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;apis&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;jsonApi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;apiMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsonApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonApi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Inject into the nuxt/vue context&lt;/span&gt;
  &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;apiMap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;apiMap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;CONFIG&lt;/code&gt; constant is generated by the following library &lt;a href="https://www.npmjs.com/package/config"&gt;config&lt;/a&gt; and &lt;a href="https://github.com/lorenwest/node-config/wiki/Webpack-Usage#option-1"&gt;injected&lt;/a&gt; into the app for easy access.&lt;/p&gt;

&lt;p&gt;To use the plugin, &lt;code&gt;index.js&lt;/code&gt; is a generic export for the various API &lt;em&gt;models&lt;/em&gt; that we're going to use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;InventoryItem&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./InventoryItem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;model&lt;/em&gt; is nothing more than a simple object that returns the required configuration for the api and exposes it after trough its own methods.&lt;/p&gt;

&lt;p&gt;I'd rather not tightly couple the app to Devour, so keeping them into our own classes should make it easier to swap it out going forward, and/or just use axios directly if needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;InventoryItem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inventory-item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;getInventoryItems&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;InventoryItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;modelName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am curious on knowing how you guys are separating your API calls in your own SPA apps &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>vue</category>
      <category>nuxt</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Sideprojects Motivations and Goals</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Sun, 04 Aug 2019 19:08:17 +0000</pubDate>
      <link>https://dev.to/coolgoose/sideprojects-motivations-and-goals-54od</link>
      <guid>https://dev.to/coolgoose/sideprojects-motivations-and-goals-54od</guid>
      <description>&lt;p&gt;Hi Everyone,&lt;/p&gt;

&lt;p&gt;This is more of an introspective blog post regarding side-projects and finding the motivation and time to do other 'work' outside of the daily job.&lt;/p&gt;

&lt;p&gt;As you may or may not notice, I had a solid 6+ months pause from blogging.&lt;/p&gt;

&lt;p&gt;The main issue here was the fact that I have the tendency at times in my side projects to search for the best solution, and not focus on the task at hand. Hence, this caused a lack of progress, that well, reduced the 'rewards' so the motivation all but vanished.&lt;/p&gt;

&lt;p&gt;Since I recently re-started working on some side projects, there are a few things that I noted down that at least in my case helped to keep myself motivated.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If you are starting a new project, allocate time to define what a minimal viable product means for you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My mistake here was that I was thinking initially that the project I want to work on will cover a broad range of features.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Allocate at least 30 minutes of uninterrupted time to work on your project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't keep reddit, youtube, ycombinator or any other sites open while you work on your project since at least for me, I am tempted to do a refresh and read new things. That, in turn, makes the limited available time for the side project to get that much smaller.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Don't chase magical solutions that cover all cases, but work on your product and do clean up as you advance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You will be tempted to work on the 'best' solution since you're not at your daily job and be strongly against cutting corners. But the issue here is that without real deadlines you will not progress and the project world, in general, is full of imperfect solutions that get their job done.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you choose a technology that takes you out of your comfort zone, have a good reason to do it or just stick to your best technology.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When I initially started on the project, my main motivation was working more with C# . At some point I was asking myself if this isn't something that just keeps me back on being more productive than just writing the backend in something I'm more comfortable with (mainly PHP, Python or Javascript), but at the end of the day it's more important for me to get out of my comfort zone.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hopefully, this will ring a bell and help somebody else go over their impasse and continue to have fun and progress when working with new things or doing side projects.&lt;/p&gt;

</description>
      <category>coding</category>
      <category>career</category>
      <category>beginners</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>How to Stop requestAnimationFrame in Vuejs / Javascript</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Sat, 20 Jul 2019 13:10:10 +0000</pubDate>
      <link>https://dev.to/coolgoose/how-to-stop-requestanimationframe-in-vuejs-javascript-5f75</link>
      <guid>https://dev.to/coolgoose/how-to-stop-requestanimationframe-in-vuejs-javascript-5f75</guid>
      <description>&lt;p&gt;TLDR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fancyFunctionHere&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cancelAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now for the longer version. Technically in Vue.js you might have components/mixins that use window.requestAnimationFrame. Since the &lt;code&gt;fancyFunctionHere&lt;/code&gt; is used as a callback, everytime you call &lt;code&gt;window.requestAnimationFrame&lt;/code&gt; you are going to get a new id that you should use on the &lt;code&gt;destroy&lt;/code&gt; method to stop it.&lt;/p&gt;

&lt;p&gt;Unfortunately this is not imediately clear on &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame"&gt;MDN&lt;/a&gt; so hopefully my documentation edit with the comment in the code example goes trough.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fancyFunctionHere&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="nx"&gt;destroyed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cancelAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nl"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;fancyFunctionHere&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>vue</category>
    </item>
    <item>
      <title>Systemctl shows service file Not Found even though .service file is present</title>
      <dc:creator>Alexandru Bucur</dc:creator>
      <pubDate>Mon, 17 Jun 2019 09:05:14 +0000</pubDate>
      <link>https://dev.to/coolgoose/systemctl-shows-service-file-not-found-even-though-service-file-is-present-29jj</link>
      <guid>https://dev.to/coolgoose/systemctl-shows-service-file-not-found-even-though-service-file-is-present-29jj</guid>
      <description>&lt;p&gt;Hi All,&lt;/p&gt;

&lt;p&gt;I'm writing a step by step setup for a self hosted gitea instance (on CentOS 7) and hit the stupidest &lt;strong&gt;bug&lt;/strong&gt; (if you can call it that) of systemd.&lt;br&gt;
After writing the gitea service file I was getting the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;root@gitea ~]# systemctl start giteaselfhost
Failed to start giteaselfhost.service: Unit not found.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a few hours of maddening permission checks and debugging, the problem was that I had a &lt;code&gt;Requires&lt;/code&gt; dependency to a &lt;a href="https://serverfault.com/a/968233/89407"&gt;service file that wasn't there&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Removing the broken dependency made the service work, so hopefully at some point systemd will give nicer errors when missing dependencies.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>systemd</category>
      <category>centos</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
