<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Igor Irianto</title>
    <description>The latest articles on DEV Community by Igor Irianto (@iggredible).</description>
    <link>https://dev.to/iggredible</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%2F161246%2Fdbb2e809-5e9a-4d81-98a3-174bd0788b9a.png</url>
      <title>DEV Community: Igor Irianto</title>
      <link>https://dev.to/iggredible</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iggredible"/>
    <language>en</language>
    <item>
      <title>Vim Global Command</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Sat, 19 Nov 2022 17:44:29 +0000</pubDate>
      <link>https://dev.to/iggredible/vim-global-command-2mkl</link>
      <guid>https://dev.to/iggredible/vim-global-command-2mkl</guid>
      <description>&lt;p&gt;The global command (&lt;code&gt;:h :global&lt;/code&gt;) is used to run Ex-commands on multiple lines.&lt;/p&gt;

&lt;p&gt;If you want to delete a line, Vim has the &lt;code&gt;:d&lt;/code&gt; (&lt;code&gt;:h :delete&lt;/code&gt;) command (or you can press &lt;code&gt;dd&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Wait a second - if I want to run the delete command on multiple lines, can't I just run &lt;code&gt;:%d&lt;/code&gt; to delete all the lines in my buffer? Yes, you definitely can.&lt;/p&gt;

&lt;p&gt;Where the global command shines, is that it lets you to execute the delete command on all the lines &lt;em&gt;matching the  pattern&lt;/em&gt;. So if you want to delete all the lines containing "foo", without the global command, you may need to first &lt;em&gt;find&lt;/em&gt; the lines with foo (&lt;code&gt;/foo&lt;/code&gt;), then delete them (&lt;code&gt;dd&lt;/code&gt; or &lt;code&gt;:d&lt;/code&gt;). Repeat the process as many times as there are lines containing foo in your buffer. This can get tedious if there are tens, if not hundreds of lines. With the global command, you can run &lt;code&gt;:g/foo/d&lt;/code&gt; once and - voila! All foo lines are deleted.&lt;/p&gt;

&lt;p&gt;This is the power of the global command. It lets you to apply a command to multiple lines at once. In this post, I will show you how to unlock some of the global command's potentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Commands Can I Run With the Global Command?
&lt;/h2&gt;

&lt;p&gt;When you go to the help section for the global command, &lt;code&gt;:h :global&lt;/code&gt;, it says something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Execute the Ex command cmd (default ":p") on the lines within [range] where {pattern} matches.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So what are the Ex commands that I can run with the global command?&lt;/p&gt;

&lt;p&gt;You can find a list of Vim's ex commands with &lt;code&gt;:h ex-cmd-index&lt;/code&gt; (warning: there are hundreds of them). I've been using Vim for years and frankly, I only use very, very few of them. I believe the trick here is to use the few tools that you have well.&lt;/p&gt;

&lt;p&gt;For the sake of brevity, based on my personal experience, I found the following 8 commands useful to work with the global commands (if you have a command that you use often and it is not listed here, please let me know!)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delete&lt;/li&gt;
&lt;li&gt;Substitute&lt;/li&gt;
&lt;li&gt;Normal&lt;/li&gt;
&lt;li&gt;Print&lt;/li&gt;
&lt;li&gt;Move&lt;/li&gt;
&lt;li&gt;Put&lt;/li&gt;
&lt;li&gt;Copy&lt;/li&gt;
&lt;li&gt;Sort&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CMD: Delete
&lt;/h3&gt;

&lt;p&gt;The delete command deletes line(s). Type &lt;code&gt;:d&lt;/code&gt; to delete the current line, &lt;code&gt;:1,5d&lt;/code&gt; to delete lines 1-5, &lt;code&gt;:%d&lt;/code&gt; to delete the whole buffer, and &lt;code&gt;:+3d&lt;/code&gt; to delete the third line below your cursor.&lt;/p&gt;

&lt;p&gt;With the global command, you can delete multiple lines.&lt;/p&gt;

&lt;p&gt;To delete all lines containing &lt;code&gt;console&lt;/code&gt;: &lt;code&gt;:g/console/d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To delete all lines that do &lt;strong&gt;not&lt;/strong&gt; end with a number 0-9: &lt;code&gt;:g/[^0-9]$/d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When we run the delete command, Vim stores the deleted text in the numbered register. If you prefer not to modify your register, you can run the blackhole (&lt;code&gt;_&lt;/code&gt;) delete command instead: &lt;code&gt;:g/console/d_&lt;/code&gt;. It is a little more verbose but it preserves your registers! If you don't use the number register that often, you can just use the regular delete command.&lt;/p&gt;

&lt;h3&gt;
  
  
  CMD: Substitute
&lt;/h3&gt;

&lt;p&gt;The substitute command (&lt;code&gt;:h :substitute&lt;/code&gt;) substitutes a string with a new string. Type &lt;code&gt;:s/foo/bar&lt;/code&gt; to sub foo with bar.&lt;/p&gt;

&lt;p&gt;To substitute all to_s with to_f on all lines containing puts: &lt;code&gt;:g/puts/s/to_s/to_f&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  CMD: Normal
&lt;/h3&gt;

&lt;p&gt;Vim has a &lt;code&gt;:normal&lt;/code&gt; command to execute normal mode commands. If you type &lt;code&gt;:normal Ahello&lt;/code&gt;, it's similar to pressing &lt;code&gt;A&lt;/code&gt; (append text at the end of the line) then typing "hello". Think of it like running a brief normal-mode script.&lt;/p&gt;

&lt;p&gt;If you want to insert "//" before all &lt;code&gt;import&lt;/code&gt; texts, you can run: &lt;code&gt;:g/import/normal I//&lt;/code&gt;. This will effectively comment out all the import commands (even better, if you have a comment plugin and &lt;code&gt;gcc&lt;/code&gt; is set to toggle comment, you can also run &lt;code&gt;:g/import/normal gcc&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;You can also execute macro (&lt;code&gt;:h macro&lt;/code&gt;) using the normal command. Assuming you've recorded a macro in the register &lt;code&gt;a&lt;/code&gt;, to execute your macro on all lines containing &lt;code&gt;console&lt;/code&gt;: &lt;code&gt;:g/console/normal @a&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  CMD: Put
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;:put&lt;/code&gt; command (&lt;code&gt;:h :put&lt;/code&gt;) lets you to put a text from the Vim register.&lt;/p&gt;

&lt;p&gt;Recall that registers are what Vim uses to store yanked (copied) or deleted files. For more, check out &lt;code&gt;:h registers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To put (paste) a text from register a after the lines containing const, run &lt;code&gt;:g/const/pu a&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You also don't have to always paste from the register. You can tell &lt;code&gt;put&lt;/code&gt; to output your own text with &lt;code&gt;:g/const/pu ='hello vim'&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  CMD: Print
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;:print&lt;/code&gt; command (&lt;code&gt;:h :print&lt;/code&gt;) prints the current line. By itself it is not too useful, but with the global command, you can print all the lines containing the given pattern.&lt;/p&gt;

&lt;p&gt;To look at all the Javascript functions in the current buffer, you can print them with: &lt;code&gt;:g/() {/p&lt;/code&gt; (assuming you are using the &lt;code&gt;myFunction() { ... }&lt;/code&gt; syntax and not the arrow function).&lt;/p&gt;

&lt;p&gt;If you want to list all the import your file has, run &lt;code&gt;:g/import/p&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By default, the global command runs the print command if you don't pass it any command after the pattern. So instead of running &lt;code&gt;:g/foo/p&lt;/code&gt;, you can just run &lt;code&gt;:g/foo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One cool trivia, the default global command syntax, &lt;code&gt;:g/re/p&lt;/code&gt; (&lt;code&gt;re&lt;/code&gt; stands for Regex), spells "grep", the very same &lt;code&gt;grep&lt;/code&gt; that lives in the command-line universe. This is not a coincidence, because the &lt;code&gt;g/re/p&lt;/code&gt; command originally came from the ed editor (which is probably still in your terminal right now - try it! Just remember, if you need to quit it, type &lt;code&gt;q&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  CMD: Move
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;:move&lt;/code&gt; command (&lt;code&gt;:h :move&lt;/code&gt;) moves the current line to the line below the given address. Address is usually the line number. For example, to move the current line to below line 10, you can run &lt;code&gt;:m 10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With the global command, you can do neat trick like reversing the entire file with &lt;code&gt;:g/^/m 0&lt;/code&gt;. Note that &lt;code&gt;^&lt;/code&gt; is the pattern for the beginning of a line (use it to match all lines, including empty lines)&lt;/p&gt;

&lt;p&gt;If you want to gather all your &lt;code&gt;require&lt;/code&gt; lines to the top of the file, you can run &lt;code&gt;:g/require/m 0&lt;/code&gt; (keep in mind that their order will be reversed).&lt;/p&gt;

&lt;h3&gt;
  
  
  CMD: Copy
&lt;/h3&gt;

&lt;p&gt;The copy command (&lt;code&gt;:h :t&lt;/code&gt; - not sure why it's the letter t) can copy the current line into the line below the given address (similar to move, except it keeps the original line). To copy the current line to below line 10, run &lt;code&gt;:t 10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To copy &lt;code&gt;const&lt;/code&gt; to the line below them, run &lt;code&gt;:g/const/t .&lt;/code&gt; - note that &lt;code&gt;.&lt;/code&gt; represents the current line. This effectively duplicates all lines containing const.&lt;/p&gt;

&lt;h2&gt;
  
  
  Range in The Global Command
&lt;/h2&gt;

&lt;p&gt;There are two range types that you can pass to the global command: address range and the pattern range.&lt;/p&gt;

&lt;h3&gt;
  
  
  Address Range
&lt;/h3&gt;

&lt;p&gt;The address range has a syntax of: &lt;code&gt;:n,mg/pattern/cmd&lt;/code&gt; (&lt;code&gt;n&lt;/code&gt; and &lt;code&gt;m&lt;/code&gt; are the starting and ending addresses)&lt;/p&gt;

&lt;p&gt;To delete the lines containing "puts" between lines 1 and 5, run &lt;code&gt;:1,5g/puts/d&lt;/code&gt; (anything outside lines 1-5 aren't affected).&lt;/p&gt;

&lt;p&gt;To delete the lines containing "import" between the current line to the end of the file, run &lt;code&gt;:.,$g/import/d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To delete all lines containing "require" between the 2 lines above and below the current line, run &lt;code&gt;:-2,+2g/require/d&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern Range
&lt;/h3&gt;

&lt;p&gt;Up to now, we have been passing one pattern to the global command: &lt;code&gt;:g/pattern/command&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To pass two patterns, pass it another one: &lt;code&gt;:g/pattern1/,/pattern2/command&lt;/code&gt;. When given two patterns, the global command will take effect only &lt;em&gt;between&lt;/em&gt; the two pattern matches.&lt;/p&gt;

&lt;p&gt;To delete everything between the line containing foo and the line containing bar, including the lines containing foo and bar themselves, run: &lt;code&gt;:g/foo/,/bar/d&lt;/code&gt;. Anything outside of the foo-bar sandwich will not be deleted (ie: any line before foo and any line after bar).&lt;/p&gt;

&lt;p&gt;The command above deletes all lines sandwiched between foo and bar &lt;em&gt;including&lt;/em&gt; the foo and bar lines; if you want to preserve the foo and bar lines, run &lt;code&gt;:g/foo/+1,/bar/-1d&lt;/code&gt;. &lt;code&gt;/foo/+1&lt;/code&gt; tells the global command to run the command one line &lt;em&gt;after&lt;/em&gt; foo; retrospectively, &lt;code&gt;/bar/-1&lt;/code&gt; executes the command one line &lt;em&gt;before&lt;/em&gt; bar.&lt;/p&gt;

&lt;h3&gt;
  
  
  CMD: Sort
&lt;/h3&gt;

&lt;p&gt;Vim has a &lt;code&gt;:sort&lt;/code&gt; command (&lt;code&gt;:h :sort&lt;/code&gt;) to sort lines. I find the sort command useful combined with the pattern range of the global command.&lt;/p&gt;

&lt;p&gt;If you just run the &lt;code&gt;:sort&lt;/code&gt; command, Vim sorts the entire file. Often this is not the effect you want. What usually happens is that there would be times when I need to sort the content inside an array or object/hash/dict (I'll refer this data structure &lt;code&gt;{foo: bar}&lt;/code&gt; as object from now on in this article) that goes over a few lines and I'd like to sort them. &lt;/p&gt;

&lt;p&gt;To sort only the elements inside each array that spans over several lines, run &lt;code&gt;:g/\[/+1,/\]/-1sort&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arr1 = [
  "i",
  "g",
  "e",
  "c",
  "a",
  "h",
  "b",
  "f",
  "d"
]

arr2 = [
  "b",
  "d",
  "c",
  "a",
  "e"
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arr1 = [
  "a",
  "b",
  "c",
  "d"
  "e",
  "f",
  "g",
  "h",
  "i",
]

arr2 = [
  "a",
  "b",
  "c",
  "d",
  "e"
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command &lt;code&gt;:g/\[/+1,/\]/-1sort&lt;/code&gt; looks intimidating with all these symbols, let's break it down.&lt;/p&gt;

&lt;p&gt;When you look at the command &lt;code&gt;:g/\[/+1,/\]/-1sort&lt;/code&gt;, it follows the pattern &lt;code&gt;:g/pattern1/,/pattern2/cmd&lt;/code&gt;. It starts with the first pattern, followed by the second pattern, followed by a command.&lt;/p&gt;

&lt;p&gt;The first pattern is &lt;code&gt;/\[/+1&lt;/code&gt;. The pattern is enclosed inside a pair of forward-slashes &lt;code&gt;/&lt;/code&gt;. The pattern itself is &lt;code&gt;\[&lt;/code&gt;, which is an opening square bracket &lt;code&gt;[&lt;/code&gt;. Note that in regex, &lt;code&gt;[&lt;/code&gt; is a special character for &lt;a href="https://www.regular-expressions.info/charclass.html" rel="noopener noreferrer"&gt;character class&lt;/a&gt;, so we can't just do &lt;code&gt;/[/&lt;/code&gt;. We have to escape it to match a literal &lt;code&gt;[&lt;/code&gt;. That's why we have &lt;code&gt;/\[/&lt;/code&gt;. &lt;code&gt;+1&lt;/code&gt; matches one line after the square bracket. We don't want to sort that line containing &lt;code&gt;[&lt;/code&gt; itself, but the line &lt;em&gt;after&lt;/em&gt; that, that's why we add the &lt;code&gt;+1&lt;/code&gt; modifier.&lt;/p&gt;

&lt;p&gt;The second pattern is &lt;code&gt;/\]/-&lt;/code&gt;. It is similar to the first pattern. I won't break it down here, but basically it matches one line before the closing square bracket &lt;code&gt;]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;/\[/+1,/\]/-1&lt;/code&gt; then captures anything one line after &lt;code&gt;[&lt;/code&gt; and one line before &lt;code&gt;]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, the last part of our command &lt;code&gt;:g/\[/+1,/\]/-1sort&lt;/code&gt; is the &lt;code&gt;sort&lt;/code&gt; command itself. Any line one line after &lt;code&gt;[&lt;/code&gt; and one line before &lt;code&gt;]&lt;/code&gt; will be sorted. Hey, that was not too bad!&lt;/p&gt;

&lt;p&gt;Let's try another one. Can you sort only the keys in the array of objects below? I'll give the solution down below, but spend a few minutes attempting it yourself before scrolling down!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    one: 1,
    two: 2,
    three: 3,
    four: 4
  },
  {
    def: 2,
    abc: 1,
    jkl: 4,
    ghi: 3,
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My command is &lt;code&gt;:g/{/+1,/}/-1 sort&lt;/code&gt;. Does yours work?&lt;/p&gt;

&lt;p&gt;Result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    four: 4
    one: 1,
    three: 3,
    two: 2,
  },
  {
    abc: 1,
    def: 2,
    ghi: 3,
    jkl: 4,
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Vim's global command augments Vim's Ex commands so that you can apply them on multiple lines. With this, you only need to run a command once and Vim will do the rest for you. Why run a command multiple times if you can just do it once?&lt;/p&gt;

&lt;p&gt;If you want to learn more Vim tips/tricks, follow my Twitter account &lt;a href="https://twitter.com/learnvim" rel="noopener noreferrer"&gt;learnvim&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>vim</category>
      <category>global</category>
      <category>ex</category>
      <category>command</category>
    </item>
    <item>
      <title>Learning Vim Regex</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Sat, 29 Jan 2022 15:47:56 +0000</pubDate>
      <link>https://dev.to/iggredible/learning-vim-regex-26ep</link>
      <guid>https://dev.to/iggredible/learning-vim-regex-26ep</guid>
      <description>&lt;h1&gt;
  
  
  Learning Vim Regex
&lt;/h1&gt;

&lt;p&gt;Learning regular expressions is like learning latin. It is not pleasant but it is good for your soul. They are incredibly useful but also hard to read. People who master them are hailed as gods. Many desired to learn them but a few actually did.&lt;/p&gt;

&lt;p&gt;To a programmer, regex (regular expression) is a tool. It can be learned (and mastered). Learning it is a lifetime investment. Here's why: First, regex is portable. Sure, there are different regex flavors, but the basic principle is the same across all flavors. Regex knowledge in one domain will transfer everywhere. Second, regex is powerful and knowing it can save you a lot of time. Programming is all about creating and updating text. Regex allows you to search and modify texts efficiently. Many powerful programs (like parsers) are built on top of regexes. Third, it is fun (once you get to a certain proficiency).&lt;/p&gt;

&lt;p&gt;Regex knowledge boosts your Linux-fu. You'll unlock more powerful commands using programs like sed, awk, grep, find, vim, and more. In this article, we will focus on learning and understanding regexes in Vim. &lt;/p&gt;

&lt;p&gt;This article is by no means a complete regex tutorial. In fact, I'll be honest right now, that this article probably contains less than a third of what Vim regex can do. But they are the ones that I find very useful. I call them the good parts.&lt;/p&gt;

&lt;p&gt;Many of the regex information you will be learning here is also transferable. Although the syntax may vary slightly in different environments, the principle is the same. If you understand everything in this article, you should be well on your way to use regex in other environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Regex in Vim
&lt;/h2&gt;

&lt;p&gt;Many of Vim's search features allow you to use regular expressions. Some of them are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The search commands (&lt;code&gt;/&lt;/code&gt; and &lt;code&gt;?&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The global and substitute command-line (ex) commands (&lt;code&gt;:g&lt;/code&gt; and &lt;code&gt;:s&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The grep commands (&lt;code&gt;:vimgrep&lt;/code&gt; and &lt;code&gt;:grep&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are other places where you can use regex, but based on my experience, these three are the main places I would use regex in.&lt;/p&gt;

&lt;p&gt;Finally, this is not a guide about how to use the global command, or grep, or whatever. This is more of a regex guide than a Vim guide. Think of it as a regex guide that uses Vim. It will show you how to use regex in Vim. &lt;/p&gt;

&lt;p&gt;I am going to limit the command to only the search command. Almost everything you see here is done using the search command &lt;code&gt;/&lt;/code&gt; (I may release more guides in the future with different commands).&lt;/p&gt;

&lt;h2&gt;
  
  
  To Magic or Not
&lt;/h2&gt;

&lt;p&gt;If you are acquainted with Vim regex, you might be aware of Vim's special "flavor" of Regex. You can read more in &lt;code&gt;:h /magic&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Basically Vim allows you to pass an option where certain characters are treated as literal characters while others as special characters.&lt;/p&gt;

&lt;p&gt;In this guide, I won't use any magic option - meaning no &lt;code&gt;\v&lt;/code&gt;, &lt;code&gt;\m&lt;/code&gt;, &lt;code&gt;\V&lt;/code&gt;, or &lt;code&gt;\M&lt;/code&gt; (you basically will see a lot of backslashes).&lt;/p&gt;

&lt;p&gt;Enough with introductory stuff, let's start!&lt;/p&gt;

&lt;h1&gt;
  
  
  The Good Parts of Vim Regex
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Basic Search &lt;code&gt;/&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The most basic search that you could do is to search for a literal word. If you want to search for the string &lt;code&gt;donut&lt;/code&gt;, run &lt;code&gt;/donut&lt;/code&gt;. Vim will look for a literal word donut. It won't match &lt;code&gt;d0nut&lt;/code&gt;, &lt;code&gt;Donut&lt;/code&gt;, or &lt;code&gt;DONUT&lt;/code&gt; (unless you have &lt;code&gt;'smartsearch'&lt;/code&gt; option on, but that's another topic).&lt;/p&gt;

&lt;p&gt;In real life, things are not that simple. Maybe you need to look for variations of &lt;code&gt;foo&lt;/code&gt; string including &lt;code&gt;food&lt;/code&gt;, &lt;code&gt;fool&lt;/code&gt;, and &lt;code&gt;foos&lt;/code&gt;. Maybe you need to match a phone-number-looking pattern like &lt;code&gt;xxx-xxx-xxxx&lt;/code&gt; where x could be &lt;em&gt;any&lt;/em&gt; integer. So you want this pattern to match &lt;code&gt;123-123-1234&lt;/code&gt; and &lt;code&gt;333-444-5555&lt;/code&gt;, but not &lt;code&gt;1234-123-123&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Practically speaking, we often need to search for a &lt;em&gt;pattern&lt;/em&gt;, not a literal word. This is where knowing a little bit of regex goes a long way. In fact, just by knowing a handful of regex concepts in this article, you should be able to handle 99% of your searching needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Any Character &lt;code&gt;.&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The most simple, versatile, and almost universal regex pattern is the dot symbol (&lt;code&gt;.&lt;/code&gt;). It matches any single character.&lt;/p&gt;

&lt;p&gt;For example, if you need to search for a 3-letter string that starts with an n and ends with a t, and you don't care what goes in the middle, you can use the pattern &lt;code&gt;n.t&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;/n.t&lt;/code&gt; will match the strings &lt;code&gt;not&lt;/code&gt;, &lt;code&gt;nut&lt;/code&gt;, &lt;code&gt;net&lt;/code&gt;, &lt;code&gt;n0t&lt;/code&gt;, and even &lt;code&gt;n t&lt;/code&gt; (space between n and t).&lt;/p&gt;

&lt;p&gt;You can also use it multiple times, so &lt;code&gt;/n..b&lt;/code&gt; matches any 4 character string that starts with n, followed by any character, followed by any character, and ends with b. So it will match &lt;code&gt;noob&lt;/code&gt;, &lt;code&gt;n00b&lt;/code&gt;, &lt;code&gt;n3wt&lt;/code&gt;. It will not match &lt;code&gt;nob&lt;/code&gt; or &lt;code&gt;nooob&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Character Class
&lt;/h2&gt;

&lt;p&gt;The dot syntax is useful, but sometimes you want to classify your search. Recall that &lt;code&gt;/n.t&lt;/code&gt; matches any three-lettered word that starts with n, ends with t, and anything goes in the middle. What if we only want alphabetic characters, so it would match &lt;code&gt;not&lt;/code&gt;, &lt;code&gt;nut&lt;/code&gt;, and &lt;code&gt;net&lt;/code&gt; but not &lt;code&gt;n0t&lt;/code&gt;, &lt;code&gt;n t&lt;/code&gt;, and &lt;code&gt;n?t&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To match only between a set of characters, a character class can help you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Character Class &lt;code&gt;[]&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A character class or a collection, is a sequence / set of characters that you can use to match any &lt;em&gt;single&lt;/em&gt; character in the collection.&lt;/p&gt;

&lt;p&gt;In this case, to match lowercase and uppercase alphabetic characters (a-z and A-Z), we can use &lt;code&gt;/n[a-zA-Z]t&lt;/code&gt;. This will match &lt;code&gt;net&lt;/code&gt;, &lt;code&gt;nUt&lt;/code&gt;, and &lt;code&gt;not&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you need to match only lowercase alphabets, you can instead use &lt;code&gt;/n[a-z]t&lt;/code&gt;. It will now match &lt;code&gt;net&lt;/code&gt;, &lt;code&gt;nut&lt;/code&gt;, and &lt;code&gt;not&lt;/code&gt;, but it won't match &lt;code&gt;nEt&lt;/code&gt;, &lt;code&gt;nUt&lt;/code&gt;, and &lt;code&gt;nOt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To match only vowels, use &lt;code&gt;/n[aeiou]t&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To match only numbers, use &lt;code&gt;/n[0-9]t&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To match only numbers 0 to 5, use &lt;code&gt;/n[0-5]t&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To match only uppercase A-F &lt;em&gt;and&lt;/em&gt; numbers 0-9, use &lt;code&gt;/n[A-F0-9]t&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You are not limited to alphabets and numbers, if you want it to match either a space, an exclamation mark, and a question mark, you can do something like &lt;code&gt;/n[ !?]t&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Negated Char Class &lt;code&gt;[^]&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;There is a special behavior that you need to know with the character class &lt;code&gt;[]&lt;/code&gt;. If you put a caret (&lt;code&gt;^&lt;/code&gt;) as the first character in it, it will act as a negation character. &lt;code&gt;[^a]&lt;/code&gt; means "not a". &lt;code&gt;[^0-9]&lt;/code&gt; means any non-number character. &lt;code&gt;[^aeiou]&lt;/code&gt; means any non-vowel character.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;/n[^ue]t&lt;/code&gt; means any non-u or non-e character. It will not match &lt;code&gt;nut&lt;/code&gt; and &lt;code&gt;net&lt;/code&gt;, but it will match any &lt;code&gt;not&lt;/code&gt;, &lt;code&gt;nUt&lt;/code&gt;, and &lt;code&gt;n0t&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Special Characters
&lt;/h2&gt;

&lt;p&gt;Vim comes with a predefined special character set. &lt;/p&gt;

&lt;p&gt;If you want to match a number, instead of using &lt;code&gt;/[0-9]&lt;/code&gt;, you can also do &lt;code&gt;/\d&lt;/code&gt; (digit). If you want to match a non-number, instead of using &lt;code&gt;/[^0-9]&lt;/code&gt;, you can use &lt;code&gt;/\D&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to match a lowercase alphabet character, instead of using &lt;code&gt;/[a-z]&lt;/code&gt;, you can use &lt;code&gt;/\l&lt;/code&gt;. If you want to match a non-lowercase, alphabet character, instead of &lt;code&gt;/[^a-z]&lt;/code&gt;, you can use &lt;code&gt;/\L&lt;/code&gt;. To match an uppercase, use &lt;code&gt;/\u&lt;/code&gt;. For the non-uppercase, use &lt;code&gt;/\U&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to match a hex digit, instead of &lt;code&gt;/[0-9A-Fa-f]&lt;/code&gt;, you can use &lt;code&gt;/\x&lt;/code&gt;. To match a non-hex digit, use &lt;code&gt;/\X&lt;/code&gt;. You should see a pattern of using the uppercase letter to indicate the negated version of that special character.&lt;/p&gt;

&lt;p&gt;If you want to match a whitespace character (tab and space), use &lt;code&gt;/\s&lt;/code&gt;. To match a non-whitespace character, use &lt;code&gt;/\S&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To match a "word" character (lower and uppercase alphabets, numbers, and underscore), use &lt;code&gt;/\w&lt;/code&gt;. To match a non-word character, use &lt;code&gt;/\W&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you know your predefined characters, you can save a few keystrokes (&lt;code&gt;/\d&lt;/code&gt; is 3 strokes vs &lt;code&gt;/[0-9]&lt;/code&gt; 6 strokes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Quantifiers
&lt;/h2&gt;

&lt;p&gt;Repeating patterns are common when searching. For example, maybe you need to look for repeating digits in a phone number pattern. Nobody wants to type &lt;code&gt;[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]&lt;/code&gt; to match 123-123-1234 and 111-222-3333.Instead typing the characters many times, you can use quantifiers to simplify the search.&lt;/p&gt;

&lt;h3&gt;
  
  
  Min/Max
&lt;/h3&gt;

&lt;p&gt;The pattern &lt;code&gt;123-123-1234&lt;/code&gt; consists of a set of 3 consecutive numbers, followed by a dash, then another set of 3 consecutive numbers, followed by another dash, then another set of 4 consecutive numbers. &lt;/p&gt;

&lt;p&gt;You can use the &lt;code&gt;{n}&lt;/code&gt; (where n is an integer) quantifiers to do the job. The &lt;code&gt;{n}&lt;/code&gt; quantifier expects the preceding character to repeat n times. The &lt;code&gt;{}&lt;/code&gt; syntax is a special character and needs to be escaped (without the escape, Vim will treat &lt;code&gt;{3}&lt;/code&gt; as a literal {3}. The search command &lt;code&gt;/[0-9]\{3}-[0-9]\{3}-[0-9]\{4}&lt;/code&gt; will match the phone number pattern. In the case of &lt;code&gt;/[0-9]\{3}&lt;/code&gt;, it expects the digit to be repeated 3 times. It will match &lt;code&gt;123&lt;/code&gt; or &lt;code&gt;777&lt;/code&gt;, but not &lt;code&gt;12&lt;/code&gt; or &lt;code&gt;7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The search command to find the phone number 123-123-1234 looks like: &lt;code&gt;/[0-9]\{3}-[0-9]\{3}-[0-9]\{4}&lt;/code&gt;. That's a lot simpler than typing &lt;code&gt;/[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are variations in the min/max quantifier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{n}
{n,m}
{n,}
{,m}
{}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Exact Match &lt;code&gt;{n}&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;You have already seen the first one, &lt;code&gt;{n}&lt;/code&gt;. It means the preceding character is repeated &lt;em&gt;exactly&lt;/em&gt; n times. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;/a\{5}&lt;/code&gt; will match &lt;code&gt;aaaaa&lt;/code&gt;. &lt;code&gt;/[a-z]\{3}&lt;/code&gt; will match &lt;code&gt;abc&lt;/code&gt; and &lt;code&gt;zzz&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Min Max Match &lt;code&gt;{n,m}&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Let's explore the second one, &lt;code&gt;{n,m}&lt;/code&gt;. It expects the preceding character to be repeated a minimum of n times and a max of m times (n and m are integers).&lt;/p&gt;

&lt;p&gt;When we search using &lt;code&gt;/[0-9]\{2,4}&lt;/code&gt;, it searches for any numbers 0-9 repeated between two and four times. It will match 99, 789, and 1234, but not 9, 78, and 12345 (although it will match the first 4 digits)&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;/fo\{2,5}&lt;/code&gt; searches for a string that starts with an f, followed by the letter o repeated 2 to 5 times. It matches foo, foooo, and fooooo, but not fo and foooooo (if will match up to fooooo).&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;/fo\{2,5}d&lt;/code&gt; will match food and foooood, but not fooooood. It expects no more than 5 o's between f and d, whereas it finds 6 o's.&lt;/p&gt;

&lt;h4&gt;
  
  
  Min Match &lt;code&gt;{n,}&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The next form, &lt;code&gt;{n,}&lt;/code&gt;, expects a minimum of n, up to infinity. &lt;/p&gt;

&lt;p&gt;The search &lt;code&gt;/fo\{3,}&lt;/code&gt; looks for the letter f, followed by 3 or more o. It matches fooo, foooo, and foooooooooooooooooooo. It won't match fo or foo.&lt;/p&gt;

&lt;p&gt;The search &lt;code&gt;/[0-9]\{2,}&lt;/code&gt; looks for 2 or more digits. It matches 11, 123, 1234567, and 999999999999999999.&lt;/p&gt;

&lt;h4&gt;
  
  
  Max Match &lt;code&gt;{,m}&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The next form, &lt;code&gt;{,m}&lt;/code&gt;, expects a minimum of zero, up to m occurrence. &lt;/p&gt;

&lt;p&gt;The search &lt;code&gt;/fo\{,5}&lt;/code&gt; looks for the letter f, followed by no o, up to 5 o's. It matches f, fo, foo, and fooooo. It won't match foooooo (it will only the first 5 o's).&lt;/p&gt;

&lt;h4&gt;
  
  
  Zero or More Match &lt;code&gt;{}&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The final variation of the min/max quantifier is &lt;code&gt;{}&lt;/code&gt; (or &lt;code&gt;{,}&lt;/code&gt;, personally this syntax makes more sense to me). It means zero or more.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/fo\{}&lt;/code&gt; expects an f, followed by zero o and up to unlimited o's. It will match f, fo, fooooo, fooooooooooooooo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero or More &lt;code&gt;*&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The zero or more quantifier matches zero or more of the preceding character and is expressed with an asterisk &lt;code&gt;*&lt;/code&gt;. It doesn't need to be escaped.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;/fo*&lt;/code&gt;, Vim looks for the letter f, followed by zero o, up to infinite o's. It will match f, fo, foo, fooooooooooooooo.&lt;/p&gt;

&lt;p&gt;If you think about it, it is similar to &lt;code&gt;/fo\{,}&lt;/code&gt;, but instead of typing all those brackets, you just type an asterisk.&lt;/p&gt;

&lt;h3&gt;
  
  
  One or More &lt;code&gt;+&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The one or more quantifier matches one or more of the preceding character and is expressed with a plus &lt;code&gt;+&lt;/code&gt;. It needs to be escaped, otherwise Vim treats it as a literal plus sign.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;/fo\+&lt;/code&gt;, Vim looks for the letter f, followed by one or more o's. It will match fo, fooooo, and foooooooooooooo. It won't match an f.&lt;/p&gt;

&lt;p&gt;It is also equivalent to &lt;code&gt;/fo\{1,}&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero or One &lt;code&gt;?&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The zero or one quantifier matches either zero or one of the preceding characters. It is expressed with a question mark &lt;code&gt;?&lt;/code&gt;. It needs to be escaped, otherwise it would be treated as a literal &lt;code&gt;?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;/fo\?&lt;/code&gt;, it will match both f and fo, but not foo.&lt;/p&gt;

&lt;p&gt;Its min/max equivalent is &lt;code&gt;/fo\{,1}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Greedy Vs Lazy
&lt;/h2&gt;

&lt;p&gt;There are two different quantifiers: greedy and lazy. &lt;em&gt;By the way, in regex, there's also a third quantifier type, possessive, but I won't cover that here.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Greedy
&lt;/h3&gt;

&lt;p&gt;You actually have seen greedy quantifier in action. &lt;code&gt;*&lt;/code&gt; is one example.&lt;/p&gt;

&lt;p&gt;Suppose that you have the following sentence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I say, "I use Vim". You say, "I don't use Vim". Uh-oh.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, when you do &lt;code&gt;/".*"&lt;/code&gt; (a string that starts with a double-quote, then zero or more of any character, then a double quote), Vim finds one match: &lt;code&gt;"I use Vim". You say, "I don't use Vim"&lt;/code&gt;. This is because by using a greedy quantifier, you will get the largest possible value.&lt;/p&gt;

&lt;p&gt;But what if you want to match for the smallest pattern? You need to use a lazy quantifier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy
&lt;/h3&gt;

&lt;p&gt;If you look at lazy quantifiers, they look a lot like the min/max quantifiers, except that they have a &lt;code&gt;-&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{-}
{-n,m}
{-n,}
{-,m}
{-n}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go over the first one. Recall that &lt;code&gt;{}&lt;/code&gt; has the same effect as &lt;code&gt;*&lt;/code&gt;: zero or more of the preceding character, &lt;em&gt;the largest possible match&lt;/em&gt;. &lt;code&gt;{-}&lt;/code&gt; is the lazy version of &lt;code&gt;{}&lt;/code&gt;. It matches zero or more of the preceding character, &lt;em&gt;the smallest possible match&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Going back to our sentence earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I say, "I use Vim". You say, "I don't use Vim". Uh-oh.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's use the lazy search: &lt;code&gt;/".\{-}"&lt;/code&gt;. You will see &lt;em&gt;two&lt;/em&gt; matches: "I use Vim" and "I don't use Vim". Cool!&lt;/p&gt;

&lt;p&gt;Let's go over the second variation, &lt;code&gt;{-n,m}&lt;/code&gt;. If &lt;code&gt;{n,m}&lt;/code&gt; matches at least n and at most m of the preceding character, &lt;em&gt;the largest possible match&lt;/em&gt;, then &lt;code&gt;{-n,m}&lt;/code&gt; matches at least n and at most m of the preceding character, &lt;em&gt;the smallest possible match&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Suppose that you have the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fo
foo
fooooo
foooooooooo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do &lt;code&gt;/fo\{-2,5}&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the first string it will find no match, because it doesn't meet the string requirement of at least two o's. &lt;/li&gt;
&lt;li&gt;On the second string, it will match foo, the minimum requirement. - On the third match, instead of matching fooooo, it only matches foo, the least available match (two o's).&lt;/li&gt;
&lt;li&gt;On the fourth string, it also only matches foo, the smallest number of possible match.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will leave the remaining lazy quantifiers, &lt;code&gt;{-n,}&lt;/code&gt;, &lt;code&gt;{-,m}&lt;/code&gt;, and &lt;code&gt;{-n}&lt;/code&gt;, to you. They behave similar to the greedy quantifiers, but instead of finding the largest number of matches, they find the smallest number of matches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anchors
&lt;/h2&gt;

&lt;p&gt;Sometimes you need to find a match not based on its content, but based on &lt;em&gt;where&lt;/em&gt; it is. To search by location, we use anchors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beginning of line &lt;code&gt;^&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The caret matches the start of the line.&lt;/p&gt;

&lt;p&gt;If you have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;donut is life
life is donut
a donut a day
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do &lt;code&gt;/^donut&lt;/code&gt;, it will match "donut is life" because the word donut is at the start of the line. "life is donut" and "a donut a day" do not have a donut at the start of the line, so they won't match.&lt;/p&gt;

&lt;h3&gt;
  
  
  End of Line &lt;code&gt;$&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The opposite of the start-of-the-line anchor is the end-of-the-line anchor, &lt;code&gt;$&lt;/code&gt;. If you do &lt;code&gt;/donut$&lt;/code&gt;, it will match the donut in "life is donut" because the word donut is at the end of the line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Word Boundaries &lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Another useful anchor is the word boundary anchors.&lt;/p&gt;

&lt;p&gt;Given the following sentence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Without further ado, I do like donut very much
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do (pun not intended :P) &lt;code&gt;/do&lt;/code&gt;, Vim will match the do in: &lt;code&gt;ado&lt;/code&gt;, &lt;code&gt;do&lt;/code&gt;, and &lt;code&gt;donut&lt;/code&gt;. What if you only want to match for the do in the word &lt;code&gt;do&lt;/code&gt;, not in &lt;code&gt;ado&lt;/code&gt; and &lt;code&gt;donut&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Word boundaries can help. The syntax is &lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt;. &lt;code&gt;&amp;lt;&lt;/code&gt; means the start of a word and &lt;code&gt;&amp;gt;&lt;/code&gt; means the end of a word. You need to escape them, otherwise Vim will match for literal &lt;code&gt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&lt;/code&gt;. &lt;code&gt;/\&amp;lt;do\&amp;gt;&lt;/code&gt; will match only the standalone &lt;code&gt;do&lt;/code&gt;, and not the do in &lt;code&gt;ado&lt;/code&gt; and &lt;code&gt;donut&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you want to match the do in donut and the word do, then you are looking for the start-of-the-word do, so you can use &lt;code&gt;/\&amp;lt;do&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Likewise, to match the do in ado and the word do, it is the same as looking for the end-of-the-word do, hence you can use &lt;code&gt;/do\&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Or &lt;code&gt;|&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes you need to look for either A or B or C. In Vim, you can search for alternatives with the OR (bar) syntax &lt;code&gt;|&lt;/code&gt;. You need to escape the bar syntax, otherwise Vim will match a literal bar symbol.&lt;/p&gt;

&lt;p&gt;If you need to search for either pancake or waffle (part of a tasty breakfast :D), you can do &lt;code&gt;/pancake\|waffle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you need to search for a line that starts with either foo or bar, you can do &lt;code&gt;/^foo\|^bar&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Groups
&lt;/h2&gt;

&lt;p&gt;Earlier you learned about quantifiers. They can help you search for repeating characters. However, more often than not, you need to look for repeated groups, not individual characters. You can do that with capture groups.&lt;/p&gt;

&lt;h3&gt;
  
  
  Capture Group (Sub-Expression) &lt;code&gt;( )&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The capture group is represented by a set of parentheses &lt;code&gt;()&lt;/code&gt;. In Vim, they need to be escaped &lt;code&gt;\(\)&lt;/code&gt; or they will match literal parentheses.&lt;/p&gt;

&lt;p&gt;If I need to look for one or more donuts, like donutdonutdonut, I can use &lt;code&gt;/\(donut\)\+&lt;/code&gt;. Recall that way earlier I said that quantifiers like &lt;code&gt;+&lt;/code&gt; search for one or more the &lt;em&gt;preceding character&lt;/em&gt;. I lied. Technically, it searches for the preceding character &lt;em&gt;or&lt;/em&gt; group. In Vim, they are called atoms. &lt;/p&gt;

&lt;p&gt;So &lt;code&gt;/fo\+&lt;/code&gt; looks for an f, followed by one or more o's, and matches fo, foo, and fooooo. While &lt;code&gt;/\(fo\)\+&lt;/code&gt; looks for one or more fo's and will match fo and fofofofo.&lt;/p&gt;

&lt;p&gt;Capture groups can be used with quantifiers. &lt;code&gt;/\(foo\)*&lt;/code&gt; looks for zero or more foos, &lt;code&gt;/\(foo\)\{3,4}&lt;/code&gt; looks for 3 or 4 foo's (greedy), &lt;code&gt;/\(foo\)\{-3}&lt;/code&gt; looks for at least 3 foos (lazy).&lt;/p&gt;

&lt;p&gt;Let's combine what we've learned together. What kind of string do you think &lt;code&gt;/\(super\|duper\)\{1,2} yummy\( in my tummy\)\?&lt;/code&gt; matches? Think about it before you scroll down!&lt;/p&gt;

&lt;p&gt;.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;/p&gt;

&lt;p&gt;Ok, it will match these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;super yummy
superduper yummy
supersuper yummy
dupersuper yummy in my tummy
duper yummy in my tummy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you understand why? If you don't, look back at the previous sections and make sure that you understand how they work!&lt;/p&gt;

&lt;h3&gt;
  
  
  Backreferences &lt;code&gt;\n&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The capture group sure is very useful. It allows us to construct a pattern group that can be treated as a unit. It works great with quantifiers. But that's not all! Capture groups also work with backreferences.&lt;/p&gt;

&lt;p&gt;Back...what?&lt;/p&gt;

&lt;p&gt;A backreference lets you match the same text previously matched by a capturing group. You can spot a backreference when you see a backslash followed by a number: &lt;code&gt;\1&lt;/code&gt;, &lt;code&gt;\2&lt;/code&gt;, &lt;code&gt;\3&lt;/code&gt;, ... &lt;code&gt;\9&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, when you use &lt;code&gt;/\(foo\).*\1&lt;/code&gt; against:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;foobarfoo
foo bar foo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They would match the entire string. How?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first capture group &lt;code&gt;\(foo\)&lt;/code&gt; captures the string foo.&lt;/li&gt;
&lt;li&gt;Then we have zero or more of any character, &lt;code&gt;.*&lt;/code&gt;. This matches any string between the first foo and the last foo.&lt;/li&gt;
&lt;li&gt;Finally, &lt;code&gt;\1&lt;/code&gt; is a &lt;em&gt;backreference&lt;/em&gt; to the first capture group &lt;code&gt;\(foo\)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;/\(foo\).*\1&lt;/code&gt; is effectively the same as doing &lt;code&gt;/foo.*foo&lt;/code&gt;, but using &lt;code&gt;\1&lt;/code&gt; gives you far more flexibility as you'll see in a little bit.&lt;/p&gt;

&lt;p&gt;You can use multiple backreferences, like &lt;code&gt;/\(foo\)\(bar\).*\2\1\1&lt;/code&gt;. Here, the first capture group is foo and is referenced with &lt;code&gt;\1&lt;/code&gt;. The second capture group is bar and is referenced with &lt;code&gt;\2&lt;/code&gt;. The search above is effectively similar to &lt;code&gt;/foobar.*barfoofoo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Suppose that you want to match an opening and closing of an XML tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;foo&amp;gt;Hello&amp;lt;/foo&amp;gt;
&amp;lt;bar&amp;gt;Greetings&amp;lt;/bar&amp;gt;
&amp;lt;baz&amp;gt;Hello and greetings&amp;lt;/baz&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since XML opening tags need to match closing tags, we do not want it to match mismatched tags like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;foo&amp;gt;Nope&amp;lt;/bar&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use: &lt;code&gt;/&amp;lt;\([^&amp;gt;]*\)&amp;gt;.*&amp;lt;\/\1&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Whoa, that got messy and hard-to-read quickly. Let's break it down!&lt;/p&gt;

&lt;p&gt;Without escape characters, we actually have &lt;code&gt;&amp;lt;([^&amp;gt;]*)&amp;gt;.*&amp;lt;/\1&amp;gt;&lt;/code&gt;. A little simpler, but still a lot of symbols. Let's further break it apart into smaller sub-components.&lt;/p&gt;

&lt;p&gt;The pattern above is composed of three components: &lt;code&gt;&amp;lt;([^&amp;gt;]*)&amp;gt;&lt;/code&gt;, &lt;code&gt;.*&lt;/code&gt;, and &lt;code&gt;&amp;lt;/\1&amp;gt;&lt;/code&gt;. Let's investigate each starting from the first one.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;&amp;lt;([^&amp;gt;]*)&amp;gt;&lt;/code&gt;, the outermost &lt;code&gt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&lt;/code&gt; are literal angle brackets to match &lt;code&gt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&lt;/code&gt; in &lt;code&gt;&amp;lt;foo&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;bar&amp;gt;&lt;/code&gt;. The pair of parentheses are the first capture group. So what's that weird &lt;code&gt;[^&amp;gt;]*&lt;/code&gt; syntax inside? Recall that &lt;code&gt;[]&lt;/code&gt; is a character class and when you have a caret as the first character inside a &lt;code&gt;[]&lt;/code&gt;, it means negation. So &lt;code&gt;[^&amp;gt;]&lt;/code&gt; means a non-&lt;code&gt;&amp;gt;&lt;/code&gt; character. Finally you are looking for zero or more of this non-&lt;code&gt;&amp;gt;&lt;/code&gt; character. &lt;code&gt;[^&amp;gt;]*&lt;/code&gt; will match &lt;code&gt;foo&lt;/code&gt;, &lt;code&gt;bar&lt;/code&gt;, and &lt;code&gt;baz&lt;/code&gt;. Overall, this pattern effectively matches &lt;code&gt;&amp;lt;foo&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;bar&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;baz&amp;gt;&lt;/code&gt;, etc. The capture group captures the contents &lt;em&gt;inside&lt;/em&gt; the &lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt;. It captures and temporarily stores the texts &lt;code&gt;foo&lt;/code&gt;, &lt;code&gt;bar&lt;/code&gt;, and &lt;code&gt;baz&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second pattern, &lt;code&gt;.*&lt;/code&gt;, is a familiar one: zero or more of any character. This matches any text between the HTML tags.&lt;/p&gt;

&lt;p&gt;The third pattern is &lt;code&gt;&amp;lt;/\1&amp;gt;&lt;/code&gt;. The opening and closing angle brackets &lt;code&gt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&lt;/code&gt; match literal opening and closing HTML tags. &lt;code&gt;/&lt;/code&gt; matches a literal forward slash. Finally, &lt;code&gt;\1&lt;/code&gt; is a backreference to the first capture group, which as you recall was the content of the HTML tags: &lt;code&gt;foo&lt;/code&gt;, &lt;code&gt;bar&lt;/code&gt;, and &lt;code&gt;baz&lt;/code&gt;. Putting the capture group and backreference together, this means that your opening XML tag needs to match the closing XML tag. If the starting XML tag was &lt;code&gt;&amp;lt;foo&amp;gt;&lt;/code&gt;, then the closing HTML tag needs to be &lt;code&gt;&amp;lt;/foo&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Whole Match &lt;code&gt;\0&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;There is one more special backreference in Vim: &lt;code&gt;\0&lt;/code&gt;. It represents the whole regex match. So if your search pattern is &lt;code&gt;/foo&lt;/code&gt;, then &lt;code&gt;\0&lt;/code&gt; is foo. If your search pattern is &lt;code&gt;/foo[0-9]&lt;/code&gt; and the string is foo9, then &lt;code&gt;\0&lt;/code&gt; is foo9.&lt;/p&gt;

&lt;p&gt;This can come in handy in substitution.&lt;/p&gt;

&lt;p&gt;Suppose that you have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const one = 1;
const two = 2;
const ten = 10;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to enclose the numbers 1, 2, and 10 in double quotes, the fastest way to do it using the substitute command is &lt;code&gt;:%s/[0-9]\+/"\0"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I won't go over how the substitute command works because it is not the scope of this article, but I want to highlight the patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[0-9]\+&lt;/code&gt;, matches one or more digits (therefore it matches 1, 2, and 10). &lt;/li&gt;
&lt;li&gt;The new substitute pattern, &lt;code&gt;"\0"&lt;/code&gt; efficiently encloses all the matches with double-quotes. In the first line, &lt;code&gt;\0&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt;. &lt;code&gt;"\0"&lt;/code&gt; is the same as &lt;code&gt;"1"&lt;/code&gt;. In the third line, &lt;code&gt;\0&lt;/code&gt; is 10. &lt;code&gt;"\0"&lt;/code&gt; then is the same as &lt;code&gt;"10"&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the way, &lt;code&gt;\0&lt;/code&gt; can also be aliased with &lt;code&gt;&amp;amp;&lt;/code&gt;. &lt;code&gt;:s/\d/"\0"/g&lt;/code&gt; is the same as &lt;code&gt;:s/\d/"&amp;amp;"/g&lt;/code&gt;. It is one less character to type, if you prefer &lt;code&gt;&amp;amp;&lt;/code&gt; over &lt;code&gt;\0&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-Capture Group &lt;code&gt;%( )&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;All capture groups come with the backreference feature. If you don't want the backreference capability, use &lt;code&gt;%()&lt;/code&gt; pattern to use a non-capture group instead of the regular capture group &lt;code&gt;()&lt;/code&gt;. So &lt;code&gt;/\%(foo\)\+&lt;/code&gt; still looks for one or more foo, but you won't be able to backreference it with &lt;code&gt;\1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So why would anyone want to not backreference it?&lt;/p&gt;

&lt;p&gt;Performance. Backreferencing comes at performance cost. If you don't store backreference, you get some performance boosts. However, in my experience, I never really noticed any difference. But it wouldn't hurt to know about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Atoms
&lt;/h2&gt;

&lt;p&gt;Earlier I mentioned about atoms. What on earth are atoms?&lt;/p&gt;

&lt;p&gt;In Vim regex, an atom is a unit match. Technically almost everything in this article can be considered as atoms. The &lt;code&gt;a&lt;/code&gt; in &lt;code&gt;/a&lt;/code&gt; is an atom. The &lt;code&gt;^&lt;/code&gt; in &lt;code&gt;/^hello&lt;/code&gt; is an atom. The &lt;code&gt;[0-9]&lt;/code&gt; in &lt;code&gt;/[0-9]&lt;/code&gt; (any single-digit integer) is an atom. The &lt;code&gt;what&lt;/code&gt; in &lt;code&gt;/\(what\)\+&lt;/code&gt; (group match) is an atom. An atom can be an individual character match, an anchor, or a group match.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zero-Width
&lt;/h2&gt;

&lt;p&gt;"Zero-width" is a regex term. It is also mentioned in Vim help a few times and earned its place as an entry (&lt;code&gt;:h /zero-width&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;So what is zero width? A zero-width pattern is a pattern that doesn't actually match any character. If I search for the letter a (&lt;code&gt;/a&lt;/code&gt;), it has a width of one. If I search for the letter a followed by any number (&lt;code&gt;/a[0-9]&lt;/code&gt;), it has a width of two. The regex engine looks for a literal letter a. Anchors are good examples of zero-width patterns. If I search for the letter a at the start of the line (&lt;code&gt;/^a&lt;/code&gt;), although the pattern &lt;code&gt;a&lt;/code&gt; looks for a literal match of the letter a, the caret &lt;code&gt;^&lt;/code&gt; does not match any character. This makes the caret anchor a zero-width pattern. It is there to specify location, not to match a character.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;^&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;\&amp;lt;&lt;/code&gt; and &lt;code&gt;\&amp;gt;&lt;/code&gt; are examples of zero-width patterns. There are other zero-width patterns that I haven't mentioned yet: look-arounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Look-Arounds
&lt;/h2&gt;

&lt;p&gt;So what are look-arounds and why do we need them?&lt;/p&gt;

&lt;p&gt;Look-arounds are useful when you have to search for a pattern relative to another pattern. If you need to search for foo &lt;em&gt;only&lt;/em&gt; when it is before bar, a look-around can help you.&lt;/p&gt;

&lt;p&gt;There are two types of look-arounds: look-aheads and look-behinds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Look-Aheads
&lt;/h3&gt;

&lt;p&gt;Vim's lookahead syntax is &lt;code&gt;\ze&lt;/code&gt;. Think of the e as "ending".&lt;/p&gt;

&lt;p&gt;To match a foo that is followed by a bar (foobar), you can search &lt;code&gt;/foo\zebar&lt;/code&gt;. The way I think about it is, &lt;code&gt;/foo&lt;/code&gt; searches and matches for foo. Then you tell Vim to end the match with &lt;code&gt;\ze&lt;/code&gt;. But the pattern doesn't stop there. The search continues. There's a bar after that. But you don't want bar to be part of the match. You're really searching for foobar (&lt;code&gt;/foobar&lt;/code&gt;). So up to &lt;code&gt;\ze&lt;/code&gt;, it will be searched and matched. After &lt;code&gt;\ze&lt;/code&gt;, it will still be searched, but won't be matched. Note that in this section, I am making a subtle distinction between a "match" and a "search". A search is a pattern that the regex engine looks out for. A match is what is being selected / highlighted. All searches are matches but not all matches are searches.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/foo\zebar&lt;/code&gt; matches &lt;code&gt;foobar&lt;/code&gt;, but not &lt;code&gt;foobaz&lt;/code&gt; or &lt;code&gt;foo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The look-ahead pattern has another form: &lt;code&gt;\@=&lt;/code&gt;. If you are familiar with the Perl regex, this is similar to the &lt;code&gt;(?=pattern)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When used in Vim, it matches the preceding atom. The syntax works differently from &lt;code&gt;\ze&lt;/code&gt;, but the idea is the same.&lt;/p&gt;

&lt;p&gt;To search for foo in foobar (but not in foobaz or foo), run &lt;code&gt;/foo\(bar\)\@=&lt;/code&gt;. Note that you are using a capture group on bar, &lt;code&gt;\(bar\)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the syntax is confusing, don't worry, you're not alone. It took me a while to grasp it when I started to learn about it.&lt;/p&gt;

&lt;p&gt;The best way to understand it is, whatever character or capture group that precedes &lt;code&gt;\@=&lt;/code&gt; won't be matched or highlighted, but it will still be used as a part of the search pattern. Think of it as a veil that covers it. &lt;code&gt;\(bar\)\@=&lt;/code&gt;. It takes a stretch of imagination, but I see &lt;code&gt;\@=&lt;/code&gt; as a magician, &lt;code&gt;@=&lt;/code&gt; is the head (looks like a duck magician) and &lt;code&gt;\&lt;/code&gt; is his left hand. &lt;code&gt;\(bar\)&lt;/code&gt; is a veil containing the word "bar". He is covering it so it won't be highlighted. So &lt;code&gt;/foo\(bar\)\@=&lt;/code&gt; to me is like a giant text that spells "foobar", whereas a duck-magician person comes and covers up the "bar" part so it won't be visible to the audience... sort-of kind-of... Well, anyway, let's go to the next look-around, look-behinds!&lt;/p&gt;

&lt;h3&gt;
  
  
  Look-Behinds
&lt;/h3&gt;

&lt;p&gt;Look-behinds are principally similar to look-aheads, except they work backwards.&lt;/p&gt;

&lt;p&gt;In Vim, you can use &lt;code&gt;\zs&lt;/code&gt;. Think of the s as "start". If you want to match bar but only if it is followed by foo (foobar), do &lt;code&gt;/foo\zsbar&lt;/code&gt;. Again, the search pattern is technically &lt;code&gt;/foobar&lt;/code&gt;. However, the matching only start after &lt;code&gt;\zs&lt;/code&gt;, hence only bar is highlighted while foo is not.&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;\ze&lt;/code&gt; and &lt;code&gt;\zs&lt;/code&gt; are Vim inventions. But they both have regex look-ahead and look-behind syntax counterparts. Just like &lt;code&gt;\ze&lt;/code&gt; has a &lt;code&gt;\@=&lt;/code&gt; regex counterpart, &lt;code&gt;\zs&lt;/code&gt; also has a regex counterpart and it is &lt;code&gt;\@&amp;lt;=&lt;/code&gt; (it's like &lt;code&gt;\@=&lt;/code&gt;, except now it also has an arrow pointing back). The way it works, is that the atom that precedes it won't be matched (highlighted), although it will still be used as a part of the search pattern.&lt;/p&gt;

&lt;p&gt;To search for bar in foobar, use &lt;code&gt;/\(foo\)\@&amp;lt;=bar&lt;/code&gt;. To search for baz in foobaz, use &lt;code&gt;/\(foo\)\@&amp;lt;=baz&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the whole look-behind syntax pattern is confusing, I find the duck-magician imagery helps. &lt;code&gt;\(foo\)\@&amp;lt;=&lt;/code&gt; is our pattern. &lt;code&gt;@&amp;lt;=&lt;/code&gt; looks like a duck magician that shoots a beam. &lt;code&gt;\&lt;/code&gt; is his left hand. &lt;code&gt;\(foo\)&lt;/code&gt; is the veil that covers up the word foo. Again, whatever word/pattern that the magician veils will be hidden (not highlighted). So I imagine &lt;code&gt;\(foo\)\@&amp;lt;=bar&lt;/code&gt; like a giant "foobar" text and this duck-magician guy veils up the word foo so it won't be visible to the audience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Look-Ahead and Look-Behind
&lt;/h2&gt;

&lt;p&gt;You can definitely use both look-aheads and look-behinds in a pattern.&lt;/p&gt;

&lt;p&gt;If you need to match and highlight the bar only if it comes after foo and before baz (foobarbaz), not in bazbarfoo, foobar, or barbaz, use &lt;code&gt;/foo\zsbar\zebaz&lt;/code&gt;. Alternatively, you can also use &lt;code&gt;/\(foo\)\@&amp;lt;=bar\(baz\)\@=&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Negative Look-Aheads
&lt;/h3&gt;

&lt;p&gt;Negative look-aheads are the negative version of the look-aheads. The syntax is &lt;code&gt;\@!&lt;/code&gt; (as opposed to &lt;code&gt;\@=&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;Negative look-aheads search for a match NOT followed by the given pattern. To match foo &lt;em&gt;not&lt;/em&gt; followed by baz, run &lt;code&gt;/foo\(baz\)\@!&lt;/code&gt;. This will match foo and foobar, not foobaz.&lt;/p&gt;

&lt;h3&gt;
  
  
  Negative Look-Behinds
&lt;/h3&gt;

&lt;p&gt;There are also negative look-behinds. The syntax is &lt;code&gt;\@&amp;lt;!&lt;/code&gt; (as opposed to &lt;code&gt;\@&amp;lt;=&lt;/code&gt;). It finds a match NOT preceded by the pattern.&lt;/p&gt;

&lt;p&gt;To match bar not preceded by foo, run &lt;code&gt;/\(foo\)\@&amp;lt;!bar&lt;/code&gt;. This will match bazbar and bar, not foobar.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Vim regex
&lt;/h2&gt;

&lt;p&gt;The following are patterns exclusive in Vim. They are not available in most regex engines outside of Vim.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional Match &lt;code&gt;\%[ ]&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You can search for optional, sequential matches with the &lt;code&gt;\%[]&lt;/code&gt; pattern. It will match if the string contains, sequentially, any of the characters inside the square brackets.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/do%[nut]&lt;/code&gt; will match either &lt;code&gt;do&lt;/code&gt;, &lt;code&gt;don&lt;/code&gt;, &lt;code&gt;donu&lt;/code&gt;, and &lt;code&gt;donut&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple Lines &lt;code&gt;\_x&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Sometimes you need to search for patterns that may or may not be separated by newlines and/or whitespaces.&lt;/p&gt;

&lt;p&gt;If you need to match the chocolate donut string, one separated by a whitespace and another separated by a newline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chocolate donut

chocolate
donut
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can search with &lt;code&gt;/chocolate\_sdonut&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Recall that &lt;code&gt;\s&lt;/code&gt; is a special character for a whitespace character. By adding an underscore, &lt;code&gt;\_s&lt;/code&gt; now also includes a newline.&lt;/p&gt;

&lt;p&gt;So if you want to match:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chocolate donut

chocolatedonut

chocolate
donut

chocolate



donut
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use zero-or-more quantifier (&lt;code&gt;*&lt;/code&gt;), &lt;code&gt;/chocolate\_s*donut&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start and End of File &lt;code&gt;\%^ \%$&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Sometimes you need to search for a pattern at the start of the file. You can use the &lt;code&gt;\%^&lt;/code&gt; pattern. If you need to search for foo that is at the start of the file, use &lt;code&gt;/\%^foo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To search for a pattern at the end of the file, use &lt;code&gt;\%$&lt;/code&gt;. If you need to search for foo at the end of the file, use &lt;code&gt;/foo\%$&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start Within Visual Area &lt;code&gt;\%V&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Vim has a Visual mode (&lt;code&gt;v&lt;/code&gt;, &lt;code&gt;V&lt;/code&gt;, or &lt;code&gt;Ctrl-V&lt;/code&gt;) that allows you to highlight a certain area of text. I assume that you know what the visual mode is, if not, check out &lt;code&gt;:h visual-mode&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When you are currently highlighting a visual area, you can search for a pattern &lt;em&gt;within&lt;/em&gt; that visual area with &lt;code&gt;\%V&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you have the text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;barfoobazfoobarfoobazfoobarfoobazfoo

foobarfoobazfoobarfoobazfoobarfoobaz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While you are currently Visually highlighting the first line, you can search for foo within the visual highlight if you do &lt;code&gt;/\%Vfoo&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Magic and Very Magic &lt;code&gt;\v \m&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Earlier I mentioned about &lt;code&gt;\v&lt;/code&gt;, &lt;code&gt;\V&lt;/code&gt;, &lt;code&gt;\m&lt;/code&gt;, and &lt;code&gt;\M&lt;/code&gt;. Some regex syntaxes require them to be escaped for them to be treated as special characters.&lt;/p&gt;

&lt;p&gt;For example, to match one or more foo, normally you would do &lt;code&gt;/\(foo\)\+&lt;/code&gt;. Note that the group match &lt;code&gt;()&lt;/code&gt; and the one-or-more quantifier &lt;code&gt;+&lt;/code&gt; are escaped.&lt;/p&gt;

&lt;p&gt;If you don't want to escape them, you can use &lt;code&gt;\v&lt;/code&gt;. The &lt;code&gt;v&lt;/code&gt; stands for "very magic". Your search would look like this: &lt;code&gt;/\v(foo)+&lt;/code&gt;. Vim treats &lt;code&gt;()&lt;/code&gt; and &lt;code&gt;+&lt;/code&gt; as a special character instead of treating them as literal parentheses and plus signs.&lt;/p&gt;

&lt;p&gt;So how do you know which characters no longer need to be escaped and which characters still need to be escaped? The rule of thumb is, all characters except for word characters (digits 0-9, lowercase alphabets a-z, uppercase alphabets A-Z, and underscore _) are treated as special characters. As you've seen earlier, &lt;code&gt;()&lt;/code&gt; and &lt;code&gt;+&lt;/code&gt; are not word characters, so under very magic, they are treated as special characters. Also, special characters like &lt;code&gt;\d&lt;/code&gt; (digits) and &lt;code&gt;\l&lt;/code&gt; (lowercase alphabets) still need to be escaped.&lt;/p&gt;

&lt;p&gt;Likewise, in very magic mode, since it automatically treats non-word characters as special characters, previously literal characters would need to be escaped if you want to match them literally. So if you need to match a literal parentheses while under very magic mode, like &lt;code&gt;(foo)&lt;/code&gt;, then you'd have to escape it: &lt;code&gt;/\v\(foo\)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;"Very magic" has a sibling, "magic". You actually have been acquainted with this magic mode. How so? Because Vim by default uses magic mode! If you run &lt;code&gt;:set magic?&lt;/code&gt;, it will return &lt;code&gt;magic&lt;/code&gt;. Everything that you've used so far is done under magic mode.&lt;/p&gt;

&lt;p&gt;Vim also has two more modes: "no magic" (&lt;code&gt;\M&lt;/code&gt;) and "no very magic" (&lt;code&gt;\V&lt;/code&gt;). I won't cover them here because I personally think their usage is limited in everyday editing (I could be mistaken). But if you're curious, check out &lt;code&gt;:h /\V&lt;/code&gt; and &lt;code&gt;:h /\M&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I think this is a good place to stop. &lt;/p&gt;

&lt;p&gt;I hope that you gained valuable insight from this guide. Regex is a lot of fun once you know how to use it. It is an invaluable skill for any programmer. You don't need to master it, you just need to be good enough. Most popular programming languages employ regex to a certain extent. By learning regex in the Vim domain, you will inevitably know how to use it anywhere else. You will also be able to find and edit things much faster. Finally, it simply looks so darn cool.&lt;/p&gt;

&lt;p&gt;Take the time reading this. No rush. Make it into your muscle memory. Understanding beats superficial knowledge. Test your knowledge. Have fun with it!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I am already planning to write more about regex in the future, so stay tuned!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vim</category>
      <category>neovim</category>
      <category>regex</category>
      <category>search</category>
    </item>
    <item>
      <title>Vimgrep Tips and Tricks</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Tue, 04 Jan 2022 16:16:12 +0000</pubDate>
      <link>https://dev.to/iggredible/vimgrep-tips-and-tricks-54pl</link>
      <guid>https://dev.to/iggredible/vimgrep-tips-and-tricks-54pl</guid>
      <description>&lt;p&gt;When I started using Vim, I wished that Vim had a powerful in-file search feature that other popular IDEs / editors have. How could I search for the files that contain the string "echo"? How could I search for only the &lt;code&gt;.js&lt;/code&gt; files containing the string "const"?&lt;/p&gt;

&lt;p&gt;It turns out that Vim &lt;em&gt;does&lt;/em&gt; come with a powerful in-file search right out of the box.&lt;/p&gt;

&lt;p&gt;There are two main in-file searches in Vim: &lt;code&gt;:grep&lt;/code&gt; and &lt;code&gt;:vimgrep&lt;/code&gt;. The former uses an external grep command and the latter is built into Vim. This article will cover how to use the &lt;code&gt;:vimgrep&lt;/code&gt; command. Maybe in the future I will write about &lt;code&gt;:grep&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Learn Vimgrep
&lt;/h2&gt;

&lt;p&gt;The ability to perform complex searches quickly can boost your productivity.&lt;/p&gt;

&lt;p&gt;It is true that the Vim ecosystem today contains many useful plugins, some of them are search-related plugins like ctrlp, denite, and fzf.vim. These plugins are convenient and powerful, so why bother learning vimgrep?&lt;/p&gt;

&lt;p&gt;Just because it is old doesn't mean it is no good. There are a few advantages of learning vimgrep.&lt;/p&gt;

&lt;p&gt;First, the &lt;code&gt;:vimgrep&lt;/code&gt; command is built into Vim, so you don't have to worry about installing dependencies (and all the issues that might come with it). If you ever had to use vanilla Vim (ex: when you're in an SSH, or using someone else's computer, or in your mobile phone, etc), you can be sure that &lt;code&gt;:vimgrep&lt;/code&gt; will always be there.&lt;/p&gt;

&lt;p&gt;Second, vimgrep uses Vim's built-in regex engine (remember &lt;code&gt;'verymagic'&lt;/code&gt;? :D). This may sound like a con to some people, but to me, this is a huge pro. Using the same, consistent regex engine as Vim itself means there is zero friction between performing a Vim search (&lt;code&gt;/&lt;/code&gt;) and using &lt;code&gt;:vimgrep&lt;/code&gt;. Your brain won't have to switch to a different mode. The less you have to use your brain for editing, the more you can use it for the more fun stuff!&lt;/p&gt;

&lt;p&gt;Vimgrep has some downsides. The biggest one is that because it loads all the search results into memory,  if you have a large search result, it can slow down Vim. However, if you're working on a small / medium project, it is fast enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;

&lt;p&gt;Did you know that &lt;code&gt;:vimgrep&lt;/code&gt; shorthand is &lt;code&gt;:vim&lt;/code&gt;? That's right! A &lt;code&gt;:vim&lt;/code&gt; command inside Vim? How meta!&lt;/p&gt;

&lt;p&gt;Anyway, from now on, I'll refer to it as &lt;code&gt;:vim&lt;/code&gt; in the remainder of this article.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;:vim&lt;/code&gt; command follows the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /pattern/flag path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pattern&lt;/code&gt; is your search pattern.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;flag&lt;/code&gt; is a flag that you can pass to the search pattern.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;path&lt;/code&gt; is the file argument. You can pass multiple arguments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok, enough theory. You're here to learn some vimgrep, aren't you? Let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Searching for a String Inside a Particular File
&lt;/h2&gt;

&lt;p&gt;If you need to find the string "hello" inside all ruby files (.rb) inside app/controllers/ directory, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /hello/ app/controllers/**/*.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use the wildcards &lt;code&gt;*&lt;/code&gt; and double wildcards (globstar) &lt;code&gt;**&lt;/code&gt; a lot. The globstar, &lt;code&gt;**&lt;/code&gt;, searches recursively (it will match things like &lt;code&gt;app/controllers/dir/&lt;/code&gt;, &lt;code&gt;app/controllers/some/dir/&lt;/code&gt;, &lt;code&gt;app/controllers/file&lt;/code&gt;). The wildcard, &lt;code&gt;*&lt;/code&gt;, matches any string of any length. In this case, &lt;code&gt;*.rb&lt;/code&gt; matches any string that ends with &lt;code&gt;.rb&lt;/code&gt; (like &lt;code&gt;hello_controller.rb&lt;/code&gt;, &lt;code&gt;whatever.rb&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Btw, do not confuse the wildcards with the asterisk in regex. These two are different things. Regex asterisk pattern means zero or more of subsequent pattern (ex: &lt;code&gt;a*&lt;/code&gt; means zero or more "a"), while the wildcard does not require a subsequent pattern (&lt;code&gt;*&lt;/code&gt; means any string of any length).&lt;/p&gt;

&lt;p&gt;If you want to learn about globs, check out &lt;a href="https://mywiki.wooledge.org/glob" rel="noopener noreferrer"&gt;https://mywiki.wooledge.org/glob&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;:vim&lt;/code&gt; search displays the results in quickfix. If you aren't familiar with it, think of it as a set of items. In this case, it is a set of search results.&lt;/p&gt;

&lt;p&gt;After running the search command, run &lt;code&gt;:copen&lt;/code&gt; to open the quickfix window.&lt;/p&gt;

&lt;p&gt;If you're brand new to quickfix and aren't sure how to interact with it, here are some useful quickfix commands to get you started immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:copen        Open the quickfix window
:cclose       Close the quickfix window
:cnext        Go to the next location
:cprevious    Go to the previous location
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above list is by no means comprehensive. I suggest you learn about quickfix if you have time. It shouldn't take long. It's a useful skill to have in your Vim toolbelt. To learn more about quickfix, check out &lt;code&gt;:h quickfix&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Searching for a String Inside a Particular File Extension
&lt;/h2&gt;

&lt;p&gt;If you need to look for the string "echo" but only inside a &lt;code&gt;.sh&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/ **sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The globstar is very useful if you have a nested directory structure. Here, it will match both &lt;code&gt;./some_file.sh&lt;/code&gt; and &lt;code&gt;./some/really/long/dir/then/file.sh&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you only want to search in adjacent files (like &lt;code&gt;./hey.sh&lt;/code&gt; and &lt;code&gt;./some_file.sh&lt;/code&gt;, not &lt;code&gt;./some_dir/then/file.sh&lt;/code&gt;), instead of using the globstar, use a single wildcard: &lt;code&gt;*sh&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Searching for a String Inside Files Ending With Particular Extensions
&lt;/h2&gt;

&lt;p&gt;If you need to look for the string "echo" but only inside either a &lt;code&gt;.sh&lt;/code&gt; or a &lt;code&gt;.rb&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/ **{sh,rb}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Passing Multiple Files to Search Inside of
&lt;/h2&gt;

&lt;p&gt;Note that earlier I said that vimgrep accepts multiple file arguments. We have been passing it only one argument so far. However, we can totally pass it with more than one argument!&lt;/p&gt;

&lt;p&gt;If you need to look for the string "echo" inside either &lt;code&gt;.sh&lt;/code&gt; or &lt;code&gt;.rb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/ **sh **rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to look for the string "echo" inside of either &lt;code&gt;app/controllers/&lt;/code&gt; or &lt;code&gt;Rakefile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/ app/controllers/** Rakefile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You are not limited to only two file arguments, you can pass it as many arguments as you want. If you need to look for "echo" inside of either &lt;code&gt;app/controllers/&lt;/code&gt; directory, &lt;code&gt;Rakefile&lt;/code&gt; in the current directory, a &lt;code&gt;.json&lt;/code&gt; in the current directory, and a &lt;code&gt;sh&lt;/code&gt; file somewhere inside the &lt;code&gt;bin/&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/ app/controllers/** Rakefile *.json bin/**/*sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Finding Multiple Matches in the Same Line
&lt;/h2&gt;

&lt;p&gt;When we did &lt;code&gt;:vim /echo/ app/controllers/**&lt;/code&gt;, Vim returns the first match on each line.&lt;/p&gt;

&lt;p&gt;That means if we have a line that contains multiple keywords, like &lt;code&gt;echo "I like to echo echo echo"&lt;/code&gt;, the search result only displays one result instead of four. Using the pattern &lt;code&gt;/echo/&lt;/code&gt; only matches the first "echo" of that line.&lt;/p&gt;

&lt;p&gt;What if we want our search result to display all four of them?&lt;/p&gt;

&lt;p&gt;To catch all of the "echo" strings whenever it occurs multiple times in a line, we need to use the global flag (&lt;code&gt;g&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/g app/controllers/**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it will match all 4 "echo" occurrences in that line.&lt;/p&gt;

&lt;p&gt;I like the global flag and I use it in over 80% of my vimgrep searches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fuzzy Search a String Inside a Particular File
&lt;/h2&gt;

&lt;p&gt;Vimgrep is also capable of running a fuzzy search. We need to pass it a &lt;code&gt;f&lt;/code&gt; flag. To fuzzy search the string "echo" inside a &lt;code&gt;.sh&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/fg  **sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will fuzzy search all lines inside &lt;code&gt;**sh&lt;/code&gt; pattern for strings that &lt;em&gt;resemble&lt;/em&gt; "echo".&lt;/p&gt;

&lt;p&gt;So how does a vimgrep fuzzy search differ from a regular search?  In addition to matching a literal "echo" string, it would also match something like: &lt;code&gt;puts "Checking Homebrew..."&lt;/code&gt; because the "ec" in "Checking" and "Ho" in "Homebrew" constructs an "echo".&lt;/p&gt;

&lt;h2&gt;
  
  
  Search a Regular Expression Pattern in a Particular File
&lt;/h2&gt;

&lt;p&gt;Vimgrep accepts regular expression in your keyword search pattern. If want to search for either "echo" or "ecko" inside a &lt;code&gt;.sh&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /ec[hk]o/g **sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;[]&lt;/code&gt; in &lt;code&gt;[hk]&lt;/code&gt; is a character set syntax. In this case, it will match either "h" or "k" letters.&lt;/p&gt;

&lt;p&gt;If you need to search for a text surrounded by a single quote (like &lt;code&gt;'hello'&lt;/code&gt;, or &lt;code&gt;'foo'&lt;/code&gt;, or &lt;code&gt;'1234'&lt;/code&gt;) inside a &lt;code&gt;.sh&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /'[^']*'/g **sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is so much more you can do with regex. I won't cover how to use regex here  - but I want to show you that vimgrep works great with regex. If you want to learn more regex, I like to go to &lt;a href="https://www.regular-expressions.info/tutorial.html" rel="noopener noreferrer"&gt;https://www.regular-expressions.info/tutorial.html&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search for a String Inside a Particular Directory
&lt;/h2&gt;

&lt;p&gt;The double star (globstar) &lt;code&gt;**&lt;/code&gt; and the wildcard can be used at the start, in the middle, or at the end. It can also be used multiple times in a file pattern.&lt;/p&gt;

&lt;p&gt;If you want to search for "echo" inside the &lt;code&gt;/controllers/&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/g **/controllers/**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to search for "echo" inside the &lt;code&gt;/controllers/&lt;/code&gt; directory and inside a file that begins with "shipment" and end with "rb" (ex: &lt;code&gt;shipment_domestic.rb&lt;/code&gt;, &lt;code&gt;shipment_incoming.rb&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/g **/controllers/**/shipment*rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Search for a String Inside a Different Directory Than Your Current Working Directory
&lt;/h2&gt;

&lt;p&gt;Vimgrep searches in your working directory. But what if you need to search for the string "echo" inside a different directory? Easy. Just go to that other directory, then do the search!&lt;/p&gt;

&lt;p&gt;Vim has a &lt;code&gt;:cd&lt;/code&gt; command that changes the directory you are currently in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:cd somewhere/else
:vim /echo/g **js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're done, just &lt;code&gt;:cd&lt;/code&gt; back to your previous directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search in the Current File
&lt;/h2&gt;

&lt;p&gt;You can use Vim's filename expansion to shortcut your file pattern search. &lt;code&gt;%&lt;/code&gt; in Vim represents the current active buffer (the file you're currently on).&lt;/p&gt;

&lt;p&gt;If you need to search for "echo" the current file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/g %
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more: :help :_%&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Other Search Commands
&lt;/h2&gt;

&lt;p&gt;There are times when we need to perform a more advanced search. We may need to use other commands, like &lt;code&gt;find&lt;/code&gt;. No problem. To search for "echo" inside all files whose names start with "docker" using the &lt;code&gt;find&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/g `find . -type f -name 'docker*'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more on how &lt;code&gt;find&lt;/code&gt; works, check out &lt;code&gt;man find&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;git ls-files&lt;/code&gt; is another useful shell command for git-related searches. Assuming that you are inside a git repository, to search for "echo" inside of all modified files only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/g `git ls-files --modified`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more on how &lt;code&gt;git ls-files&lt;/code&gt; works, check out &lt;code&gt;man git-ls-files&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Searching in-Files Within Arglist
&lt;/h2&gt;

&lt;p&gt;The argument list (&lt;code&gt;arglist&lt;/code&gt;) is a Vim feature wherein Vim stores a list of files.&lt;/p&gt;

&lt;p&gt;The gist of arglist is, if you open Vim with multiple files (ex: &lt;code&gt;vim file1.js file2.rb file3.py&lt;/code&gt;), Vim collects these files inside the arglist. To see them, run &lt;code&gt;:args&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Arglist does not necessarily have to be populated on start too. You can create your own arglist while in Vim by running &lt;code&gt;:args file1.js file2.rb file3.py&lt;/code&gt;. To see them, run &lt;code&gt;:args&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you have a list of files, you can quickly go to the next or previous arglist files with &lt;code&gt;:next&lt;/code&gt; or &lt;code&gt;:prev&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ok, so arglist is a collection of files. So how does arglist relate to vimgrep?&lt;/p&gt;

&lt;p&gt;Usually when performing a task, you would gather all the relevant files first. Once you have all your relevant files in a collection, you can very quickly navigate between them. Arglist is a very useful feature for that.&lt;/p&gt;

&lt;p&gt;Vim has a number of file expansion shortcuts. Just like how &lt;code&gt;%&lt;/code&gt; represents the current buffer, Vim has one for arglist too! &lt;code&gt;##&lt;/code&gt; represents the current arglist.&lt;/p&gt;

&lt;p&gt;So if we want to search within our arglist files for the string "echo":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo/g ##
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why is this useful? I mean, it looks like I'm adding an extra step to the search process: first, I need to gather the files to an arglist and second, I run the vimgrep command. That's two steps altogether. Why can't I just run &lt;code&gt;:vim /echo/g file1.js file2.rb file3.py&lt;/code&gt; and be done with only one step?&lt;/p&gt;

&lt;p&gt;Speaking from experience, often I find myself needing to perform multiple keyword searches within the same set of files, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo1/g file1.js file2.rb file3.py
:vim /foo2/g file1.js file2.rb file3.py
:vim /bar3/g file1.js file2.rb file3.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I find it painful each time I have to re-type the same set of files. This is where arglist can save time!&lt;/p&gt;

&lt;p&gt;Why not collect an arglist first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:arglist file1.js file2.rb file3.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then reuse it in subsequent vimgrep searches? &lt;/p&gt;

&lt;p&gt;Now I can just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:vim /echo1/g ##
:vim /foo2/g ##
:vim /bar3/g ##
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to perform different keyword searches against the same set of files, arglist can save you time.&lt;/p&gt;

&lt;p&gt;If you're curious about how &lt;code&gt;##&lt;/code&gt; works, check out &lt;code&gt;:h :_##&lt;/code&gt;. If you want to learn more arglist, check out &lt;code&gt;:h :arglist&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quickly Get the Last Search Pattern
&lt;/h2&gt;

&lt;p&gt;Sometimes I need to search for a complicated pattern. Before I enter that in the &lt;code&gt;:vim&lt;/code&gt; command, I like to test it with search (&lt;code&gt;/&lt;/code&gt;) first.&lt;/p&gt;

&lt;p&gt;For example, if you want to search for a string surrounded by a single quote, while &lt;em&gt;excluding&lt;/em&gt; the single quotes, you could do &lt;code&gt;'\zs[^']*\ze'&lt;/code&gt;. But this pattern may not be intuitive at first. When using a semi-complicated pattern, I like to test if it does what I think it does, so before I run &lt;code&gt;:vim /'\zs[^']*\ze'/g **sh&lt;/code&gt;, I would usually do a quick search command &lt;code&gt;/'\zs[^']*\ze'&lt;/code&gt; to test if it works.&lt;/p&gt;

&lt;p&gt;Once I confirm that the pattern meets my expectations, I would then enter it to the &lt;code&gt;:vim&lt;/code&gt; command. But do I really want to re-type &lt;code&gt;'\zs[^']*\ze'&lt;/code&gt; all over again? I mean, look at those brackets and single quotes and backslashes... I could easily mistype them when I am typing them on the &lt;code&gt;:vim&lt;/code&gt; command. &lt;/p&gt;

&lt;p&gt;Moreover, what if my pattern is a lot longer, like &lt;code&gt;\(["']\)\(\%(\1\@!.\)*\)\1&lt;/code&gt;? Oh boy, look at those backslashes, parentheses, and brackets... what are the chances of me retyping that correctly in the first try?&lt;/p&gt;

&lt;p&gt;Luckily, there is a trick that allows you to "paste" your most recently used search command. After typing &lt;code&gt;:vim /&lt;/code&gt;, type &lt;code&gt;Ctrl-r&lt;/code&gt; then &lt;code&gt;/&lt;/code&gt;. The secret is that &lt;code&gt;Ctrl-r&lt;/code&gt; when used in insert mode (or in this case, command-line mode) invokes the Vim registers. Here we ask Vim for the value from the search register (&lt;code&gt;/&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;This is where the &lt;code&gt;:vim&lt;/code&gt; command has an advantage over the regular &lt;code&gt;:grep&lt;/code&gt; command. The search command (&lt;code&gt;/&lt;/code&gt;) uses Vim regex flavor, which &lt;code&gt;:vim&lt;/code&gt; also uses. But the &lt;code&gt;:grep&lt;/code&gt; command doesn't use Vim regex flavor (it uses whatever grep external command you set up; for more, check out &lt;code&gt;:h 'grepprg'&lt;/code&gt;). Using the same regex flavor for &lt;code&gt;/&lt;/code&gt; then &lt;code&gt;:vim&lt;/code&gt; command means zero friction and a buttery-smooth search experience!&lt;/p&gt;

&lt;p&gt;Albeit, performance-wise, &lt;code&gt;:grep&lt;/code&gt; is faster, but if speed is not a big issue (it isn't really noticeable in most cases), &lt;code&gt;:vim&lt;/code&gt; offers a better user experience.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This is a good place to stop. You've learned a number of cool tricks for the &lt;code&gt;:vim&lt;/code&gt; program. I wish I knew half of these tricks when I started Vim. Don't just speed read this and leave. Take your time going through each command. Go through each one of them - tweak it, break it, and understand it. Make it your goal to be able to perform them without much mental effort. This is by no means a comprehensive list of &lt;code&gt;:vimgrep&lt;/code&gt; tips and tricks. There are so many other combinations that you can do with vimgrep. Don't stop learning!&lt;/p&gt;

&lt;p&gt;Vim is a great editor even without plugins. Vim is a universal program that can be found/installed in practically any machine. There may be times when you can't use search plugins. This will be the time where your vanilla Vim knowledge will shine. Don't let the lack of plugins cripple your Vim productivity. Learn to use Vim with and without plugins. Learn &lt;code&gt;:vimgrep&lt;/code&gt; and also learn &lt;code&gt;:grep&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Happy Vimming!&lt;/p&gt;

</description>
      <category>vim</category>
      <category>grep</category>
      <category>vimgrep</category>
      <category>tips</category>
    </item>
    <item>
      <title>The Easy Way to Copy Text in Tmux</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Mon, 22 Nov 2021 15:34:08 +0000</pubDate>
      <link>https://dev.to/iggredible/the-easy-way-to-copy-text-in-tmux-319g</link>
      <guid>https://dev.to/iggredible/the-easy-way-to-copy-text-in-tmux-319g</guid>
      <description>&lt;h2&gt;
  
  
  How to Easily Copy Texts in Tmux
&lt;/h2&gt;

&lt;p&gt;If you've used tmux for a while, you will realize that highlighting a text with a mouse in tmux to copy them is a painful experience. That's because it's now how tmux is designed. Having used text editing softwares like Microsoft Word / Google Docs and to some extent, Atom / VSCode / IntelliJ, it may feel natural to grab your mouse, highlight the body of texts, and press Ctrl + C. &lt;/p&gt;

&lt;p&gt;Not so with tmux. Copying with tmux is more like copying in Vim, where it's best done with a keyboard rather than a mouse. This is done in tmux &lt;em&gt;copy mode&lt;/em&gt;.  In this article, I will show you how to utilize tmux copy mode to easily copy text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vi Copy Mode
&lt;/h3&gt;

&lt;p&gt;Tmux is similar to vim in many ways. One of them is that they are modal programs. What that means is that to accomplish a specific task, you need to switch to a mode that's optimized for that task. In Vim, we have a normal mode where you can move around with your keyboard. Vim's normal mode is designed for moving (and to a certain extent, modifying) within your file. If you need to insert texts, you need to switch to vim insert mode.&lt;/p&gt;

&lt;p&gt;To navigate your terminal history and to copy text, you need to switch to tmux copy mode (technically it is vi-copy-mode, but to keep it simple, let's call it copy mode).&lt;/p&gt;

&lt;p&gt;So what exactly is a copy mode? &lt;/p&gt;

&lt;p&gt;If you try to copy a text from a tmux window with your mouse, you may have seen a warning saying that you can't simply copy the text. The correct way to copy a text from tmux is to first switch to copy mode, then copy it, then paste it.&lt;/p&gt;

&lt;p&gt;To enable this copy mode, in you tmux config file, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setw -g mode-keys vi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then save and source the tmux config. This will enable vi &lt;code&gt;mode-keys&lt;/code&gt;. If you are unsure about tmux config, check out my previous article on tmux config.&lt;/p&gt;

&lt;p&gt;To enter the copy mode, use &lt;code&gt;Ctrl + [&lt;/code&gt;. You should be able to see a yellow visual indicator on the top right of your tmux window. With this, you can now move around using vim navigation keys.&lt;/p&gt;

&lt;p&gt;Although tmux copy mode doesn't translate to 100% vim navigation keys - overall they are good enough to feel natural. Some navigation keys that you can use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;h / j / k / l&lt;/code&gt; to move left/down/up/right&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;w / W / e / E / b / B&lt;/code&gt; to move forward to the start / to the end / backward a word or WORD&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{ / }&lt;/code&gt; to move backward / forward a paragraph&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + e / d / f&lt;/code&gt; to scroll down a line / half screen / whole screen&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + y / u / b&lt;/code&gt; to scroll up a line / half screen / whole screen&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/ / ?&lt;/code&gt; to search forward / backward&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;n / N&lt;/code&gt; to repeat the previous search forward / backward&lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a lot more navigation keys. Check out inside &lt;code&gt;man tmux&lt;/code&gt; and search for the &lt;code&gt;mode-keys&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;In this mode, you can move around the terminal like you move around vim. To exit this mode, press &lt;code&gt;q&lt;/code&gt; or &lt;code&gt;Enter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To begin highlighting, press &lt;code&gt;Space&lt;/code&gt;. Note that your cursor will highlight the letter under it. It will expand the highlight as you move around your cursor. &lt;/p&gt;

&lt;p&gt;Once you highlight all the text you want to copy, press &lt;code&gt;Enter&lt;/code&gt;. You should automatically exit the copy mode. The text that you copied are stored inside a tmux buffer. It is an allocated space in the memory where tmux temporarily stores data.&lt;/p&gt;

&lt;p&gt;To paste from the tmux buffer, press &lt;code&gt;Ctrl + ]&lt;/code&gt;. Woot! Congratulations, you've copied a text with tmux - stress-free!&lt;/p&gt;

&lt;p&gt;To  recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;setw -g mode-keys vi&lt;/code&gt; in your tmux config&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + [&lt;/code&gt; to enter tmux vi copy mode&lt;/li&gt;
&lt;li&gt;Move around with vim navigation keys&lt;/li&gt;
&lt;li&gt;Begin highlight with &lt;code&gt;Space&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy with &lt;code&gt;Enter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Paste with &lt;code&gt;Ctrl + ]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Making Copy-Paste More Intuitive
&lt;/h3&gt;

&lt;p&gt;I find a number of the copy-pasting keys unintuitive. Let's modify them to mimic vim keybindings.&lt;/p&gt;

&lt;p&gt;Recall that vim has a visual mode (&lt;code&gt;v&lt;/code&gt;) that allows you to highlight a body of text. You can also "yank" text with &lt;code&gt;y&lt;/code&gt;. Finally, you can paste the yanked text with &lt;code&gt;p&lt;/code&gt; or &lt;code&gt;P&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's use similar keymaps. Add these lines in the tmux config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bind -T copy-mode-vi v send -X begin-selection
bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "pbcopy"
bind P paste-buffer
bind -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "pbcopy"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line, &lt;code&gt;bind -T copy-mode-vi v send -X begin-selection&lt;/code&gt;, lets you begin selection (highlight) by pressing &lt;code&gt;v&lt;/code&gt; while in copy mode (&lt;code&gt;copy-mode-vi&lt;/code&gt;). The second line allows you to yank the text with &lt;code&gt;y&lt;/code&gt;. The third line allows us to paste from the tmux buffer (where our text is saved) with &lt;code&gt;Ctrl + P&lt;/code&gt;. The last line is a bonus. It lets you copy the text that you highlight with the mouse (note that it has the same effect as the second line).&lt;/p&gt;

&lt;p&gt;Notice that on the second and fourth line, I use &lt;code&gt;pbcopy&lt;/code&gt;. I need to use it to pipe the copied text into the clipboard on my Mac. If you're on linux, omit &lt;code&gt;pbcopy&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bind-key -T copy-mode-vi y send -X copy-selection-and-cancel
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As always, don't forget to save and source the config file. With this new setting, the workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enter the copy-mode with &lt;code&gt;Ctrl + [&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Position yourself to the start of the text you want to copy with vim navigation &lt;/li&gt;
&lt;li&gt;Start highlight with &lt;code&gt;v&lt;/code&gt; (similar to vim visual mode)&lt;/li&gt;
&lt;li&gt;Yank the highlighted text with &lt;code&gt;y&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Paste with &lt;code&gt;Prefix + P&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I use an uppercase P instead of lowercase p because &lt;code&gt;Prefix + p&lt;/code&gt; is how tmux goes to the previous window (recall: &lt;code&gt;Prefix + p&lt;/code&gt; to go to the previous window and &lt;code&gt;Prefix + n&lt;/code&gt; to go to the next window. If you are not familiar with this, I'd highly recommend you to read my first tmux article).&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking Advantage of the Vi Mode
&lt;/h2&gt;

&lt;p&gt;The vi-copy-mode is not only useful for copying texts. You can use it to quickly search through your terminal.&lt;/p&gt;

&lt;p&gt;For example, in the terminal, if you are looking for a text, you would press &lt;code&gt;Cmd + f&lt;/code&gt; (or &lt;code&gt;Ctrl + f&lt;/code&gt;) and type in the string that you want to search. This method has limitations. First, you can only search for that exact string (what if instead of searching for the string "mux", you want to search for "mux", "mix", and "max" simultaneously?). Second, if you have multiple panes in a window, this method will search for the text in &lt;em&gt;all&lt;/em&gt; panes (what if you need to constrain your search only to the current pane?). Third, it is limited to what is currently displayed on tmux at the moment. Due to the nature of tmux's scrolling, it can't search for texts that are above the displayed window.&lt;/p&gt;

&lt;p&gt;A better way to search is to leverage the vi-copy-mode. Recall that in Vim, you can search forward with &lt;code&gt;/&lt;/code&gt; and backward with &lt;code&gt;?&lt;/code&gt;. With vi mode, you can do that too. &lt;/p&gt;

&lt;p&gt;Suppose that I need to search for "redis_1" in my terminal. Here's how I would do it.&lt;/p&gt;

&lt;p&gt;From inside a tmux session, enter the vi mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + [
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then search backward with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;? + KEYWORD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, KEYWORD is "redis_1". I find myself using &lt;code&gt;?&lt;/code&gt; much more than &lt;code&gt;/&lt;/code&gt;, because 80% of the time I would be searching backwards. Tmux should highlight all "redis_1" texts. To keep jumping to the subsequent or preceding matches, use either &lt;code&gt;n&lt;/code&gt; or &lt;code&gt;N&lt;/code&gt;. Sweet!&lt;/p&gt;

&lt;p&gt;But wait, there's more! Just like you can use regular expressions in Vim while searching, you can with tmux too!&lt;/p&gt;

&lt;p&gt;Suppose that I want to search for words like "redis_1" OR "node_1", OR "rails_1", I can search for all of them with &lt;code&gt;[a-z]+_1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;? + [a-z]+_1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regex breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[a-z]&lt;/code&gt; is the lowercase a-z&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+&lt;/code&gt; means one or more subsequent characters (which was a-z). &lt;code&gt;[a-z]+&lt;/code&gt; means one or more any lowercase alphabet character&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_1&lt;/code&gt; is a literal underscore followed by a literal one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will match "redis_1", "node_1", and "rails_1" (it will also match strings like "java_1", "sidekiq_1", etc.&lt;/p&gt;

&lt;p&gt;If you want to match ONLY "redis_1", "node_1", or "rails_1", you can use a group match:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;? + (redis|node|rails)_1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty cool! I won't go through regex here because it's outside the scope of this article. The point is, searching in tmux using vi mode is a powerful tool especially if you're proficient with regex (even if you don't, you can get pretty far with just a little regex knowledge).&lt;/p&gt;

&lt;h2&gt;
  
  
  Emacs Copy Mode
&lt;/h2&gt;

&lt;p&gt;If you look at the &lt;code&gt;man tmux&lt;/code&gt; page, in addition to the vi-copy-mode, tmux also has an emacs-copy mode. It is similar to vi-copy-mode, but instead of using vi key bindings, it uses emacs key bindings.&lt;/p&gt;

&lt;p&gt;If you're more of an emacs guy (don't worry, we can still be friends) and want to set it up to use emacs keybindings instead, check out inside the &lt;code&gt;man tmux&lt;/code&gt; page under &lt;code&gt;mode-keys&lt;/code&gt; section. There you will find instructions on how to set it up, including a list of keymaps.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In this article, we learned how to leverage the copy mode to make it easier to copy-paste from your tmux terminal. We also learned how to configure it to mimic vim copy-pasting behavior. This copy mode can be leveraged to be an effective search tool.&lt;/p&gt;

&lt;p&gt;Tmux is a powerful tool. It complements with vim well. To make it even more powerful, you can configure it to behave like vim behaves.&lt;/p&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

</description>
      <category>tmux</category>
      <category>vim</category>
      <category>vi</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Tmux Tutorial for Beginners</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Wed, 10 Nov 2021 16:33:24 +0000</pubDate>
      <link>https://dev.to/iggredible/tmux-tutorial-for-beginners-5c52</link>
      <guid>https://dev.to/iggredible/tmux-tutorial-for-beginners-5c52</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Tmux is life. That is not an exaggeration. Once you started using Tmux, you will ask yourself why you have not used it until now.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Tmux Is
&lt;/h3&gt;

&lt;p&gt;According to &lt;code&gt;man tmux&lt;/code&gt;, Tmux stands for "Terminal MUltipleXer". Before you get perPLEXed by the phrase Terminal MUltipleXer, I'll explain what it means.&lt;/p&gt;

&lt;p&gt;A terminal multiplexer lets you to leave a terminal in the middle of a process and return to it seamlessly. For example, suppose that you are running a &lt;code&gt;rails server&lt;/code&gt;, &lt;code&gt;vim&lt;/code&gt; editor, and a &lt;code&gt;mysql&lt;/code&gt; console in the middle of a rails workflow. Then someone asks you to debug a completely different node project. Without tmux, I would probably stop the rails server, close vim, and exit the mysql server before starting the node-project task. This context switch causes a grinding halt in your flow. What if instead of killing those rails-related processes, you can "put them aside" (while they're still running), run whatever processes you need to complete your node task, then return to your original rails-project task as if you never left? That would be nice, wouldn't it? Tmux lets you do just that!&lt;/p&gt;

&lt;p&gt;To be fair, you could argue that you could just open more tabs for node tasks instead of killing the previous rails processes. Although that would work, this could cause tab chaos. At some point, you'll start asking, "which of these 6 tabs did I just run the &lt;code&gt;jest&lt;/code&gt; test?" or "which of these two Vim tabs was my rails codebase?". When you start mixing tabs from completely unrelated tasks without clear boundaries, you can't tell which tab is for what. This also causes a grinding halt to your workflow. &lt;/p&gt;

&lt;p&gt;The terminal is the crux of my workflow. I need to organize my terminal. Imagine this: I can contain all my rails processes inside a session named "rails_project" and all my node processes in a session named "node_project". If I need to do node tasks, I'll leave rails_project and visit node_project session. When I'm done, I'll leave node_project and revisit rails_project. Easy!&lt;/p&gt;

&lt;p&gt;Tmux allows me to create any number of terminals from a single screen and group them. I can "detach" them and they will still continue running in the background. The best part? I can "attach" them at any time. Tmux is great for long-term running processes and local development.&lt;/p&gt;

&lt;p&gt;Don't you want to learn how to do that too?&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Do I Want to Use Tmux?
&lt;/h4&gt;

&lt;p&gt;Over time, the number of process dependencies you need to get a job done increases. Today, it is often not enough to have just two terminals: one for running &lt;code&gt;rails server&lt;/code&gt; and one for running &lt;code&gt;vim&lt;/code&gt; to accomplish your task. In reality, you probably need a &lt;code&gt;rails server&lt;/code&gt;, a &lt;code&gt;webpacker&lt;/code&gt;, a &lt;code&gt;sidekiq&lt;/code&gt;, a &lt;code&gt;redis&lt;/code&gt; instance, and a growing number of microservices to launch your app. In addition, you may need to have &lt;code&gt;mysql&lt;/code&gt; console and &lt;code&gt;rails console&lt;/code&gt; to see what's inside your app. You may even need a dedicated terminal to run your tests. Don't forget that SSH window to get the sql dump too! Even if you have docker-compose to host multiple services, if you need to debug them, you'll need multiple terminals to debug each service. My point is, a simple task today would require more than 10 different active processes! It makes it harder to switch context.&lt;/p&gt;

&lt;p&gt;Even if you don't need to switch context often, it is still useful to categorize your sub-workflows within your workflow. Maybe today you are focusing on writing tests, so you need to use vim and a free terminal to run your test code; they would need to fit inside a display. The next day, you may need to solve a data migration issue, so you need a vim editor, a mysql server to view your databases, and a rails console to check your models. Within a single project, you can still experience a grinding halt when trying to accomplish a different task.&lt;/p&gt;

&lt;p&gt;The point is, you need to reduce the frictions caused by context-switching in today's increasingly complex tasks. Tmux can help with that.&lt;/p&gt;

&lt;h4&gt;
  
  
  What to Expect From This Guide
&lt;/h4&gt;

&lt;p&gt;Ultimately, you decide whether you want to use tmux or not. You don't have to use tmux. There are alternatives like GNU Screen, Terminator, Byobu, etc. Check them out and you decide whether or not to use tmux.&lt;/p&gt;

&lt;p&gt;Personally, I think tmux is a better fit for my workflow. I am writing this guide to share what I understand about tmux. I hope that you will learn one or two useful things.&lt;/p&gt;

&lt;p&gt;Here is what you will learn in this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sessions&lt;/li&gt;
&lt;li&gt;Windows&lt;/li&gt;
&lt;li&gt;Panes&lt;/li&gt;
&lt;li&gt;Servers&lt;/li&gt;
&lt;li&gt;Basic configs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of this article, you will be faster than you would ever be without tmux. Hopefully you will learn enough to continue pursuing learning tmux on your own, just like the proverbs say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Teach a man tmux, you improve his productivity for a lifetime (someone, probably)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Please read this guide &lt;strong&gt;slowly&lt;/strong&gt;. It is tempting to speed-read through a book, call it done, and move on to the next book. To get the most out of this, take your time understanding each section. For every 5 minutes you spend reading, spend 15 minutes tinkering around with what you just read. Break things.&lt;/p&gt;

&lt;p&gt;With that said, let's learn some tmux!&lt;/p&gt;

&lt;h4&gt;
  
  
  Installation
&lt;/h4&gt;

&lt;p&gt;First, you need to install tmux if you haven't already. A good way to visit the &lt;a href="https://github.com/tmux/tmux/wiki/Installing" rel="noopener noreferrer"&gt;tmux repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am using a Mac, so for me, I just needed to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install tmux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool! Verify that it is installed. Run &lt;code&gt;which tmux&lt;/code&gt;. It should return with a path. Now that tmux is installed, let's learn tmux's cornerstone: sessions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tmux Sessions
&lt;/h3&gt;

&lt;p&gt;A tmux session is a collection of pseudo-terminals. Imagine running 10 different terminal processes, each doing different things. All these terminals are contained in a neat space that you can leave unattended and revisit at any time.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating a New Session
&lt;/h4&gt;

&lt;p&gt;Let's use it. Run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will launch a new tmux &lt;em&gt;session&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you're still unsure about the tmux session, don't worry. I initially had a hard time grasping the concept too. It would become much easier once I started getting immersed in it. So let's continue.&lt;/p&gt;

&lt;h4&gt;
  
  
  Attaching and Detaching a Session
&lt;/h4&gt;

&lt;p&gt;To exit a session, you need to *d*etach. Press:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hold up, what is a Prefix? I don't see any prefix key on my keyboard.&lt;/p&gt;

&lt;p&gt;The prefix key can be anything you want. Many tmux shortcuts require you to press a prefix key first. If you're a Vim user, it is similar to the concept of a leader key. Think of it like a key to signal tmux that you are executing a tmux command. By default, tmux uses &lt;code&gt;Ctrl + b&lt;/code&gt; as the Prefix key. From now, each time you see &lt;code&gt;Prefix&lt;/code&gt;, it means &lt;code&gt;Ctrl + b&lt;/code&gt; (hold Ctrl then press b). In this case, &lt;code&gt;Prefix + d&lt;/code&gt; means holding Ctrl, then press b, then release them, then quickly press the letter d. Later, you'll learn how to change the prefix key from &lt;code&gt;Ctrl + b&lt;/code&gt; to any key you want.&lt;/p&gt;

&lt;p&gt;If you do it correctly, you should be taken out of the tmux session back to the original terminal.&lt;/p&gt;

&lt;p&gt;When you're detaching from a session, any process running in that session is not terminated. It's still running. You just don't see it. Think of it like a background job.&lt;/p&gt;

&lt;p&gt;Let's stop and appreciate how awesome this is. On a regular terminal, if we close the tab, whatever process that we were running would be terminated immediately. If I had &lt;code&gt;rails server&lt;/code&gt; running and I close the tab, the rails server process would be killed. But if we detach from a session with &lt;code&gt;rails server&lt;/code&gt; running, the rails server is still there. You are hiding the current process so you can focus on a different one. Later when you're ready to resume, you can "unhide" the rails server session by attaching into it. &lt;/p&gt;

&lt;p&gt;To attach, from the terminal, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux attach
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aaannd you're back. Cool!&lt;/p&gt;

&lt;p&gt;The command line equivalent to detach (&lt;code&gt;Prefix + d&lt;/code&gt;) is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux detach
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Named Session
&lt;/h4&gt;

&lt;p&gt;With tmux, you can liberally generate as many sessions as you need. Right now we have only one session running. To generate more sessions, you first need to be on the regular terminal (not inside a session). This time though, let's give our session a name. It's around breakfast time as I type this, so let's name it "breakfast" session (you can give it any name you want :D). Type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux new -s breakfast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The alternative (verbose) command is &lt;code&gt;tmux new-session -s breakfast&lt;/code&gt;, but I like to keep it short. With that, you should be in the tmux breakfast session. Yum!&lt;/p&gt;

&lt;p&gt;While you're inside the breakfast session, recall that we also have the original session running. To see a list of sessions and travel between sessions, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's detach from whatever session you are in and go back to the regular terminal (you're not inside any session). We now have two detached sessions: the original session and the breakfast session. So how do we attach to a particular session from the terminal? Earlier we ran the &lt;code&gt;tmux attach&lt;/code&gt; to attach to the only available tmux session. Now that there are two sessions, we need to be more specific.&lt;/p&gt;

&lt;p&gt;First, if you're forgetful like me and already forgot the name of your sessions, you can list the name of all the sessions by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I want to attach to the breakfast session, run the attach command with &lt;code&gt;-t&lt;/code&gt; (target) followed by the session name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux attach -t breakfast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I'm back to the breakfast session. Tmux is smart enough that you can give it a partial string. So if I run &lt;code&gt;tmux attach -t b&lt;/code&gt;, as long as I don't have any session starting with b other than breakfast, tmux knows that I intend to go to breakfast.&lt;/p&gt;

&lt;p&gt;Think of sessions like terminal containers. Modern development usually requires you to launch multiple services and jobs just to get the app running. For example, maybe the app that you're working on requires a redis server, a rails server, two node services, and a background job. You can use a session to contain all of those processes. This makes your workflow manageable and identifiable. If you ever need to leave them to work on something else, no need to kill them, just detach it, do whatever else you need to do, and -re-attach.&lt;/p&gt;

&lt;h4&gt;
  
  
  Killing a Session
&lt;/h4&gt;

&lt;p&gt;Once you're done with the session task, you can kill that session.&lt;/p&gt;

&lt;p&gt;There are two ways to kill a session:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the terminal command to kill a session&lt;/li&gt;
&lt;li&gt;Close all the windows until there is no more&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll start with method 1. To kill the breakfast session, run this from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux kill-session -t breakfast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;kill-session&lt;/code&gt; command needs a target (&lt;code&gt;-t&lt;/code&gt;) and a session name that you want to kill. Note the &lt;code&gt;-t&lt;/code&gt; (target) argument is similar to the &lt;code&gt;attach -t&lt;/code&gt; command. In tmux, anytime you have multiple targets and you need to pinpoint a single abstraction (like a session name), you probably need to pass it a target (&lt;code&gt;-t&lt;/code&gt;) plus the target name.&lt;/p&gt;

&lt;p&gt;Anyway, running &lt;code&gt;tmux kill-session -t breakfast&lt;/code&gt; will effectively kill that session. Note: killing a session terminates all processes inside it - make sure that you save all your changes.&lt;/p&gt;

&lt;p&gt;The second method is to kill all the panes and windows inside a session until there is nothing left. We will go over panes and windows in a little bit. For now, just follow along. To kill a pane, press:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you do that to every single pane and window, upon closing the last pane in the last window in a session, the session is effectively killed.&lt;/p&gt;

&lt;p&gt;An alternative shortcut to &lt;code&gt;Prefix + x&lt;/code&gt; is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ctrl + d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does the same thing as &lt;code&gt;Prefix + x&lt;/code&gt;. Personally, I prefer &lt;code&gt;Ctrl + d&lt;/code&gt; because it only requires two keypresses as opposed to &lt;code&gt;Prefix + x&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tmux Sessions Conclusion
&lt;/h4&gt;

&lt;p&gt;We are done with tmux sessions. Let's recap what we learned!&lt;/p&gt;

&lt;p&gt;We learned that a session is like a container to a set of terminals. You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a session in tmux with &lt;code&gt;tmux new -s MY_SESSION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Detach from a session with &lt;code&gt;Prefix + d&lt;/code&gt; or &lt;code&gt;tmux detach&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;List sessions with &lt;code&gt;tmux ls&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Attach to a session with &lt;code&gt;tmux attach -t MY_SESSION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;List sessions and switch to a different session with &lt;code&gt;Prefix + s&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Kill a session with &lt;code&gt;tmux kill-session -t MY_SESSION&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Close a pane / window with either &lt;code&gt;Ctrl + d&lt;/code&gt; or &lt;code&gt;Prefix + x&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are new to tmux, let this soak in. Take time to internalize this. Practice, practice, practice. Don't rush to the next one. It's better to go at a slower pace but to retain more than go at full-speed but forget almost everything.&lt;/p&gt;

&lt;p&gt;When you're ready, let's learn about tmux windows!&lt;/p&gt;

&lt;h3&gt;
  
  
  Tmux Windows
&lt;/h3&gt;

&lt;p&gt;Tmux windows are subsets of tmux sessions. When you're creating a new tmux session (&lt;code&gt;tmux new -s MY_SESSION&lt;/code&gt;), what you're seeing is technically a tmux window. Earlier I said that a tmux session is like a container of terminals. While that was true, each terminal activity happens inside a window. So technically, a tmux session is a container for tmux windows.&lt;/p&gt;

&lt;p&gt;You can have as many windows as you want in a session. Since a window contains a terminal on its own, you can have a window dedicated for running your application server, another window for logging, and another window for text-editing.&lt;/p&gt;

&lt;p&gt;Many tmux window commands are conceptually similar to the session commands. You can create, delete, and switch windows, just to name a few. I won't go through every single tmux window operation because in my opinion, you can be very productive just by learning only a few of them.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating a New Window
&lt;/h4&gt;

&lt;p&gt;You can only create a new window from inside a tmux session. Since it's almost lunch time at the time I wrote this, let's start a new lunch session. From the regular terminal (not from inside tmux), create a new session. This should look familiar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux new -s lunch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool! You're inside a session named lunch. You're looking at a tmux window. When you create a new session, tmux automatically creates a new window. &lt;/p&gt;

&lt;p&gt;So right now there is one window - the default window - in the lunch session. To create a new window inside a session, run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux new-window -n fried-rice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a new window named fried-rice (I had that earlier this week). If the &lt;code&gt;new-window&lt;/code&gt; command is too verbose, you can shorthand it a bit with &lt;code&gt;neww&lt;/code&gt;. Let's create a new window named ramen, because I'm craving that right now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux neww -n ramen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Practically speaking though, I almost never use the &lt;code&gt;new-window&lt;/code&gt; terminal command. 99% of the time, I use the following new-window keyboard shortcut:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try creating two or three new windows! Get this in your muscle memory. Window creation is one of the most often-used commands in my tmux workflow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Switching Windows
&lt;/h4&gt;

&lt;p&gt;By now you should have multiple windows in a session. Let's learn how to quickly switch windows.&lt;/p&gt;

&lt;p&gt;Right now I have three windows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the default window&lt;/li&gt;
&lt;li&gt;fried-rice window&lt;/li&gt;
&lt;li&gt;ramen window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am currently on the first window. If I want to go to the *n*ext window, I can do that with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retrospectively, to go to the *p*revious window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another thing to know is that tmux window is indexed like an array data structure. In many programming languages, an array data structure is zero-indexed. Tmux window is also zero-based. The first window is window number 0, the second window window number 1, etc. To go to window number N, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + N
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whereas N is the window number. So if I want to go to the first window, &lt;code&gt;Prefix + 0&lt;/code&gt; will do it. What if I want to go to the second window? &lt;code&gt;Prefix + 1&lt;/code&gt;. Third window? &lt;code&gt;Prefix + 2&lt;/code&gt;. In my regular workflow, I try to keep my window collections small. Normally I don't have more than 5 tmux windows in any session (if I have more, it can quickly get out of control). However, people's workflows are different. You may function better by having dozens of windows in any session. Use whatever works for you. &lt;/p&gt;

&lt;p&gt;If that's the case, how can you quickly jump to window number 11? The Prefix + N shortcut only accepts one key. When you try to do Prefix + 10 (the 11th window), tmux thinks you're doing &lt;code&gt;Prefix + 1&lt;/code&gt;. To quickly jump to double window digits, you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + ' + N
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whereas N is the window number. First, press the prefix. Then press &lt;code&gt;'&lt;/code&gt; (a single quote). This lets you enter any window index number, like 10. Then press Return. &lt;/p&gt;

&lt;p&gt;I forget things a lot (my wife can vouch for that :D). I can hardly keep track of the 5 windows I have opened in the current session. I definitely &lt;em&gt;can't&lt;/em&gt; keep track of all the windows across &lt;em&gt;all&lt;/em&gt; my sessions if I have multiple sessions running. Luckily, you can quickly list and switch to any window in any session with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + w
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you do &lt;code&gt;Prefix + w&lt;/code&gt;, tmux lists all the windows inside all the sessions you have (even the windows from detached sessions). Try it! I also use this command a lot.&lt;/p&gt;

&lt;h4&gt;
  
  
  Renaming Windows
&lt;/h4&gt;

&lt;p&gt;A window name is used to identify what the window is about. It's good to give it a succinct name. If I'm debugging a controller test, then I'll create a new window named "controller test" (yes, not original, but it's concise!). However, sometimes your task changes. The "controller test" task may morph into "feature test" (&lt;em&gt;shudders&lt;/em&gt;). In this case, you may want to rename your window. To rename the current window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + ,
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your cursor is now on the lower window area where you can edit the window name.&lt;/p&gt;

&lt;h4&gt;
  
  
  Deleting Windows
&lt;/h4&gt;

&lt;p&gt;When you're done with a window, you may want to delete it so it doesn't crowd your session. There are two ways to kill a window:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;kill the window with a terminal command&lt;/li&gt;
&lt;li&gt;kill all panes inside a window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For method 1, you can run this from inside a window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux kill-window
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kills the current window you're in. If you want to kill a different window, you can pass a target option to the command &lt;code&gt;-t&lt;/code&gt;. To kill the "ramen" window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux kill-window -t ramen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a less verbose option, you can use &lt;code&gt;killw&lt;/code&gt; instead of &lt;code&gt;kill-window&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux killw -t fried-rice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the second method, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ctrl + d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Tmux Windows Conclusion
&lt;/h4&gt;

&lt;p&gt;We are done with tmux windows. Let's recap.&lt;/p&gt;

&lt;p&gt;A window is where your terminal lives. A session consists of one or more windows. Some window commands that we learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a window with &lt;code&gt;tmux new-window -n MY_WINDOW&lt;/code&gt; or &lt;code&gt;Prefix + c&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Switch to a different window with &lt;code&gt;Prefix + n&lt;/code&gt;, &lt;code&gt;Prefix + p&lt;/code&gt;, and &lt;code&gt;Prefix + N&lt;/code&gt; (where &lt;code&gt;N&lt;/code&gt; is the window index number, zero-based)&lt;/li&gt;
&lt;li&gt;Kill a window with &lt;code&gt;tmux kill-window -t MY_WINDOW&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Close a pane / window with either &lt;code&gt;Ctrl + d&lt;/code&gt; or &lt;code&gt;Prefix + x&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always, take your time to internalize this. Practice what you've learned about windows &lt;em&gt;and&lt;/em&gt; sessions. Try to create several windows, navigate between them, and delete them. Create a new session and create some new windows there too.&lt;/p&gt;

&lt;p&gt;Don't rush. When you're ready, it's time to learn about tmux panes!&lt;/p&gt;

&lt;h3&gt;
  
  
  Tmux Panes
&lt;/h3&gt;

&lt;p&gt;Earlier I said that when you started a new session, what you saw was a tmux window. I lied, again. What you saw was actually a tmux pane inside a tmux window inside a tmux session. When you started a new session, tmux automatically created a new window. When a new window was created, tmux generated a new pane. Just like how a tmux session has at least one window, a tmux window always contains at least one tmux pane.&lt;/p&gt;

&lt;p&gt;Now that we've been exposed to sessions, windows, and panes, let's get the terminology straight. A tmux window is a container to tmux panes. A tmux session is a container to tmux windows. When you start a session, you have at least one tmux window. Inside a session, you can create many windows (&lt;code&gt;Prefix + c&lt;/code&gt;). Inside a tmux window, you have at least one tmux pane. When you split a window for the first time, you are splitting it into two panes. Each boxed terminal is a pane in its own right. The hierarchy goes like this: Session &amp;gt; window &amp;gt; pane.&lt;/p&gt;

&lt;p&gt;Let's go through some tmux pane operations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating a New Pane
&lt;/h4&gt;

&lt;p&gt;If you own tablets or large smart phones, they probably have a feature to split the screen in half so you can open two apps simultaneously. Panes are similar such that you can split the screen vertically (or horizontally) so you can have multiple terminals in a single window.&lt;/p&gt;

&lt;p&gt;A tmux window can be split many times into smaller panes. The command to split a window horizontally is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux split-window -h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To split it vertically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux split-window -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They are rather easy to remember: &lt;code&gt;-h&lt;/code&gt; for *h*orizontal and &lt;code&gt;-v&lt;/code&gt; for *v*ertical.&lt;/p&gt;

&lt;p&gt;To split a window horizontally with a keyboard shortcut:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + %
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To split a window vertically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + "
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Split windows are also one of my most frequently used tmux commands. Commit them to your muscle memory!&lt;/p&gt;

&lt;h4&gt;
  
  
  Deleting a Pane
&lt;/h4&gt;

&lt;p&gt;To delete a pane is similar to deleting a window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ctrl + d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is our third time seeing &lt;code&gt;Prefix + x&lt;/code&gt; and &lt;code&gt;Ctrl + d&lt;/code&gt;. Now you finally understand what this command actually does. It deletes a pane. When the last pane of a window is deleted, that window is automatically removed. When the last window of a session is deleted, that session is automatically killed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Navigate Between Panes
&lt;/h4&gt;

&lt;p&gt;Let's learn the different ways to navigate between panes. First, create multiple panes in a window. Use the &lt;code&gt;Prefix + %&lt;/code&gt; or &lt;code&gt;Prefix + &amp;amp;&lt;/code&gt; shortcut to do that.&lt;/p&gt;

&lt;p&gt;To switch to the "next" pane, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + o
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tmux focuses on a different pane each time you run that command.&lt;/p&gt;

&lt;p&gt;You can also move directionally with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + Up
Prefix + Down
Prefix + Left
Prefix + Right
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands give you slightly more control. Now you can instruct tmux which direction you want to focus on.&lt;/p&gt;

&lt;p&gt;But that's not all. Tmux can also display all the pane numbers of the current window for you to select from. Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + q
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see numbers displayed in the foreground center of each pane. If you type a particular number, tmux will focus on that pane number.&lt;/p&gt;

&lt;p&gt;So if I want to go to pane number 1, I just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + q + 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To go to pane number 5, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + q + 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Btw, you could also have done this with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux display-panes
tmux select-pane -t N
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command lists all the panes and the second command jumps to pane number N. I personally would rather to &lt;code&gt;Prefix + q + N&lt;/code&gt;. Ain't nobody got time to type all that! :)&lt;/p&gt;

&lt;h4&gt;
  
  
  Resize a Pane
&lt;/h4&gt;

&lt;p&gt;I usually have about 2-3 panes in a window. But you may need to adjust their sizes. For example, the other day I had to debug a controller spec. I had the tmux window split horizontally into two panes: top and bottom. I had Vim on the top window and the terminal on the bottom for running the specs. By default, tmux splits them equally, but I prefer to have Vim to have more screen real-estate. To resize a pane, you can run one of the followings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux resize-pane -D 10
tmux resize-pane -U 10
tmux resize-pane -L 10
tmux resize-pane -R 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The number 10 is a measurement unit (tmux "cells"). The &lt;code&gt;-D/U/L/R&lt;/code&gt; options stand for Down/Up/Left/Right. Unfortunately, there are no keyboard shortcuts for this. You can create your own shortcuts to make resizing quicker. I'll show you how to do that in a later section.&lt;/p&gt;

&lt;h4&gt;
  
  
  Zoom a Pane
&lt;/h4&gt;

&lt;p&gt;Another feature I find helpful is pane zooming. If you have four panes displayed in a window, each taking up 25% of that window total area, you can zoom your current pane into 100% and hide the other panes with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it looks as if you only have a single pane, allowing you to view the current pane at maximum area. This is useful if you need to remove distractions and focus on a specific task at a specific pane. Then once you're done, you can de-zoom and return to the previous layout by running &lt;code&gt;Prefix + z&lt;/code&gt; one more time.&lt;/p&gt;

&lt;h4&gt;
  
  
  Swapping Panes
&lt;/h4&gt;

&lt;p&gt;If you have two panes in a window side-by-side, you can swap them with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + {
Prefix + }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also rotate the pane positions with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + Ctrl + o
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Tmux Layouts
&lt;/h4&gt;

&lt;p&gt;While we are discussing panes, let's learn about tmux layouts. because they are closely related. &lt;/p&gt;

&lt;p&gt;"Wait a minute, what are tmux layouts?" Good question! Tmux layouts are pane arrangements to organize your panes in a window. Tmux comes with five ready-to-use layouts. If that description is ambiguous and you're still confused, don't worry. Just follow along and you'll understand it soon enough!&lt;/p&gt;

&lt;p&gt;Create a new window. Then split it horizontally once (Prefix + %). Then split it vertically once (Prefix + "). Your window should now have three panes: one half on the left, and a quarter on top right and a quarter on bottom right.&lt;/p&gt;

&lt;p&gt;Let's go back to layouts. Tmux comes with 5 different layouts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;even-horizontal&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;even-vertical&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main-horizontal&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main-vertical&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tiled&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's try them. Type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux select-layout even-horizontal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how your tmux window is now split horizontally evenly. Just like the name says, the even-horizontal layout re-arranges the current panes into equidistant horizontal panes. &lt;/p&gt;

&lt;p&gt;Let's try the vertical one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux select-layout even-vertical
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's try a different flavor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux select-layout main-vertical
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your tmux window is now split horizontally with the "main" pane taking up more space - while the other two panes are split evenly, taking up less window real estate. Let's try the horizontal version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux select-layout main-horizontal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, let's see what the last one looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux select-layout tiled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your tmux window is split equally. If you had 3 panes, it wouldn't exactly be split evenly, but if you had 4 panes, it would split them perfectly equal.&lt;/p&gt;

&lt;p&gt;You can toggle tmux layouts with a keyboard shortcut. Press:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + Space
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first time you press Prefix + space, tmux goes to even-horizontal layout, then it goes to even-vertical layout, then main-horizontal, etc. It cycles between those five layouts.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tmux Panes Conclusion
&lt;/h4&gt;

&lt;p&gt;Let's go over what we learned.&lt;/p&gt;

&lt;p&gt;You learned about tmux pane. A pane is where your sub-terminals are displayed through. A window can have one or more panes. Here are the commands you learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Split a window horizontally with &lt;code&gt;tmux split-window -h&lt;/code&gt; or &lt;code&gt;Prefix + %&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Split a window vertically with &lt;code&gt;tmux split-window -v&lt;/code&gt; or &lt;code&gt;Prefix + "&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Delete a pane with &lt;code&gt;Prefix + x&lt;/code&gt; or &lt;code&gt;Ctrl + d&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to the next pane with &lt;code&gt;Prefix + o&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to another pane directionally with &lt;code&gt;Prefix + Up/Down/Left/Right&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to pane number N with &lt;code&gt;Prefix + q + N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Resize a pane by N unit with &lt;code&gt;tmux resize-pane -D/U/L/R N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Zoom/de-zoom a pane with &lt;code&gt;Prefix + z&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Swap panes with &lt;code&gt;Prefix + {&lt;/code&gt; or &lt;code&gt;Prefix + }&lt;/code&gt; and rotate panes with &lt;code&gt;Prefix + Ctrl + o&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Toggle layouts with &lt;code&gt;tmux select-layout even-horizontal/even-vertical/main-horizontal/main-vertical/tiled&lt;/code&gt; or &lt;code&gt;Prefix + Space&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tmux pane is a unique feature that differentiates tmux from most regular terminals. Usually, to start a new terminal, you need to open a new tab. But what if you need to have two terminals side-by-side? With tmux, you can easily split a window into two or more panes. You can even organize how the panes are displayed.&lt;/p&gt;

&lt;p&gt;As always, take your time to digest what you just learned. Play around! Create multiple panes in a window, then navigate around them. Delete some panes. Resize them. Zoom in and out. Change the layouts. &lt;/p&gt;

&lt;p&gt;Combine this lesson with what you've learned. Create a new session. Create a few new windows with multiple panes in them. See how fast you can go from the current pane to another pane in a different window from a different session. Do this until you can navigate around effortlessly. Take as much time as you need.&lt;/p&gt;

&lt;p&gt;When you are ready, let's learn about tmux servers!&lt;/p&gt;

&lt;h3&gt;
  
  
  Tmux servers
&lt;/h3&gt;

&lt;p&gt;By now, you should have a good idea what tmux can do. You should also understand how sessions, windows, and panes relate (otherwise, stop and review the last three sections). There is one more missing piece: tmux servers. Although you can do fine merely knowing about sessions, windows, and panes without knowing about tmux servers, it is good to know the whole picture to have a more accurate mental model. Understanding tmux server will explain why some commands, like &lt;code&gt;tmux kill-server&lt;/code&gt;, exist (to kill the server, duh!)&lt;/p&gt;

&lt;p&gt;When we run the command &lt;code&gt;tmux&lt;/code&gt;, tmux not only creates a new session, but it also creates a new server instance. This whole ecosystem that you have been &lt;em&gt;interacting with&lt;/em&gt; - you can think of it like the client in client-server interaction. If it is like a client-server interaction, then there must be a tmux server somewhere. Tmux server is what runs in the background while Tmux client runs in the foreground.&lt;/p&gt;

&lt;p&gt;When we create multiple sessions: &lt;code&gt;tmux new -s breakfast&lt;/code&gt;, &lt;code&gt;tmux new -s lunch&lt;/code&gt;, and &lt;code&gt;tmux new -s dinner&lt;/code&gt;, those three are connected to the same tmux server. Since we don't mention a server name, these sessions are connected to a &lt;em&gt;default&lt;/em&gt; server. &lt;/p&gt;

&lt;p&gt;To launch a named server - let's name it the food server - run this from the regular terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux -L food
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a new server named food. Running this command also launches a new session by default. Cool! Let's detach from this server (&lt;code&gt;Prefix + d&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;So we have a food server running somewhere in your machine, but you are detached from it. What if you want to reconnect to the food server? Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux -L food attach
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll be reattached to the food server. Wait a minute, this looks like the attach command from way earlier when we only had one session (&lt;code&gt;tmux attach&lt;/code&gt;). It's because it is. The difference is that we are attaching back to a session from the food server instead of the default server.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;tmux -L food&lt;/code&gt; creates a default session inside the food session. What if we want to create a named session? To create a new named session inside the food server, say a roast-duck session, we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux -L food new -s roast-duck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recall that running &lt;code&gt;tmux ls&lt;/code&gt; will list the sessions from the default server. But what if we want to view all the sessions in the food server? Easy, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux -L food ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to attach to the roast-duck session in the food server, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux -L food attach -t roast-duck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, to kill this food server, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux -L food kill-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The kill-server command kills a server. When a server is killed, it kills everything inside it (sessions, windows, and panes) - make sure that you save everything before closing it. By the way, to kill the default (unnamed) server, just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux kill-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run &lt;code&gt;tmux kill-server&lt;/code&gt; when nothing is running, you'll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;no server running on /private/tmp/tmux-501/default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your exact path might be different from what I have, but the important ideas are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The command &lt;code&gt;kill-server&lt;/code&gt; is looking in the &lt;code&gt;tmp/&lt;/code&gt; directory, which is usually where linux sockets are. Wait, did you say socket? That sounds like a client-server interaction!&lt;/li&gt;
&lt;li&gt;The directory is named "default" because we tried to kill the default server. By the way, if you created multiple servers, you'll find all those server names stored in here. So if you created a food server, you would find &lt;code&gt;/food&lt;/code&gt; in there too.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Phew. That's a lot to take in. Let's practice what we just learned to solidify what we just learned. Do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create 2 new tmux servers (give them any name you want)&lt;/li&gt;
&lt;li&gt;Inside each server, create multiple sessions. Inside each session, create multiple windows. Inside each window, create multiple panes&lt;/li&gt;
&lt;li&gt;Detach from one server and attach to the other one&lt;/li&gt;
&lt;li&gt;Delete the servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Practically speaking, I almost never use more than one server in my workflow. However, your use case might be different. Regardless, it wouldn't hurt to know! The more you know, the less you don't know.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing tmux
&lt;/h3&gt;

&lt;p&gt;In my opinion, tmux could use a better set of keys. For example, I find that using the &lt;code&gt;Ctrl + b&lt;/code&gt; keys are not comfortable. Let's change some key shortcuts.&lt;/p&gt;

&lt;p&gt;You can modify tmux keys with the tmux config file. When you launch tmux, it looks for a file named &lt;code&gt;.tmux.conf&lt;/code&gt; in the HOME path - in my case, it is &lt;code&gt;~/.tmux.conf&lt;/code&gt;. If it isn't there yet, create a file &lt;code&gt;.tmux.conf&lt;/code&gt; in your HOME path.&lt;/p&gt;

&lt;p&gt;Let's change the tmux prefix. Some of the popular prefix alternatives are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ctrl + a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Space&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + s&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + u&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Backticks &lt;/li&gt;
&lt;li&gt;Tab + key variation instead of Ctrl + key&lt;/li&gt;
&lt;li&gt;etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Personally, I use &lt;code&gt;Ctrl + Space&lt;/code&gt; mainly because my Vim leader key is the Space key. But ultimately, use whatever keys that make the most sense to you.&lt;/p&gt;

&lt;p&gt;To change your prefix to &lt;code&gt;Ctrl + Space&lt;/code&gt;, add these in the tmux config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unbind C-Space
set -g prefix C-Space
bind C-Space send-prefix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The changes above won't take place immediately. You first need to source the file. You can either close tmux (kill your tmux session and start a new one) or source the config file.&lt;/p&gt;

&lt;p&gt;To source tmux config file, from inside a tmux session, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tmux source-file ~/.tmux.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the way, in the future, I would like to be able to source my configurations quickly with &lt;code&gt;Prefix + r&lt;/code&gt;. Add this in the config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bind-key r source-file ~/.tmux.conf \; display-message "Tmux config reloaded!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to restart the tmux session. Now you can just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix + r
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To quickly source your file. &lt;/p&gt;

&lt;p&gt;By the way, with some changes, you may notice that even running &lt;code&gt;Prefix + r&lt;/code&gt; isn't enough. You need to also restart the tmux server. Detach from the session, kill the server (&lt;code&gt;tmux kill-server&lt;/code&gt;), then start a new session. Alternatively, you can also run &lt;code&gt;Prefix + I&lt;/code&gt; (note the I is uppercased) to reload the tmux environment.&lt;/p&gt;

&lt;p&gt;In short, if running &lt;code&gt;Prefix + r&lt;/code&gt; is not sufficient, try running &lt;code&gt;Prefix + I&lt;/code&gt; also. If all fails, restart the tmux &lt;/p&gt;

&lt;p&gt;Two more shortcuts that I don't find intuitive are the window splits, &lt;code&gt;Prefix + %&lt;/code&gt; and &lt;code&gt;Prefix + "&lt;/code&gt;. To me, it makes more sense to use &lt;code&gt;|&lt;/code&gt; for a vertical split and &lt;code&gt;-&lt;/code&gt; for a horizontal split. Add these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bind | split-window -hc "#{pane_current_path}"
bind - split-window -vc "#{pane_current_path}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when I press &lt;code&gt;Prefix + |&lt;/code&gt;, tmux does a vertical split and when I press &lt;code&gt;Prefix + -&lt;/code&gt;, tmux does a horizontal split.&lt;/p&gt;

&lt;h4&gt;
  
  
  More configs?
&lt;/h4&gt;

&lt;p&gt;There are many different ways you can configure your tmux config. To address them all would be out of the scope of this article.&lt;/p&gt;

&lt;p&gt;If you want to learn more about tmux configs, I am currently working on another article to address tmux configs in more detail, so stay tuned! I will update this post with the link to the said article when it is done.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;11/18 Update: Part 2 is out! Check it out here: &lt;a href="https://dev.to/iggredible/useful-tmux-configuration-examples-k3g"&gt;Useful Tmux Configuration Examples&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you want to see what my personal configs look like, check out my &lt;a href="https://github.com/iggredible/dotfiles" rel="noopener noreferrer"&gt;dotfiles&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Phew, we have now reached the end of this guide. I hope that you learned valuable things about tmux. If there is anything that is unclear, please feel free to drop by the comment section.&lt;/p&gt;

&lt;p&gt;Here's the final recap. In this guide, we learned about tmux session, window, pane, and server. We learned about their relationships with each other. We also learned a little about configuring tmux. In the next article, you will learn more about configuring tmux in detail. I will update this guide with the link to the next article when it is ready.&lt;/p&gt;

&lt;p&gt;More importantly, take your time reading this guide. It can be tempting to read through the entire guide without doing any practice. Take a day to read about a section and let it digest. Apply what you learn that day. Instead of reading for 15 minutes and practicing for 5 minutes, for every 5 minutes you learn about something, spend 15 minutes. Yes, it is a lot. Yes, you'll read less on average. But you will learn a lot more. In the end, what you learn is what actually matters, not the amount of articles/ books you read.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>tmux</category>
      <category>vim</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What Is Inside My Vimrc</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Thu, 16 Sep 2021 14:55:08 +0000</pubDate>
      <link>https://dev.to/iggredible/what-is-inside-my-vimrc-3ob7</link>
      <guid>https://dev.to/iggredible/what-is-inside-my-vimrc-3ob7</guid>
      <description>&lt;p&gt;A vimrc is an important file for us Vim users.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Edit: My Vimrc has changed since I began writing this article (it is now 7 lines long), but the principle is still the same. If you want to look at the state of the Vimrc at the time I wrote this article, check out &lt;a href="https://github.com/iggredible/dotfiles/tree/691af3370c9914cdbb36f05af57d6c163ef5ed62" rel="noopener noreferrer"&gt;this link&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you're like me, you probably have spent an ungodly amount of time tinkering with it until it grows massive. At some point, it is a good idea to split your vimrc into multiple parts for maintainability. Plus, if you want to share your vimrc to the world, splitting it into an organized structure will help clarify with other devs who are looking at your vimrc.&lt;/p&gt;

&lt;p&gt;In this article, I will share how I organize my vimrc. Everything here is a matter of personal preference. There is no objectively right or wrong way to organize a vimrc. I hope that by sharing what's inside my vimrc, you will gain insight into how you can organize your own vimrc to meet your needs. Don't put down any line in your vimrc that you don't understand.&lt;/p&gt;

&lt;p&gt;Lastly, this article makes the assumption that your default vimrc file and Vim files directory are in the root directory, &lt;code&gt;~/.vimrc&lt;/code&gt; and &lt;code&gt;~/.vim/&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source, The Secret Sauce
&lt;/h2&gt;

&lt;p&gt;The secret sauce of a modular vimrc is the &lt;code&gt;source&lt;/code&gt; Vimrscript command. Think of it like the &lt;code&gt;require&lt;/code&gt;, &lt;code&gt;include&lt;/code&gt;, or &lt;code&gt;import&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;If you have this inside your &lt;code&gt;~/.vimrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source '~/my-script.vim'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;~/my-script.vim&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Hello from outside yo vimrc"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next time you open Vim, it will output "Hello from outside yo vimrc". Great! This is how you can split your vimrc into multiple parts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dotfiles
&lt;/h2&gt;

&lt;p&gt;My Vim configs are stored inside my &lt;a href="https://github.com/iggredible/dotfiles" rel="noopener noreferrer"&gt;dotfiles repository&lt;/a&gt; - this way I can access them when I'm away from my computer. So if I have to login from a foreign computer, all I need to do is symlink the Vim files from the dotfiles repository, install the dependencies (I have a script for that too, but that's for another time), and I'm set to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Structure
&lt;/h2&gt;

&lt;p&gt;This is the structure for my Vim-related files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotfiles/
├─ vim/
│  ├─ custom-functions/
│  │  ├─ function1.vim
│  │  ├─ function2.vim
│  │  ├─ function-N.vim
│  ├─ custom-plugins/
│  │  ├─ ale.vim
│  │  ├─ fzf.vim
│  │  ├─ plugin-N.vim
│  ├─ main/
│  │  ├─ settings.vim
│  │  ├─ themes.vim
│  │  ├─ keymaps.vim
│  ├─ UltiSnips/
│  │  ├─ javascript.snippets
│  │  ├─ ruby.snippets
│  ├─ vimspector.json
├─ vimrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important ones are the &lt;code&gt;vimrc&lt;/code&gt; file and the &lt;code&gt;vim/&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Note that I name them without the dot (&lt;code&gt;vimrc&lt;/code&gt; and &lt;code&gt;vim/&lt;/code&gt; as opposed to &lt;code&gt;.vimrc&lt;/code&gt; and &lt;code&gt;.vim/&lt;/code&gt;). This is so that when I clone it, they won't be invisible. It's easier to deal with visible files than invisible ones.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;vim/&lt;/code&gt; directory, I divide them into multiple sub-directories. The three important ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;custom-functions/&lt;/code&gt; where I store my own custom functions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;custom-plugins/&lt;/code&gt; where I store configs specific for Vim plugins&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;main/&lt;/code&gt; where I store the main Vim configurations and basic keymaps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you notice, I also have a &lt;code&gt;vimspector.json&lt;/code&gt; file and a &lt;code&gt;UltiSnips/&lt;/code&gt; directory. I use the &lt;a href="https://github.com/puremourning/vimspector" rel="noopener noreferrer"&gt;Vimspector&lt;/a&gt; plugin and it requires a config file. I also use the &lt;a href="https://github.com/SirVer/ultisnips" rel="noopener noreferrer"&gt;ultisnips&lt;/a&gt; plugin. It uses&lt;code&gt;UltiSnips/&lt;/code&gt; directory to store custom snippets. If you don't use any of these plugins, just ignore them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vimrc
&lt;/h2&gt;

&lt;p&gt;The vimrc file is called first whenever you launch Vim. Inside it, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if empty(glob('~/.vim/autoload/plug.vim'))
  silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
    \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  autocmd VimEnter * PlugInstall | source $MYVIMRC
endif

call plug#begin('~/.vim/plugged')
  Plug 'iggredible/totitle-vim'
  Plug 'tpope/vim-sensible'
  Plug 'sjl/badwolf'
  Plug 'itchyny/lightline.vim'
  Plug 'junegunn/fzf.vim'
  Plug 'junegunn/fzf', { 'do': { -&amp;gt; fzf#install() } }
  Plug 'ludovicchabant/vim-gutentags'
  Plug 'tomtom/tcomment_vim'
  Plug 'mattn/emmet-vim'
  Plug 'sheerun/vim-polyglot'
  Plug 'tpope/vim-fugitive'
  Plug 'Yggdroot/indentLine'
  Plug 'preservim/nerdtree'
  Plug 'luochen1990/rainbow'
  Plug 'tpope/vim-dispatch'
  Plug 'junegunn/vim-peekaboo'
  Plug 'machakann/vim-sandwich'
  Plug 'simnalamburt/vim-mundo'
  Plug 'tpope/vim-endwise'
  Plug 'tpope/vim-unimpaired'
  Plug 'godlygeek/tabular'
  Plug 'mhinz/vim-signify', { 'branch': 'legacy' }
  Plug 'ryanoasis/vim-devicons'
  Plug 'dense-analysis/ale'
  Plug 'szw/vim-maximizer'
  Plug 't9md/vim-choosewin'
  Plug 'Shougo/unite.vim'
  Plug 'puremourning/vimspector'
  Plug 'SirVer/ultisnips'
  Plug 'honza/vim-snippets'
call plug#end()

let b:fileList = split(globpath('~/.vim/main', '*.vim'), '\n')
let b:fileList += split(globpath('~/.vim/custom-functions', '*.vim'), '\n')
let b:fileList += split(globpath('~/.vim/custom-plugins', '*.vim'), '\n')

for fpath in b:fileList
  exe 'source' fpath
endfor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My vimrc is less than 50 lines long, including empty lines. Hey, that's pretty readable! Let's go over what they do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatically Installing Vim Plug
&lt;/h3&gt;

&lt;p&gt;I use &lt;a href="https://github.com/junegunn/vim-plug" rel="noopener noreferrer"&gt;vim-plug&lt;/a&gt; as my plugin manager. The code below checks for the existence of &lt;code&gt;~/.vim/autoload/plug.vim&lt;/code&gt; when you start Vim. The plugin manager uses that file to read the plugin files. If &lt;code&gt;plug.vim&lt;/code&gt; doesn't already exist, then it will download the &lt;code&gt;plug.vim&lt;/code&gt; file and create the &lt;code&gt;~/.vim/autoload/plug.vim&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if empty(glob('~/.vim/autoload/plug.vim'))
  silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
    \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  autocmd VimEnter * PlugInstall | source $MYVIMRC
endif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also find the automatic install script above in the &lt;a href="https://github.com/junegunn/vim-plug/wiki/tips#automatic-installation" rel="noopener noreferrer"&gt;vim-plug tips page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I haven't really looked at other plugin managers, but I'm confident that you can pull something similar with other plugin managers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;The next line lists a list of plugins I use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;call plug#begin('~/.vim/plugged')
  Plug 'iggredible/totitle-vim'
  Plug 'tpope/vim-sensible'
  Plug 'sjl/badwolf'
  Plug 'itchyny/lightline.vim'
  Plug 'junegunn/fzf.vim'
  Plug 'junegunn/fzf', { 'do': { -&amp;gt; fzf#install() } }
  Plug 'ludovicchabant/vim-gutentags'
  Plug 'tomtom/tcomment_vim'
  Plug 'mattn/emmet-vim'
  Plug 'sheerun/vim-polyglot'
  Plug 'tpope/vim-fugitive'
  Plug 'Yggdroot/indentLine'
  Plug 'preservim/nerdtree'
  Plug 'luochen1990/rainbow'
  Plug 'tpope/vim-dispatch'
  Plug 'junegunn/vim-peekaboo'
  Plug 'machakann/vim-sandwich'
  Plug 'simnalamburt/vim-mundo'
  Plug 'tpope/vim-endwise'
  Plug 'tpope/vim-unimpaired'
  Plug 'godlygeek/tabular'
  Plug 'mhinz/vim-signify', { 'branch': 'legacy' }
  Plug 'ryanoasis/vim-devicons'
  Plug 'dense-analysis/ale'
  Plug 'szw/vim-maximizer'
  Plug 't9md/vim-choosewin'
  Plug 'Shougo/unite.vim'
  " Plug 'puremourning/vimspector'
  Plug 'SirVer/ultisnips'
  Plug 'honza/vim-snippets'
call plug#end()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This part is totally up to you. Use whatever plugins that &lt;em&gt;you need&lt;/em&gt;, not what you see other people use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sourcing Stuff
&lt;/h3&gt;

&lt;p&gt;Here's what the next 3 lines look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let b:fileList = split(globpath('~/.vim/main', '*.vim'), '\n')
let b:fileList += split(globpath('~/.vim/custom-functions', '*.vim'), '\n')
let b:fileList += split(globpath('~/.vim/custom-plugins', '*.vim'), '\n')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are creating an array named &lt;code&gt;fileList&lt;/code&gt; and appending it with the paths for all the files inside &lt;code&gt;main/&lt;/code&gt;, &lt;code&gt;custom-functions/&lt;/code&gt;, and &lt;code&gt;custom-plugins/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, we have this loop. This is where the magic happens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for fpath in b:fileList
  exe 'source' fpath
endfor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It iterates through the &lt;code&gt;fileList&lt;/code&gt; array and calls &lt;code&gt;source&lt;/code&gt; on each file. This keeps my vimrc to be concise and spark joy :D.&lt;/p&gt;

&lt;p&gt;Next, let's explore some contents of my &lt;code&gt;main/&lt;/code&gt;, &lt;code&gt;custom-functions/&lt;/code&gt;, and &lt;code&gt;custom-plugins/&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  the Main Directory
&lt;/h3&gt;

&lt;p&gt;The main directory contains the base vimrc configs that don't depend on any custom plugin.&lt;/p&gt;

&lt;p&gt;Inside, I sub-divide them into three files: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;settings.vim&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;keymaps.vim&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;themes.vim&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Main Settings
&lt;/h3&gt;

&lt;p&gt;This is what's inside the &lt;code&gt;settings.vim&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set clipboard=unnamed
set noswapfile
set relativenumber number
set tabstop=2
set shiftwidth=2
set expandtab
set ignorecase
set smartcase
set hlsearch
set confirm
set hidden
set shortmess-=S

let s:english_dict = "/usr/share/dict/words"

if filereadable(s:english_dict)
  let &amp;amp;dictionary=s:english_dict
endif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file primarily deals with base settings (if you're curious what they do, consult &lt;code&gt;:help&lt;/code&gt;). The last command with the &lt;code&gt;english_dict&lt;/code&gt; adds a dictionary autocompletion (&lt;code&gt;CTRL-X CTRL-K&lt;/code&gt;), if a dictionary exists.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main Keymaps
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;keymaps.vim&lt;/code&gt; file contains key mappings independent from plugins. For plugin-specific maps, they are inside &lt;code&gt;custom-plugins/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside my &lt;code&gt;keymaps.vim&lt;/code&gt;, I have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let mapleader = "\&amp;lt;Space&amp;gt;"

nnoremap &amp;lt;Leader&amp;gt;vs :source ~/.vimrc&amp;lt;CR&amp;gt;
nnoremap &amp;lt;Leader&amp;gt;ve :vsplit ~/.vimrc&amp;lt;CR&amp;gt;

nnoremap &amp;lt;Esc&amp;gt;&amp;lt;Esc&amp;gt; :noh&amp;lt;Return&amp;gt;&amp;lt;Esc&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like to use &lt;code&gt;Space&lt;/code&gt; as the leader - but you can use whatever leader key you feel comfortable with.&lt;/p&gt;

&lt;p&gt;I have three custom maps. The first two, &lt;code&gt;&amp;lt;Leader&amp;gt;vs&lt;/code&gt; and &lt;code&gt;&amp;lt;Leader&amp;gt;ve&lt;/code&gt;, are to quickly open  and source (vs mnemonic: Vimrc Source) Vimrc (mnemonics: &lt;strong&gt;V&lt;/strong&gt;imrc &lt;strong&gt;E&lt;/strong&gt;dit and &lt;strong&gt;V&lt;/strong&gt;imrc &lt;strong&gt;Source&lt;/strong&gt;). I've used this countless times.&lt;/p&gt;

&lt;p&gt;I also have a &lt;code&gt;&amp;lt;Esc&amp;gt;&amp;lt;Esc&amp;gt;&lt;/code&gt; mapped to &lt;code&gt;:noh&lt;/code&gt; (nohighlight). This is used to remove the highlights after searching for keywords.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main Themes
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;themes.vim&lt;/code&gt; file contain configurations for the color schemes and various UI-related settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;silent! colorscheme evening
silent! colorscheme badwolf

highlight CursorColumn guibg=#ecf0c1
highlight CursorLine guibg=#ecf0c1

set termguicolors
set background=dark
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you notice, I use &lt;em&gt;two&lt;/em&gt; color schemes. What's up with that?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sjl/badwolf" rel="noopener noreferrer"&gt;badwolf&lt;/a&gt; is a custom color scheme plugin. When I launch Vim for the first time on a new machine, I won't have the plugins installed yet, using &lt;code&gt;badwolf&lt;/code&gt; immediately will cause it to fail on that first Vim run. &lt;code&gt;evening&lt;/code&gt; is a built-in Vim color scheme. By putting &lt;code&gt;silent! colorscheme evening&lt;/code&gt; followed by &lt;code&gt;silent! colorscheme badwolf&lt;/code&gt;, if &lt;code&gt;badwolf&lt;/code&gt; isn't available, it will, in effect, &lt;em&gt;falls back&lt;/em&gt; to &lt;code&gt;evening&lt;/code&gt;. &lt;code&gt;silent!&lt;/code&gt; will also omit the error message (otherwise you'll see an error message when Vim couldn't find &lt;code&gt;badwolf&lt;/code&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Functions
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;custom-functions/&lt;/code&gt; directory is where all the custom functions live. These are user-specific functions. What I need might be different from yours. But I'll go over some of mine anyway. Feel free to take them, modify them, and steal them (I stole two of them somewhere sometime ago :P).&lt;/p&gt;

&lt;p&gt;I have four custom functions. Here are some of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Functions to Delete Buffers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function! DeleteAllBuffers()
  let l:current_pos = getpos('.')
  execute "%bd | e# | echo 'Buffers Deleted'"
  call setpos('.', l:current_pos)
endfunc

function! DeleteMatchingBuffers(pattern)
    let l:bufferList = filter(range(1, bufnr('$')), 'buflisted(v:val)')
    let l:matchingBuffers = filter(bufferList, 'bufname(v:val) =~ a:pattern')
    if len(l:matchingBuffers) &amp;lt; 1
        echo 'No buffers found matching pattern ' . a:pattern
        return
    endif
    exec 'bd ' . join(l:matchingBuffers, ' ')
endfunction

command! -nargs=1 DelBuf call DeleteMatchingBuffers('&amp;lt;args&amp;gt;')

nnoremap &amp;lt;silent&amp;gt; &amp;lt;Leader&amp;gt;bD :call DeleteAllBuffers()&amp;lt;CR&amp;gt;
nnoremap &amp;lt;silent&amp;gt; &amp;lt;Leader&amp;gt;bd :DelBuf&amp;lt;Space&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I won't go into how Vimscript works. If you want to learn Vimscript, check out &lt;a href="https://github.com/iggredible/Learn-Vim" rel="noopener noreferrer"&gt;my Learn Vim book&lt;/a&gt; (free to read).&lt;/p&gt;

&lt;p&gt;The main point is, I have a target-delete &lt;code&gt;&amp;lt;Leader&amp;gt;bd&lt;/code&gt; to delete a specific buffer(s) and mass-delete &lt;code&gt;&amp;lt;Leader&amp;gt;bD&lt;/code&gt; to delete all buffers except the current one. &lt;/p&gt;

&lt;p&gt;After coding for a few hours, my buffer list would usually balloon and get convoluted. I'd need to clear them up.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;&amp;lt;Leader&amp;gt;bD&lt;/code&gt;, it will indiscriminately delete all items in the buffer list (&lt;code&gt;:ls&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;&amp;lt;Leader&amp;gt;bd&lt;/code&gt;, it will ask for a pattern. Vim will delete all buffers matching the pattern. So if you have &lt;code&gt;users_controller.rb&lt;/code&gt;, &lt;code&gt;packages_controller.rb&lt;/code&gt;, &lt;code&gt;user_model.rb&lt;/code&gt;, and &lt;code&gt;package_model.rb&lt;/code&gt; and you enter "controller" as pattern, it will delete the controller buffers and keep the model buffers. &lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Functions to Open Url Under Cursor
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function! OpenURLUnderCursor()
  let l:uri = expand('&amp;lt;cWORD&amp;gt;')
  silent exec "!open '" . l:uri . "'"
  redraw!
endfunction

nnoremap gx :call OpenURLUnderCursor()&amp;lt;CR&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one is actually a native feature of Vim (NETRW actually - &lt;code&gt;:help netrw-gx&lt;/code&gt;). By pressing &lt;code&gt;gx&lt;/code&gt; while your cursor is inside a URL, Vim will open that document. However, in Mac, that behavior doesn't work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Functions to Toggle Cursor Display
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function! ToggleCursor()
  if(&amp;amp;cursorcolumn == 1)
    set nocursorcolumn
  elseif (&amp;amp;cursorcolumn == 0)
    set cursorcolumn
  endif

  if(&amp;amp;cursorline == 1)
    set nocursorline
  elseif (&amp;amp;cursorline == 0)
    set cursorline
  endif
endfunction

nnoremap &amp;lt;leader&amp;gt;tc :call ToggleCursor()&amp;lt;CR&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can toggle the horizontal cursor highlight with &lt;code&gt;:set cursorline&lt;/code&gt; / &lt;code&gt;:set nocursorline&lt;/code&gt; and the vertical cursor highlight with &lt;code&gt;:set cursorcolumn&lt;/code&gt; / &lt;code&gt;:set nocursorcolumn&lt;/code&gt;. This can be useful if you need a makeshift straight edge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Functions to Toggle Numbers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function! ToggleNumber()
  if(&amp;amp;relativenumber == 1)
    set norelativenumber
  else
    set relativenumber
  endif
endfunc

nnoremap &amp;lt;leader&amp;gt;tn :call ToggleNumber()&amp;lt;CR&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like using &lt;code&gt;relativenumber&lt;/code&gt; to see how far apart a text is from the cursor. However, there are times when I need to see the absolute line number instead. This allows me to quickly toggle the number setting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Plugins
&lt;/h2&gt;

&lt;p&gt;Finally, the &lt;code&gt;custom-plugins/&lt;/code&gt; section is where the settings for each plugin is.&lt;/p&gt;

&lt;p&gt;Since there are so many of them, I will only cover one or two in this article. If you're curious, feel free to check out my &lt;a href="https://github.com/iggredible/dotfiles" rel="noopener noreferrer"&gt;dotfiles repository&lt;/a&gt; and see what else I have.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;custom-plugins/&lt;/code&gt; directory, I have files named after the plugin itself (you can name them anything you want).&lt;/p&gt;

&lt;p&gt;For example, inside &lt;code&gt;ale.vim&lt;/code&gt; (ale is a linting engine for Vim):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;" -------------------------
" Configs
" -------------------------

let g:ale_linters = {
      \   'javascript': ['eslint'],
      \   'ruby': ['rubocop'],
      \}

let g:ale_fixers = {
      \   'javascript': ['eslint'],
      \   'ruby': ['rubocop'],
      \}
let g:ale_linters_explicit = 1 " Only run linters named in ale_linters settings.
let g:ale_sign_column_always = 1

" -------------------------
" Keymaps
" -------------------------

nmap &amp;lt;silent&amp;gt; &amp;lt;C-k&amp;gt; &amp;lt;Plug&amp;gt;(ale_previous_wrap)
nmap &amp;lt;silent&amp;gt; &amp;lt;C-j&amp;gt; &amp;lt;Plug&amp;gt;(ale_next_wrap)

nnoremap &amp;lt;Leader&amp;gt;at :ALEToggle&amp;lt;CR&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, I have &lt;a href="https://github.com/iggredible/dotfiles" rel="noopener noreferrer"&gt;ale&lt;/a&gt; configured for Javascript and Ruby (using eslint and rubocop) - because I mainly work with Ruby and Javascript. Finally, I also have some keymaps related to the ale plugin.&lt;/p&gt;

&lt;p&gt;Many of the plugins that I use don't need any configurations, like &lt;code&gt;emmet-vim&lt;/code&gt;, &lt;code&gt;tcomment_vim&lt;/code&gt;, &lt;code&gt;vim-sandwich&lt;/code&gt;, etc. You'll find that you don't need as many custom-plugin files as you have plugins installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Next?
&lt;/h2&gt;

&lt;p&gt;This concludes this article. I hope that you learned a thing or two. Make your vimrc uniquely yours. Keep improving everyday.&lt;/p&gt;

&lt;p&gt;For max usage, I strongly recommend you reading this in conjunction with my dotfiles article for a complete guide on portability.&lt;/p&gt;

&lt;p&gt;If you're still hungry for more, I suggest looking up other people's Vimrcs. Here are a few that I can think of.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;Some great resources to learn and steal (&lt;em&gt;cough&lt;/em&gt;) Vimrcs (and dotfiles):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/amix/vimrc" rel="noopener noreferrer"&gt;amix's vimrc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/skwp/dotfiles" rel="noopener noreferrer"&gt;skwp's dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mattjmorrison/dotfiles" rel="noopener noreferrer"&gt;mattjmorrison's dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/thoughtbot/dotfiles" rel="noopener noreferrer"&gt;Thougtbot's dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/square/maximum-awesome" rel="noopener noreferrer"&gt;Square's dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/mmphego/how-i-increased-my-productivity-using-dotfiles-2f4m"&gt;How I increased my productivity using dotfiles [updated]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dougblack.io/words/a-good-vimrc.html" rel="noopener noreferrer"&gt;A Good Vimrc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vim</category>
      <category>vimrc</category>
      <category>editor</category>
      <category>ide</category>
    </item>
    <item>
      <title>How to Use Rsync to Backup Your Files</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Fri, 03 Sep 2021 16:00:13 +0000</pubDate>
      <link>https://dev.to/iggredible/how-to-use-rsync-to-backup-your-file-6p1</link>
      <guid>https://dev.to/iggredible/how-to-use-rsync-to-backup-your-file-6p1</guid>
      <description>&lt;h1&gt;
  
  
  What Is Rsync
&lt;/h1&gt;

&lt;p&gt;If you've been programming for a while, you may have heard of rsync. It is a tool to transfer and synchronize files in different directories. These directories can be inside the same machine or between two connected machines.&lt;/p&gt;

&lt;p&gt;Some of you may wonder, "Well, why can't I just use the copy command &lt;code&gt;cp&lt;/code&gt;, that way I don't have to learn a new command?" These two are two different programs. &lt;code&gt;cp&lt;/code&gt; copies everything from one location to another, while &lt;code&gt;rsync&lt;/code&gt; copies the deltas (the differences) from one location to another. &lt;/p&gt;

&lt;p&gt;Suppose that your source directory A contains files totaling 1GB in size. Assume that you also have directory B with the same 1GB of files. Then you add small changes of about 0.1GB. With rsync, you won't have to copy the whole 1.1GB of data from A to B. You will only have to transfer 0.1GB of data. Why copy mostly the same data if you can just copy only the differences? This lets you minimize the network usage, which can be useful if you have a small bandwidth.&lt;/p&gt;

&lt;p&gt;Let's jump straight to the code. I would strongly encourage you to code along. I find it more useful when learning a new thing if I actually type the commands. Moreover, don't just type everything you see in this article and stop there. Experiment with these commands. Read the &lt;code&gt;man rsync&lt;/code&gt; page. Make variations. Experiment. Do things that I don't mention here. Break things! Just make sure you make a backup first (see what I did there? :D) Only by doing these you'll get the most out of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic rsync
&lt;/h2&gt;

&lt;p&gt;At its core, the rsync command looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsync source destination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose that you have a file &lt;code&gt;~/Projects/source/file1.txt&lt;/code&gt; that you want to sync to &lt;code&gt;~/Projects/destination/&lt;/code&gt;. Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsync ~/Projects/source/file1.txt ~/Projects/destination/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see &lt;code&gt;file1.txt&lt;/code&gt; inside &lt;code&gt;destination/&lt;/code&gt; now. Cool! However, practically speaking, you probably don't need to rsync a single file. Rsync is usually used on a directory. &lt;/p&gt;

&lt;p&gt;To rsync the &lt;code&gt;source/&lt;/code&gt; directory (including all its files) to the &lt;code&gt;destination/&lt;/code&gt; directory, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsync source/* destination/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you will find all the files inside &lt;code&gt;source/&lt;/code&gt; are copied inside the &lt;code&gt;destination/&lt;/code&gt;. If you run the command &lt;code&gt;rsync source/* destination/&lt;/code&gt; again without making any changes, rsync won't do anything (there are no deltas).&lt;/p&gt;

&lt;p&gt;If you add a file inside &lt;code&gt;source/&lt;/code&gt; that is not yet in &lt;code&gt;destination/&lt;/code&gt;, running the rsync command adds that file into &lt;code&gt;destination/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you remove a file inside &lt;code&gt;source/&lt;/code&gt; and that file is also inside &lt;code&gt;destination/&lt;/code&gt;, running the rsync command will &lt;em&gt;not&lt;/em&gt; remove that file from &lt;code&gt;destination/&lt;/code&gt;. Rsync by default has an additive nature. To also delete a file in &lt;code&gt;destination/&lt;/code&gt; when the source file is deleted, pass the &lt;code&gt;--delete&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;Finally, if you add a directory inside &lt;code&gt;source/&lt;/code&gt;, the rsync command above won't sync the directory (and neither the contents inside that directory). To sync directories within a source directory, you need to use rsync recursively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recursive Rsync
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;-r&lt;/code&gt; option syncs a directory recursively. If your &lt;code&gt;source/&lt;/code&gt; directory contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file1.txt
file2.txt
dir1/
dir1/file1.md
dir1/file2.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;rsync source/* destination/&lt;/code&gt; won't bring &lt;code&gt;dir1/&lt;/code&gt; (and the files inside it) into the &lt;code&gt;destination/&lt;/code&gt; directory. However, if you run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsync -r source/ destination/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything will carry over. Neat!&lt;/p&gt;

&lt;h2&gt;
  
  
  Rsync Archive
&lt;/h2&gt;

&lt;p&gt;If you read online articles about rsync, you will notice that many developers use the &lt;code&gt;-a&lt;/code&gt; command (&lt;code&gt;--archive&lt;/code&gt;). This is analogous to running &lt;code&gt;rsync -rlptgoD&lt;/code&gt;. Whoa, that's a lot of options! Don't worry, let's break it down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-r&lt;/code&gt; is recursive, just as you saw above&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-l&lt;/code&gt; copies symlinks and keep them as symlinks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p&lt;/code&gt; preserves file permissions / privileges&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-t&lt;/code&gt; preserves time metadata in a file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-g&lt;/code&gt; preserves a group&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-o&lt;/code&gt; preserves owner (only for super-user)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-D&lt;/code&gt; preserves device and special files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The big picture is, running &lt;code&gt;rsync -a&lt;/code&gt; preserves all the important metadata when transferring files. It is safe to say you will want to run &lt;code&gt;rsync -a&lt;/code&gt; 90% of the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rsync and SSH
&lt;/h2&gt;

&lt;p&gt;You can use rsync over a network connection. If you have access to a remote server, you can quickly sync your directory locally with a remote server, vice versa.&lt;/p&gt;

&lt;p&gt;Wait a second... doesn't that sound like dropbox? Yup! There are tons of other features that Dropbox has that rsync doesn't, but at the gist of it, dropbox is a fancy and glorified rsync with durability added.&lt;/p&gt;

&lt;p&gt;For this section, if you're coding along, I am assuming that you have access to a remote server. If you don't, keep reading but take a mental note. There will probably come a time when you need to do this in the future.&lt;/p&gt;

&lt;p&gt;To rsync your &lt;code&gt;source/&lt;/code&gt; directory to the remote server's &lt;code&gt;~/stash/destination/&lt;/code&gt;, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsync -a source/ yourUserName@123.456.788.000:~/stash/destination/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you store a Host inside SSH config, you can also use that. For example, I have a Host named &lt;code&gt;gc&lt;/code&gt; (Google Compute). To sync the &lt;code&gt;Projects/&lt;/code&gt; directory, I can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsync -a ~/Projects gc:~
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that I don't have a forward slash after &lt;code&gt;Projects&lt;/code&gt; even though it is a directory. When you rsync a directory but you don't pass it a slash, rsync will create a directory with the same name as the source. What this does is it creates a &lt;code&gt;~/Projects/&lt;/code&gt; directory inside my &lt;code&gt;gc&lt;/code&gt; Host.&lt;/p&gt;

&lt;p&gt;Here are some options that can be helpful when transferring files over the net:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-z&lt;/code&gt; to compress data during transfer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-v&lt;/code&gt; stands for verbose. This will show the outputs of the file transfer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-P&lt;/code&gt; stands for &lt;code&gt;--partial&lt;/code&gt; and &lt;code&gt;--progress&lt;/code&gt;: partial creates a partial file, in case a transfer is interrupted and progress shows the file transfer progress. This option is useful for large files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Btw, did you know that you can pass a command when running rsync? &lt;/p&gt;

&lt;p&gt;For example, if I want to rsync only &lt;code&gt;test1.txt&lt;/code&gt;, &lt;code&gt;test2.txt&lt;/code&gt;, ... &lt;code&gt;test9.txt&lt;/code&gt; files from the remote server, I can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsync -avz gc:'`find . -name "*test[0-9].txt"`' ~/Projects/source
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trick here is &lt;code&gt;yourRemoteHost:'YOUR_CMD'&lt;/code&gt;. Note the backtick surrounding the &lt;code&gt;find&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Use this when you need to filter for specific files from a remote host instead of having to manually pick-and-choose the files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rsync and Cron
&lt;/h2&gt;

&lt;p&gt;Rsync reminds me of file-backup services like Dropbox. When combined with cron, you can create an automated job to automatically sync data every day, hour, etc.&lt;/p&gt;

&lt;p&gt;In Mac, I can edit a cron job with the &lt;code&gt;crontab -e&lt;/code&gt; command (yours might be different depending on what OS you have). &lt;/p&gt;

&lt;p&gt;To create a multiple backups:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00 */1 * * * rsync -a --delete /Users/iggy/source/ /Users/iggy/backup/hourly
00 17 * * * rsync -a --delete /Users/iggy/source/ /Users/iggy/backup/daily
00 18 * * 5 rsync -a --delete  /Users/iggy/source/ /Users/iggy/backup/weekly
00 19 1 * * rsync -a --delete /Users/iggy/source/ /Users/iggy/backup/monthly_$(date +%Y%m)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This performs 4 backups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an hourly backup&lt;/li&gt;
&lt;li&gt;a daily backup every day at 5 PM&lt;/li&gt;
&lt;li&gt;a weekly backup every Friday (day 5) at 6PM&lt;/li&gt;
&lt;li&gt;a monthly backup on the 1st at 7PM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first three backups will overwrite the previous backup (it will rsync into the directory with the same name). The monthly backup will have a unique name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Rsync is a powerful command for creating backups or syncing two directories. If you only need to do a one-time copy, the &lt;code&gt;cp&lt;/code&gt; command is probably simpler. But if you need to keep two directories in sync, &lt;code&gt;rsync&lt;/code&gt; is a better option.&lt;/p&gt;

&lt;p&gt;Rsync and cron are like peanut butter and jelly. Together they let you perform automated backups easily. What other uses of rsync can you think of?&lt;/p&gt;

&lt;p&gt;Who knows, maybe in the future you will use rsync to create the next Dropbox rival! When you do, please let me know :). &lt;/p&gt;

&lt;p&gt;Until then, happy coding!&lt;/p&gt;

</description>
      <category>rsync</category>
      <category>backup</category>
      <category>cron</category>
    </item>
    <item>
      <title>Hard Link Vs Symbolic Link 101</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Wed, 25 Aug 2021 13:03:17 +0000</pubDate>
      <link>https://dev.to/iggredible/hard-link-vs-symbolic-link-360b</link>
      <guid>https://dev.to/iggredible/hard-link-vs-symbolic-link-360b</guid>
      <description>&lt;p&gt;You probably have heard of "hard link" (&lt;code&gt;ln&lt;/code&gt;) and "symbolic link" (&lt;code&gt;ln -s&lt;/code&gt;). You may have some vague idea that these commands have something to do with linking a file to another file... or something like that. This article will clarify the differences between &lt;code&gt;ln&lt;/code&gt; and &lt;code&gt;ln -s&lt;/code&gt; and provide some use cases.&lt;/p&gt;

&lt;p&gt;To get the most out of this, I strongly encourage you to code along as you read. Meaningful reading is not passive. It is an active act where you, the reader, must also put in the work to get the most out of this article. &lt;/p&gt;

&lt;p&gt;As much as you can, do lots of experiments on your own: try different variations of a command, repeat the command without looking at the article, and repeat it again the next day to fortify your memory (you'll be surprised at how fast you forget things!).&lt;/p&gt;

&lt;h1&gt;
  
  
  Hard Link
&lt;/h1&gt;

&lt;p&gt;If you have Googled "hard vs soft link" in the past, you might have seen a reference to an "inode". An inode is a file's unique serial number. When you create a new file (&lt;code&gt;touch newfile.txt&lt;/code&gt;), you are actually creating an inode and a link to that inode. That file that you just created consists of at least two parts: an inode (a unique identifier) and a file name.&lt;/p&gt;

&lt;p&gt;Let's create a file, &lt;code&gt;test1.txt&lt;/code&gt;. Inside it, add some texts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch 'hello test1' &amp;gt;&amp;gt; test1.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aight, you created a file. Now let's create a hard link - let's call it &lt;code&gt;hard1.txt&lt;/code&gt;. Remember - when you create a new hard link, you are creating a new link to the inode of the original file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln test1.txt hard1.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;ls -l&lt;/code&gt;. You should see two files displayed: a &lt;code&gt;test1.txt&lt;/code&gt; and a &lt;code&gt;hard1.txt&lt;/code&gt;. If you run &lt;code&gt;cat hard1.txt&lt;/code&gt;, you'll see that it has the same content as &lt;code&gt;test1.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, add a line into &lt;code&gt;test1.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Hello again test1" &amp;gt;&amp;gt; test1.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see "Hello again test1" inside &lt;em&gt;both&lt;/em&gt; &lt;code&gt;test1.txt&lt;/code&gt; and &lt;code&gt;hard1.txt&lt;/code&gt;. Changing the original file changes the hard link file as well!&lt;/p&gt;

&lt;p&gt;What if we change the content of &lt;code&gt;hard1.txt&lt;/code&gt; instead? Let's find out!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Hello from hard1" &amp;gt;&amp;gt; hard1.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see "Hello from hard1" text inside both &lt;code&gt;hard1.txt&lt;/code&gt; and &lt;code&gt;text1.txt&lt;/code&gt;. So changing &lt;em&gt;either&lt;/em&gt; the original or the hard link file changes the other.&lt;/p&gt;

&lt;p&gt;Finally, let's see what happens if we delete the original file, &lt;code&gt;test1.txt&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm test1.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;hard1.txt&lt;/code&gt; is still there and the text inside hasn't changed. Great!&lt;/p&gt;

&lt;p&gt;Let's recap. When you created &lt;code&gt;test1.txt&lt;/code&gt;, you created an inode. It contained "hello test1" initially. This inode (I'll call it "test1 inode") is connected to a file name &lt;code&gt;test1.txt&lt;/code&gt;. When you ran &lt;code&gt;ln test1.txt hard1.txt&lt;/code&gt;, you created a new file name, &lt;code&gt;hard1.txt&lt;/code&gt;, connected to the test1 inode. Think of test1 inode like an underground rabbit's burrow. &lt;code&gt;test1.txt&lt;/code&gt; and &lt;code&gt;hard1.txt&lt;/code&gt; are the two holes connecting that burrow to the surface. From the outside, we see two holes. If you remove one hole, the bunny can still go out from the other hole. If you create a new hard link, you are just creating a third hole to the same, existing burrow. If you delete the &lt;code&gt;test1.txt&lt;/code&gt; burrow, it won't affect &lt;code&gt;hard1.txt&lt;/code&gt; at all! The only way to remove it is to completely remove all references to the inode. You need to remove all the hard links.&lt;/p&gt;

&lt;p&gt;A few things that I'd like you to do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We've deleted &lt;code&gt;test1.txt&lt;/code&gt; but we still have &lt;code&gt;hard1.txt&lt;/code&gt;. Create another hard link out of &lt;code&gt;hard1.txt&lt;/code&gt;, name it &lt;code&gt;anotherhard1.txt&lt;/code&gt;. What do you expect to happen? What does this tell you about the &lt;code&gt;rm&lt;/code&gt; command? &lt;em&gt;(It doesn't really "delete" the file. It actually deletes a link to an inode)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Rename &lt;code&gt;hard1.txt&lt;/code&gt; to another name, &lt;code&gt;hardy1.txt&lt;/code&gt;. What is the relationship between &lt;code&gt;anotherhard1.txt&lt;/code&gt; and &lt;code&gt;hardy1.txt&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Modify the content of one of the hard links. What do you think will happen to the content of the rest of the links?&lt;/li&gt;
&lt;li&gt;When do you think a hard link might come in handy? What is the use case?&lt;/li&gt;
&lt;li&gt;By the way, if you want to see the inode of a file, you can use &lt;code&gt;ls -i hard1.txt&lt;/code&gt;. Compare the inode number of a file vs its hard link and the inode number of a file vs its symlink (do this one later after you read the symlink section). You will find that the hard link has the same inode number as the original link and that a symlink has a different inode number as the original link. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Don't go to the next section yet. Spend some time creating your own hard links. Modify them. Do things that weren't covered in this section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symbolic / Soft link
&lt;/h2&gt;

&lt;p&gt;Unlike a hard link that points a file to an inode, a symbolic link (sometimes known as a soft link) connects by a file name, not an inode. Because it doesn't connect to an inode like that underground rabbit burrow analogy and it only connects on the surface level, their connection is "softer / weaker" than hard links (that's how I think about it anyway). As a result, by simply changing the name of the original file, you destroy its connection.&lt;/p&gt;

&lt;p&gt;Create a new file &lt;code&gt;test2.txt&lt;/code&gt; and add a line into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "hello test2" &amp;gt;&amp;gt; test2.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create a symlink:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln -s test2.txt soft2.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you check the content inside &lt;code&gt;test2.txt&lt;/code&gt; and &lt;code&gt;soft2.txt&lt;/code&gt;, you'll notice that they are one and the same. Good.&lt;/p&gt;

&lt;p&gt;Let's update the content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "hello soft2" &amp;gt;&amp;gt; soft2.txt
cat soft2.txt
cat test2.txt

echo "hello original" &amp;gt;&amp;gt; test2.txt
cat soft2.txt
cat test2.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that updating &lt;em&gt;either&lt;/em&gt; the symlink file or the original file updates the other file. So far symlink acts like a hard link.&lt;/p&gt;

&lt;p&gt;Now here comes the kicker. If you either &lt;em&gt;change the name&lt;/em&gt; of the original file or &lt;em&gt;remove the original file&lt;/em&gt; (&lt;code&gt;rm test2.txt&lt;/code&gt;), it will break the connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm test2.txt

cat soft2.txt
cat: soft2.txt: No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retrospectively, if you had renamed the original file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv test2.txt somethingelse2.txt

cat soft2.txt
cat: soft2.txt: No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if you instead had removed the symlink file instead and kept the original file, the content of the original file is preserved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm soft2.txt

cat test2.txt
# content is still there
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spend some time to play around with symlinks. Do the things that I didn't mention in this section. Learn by breaking things.&lt;/p&gt;

&lt;p&gt;Here are some things to think about:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Can you create a soft link out of a soft link?&lt;/li&gt;
&lt;li&gt;What would happen if you move the location of the original file to a different directory (but keep the same name)?&lt;/li&gt;
&lt;li&gt;Can you create a soft link out of a hard link?&lt;/li&gt;
&lt;li&gt;Can you create a hard link out of a soft link?&lt;/li&gt;
&lt;li&gt;Create a symlink &lt;em&gt;and&lt;/em&gt; a hard link from a file. Do different things to each. Notice how they differ.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Usage
&lt;/h1&gt;

&lt;p&gt;Now that you know what the differences between &lt;code&gt;ln&lt;/code&gt; and &lt;code&gt;ln -s&lt;/code&gt; are, let's talk about usage.&lt;/p&gt;

&lt;p&gt;One usage for a symbolic link is to create portable dotfiles. I use Vim as a text editor. Vim can be configured with a &lt;code&gt;.vimrc&lt;/code&gt; file and a &lt;code&gt;.vim/&lt;/code&gt; directory in the root directory. But what if I want to keep my dotfiles portable and my config files source-of-truth inside &lt;code&gt;~/Projects/iggy-dotfiles/vimrc&lt;/code&gt; and &lt;code&gt;~/Projects/iggy-dotfiles/vim/&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Before learning about &lt;code&gt;ln&lt;/code&gt;, I used to copy-paste the &lt;code&gt;vimrc&lt;/code&gt; file and &lt;code&gt;vim/&lt;/code&gt; directory from my dotfiles into the root directory. But if I copy-paste them, anytime I make changes to &lt;code&gt;~/.vimrc&lt;/code&gt;, I would have to apply the same change to my &lt;code&gt;~/Projects/iggy-dotfiles/vimrc&lt;/code&gt; file (I can also use &lt;code&gt;rsync&lt;/code&gt;, but that still requires a manual syncing). That's not good. I want to change either &lt;code&gt;~/.vimrc&lt;/code&gt; or &lt;code&gt;~/Projects/iggy-dotfiles/vimrc&lt;/code&gt; and have the other file to update automatically - wait a second... this sounds like symlink! &lt;/p&gt;

&lt;p&gt;A better way is to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm ~/.vimrc
ln -s ~/Projects/iggy-dotfiles/vimrc ~/.vimrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, each time I make changes to &lt;em&gt;either&lt;/em&gt; dotfiles vimrc or root vimrc, the content will always be the same. Btw, you can also use a symlink on a directory, so &lt;code&gt;ln -s ~/Projects/iggy-dotfiles/vim/ ~/.vim&lt;/code&gt; should work.&lt;/p&gt;

&lt;p&gt;By the way, you could've also used a hard link, but the popular convention is to use symlink. If I ever need to delete a file, I can just delete &lt;code&gt;~/Projects/iggy-dotfiles/vimrc&lt;/code&gt; and my &lt;code&gt;~/.vimrc&lt;/code&gt; will automatically become obsolete. Having only one source of truth makes it easier to keep track of where things are. If you used a hard link, you'll have to remember to delete all of your vimrc sources.&lt;/p&gt;

&lt;p&gt;You can use this technique with any config files like &lt;code&gt;.zshrc&lt;/code&gt;, &lt;code&gt;.bashrc&lt;/code&gt;, &lt;code&gt;.launch.json&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;On the other hand, hard links are useful for backups. For example, if you have a directory full of books:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aesop_fables.pdf
bradbury_fahrenheit.pdf
calvin_institutes.pdf
darwin_origin.pdf
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assume that you need to create multiple directories so you can sort them based on author and title. It doesn't make sense to copy all your books into the directory &lt;code&gt;authors/&lt;/code&gt; and once more in &lt;code&gt;title/&lt;/code&gt;. It makes more sense if you keep the original books, then create a hard link twice (remember, creating a hard link &lt;em&gt;barely takes up any space&lt;/em&gt;). Inside the &lt;code&gt;authors/&lt;/code&gt; directory you can have your books named and sorted by author. Inside the &lt;code&gt;title/&lt;/code&gt; directory you can name and sort them by title. You can "duplicate" and "sort" your data as many ways as you want and they will barely take up any space.&lt;/p&gt;

&lt;p&gt;We've reached the end. Thanks for making it this far. Hopefully by now you've understood &lt;code&gt;ln&lt;/code&gt; vs &lt;code&gt;ln -s&lt;/code&gt; and put this knowledge to good use. Keep learning and happy coding!&lt;/p&gt;

</description>
      <category>hardlink</category>
      <category>symboliclink</category>
      <category>softlink</category>
      <category>linux</category>
    </item>
    <item>
      <title>Debugging a Rails App in Vim With Vimspector</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Sat, 14 Aug 2021 15:08:11 +0000</pubDate>
      <link>https://dev.to/iggredible/debugging-a-rails-app-in-vim-with-vimspector-pi</link>
      <guid>https://dev.to/iggredible/debugging-a-rails-app-in-vim-with-vimspector-pi</guid>
      <description>&lt;p&gt;&lt;em&gt;Follow &lt;a href="https://twitter.com/learnvim" rel="noopener noreferrer"&gt;@learnvim&lt;/a&gt; for more Vim tips and tricks!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I recently published an article on Vimspector (&lt;a href="https://dev.to/iggredible/debugging-in-vim-with-vimspector-4n0m"&gt;Debugging in Vim with Vimspector&lt;/a&gt;). There I covered different ways to run Vimspector for various Javascript environments. If you're a Rails developer like me, you may ask, "I'm sold on Vimspector, but how can I run it in Rails?"&lt;/p&gt;

&lt;p&gt;To be frank, there are not a lot of resources online on how to accomplish this. After tinkering for a few days, I found a few setups that work on a basic Rails application.&lt;/p&gt;

&lt;p&gt;I am not claiming that this is the foolproof way to debug any Rails application. There are rooms for improvement and exploration. But for starting out, this is sufficient.&lt;/p&gt;

&lt;p&gt;This article assumes that you have had some experience with Vimspector. At minimum, you need to know how to step into, step over, and step out of breakpoints. You also need to know how to launch and restart Vimspector. If you don't, please read my previous article first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Basic Rails App
&lt;/h2&gt;

&lt;p&gt;I am a huge fan of practical learning. I believe you'll get far more mileage if you actually do the steps as you are reading this article. So for the sake of hands-on approach, let's create a brand new Rails app. Don't worry, it should take less than 5 min.&lt;/p&gt;

&lt;p&gt;Create a new Rails app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails new hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails generate controller Says hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go to the controller and write up some codes. Inside &lt;code&gt;./app/controllers/says_controller.rb&lt;/code&gt;, modify the &lt;code&gt;hello&lt;/code&gt; action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SaysController &amp;lt; ApplicationController
  def hello
    @time = DateTime.now
    @greetings = "Greetings"
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify the &lt;code&gt;hello.html.erb&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Says#hello&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;%= @greetings %&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;It is now &amp;lt;%= @time %&amp;gt;&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Excellent! Let's quickly test if the Rails app is running properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;a href="http://localhost:3000/says/hello" rel="noopener noreferrer"&gt;http://localhost:3000/says/hello&lt;/a&gt;. You should also see the values of the &lt;code&gt;@greetings&lt;/code&gt; and &lt;code&gt;@time&lt;/code&gt; instance variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Important Gems
&lt;/h3&gt;

&lt;p&gt;Vimspector isn't a debugger. It's a "middle-man" that talks to a debugger. Vimspector provides a standard protocol to communicate with different debuggers. With Vimspector, you can communicate the same way with a Node debugger, Python debugger, Go debugger, etc.&lt;/p&gt;

&lt;p&gt;For Vimspector to work with Ruby, you need to install a Ruby debugger. We will use &lt;a href="https://github.com/ruby-debug/ruby-debug-ide" rel="noopener noreferrer"&gt;ruby-debug-ide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In addition, you also need to install &lt;code&gt;debase&lt;/code&gt; (&lt;a href="https://github.com/rubyide/vscode-ruby/blob/main/docs/debugger.md" rel="noopener noreferrer"&gt;source&lt;/a&gt;). Add these two in your gemfile (in a real project, you probably want to put them inside the &lt;code&gt;group :development, :test do ...&lt;/code&gt; block)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem 'ruby-debug-ide'
gem 'debase'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Vimspector JSON
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;.vimspector.json&lt;/code&gt; at the Rails project root. Inside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "configurations": {
    "rails": {
      "adapter": "cust_vscode-ruby",
      "default": true,
      "configuration": {
          "name": "Debug Rails server",
          "type": "Ruby",
          "request": "launch",
          "cwd": "${workspaceRoot}",
          "pathToBundler": "/Users/iggy/.rbenv/shims/bundle",
          "pathToRDebugIDE": "/Users/iggy/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ruby-debug-ide-0.7.2",
          "program": "${workspaceRoot}/bin/rails",
          "args": [
              "server"
          ]
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that you have to update &lt;code&gt;pathToRDebugIDE&lt;/code&gt; and &lt;code&gt;pathToBundler&lt;/code&gt; with your own paths. I'll explain below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bundler, Debugger, and Adapter
&lt;/h3&gt;

&lt;p&gt;There are three things that you need to provide Vimspector with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The path to bundler.&lt;/li&gt;
&lt;li&gt;The path to the debugger.&lt;/li&gt;
&lt;li&gt;Which adapter to use.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To get the path for &lt;code&gt;pathToBundler&lt;/code&gt;, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;which bundler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, it returns &lt;code&gt;/User/iggy/.rbenv/shims/bundle&lt;/code&gt;. Use whatever path your machine uses.&lt;/p&gt;

&lt;p&gt;Assuming you have installed the ruby-debug-ide gem via your Rails' Gemfile, to get the &lt;code&gt;pathToRDebugIDE&lt;/code&gt; path, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle show ruby-debug-ide
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my case, it returns &lt;code&gt;/Users/iggy/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ruby-debug-ide-0.7.2&lt;/code&gt;. Use whatever path you see.&lt;/p&gt;

&lt;p&gt;Finally, recall that Vimspector requires a special adapter for each language / environment you use (in my previous article, I installed  adapters - also known as "gadgets" - for node and chrome). Since we're debugging a Ruby framework, we need a Ruby adapter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a Ruby Adapter
&lt;/h3&gt;

&lt;p&gt;If you look at the Vimspector config file above, you'll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"adapter": "cust_vscode-ruby",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, Ruby is not in one of the &lt;a href="https://github.com/puremourning/vimspector#supported-languages" rel="noopener noreferrer"&gt;supported languages in the Vimspector page&lt;/a&gt; (&lt;em&gt;darn it!&lt;/em&gt;). Don't worry, if you dig the Vimspector repo deep enough, you will find instructions on how to "install" a Ruby gadget there.&lt;/p&gt;

&lt;p&gt;Here's &lt;a href="https://github.com/puremourning/vimspector/wiki/languages#ruby-gadget-installer-file" rel="noopener noreferrer"&gt;the page&lt;/a&gt; with information for languages not officially mentioned in the README. If you scroll down, you'll find an instruction for Ruby. &lt;/p&gt;

&lt;p&gt;Follow the instruction on the &lt;a href="https://github.com/puremourning/vimspector/wiki/languages#introduction" rel="noopener noreferrer"&gt;introduction section&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inside the Vimspector &lt;em&gt;directory&lt;/em&gt; (in my case, it is in &lt;code&gt;~/.vim/plugged/vimspector/gadgets/custom/cust_vscode-ruby.json&lt;/code&gt; - yours could be in a different directory depending on what plugin manager you use), add a custom  json file for your language.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;./install_gadget.py --upgrade&lt;/code&gt;. Vimspector should install some files from &lt;code&gt;vscode-ruby&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Phew! We are done with the preliminary setup.&lt;/p&gt;

&lt;p&gt;If you're still curious what just happened, here are a few pages to read:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/puremourning/vimspector/wiki/languages#ruby-gadget-installer-file" rel="noopener noreferrer"&gt;Ruby gadget installer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rubyide/vscode-ruby/blob/main/docs/debugger.md" rel="noopener noreferrer"&gt;VSCode-Ruby Debugger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Program and Args
&lt;/h3&gt;

&lt;p&gt;Let's take another look at a section inside the Vimspector config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"program": "${workspaceRoot}/bin/rails",
"args": [
  "server"
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recall from the previous article, &lt;code&gt;program&lt;/code&gt; is the program that Vimspector will run when you tell it to launch something and &lt;code&gt;args&lt;/code&gt; is the argument that gets passed to &lt;code&gt;program&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When running a rails app, you would (usually) run &lt;code&gt;bin/rails server&lt;/code&gt;. The config does exactly that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Vimspector
&lt;/h2&gt;

&lt;p&gt;Now we are ready to run Vimspector. Our config is set to &lt;code&gt;launch&lt;/code&gt;, so do not run &lt;code&gt;rails s&lt;/code&gt; from the terminal. We will run it from the debugger.&lt;/p&gt;

&lt;p&gt;Go to the &lt;code&gt;says_controller.rb&lt;/code&gt; and add a breakpoint on &lt;code&gt;@time&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SaysController &amp;lt; ApplicationController
  def hello
    @time = DateTime.now # add a breakpoint here
    @greetings = "Greetings"
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Excellent. Now here comes the moment of truth - let's launch Vimspector!&lt;/p&gt;

&lt;p&gt;Wait a few seconds, you should see on the &lt;code&gt;Console&lt;/code&gt; window that Vimspector is launching a Rails app.&lt;/p&gt;

&lt;p&gt;Now, visit &lt;a href="http://localhost:3000/says/hello" rel="noopener noreferrer"&gt;http://localhost:3000/says/hello&lt;/a&gt;. The app should pause.&lt;/p&gt;

&lt;p&gt;Check your Vimspector. You should see it paused at the breakpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4h9k7qgp4wzm6kf59202.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4h9k7qgp4wzm6kf59202.png" alt="Rails Vimspector Launch" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this is what you see, congratulations! You've successfully launched a Rails debugger - from Vim!&lt;/p&gt;

&lt;p&gt;From there, you can step into, step over, and step out of different lines of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attach Vs Launch
&lt;/h2&gt;

&lt;p&gt;There are two ways you can run Vimspector: attach and launch. The former attaches the debugger into an already running process. The latter launches a process from the debugger.&lt;/p&gt;

&lt;p&gt;The Rails example above is an example of launch, as it launches a Rails process directly from the debugger. Theoretically, you should be able to perform either attach or launch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attaching a Debugger to a Rails Server
&lt;/h3&gt;

&lt;p&gt;You've seen how to launch a Rails app from Vimspector. Let's see how you can attach Vimspector to a Rails process.&lt;/p&gt;

&lt;p&gt;First, modify our &lt;code&gt;.vimspector.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "configurations": {
    "rails": {
      "adapter": "cust_vscode-ruby",
      "default": true,
      "configuration": {
          "name": "Debug Rails server",
          "type": "Ruby",
          "request": "attach",
          "cwd": "${workspaceRoot}",
          "remoteHost": "0.0.0.0",
          "remotePort": "1234",
          "pathToBundler": "/Users/iggy/.rbenv/shims/bundle",
          "pathToRDebugIDE": "/Users/iggy/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ruby-debug-ide-0.7.2"
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are the changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;request&lt;/code&gt; is now &lt;code&gt;attach&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We added &lt;code&gt;remoteHost&lt;/code&gt; and &lt;code&gt;remotePort&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We removed &lt;code&gt;"programs"&lt;/code&gt; and &lt;code&gt;"args"&lt;/code&gt; (they are unnecessary for attach).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;remoteHost&lt;/code&gt; and &lt;code&gt;remotePort&lt;/code&gt; are the IP address and port number that we will be running the debugger on. The host is set to &lt;code&gt;0.0.0.0&lt;/code&gt; and the port is set to &lt;code&gt;1234&lt;/code&gt;. These numbers will make sense in a little bit.&lt;/p&gt;

&lt;p&gt;Once your &lt;code&gt;vimspector.json&lt;/code&gt; file is configured, let's run the app. Instead of running the regular &lt;code&gt;bin/rails s&lt;/code&gt;, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rdebug-ide --host 0.0.0.0 --port 1234 --dispatcher-port 1234 -- bin/rails s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will launch the &lt;code&gt;ruby-debug-ide&lt;/code&gt; program installed earlier. Note the host and port numbers: we are running the debugger on host &lt;code&gt;0.0.0.0&lt;/code&gt; and port &lt;code&gt;1234&lt;/code&gt; in addition to running the rails server.&lt;/p&gt;

&lt;p&gt;Next, add the breakpoints inside the &lt;code&gt;says_controller.rb&lt;/code&gt; file, then launch Vimspector. Since we are running Vimspector on attach mode, it won't launch a Rails server this time. Head to the page related to this controller: &lt;a href="http://localhost:3000/says/hello" rel="noopener noreferrer"&gt;http://localhost:3000/says/hello&lt;/a&gt;. Watch your Vimspector pauses at the breakpoint(s). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhc1gtnt8hxs19brnu45k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhc1gtnt8hxs19brnu45k.png" alt="Rails Vimspector Attach" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sweet chocolate pancake! Super cool, isn't it? Well, this also concludes this article.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Congratulations! You've successfully debugged a Rails app. You are one step closer from becoming a supreme master developer.&lt;/p&gt;

&lt;p&gt;There is still much to explore about Vimspector and Rails applications. There are different settings, environments, and configs that I don't mention in this article. Experiment. Share this article. Let me know how you do things differently.&lt;/p&gt;

&lt;p&gt;In the end, I hope that this article has given you a good place to start. Happy Vimming!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Reducing a Screenshot Size in Mac</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Wed, 11 Aug 2021 13:46:09 +0000</pubDate>
      <link>https://dev.to/iggredible/reducing-a-screenshot-size-in-mac-15ic</link>
      <guid>https://dev.to/iggredible/reducing-a-screenshot-size-in-mac-15ic</guid>
      <description>&lt;h1&gt;
  
  
  Motivation
&lt;/h1&gt;

&lt;p&gt;I have a retina 15-inch Macbook (2016, used 🙂). Whenever I take a screenshot, it usually captures a PNG with 2-4MB in size.&lt;/p&gt;

&lt;p&gt;Although storage is getting cheaper nowadays, for its purpose, having 2-4MB screenshots are, in my opinion, still overkill. It could be smaller. Especially if you are using these screenshots in an online storage (they cost $$!). If I can shrink a 2MB image by 90%, I can store ten times as many images!&lt;/p&gt;

&lt;p&gt;In this article, I’ll share simple tips / tricks to reduce the size of my screenshot images. Even if you don’t use Mac, this article should largely be relevant to you - so keep reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  ImageMagick
&lt;/h2&gt;

&lt;p&gt;The main ingredient to accomplish this is a tool called &lt;a href="https://imagemagick.org/index.php" rel="noopener noreferrer"&gt;ImageMagick&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The quickest way to install is to use homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install imagemagick
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have a Windows or a Linux machine, or if you have Mac but want to download it outside of Homebrew, check out the &lt;a href="https://imagemagick.org/script/download.php" rel="noopener noreferrer"&gt;ImageMagick's download page&lt;/a&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  Converting Image With ImageMagick
&lt;/h3&gt;

&lt;p&gt;ImageMagick has a long list of APIs. When you have the time, I strongly encourage you to read what else it can do. &lt;/p&gt;

&lt;p&gt;By default, Macbook a full-screen screenshot has a size of roughly 2000 x 3000 px. Usually, half of that size is sufficient.&lt;/p&gt;

&lt;p&gt;To reduce an image size, we can use ImageMagick's &lt;code&gt;convert&lt;/code&gt; command. To convert an image by 50%, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;convert MY-SCREENSHOT.png -resize 50% MY-RESIZED-SCREENSHOT.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-resize 50%&lt;/code&gt; option will resize the input image by 50%.&lt;/p&gt;

&lt;p&gt;Try it! Take a screenshot of the current window with &lt;code&gt;Cmd + Shift + 4&lt;/code&gt; then press &lt;code&gt;Space&lt;/code&gt;. Click on the window that you want to take a screenshot on. In my case, the resulting screenshot is 2.1MB and has a dimension of 3548 x 2030. That's big!&lt;/p&gt;

&lt;p&gt;Running the &lt;code&gt;convert&lt;/code&gt; command above reduces the dimension to 1792 x 1015. The file size is also reduced down to about 430KB. That's a 80% reduction for a short one-line command!&lt;/p&gt;

&lt;p&gt;Some of you may think 50% is too small - if that's the case, feel free to play around with the &lt;code&gt;resize&lt;/code&gt; option. A good place to start is ImageMagick's &lt;code&gt;resize&lt;/code&gt; documentation: &lt;a href="https://legacy.imagemagick.org/Usage/resize/" rel="noopener noreferrer"&gt;Resize or Scaling (General Techniques)&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  PNGQuant
&lt;/h2&gt;

&lt;p&gt;Reducing an image from 2MB to 400KB is already a significant improvement. However, we can do more. We can do a lossy compression of our image. This is a job for &lt;a href="https://pngquant.org/" rel="noopener noreferrer"&gt;PNGQuant&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Although ImageMagick also performs an image compression, I prefer to use PNGQuant because it has a cleaner API and produces a better output than ImageMagick (disclaimer: I actually haven't spent that much time with ImageMagick's compression tools - take my word with a heavy grain of salt and experiment around with ImageMagick compression tools yourself!)&lt;/p&gt;

&lt;p&gt;You can download PNGQuant with homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install pngquant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compressing with PNGQuant
&lt;/h3&gt;

&lt;p&gt;By default, the screenshots taken by my Mac are PNG files, so it works right out of the box.&lt;/p&gt;

&lt;p&gt;To compress an image, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pngquant MY-IMAGE.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I prefer to add a few extra safeties, so my preferred command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pngquant --skip-if-larger --force --ext=.png MY-IMAGE.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The option &lt;code&gt;--skip-if-larger&lt;/code&gt; skips the image compression process if the resulting image is larger than the input image. I personally always run PNGQuant with this option.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;--ext=.png&lt;/code&gt; creates an image whose extension is a png. By default, PNGQuant creates an output file name ending with &lt;code&gt;-fs8.png&lt;/code&gt;. This option prevents that.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;--force&lt;/code&gt; works in conjunction with &lt;code&gt;--ext&lt;/code&gt;. 

&lt;ul&gt;
&lt;li&gt;Without force, the command above will complain that the file name already exists. &lt;/li&gt;
&lt;li&gt;With force, pngquant will overwrite the image with the compressed version. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;--force --ext=.png&lt;/code&gt; command technically mutates the image. If you prefer to keep the original copy of the image, just remove the &lt;code&gt;--force --ext=.png&lt;/code&gt; options.&lt;/p&gt;

&lt;p&gt;You can either run the PNGQuant command by itself against a freshly captured screenshot or against a resized screenshot. If you choose to run both the ImageMagick and PNGQuant commands together, run the ImageMagick command first. If you run the PNGQuant first followed by the ImageMagick command, you may end up with a less compressed image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting Them Together and Creating a Bash Command
&lt;/h2&gt;

&lt;p&gt;Inside my &lt;code&gt;.bashrc&lt;/code&gt; / &lt;code&gt;.zshrc&lt;/code&gt; / whatever, I created this mini utility function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minimg() {
  echo "Resizing $1"
  convert $1 -resize 50% $1
  pngquant --skip-if-larger --force --ext=.png $1
  echo "Done!"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to save and source the file. With this, I can just run this to resize the image and compress it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minimg MY-IMAGE.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On average, this reduces a screenshot image from 2MB to roughly 150KB, a 92.5% reduction. Not bad!&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra: taking screenshot and resizing the image
&lt;/h2&gt;

&lt;p&gt;If you prefer to run everything from the terminal, you can modify the function to include the &lt;code&gt;screencapture&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;screencap() {
  echo "Screencapturing.."
  screenshot=$(which screencapture)
  $screenshot -i $1
  if test -f "$1"; then
    echo "Resizing $1"
    convert $1 -resize 50% $1
    pngquant --skip-if-larger --force --ext=.png $1
    echo "Done!"
  fi
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;screencapture&lt;/code&gt; command above is equivalent to Mac's &lt;code&gt;Cmd + Shift + 4&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;For example, to take a screencapture from CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;screencapture -i say-cheese.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running this command, notice that your cursor turns into a screencapture crosshair (if you press &lt;code&gt;Space&lt;/code&gt; in this mode, it turns into a window screen capture). With this function, you can take a screenshot, resize it, then compress it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;That's it. That’s how I resize my screenshots. I hope you're now able to take much lower resolution screenshots and make a better use of your local / cloud storage. More importantly, now that you have smaller screenshots, they will be easier to transport around. Plus you get to learn a little bit about image modification. I think it's a win-win.&lt;/p&gt;

</description>
      <category>screenshot</category>
      <category>image</category>
      <category>imagemagick</category>
      <category>png</category>
    </item>
    <item>
      <title>Debugging in Vim with Vimspector</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Sat, 07 Aug 2021 13:57:58 +0000</pubDate>
      <link>https://dev.to/iggredible/debugging-in-vim-with-vimspector-4n0m</link>
      <guid>https://dev.to/iggredible/debugging-in-vim-with-vimspector-4n0m</guid>
      <description>&lt;p&gt;&lt;em&gt;Follow &lt;a href="https://twitter.com/learnvim" rel="noopener noreferrer"&gt;@learnvim&lt;/a&gt; for more Vim tips and tricks!&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Debugging in Vim with Vimspector
&lt;/h1&gt;

&lt;p&gt;Vimspector is a powerful graphical debugger plugin for Vim. However, it also will take you a while to get started. In this article, I will show you how to use Vimspector to debug:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Node file.&lt;/li&gt;
&lt;li&gt;Client-side app using Chrome.&lt;/li&gt;
&lt;li&gt;Jest testing.&lt;/li&gt;
&lt;li&gt;An Express app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both their &lt;a href="https://github.com/puremourning/vimspector" rel="noopener noreferrer"&gt;Github page&lt;/a&gt; and their &lt;a href="https://puremourning.github.io/vimspector-web/" rel="noopener noreferrer"&gt;website&lt;/a&gt; are very comprehensive. I would suggest you read them when you have the chance!&lt;/p&gt;

&lt;p&gt;Much content found in this article can be found inside the Vimspector websites. However, when I was reading them, I was overwhelmed by the sheer amount of the information. This article serves as a bridge to get you started as early as possible. I think it is beneficial to get our hands dirty early-on. Once you start using it, reading the docs becomes clearer. Although I am using the Javascript ecosystem as examples (backend, frontend, testing), you should be able to apply the same concept to any language of your choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;At the time of this writing, I am using Vim 8.2 on MacOS Catalina. This guide should work with any OS (with appropriate modifications). The Vimspector Github page though, recommends you to have either Vim 8.2 or NeoVim 0.4.3. You also need to have Python 3.6 or up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Overview
&lt;/h2&gt;

&lt;p&gt;So what is Vimspector? How does it work?&lt;/p&gt;

&lt;p&gt;Vimspector is not a universal language debugger. It technically does not handle the debugging. Think of it like a middle-man that facilitates communicating with the debugger for your language-of-choice. It relies on specific gadgets depending on what language you are working with. So if you want to debug a node application, use the &lt;code&gt;vscode-node-debug2&lt;/code&gt; gadget. If you want to debug a go app, use &lt;code&gt;vscode-go&lt;/code&gt; gadget. If you want to debug a client-side JS app, use &lt;code&gt;debugger-for-chrome&lt;/code&gt; gadget.&lt;/p&gt;

&lt;p&gt;Different languages have different debuggers. Some have built-in debuggers while some use external libraries for debugging. If we want to integrate multiple languages into our favorite editors / IDEs, it could get messy. A Python debugger communicates differently from a Node debugger. A Node debugger behaves differently from a front-end JS debugger via Chrome. If you're a Ruby / Javascript developer, you could technically have a Ruby and Node debuggers installed in your editor / IDE. But these two debuggers probably have different protocols and exhibit different behaviors. The more languages / environments you deal with, the more the complexity increases.&lt;/p&gt;

&lt;p&gt;So having different language environments to debug can get messy. To reconcile these differences, we need to bridge the gap between language X debugger and our editor / IDE - we need an abstract protocol. This protocol is known as Debug Adapter Protocol (DAP). DAP was originally created by the VSCode team. But luckily for us, they decided to make it (somewhat) editor agnostic, so developers can use it for other editors / IDEs. Vimspector is the result of DAP development for the Vim editor. For a list of tools that support DAP, check out this page: &lt;a href="https://microsoft.github.io/debug-adapter-protocol/implementors/tools/" rel="noopener noreferrer"&gt;Tools Supporting the DAP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Although not required readings, but when you have the time, I would strongly recommend you to look into these pages to get a better understanding on DAP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/" rel="noopener noreferrer"&gt;Debug Adapters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://microsoft.github.io/debug-adapter-protocol/overview" rel="noopener noreferrer"&gt;DAP Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/docs/editor/debugging" rel="noopener noreferrer"&gt;VSCode Debugging&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, enough theory - let's get started with an actual example!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;To get started, install Vimspector if you haven't. Follow the &lt;a href="https://github.com/puremourning/vimspector#installation" rel="noopener noreferrer"&gt;Vimspector installation guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For me, I used &lt;a href="https://github.com/junegunn/vim-plug" rel="noopener noreferrer"&gt;vim-plug&lt;/a&gt;. All I did was add the following in my vimrc's list of plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plug 'puremourning/vimspector'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then sourced my vimrc and ran &lt;code&gt;:PlugInstall&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;The fastest way to learn a new skill is to jump into it and learn it along the way. You may have a lot of questions right now, but once you see how it works, by the end of this article, I hope that some of your questions will be answered.&lt;/p&gt;

&lt;p&gt;Let's go through the node example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging a node app
&lt;/h3&gt;

&lt;p&gt;The Vimspector plugin itself already comes with examples. Go to the directory where Vim saves your Vimspector plugin. I am using vim-plugged, so my plugins are installed inside the &lt;code&gt;plugged/&lt;/code&gt; directory. In my case, the directory is in &lt;code&gt;~/.vim/plugged/vimspector/&lt;/code&gt;. Yours might be in a different location, depending on your plugin manager and your system. Once you find them, from the &lt;code&gt;vimspector/&lt;/code&gt; directory, go to the &lt;code&gt;/support/test/&lt;/code&gt; directory. Inside this directory, you will find different examples that I also strongly encourage you to check out once you're done reading this article.&lt;/p&gt;

&lt;p&gt;Since this section is about debugging a node app, let's check out the node directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd node/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside, at the time of this writing, you should find a directory named &lt;code&gt;simple/&lt;/code&gt;. Go there and you'll see a &lt;code&gt;simple.js&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Before we debug this file, there are at least two requirements to debug with Vimspector: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A relevant gadget.&lt;/li&gt;
&lt;li&gt;A Vimspector config file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A gadget is a debug adapter (like the ones listed in &lt;a href="https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/" rel="noopener noreferrer"&gt;Microsoft's Debug Adapters page&lt;/a&gt;). Since we are debugging a node app, we need a node adapter. This node adapter will relay messages between NodeJS and the abstract protocol DAP.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(By the way, before installing the node adapter, per &lt;a href="https://github.com/puremourning/vimspector#javascript-typescript-etc" rel="noopener noreferrer"&gt;Vimspector's site&lt;/a&gt;, you need to be using a Node version between 6 and 12).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For the first requirement, to install a node adapter, from Vim, run &lt;code&gt;:VimspectorInstall vscode-node-debug2&lt;/code&gt;.You need a different gadget when you are debugging a different language/environment. If you need to debug a Python file, you have to install a python gadget. If you are debugging a Go file, you have to install a Go gadget. Since we are debugging a node app, we need to install a node gadget. For a list of gadgets, check out this section from the Vimspector Github page: &lt;a href="https://github.com/puremourning/vimspector#supported-languages" rel="noopener noreferrer"&gt;Supported Languages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the second requirement, the &lt;code&gt;.vimspector.json&lt;/code&gt; file is conveniently already located at the root of the project (inside &lt;code&gt;simple/&lt;/code&gt;). If you check the hidden files of the &lt;code&gt;vimspector/support/test/simple/&lt;/code&gt; directory, there should already be one &lt;code&gt;.vimspector.json&lt;/code&gt; file available, so you don't need to do anything. Keep in mind that when you are inspecting your own project, remember to create your own vimspector file.&lt;/p&gt;

&lt;p&gt;With those two requirements in place, let's debug.&lt;/p&gt;

&lt;p&gt;Vimspector offers many commands and shortcuts. Using them all when you're starting can be overwhelming. I found that the following are sufficient to get started with. Below are some of my vimrc vimspector shortcuts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nnoremap &amp;lt;Leader&amp;gt;dd :call vimspector#Launch()&amp;lt;CR&amp;gt;
nnoremap &amp;lt;Leader&amp;gt;de :call vimspector#Reset()&amp;lt;CR&amp;gt;
nnoremap &amp;lt;Leader&amp;gt;dc :call vimspector#Continue()&amp;lt;CR&amp;gt;

nnoremap &amp;lt;Leader&amp;gt;dt :call vimspector#ToggleBreakpoint()&amp;lt;CR&amp;gt;
nnoremap &amp;lt;Leader&amp;gt;dT :call vimspector#ClearBreakpoints()&amp;lt;CR&amp;gt;

nmap &amp;lt;Leader&amp;gt;dk &amp;lt;Plug&amp;gt;VimspectorRestart
nmap &amp;lt;Leader&amp;gt;dh &amp;lt;Plug&amp;gt;VimspectorStepOut
nmap &amp;lt;Leader&amp;gt;dl &amp;lt;Plug&amp;gt;VimspectorStepInto
nmap &amp;lt;Leader&amp;gt;dj &amp;lt;Plug&amp;gt;VimspectorStepOver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to steal what I have or make your own. Vimspector also comes with a set of shortcuts called the &lt;a href="https://github.com/puremourning/vimspector#human-mode" rel="noopener noreferrer"&gt;human-mode mapping&lt;/a&gt;. If you're used to VSCode debugging shortcut, you may feel more at home with them.&lt;/p&gt;

&lt;p&gt;Finally, let's open &lt;code&gt;simple.js&lt;/code&gt;. It should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var msg = 'Hello, world!'

var obj = {
  test: 'testing',
  toast: function() {
    return 'toasty' + this.test;
  }
}

console.log( "OK stuff happened " + obj.toast() )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To launch vimspector, run the launch command. Press &lt;code&gt;&amp;lt;Leader&amp;gt;dd&lt;/code&gt; (&lt;code&gt;:call vimspector#Launch()&lt;/code&gt;).  You should see a Vimspector window. Pretty cool! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5c5jkjd6awnktzqis1cn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5c5jkjd6awnktzqis1cn.png" alt="Vimspector layout" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There should be 6 different windows displayed - depending on your Vim orientation, you may see them in different order. If you have never used a debugger before, don't feel intimidated. You'll get used to some of them after playing with them for a while. To exit Vimspector, press &lt;code&gt;&amp;lt;Leader&amp;gt;de&lt;/code&gt; (&lt;code&gt;:call vimspector#Reset()&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;By the way, there will be some prompts on the bottom of the windows when you launch vimspector, asking for something like &lt;code&gt;...Break on Uncaught Exceptions?&lt;/code&gt;. I usually pressed &lt;code&gt;N&lt;/code&gt;. If you don't want to get prompted all the time, add these in your vimspector.json file inside the &lt;code&gt;"run": { ...&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ...
  "breakpoints": {
    "exception": {
      "all": "N",
      "uncaught": "N"
    }
  },
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My full vimspector json (so you can just copy paste it) for this file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "configurations": {
    "run": {
      "adapter": "vscode-node",
      "breakpoints": {
        "exception": {
          "all": "N",
          "uncaught": "N"
        }
      },
      "configuration": {
        "request": "launch",
        "protocol": "auto",
        "stopOnEntry": true,
        "console": "integratedTerminal",
        "program": "${workspaceRoot}/simple.js",
        "cwd": "${workspaceRoot}"
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Back to the debugging, start the vimspector again (&lt;code&gt;&amp;lt;Leader&amp;gt;dd&lt;/code&gt;). Since we have &lt;code&gt;stepOnEntry&lt;/code&gt; to be &lt;code&gt;true&lt;/code&gt; in the Vimspector json file, Vimspector will stop on the first line even though you haven't marked a breakpoint.&lt;/p&gt;

&lt;p&gt;To traverse through the file, you can either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Step out (steps out of the scope)&lt;/li&gt;
&lt;li&gt;Step into (steps into the function scope)&lt;/li&gt;
&lt;li&gt;Step over (steps to the next line, in scope)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here are the key maps that I use. Note that I use &lt;code&gt;hlj&lt;/code&gt; keys similar to the Vim movement keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nmap &amp;lt;Leader&amp;gt;dh &amp;lt;Plug&amp;gt;VimspectorStepOut
nmap &amp;lt;Leader&amp;gt;dl &amp;lt;Plug&amp;gt;VimspectorStepInto
nmap &amp;lt;Leader&amp;gt;dj &amp;lt;Plug&amp;gt;VimspectorStepOver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are not sure what stepping out, stepping into, and stepping over are, I found these short video tutorials very helpful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=KEdq7gC_RTA&amp;amp;t=347s" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=KEdq7gC_RTA&amp;amp;t=347s&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ypxabWbxSBY" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=ypxabWbxSBY&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Back to our debugging - now that we are on the first line of the code, press &lt;code&gt;&amp;lt;Leader&amp;gt;dj&lt;/code&gt; (&lt;code&gt;&amp;lt;Plug&amp;gt;VimspectorStepOver&lt;/code&gt;). Note the highlight moves to the variable declaration. If you press &lt;code&gt;&amp;lt;Leader&amp;gt;dj&lt;/code&gt; one more time, it will move down again. If you keep stepping over, eventually you will reach the end of &lt;code&gt;simple.js&lt;/code&gt; file. Unfortunately, you can't step "back" to the previous line. Once you're on the next step, you continue forward until you reach the end.&lt;/p&gt;

&lt;p&gt;If you accidentally step over an important line, just restart the debugger. To restart, run &lt;code&gt;&amp;lt;Leader&amp;gt;dk&lt;/code&gt; (&lt;code&gt;&amp;lt;Plug&amp;gt;VimspectorRestart&lt;/code&gt;). When you restart, Vimspector starts over from the beginning. Alternatively, you could also Reset and Launch Vimspector again.&lt;/p&gt;

&lt;p&gt;You can put breakpoints throughout the file. Back in the main &lt;code&gt;simple.js&lt;/code&gt; file, run &lt;code&gt;&amp;lt;Leader&amp;gt;dt&lt;/code&gt; (&lt;code&gt;:call vimspector#ToggleBreakpoint()&lt;/code&gt;) on the line where you want to add a breakpoint (run that command again on the line with the breakpoint to remove it).&lt;/p&gt;

&lt;p&gt;Once you sprinkle breakpoints all over your file, launch Vimspector again. If you press &lt;code&gt;&amp;lt;Leader&amp;gt;dc&lt;/code&gt; (&lt;code&gt;:call vimspector#Continue()&lt;/code&gt;), Vimspector will jump to the next breakpoint. Pretty cool!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7alill7meanmvus075d2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7alill7meanmvus075d2.png" alt="Vimspector continue" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To clear the breakpoints, run &lt;code&gt;&amp;lt;Leader&amp;gt;dT&lt;/code&gt; (&lt;code&gt;:call vimspector#ClearBreakpoints()&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Before moving on to the next section, spend 10-15 minutes experimenting with &lt;code&gt;simple.js&lt;/code&gt;. Change the codes in &lt;code&gt;simple.js&lt;/code&gt;. Move around. Play.&lt;/p&gt;

&lt;p&gt;Before we move on to the next section, let's briefly go over what  the 6 Vimspector windows do.&lt;/p&gt;

&lt;h4&gt;
  
  
  Variables window
&lt;/h4&gt;

&lt;p&gt;The Variables window contains the available variables (and their current values) relative to their current scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Scope: Local
  + this (Object): Object
  - __dirname (string): "/Users/iggy/.vim/plugged/vimspector/support/test/node/simple"
  - __filename (string): "/Users/iggy/.vim/plugged/vimspector/support/test/node/simple/simple.js"
  + exports (Object): Object {}
  + module (Object): Module {id: ".", path: "/Users/iggy/.vim/plugged/vimspector/support/test/n…", exports: Object, …}
 *- msg (undefined): undefined
 *- obj (undefined): undefined
  + require (Function): function require(path) { … }
+ Scope: Global
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, inside the Local scope, I have common Node variables like &lt;code&gt;this&lt;/code&gt;, &lt;code&gt;__dirname&lt;/code&gt;, &lt;code&gt;__filename&lt;/code&gt; and the written variables &lt;code&gt;msg&lt;/code&gt; and &lt;code&gt;obj&lt;/code&gt;. Pay attention as you step over to the next variable. Watch them go from undefined to having a value.&lt;/p&gt;

&lt;p&gt;Do this: step over and into different function scopes. Find a way to get inside a function and see what the available variables are. Then step outside and compare them. Also check what is inside &lt;code&gt;Scope: Global&lt;/code&gt;. Why does it have the variables it has? What does it tell you about Node?&lt;/p&gt;

&lt;h4&gt;
  
  
  Watch Window
&lt;/h4&gt;

&lt;p&gt;The Watch window is where you can watch for specific values. Initially it will be blank. If you want to watch the value of the &lt;code&gt;msg&lt;/code&gt; variable, type into the Watch window that variable, &lt;code&gt;msg&lt;/code&gt;. When you're at the start of the file, the value will be &lt;code&gt;undefined&lt;/code&gt;. Then as you steps over, the value will change into &lt;code&gt;'Hello, world!'&lt;/code&gt;. &lt;/p&gt;

&lt;h4&gt;
  
  
  Stack Trace window
&lt;/h4&gt;

&lt;p&gt;The Stack Trace window displays the call stack of the node file execution.&lt;/p&gt;

&lt;h4&gt;
  
  
  Console window
&lt;/h4&gt;

&lt;p&gt;In the Console window, you can enter the defined variables like &lt;code&gt;msg&lt;/code&gt;. You can also evaluate expressions.&lt;/p&gt;

&lt;h4&gt;
  
  
  Terminal window
&lt;/h4&gt;

&lt;p&gt;The Terminal window displays all the outputs throughout the entire debugging session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging in a Browser
&lt;/h3&gt;

&lt;p&gt;Let's explore how to use the Chrome-debugger to debug a client-side app. Lucky for us, there is also an example in the Vimspector directory. Inside &lt;code&gt;~/.vim/plugged/vimspector/support/test/chrome/&lt;/code&gt; directory, you will find a file named &lt;code&gt;run_server&lt;/code&gt;, a &lt;code&gt;test.js&lt;/code&gt;, and a &lt;code&gt;.vimspector.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's check out what is inside the vimspector config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "configurations": {
    "launch": {
      "adapter": "chrome",
      "configuration": {
        "request": "launch",
        "url": "http://localhost:1234/",
        "webRoot": "${workspaceRoot}/www"
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration sure looks different from the Node Vimspector config one we saw earlier. One important line is &lt;code&gt;"adapter": "chrome"&lt;/code&gt; - it indicates that we will be using a Chrome adapter. The URL is defined to be on &lt;code&gt;localhost:1234&lt;/code&gt; because that's the port where our server will be running on.&lt;/p&gt;

&lt;p&gt;Btw, when you launch Vimspector later, it will prompt if you want to break on uncaught exceptions etc again. If you don't want to deal with those prompts, add these lines inside the &lt;code&gt;.vimspector.json&lt;/code&gt; just like you added it to your Node app earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"breakpoints": {
  "exception": {
    "all": "N",
    "uncaught": "N"
  }
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to install the correct gadget. In the earlier section, we installed one with &lt;code&gt;:VimspectorInstall vscode-node-debug2&lt;/code&gt;. This time we have to install one for chrome. Run this from Vim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:VimspectorInstall debugger-for-chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once done, run the server (make sure you have PHP installed):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./run_server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out &lt;code&gt;localhost:1234&lt;/code&gt;. You should see a simple app with some pop-out modals.&lt;/p&gt;

&lt;p&gt;Now open &lt;code&gt;www/js/test.js&lt;/code&gt;. Add breakpoints anywhere you like. Run the Vimspector launch command &lt;code&gt;&amp;lt;Leader&amp;gt;dd&lt;/code&gt;. By running it, it will automatically launch the Chrome browser. Vimspector will pause the Chrome browser where your breakpoints are. Step over and step into your breakpoints. Watch some variables. Change the code. Play around!&lt;/p&gt;

&lt;p&gt;Note: check out the Variables window. Check out both the Local and Global scope. Did you see anything different in the Global scope compared to when you're debugging with Node? What does this tell you about client-side vs backend code execution?&lt;/p&gt;

&lt;p&gt;Note 2: notice how this time, when you launch Vimspector, it launches a Chrome browser. If you look at the &lt;code&gt;.vimspector.json&lt;/code&gt;, you'll see a &lt;code&gt;"request": "launch",&lt;/code&gt; instead of &lt;code&gt;"request": "attach",&lt;/code&gt; from earlier Node debugging. How are they different? There are two ways you can debug an app: by attaching it to an already running process or by launching a new process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging a Jest test
&lt;/h2&gt;

&lt;p&gt;Now let's learn how to debug a Jest test. For this section, I will be using the &lt;a href="https://github.com/microsoft/vscode-recipes/" rel="noopener noreferrer"&gt;vscode-recipes&lt;/a&gt; repository. First go to the site and clone the repository. Then go to the &lt;code&gt;debugging-jest-tests/&lt;/code&gt; directory. You will find two directories: &lt;code&gt;lib/&lt;/code&gt; and a &lt;code&gt;test/&lt;/code&gt;. This is our workspace root directory. &lt;/p&gt;

&lt;p&gt;First, install the dependencies: &lt;code&gt;npm i&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Make sure that the Jest test is running and they are all passing: &lt;code&gt;npm run test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Debugging a Jest test requires a node debugger. If you've been typing along, you should already have the Node debugger from earlier. With Vimspector, you install your gadget only once (Vimspector saves all the installed gadgets inside the Vimspector directory - in my case, they are stored inside &lt;code&gt;~/.vim/plugged/vimspector/&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;debugging-jest-tests/&lt;/code&gt; directory, add a &lt;code&gt;.vimspector.json&lt;/code&gt; file. Inside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "configurations": {
    "my awesome jest test": {
      "adapter": "vscode-node",
      "breakpoints": {
        "exception": {
          "all": "N",
          "uncaught": "N"
        }
      },
      "configuration": {
        "request": "launch",
        "name": "Jest debugger",
        "type": "node",
        "console": "integratedTerminal",
        "program": "${workspaceRoot}/node_modules/.bin/jest",
        "skipFiles": ["*/&amp;lt;node_internals&amp;gt;/**/*.js", "node_modules/**/*.js"],
        "cwd": "${workspaceRoot}"
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration looks familiar, with a new addition of: &lt;code&gt;"program"&lt;/code&gt;: "&lt;code&gt;${workspaceRoot}/node_modules/.bin/jest"&lt;/code&gt;. Here's the breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;workspaceRoot&lt;/code&gt; is the current directory (the &lt;code&gt;debugging-jest-tests/&lt;/code&gt; directory). &lt;/li&gt;
&lt;li&gt;The &lt;code&gt;node_modules/.bin/jest&lt;/code&gt; is the Jest executable from the &lt;code&gt;node_modules/&lt;/code&gt; (which you should have after &lt;code&gt;npm i&lt;/code&gt;). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This time when you run the debugger, Vimspector needs to run the Jest executable. One place where you can find a Jest executable is inside the &lt;code&gt;node_modules/&lt;/code&gt; directory. You could've also run it from the global Jest command, but I like to keep it compartmentalized (what if I am running this from a container and I'm not guaranteed to have a global Jest command? By using the &lt;code&gt;.bin/jest&lt;/code&gt; command, I'm guaranteed to have it - but that's just my personal preference).&lt;/p&gt;

&lt;p&gt;Cool! Let's put some breakpoints inside the test files, then launch the Vimspector (&lt;code&gt;&amp;lt;Leader&amp;gt;dd&lt;/code&gt;). Voila! Your test suite will pause and you can now debug your code.&lt;/p&gt;

&lt;p&gt;If you put your breakpoint on the line where it calls the function, like the function &lt;code&gt;add()&lt;/code&gt; below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
it('Should return correct result', () =&amp;gt; {
  const result = add(1, 2); // put a breakpoint here
  expect(result).toEqual(3);
});
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you step into it (&lt;code&gt;&amp;lt;Leader&amp;gt;dl&lt;/code&gt;), it will go into the original function declaration inside &lt;code&gt;lib/calc.js&lt;/code&gt;, allowing you to investigate the source code. How awesome is that!? With this, you can debug a faulty test down to where the function originated!&lt;/p&gt;

&lt;p&gt;There is one problem. With the current Vimspector config, it will run &lt;em&gt;all&lt;/em&gt; the tests when you launch it. That's great but in real life, your app probably has hundreds of tests (if you've been practicing TDD... &lt;strong&gt;wink wink&lt;/strong&gt;). Running &lt;em&gt;all&lt;/em&gt; tests are probably not the best way to live your life. What if you want to run one particular test at a time?&lt;/p&gt;

&lt;p&gt;You sure can!&lt;/p&gt;

&lt;p&gt;In Jest, you can run a specific file by passing that file name (or part of the name) as an argument. If you want to run only the &lt;code&gt;add.spec.js&lt;/code&gt;, you can run the command &lt;code&gt;jest add&lt;/code&gt;. Jest is smart enough to match the &lt;code&gt;add.spec.js&lt;/code&gt; and not the &lt;code&gt;subtract.spec.js&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you want to match a particular test in a file, Jest is also smart enough to match any keyword you pass using the &lt;code&gt;-t&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;Suppose that inside the &lt;code&gt;add.spec.js&lt;/code&gt; I have two tests (notice that I modified the test descriptions):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { add } = require('../lib/calc');

describe('When adding numbers', () =&amp;gt; {
  it('one should return correct result', () =&amp;gt; {
    const result = add(1, 2);
    expect(result).toEqual(3);
  });

  it('two should not return correct result', () =&amp;gt; {
    const result = add(1, 5);
    expect(result).not.toEqual(3);
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I want to run only the second test. To do that, from the CLI I can run &lt;code&gt;test add -t two&lt;/code&gt;. Jest is smart enough to run only &lt;code&gt;add.spec.js&lt;/code&gt; &lt;strong&gt;and&lt;/strong&gt; only the &lt;code&gt;'two should not return correct result'&lt;/code&gt; test! Try it.&lt;/p&gt;

&lt;p&gt;Armed with that knowledge, we need to pass these arguments when running Vimspector. Turns out that Vimspector has the &lt;code&gt;args&lt;/code&gt; attribute where you can pass argument(s) to your program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "configurations": {
    "jest": {
      "adapter": "vscode-node",
      "breakpoints": {
        "exception": {
          "all": "N",
          "uncaught": "N"
        }
      },
      "configuration": {
        "request": "launch",
        "name": "Jest debugger",
        "type": "node",
        "console": "integratedTerminal",
        "program": "${workspaceRoot}/node_modules/.bin/jest",
        "skipFiles": ["*/&amp;lt;node_internals&amp;gt;/**/*.js", "node_modules/**/*.js"],
        "cwd": "${workspaceRoot}",
        "args": [
                "${FileName}",
                "-t",
                "${TestName}"
            ]
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our new attribute, &lt;code&gt;args&lt;/code&gt;, is an array with 3 elements. The funny looking variables (&lt;code&gt;${FileName}&lt;/code&gt; and &lt;code&gt;${TestName}&lt;/code&gt;) are the Vimspector's named arguments. With this I can pass the &lt;code&gt;FileName&lt;/code&gt; and &lt;code&gt;TestName&lt;/code&gt; variables when launching Vimspector.&lt;/p&gt;

&lt;p&gt;Let's launch Vimspector again. This time it will prompt: "Enter value for FileName" (in which you'll enter "add"). After that, the Vimspector will prompt: "Enter value for TestName" (in which you'll enter "two"). And watch it runs only that particular test from that particular file. Success!! &lt;/p&gt;

&lt;p&gt;Now you have &lt;strong&gt;no&lt;/strong&gt; excuse not to practice TDD! :D&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging an Express App
&lt;/h2&gt;

&lt;p&gt;For the next example, let's try to debug a simple Express app. Since express is a node library, a node gadget is required.&lt;/p&gt;

&lt;p&gt;Create a directory (&lt;code&gt;mkdir express-debug&lt;/code&gt;) and go in there. Run &lt;code&gt;npm init -y&lt;/code&gt; to initialize an NPM project. Install express (&lt;code&gt;npm i express&lt;/code&gt;). Then create an &lt;code&gt;app.js&lt;/code&gt;. Inside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const app = express();
const port = 3000;

const helloFunc = () =&amp;gt; {
  const hello = 'hello';
  return hello;
};

app.get('/', (req, res) =&amp;gt; {
  const msg = helloFunc();
  res.send(msg);
});

app.listen(port, () =&amp;gt; {
  console.log(`Example app listening on port ${port}!`)
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.vimspector.json&lt;/code&gt; in that directory. At minimum you should have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "configurations": {
    "run": {
      "adapter": "vscode-node",
      "default": true,
      "configuration": {
        "type": "node",
        "request": "attach",
        "processId": "${processId}"
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, it's probably better if we enable some default configs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "configurations": {
    "run": {
      "adapter": "vscode-node",
      "default": true,
      "breakpoints": {
        "exception": {
          "all": "N",
          "uncaught": "N"
        }
      },
      "configuration": {
        "name": "Attaching to a process ID",
        "type": "node",
        "request": "attach",
        "skipFiles": ["node_modules/**/*.js", "&amp;lt;node_internals&amp;gt;/**/*.js"],
        "processId": "${processId}"
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the express app in inspect mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node --inspect app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see your app running on &lt;code&gt;localhost:3000&lt;/code&gt;. Next, add a few breakpoints inside &lt;code&gt;app.js&lt;/code&gt;, then launch Vimspector (it will also ask for &lt;code&gt;processId&lt;/code&gt;, but I find that not giving it any value and simply pressing the Return/Enter key works).&lt;/p&gt;

&lt;p&gt;Finally, refresh the page and you should see the debugger pauses at your first breakpoint. From there, you can step out, step into, and step over your code. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvf78ki6u7pmopbgq8g4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvf78ki6u7pmopbgq8g4g.png" alt="Vimspector express" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You've successfully debugged an express app.&lt;/p&gt;

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

&lt;p&gt;This article barely scratched the surface of what a debugger can do. There are many more things that you can do with Vimspector. Hopefully by approaching it from different angles, you'll gain a more thorough understanding of this plugin. &lt;/p&gt;

&lt;p&gt;Your debugging needs probably differ from the examples I gave in this article, but I am a sincere believer that if you understand the principles behind it, you should be able to implement Vimspector to meet your needs.&lt;/p&gt;

&lt;p&gt;With that, thanks for reading this far. Happy Vimming!&lt;/p&gt;

</description>
      <category>vim</category>
      <category>vimspector</category>
      <category>debug</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Executing a Command in Multiple Files in Vim</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Thu, 03 Jun 2021 15:15:28 +0000</pubDate>
      <link>https://dev.to/iggredible/executing-a-command-in-multiple-files-in-vim-187j</link>
      <guid>https://dev.to/iggredible/executing-a-command-in-multiple-files-in-vim-187j</guid>
      <description>&lt;h1&gt;
  
  
  Executing a Command in Multiple Files in Vim
&lt;/h1&gt;

&lt;p&gt;When editing, you may need to execute a command across multiple files. For example, replacing all &lt;code&gt;let&lt;/code&gt; with &lt;code&gt;const&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;There are eight different ways you can do this in Vim.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:argdo    argument list (files)
:bufdo    buffers
:windo    windows in the current tab
:tabdo    tabs
:cdo      each item in the quickfix list
:cfdo     each file in the quickfix list
:ldo      each item in the location list
:lfdo     each file in the location list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eight sounds like a lot of methods learn at once. However, the principle behind all of them is the same: make a list of what you want to change, then run the command to the entire member of that group, then save. The only difference is the scope of each entry.&lt;/p&gt;

&lt;p&gt;Let's go over two of them here. Once you get a feeling how it works, using any of the methods above is just a matter of syntactical differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Argument List
&lt;/h2&gt;

&lt;p&gt;The argument list (&lt;code&gt;argdo&lt;/code&gt;) uses file as the scope. To create an argument list consisting of &lt;code&gt;file1.txt&lt;/code&gt;, &lt;code&gt;file2.txt&lt;/code&gt;, and &lt;code&gt;file3.txt&lt;/code&gt;, run &lt;code&gt;:args file1.txt file2.txt file3.txt&lt;/code&gt; (you can also use the blob operator: run &lt;code&gt;:args *txt&lt;/code&gt; to collect all txt files in the current directory, run &lt;code&gt;:args **txt&lt;/code&gt; to collect all txt files recursively, run &lt;code&gt;:args z*txt&lt;/code&gt; to collect all txt files in the current directory that starts with "z"). &lt;/p&gt;

&lt;p&gt;To check that you have the correct files, run &lt;code&gt;:args&lt;/code&gt;. On the bottom screen, you should see something like &lt;code&gt;[file1.txt] file2.txt file3.txt&lt;/code&gt;, indicating that you are currently on &lt;code&gt;file1.txt&lt;/code&gt;. You can move around the argument list with &lt;code&gt;:next&lt;/code&gt;, &lt;code&gt;:prev&lt;/code&gt;, &lt;code&gt;:first&lt;/code&gt;, &lt;code&gt;:last&lt;/code&gt;, etc. Make sure that you are on the first entry before running the command.&lt;/p&gt;

&lt;p&gt;Now run &lt;code&gt;:argdo %s/kale/pancake/g | update&lt;/code&gt;. That's it. All kales inside &lt;code&gt;file1.txt&lt;/code&gt;, &lt;code&gt;file2.txt&lt;/code&gt;, and &lt;code&gt;file3.txt&lt;/code&gt; are now substituted with pancakes. Sweet!&lt;/p&gt;

&lt;p&gt;Command breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:argdo&lt;/code&gt; performs the given command on all entry in the argument list. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:%s/kale/pancake/g&lt;/code&gt; is the substitute command. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;|&lt;/code&gt; lets you to chain multiple commands together. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;update&lt;/code&gt; saves each file.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quickfix List
&lt;/h2&gt;

&lt;p&gt;Next, let's go over the quickfix list. If you not familiar, quickfix is Vim's special mode originally created to handle edit-compile-edit cycle error messages, but eventually evolved and used for all sorts of other things from displaying STDOUT when running async operations in &lt;a href="https://github.com/tpope/vim-dispatch" rel="noopener noreferrer"&gt;vim-dispatch&lt;/a&gt;, fuzzy searching in &lt;a href="https://github.com/junegunn/fzf.vim" rel="noopener noreferrer"&gt;fzf.vim&lt;/a&gt;, etc. For our purpose, think of it as &lt;strong&gt;a list&lt;/strong&gt; of pointers to various location in your files.&lt;/p&gt;

&lt;p&gt;Some commands in Vim automatically uses quickfix, like &lt;code&gt;:make&lt;/code&gt;, &lt;code&gt;:grep&lt;/code&gt;, and &lt;code&gt;:vimgrep&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you need to list all occurrences of "veggies" inside any text file, run &lt;code&gt;:vimgrep /veggies/ **txt&lt;/code&gt;. To see the quickfix matches, run &lt;code&gt;:copen&lt;/code&gt; (quickfix open). To apply the substitute command to all quickfix matches, run &lt;code&gt;:cfdo %s/kale/pancake/g | update&lt;/code&gt;. That's it. It follows a similar pattern like the argument list: collect-apply-save.&lt;/p&gt;

&lt;p&gt;You can move around in a quickfix list with &lt;code&gt;:cfirst&lt;/code&gt;, &lt;code&gt;:clast&lt;/code&gt;, &lt;code&gt;:cnext&lt;/code&gt;, &lt;code&gt;:cprev&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;If you notice, on the list above you'll see &lt;code&gt;cfdo&lt;/code&gt; and &lt;code&gt;cdo&lt;/code&gt; quickfix operations. What's the difference? The difference is that &lt;code&gt;cfdo&lt;/code&gt; is a per-file operator and &lt;code&gt;cdo&lt;/code&gt; is a per-match operator. &lt;code&gt;cfdo&lt;/code&gt; will run the command once per file and &lt;code&gt;cdo&lt;/code&gt; will run the command once per match. &lt;/p&gt;

&lt;p&gt;If you have 5 matches for "veggies" inside &lt;code&gt;file1.txt&lt;/code&gt;, running &lt;code&gt;:cfdo %s/kale/pancake/g&lt;/code&gt; will run the command once while running &lt;code&gt;:cdo %s/kale/pancake/g&lt;/code&gt; will run the command 5 times.&lt;/p&gt;

&lt;p&gt;Since we are running a file-wide command (&lt;code&gt;%s&lt;/code&gt;), it makes sense to run it only once per file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Vim's multi-file operations are useful to apply a change across multiple files. There are eight different ways to accomplish this, although the underlying principle is the same: collect-apply-save. Play around with the &lt;code&gt;args&lt;/code&gt; / &lt;code&gt;argdo&lt;/code&gt; and &lt;code&gt;vimgrep&lt;/code&gt; / &lt;code&gt;cfdo&lt;/code&gt; combos. Once you get comfortable with them, play around with the other commands.&lt;/p&gt;

&lt;p&gt;Happy Vimming!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shameless disclaimer&lt;/strong&gt;: if you enjoy this, there's a 98.39% &lt;em&gt;(not scientifically proven)&lt;/em&gt; you will also enjoy my &lt;strong&gt;&lt;a href="https://leanpub.com/gourmetvim/" rel="noopener noreferrer"&gt;Vim Cookbook: Gourmet Vim&lt;/a&gt;&lt;/strong&gt;. Check it out!&lt;/p&gt;

</description>
      <category>vim</category>
      <category>files</category>
      <category>substitute</category>
    </item>
  </channel>
</rss>
