<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Yanis</title>
    <description>The latest articles on Forem by Yanis (@janis_t).</description>
    <link>https://forem.com/janis_t</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%2F181178%2F0b1c8fe9-c12f-4987-9a0a-24aab7cace2d.jpg</url>
      <title>Forem: Yanis</title>
      <link>https://forem.com/janis_t</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/janis_t"/>
    <language>en</language>
    <item>
      <title>Upcoming ECMAScript features I'm excited about</title>
      <dc:creator>Yanis</dc:creator>
      <pubDate>Fri, 22 Jul 2022 13:35:33 +0000</pubDate>
      <link>https://forem.com/janis_t/upcoming-ecmascript-features-im-excited-about-pba</link>
      <guid>https://forem.com/janis_t/upcoming-ecmascript-features-im-excited-about-pba</guid>
      <description>&lt;p&gt;ECMAScript spec train hasn't slowed down anyhow. There are still tons of great proposals waiting for their time.&lt;/p&gt;

&lt;p&gt;Here are several of the upcoming ECMAScript features I'm particularly excited about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Temporal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://tc39.es/proposal-temporal/docs/index.html"&gt;Docs&lt;/a&gt;, &lt;a href="https://tc39.es/proposal-temporal/docs/cookbook.html"&gt;Cookbook&lt;/a&gt;, &lt;a href="https://github.com/js-temporal/temporal-polyfill"&gt;Polyfill&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The date/time API has always been a weak point of JavaScript. Great libraries like moment.js (already deprecated) emerged to fix this, and they did great.&lt;/p&gt;

&lt;p&gt;But now, finally, we got to a point where we can sum up our knowledge and experience and introduce a modern, robust date/time API into JavaScript standard library.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Temporal&lt;/code&gt; is a new global object which acts as a module packed with utility functions (like &lt;code&gt;Math&lt;/code&gt;). The API is based on immutable objects, and there's excellent support for time zones and non-Gregorian calendars.&lt;/p&gt;

&lt;p&gt;Here are some examples.&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="c1"&gt;// parsing a string&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Temporal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Instant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1969-07-20T20:17Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// just plain date&lt;/span&gt;
&lt;span class="nx"&gt;Temporal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PlainDate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; 2000-08-02&lt;/span&gt;

&lt;span class="c1"&gt;// difference between two points&lt;/span&gt;
&lt;span class="c1"&gt;// in time in different time zones&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Temporal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ZonedDateTime&lt;/span&gt;

&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2020-03-08T11:55:00+08:00[Asia/Hong_Kong]&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="nx"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2020-03-08T09:50:00-07:00[America/Los_Angeles]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="c1"&gt;//=&amp;gt; PT12H55M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I recommend skimming through &lt;a href="https://tc39.es/proposal-temporal/docs/cookbook.html#converting-between-temporal-types-and-legacy-date"&gt;the cookbook&lt;/a&gt; to really realize the potential of this great API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Array grouping
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/tc39/proposal-array-grouping"&gt;Proposal&lt;/a&gt;, &lt;a href="https://github.com/zloirock/core-js"&gt;Polyfill&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This small proposal adds two &lt;code&gt;group&lt;/code&gt; and &lt;code&gt;groupToMap&lt;/code&gt; to the Array's prototype.&lt;/p&gt;

&lt;p&gt;Both methods are used to group items in an array by certain criteria (the closest relative is lodash's &lt;a href="https://lodash.com/docs/#groupBy"&gt;groupBy&lt;/a&gt;).&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;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&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="s2"&gt;Jane&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="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="s2"&gt;John&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="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="s2"&gt;Tom&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="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;charAt&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="c1"&gt;// {&lt;/span&gt;
  &lt;span class="c1"&gt;// "j": [{name: "Jane"}, {name: "John"],&lt;/span&gt;
  &lt;span class="c1"&gt;// "t": [{ name: "Tom" }]&lt;/span&gt;
  &lt;span class="c1"&gt;// }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;groupToMap&lt;/code&gt; works similarly but gives us a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map"&gt;Map&lt;/a&gt;. It might come in handy when we need non-string keys.&lt;/p&gt;

&lt;p&gt;Well, and there are &lt;a href="https://www.zhenghao.io/posts/object-vs-map"&gt;other reasons to prefer Maps&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Array's change-by-copy (Stage 3)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/tc39/proposal-change-array-by-copy"&gt;Proposal&lt;/a&gt;, &lt;a href="https://github.com/zloirock/core-js#change-array-by-copy"&gt;Polyfill&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's wrong with Array's methods like &lt;code&gt;reverse&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;, or &lt;code&gt;splice&lt;/code&gt;? Well, nothing, they are all great. The only problem is that they modify the array in place, making it harder to use them in an FP code.&lt;/p&gt;

&lt;p&gt;This proposal introduces 4 new non-mutating methods on arrays (and also on &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays"&gt;typed arrays&lt;/a&gt;) which work similarly, but don't modify the source array: &lt;code&gt;toReversed()&lt;/code&gt;, &lt;code&gt;toSorted()&lt;/code&gt;, &lt;code&gt;toSpliced()&lt;/code&gt;, and &lt;code&gt;with()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The last one is used to replace a single element in an array:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;j&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="kd"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;//=&amp;gt; ['j', 'a', 'd', 'e']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Records and Tuples
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/tc39/proposal-record-tuple"&gt;Proposal&lt;/a&gt;, &lt;a href="https://rickbutton.github.io/record-tuple-playground"&gt;Playground&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Records and tuples are new primitive data structures similar to objects and arrays but deeply immutable.&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;const&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;"&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;tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax highlights the similarities between them and objects/arrays. All you have to do is to prefix it with &lt;code&gt;#&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Records and tuples can only contain other primitive values (including other records/tuples).&lt;/p&gt;

&lt;p&gt;This limitation allows them to be deeply immutable.&lt;/p&gt;

&lt;p&gt;It allows makes the equality comparison &lt;code&gt;===&lt;/code&gt; work for them like for other primitives. If two records/tuples are structurally deeply equal, the &lt;code&gt;===&lt;/code&gt; will return &lt;code&gt;true&lt;/code&gt; - and this is a big deal.&lt;/p&gt;

&lt;p&gt;Introducing such data structures is a great way to improve the JavaScript functional capabilities (as immutability is crucial in the functional paradigm).&lt;/p&gt;

&lt;p&gt;But this is quite a big topic, and I will return to it in a dedicated article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go next
&lt;/h2&gt;

&lt;p&gt;Those were the great JavaScript proposals I can't wait for. Hope you like them too.&lt;/p&gt;

&lt;p&gt;More proposals can be found on &lt;a href="https://github.com/tc39/proposals"&gt;the official GitHub page&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Using Git From Vim</title>
      <dc:creator>Yanis</dc:creator>
      <pubDate>Fri, 17 Sep 2021 15:59:53 +0000</pubDate>
      <link>https://forem.com/janis_t/using-git-from-vim-2pi9</link>
      <guid>https://forem.com/janis_t/using-git-from-vim-2pi9</guid>
      <description>&lt;p&gt;Git. Everyone loves it. Everyone hates it. Hardly anyone can resist it.&lt;/p&gt;

&lt;p&gt;You have just read my best article intro of all time.&lt;/p&gt;

&lt;p&gt;Using Git from within Vim can be very beneficial: you don't need to switch context or jump between windows. With some help from our friends (plugins), we can do almost anything from Vim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commit message
&lt;/h2&gt;

&lt;p&gt;You probably want to edit your commit messages in Vim.&lt;/p&gt;

&lt;p&gt;To do it, add the &lt;code&gt;EDITOR&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;p&gt;Put this into your &lt;code&gt;.bashrc&lt;/code&gt; / &lt;code&gt;.zshrc&lt;/code&gt; file.&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="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As an alternative, set the editor in &lt;code&gt;~/.gitconfig&lt;/code&gt; (this option has a priority over &lt;code&gt;$EDITOR&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;git config &lt;span class="nt"&gt;--global&lt;/span&gt; core.editor nvim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;git config&lt;/code&gt; command writes the settings into the &lt;code&gt;~/.gitconfig&lt;/code&gt; file. You can edit that file directly as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminal and external commands
&lt;/h2&gt;

&lt;p&gt;Modern Vim has a built-in &lt;a href="https://vimhelp.org/terminal.txt.html"&gt;terminal&lt;/a&gt;. That means you can always start &lt;code&gt;:term&lt;/code&gt; and start using Git command-line interface like you're used to.&lt;/p&gt;

&lt;p&gt;You can also start a specific command like &lt;code&gt;:term git status&lt;/code&gt; or &lt;code&gt;:term git add %&lt;/code&gt; (where &lt;code&gt;%&lt;/code&gt; refers to the current file path).&lt;/p&gt;

&lt;p&gt;For simple commands, even simple bang! command &lt;code&gt;:!&lt;/code&gt; (see &lt;code&gt;:help :!&lt;/code&gt;) would do. We can run any shell command like &lt;code&gt;:!git status&lt;/code&gt; or &lt;code&gt;:!git checkout %&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;All those are excellent options, but we can do better.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/airblade/vim-gitgutter"&gt;airblade/vim-gitgutter&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The Gitgutter's primary purpose is to show signs in the gutter on the left of what lines have been changed, added, or modified. Here's how it looks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nuON5efV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unoqg6cgb9uwn4a55ess.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nuON5efV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unoqg6cgb9uwn4a55ess.png" alt="gitgutter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See those little pluses and minuses on the left. That's it.&lt;/p&gt;

&lt;p&gt;While it's on its own quite a nice addition, it also comes with more useful stuff.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You can jump between "hunks" (modified pieces of code) with &lt;code&gt;]c&lt;/code&gt; / &lt;code&gt;]c&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While at a chunk, you either add/stage it with &lt;code&gt;&amp;lt;leader&amp;gt;hs&lt;/code&gt;, or revert/undo it with &lt;code&gt;&amp;lt;leader&amp;gt;hu&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To preview the change, press &lt;code&gt;&amp;lt;leader&amp;gt;hp&lt;/code&gt;. That's handy when you need to figure out what has changed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it's not all, so &lt;a href="https://github.com/airblade/vim-gitgutter"&gt;check it out&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/tpope/vim-fugitive"&gt;tpope/vim-fugitive&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/tpope"&gt;Tim Pope&lt;/a&gt; is the guy behind so many awesome Vim plugins, and this one is his most popular.&lt;/p&gt;

&lt;p&gt;It's "so awesome, it should be illegal," as we all agree.&lt;/p&gt;

&lt;p&gt;Here's how I use it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Git&lt;/code&gt; without any argument brings up the summary screen. From there, you can use mappings to add files (&lt;code&gt;s&lt;/code&gt;), unstage(&lt;code&gt;u&lt;/code&gt;), toggle(&lt;code&gt;-&lt;/code&gt;), and finally commit your changes(&lt;code&gt;cc&lt;/code&gt;). &lt;code&gt;=&lt;/code&gt; shows the current diff. There are many more mappings (press &lt;code&gt;g?&lt;/code&gt; to see them all). &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Git blame&lt;/code&gt; shows a commit hash and author near each line of code. Press enter at any lineg, and it will take you to that commit's diff. I use it so often I have it aliased to &lt;code&gt;&amp;lt;leader&amp;gt;a&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xm3DqBhW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngz2fojrzz0wkcvlnj3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xm3DqBhW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngz2fojrzz0wkcvlnj3i.png" alt="fugitive_blame"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You also do diffing, merging, and all the kinds of crazy stuff with fugitive. Have a look at the docs!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/tpope/vim-rhubarb"&gt;tpope/vim-rhubarb&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes we need to open a file in a browser (using Github UI), look around, or send a link to a colleague.&lt;/p&gt;

&lt;p&gt;With this plugin installed, it can be done by running &lt;code&gt;:Gbrowse&lt;/code&gt; either in normal or a visual mode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in normal mode, it will open the entire file in the web browser&lt;/li&gt;
&lt;li&gt;in visual mode, it will open the file with the selected lines highlighted (with Github, it works by appending a hash to the file's URL, e.g. &lt;code&gt;#L61-L62&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/junegunn/gv.vim"&gt;junegunn/gv.vim&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This plugin by the FZF author adds a command &lt;code&gt;:GV&lt;/code&gt;, which brgings on the Git commit log. Each commit can be viewed right in a split which is very handy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M9S7RvP9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgic55z96gliw696iq88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M9S7RvP9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgic55z96gliw696iq88.png" alt="gv"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As you can see, there are many great plugins that will make your life with Git much easier.&lt;/p&gt;

&lt;p&gt;There are, of course, others, which you may want to check out as well (though I don't use them, so I can't say if they are any good).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/mhinz/vim-signify"&gt;mhinz/vim-signify&lt;/a&gt; highlights the changes similarly to git-gutter&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lambdalisue/gina.vim"&gt;lambdalisue/gina.vim&lt;/a&gt; another way to create/update commits&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sodapopcan/vim-twiggy"&gt;sodapopcan/vim-twiggy&lt;/a&gt; a fugitive extension for managing branches&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/jreybert/vimagit"&gt;jreybert/vimagit&lt;/a&gt; a full-blown alternative to fugitive&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vim</category>
      <category>git</category>
      <category>tooling</category>
    </item>
    <item>
      <title>What's new in ECMAScript 2020</title>
      <dc:creator>Yanis</dc:creator>
      <pubDate>Sat, 05 Sep 2020 19:35:45 +0000</pubDate>
      <link>https://forem.com/janis_t/what-s-new-in-ecmascript-2020-4n02</link>
      <guid>https://forem.com/janis_t/what-s-new-in-ecmascript-2020-4n02</guid>
      <description>&lt;p&gt;ECMAScript 2020, the 11th installment of our favorite programming language, contains a handful of new features. Some are small ones, but others have the potential to change forever the way we write JavaScript.&lt;/p&gt;

&lt;p&gt;This article is an attempt at a short and concise overview of those new features. Grab your cup of tea and let's go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic import()
&lt;/h2&gt;

&lt;p&gt;ES2015 introduced the &lt;code&gt;static import&lt;/code&gt; syntax. Now you could export a variable from one module and then import it in another.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// utils.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;splitName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="c1"&gt;// index.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;splitName&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;./utils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;splitName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Snow&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;That syntax is called static because you can't import a module dynamically (depending on some conditions) at runtime. Note that it's not necessarily a bad thing: static imports can be optimized at compile time, allowing for &lt;a href="https://webpack.js.org/guides/tree-shaking/"&gt;Tree Shaking&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dynamic imports, on the other hand, when used wisely, can help with reducing bundle size by loading dependencies on-demand.&lt;/p&gt;

&lt;p&gt;The new &lt;code&gt;dynamic import&lt;/code&gt; syntax looks like a function (but it's not), and it returns &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;a promise&lt;/a&gt;, which also means we can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function"&gt;async/await&lt;/a&gt; with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rectangle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rectangle.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;circle.js&lt;/span&gt;&lt;span class="dl"&gt;"&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;calcSquare&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mod&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;calcSquare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Nullish coalescing
&lt;/h2&gt;

&lt;p&gt;The popular way of setting a default value with &lt;a href="https://en.wikipedia.org/wiki/Short-circuit_evaluation"&gt;short-circuting&lt;/a&gt; has its flaws. Since it's not really checking for the emptiness, but rather checking for the &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Falsy"&gt;falsyness&lt;/a&gt;, it breaks with values like &lt;code&gt;false&lt;/code&gt;, or &lt;code&gt;0&lt;/code&gt; (both of which are considered to be falsy).&lt;/p&gt;

&lt;p&gt;ES2020 introduces a new operator &lt;code&gt;??&lt;/code&gt; which works similarly but only evaluates to the right-hand when the initial value is either &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's a quick example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialVal&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="c1"&gt;// old way&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myVar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialVal&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 10&lt;/span&gt;

&lt;span class="c1"&gt;// new way&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myVar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialVal&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.strictmode.io/articles/nullish-coalescing-vs/"&gt;I wrote a detailed article&lt;/a&gt; about this feature and how it compares to the other methods for setting a default value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optional chaining
&lt;/h2&gt;

&lt;p&gt;The new &lt;code&gt;optional chaining&lt;/code&gt; operator aims to make the code shorter when dealing with nested objects and checking for possible &lt;code&gt;undefineds&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&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="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Fails with `Uncaught TypeError: Cannot read property 'city' of undefined`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Works but verbose&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Set&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Works and concise but requires a 3rd party library&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;address.city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Set&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 🤗&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Set&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;h2&gt;
  
  
  BigInt
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;BigInt&lt;/code&gt; is a new object that represents numbers higher than &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt; (which is &lt;code&gt;2^53 - 1&lt;/code&gt;). While for normal folks, it may sound more than enough, for some math applications and machine learning, the new &lt;code&gt;BigInt&lt;/code&gt; type comes in handy.&lt;/p&gt;

&lt;p&gt;It comes with its own literal notation (just add an &lt;code&gt;n&lt;/code&gt; to a number):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9007199254740991&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// or it can be constructed from a string&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;9007199254740991234&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;&lt;code&gt;BigInts&lt;/code&gt; come with their own algebra, which is not translated to regular numbers by which we can't mix up numbers and BigInts. They should be coerced to either type first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// throws Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// nope&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// that works&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  String.matchAll
&lt;/h2&gt;

&lt;p&gt;So here's an example. Imagine, you have a very long string of text, and you need to extract all the tags (that are words starting with &lt;code&gt;#&lt;/code&gt;) out of it. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions"&gt;Regular expressions&lt;/a&gt; to the rescue!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tweet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#JavaScript is full of #surprises. Both good and bad ones #TIL&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;h&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;#&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// or&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;#&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;matchAll&lt;/code&gt; returns an iterator. We could either iterate over it with &lt;code&gt;for..of&lt;/code&gt;, or we can convert it to an array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Promise.allSettled
&lt;/h2&gt;

&lt;p&gt;Remember the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all"&gt;Promise.all&lt;/a&gt; function? It resolves only when all of the passed promises get resolved. It rejects if at least one of the promises got rejected, while the others may still be pending.&lt;/p&gt;

&lt;p&gt;The new &lt;code&gt;allSettled&lt;/code&gt; behaves differently. It resolves whenever all of the promises finished working, that is, became either fulfilled or rejected. It resolves to an array that contains both the status of the promise and what it resolved to (or an error).&lt;/p&gt;

&lt;p&gt;Thus, &lt;code&gt;allSettled&lt;/code&gt; is never rejected. It's either &lt;code&gt;pending&lt;/code&gt;, or &lt;code&gt;resolved&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A real-world problem might be removing a loading indicator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// const urls = [...]
try {
  await Promise.all(urls.map(fetch))
} catch (e) {
  // at least one fetch is rejected here, but there may others still pending
  // so it may be too early for removing the loading indicator
  removeLoading()
}

// with allSettled
await Promise.allSettled(urls.map(fetch))
removeLoading()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  globalThis
&lt;/h2&gt;

&lt;p&gt;In JavaScript, there's always one big context object that contains everything. Traditionally, in browsers it was &lt;code&gt;window&lt;/code&gt;. But if you try accessing it in Node application, you'll get an error. There is no &lt;code&gt;window&lt;/code&gt; global object in Node; instead there is &lt;code&gt;global&lt;/code&gt; object. Then again, in WebWorkers, there is no access to &lt;code&gt;window&lt;/code&gt;, but there is &lt;code&gt;self&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;The new &lt;code&gt;globalThis&lt;/code&gt; property abstracts away the difference. Meaning that you can always refer to &lt;code&gt;globalThis&lt;/code&gt; without caring in which context you are now.&lt;/p&gt;

&lt;p&gt;Now, if you think that the naming is rather awkward, I'm totally with you, but note that naming it &lt;code&gt;self&lt;/code&gt; or &lt;code&gt;global&lt;/code&gt; could make some older code incompatible. So I guess we'll have to live with that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;For your convenience, here are the links to the MDN documentation for each of the features mentioned in this article.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import"&gt;Dynamic imports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator"&gt;Nullish coalescing operator&lt;/a&gt; but also &lt;a href="https://www.strictmode.io/articles/nullish-coalescing-vs/"&gt;my own article&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining"&gt;Optional chaining&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt"&gt;BigInt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled"&gt;Promise.allSettled&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis"&gt;globalThis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you like articles like this, you can &lt;a href="https://twitter.com/janis_t"&gt;follow me on Twitter&lt;/a&gt; to get notified about the new ones.&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>Vim and Language Server Protocol</title>
      <dc:creator>Yanis</dc:creator>
      <pubDate>Fri, 28 Aug 2020 14:40:15 +0000</pubDate>
      <link>https://forem.com/janis_t/vim-and-language-server-protocol-4enp</link>
      <guid>https://forem.com/janis_t/vim-and-language-server-protocol-4enp</guid>
      <description>&lt;p&gt;In this article, we'll quickly talk about what is a language server, why we need the LSP protocol, and how to set up it with Vim.&lt;/p&gt;

&lt;p&gt;But let's start from the beginning.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a language server?
&lt;/h2&gt;

&lt;p&gt;The idea is quite simple. There's a dedicated process running in the background and analyzes your codebase. It's also a server meaning that clients (text editors like Vim, IDEs, what have you) can connect and request some information or ask to perform a certain action.&lt;/p&gt;

&lt;p&gt;Language servers usually provide a whole set of operations that a modern IDE is capable of: things like intelligent code completion, auto-formatting, navigation("find the definition of that symbol under the cursor"), refactoring tools("rename that method"), and so on.&lt;/p&gt;

&lt;p&gt;If an IDE is a text editor plus some sophisticated code analyzing and refactoring tools, a language server separates those concepts. Now each of the tools can focus on doing their job will - editors can focus on text editing and language servers on language-specific tooling. As long as there is an interface for them to interact with one another, we can benefit from both.&lt;/p&gt;

&lt;p&gt;(If that rings a bell, that's because it resonates with &lt;a href="https://en.wikipedia.org/wiki/Unix_philosophy"&gt;the Unix philosophy&lt;/a&gt;: Write programs that do one thing and do it well, write programs to work together.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Now what is a language server protocol?
&lt;/h2&gt;

&lt;p&gt;Historically, every language server author come up his own API, and the client should implement it to make it work.&lt;/p&gt;

&lt;p&gt;As you might imagine, that approach is not too extensible.&lt;/p&gt;

&lt;p&gt;Imagine you created a new language server, and you want it to work with all the popular editors out there. How can you do that? Well, you now have to go and implement a plugin for each of those editors one by one because your server's custom API is not automatically compatible with a particular client.&lt;/p&gt;

&lt;p&gt;That's where the Language Server Protocol (or simply LSP) comes under the spotlight. LSP is an open standard &lt;a href="https://microsoft.github.io/language-server-protocol/"&gt;originally developed by Microsoft&lt;/a&gt; that governs how an interaction with a language server should look like. It is based on &lt;a href="https://en.wikipedia.org/wiki/JSON-RPC"&gt;JSON-RPC&lt;/a&gt; and defines an interface for how LS clients and servers should interact.&lt;/p&gt;

&lt;p&gt;Now we don't need multiple clients - one per each server, we just need one plugin, and since the protocol is the same for all language servers, we don't need anything else.&lt;/p&gt;

&lt;p&gt;There are &lt;a href="https://microsoft.github.io/language-server-protocol/implementors/servers/"&gt;lots and lots of LSP-compatible servers&lt;/a&gt; for all sorts of programming languages out there. The quality of the tools (as this is still a nascent area), and the capabilities (some languages are easier to tame than the other) can vary quite a bit.&lt;/p&gt;

&lt;p&gt;But for popular languages out there like &lt;a href="https://github.com/castwide/solargraph"&gt;Ruby&lt;/a&gt;, &lt;a href="https://github.com/palantir/python-language-server"&gt;Python&lt;/a&gt;, or &lt;a href="https://github.com/theia-ide/typescript-language-server"&gt;TypeScript&lt;/a&gt; the plank is high. Interestingly enough, the infamous &lt;a href="https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29"&gt;tsserver&lt;/a&gt; does not comply with LSP (although it's similar), so we need a proxy to make it work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Language Server Protocol with ALE
&lt;/h2&gt;

&lt;p&gt;At the moment, ALE doesn't seem to be as popular as &lt;code&gt;coc.vim&lt;/code&gt;, so I feel obliged to say a few words about why ALE, and not CoC.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First of all, ALE is so awesome at linting, it's an integral part of my setup anyway. And if I can make it work without introducing another plugin, I try to stick to it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Second, ALE supports TypeScript (which is not LSP-compatible) directly, so there's no need for a proxy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally (and that might be a bit personal), I find &lt;code&gt;CoC&lt;/code&gt; a bit out of place in Vim ecosystem with its own plugin system, and with it's own configuration file (instead of &lt;code&gt;.vimrc&lt;/code&gt;). Not to mention the expensive &lt;code&gt;node&lt;/code&gt; process it needs to operate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That being said, I've been using &lt;code&gt;coc.vim&lt;/code&gt; as well, and it's a really sharp, high-quality tool. If you find it better for your needs, go ahead and use it.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does ALE know which server to run?
&lt;/h3&gt;

&lt;p&gt;ALE tries to be smart about your environment. If it's able to find an LSP executable for a specific file type, it will run it and make it work (same goes with linters, ALE doesn't make any difference between language servers, a regular linters in that aspect). For example, if you have typescript installed, and open a &lt;code&gt;.ts&lt;/code&gt; file, it will start the &lt;code&gt;tsserver&lt;/code&gt; server automatically. In &lt;code&gt;:ALEInfo&lt;/code&gt;, you will find something similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(executable check - success) /Users/yanis/projects/web/candl/node_modules/.bin/tsserver
(started) ['/bin/zsh', '-c', '''/Users/yanis/projects/web/candl/node_modules/.bin/tsserver''']
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In case, ALE failed to recognise a language server, you can still define it manually (see &lt;code&gt;:help ale-lint-language-servers&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;  &lt;span class="k"&gt;call&lt;/span&gt; ale#linter#Define&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'filetype_here'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;  \&lt;/span&gt;   &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'any_name_you_want'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;  \&lt;/span&gt;   &lt;span class="s1"&gt;'lsp'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'stdio'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;  \&lt;/span&gt;   &lt;span class="s1"&gt;'executable'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/path/to/executable'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;  \&lt;/span&gt;   &lt;span class="s1"&gt;'command'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'%e run'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;  \&lt;/span&gt;   &lt;span class="s1"&gt;'project_root'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/path/to/root_of_project'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;  \&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note, that ALE doesn't support all of the LSP capabilities. So what can you do with the limited ALE's LSP functionality?&lt;/p&gt;

&lt;h3&gt;
  
  
  Jump To Definition
&lt;/h3&gt;

&lt;p&gt;You can put your cursor on a cursor and run &lt;code&gt;:ALEGoToDefinition&lt;/code&gt;, and it will take you to the place where it's defined. It happens in the same window, press &lt;code&gt;&amp;lt;C-o&amp;gt;&lt;/code&gt; to jump back. There are also alternative commands, to make it work in a new tab (&lt;code&gt;:ALEGoToDefinitionInTab&lt;/code&gt;), and in horizontal(&lt;code&gt;:ALEGoToDefinitionInSplit&lt;/code&gt;) or vertical(&lt;code&gt;ALEGoToDefinitionInVSplit&lt;/code&gt;) splits. I find the following mapping most natural:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;nmap &lt;span class="nb"&gt;gd&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;ALEGoToDefinitionInTab&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; " because I prefer &lt;span class="k"&gt;tabs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Find references
&lt;/h3&gt;

&lt;p&gt;Another useful feature is being able to find all occurrences of a function or a variable in the codebase. Again, after putting your cursor on a symbol type &lt;code&gt;:ALEFindRefereneces&lt;/code&gt;. It will open up a preview window from which you can jump to any file.&lt;/p&gt;

&lt;p&gt;Note that it's different from a simple text search. If you are looking for a class name &lt;code&gt;User&lt;/code&gt;, and you also have a string &lt;code&gt;"User"&lt;/code&gt; somewhere, the later will not appear in the search results. "Finding references" is aware of the semantics.&lt;/p&gt;

&lt;p&gt;A useful shortcut:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;nmap &lt;span class="k"&gt;gr&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;ALEFindReferences&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Hover
&lt;/h3&gt;

&lt;p&gt;In modern IDEs, you can hover over a symbol to get a piece of useful information. For example, in TypeScript, it's very common to hover over a variable to see its type. LSPs define a special operation just for that, and you can invoke it through ALE with &lt;code&gt;:ALEHover&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;nmap K &lt;span class="p"&gt;:&lt;/span&gt;ALEHover&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Hover information can be displayed in a hovering window with &lt;code&gt;let g:ale_set_balloons=1&lt;/code&gt; (though it doesn't work in Neovim, as the API is a bit different).&lt;/p&gt;

&lt;h3&gt;
  
  
  Completion
&lt;/h3&gt;

&lt;p&gt;ALE supports completion via LSP, and "just works" with &lt;a href="https://github.com/Shougo/deoplete.nvim"&gt;Deoplete&lt;/a&gt;. If you don't use Deoplete, you need to enable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_completion_enabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can also make it work through Omni-completion by setting &lt;code&gt;ale#completion#OmniFunc&lt;/code&gt; as autocompletion function, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;omnifunc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;ale#completion#OmniFunc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Linting
&lt;/h3&gt;

&lt;p&gt;Finally, linting is the primary purpose of ALE, so it definitely knows how to make it right. In the LSP world, it's called "Diagnostics" by the way.&lt;/p&gt;

&lt;p&gt;For ALE, any LSP-compatible server is just one of &lt;a href="https://github.com/dense-analysis/ale/blob/master/supported-tools.md"&gt;the possible linting tools&lt;/a&gt; it knows hot to work with. So if you're familiar with ALE, there's nothing new here.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript-only bonus
&lt;/h3&gt;

&lt;p&gt;ALE also defines a couple of useful actions that, at the moment, only work with TypeScript.&lt;/p&gt;

&lt;p&gt;The first one is &lt;code&gt;:ALEOrganizeImports&lt;/code&gt;, which orders your imports and also removes the unused ones.&lt;/p&gt;

&lt;p&gt;The second one is &lt;code&gt;:ALERename&lt;/code&gt;. You can rename any symbol, and it will again happen semantically, which is quite handy. By the way, renaming a symbol is something many language servers support, it's just that ALE can only do that for TypeScript. Hopefully, that will change in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Downsides
&lt;/h3&gt;

&lt;p&gt;ALE is a fantastic tool, and I'm very happily using it. It's not without it's drawbacks, and the most obvious one is the lack of full LSP support. It's also sad to see that its development has slowed down quite a bit recently, as the author seem to not have enough time. At the moment of writing, there are &lt;a href="https://github.com/dense-analysis/ale/pulls"&gt;113 pull-request&lt;/a&gt; awaiting to get reviewed. Hopefully, this situation will get better.&lt;/p&gt;

&lt;p&gt;So personally, I'm very excited about the announced Neovim's built-in support for LSP (since version 0.5). That seems to be both a much more comprehensive solution, but also a native one, so that's probably a way to go if you're using Neovim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Learn more about &lt;a href="https://microsoft.github.io/language-server-protocol/"&gt;LSP on Microsoft page&lt;/a&gt;, and for the curious, &lt;a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/"&gt;the detailed specification&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Popular Vim LSP clients include &lt;a href="https://github.com/dense-analysis/ale"&gt;ale&lt;/a&gt;, &lt;a href="https://github.com/neoclide/coc.nvim"&gt;coc.vim&lt;/a&gt;, &lt;a href="https://github.com/autozimu/LanguageClient-neovim"&gt;LanguageClient-neovim&lt;/a&gt;, and &lt;a href="https://github.com/prabirshrestha/vim-lsp"&gt;vim-lsp&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;A native &lt;a href="https://neovim.io/doc/user/lsp.html"&gt;LSP support introduced in Neovim&lt;/a&gt; since the version 0.5&lt;/li&gt;
&lt;li&gt;Setting up Vim and LSP (among other things) for &lt;a href="https://www.vimfromscratch.com/articles/vim-for-javascript-and-react-in-2019/"&gt;JavaScript&lt;/a&gt;, &lt;a href="https://www.vimfromscratch.com/articles/setting-up-vim-for-typescript/"&gt;TypeScript&lt;/a&gt;, &lt;a href="https://www.vimfromscratch.com/articles/vim-for-ruby-and-rails-in-2019/"&gt;Ruby&lt;/a&gt;, and &lt;a href="https://www.vimfromscratch.com/articles/vim-for-python/"&gt;Python&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ALE LSP capabilities &lt;code&gt;:help ale-lsp&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vim</category>
    </item>
    <item>
      <title>Vim for Python</title>
      <dc:creator>Yanis</dc:creator>
      <pubDate>Wed, 08 Jan 2020 13:05:00 +0000</pubDate>
      <link>https://forem.com/janis_t/vim-for-python-4f61</link>
      <guid>https://forem.com/janis_t/vim-for-python-4f61</guid>
      <description>&lt;p&gt;I started working on a Python project about a year ago. It was very annoying at first, as I was trying to embrace the Python style and figure out my workflow and the tooling. It took me some time until I finally set the things appropriately.&lt;/p&gt;

&lt;p&gt;In this article, I'd like to share how I made a productive Vim-based environment for working with Python.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ux4KwS1M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/python-nvim-b380ce5d2ef80c6b7cbb6ef9966feec90f7632d334e87b6e3ffb0513ad17ab67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ux4KwS1M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/python-nvim-b380ce5d2ef80c6b7cbb6ef9966feec90f7632d334e87b6e3ffb0513ad17ab67.png" alt="Here's How My Vim Looks Like"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: For some you, my setup may seem like a bit too much. You don't have to install every plugin listed in this article or copy every configuration line. Pick up what you like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Essentials
&lt;/h2&gt;

&lt;p&gt;Let's start with a list of some general-purpose plugins which I find irreplaceable for any language.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/junegunn/vim-plug"&gt;vim-plug&lt;/a&gt; is a minimalistic plugin manager&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/scrooloose/nerdtree"&gt;scrooloose/nerdtree&lt;/a&gt; to navigate the file tree&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/junegunn/fzf.vim"&gt;junegunn/fzf.vim&lt;/a&gt; fuzzy search through the files (and much more, really)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/tpope/vim-commentary"&gt;tpope/vim-commentary&lt;/a&gt; ( or &lt;a href="https://github.com/scrooloose/nerdcommenter"&gt;scrooloose/nerdcommenter&lt;/a&gt; ) — press &lt;code&gt;gcc&lt;/code&gt; to comment out a line or &lt;code&gt;gc&lt;/code&gt; to comment a selection in visual mode&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/liuchengxu/vista.vim"&gt;liuchengxu/vista.vim&lt;/a&gt; which is a "tagbar" that learns from LSP servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The other plugins I use include&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/jeetsukumaran/vim-pythonsense"&gt;jeetsukumaran/vim-pythonsense&lt;/a&gt; provides some Python-specific text objects: classes, functions, etc&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/jiangmiao/auto-pairs"&gt;jiangmiao/auto-pairs&lt;/a&gt; inserts closing quotes and parenthesis as you type&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The colorscheme used on the screenshots is &lt;a href="https://github.com/joshdick/onedark.vim"&gt;joshdick/onedark.vim&lt;/a&gt;, which is inspired by the Atom theme.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax highlighting
&lt;/h2&gt;

&lt;p&gt;Vim comes with syntax highlighting for many popular languages, including Python, though it is not always the best one.&lt;/p&gt;

&lt;p&gt;There are several options to improve the default highlighting.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/numirias/semshi"&gt;numirias/semshi&lt;/a&gt;, in my opinion, is the best. It works with Neovim only and requires the Python 3 support.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sheerun/vim-polyglot"&gt;sheerun/vim-polyglot&lt;/a&gt; includes support for many languages including Python&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/python-mode/python-mode"&gt;python-mode/python-mode&lt;/a&gt; is also a decent one although it comes with a lots of other stuff beside highlighting which I don't quite like&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--taqqONX5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/python-hl-be538d29e5928a1cf9bf710cdf9a3df2ea195002a82315eca1d960af6f31e4c4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--taqqONX5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/python-hl-be538d29e5928a1cf9bf710cdf9a3df2ea195002a82315eca1d960af6f31e4c4.png" alt="Semshi (on the left) vs. the default one"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My favorite color schemes (which I switch quite often) include &lt;a href="https://github.com/junegunn/seoul256.vim"&gt;junegunn/seoul256.vim&lt;/a&gt; and &lt;a href="https://github.com/joshdick/onedark.vim"&gt;joshdick/onedark.vim&lt;/a&gt; (the one on the screenshots).&lt;/p&gt;

&lt;h2&gt;
  
  
  Indentation
&lt;/h2&gt;

&lt;p&gt;You can set up indentation rules manually like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;au&lt;/span&gt; &lt;span class="nb"&gt;BufNewFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;BufRead&lt;/span&gt; *&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;py&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;expandtab&lt;/span&gt;       &lt;span class="p"&gt;|&lt;/span&gt;" replace &lt;span class="k"&gt;tabs&lt;/span&gt; with spaces
&lt;span class="se"&gt;    \&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;autoindent&lt;/span&gt;      &lt;span class="p"&gt;|&lt;/span&gt;" &lt;span class="k"&gt;copy&lt;/span&gt; &lt;span class="nb"&gt;indent&lt;/span&gt; when starting &lt;span class="k"&gt;a&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;line&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;tabstop&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;softtabstop&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="se"&gt;    \&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;shiftwidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A better alternative is &lt;a href="https://github.com/Vimjas/vim-python-pep8-indent"&gt;Vimjas/vim-python-pep8-indent&lt;/a&gt; plugin. It does a much better job complying with the &lt;a href="https://www.python.org/dev/peps/pep-0008/"&gt;PEP8&lt;/a&gt; style guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Folding
&lt;/h2&gt;

&lt;p&gt;Folding (&lt;code&gt;:help foldmethod&lt;/code&gt;) is when you collapse junks of code so that they don't distract you from the part that you are looking at right now.&lt;/p&gt;

&lt;p&gt;The best approximation is to use the folding method &lt;code&gt;indent&lt;/code&gt; though it doesn't work perfectly all the time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;au&lt;/span&gt; &lt;span class="nb"&gt;BufNewFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;BufRead&lt;/span&gt; *&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;py&lt;/span&gt; \
  &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;foldmethod&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;indent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To toggle a fold you can press &lt;code&gt;za&lt;/code&gt; (&lt;code&gt;:help fold-commands&lt;/code&gt;), and I have it mapped to &lt;code&gt;Space&lt;/code&gt; for convenience.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;space&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; za
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Linting &amp;amp; Fixing
&lt;/h2&gt;

&lt;p&gt;The fantastical &lt;a href="https://github.com/dense-analysis/ale"&gt;dense-analysis/ale&lt;/a&gt; plugin can be used for linting (which essentially means checking for syntax errors) and auto-fixing extremely well. It's asynchronous, meaning that it won't block the UI while running an external linter, and it supports &lt;a href="https://github.com/dense-analysis/ale/blob/master/supported-tools.md"&gt;a great range of languages&lt;/a&gt; and tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n4DvZnxa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/python-ale-d8700af0b918c6101dd6f5855d56227adb17f992d2fa9b51484959871f469129.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n4DvZnxa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/python-ale-d8700af0b918c6101dd6f5855d56227adb17f992d2fa9b51484959871f469129.png" alt="Python + ALE = ❤️"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ALE highlights problems with your code in the gutter. When you move the cursor to the problematic line, it shows the full error message at the bottom of the screen.&lt;/p&gt;

&lt;p&gt;By default, ALE will use all possible linters it could find on your machine. Run &lt;code&gt;:ALEInfo&lt;/code&gt; to see which linters are available and which are enabled.&lt;/p&gt;

&lt;p&gt;It is better though to explicitly specify which ones you're going to use with a particular filetype:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_linters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;   &lt;span class="s1"&gt;'python'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'flake8'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'pylint'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;   &lt;span class="s1"&gt;'ruby'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'standardrb'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'rubocop'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;   &lt;span class="s1"&gt;'javascript'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'eslint'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Some of the linters are also capable of fixing the problems in your code. ALE has a special command &lt;code&gt;:ALEFix&lt;/code&gt; that fixes the whole file. So far, I'm only Google's &lt;a href="https://github.com/google/yapf"&gt;YAPF&lt;/a&gt; as a fixer that formats the whole file when I press &lt;code&gt;F10&lt;/code&gt; or save the current buffer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_fixers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;    &lt;span class="s1"&gt;'python'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'standardrb'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="se"&gt;      \&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
nmap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;F10&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;ALEFix&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:ale_fix_on_save&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The last option is a huge time saver — it will automatically fix (and thus format) your file on save.&lt;/p&gt;

&lt;p&gt;I also have a little piece of configuration that shows the total number of warnings and errors in the status line. Very convenient.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; LinterStatus&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;counts &lt;span class="p"&gt;=&lt;/span&gt; ale#&lt;span class="nb"&gt;statusline&lt;/span&gt;#Count&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;bufnr&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;let&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;all_errors &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;counts&lt;span class="p"&gt;.&lt;/span&gt;error &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;counts&lt;span class="p"&gt;.&lt;/span&gt;style_error
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;all_non_errors &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;counts&lt;span class="p"&gt;.&lt;/span&gt;total &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;all_errors

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;counts&lt;span class="p"&gt;.&lt;/span&gt;total &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; ? &lt;span class="s1"&gt;'✨ all good ✨'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="se"&gt;        \&lt;/span&gt;   &lt;span class="s1"&gt;'😞 %dW %dE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;        \&lt;/span&gt;   all_non_errors&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="se"&gt;        \&lt;/span&gt;   all_errors
&lt;span class="se"&gt;        \&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;statusline&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;statusline&lt;/span&gt;&lt;span class="p"&gt;+=&lt;/span&gt;%&lt;span class="k"&gt;m&lt;/span&gt;
&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;statusline&lt;/span&gt;&lt;span class="p"&gt;+=&lt;/span&gt;\ %&lt;span class="k"&gt;f&lt;/span&gt;
&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;statusline&lt;/span&gt;&lt;span class="p"&gt;+=&lt;/span&gt;%&lt;span class="p"&gt;=&lt;/span&gt;
&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;statusline&lt;/span&gt;&lt;span class="p"&gt;+=&lt;/span&gt;\ %&lt;span class="p"&gt;{&lt;/span&gt;LinterStatus&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And here are a couple of alternatives to ALE:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/vim-syntastic/syntastic"&gt;vim-syntastic/syntastic&lt;/a&gt; very popular one but synchronous which can cause significant lags in UI&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/neomake/neomake"&gt;neomake/neomake&lt;/a&gt; asynchronous linting and make framework for Neovim/Vim (didn't try that one)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Jedi
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/davidhalter/jedi"&gt;Jedi&lt;/a&gt; is a "language server", which simply means that it's a separate process that runs in background and analyses your code. Other clients (editors or IDEs) can connect to it and request some information, like completion options, or "go to definition" coordinates.&lt;/p&gt;

&lt;p&gt;In order to use it, you need to install it with &lt;code&gt;pip install jedi&lt;/code&gt;, and then also add a client.&lt;/p&gt;

&lt;p&gt;One option is &lt;a href="https://github.com/davidhalter/jedi"&gt;davidhalter/jedi&lt;/a&gt;, which does a very decent job.&lt;/p&gt;

&lt;p&gt;Here's what it can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Press &lt;code&gt;ctrl + space&lt;/code&gt; for the completion options&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;leader&amp;gt;d&lt;/code&gt; goes to definition&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;leader&amp;gt;g&lt;/code&gt; goes to assignment&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;K&lt;/code&gt; shows the documentation&lt;/li&gt;
&lt;li&gt;and more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recently I have switched to &lt;a href="https://github.com/neoclide/coc.nvim"&gt;neoclide/coc.nvim&lt;/a&gt; and &lt;a href="https://github.com/neoclide/coc-python"&gt;coc-python&lt;/a&gt;. Coc is an "an intellisense engine" for Vim and Neovim and does a really good job when it comes to completion and communicating with language servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coc (Conquer of Completion)
&lt;/h2&gt;

&lt;p&gt;To me, the selling point is the usage of the new &lt;code&gt;floating window&lt;/code&gt; API of Neovim, which makes it very convenient.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Coc-python&lt;/code&gt; can use both Jedi and the Microsoft's Python Language Server. The first time you run it, it will ask you to install the components it needs (like a linter).&lt;/p&gt;

&lt;p&gt;Coc provides (with the help of Jedi) some basic IDE capabilities like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Going To definition
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;nmap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;gd&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;Plug&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;coc&lt;span class="p"&gt;-&lt;/span&gt;definition&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Displaying documentation (in the floating window!)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight viml"&gt;&lt;code&gt;nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; K &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;show_documentation&lt;span class="p"&gt;()&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:show_documentation&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;index&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'vim'&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; &amp;amp;&lt;span class="k"&gt;filetype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s1"&gt;'h '&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;expand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;cword&amp;gt;'&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;call&lt;/span&gt; CocAction&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'doHover'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;endif&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Smart rename (renames the exports across all files)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nmap &amp;lt;leader&amp;gt;rn &amp;lt;Plug&amp;gt;(coc-rename)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And of course the auto-complete menu (which you can see on the very first screenshot) appears as you type.&lt;/p&gt;

&lt;p&gt;Basically, it's a very solid and comprehensive plugin which covers almost all of our needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/neoclide/coc.nvim/wiki"&gt;Read to the wiki&lt;/a&gt; for more information about its capabilities.&lt;/p&gt;

&lt;p&gt;The drawbacks of using Coc include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An expensive Node process that Coc needs to run in order to operate&lt;/li&gt;
&lt;li&gt;Own independent extension system and its own (JSON) configuration file&lt;/li&gt;
&lt;li&gt;The aspiration to do everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still, it does the job well, and I continue using it (until there's a better option).&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to go next?
&lt;/h2&gt;

&lt;p&gt;Here are some other articles I learned from a lot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://realpython.com/vim-and-python-a-match-made-in-heaven/"&gt;VIM and Python – A Match Made in Heaven&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackabuse.com/vim-for-python-development/"&gt;Vim for Python Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/bezirganyan/editor-wars-vim-as-a-perfect-python-ide-19ne"&gt;Editor Wars: VIM as a perfect Python IDE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And some more articles in the similar vein from this website:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.vimfromscratch.com/articles/vim-for-ruby-and-rails-in-2019/"&gt;Vim for Ruby and Rails in 2019&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vimfromscratch.com/articles/vim-for-javascript-and-react-in-2019/"&gt;Vim for JavaScript and React in 2019&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, don't forget to &lt;a href="https://twitter.com/janis_t"&gt;Follow me on Twitter&lt;/a&gt; ;)&lt;/p&gt;

&lt;p&gt;P.S.: I'm writing a book about the modern Vim setup for IDE-like experience. &lt;a href="https://gumroad.com/l/vimfromscratchbook"&gt;You can check it out here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>python</category>
    </item>
    <item>
      <title>Awesome Command-Line Tools</title>
      <dc:creator>Yanis</dc:creator>
      <pubDate>Tue, 03 Dec 2019 11:54:29 +0000</pubDate>
      <link>https://forem.com/janis_t/awesome-command-line-tools-204n</link>
      <guid>https://forem.com/janis_t/awesome-command-line-tools-204n</guid>
      <description>&lt;p&gt;Most of the time, when I'm not using Vim, I'm probably hanging around in the command line. Thankfully, there is no lack of excellent CLI tools. Here I'd like to share some of them and how I use them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;For a TL;DR&lt;/strong&gt;, scroll to the bottom where you'll find a short list with the links.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  tldr
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_gb3U7zX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/man-tldr-a499fa8f74758f78c2c3ec83cdcdd945c9670f6a0764cb5899f6cc3ea8e06cdd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_gb3U7zX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/man-tldr-a499fa8f74758f78c2c3ec83cdcdd945c9670f6a0764cb5899f6cc3ea8e06cdd.png" alt="Man vs. tldr"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Man pages is a fantastic place to look for a documentation and learn how a program works but sometimes what we need is to quickly have a look at examples of how a particular tool should be used. For example I never remember how should to send a POST request with &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tldr-pages/tldr"&gt;tldr&lt;/a&gt; does just that — prints a short description and then gives you the possible ways of usage. With the most common example at hand I can quickly copy what I need and run.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For &lt;a href="https://www.alfredapp.com/"&gt;Alfred&lt;/a&gt; users, &lt;a href="https://github.com/cs1707/tldr-alfred"&gt;here is the workflow for it&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;And yes, there's a &lt;a href="https://github.com/wlemuel/vim-tldr"&gt;Vim plugin&lt;/a&gt; but somehow I don't find it too useful.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  rupa/z
&lt;/h2&gt;

&lt;p&gt;I can't imagine living without &lt;a href="https://github.com/rupa/z"&gt;this little script&lt;/a&gt;. It tracks my most frequently used directories along with the frequency, and then it lets me jump to a directory by typing a partial path.&lt;/p&gt;

&lt;p&gt;For example, when I want to get to &lt;code&gt;~/projects/web/vimfromscratch&lt;/code&gt;, I just type &lt;code&gt;z vimf&lt;/code&gt; and then hit &lt;code&gt;Enter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I would also suggest changing the default command name from &lt;code&gt;z&lt;/code&gt; to &lt;code&gt;j&lt;/code&gt; (as this is much easier for your fingers). You can either create an alias, or set the global env variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export _Z_CMD="j"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I have to mention, there are some alternatives you can try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/wting/autojump"&gt;autojump&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/huyng/bashmarks"&gt;bashmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/clvv/fasd"&gt;fasd&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  diff-so-fancy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_lupEjyc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/diffsf-9e7be84e9ef78034d3f198b68b6a3054df67514069b8c89b0a8edfa880d54e91.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_lupEjyc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/diffsf-9e7be84e9ef78034d3f198b68b6a3054df67514069b8c89b0a8edfa880d54e91.png" alt="diff-so-fancy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/so-fancy/diff-so-fancy"&gt;This tool&lt;/a&gt; is a drop-in replacement for &lt;code&gt;diff&lt;/code&gt; or &lt;code&gt;git diff&lt;/code&gt;. It does the same thing but does it with style. The default colors are much nicer, and the diff shows changes within the same line (see the screenshot).&lt;/p&gt;

&lt;p&gt;In order to make it your default Git pager, run this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; core.pager &lt;span class="s2"&gt;"diff-so-fancy | less --tabs=4 -RFX"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then also, you can replace your default &lt;code&gt;diff&lt;/code&gt; by setting an alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;diff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"diff-so-fancy"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Bat
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ny70G1ty--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/cat-vs-bat-964daf1c0a508e43b338ba7d3890f38260884b5d06e592608a7839e01a1b93dc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ny70G1ty--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/cat-vs-bat-964daf1c0a508e43b338ba7d3890f38260884b5d06e592608a7839e01a1b93dc.png" alt="Cat vs. Bat"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we started talking about syntax highlighting, have you ever thought of how &lt;code&gt;cat&lt;/code&gt; is a bit boring? Wouldn't it be nice if it was able to highlight the syntax of a file that it's printing out?&lt;/p&gt;

&lt;p&gt;The answer to this question is &lt;a href="https://github.com/sharkdp/bat"&gt;bat&lt;/a&gt;. &lt;code&gt;bat&lt;/code&gt; adds a syntax highlighting for a large number of languages. Plus, it is integrated with Git, so it will show what has changed in the file you're viewing.&lt;/p&gt;

&lt;p&gt;You would want to replace your older model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias cat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bat"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can colorize you man page by exporting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MANPAGER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sh -c 'col -bx | bat -l man -p'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For other interesting integration, please have a &lt;a href="https://github.com/sharkdp/bat"&gt;look at the README&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ripgrep
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BFwyM5Qh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/ripgrep-c796b44132acbe6c0688f9aa8e7bc4dc3bdc4b4a9c13b8f26eb9bbda8616bb1b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BFwyM5Qh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/ripgrep-c796b44132acbe6c0688f9aa8e7bc4dc3bdc4b4a9c13b8f26eb9bbda8616bb1b.png" alt="Searching for a React component with ripgrep"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/BurntSushi/ripgrep"&gt;Ripgrep&lt;/a&gt; is an alternative to &lt;code&gt;ag&lt;/code&gt; (the silver searcher). It is significantly faster, and also it comes with some sane default behaviour, like respecting your &lt;code&gt;.gitignore&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;As you can see on the screenshot, the output is clear, and the search pattern is highlighted in the output results which is nice.&lt;/p&gt;

&lt;h2&gt;
  
  
  exa
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2fmkTH_R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/exa-685149d4582530e42f6cf70dc530b9dd8fceac35a91a9d8db7917a556d62b363.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2fmkTH_R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/exa-685149d4582530e42f6cf70dc530b9dd8fceac35a91a9d8db7917a556d62b363.png" alt="Regular `ls` vs `exa`"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another drop in replacement you can use instead of the build-in &lt;code&gt;ls&lt;/code&gt; command is &lt;a href="https://github.com/ogham/exa"&gt;Exa&lt;/a&gt;. Again, as some other tools in this article &lt;code&gt;exa&lt;/code&gt; provides color highlighting and some sane defaults but overall remains compatible with &lt;code&gt;ls&lt;/code&gt; API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"exa"&lt;/span&gt;

&lt;span class="c"&gt;# I usually use this command instead&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"exa -lahF"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  fd
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JP7Gqr4T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/fd-vs-find-a8601a4cf6987eb88e948ef6ec7773057f32b4929f1aa4f388c52da48479265d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JP7Gqr4T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/fd-vs-find-a8601a4cf6987eb88e948ef6ec7773057f32b4929f1aa4f388c52da48479265d.png" alt="Regular `find` vs `fd`"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By this time, you probably already figured out that if there is a replacement for some built-in command, I would probably have it installed.&lt;/p&gt;

&lt;p&gt;Meet &lt;a href="https://github.com/sharkdp/fd"&gt;fd&lt;/a&gt;, a faster alternative to &lt;code&gt;find&lt;/code&gt;. The problem with &lt;code&gt;find&lt;/code&gt; is that as I can never remember how to use it. Should it be &lt;code&gt;find myfile.py&lt;/code&gt;, or &lt;code&gt;find --name myfile.py&lt;/code&gt;, or is it with a single dash? Should I add &lt;code&gt;.&lt;/code&gt; before or after the search pattern? Argggh.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;fd&lt;/code&gt;, it's always straightforward &lt;code&gt;fd myfile.py&lt;/code&gt;. Again that's about saner defaults and beautiful colorized output (see the screenshot).&lt;/p&gt;

&lt;p&gt;Don't forget to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;find&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fd"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Fzf
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FBK3yexP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/fzf-preview-38df213a8843c333be881f2097fb9e5455276483e9549a763d6526ce95ecbd83.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FBK3yexP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://d3ep7iiirnq25a.cloudfront.net/assets/fzf-preview-38df213a8843c333be881f2097fb9e5455276483e9549a763d6526ce95ecbd83.png" alt="Fzf with a file preview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oh yes, I saved the coolest for the end. &lt;a href="https://github.com/junegunn/fzf"&gt;Fzf&lt;/a&gt; (fuzzy finder) is a super fast tool written in Go which does just one thing: It takes a list of lines as an input and then let's a user fuzzy search in them for some text.&lt;/p&gt;

&lt;p&gt;While that may not sound too impressive, the fun part begins with the applications.&lt;/p&gt;

&lt;p&gt;For example, try&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;vim &lt;span class="si"&gt;$(&lt;/span&gt;fzf&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You'll be prompted with a list of files, and you can search among those. After you press &lt;code&gt;enter&lt;/code&gt;, the selected file will open in Vim.&lt;/p&gt;

&lt;p&gt;Or, you try pressing &lt;code&gt;Ctrl+R&lt;/code&gt; (the command that runs the command history in the shell). You can now fuzzy search among your commands, then press &lt;code&gt;enter&lt;/code&gt; to execute it.&lt;/p&gt;

&lt;p&gt;While searching for a file, &lt;code&gt;Fzf&lt;/code&gt; can give you a nice preview (see the screenshot), you just need to specify the preview command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;fzf &lt;span class="nt"&gt;--preview&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bat {} --color=always"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Remember the &lt;code&gt;rupa/z&lt;/code&gt; script? &lt;code&gt;Fzf&lt;/code&gt; integrates with it nicely, so if you run &lt;code&gt;z&lt;/code&gt; without arguments you can fuzzy search among your most frequently used directories.&lt;/p&gt;

&lt;p&gt;Honestly, the list of possibilities how you can use it is really endless. Sky is the limit. Try browsing &lt;a href="https://github.com/junegunn/fzf/wiki/examples"&gt;this page with examples&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is this thing you're using?
&lt;/h2&gt;

&lt;p&gt;In case you want to know, here is what my setup is based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://iterm2.com/"&gt;iTerm2&lt;/a&gt; terminal&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Menlo_(typeface)"&gt;Menlo typeface&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mbadolato/iTerm2-Color-Schemes/blob/master/schemes/Afterglow.itermcolors"&gt;Afterglow colorscheme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Z_shell"&gt;Z shell&lt;/a&gt; with &lt;a href="https://github.com/robbyrussell/oh-my-zsh"&gt;oh-my-zsh&lt;/a&gt; configuration framework&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hiquest/dotfiles/blob/master/yanis.zsh-theme"&gt;Custom theme&lt;/a&gt; for &lt;code&gt;oh-my-zsh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The numbers you see on the screenshots are &lt;code&gt;ruby&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt; versions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tl;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/tldr-pages/tldr"&gt;tldr&lt;/a&gt; for quickly viewing the usage examples&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/rupa/z"&gt;rupa/z&lt;/a&gt; for jumping between directories&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/so-fancy/diff-so-fancy"&gt;diff-so-fancy&lt;/a&gt; for better diffing&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sharkdp/bat"&gt;bat&lt;/a&gt; to replace &lt;code&gt;cat&lt;/code&gt; with&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/BurntSushi/ripgrep"&gt;ripgrep&lt;/a&gt; for searching pattern within text files&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ogham/exa"&gt;exa&lt;/a&gt; a colorful and fast &lt;code&gt;ls&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sharkdp/fd"&gt;fd&lt;/a&gt; a drop-in replacement for &lt;code&gt;find&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/junegunn/fzf"&gt;Fzf&lt;/a&gt; for fuzzy search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;P.S.: I'm writing a book on Vim for developers. Feel free to &lt;a href="https://gumroad.com/l/vimfromscratchbook"&gt;check it out&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>bash</category>
      <category>vim</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
