<?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: Igor Santos</title>
    <description>The latest articles on DEV Community by Igor Santos (@igorsantos07).</description>
    <link>https://dev.to/igorsantos07</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%2F17255%2Fe8019ff6-bced-4fd8-8894-f7e9e0904f30.jpg</url>
      <title>DEV Community: Igor Santos</title>
      <link>https://dev.to/igorsantos07</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/igorsantos07"/>
    <language>en</language>
    <item>
      <title>Keyboard shortcuts to raise specific windows</title>
      <dc:creator>Igor Santos</dc:creator>
      <pubDate>Sun, 22 Jun 2025 17:40:28 +0000</pubDate>
      <link>https://dev.to/igorsantos07/keyboard-shortcuts-to-raise-specific-windows-41j3</link>
      <guid>https://dev.to/igorsantos07/keyboard-shortcuts-to-raise-specific-windows-41j3</guid>
      <description>&lt;p&gt;As soon as I got a Keychron K10 Pro, I started to wonder what to do with those extra 4 keys on the corner.&lt;/p&gt;

&lt;p&gt;First, of course, I needed some cooler keycaps than square/circle/triangle/cross. So I got a couple from AliExpress - Pokémon not only because yes but also because cooler keycaps were waaaay too expensive (RIP One Piece).&lt;/p&gt;

&lt;p&gt;Then, I had to do &lt;em&gt;something&lt;/em&gt; with those damn keycaps.&lt;br&gt;
For years and years, I already had a tiny script that only allowed me to open a single instance of &lt;a href="https://heldercorreia.bitbucket.io/speedcrunch/" rel="noopener noreferrer"&gt;SpeedCrunch&lt;/a&gt; (a simpler but smarter calculator, with no keyboard because I always used full keyboards lol). If the calculator was already opened &lt;em&gt;somewhere&lt;/em&gt;, the script would raise the window instead.&lt;/p&gt;

&lt;p&gt;Over the last year or so, that script suffered multiple iterations, until the current &lt;code&gt;siwm&lt;/code&gt; version, which is PHP-based and uses &lt;code&gt;wmctrl&lt;/code&gt; and &lt;code&gt;xprop&lt;/code&gt; to play around with the windows.&lt;/p&gt;

&lt;p&gt;Right now, my keyboard can directly focus all the routine apps I use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bulbasaur opens Home Assistant and Spotify;&lt;/li&gt;
&lt;li&gt;Pikachu opens Slack and PHPStorm;&lt;/li&gt;
&lt;li&gt;Squirtle opens my time-tracking apps;&lt;/li&gt;
&lt;li&gt;Charmander opens WhatsApp and Telegram.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this is useful for more people! It's not public on GitHub because it's inside my private dotfiles repo 🙃&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;#!/usr/bin/env php
&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nb"&gt;array_shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$argv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//script name&lt;/span&gt;
&lt;span class="nv"&gt;$search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$argv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;has_arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&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="nb"&gt;in_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"--&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$GLOBALS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'argv'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;preg_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/(?&amp;lt;!-)-[a-z]*&lt;/span&gt;&lt;span class="nv"&gt;$arg[0]&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$GLOBALS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'argv'&lt;/span&gt;&lt;span class="p"&gt;])));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$msg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[DEBUG] &lt;/span&gt;&lt;span class="nv"&gt;$msg&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DEBUG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;has_arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'debug'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$search&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$search&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'-'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;has_arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'help'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="sh"&gt;&amp;lt;&amp;lt;&amp;lt;HELP
    Usage: siwm &amp;lt;search&amp;gt; [executable] [-hdc]
    Args:
        search    : what you're searching for (window title, or class together with --class)
        executable: what to run if nothing is found - if this is not given, it tries to execute the search string
    Options:
        -h/--help : show this and quit 🙃
        -d/--debug: show extra debug info
        -c/--class: search by window classes instead of titles

    HELP;&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;exit&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="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;has_arg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$wmctrlSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'wmctrl -x'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Searching by class: &lt;/span&gt;&lt;span class="nv"&gt;$search&lt;/span&gt;&lt;span class="s2"&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$wmctrlSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'wmctrl'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Searching through window titles: &lt;/span&gt;&lt;span class="nv"&gt;$search&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;preg_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/([\[\]])/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'\\\$1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$search&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$searchCmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$wmctrlSearch&lt;/span&gt;&lt;span class="s2"&gt; -l | grep -iw -m1 &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$search&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"$&amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;$searchCmd&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$isOpen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shell_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$searchCmd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$isOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$wmctrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'wmctrl -i'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//selects the window by its ID, which is more reliable&lt;/span&gt;
    &lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Window found: "'&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$isOpen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$isOpen&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Raising window &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;shell_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"xprop -id &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;id"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'STICKY'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[DEBUG] Hmmmm, it's sticky! Let's do it differently.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;shell_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$wmctrl&lt;/span&gt;&lt;span class="s2"&gt; -R &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;; &lt;/span&gt;&lt;span class="nv"&gt;$wmctrl&lt;/span&gt;&lt;span class="s2"&gt; -r &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt; -b add,sticky"&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="nb"&gt;shell_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$wmctrl&lt;/span&gt;&lt;span class="s2"&gt; -a &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No window found matching '&lt;/span&gt;&lt;span class="nv"&gt;$search&lt;/span&gt;&lt;span class="s2"&gt;' 🤨 &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$argv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;str_starts_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$search&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;shell_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"which &lt;/span&gt;&lt;span class="nv"&gt;$search&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$search&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="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Also, nothing to execute related to that. Try [...]&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;//https://stackoverflow.com/a/11921855/102960&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Running `&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="s2"&gt;`...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;pcntl_fork&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;shell_exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$app&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>keyboard</category>
      <category>shortcuts</category>
      <category>windowmanagement</category>
      <category>linux</category>
    </item>
    <item>
      <title>Quick tip: Sharing JetBrains code style throughout the repository</title>
      <dc:creator>Igor Santos</dc:creator>
      <pubDate>Thu, 15 Nov 2018 01:46:32 +0000</pubDate>
      <link>https://dev.to/igorsantos07/quick-tip-sharing-jetbrains-code-style-throughout-the-repository-5eme</link>
      <guid>https://dev.to/igorsantos07/quick-tip-sharing-jetbrains-code-style-throughout-the-repository-5eme</guid>
      <description>

&lt;p&gt;This is a quick one. There's &lt;a href="https://intellij-support.jetbrains.com/hc/en-us/articles/206544839"&gt;an article from JetBrains explaining how to properly include the &lt;code&gt;.idea&lt;/code&gt; folder in the project's repository&lt;/a&gt;. However, I was never able to understand how to include the Code Style there. On three different projects, we ended up sharing the Code Style export through Slack... lol&lt;/p&gt;

&lt;p&gt;However, if you simply copy the style from the IDE into the Project itself, it will start showing properly on the &lt;code&gt;.idea&lt;/code&gt; folder. The problem is that this option is not really obvious, and there's little clue on why this single setting is not included on the said folder, while other parts of the project settings are clearly marked as "shared/project exclusive".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r5iO1IOG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/toolzap5m4b2ktakd961.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r5iO1IOG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/toolzap5m4b2ktakd961.png" alt="Copy style into JetBrains project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This has been tested on PHPStorm, but I'm pretty sure it will work on PyCharm, IntelliJ, WebStorm or whatever else flavor of a JetBrains IDE you use!&lt;/p&gt;

&lt;p&gt;Have fun coding.&lt;/p&gt;


</description>
      <category>phpstorm</category>
      <category>jetbrains</category>
      <category>codestyle</category>
      <category>repository</category>
    </item>
    <item>
      <title>My preferred merge strategy for Pull Requests</title>
      <dc:creator>Igor Santos</dc:creator>
      <pubDate>Fri, 03 Aug 2018 07:42:47 +0000</pubDate>
      <link>https://dev.to/igorsantos07/my-preferred-merge-strategy-for-pull-requests-1lo5</link>
      <guid>https://dev.to/igorsantos07/my-preferred-merge-strategy-for-pull-requests-1lo5</guid>
      <description>&lt;p&gt;In every decent team project I've worked before (that had PRs in place), the merge strategy was to squash all commits into a single one, to be done into the master branch.&lt;/p&gt;

&lt;p&gt;In the beginning, it felt odd, as "all my hard work and organized commits" would become a single, standardized blob of sorts. Then I got used to the flow and, well, whatever, right? &lt;em&gt;It works®&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But then it came the time it was &lt;strong&gt;me&lt;/strong&gt; who was deciding the path a team would start to walk through. And the question came, why squash merges? Why rebases?&lt;/p&gt;

&lt;p&gt;As people say, &lt;em&gt;first you resist, then you accept, and then you question what was happening&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhelp.github.com%2Fassets%2Fimages%2Fhelp%2Fpull_requests%2Fcommit-squashing-diagram.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhelp.github.com%2Fassets%2Fimages%2Fhelp%2Fpull_requests%2Fcommit-squashing-diagram.png" alt="Squash diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, to help with understanding why I chose Squash Merge to be the default for our repository:&lt;/p&gt;

&lt;p&gt;Squash merges are usually preferred not only because of the "flat history" (that is usually easier to navigate with any tooling), but actually, because the history gets much cleaner and "straight to the point", without all the partial commits that are common during development.&lt;br&gt;
If the squash is done correctly, you'll still maintain all commits' text in the squashed commit, so you can still get some details about the development of that feature, without clogging your &lt;code&gt;master&lt;/code&gt; history.&lt;/p&gt;

&lt;p&gt;One should also remember history is not only used to see code progress on a timeline/tree, but also for &lt;em&gt;blaming changes&lt;/em&gt;. Even though you can use tools or extra options to "ignore" partial commits, blame probably won't - or will get too convoluted, at least.&lt;/p&gt;

&lt;p&gt;I did some quick research to see discussions on the subject, and I can link you to two references that show my opinion and that I used to enhance my arguments above:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/reenhanced/gitreflow/issues/52#issuecomment-28437323" rel="noopener noreferrer"&gt;Answer about squash preference, on a CLI tool for Git Workflow&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;[...] And over time, that's all we really care about in the history. Who made this change and why was it made. Squash merging allows us to do that while still giving all of our developers the individual freedom to develop in the way that suits them best.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://help.github.com/articles/about-pull-request-merges/" rel="noopener noreferrer"&gt;GitHub manual about PR merge strategies&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;You can use squash and merge to create a more streamlined Git history in your repository. Work-in-progress commits are helpful when working on a feature branch, but they aren’t necessarily important to retain in the Git history. If you squash these commits into one commit while merging to the default branch, you can retain the original changes with a clear Git history.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;&lt;a href="https://medium.com/@igorsantos07/my-preferred-merge-strategy-for-pull-requests-6a9db5b0acd5" rel="noopener noreferrer"&gt;(this was also posted to my Medium)&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Best wishes of no-conflict merges!&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>bitbucket</category>
      <category>pullrequest</category>
    </item>
    <item>
      <title>The state of Laravel-based APIs - a personal research</title>
      <dc:creator>Igor Santos</dc:creator>
      <pubDate>Tue, 12 Jun 2018 08:02:33 +0000</pubDate>
      <link>https://dev.to/phprio/the-state-of-laravel-based-apis-4e3</link>
      <guid>https://dev.to/phprio/the-state-of-laravel-based-apis-4e3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Friendly disclaimer:&lt;/strong&gt; this is a quick and dirty post that I'm putting together as I research API resources to build an API for a project I'm working on, so I'm sorry for being so direct and to the point, and also for the number of levels and bullet points :)&lt;br&gt;
It was written in the order of "here only for the sake of completeness" down to "probably what we're going to use".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;GraphQL should be the way to go only if your frontend sort of requires it. Needs a lot of boilerplate and manual sync between your Eloquent models and GraphQL-related code.&lt;/li&gt;
&lt;li&gt;JSON-API is the most respected standard that could face GraphQL, but on Laravel-land it renders you documentation-less. You'll probably have to write separate documentation on API Blueprint or something like that, and it might take you some time as well. You can also discover how to get Blueprint generated through a specific package (that bridges JSON-API with Dingo), but... good luck on that.&lt;/li&gt;
&lt;li&gt;Handwritten RESTful API... Do I need to comment on that? It's handwritten. Certainly not a good option for a medium or big API. &lt;code&gt;EOF&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Prologue: basic API requirements we had
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;should have built-in documentation, that's not dependent on the developer to manually write it (think PHPDocs that magically autocomplete in your IDE)&lt;/li&gt;
&lt;li&gt;it needs to be blazing fast, as it will be used on a speed-sensitive user interface

&lt;ul&gt;
&lt;li&gt;here the features of field-selection from GraphQL or JSON-API come to my mind&lt;/li&gt;
&lt;li&gt;obviously, a simple cache layer might also be helpful&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h1&gt;
  
  
  Research and comparisons
&lt;/h1&gt;

&lt;h2&gt;
  
  
  API type option 1: &lt;a href="https://graphql.org/learn/" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Short conclusion.&lt;/strong&gt; Doesn't seem trivial to be built, as there's a lot of boilerplate to be written that repeats information from Eloquent: GraphQL Types, Queries, and Mutations. That happens on both packages found, and neither of them helps by having a boilerplate-generator.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Helpful Packages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Folkloreatelier/laravel-graphql" rel="noopener noreferrer"&gt;By Folkore Atelier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/rebing/graphql-laravel" rel="noopener noreferrer"&gt;By Rebing&lt;/a&gt;, based on Folklore's&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  API type option 2: RESTful
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Subtype 1: &lt;a href="http://jsonapi.org/" rel="noopener noreferrer"&gt;JSON-API&lt;/a&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Conclusion: also not that trivial to work with, but seems simpler than GraphQL. However, documentation might be a weak point.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Helpful packages
&lt;/h4&gt;

&lt;h5&gt;
  
  
  &lt;a href="https://github.com/nilportugues/laravel5-jsonapi" rel="noopener noreferrer"&gt;Nil's Laravel5-json-api&lt;/a&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Implements &lt;code&gt;include&lt;/code&gt;, &lt;code&gt;fields&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;page&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Almost boilerplate-free with generic controllers

&lt;ul&gt;
&lt;li&gt;However, you still need to &lt;a href="https://github.com/nilportugues/laravel5-jsonapi#step-3-definition" rel="noopener noreferrer"&gt;configure Transformers&lt;/a&gt;, although they don't repeat much information from the Eloquent model&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;No support for documentation generation. At all.&lt;/li&gt;

&lt;/ul&gt;

&lt;h5&gt;
  
  
  &lt;a href="https://github.com/nilportugues/laravel5-jsonapi-dingo" rel="noopener noreferrer"&gt;Laravel5-json-api-dingo&lt;/a&gt;
&lt;/h5&gt;

&lt;h6&gt;
  
  
  Good points
&lt;/h6&gt;

&lt;p&gt;Theoretically, brings together the best of both packages, including Dingo's features (Dingo is discussed later) such as Auth, Versioning, Rate limiting, Docs and Routes into laravel5-json-api (called L5JA from now on).&lt;/p&gt;

&lt;h6&gt;
  
  
  Bad points
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/nilportugues/laravel5-jsonapi-dingo/issues/8" rel="noopener noreferrer"&gt;it's not clear how documentation could be generated&lt;/a&gt;, as Dingo depends on annotations and L5JA is ideally based on a generic controller implementation. There might be other integration issues, as the examples do not clearly define how to bring both packages together, besides a basic routing sample.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nilportugues/laravel5-jsonapi-dingo/issues/7" rel="noopener noreferrer"&gt;support also seems to be lacking behind&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  &lt;a href="http://laravel-json-api.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;cloudcreativity's Laravel-json-api&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;This one has very long documentation; while seems complete, it might take a while to read everything and implement (took me a while reviewing the docs to see what features were available). And there are at least two empty pages, with a simple "todo" note.&lt;/p&gt;

&lt;h6&gt;
  
  
  Good points
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;also sort of boilerplate-free with generic controllers, and basic code generation for the other things (Adapters, Schemas)&lt;/li&gt;
&lt;li&gt;Adapters and Schemas will still need some filling and manual sync with the Eloquent model, though&lt;/li&gt;
&lt;li&gt;Also sports first-class validation rules for the API (which might end up being duplicated on your code, just like Eloquent details....)&lt;/li&gt;
&lt;li&gt;seems to have a decent Auth infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  Bad points
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;no clear mention on the docs about the selection of fields, and missing docs for sorting and "sparse fieldsets" (if that what I called "selection of fields"?) (&lt;a href="https://github.com/cloudcreativity/laravel-json-api/issues/193" rel="noopener noreferrer"&gt;issue on the topic&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://laravel-json-api.readthedocs.io/en/latest/fetching/filtering/#using-filter-parameter" rel="noopener noreferrer"&gt;filtering must be hand-written&lt;/a&gt; as well, there's no automatic API to turn filter parameters into Eloquent queries (much like GraphQL queries are built... sad).&lt;/li&gt;
&lt;li&gt;also, no mention about documentation generation. There's an &lt;a href="https://github.com/cloudcreativity/laravel-json-api/issues/94" rel="noopener noreferrer"&gt;old issue&lt;/a&gt; that states Swagger can't work together with JSON-API, and the main developer doesn't have time to dedicate to that (we all know how open-source is born and dies, right? Free developer time during the lifecycle of a related project...)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Subtype 2: Plain "bring-your-own-standard" JSON API
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Conclusion: the easiest to be built in our case, as we might end up needing only a couple of read-only endpoints. Might need some boilerplate to allow for field selection or advanced querying capabilities, but generates Blueprint documentation files and might even generate HTML docs with other generators.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Helpful Packages
&lt;/h4&gt;

&lt;h5&gt;
  
  
  &lt;a href="https://github.com/dingo/api/wiki" rel="noopener noreferrer"&gt;Dingo&lt;/a&gt;
&lt;/h5&gt;

&lt;h6&gt;
  
  
  Good points
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;complete feature-set: auth, rate limiting helpers, errors, routing, doc generator (through Blueprint files)&lt;/li&gt;
&lt;li&gt;Blueprint files can be used with a number of parsers to, then, generate HTML documentation or similar. Options and related resources are listed at the bottom of this post.&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  Bad points
&lt;/h6&gt;

&lt;p&gt;Well... you'll have to write all your controllers and actions by hand. And define all your filters, if any. And whatnot.&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;a href="https://github.com/Luracast/Restler" rel="noopener noreferrer"&gt;Restler&lt;/a&gt;
&lt;/h5&gt;

&lt;blockquote&gt;
&lt;p&gt;This is actually unrelated to Laravel, but Eloquent can be easily made to work with it, so it's worth mentioning as a companion project to your main Laravel application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h6&gt;
  
  
  Good points
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;complete feature-set, including Swagger documentation based on PHP Doc blocks and method parameters (that are also used for automatic request validation)&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  Bad points
&lt;/h6&gt;

&lt;p&gt;Got abandoned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stopped on PHP 5.4 support, while could have a great usage of PHP 7 first-class types&lt;/li&gt;
&lt;li&gt;stopped on an old version of Swagger, missing some of its features - probably one of the reasons the package got abandoned, as Swagger is sometimes referred as a very complicated beast to deal with.&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  Sample implementation
&lt;/h6&gt;

&lt;p&gt;Once upon a time, I started working on an &lt;a href="https://bitbucket.org/dal-glossary/server/src/master/" rel="noopener noreferrer"&gt;API Server&lt;/a&gt; build with an Eloquent extension (also sort of abandoned) and Restler. It included some base controllers that made CRUD actions only a couple of lines away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other useful resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://apiary.io/" rel="noopener noreferrer"&gt;Apiary&lt;/a&gt; - complete toolset (needs clarification!) to define, document and work on APIs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apimatic.io/transformer" rel="noopener noreferrer"&gt;Apimatic's transformer&lt;/a&gt; - UI and API that can translate to/from almost any doc format. Could be integrated in the API generation pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/apiaryio/dredd" rel="noopener noreferrer"&gt;Dredd&lt;/a&gt; - parses Blueprint/Swagger docs and automatically runs tests to ensure the Backend complies with the defined documentation.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/pixelfusion/blueman" rel="noopener noreferrer"&gt;Blueman&lt;/a&gt; &lt;em&gt;[probably outdated]&lt;/em&gt; - Generates Postman collections based on Blueprint files&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/SMillerDev/phpdraft/" rel="noopener noreferrer"&gt;PHPDraft&lt;/a&gt; - basic HTML generator from Blueprint files&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/M165437/laravel-blueprint-docs" rel="noopener noreferrer"&gt;Laravel Blueprint docs&lt;/a&gt; - generates integrated documentation inside your Laravel project, using its routing, and Blade templates for further customization.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>api</category>
      <category>rest</category>
      <category>graphql</category>
      <category>laravel</category>
    </item>
    <item>
      <title>How to set different defaults for author and committer at git</title>
      <dc:creator>Igor Santos</dc:creator>
      <pubDate>Sat, 21 Apr 2018 03:36:55 +0000</pubDate>
      <link>https://dev.to/igorsantos07/how-to-set-different-defaults-for-author-and-committer-atgit-3dd1</link>
      <guid>https://dev.to/igorsantos07/how-to-set-different-defaults-for-author-and-committer-atgit-3dd1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0yd7rfarc3jbot4ic79w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0yd7rfarc3jbot4ic79w.jpg" alt="Me, looking for a way to set different author and committer on Google: nowhere to be found" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Me, looking for a way to set different author and committer on Google: nowhere to be found. Sad Igor was sad.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wanted to have a default Committer that’s different from my default Author, as I need to differentiate commits made from my local and testing environments.&lt;/p&gt;

&lt;p&gt;This is not as straight-forward as setting name/email at git, as &lt;a href="https://git-scm.com/docs/git-config#git-config-useremail" rel="noopener noreferrer"&gt;there are no separate configuration entries for author and committer&lt;/a&gt;. However, it’s still possible if you &lt;a href="https://git-scm.com/docs/git-commit-tree#_commit_information" rel="noopener noreferrer"&gt;override some environment variables&lt;/a&gt;, as follows: &lt;br&gt;
Example (at your &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.bash_profile&lt;/code&gt;):&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="nv"&gt;GIT_COMMITTER_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;”Deploy server”
&lt;span class="nv"&gt;GIT_COMMITTER_EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;”deploy@server.dev”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;In case you’ve forgotten/don’t know, you can set default name/user for git commits by editing &lt;code&gt;~/.gitconfig&lt;/code&gt; or running commands like these:&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="nv"&gt;$ &lt;/span&gt;git config — global user.name “Igor Santos”
&lt;span class="nv"&gt;$ &lt;/span&gt;git config — global user.email “igor.santos@example.com”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>git</category>
      <category>github</category>
      <category>environments</category>
    </item>
    <item>
      <title>Hi, I'm Igor Santos</title>
      <dc:creator>Igor Santos</dc:creator>
      <pubDate>Sat, 22 Apr 2017 00:04:10 +0000</pubDate>
      <link>https://dev.to/igorsantos07/hi-im-igor-santos</link>
      <guid>https://dev.to/igorsantos07/hi-im-igor-santos</guid>
      <description>&lt;p&gt;I'm a back-end developer fond of front-end interfaces with around 10 years of experience. Most of them with PHP, but some at Rubyland as well and a couple of others dealing with JavaScript.&lt;/p&gt;

&lt;p&gt;You can find me on &lt;a href="https://github.com/igorsantos07" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://twitter.com/igorsantos07" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and most other places as igorsantos07.&lt;/p&gt;

&lt;p&gt;I live in Rio de Janeiro currently, but as &lt;a href="https://www.toptal.com/resume/igor-gomes-dos-santos#obtain-only-eye-opening-coders-now" rel="noopener noreferrer"&gt;a remote developer @ Toptal&lt;/a&gt; sometimes I'm working from all sorts of different places.&lt;/p&gt;

&lt;p&gt;That's me!&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
    <item>
      <title>A (not so) small rant on techniques to copy MySQL database structures</title>
      <dc:creator>Igor Santos</dc:creator>
      <pubDate>Tue, 07 Mar 2017 00:00:00 +0000</pubDate>
      <link>https://dev.to/igorsantos07/a-not-so-small-rant-on-techniques-to-copy-mysql-database-structures</link>
      <guid>https://dev.to/igorsantos07/a-not-so-small-rant-on-techniques-to-copy-mysql-database-structures</guid>
      <description>&lt;p&gt;And here I am, facing a simple task of duplicating the original company’s database into a test db, so we can, uh, run tests.&lt;/p&gt;

&lt;p&gt;Just a matter of &lt;code&gt;mysqldump&lt;/code&gt;’ing it, you would guess.&lt;br&gt;
Some rare folks would even point to &lt;code&gt;CREATE TABLE x2 LIKE x1&lt;/code&gt;. Very clever.&lt;/p&gt;

&lt;p&gt;But MySQL is not here for you. He’s quite a respectable but buggy guy, in the end. I’m writing this small article, to sum up all the resources I found along this adventure, in the hope this could help other adventurers out there.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TL;DR: play around with mysqldump and SSH, or use string sorcery with &lt;code&gt;SHOW CREATE TABLE.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;CREATE TABLE LIKE&lt;/code&gt; doesn’t copy views
&lt;/h2&gt;

&lt;p&gt;This issue is quite simple: you can’t create views with a &lt;code&gt;CREATE TABLE&lt;/code&gt; command, obviously.&lt;br&gt;
And no, there’s no &lt;code&gt;CREATE VIEW x2 LIKE x1&lt;/code&gt;, because a view’s usage is similar to a table’s only in some cases. You have to resort to string sorcery and the output of &lt;code&gt;SHOW CREATE VIEW&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Bonus: should I mention there’s no way to separate tables from views on commands such as &lt;code&gt;SHOW TABLES&lt;/code&gt;?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;CREATE TABLE LIKE&lt;/code&gt; copies everything from the structure, except constraints
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://dev.mysql.com/doc/refman/5.6/en/create-table-like.html" rel="noopener noreferrer"&gt;manual tells you&lt;/a&gt; that you can copy over your table using that command, including column attributes and indexes. But there’s no clear statement saying your &lt;a href="http://stackoverflow.com/questions/3755591/mysql-copy-table-structure-including-foreign-keys" rel="noopener noreferrer"&gt;constraints will go forgotten&lt;/a&gt;.&lt;br&gt;
It also tells you &lt;a href="https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html#idm140024646591168" rel="noopener noreferrer"&gt;foreign keys will be dumped correctly&lt;/a&gt; by &lt;code&gt;mysqldump&lt;/code&gt;, even telling you about the ordering issue that utility has. But why tell you the negative, unsolved issues such as that those constraints are not included in the &lt;code&gt;CREATE TABLE LIKE&lt;/code&gt; copy operation?&lt;/p&gt;

&lt;p&gt;So in those two cases, you got to resort to string sorcery. The usual features MySQL built for that doesn’t work.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;mysqldump&lt;/code&gt; might take forever to run across a network
&lt;/h2&gt;

&lt;p&gt;In some cases we would need to copy the structure from a machine to another, so the best way would simply to give mysqldump the host, user, and password, and ask him for a complete dump that database schema, correct?&lt;/p&gt;

&lt;p&gt;Oh well, if we ssh’d into the server and ran mysqldump it would take, say, 3 secs to dump everything. Downloading that dump over SSH would take the same amount of time.&lt;br&gt;
If done using host/user/password &lt;a href="http://dba.stackexchange.com/questions/165055/mysqldump-takes-forever-to-dump-tables-from-a-remote-server" rel="noopener noreferrer"&gt;it could take almost 3 minutes&lt;/a&gt; (!!!), over the exact same VPN network.&lt;/p&gt;

&lt;p&gt;Thus we had to stuff into our application some SSH credentials. Just for that single operation. DB credentials are not enough for MySQL’s dump protocol.&lt;br&gt;
Go wonder.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;mysqldump&lt;/code&gt; might ignore your foreign key order
&lt;/h2&gt;

&lt;p&gt;Again, as stated in the manual, &lt;a href="https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html#idm140024646591168" rel="noopener noreferrer"&gt;&lt;code&gt;mysqldump&lt;/code&gt; will disable foreign key checks&lt;/a&gt; on your dump so table order can be ignored during importing.&lt;br&gt;
However, that depends on your command line options. If you get naïve and try to speed up things &lt;code&gt;--compact&lt;/code&gt;‘ing your dump, MySQL will &lt;a href="https://dev.mysql.com/doc/refman/5.5/en/mysqldump.html#option_mysqldump_compact" rel="noopener noreferrer"&gt;take your disable command out&lt;/a&gt;; you’ll have to add it by hand — what’s not hard, as you’ll be renaming the original database in the dump anyway…&lt;/p&gt;
&lt;h2&gt;
  
  
  Views on mysqldump or SHOW CREATE VIEW include information related to the original user
&lt;/h2&gt;

&lt;p&gt;One more thing you get to &lt;code&gt;replace()&lt;/code&gt; on your dump: the view’s part will include the algorithm and definer options — the last one, pointing to the user that created it. Unless that user is yourself, you got to replace that or MySQL will ask you for more permissions than you have.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;ALGORITHM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;UNDEFINED&lt;/span&gt; &lt;span class="k"&gt;DEFINER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;`root`&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nv"&gt;`192.168.0.1`&lt;/span&gt; &lt;span class="k"&gt;SQL&lt;/span&gt; &lt;span class="k"&gt;SECURITY&lt;/span&gt; &lt;span class="k"&gt;DEFINER&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="nv"&gt;`mydb`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;`v_cool_view`&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The final solution
&lt;/h2&gt;

&lt;p&gt;To make stuff work both locally and across the network, we had to:&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify if we had a local copy of the original db. If the answer is yes…
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Get CREATE statements for every table and view&lt;/li&gt;
&lt;li&gt;Alter the needed information on those (especially on CREATE VIEW commands)&lt;/li&gt;
&lt;li&gt;Run drops and foreign key checks&lt;/li&gt;
&lt;li&gt;Run each of those create commands&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;As it turns out, playing around with &lt;code&gt;SHOW CREATE&lt;/code&gt; statements took the same amount of time &lt;code&gt;CREATE TABLE LIKE&lt;/code&gt; takes, if not less.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  If we had to connect to an external DB…
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;run mysqldump over ssh into that machine&lt;/li&gt;
&lt;li&gt;Alter dump as needed, especially on view commands&lt;/li&gt;
&lt;li&gt;Add drops and foreign key checks&lt;/li&gt;
&lt;li&gt;Write that into a temporary file, and run it over mysql client
&lt;em&gt;As we had to alter the dump before running it, a simple pipe wouldn’t do; altering it with cat and sed would complicate things way too much, and there was no way to run a bunch of queries at once through our ORM, nor a reliable way to separate each query in the dump file (many were comment-fenced).&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Good luck on your MySQL adventures, sir. Good luck.
&lt;/h3&gt;
&lt;/blockquote&gt;

</description>
      <category>mysql</category>
      <category>sql</category>
      <category>testing</category>
    </item>
    <item>
      <title>Quick tip on Git diffs for PHP files</title>
      <dc:creator>Igor Santos</dc:creator>
      <pubDate>Thu, 15 Sep 2016 23:00:00 +0000</pubDate>
      <link>https://dev.to/phprio/quick-tip-on-git-diffs-for-php-files</link>
      <guid>https://dev.to/phprio/quick-tip-on-git-diffs-for-php-files</guid>
      <description>&lt;p&gt;Every time a PHP developer runs &lt;code&gt;git diff&lt;/code&gt; on the command line a kitten dies:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AyE143yhomWgCeEdzer6Gmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AyE143yhomWgCeEdzer6Gmw.png" title="Badly-hunked PHP diff" alt="Badly-hunked PHP diff" width="394" height="113"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Hell no! This piece of code is inside a method, not the class :(&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those &lt;code&gt;@@&lt;/code&gt; snippets are called Hunk Headers - because every part of a diff is called a hunk, duh. Unfortunately, git is too stupid to figure out PHP files should be diff'd according to PHP syntax, so you need to give it a hand by using a &lt;a href="https://git-scm.com/docs/gitattributes#__code_diff_code" rel="noopener noreferrer"&gt;rule on git attributes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately(2), git attributes are not that easy to configure user-wide as config options are (no &lt;code&gt;git global&lt;/code&gt; commands), thus here's the tip:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create the folder if it doesn't exist: &lt;code&gt;~/.config/git&lt;/code&gt; (or whatever is in &lt;code&gt;$XDG_CONFIG_HOME&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;write in &lt;code&gt;~/.config/git/attributes&lt;/code&gt; this: &lt;code&gt;*.php diff=php&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save and diff away&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;This can also be configured per project by adding the same text inside a &lt;code&gt;.gitattributes&lt;/code&gt; file.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AL5EKHPXHoTbO4j6CY0sxBQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AL5EKHPXHoTbO4j6CY0sxBQ.png" title="Well-hunked PHP diff" alt="Well-hunked PHP diff" width="429" height="114"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;There you have it! A decent Hunk Title on PHP files&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's quite weird why Git doesn't understand out of the box that through the file extension, as there are pre-baked settings to understand several syntaxes (such as TeX, Fortran, HTML, etc). Go figure!&lt;/p&gt;




&lt;h4&gt;
  
  
  References
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/28026767/where-should-i-place-my-global-gitattributes-file" rel="noopener noreferrer"&gt;http://stackoverflow.com/questions/28026767/where-should-i-place-my-global-gitattributes-file&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>php</category>
      <category>codereview</category>
    </item>
    <item>
      <title>Migrating from Less to Sass - really a good idea?</title>
      <dc:creator>Igor Santos</dc:creator>
      <pubDate>Tue, 27 Oct 2015 23:00:00 +0000</pubDate>
      <link>https://dev.to/igorsantos07/migrating-from-less-to-sassreally-a-good-idea</link>
      <guid>https://dev.to/igorsantos07/migrating-from-less-to-sassreally-a-good-idea</guid>
      <description>&lt;p&gt;I started my &lt;a href="http://konato.igorsantos.com.br" rel="noopener noreferrer"&gt;new project&lt;/a&gt; using Laravel (more on this later), and as it comes pre-packaged with a Gulp helper called &lt;a href="http://laravel.com/docs/5.1/elixir" rel="noopener noreferrer"&gt;Elixir&lt;/a&gt; (&lt;em&gt;facepalm: they misnamed it after the &lt;a href="https://en.wikipedia.org/wiki/Elixir_%28programming_language%29" rel="noopener noreferrer"&gt;Erlang platform&lt;/a&gt;&lt;/em&gt;), I decided to migrate the original theme CSS files into Less files.&lt;/p&gt;

&lt;p&gt;Why &lt;a href="http://lesscss.org/" rel="noopener noreferrer"&gt;Less&lt;/a&gt;, you ask? I don't know either. In my last project (&lt;a href="https://github.com/igorsantos07/protoboard" rel="noopener noreferrer"&gt;ProtoBoard&lt;/a&gt;, now an abandoned pet) I used &lt;a href="https://learnboost.github.io/stylus/" rel="noopener noreferrer"&gt;Stylus&lt;/a&gt;, although I don't remember the reason as well - probably to use just some of Sass's syntax (no semicolons) without fear of deprecation or the Sass quirkinesses, or maybe because I though I would still need Ruby to compile stuff. Before that, in my old Ruby life, I used to use &lt;a href="http://sass-lang.com/" rel="noopener noreferrer"&gt;Sass&lt;/a&gt;, but there was no other option at that time besides the defunct TurbineCSS (a project I liked so much I adopted the docs site for years when the original maintainer gave up on it).&lt;/p&gt;

&lt;p&gt;Now, after a couple of strong recommendations over Sass, and the fact my stylesheets were taking a whopping ~7s to compile on my 5-years old machine (&lt;em&gt;Sass has a C compiler, so it must be fast, right?&lt;/em&gt;), I decided to do the migration over to Sass. At this time I still don't heavily use Less features, I have just indented a couple of rules from the original theme, set color variables here and there and add one mixin, so I thought it wouldn't be a painful process.&lt;/p&gt;

&lt;p&gt;Indeed, it wasn't. Besides, as said before, some Sass's quirkinesses. I'm probably going to stick with Less, because of the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I use a couple of colour functions, such as &lt;code&gt;darken()&lt;/code&gt;, &lt;code&gt;lighten()&lt;/code&gt; and &lt;code&gt;fade()&lt;/code&gt; from Less. In Less world, they receive a color (hex, HSL or name) and a number, be it a decimal or a percent. In Sass world, however, the lightness functions use percents and the opacity functions (fade-in()/fade-out()) use decimals between 0 and 1; percents and decimals are not interchangeable. &lt;em&gt;Where are the standards here? I can't see any. &lt;em&gt;Could you pls decide what type of number for percents you're going to use, Sass? thnx&lt;/em&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibzwjch7xg6algxilw2d.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibzwjch7xg6algxilw2d.jpeg" alt="code screenshot comparing Sass to Less" width="800" height="160"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Mixins: Less vs Sass, using color names as an argument. If you use darken(goldenrod, 20%) in Sass, it will work fine, but by using goldenrod as an argument to a mixin and passing the color name into &lt;code&gt;darken()&lt;/code&gt;, it yelled a compilation error regarding "color must be a color". Go figure.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Although functions like darken() can work just fine with color names in both languages, if you pass a color name into a Sass mixin and use it in a function, it's going to yell at you. So what, Sass? &lt;em&gt;Some arguments are internally changed when they're passed around? WTF&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;It appeared to me that using Sass to compile my CSS gave &lt;em&gt;whooping&lt;/em&gt; 100ms of advantage (in a process that takes around 7s). However, running a simple benchmark (below) between branches I could notice Less was actually faster on my machine. In any way, the speed difference is certainly irrelevant.&lt;/li&gt;
&lt;li&gt;Sass actually made a bigger CSS file. However, as I'm running some post-processors as well (namely Autoprefixer and a minifier), the difference would also be irrelevant in production. The size differences are highlighted in the benchmark below as well.&lt;/li&gt;
&lt;li&gt;I felt Sass (at it's mostly accepted SCSS syntax) a little bit more verbose, by having to use &lt;code&gt;@mixin&lt;/code&gt; and &lt;code&gt;@include&lt;/code&gt; to declare mixins, instead of using them transparently as classes. That's certainly a matter of taste, though. On the other hand, Less interpolation feels weird - variable: &lt;code&gt;@var&lt;/code&gt;; interpolation: &lt;code&gt;@{var}&lt;/code&gt; (?!).&lt;/li&gt;
&lt;li&gt;Sass is more simplistic when you're including another file; &lt;a href="http://lesscss.org/features/#import-options" rel="noopener noreferrer"&gt;Less allows you to&lt;/a&gt; simply reference files without actually outputting them into the final file, or force them to be interpreted as Less/CSS. That's quite handy sometimes and might make for leaner CSS files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, I saw really no advantage on using Sass over Less. Both languages seem to have almost the same features, although Sass seems to be more programmable (not that I see this as an advantage; that thing is still a styling language in its roots, right?). Both languages yield similar results on speed and file size (if minified; but you're always going to compile your files to production, right?). Thus, I'm sticking with Less, as it has a bigger front-end community (I think) and does not play a joke with me regarding percents and (you can judge me here) color names.&lt;/p&gt;

&lt;p&gt;If there's any other advantage on using Sass, could you kindly tell me? I found none... &lt;em&gt;Besides variables being written with the same prefix my project's language (PHP) uses lol&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Platform details
&lt;/h3&gt;

&lt;p&gt;The tests above were run on a 5-years old machine, a high-end Core2Duo with 8GB RAM (with most of my development applications open). The code can be seen here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sass branch: &lt;a href="https://bitbucket.org/konato/web/src/34a007329228ff8833091c284c48d2bdcf0603ea/resources/assets/sass/?at=sass" rel="noopener noreferrer"&gt;source files&lt;/a&gt;, &lt;a href="https://bitbucket.org/konato/web/src/34a007329228ff8833091c284c48d2bdcf0603ea/public/css?at=sass" rel="noopener noreferrer"&gt;compiled CSS&lt;/a&gt;, &lt;a href="https://bitbucket.org/konato/web/src/34a007329228ff8833091c284c48d2bdcf0603ea/gulpfile.js?at=sass&amp;amp;fileviewer=file-view-default" rel="noopener noreferrer"&gt;gulpfile&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Main branch (Less): &lt;a href="https://bitbucket.org/konato/web/src/685c92fc520cc40755d7c6360793264349c87bfb/resources/assets/less/?at=master" rel="noopener noreferrer"&gt;source files&lt;/a&gt;, &lt;a href="https://bitbucket.org/konato/web/src/685c92fc520cc40755d7c6360793264349c87bfb/public/css?at=master" rel="noopener noreferrer"&gt;compiled CSS&lt;/a&gt;, &lt;a href="https://bitbucket.org/konato/web/src/685c92fc520cc40755d7c6360793264349c87bfb/gulpfile.js?at=master&amp;amp;fileviewer=file-view-default" rel="noopener noreferrer"&gt;gulpfile&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And yes, I know, these source files seems to be a mess. They're original from a theme I bought, and there's already &lt;a href="https://bitbucket.org/konato/web/issues/31/improve-theme-less-file" rel="noopener noreferrer"&gt;an issue to remind me to merge them together&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Here are the benchmark results, using &lt;code&gt;gulp&lt;/code&gt; and &lt;code&gt;gulp --production&lt;/code&gt;. The size indicates the final CSS file size, and the time in bold is the average between the 5 times compilation was run (each value indicated below).&lt;/p&gt;

&lt;p&gt;The gulpfiles can be seen in the branches highlighted before, as well as the resulting development CSS files.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Less (production) - 108.007kb ~ 6.906s&lt;br&gt;
6.78s | 7.21s | 6.75s | 6.96s | 6.83s&lt;/p&gt;

&lt;p&gt;Less (dev) - 149.122kb ~ 5.366s&lt;br&gt;
5.07s | 5.41s | 5.35s | 5.55s | 5.45s&lt;/p&gt;

&lt;p&gt;Sass (production) - 108.110kb ~ 7.44s&lt;br&gt;
7.21s | 7.73s | 7.77s | 7.39s | 7.1s&lt;/p&gt;

&lt;p&gt;Sass (dev) - 151.576kb ~ 5.494s&lt;br&gt;
5.73s | 5.27s | 5.24s | 5.67s | 5.56s&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>css</category>
      <category>sass</category>
      <category>less</category>
    </item>
  </channel>
</rss>
