<?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.us-east-2.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>Claude Code Context Is Like a Fridge - Put Only Perishable Items in It</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Tue, 06 Oct 2026 15:04:02 +0000</pubDate>
      <link>https://dev.to/iggredible/claude-code-context-is-like-a-fridge-put-only-perishable-items-in-it-f1p</link>
      <guid>https://dev.to/iggredible/claude-code-context-is-like-a-fridge-put-only-perishable-items-in-it-f1p</guid>
      <description>&lt;h2&gt;
  
  
  Claude Code Fridge
&lt;/h2&gt;

&lt;p&gt;I like my fridge. It can hold yummy foods. But its space is finite, and the fuller it gets, the worse it works. Food gets shoved to the back and forgotten until it smells. That chocolate mochi donut I got? It sat in the corner for 2 weeks. I had to throw it away. When the fridge gets full, I forget what I put inside.&lt;/p&gt;

&lt;p&gt;Most of what I buy &lt;em&gt;can&lt;/em&gt; go in the fridge. That doesn't mean it &lt;em&gt;should&lt;/em&gt;. My &lt;a href="https://www.pocky.com/" rel="noopener noreferrer"&gt;Pocky&lt;/a&gt; could go in the fridge, but it doesn't need to. So it goes in the pantry, and the milk gets more room.&lt;/p&gt;

&lt;p&gt;Claude Code works the same way. The main conversation is the fridge. Context is the milk. Many tasks drag in a lot of stuff that doesn't need to be cold.&lt;/p&gt;

&lt;h3&gt;
  
  
  Milk Goes In the Fridge
&lt;/h3&gt;

&lt;p&gt;In the earlier &lt;a href="https://irian.to/blogs/claude-code-context-is-like-milk-keep-it-fresh-and-condensed" rel="noopener noreferrer"&gt;milk post&lt;/a&gt; I said context is best served fresh and condensed. But every task costs context. You can't avoid spending it. What you can choose is &lt;em&gt;where&lt;/em&gt; you spend it.&lt;/p&gt;

&lt;p&gt;You need your dessert. Storing each dessert takes up space. But not all dessert goes into the fridge. Desserts that need to be cold like chocolate milk, boba tea, and cheesecakes, they go in the fridge. Non-perishables like pocky, chocolate prertzel, and choco pie, they go in the pantry to leave the fridge some room.&lt;/p&gt;

&lt;p&gt;In Claude Code, there are four places where contexts are used and can be optimized: the main conversation, a subagent, a second session, or a headless loop. One fridge, three pantries.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fridge
&lt;/h3&gt;

&lt;p&gt;The main conversation is where you and Claude talk. Everything said here stays here until you &lt;code&gt;/clear&lt;/code&gt; it, or it gets compacted, either by &lt;code&gt;/compact&lt;/code&gt; or automatically when the fridge is nearly full. Also, &lt;code&gt;/rewind&lt;/code&gt; can also remove or summarize context.&lt;/p&gt;

&lt;p&gt;What kind of prompt goes in the main conversation?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Work that needs back-and-forth. "No, make the button smaller. Ok, now move it left." Or "what are the pros and cons of the strategy pattern here?" The kind of prompts that you can't hand off because you're the one steering. &lt;/li&gt;
&lt;li&gt;Quick, targeted changes. Start a session, make the change, get out.&lt;/li&gt;
&lt;li&gt;Anything where speed matters. A fresh subagent starts cold and has to gather context before it can do anything useful. The main conversation already has it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are your perishable items. Everything else, be picky about. They can go into the pantry. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Subagent Pantry
&lt;/h3&gt;

&lt;p&gt;A subagent is for the "go figure this out and tell me" kind of task. It's a separate Claude with its own fresh context and its own set of allowed tools. It goes off, does the work, and hands back a summary. The mess stays in &lt;em&gt;its&lt;/em&gt; context, not yours. What happens in the subagent stays in the subagent.&lt;/p&gt;

&lt;p&gt;The subagent reads 1,000 lines of noisy output. You get a three-line conclusion.&lt;/p&gt;

&lt;p&gt;Delegate to a subagent when a task makes lots of output you don't need to see, like reading dozens of files, grepping logs, running test suites. Or when the work is self-contained enough to come back as a summary. Or when you want to limit its tools, like a reviewer that can read files but not edit them.&lt;/p&gt;

&lt;p&gt;I used to tell Claude "investigate why X is slow" and let it run. It would obediently read hundreds of files. Then my context was full of stuff I didn't care about. In this case, you can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scope the task: "look at &lt;code&gt;src/cache/&lt;/code&gt; only."&lt;/li&gt;
&lt;li&gt;Hand the whole investigation to a subagent. "Go investigate X" is pantry work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So how do you start a subagent? &lt;/p&gt;

&lt;p&gt;This topic probably deserves its own blog post so I'll just touch on it briefly. There are multiple ways. One way is to ask explicitly: "Use a subagent to investigate why X is slow." If you've already defined subagents in &lt;code&gt;.claude/agents/&lt;/code&gt;, mention one by name: &lt;code&gt;@agent-code-architect plan the caching changes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can invoke the &lt;code&gt;/subtask&lt;/code&gt; command, like &lt;code&gt;/subtask Write a unit test for the authentication controller&lt;/code&gt;. A subtask is a subagent that inherits the whole conversation so far instead of starting fresh, so you don't have to re-explain anything. It runs in the background while you keep working, its tool calls stay out of your fridge. Only the result comes back to your conversation.&lt;/p&gt;

&lt;p&gt;You can also run &lt;code&gt;/fork&lt;/code&gt;, like &lt;code&gt;/fork Write a unit test for the users controller&lt;/code&gt;. A fork copies your conversation into a separate background session that keeps working on its own. Unlike a subtask, it doesn't report back to you.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;/subtask&lt;/code&gt; is like asking your assistant to do a task: when he's done, he comes back with a brief report. &lt;code&gt;/fork&lt;/code&gt; is like asking your assistant to do a task, and he wanders off to work on it and goes home when he's done. It's up to you to check on his work or assign him more.&lt;/p&gt;

&lt;p&gt;One note, if you've turned off agent view, or you're on an older version of Claude Code, &lt;code&gt;/subtask&lt;/code&gt; isn't available and &lt;code&gt;/fork&lt;/code&gt; behaves like the subtask described above.&lt;/p&gt;

&lt;h3&gt;
  
  
  The New Session Pantry
&lt;/h3&gt;

&lt;p&gt;The second pantry is a new session. This is when you spin up a new Claude session to use its main conversation instead of building on top of your current main conversation. For example, when you use Claude to write code and you want to review it, it's best to start a new session. Claude reviewing code it just wrote in the same session is like me proofreading my own essay. I see what I meant to write, not what I actually wrote. A fresh context has no attachment to the code. It just sees what's there. The &lt;a href="https://code.claude.com/docs/en/best-practices#run-multiple-claude-sessions" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt; say the same: a fresh context improves code review, since Claude won't be biased toward code it just wrote. &lt;/p&gt;

&lt;p&gt;Have two sessions. One writes, the other reviews, and the first one fixes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Session A (Writer)&lt;/th&gt;
&lt;th&gt;Session B (Reviewer)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Implement a rate limiter for our API endpoints.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Review the rate limiter in &lt;a class="mentioned-user" href="https://dev.to/src"&gt;@src&lt;/a&gt;/middleware/rateLimiter.ts. Look for edge cases, race conditions, and consistency with our existing middleware.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Here's the review feedback: {Session B output}. Address these issues.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You don't even have to copy-paste. Have Session B write its review to &lt;code&gt;review.md&lt;/code&gt;, then tell Session A to address &lt;code&gt;review.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Don't want to juggle two sessions? A subagent reviewer works too. It also starts with a fresh context, and its findings come straight back to the writer.&lt;/p&gt;

&lt;p&gt;How do you run more than one session? You can run multiple tabs. I use &lt;a href="https://github.com/tmux/tmux/" rel="noopener noreferrer"&gt;Tmux&lt;/a&gt; and I like to see everything at once with panes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Packing 3000 Lunchboxes
&lt;/h3&gt;

&lt;p&gt;Say you have 3,000 files to migrate from one framework to another. If you try to do that in one session... don't try it. By file 100, your poor milk is shoved into the deepest, darkest corner of the fridge because your fridge is stuffed.&lt;/p&gt;

&lt;p&gt;Don't use one session. Give each file its own fresh Claude. If you're packing for your class, don't pack one giant tub for the whole class! Instead, pack a lunchbox per kid. That's what a headless loop (&lt;code&gt;claude -p&lt;/code&gt;) is for!&lt;/p&gt;

&lt;p&gt;Here's one way to do it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have Claude list the files: &lt;code&gt;list all React components that need migrating&lt;/code&gt; → &lt;code&gt;files.txt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Loop over them in non-interactive mode (&lt;code&gt;-p&lt;/code&gt;).
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# claude_migrate.sh&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;file &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;files.txt&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;claude &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"Migrate &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt; from React to Angular. Return SUCCESS or FAIL."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--allowedTools&lt;/span&gt; &lt;span class="s2"&gt;"Edit,Bash(git commit *)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--permission-mode&lt;/span&gt; dontAsk
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run it on 2-3 files first. Fix your prompt based on what goes wrong. Then run it on everything.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each run starts clean. One failure doesn't poison the rest. Thousands of files is fine.&lt;/p&gt;

&lt;p&gt;If you want them to be as autonomous as possible, use these flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--allowedTools&lt;/code&gt; pre-approves the tools each run needs, so you don't have to approve them a thousand times&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--permission-mode dontAsk&lt;/code&gt; denies everything else instead of stopping to ask for approval.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You won't be around to answer anyway. Without &lt;code&gt;dontAsk&lt;/code&gt;, a run that reaches for a tool you didn't list can stall or behave unpredictably. With it, that run is simply told no and moves on, and you'll see it in the SUCCESS/FAIL output. Keep the allowed list small. you don't want a thousand Claudes accidentally destroying things.&lt;/p&gt;

&lt;p&gt;You can also pipe the output into your existing tools: &lt;code&gt;claude -p "&amp;lt;prompt&amp;gt;" --output-format json | your_command&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If your bash scripting skill is half as bad as mine and can't write a simple loop without asking Claude / looking it up, don't fret! Claude can do this natively with &lt;code&gt;/batch&lt;/code&gt;. It splits a change across 5-30 parallel subagents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clean Fridge, Happy You
&lt;/h3&gt;

&lt;p&gt;Tape this to your fridge door.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does it need back-and-forth with me, or share lots of context with what we're doing now?
├── Yes → main conversation
└── No
    ├── Is it one self-contained chunk (investigate, search, read lots of files)?
    │   └── Yes → SUBAGENT (comes back as a summary)
    ├── Do I want a second opinion on work Claude just did?
    │   └── Yes → SECOND SESSION or REVIEWER SUBAGENT (fresh eyes, no bias)
    └── Is it the same task repeated over many items?
        └── Yes → HEADLESS LOOP (claude -p per item, or /batch)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before you put anything in, ask whether it really needs to be cold. You'll be surprised at how many items don't need to go into the fridge. Put the Pocky in the pantry and leave room for the milk.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Claude Code Context Is Like Milk, Keep It Fresh and Condensed</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Wed, 30 Sep 2026 21:46:47 +0000</pubDate>
      <link>https://dev.to/iggredible/claude-code-context-is-like-milk-keep-it-fresh-and-condensed-l7o</link>
      <guid>https://dev.to/iggredible/claude-code-context-is-like-milk-keep-it-fresh-and-condensed-l7o</guid>
      <description>&lt;h2&gt;
  
  
  Milk is good for you
&lt;/h2&gt;

&lt;p&gt;I like milk. I drink it twice a day: once with smoothie, once with cereal. I like it fresh. You can tell when milk has gone bad. It has a weird, slightly sour smell to it. I also like condensed milk. I like it in my sandwich (peanut butter + condensed milk)… yum! (Man, now I'm hungry!)&lt;/p&gt;

&lt;p&gt;Anyway, why did I mention milk? Because I think LLM context is like milk, and with LLMs, context is king.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI context is like milk; it's best served fresh and condensed!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ykdojo/claude-code-tips#tip-5-ai-context-is-like-milk-its-best-served-fresh-and-condensed" rel="noopener noreferrer"&gt;ykdojo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Milk is context
&lt;/h2&gt;

&lt;p&gt;Claude is smartest at the start of a conversation, when its context is smallest (not empty: the system prompt, tools, CLAUDE.md, and MCP definitions are already loaded before you type anything). Over time as your context grows, Claude doesn't actually "remember" anything between requests. Every time you send a message, the whole conversation so far is sent again and Claude has to re-read all of it. Over time, performance goes down. There's a bit of nuance to it because of &lt;a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching" rel="noopener noreferrer"&gt;prompt caching&lt;/a&gt;, but that's another topic.&lt;/p&gt;

&lt;p&gt;It's like when you go to a drive-through and you're ordering for four families: "Yes, I'd like to have a crispy chicken sandwich, 2 spicy crispy chicken sandwiches, a California-style burger, protein style, 3 medium french fries, make 1 of them animal style, please, also can I have 1 fried okra, also can I have 3 medium drinks: a Coke, a Dr Pepper, and a Diet Coke, and 1 large root beer, and then a vanilla ice cream and 2 oatmeal cookies, with a ketchup and 2 thousand island dipping sauces, actually scratch the crispy chicken sandwich, can I have a Chicago-style hot dog instead? Go easy on the relish, and can I have extra napkins and 2 sets of knives?"&lt;/p&gt;

&lt;p&gt;That is going to confuse the heck out of the poor guy serving you. Instead, it would be easier if each family came up and ordered what they wanted.&lt;/p&gt;

&lt;p&gt;Family 1: "I'd like 2 spicy crispy chicken sandwiches and 2 medium french fries with a large root beer, please."&lt;br&gt;
Family 2: "I'd like a crispy chicken sandwich, actually make it a Chicago-style hot dog and go easy on the relish, please, also a medium Coke."&lt;br&gt;
...etc.&lt;/p&gt;

&lt;p&gt;Notice that in one order, a family changes their mind: "actually scratch the crispy chicken sandwich". The same thing happens with Claude: when you correct something, the wrong version doesn't disappear. It stays in the context right next to the correction. Each correction, "no, actually...", leaves a stale order on the ticket.&lt;/p&gt;

&lt;p&gt;If you have two distinct topics, start a new session for each.&lt;/p&gt;
&lt;h2&gt;
  
  
  Performance degrades as context fills up
&lt;/h2&gt;

&lt;p&gt;Do you ever notice that after having a long conversation with Claude, it starts making more mistakes? The model's weights don't change mid-session; its context does. Claude's models are great, even the smallest one, &lt;a href="https://www.anthropic.com/claude/haiku" rel="noopener noreferrer"&gt;Haiku&lt;/a&gt;. If you notice Claude getting sloppy over time, that's probably because its context window is filling up. Quality starts slipping well before the limit (and when it does get nearly full, Claude Code auto-compacts).&lt;/p&gt;

&lt;p&gt;Performance degrades as context fills. It's a quality problem caused by quantity: the more tokens in the window (especially stale or irrelevant ones like the corrections above), the more Claude's attention gets diluted, even when you're nowhere near the limit.&lt;/p&gt;
&lt;h2&gt;
  
  
  Keeping it fresh and condensed
&lt;/h2&gt;

&lt;p&gt;Claude has no memory between requests, so each request re-sends the whole context:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Claude Code's system prompt.&lt;/li&gt;
&lt;li&gt;Tool definitions: the built-in tools plus your MCP tools (newer versions defer MCP tools and only send their names until needed).&lt;/li&gt;
&lt;li&gt;CLAUDE.md files and memory, plus skill descriptions (only the descriptions, not the full skills).&lt;/li&gt;
&lt;li&gt;The entire conversation: your prompts, Claude's responses, every tool call, and every tool output.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So yes, CLAUDE.md is sent every time. And a file you told Claude to read an hour ago isn't read once and forgotten; it rides along on every request until you &lt;code&gt;/clear&lt;/code&gt; or &lt;code&gt;/compact&lt;/code&gt;. That's a lot of text being sent out.&lt;/p&gt;

&lt;p&gt;Two more things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One prompt from you often triggers several requests behind the scenes. Each one carries its own context.&lt;/li&gt;
&lt;li&gt;Prompt caching makes re-sending cheaper and faster, but the cached text still takes up just as much room in the context window.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nested CLAUDE.md files in subdirectories load when Claude reads files in those folders. After &lt;code&gt;/compact&lt;/code&gt;, the root CLAUDE.md is re-read from disk, which is why it survives compaction; nested ones come back the next time Claude reads files in their folder.&lt;/p&gt;

&lt;p&gt;Try to focus on the conversation. What are you trying to get out of it? If you have a stray thought and you're about to go down a rabbit hole, ask it in a separate session (or ask it with &lt;code&gt;/btw&lt;/code&gt;, which answers a side question without adding it to the conversation history).&lt;/p&gt;

&lt;p&gt;Pay attention to your context. You can see how much context you've used with &lt;code&gt;/context&lt;/code&gt; (try it! Run &lt;code&gt;/context&lt;/code&gt;, then ask it to do something, then run &lt;code&gt;/context&lt;/code&gt; again). It also breaks down what's using it (system prompt, tools, MCP, memory files, messages), so you can see what's hogging space.&lt;/p&gt;

&lt;p&gt;Even better, you can also create a status line that shows context! What's really cool is that you don't need to write the script yourself. You can ask Claude to do it for you: "Hey Claude, can you update my statusline to show context usage?" (or run &lt;code&gt;/statusline show context usage&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;After a while, it may be a good idea to shrink your context. You can use &lt;code&gt;/compact&lt;/code&gt; to have Claude summarize what you've been talking about. One downside is that Claude, upon compacting your conversation, may lose some important details. Repeated compaction can also degrade quality.&lt;/p&gt;

&lt;p&gt;You may want to re-inject the essentials after compaction. You can do that with a SessionStart hook on the &lt;code&gt;compact&lt;/code&gt; matcher. Whatever a SessionStart hook prints to stdout gets added to Claude's context, and the &lt;code&gt;compact&lt;/code&gt; matcher makes it run right after each compaction (the other matchers are &lt;code&gt;startup&lt;/code&gt;, &lt;code&gt;resume&lt;/code&gt;, &lt;code&gt;clear&lt;/code&gt;, and &lt;code&gt;fork&lt;/code&gt;). In &lt;code&gt;.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"SessionStart"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"compact"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cat &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$CLAUDE_PROJECT_DIR/.claude/essentials.md&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since CLAUDE.md already survives compaction, use this for things that change as you work: the current task file, &lt;code&gt;git status&lt;/code&gt;, or the "decisions so far" section of a handoff file like HANDOFF.md (more on that below).&lt;/p&gt;

&lt;p&gt;You can also tell Claude what to focus on when compacting. Let's say you are architecting the new user subscription API and you want to keep the context of that particular topic. Run &lt;code&gt;/compact focus on the user subscription API&lt;/code&gt;. If you always want the same focus, put something like &lt;code&gt;# Summary instructions&lt;/code&gt; section in your CLAUDE.md so every compaction follows it.&lt;/p&gt;

&lt;p&gt;Sometimes Claude implements something that doesn't work as expected. Now you have a pile of useless code. You don't need to delete it by hand. Run &lt;code&gt;/rewind&lt;/code&gt; (or press Esc twice) to open the rewind menu, where you can restore the code, the conversation, or both to an earlier point. It can also summarize the conversation from a chosen point forward, freeing up context. One catch: checkpoints only track edits Claude makes with its file-editing tools. Changes made through bash (&lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;mv&lt;/code&gt;, etc.), by most subagents, or outside Claude Code aren't restored.&lt;/p&gt;

&lt;p&gt;When you're ready to move on or dig into a different topic, it's a good idea to start fresh: &lt;code&gt;/clear&lt;/code&gt; (&lt;code&gt;/new&lt;/code&gt; and &lt;code&gt;/reset&lt;/code&gt; are aliases).&lt;/p&gt;

&lt;p&gt;If you're planning to pick up where you left off in a new session, it may be a good idea to create a bridge (like a &lt;a href="https://www.todoist.com/productivity-methods/hemingway-bridge" rel="noopener noreferrer"&gt;Hemingway Bridge&lt;/a&gt;). Ask Claude to create something like a HANDOFF.md so when you open a fresh Claude session, you can just point it at the HANDOFF.md file so it knows where it left off. This helps you keep context usage low. (Note: &lt;code&gt;/resume&lt;/code&gt; and &lt;code&gt;--continue&lt;/code&gt; are &lt;em&gt;not&lt;/em&gt; fresh starts. They reload the old context in full, baggage included.)&lt;/p&gt;

&lt;p&gt;You may want to hand off exploration to subagents: "Use a subagent to investigate the different HTTP error codes the &lt;code&gt;show&lt;/code&gt; method in &lt;code&gt;users_controller.rb&lt;/code&gt; returns." The subagent's file reads and searches stay in its own context; &lt;em&gt;only its summary comes back to yours.&lt;/em&gt; If you don't care about the exploration and don't want it to pollute your context, try it.&lt;/p&gt;

&lt;p&gt;Claude is pretty good at detecting your intent. But sometimes we aren't on the same wavelength and I have to keep correcting it. It's a good idea to clear after two failed corrections. If you've corrected Claude twice on the same thing and it's still wrong, &lt;code&gt;/clear&lt;/code&gt; and start over with a better prompt that includes what you learned. Remember that every correction leaves the old order on the ticket. By then, your context holds two wrong attempts and two corrections.&lt;/p&gt;

&lt;p&gt;Keep CLAUDE.md lean. It's paid for on every request. Move specialized instructions into skills (remember that skills are loaded in full only when used) or into rules scoped to specific file paths. I like to keep my CLAUDE.md under 200 lines, following the &lt;a href="https://code.claude.com/docs/en/memory#write-effective-instructions" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Trim MCP servers. &lt;code&gt;/context&lt;/code&gt; shows how much space tool definitions take. Disable servers you aren't using with &lt;code&gt;/mcp&lt;/code&gt;. If you think you won't be using Slack in this session, disable it.&lt;/p&gt;

&lt;p&gt;Be specific and point at specific things. "Read &lt;code&gt;src/billing.ts&lt;/code&gt; lines 40-120" is far cheaper than "look around the billing code."&lt;/p&gt;

&lt;p&gt;You can also run a command yourself with the &lt;code&gt;!&lt;/code&gt; prefix. In Claude Code, &lt;code&gt;!&lt;/code&gt; runs a shell command directly, and its output is added to the conversation. Pipe the output through a filter so only the lines you need go into context.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;!&lt;/span&gt; npm &lt;span class="nb"&gt;test &lt;/span&gt;2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-50&lt;/span&gt;
&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;grep &lt;/span&gt;ERROR logs/app.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Claude re-reads the whole conversation on every request, so performance drops as context fills. Watch it (&lt;code&gt;/context&lt;/code&gt;), condense it (&lt;code&gt;/compact&lt;/code&gt;), cut it (&lt;code&gt;/rewind&lt;/code&gt;, subagents), and refresh it (&lt;code&gt;/clear&lt;/code&gt; + HANDOFF.md). One topic per session.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>llm</category>
    </item>
    <item>
      <title>Send Code From Vim to a tmux Pane With One Operator</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Thu, 24 Sep 2026 00:33:00 +0000</pubDate>
      <link>https://dev.to/iggredible/send-code-from-vim-to-a-tmux-pane-with-one-operator-5138</link>
      <guid>https://dev.to/iggredible/send-code-from-vim-to-a-tmux-pane-with-one-operator-5138</guid>
      <description>&lt;h2&gt;
  
  
  The Console
&lt;/h2&gt;

&lt;p&gt;If you work on a Rails app long enough, you end up fixing production from the console. Something's off with a user's subscription, and the fastest way to find out why is to poke at the data directly. (Very carefully. Writing to prod data is how bad days start.)&lt;/p&gt;

&lt;p&gt;So how do you get the queries in? You can type them into the console one at a time. That works, but it's slow, and you make typos. A console is a bad place to write code.&lt;/p&gt;

&lt;p&gt;More likely, you write the queries somewhere else and paste them in. Now you have four steps: write the code, copy it, switch to the console, paste. You do that dozens of times in a debugging session. It adds up.&lt;/p&gt;

&lt;p&gt;What you really want is two steps. Write the code. Send it.&lt;/p&gt;

&lt;p&gt;You could use &lt;code&gt;rails runner&lt;/code&gt;. But the script usually isn't on the prod server, and you lose the back-and-forth that makes a console useful. You want to see the answer, digest it, and ask the next question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vim Verbs
&lt;/h2&gt;

&lt;p&gt;Vim has a name for "do something to this chunk of text": an operator. &lt;code&gt;d&lt;/code&gt; deletes, &lt;code&gt;y&lt;/code&gt; yanks, &lt;code&gt;c&lt;/code&gt; changes. Each one works with every motion and text object, so if you know a dozen motions, one new operator gets you a dozen new commands.&lt;/p&gt;

&lt;p&gt;What if there were an operator whose job was to send text somewhere else, say, the console? Call it &lt;code&gt;gs&lt;/code&gt;. &lt;code&gt;gss&lt;/code&gt; would send the current line to the Rails console. &lt;code&gt;gsj&lt;/code&gt; would send the current line and the next one. &lt;code&gt;gs10j&lt;/code&gt; would send eleven lines, and &lt;code&gt;gs}&lt;/code&gt; would send everything to the end of the paragraph.&lt;/p&gt;

&lt;p&gt;It's not hard to build and I'll show you how.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ingredients
&lt;/h2&gt;

&lt;p&gt;I use Vim inside tmux. You don't need my exact setup; the idea should carry over, though I've never tried it anywhere else.&lt;/p&gt;

&lt;p&gt;For my recipe, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vim 8.2.3619 or later (or just Vim 9). Operatorify assigns a Funcref to &lt;code&gt;'operatorfunc'&lt;/code&gt;, which Vim added in 8.2.3619. My config also uses &lt;code&gt;#{}&lt;/code&gt; dict literals and &lt;code&gt;popup_menu()&lt;/code&gt;, which Neovim doesn't have. Neovim has equivalents (like &lt;code&gt;vim.ui.select&lt;/code&gt;), but you'd have to port those parts.&lt;/li&gt;
&lt;li&gt;tmux, with Vim running in one of its panes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/preservim/vimux" rel="noopener noreferrer"&gt;vimux&lt;/a&gt;&lt;/strong&gt;, which does the real work of sending keys to a pane.&lt;/li&gt;
&lt;li&gt;Optionally, &lt;strong&gt;&lt;a href="https://github.com/iggredible/vim-operatorify" rel="noopener noreferrer"&gt;vim-operatorify&lt;/a&gt;&lt;/strong&gt; (disclaimer: my plugin), which turns a function into an operator. You don't have to use it, though.&lt;/li&gt;
&lt;li&gt;Optionally, &lt;strong&gt;&lt;a href="https://github.com/junegunn/fzf" rel="noopener noreferrer"&gt;fzf&lt;/a&gt; and fzf.vim&lt;/strong&gt;, for a nicer pane picker.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is new. vimux was inspired by &lt;a href="https://github.com/jgdavey/tslime.vim/" rel="noopener noreferrer"&gt;tslime.vim&lt;/a&gt;, which was based on slime.vim, which took its idea from Emacs' &lt;a href="https://github.com/slime/slime" rel="noopener noreferrer"&gt;SLIME&lt;/a&gt;. SLIME dates from 2003. People have been sending text from editors to REPLs for over twenty years. Some of you probably weren't even born yet!&lt;/p&gt;

&lt;p&gt;What's missing is the part that makes it feel like Vim.&lt;/p&gt;

&lt;h2&gt;
  
  
  gs operator
&lt;/h2&gt;

&lt;p&gt;I picked &lt;code&gt;gs&lt;/code&gt; because the s is a tribute to slime. It's also in my fingers by now. (If you want the long version of how operators work, I wrote about &lt;a href="https://irian.to/blogs/how-to-make-your-own-vim-operator" rel="noopener noreferrer"&gt;making your own Vim operator&lt;/a&gt;.)&lt;/p&gt;

&lt;h3&gt;
  
  
  With Operatorify
&lt;/h3&gt;

&lt;p&gt;With operatorify, the setup is two lines of real code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="c"&gt;" plugin/plugins/vimux.vim&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; VimuxSlimeExe&lt;span class="p"&gt;(&lt;/span&gt;text &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;call&lt;/span&gt; VimuxRunCommand&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;a:text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="c"&gt;" after/plugin/plugins/vimux.vim&lt;/span&gt;
&lt;span class="k"&gt;call&lt;/span&gt; Operatorify#Mapper&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'gs'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'VimuxSlimeExe'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;VimuxSlimeExe&lt;/code&gt; takes a string and hands it to vimux. That's all. It doesn't know it's an operator. Operatorify works out which text you meant, yanks it without disturbing your registers, and passes it in.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;gsiw&lt;/code&gt; sends the word under the cursor. &lt;code&gt;gs2j&lt;/code&gt; sends the current line and the two below it. &lt;code&gt;gss&lt;/code&gt; sends the current line. Every motion you already know now means something new.&lt;/p&gt;

&lt;h3&gt;
  
  
  By Hand
&lt;/h3&gt;

&lt;p&gt;If you think mentioning operatorify is my subtle way of getting you to use my plugin, you're correct. Just kidding — you don't need my plugin. Here's how you can do it without it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:SlimeOperator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;save_reg   &lt;span class="p"&gt;=&lt;/span&gt; getreginfo&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;save_sel   &lt;span class="p"&gt;=&lt;/span&gt; &amp;amp;&lt;span class="nb"&gt;selection&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;save_clip  &lt;span class="p"&gt;=&lt;/span&gt; &amp;amp;&lt;span class="nb"&gt;clipboard&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;save_marks &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;getpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"'&amp;lt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;getpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"'&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt;
    &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;selection&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;inclusive &lt;span class="nb"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt;# &lt;span class="s1"&gt;'line'&lt;/span&gt;
      &lt;span class="k"&gt;silent&lt;/span&gt; &lt;span class="k"&gt;noautocmd&lt;/span&gt; &lt;span class="k"&gt;keepjumps&lt;/span&gt; normal&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="s1"&gt;'[V'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;y&lt;/span&gt;
    &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt;# &lt;span class="s1"&gt;'char'&lt;/span&gt;
      &lt;span class="k"&gt;silent&lt;/span&gt; &lt;span class="k"&gt;noautocmd&lt;/span&gt; &lt;span class="k"&gt;keepjumps&lt;/span&gt; normal&lt;span class="p"&gt;!&lt;/span&gt; `&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;v&lt;/span&gt;`&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;y&lt;/span&gt;
    &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt;# &lt;span class="s1"&gt;'block'&lt;/span&gt;
      &lt;span class="k"&gt;silent&lt;/span&gt; &lt;span class="k"&gt;noautocmd&lt;/span&gt; &lt;span class="k"&gt;keepjumps&lt;/span&gt; &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"normal! `[\&amp;lt;C-V&amp;gt;`]y"&lt;/span&gt;
    &lt;span class="k"&gt;endif&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; VimuxRunCommand&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;getreg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;finally&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nb"&gt;setreg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;save_reg&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &amp;amp;&lt;span class="nb"&gt;selection&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;save_sel
    &lt;span class="k"&gt;let&lt;/span&gt; &amp;amp;&lt;span class="nb"&gt;clipboard&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;save_clip
    &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nb"&gt;setpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"'&amp;lt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;save_marks&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nb"&gt;setpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"'&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;save_marks&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;endtry&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gs  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;operatorfunc&lt;/span&gt;&lt;span class="p"&gt;=&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SlimeOperator&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;g&lt;/span&gt;@
xnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gs  &lt;span class="p"&gt;:&amp;lt;&lt;/span&gt;C&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="k"&gt;u&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;operatorfunc&lt;/span&gt;&lt;span class="p"&gt;=&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SlimeOperator&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;gvg@
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;silent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gss &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;operatorfunc&lt;/span&gt;&lt;span class="p"&gt;=&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SlimeOperator&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;g&lt;/span&gt;@_
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks long, but most of that is bookkeeping. You save the register, the selection option, the clipboard, and the visual marks. Then you yank the text, send it, and put most things back. The actual work is this line: &lt;code&gt;call VimuxRunCommand(getreg('"'))&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It has rough edges. It doesn't restore register &lt;code&gt;0&lt;/code&gt; or the &lt;code&gt;'[&lt;/code&gt; / &lt;code&gt;']&lt;/code&gt; marks, and a count in front (&lt;code&gt;2gss&lt;/code&gt;) fails with &lt;code&gt;E481: No range allowed&lt;/code&gt;, because &lt;code&gt;:&lt;/code&gt; turns the count into a range for &lt;code&gt;:set&lt;/code&gt;. Operatorify handles both.&lt;/p&gt;

&lt;p&gt;Watch the &lt;code&gt;gv&lt;/code&gt; in the visual mapping. &lt;code&gt;:&amp;lt;C-u&amp;gt;&lt;/code&gt; drops you out of visual mode. Without &lt;code&gt;gv&lt;/code&gt; to reselect, &lt;code&gt;g@&lt;/code&gt; just sits there waiting for a motion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aim your text
&lt;/h2&gt;

&lt;p&gt;My tmux windows are messy. I rarely have just two panes. Sometimes I have Vim, a Rails console, and Claude Code. When you press &lt;code&gt;gss&lt;/code&gt;, which pane gets the text?&lt;/p&gt;

&lt;p&gt;By default, vimux sends to what it calls the nearest pane. That sounds cool until you read the code. "Nearest" means the first pane in the window, by index, that isn't Vim. Vimux picks it once and sticks with it. (If Vim is the only pane, it opens a new split.)&lt;/p&gt;

&lt;p&gt;With two panes, that's fine. With three, it's a coin toss. Does it get sent to the Rails console or Claude Code? Imagine Vim, a local console, and a &lt;em&gt;production&lt;/em&gt; console. You meant to run &lt;code&gt;User.destroy_all&lt;/code&gt; locally, but it got sent to the &lt;em&gt;other&lt;/em&gt; console. Uh oh. Don't be that person. Aim first.&lt;/p&gt;

&lt;p&gt;How do you aim? I use &lt;code&gt;&amp;lt;Leader&amp;gt;gs&lt;/code&gt; for that. &lt;code&gt;gs&lt;/code&gt; sends; &lt;code&gt;&amp;lt;Leader&amp;gt;gs&lt;/code&gt; aims.&lt;/p&gt;

&lt;p&gt;Vimux keeps its target in a global variable, so aiming just means setting it. First, list the other panes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:GetAvailablePanes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; current &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"tmux display-message -p '#{pane_id}'"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; fmt &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'#{pane_id}|#{pane_index}|#{pane_current_command}|#{pane_width}x#{pane_height}|#{pane_title}'&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; panes &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"tmux list-panes -F '"&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; fmt &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"'"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c"&gt;" ... parse on '|', skip the pane Vim is sitting in, return dicts&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you pick one. If fzf is installed, I use &lt;code&gt;fzf#run&lt;/code&gt;. If not, I fall back to Vim's &lt;code&gt;popup_menu()&lt;/code&gt;, and failing that, a numbered &lt;code&gt;input()&lt;/code&gt; prompt. Ultimately, it ends up here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:SetVimuxRunner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;pane_id&lt;span class="p"&gt;)&lt;/span&gt; abort
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;g:VimuxRunnerIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;a:pane_id&lt;/span&gt;
  echo &lt;span class="s2"&gt;"Vimux runner set to pane "&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;a:pane_id&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;VimuxRunCommand&lt;/code&gt; sees &lt;code&gt;g:VimuxRunnerIndex&lt;/code&gt; already set and sends there. No more coin toss. (If you've closed that pane since, the next send opens a new split.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Use it
&lt;/h2&gt;

&lt;p&gt;I have Vim on top, Rails console below.&lt;/p&gt;

&lt;p&gt;First, aim. &lt;code&gt;&amp;lt;Leader&amp;gt;gs&lt;/code&gt; lists every other pane in the window, and I pick the one running &lt;code&gt;ruby&lt;/code&gt;. (If the console is on a remote box, the pane shows &lt;code&gt;ssh&lt;/code&gt; or &lt;code&gt;kubectl&lt;/code&gt; instead.) With two panes you can skip this step. &lt;/p&gt;

&lt;p&gt;Then I send. &lt;code&gt;gs&lt;/code&gt; is an ordinary operator, so it's verb plus motion:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You want&lt;/th&gt;
&lt;th&gt;Keys&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Run the line under the cursor&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gss&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run the inside of a &lt;code&gt;{ }&lt;/code&gt; block&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gsi{&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run a paragraph (e.g. a &lt;code&gt;def&lt;/code&gt; block with no blank lines)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gsip&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run an ad-hoc multi-line snippet&lt;/td&gt;
&lt;td&gt;visual-select, then &lt;code&gt;gs&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run the current line and the next four&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gs4j&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send the next line too&lt;/td&gt;
&lt;td&gt;&lt;code&gt;j.&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The one I use most is &lt;code&gt;gss&lt;/code&gt;. After that, &lt;code&gt;.&lt;/code&gt; re-sends the same line and &lt;code&gt;j.&lt;/code&gt; sends the next one. Three keys the first time, then one or two. No window switching, no mouse, no clipboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scratch
&lt;/h2&gt;

&lt;p&gt;I keep my queries in scratch files, one per problem, named by date:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 2026_09_09.scratch.rb&lt;/span&gt;
&lt;span class="n"&gt;reload!&lt;/span&gt;
&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="s2"&gt;"someone@example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pluck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:plan_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;full_messages&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I walk down the file with &lt;code&gt;gss&lt;/code&gt;, or fire the whole thing with &lt;code&gt;gsip&lt;/code&gt;. If something needs changing, I edit it and hit &lt;code&gt;gss&lt;/code&gt; again. &lt;/p&gt;

&lt;p&gt;Next problem, next file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 2026_09_09.scratch2.rb&lt;/span&gt;
&lt;span class="n"&gt;reload!&lt;/span&gt;
&lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next time something similar breaks, the queries are already there.&lt;/p&gt;

&lt;h2&gt;
  
  
  This Flow Landed Me A Job
&lt;/h2&gt;

&lt;p&gt;The general lesson is this. Whenever you write a mapping that does something to text, ask whether it should be an operator. An operator multiplies whatever you wrote by every motion and text object you know.&lt;/p&gt;

&lt;p&gt;My flow is not original. &lt;a href="https://github.com/jpalardy/vim-slime" rel="noopener noreferrer"&gt;vim-slime&lt;/a&gt; is the modern descendant of slime.vim, and it has its own operator, &lt;code&gt;&amp;lt;Plug&amp;gt;SlimeMotionSend&lt;/code&gt;. I built mine before I found out about it. I also haven't switched because I use vimux for other things, like running specs.&lt;/p&gt;

&lt;p&gt;This flow once helped me get a job once. It was a timed coding interview. I had one hour to solve a few bugs. I had a Rails console for checking data. I wrote each Active Record query once and ran it with &lt;code&gt;gss&lt;/code&gt;. Copy-pasting would have cost a few seconds every time. I finished with less than a minute left. A few seconds doesn't sound like much, but spread it across an hour, it's the difference between finishing and not. Try it! Maybe it'll help you get a job too!&lt;/p&gt;

&lt;p&gt;Not a Vim user? Vimux is mostly a wrapper around tmux commands. &lt;code&gt;tmux send-keys -t %12 'User.count' Enter&lt;/code&gt; sends a "User.count" into pane &lt;code&gt;%12&lt;/code&gt;. For a longer chunk of text, &lt;code&gt;tmux load-buffer -&lt;/code&gt; then &lt;code&gt;tmux paste-buffer -t %12&lt;/code&gt; does the same job. Any editor or IDE that can run a shell command can do this. I'd ask Claude: "How do I send a body of text to tmux pane X from my editor?"&lt;/p&gt;

</description>
      <category>vim</category>
      <category>tmux</category>
      <category>vimux</category>
      <category>operator</category>
    </item>
    <item>
      <title>How to make your own Vim operator</title>
      <dc:creator>Igor Irianto</dc:creator>
      <pubDate>Sat, 19 Sep 2026 20:55:00 +0000</pubDate>
      <link>https://dev.to/iggredible/how-to-make-your-own-vim-operator-4d4k</link>
      <guid>https://dev.to/iggredible/how-to-make-your-own-vim-operator-4d4k</guid>
      <description>&lt;h2&gt;
  
  
  Vim grammar: verb + noun
&lt;/h2&gt;

&lt;p&gt;Vim has its own grammar. When you grasp it, it's like a paradigm shift: you can run Vim commands intuitively.&lt;/p&gt;

&lt;p&gt;There is only one grammar rule in the Vim language:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;That's all you need to know. It's like saying:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"Eat (verb) a pancake (noun)"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Kick (verb) a soccer ball (noun)"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Learn (verb) Vim editor (noun)"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Vim verbs are operators
&lt;/h3&gt;

&lt;p&gt;Vim has 16 operators (&lt;code&gt;:h operator&lt;/code&gt;). Some examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;y    Yank text (copy)
d    Delete text and save to register
c    Delete text, save to register, and start insert mode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Vim nouns are motions
&lt;/h3&gt;

&lt;p&gt;Vim nouns are motions. Motions can be used independently; they're used to move around in Vim. Some examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h    Left
j    Down
k    Up
l    Right
w    Move forward to the beginning of the next word
}    Jump to the next paragraph
$    Go to the end of the line
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Vim nouns are also text objects
&lt;/h3&gt;

&lt;p&gt;Vim nouns are not just motions. There are also text objects. Text objects must be used with verbs (operators). If it's your first time using Vim, it may sound weird, but trust me, when you grasp it, it's intuitive!&lt;/p&gt;

&lt;p&gt;There are 2 kinds of text objects: inner and outer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;i + object    Inner text object
a + object    Outer text object
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't get intimidated by them. Learn more at &lt;code&gt;:h text-objects&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Combining verbs and nouns
&lt;/h3&gt;

&lt;p&gt;You don't have to memorize everything before getting started. You can memorize 20% of the nouns and verbs and get really productive (I personally use &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;d&lt;/code&gt;, and &lt;code&gt;c&lt;/code&gt; about 80% of the time; there are even some operators that I haven't used in years).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;learn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vim&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your cursor is on &lt;code&gt;l&lt;/code&gt;, you can delete everything from the current location to the end of the line with &lt;code&gt;d$&lt;/code&gt;: verb (delete &lt;code&gt;d&lt;/code&gt;) + noun (end of the line &lt;code&gt;$&lt;/code&gt;). If your cursor is on &lt;code&gt;learn&lt;/code&gt; and you want to delete the whole word, use &lt;code&gt;diw&lt;/code&gt;: verb (delete &lt;code&gt;d&lt;/code&gt;) + noun (inner word &lt;code&gt;iw&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Vim also has a "convention" where pressing the operator twice means "apply this operator on the whole line". So &lt;code&gt;dd&lt;/code&gt; deletes the whole &lt;code&gt;learn = 'vim'&lt;/code&gt; line.&lt;/p&gt;

&lt;p&gt;I wrote more on Vim grammar in &lt;a href="https://github.com/iggredible/Learn-Vim/blob/master/ch04_vim_grammar.md" rel="noopener noreferrer"&gt;Learn Vim, chapter 4.&lt;/a&gt; if you want to learn more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Vim grammar is intuitive
&lt;/h2&gt;

&lt;p&gt;Practice using Vim grammar multiple times. Start with one operator (I suggest &lt;code&gt;d&lt;/code&gt;), then expand to other operators. Once you get used to it, it's an awesome feeling: you can learn about a new operator and immediately know how to use it. Let's say you learn about &lt;code&gt;gu&lt;/code&gt; (the lowercase operator). You want to lowercase the current word. What do you press?&lt;/p&gt;

&lt;p&gt;Lowercase + the current word.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gu&lt;/code&gt; (lowercase) + &lt;code&gt;iw&lt;/code&gt; (the inner word)&lt;/p&gt;

&lt;p&gt;So you press &lt;code&gt;guiw&lt;/code&gt; ... and hey!! You just lowercased the inner word! Neat!&lt;/p&gt;

&lt;p&gt;Next, you want to lowercase everything to the end of the line.&lt;/p&gt;

&lt;p&gt;Lowercase + to the end of the line.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gu&lt;/code&gt; (lowercase) + &lt;code&gt;$&lt;/code&gt; (from the current location to the end of the line)&lt;/p&gt;

&lt;p&gt;You press &lt;code&gt;gu$&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vim has a convention - by repeating the operator key twice, it acts on the whole line. For example, &lt;code&gt;dd&lt;/code&gt; deletes the current line, &lt;code&gt;yy&lt;/code&gt; yanks the current line. But &lt;code&gt;d&lt;/code&gt; is a one-letter operator and &lt;code&gt;gu&lt;/code&gt; is a two-letter operator. What do you do? &lt;code&gt;gugu&lt;/code&gt; or &lt;code&gt;guu&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Doesn't matter. Both &lt;code&gt;gugu&lt;/code&gt; and &lt;code&gt;guu&lt;/code&gt; work!&lt;/p&gt;

&lt;p&gt;The best part is, you just knew, instinctively, that it would work. Learn a new operator and you know it will work with motions and text objects. Learn a new motion or text object and you know it will work with every operator. All you need to add to your muscle memory is the new piece.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vim grammar can be expanded
&lt;/h2&gt;

&lt;p&gt;Society keeps adding new words to our vocabulary. Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Dang it, that seagull &lt;strong&gt;photobombed&lt;/strong&gt; our family photo"&lt;/li&gt;
&lt;li&gt;"That dude drove a new Tesla just to &lt;strong&gt;flex&lt;/strong&gt; on his coworkers"&lt;/li&gt;
&lt;li&gt;"We're just gonna &lt;strong&gt;vibe&lt;/strong&gt; on the patio this Memorial Day weekend and chill"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the past 10-20 years we added many new words that I'm probably not aware of because I'm old and not cool. The point I'm making is not that I'm old and not cool (although that's sadly true), but that Vim grammar, too, can be expanded! Just like our vocabulary, Vim grammar is not fixed. We can add new Vim verbs.&lt;/p&gt;

&lt;p&gt;One way is to install plugins. There are plugins that add operators, motions, and text objects, like &lt;a href="https://github.com/tpope/vim-commentary" rel="noopener noreferrer"&gt;vim-commentary&lt;/a&gt;, &lt;a href="https://github.com/machakann/vim-sandwich" rel="noopener noreferrer"&gt;vim-sandwich&lt;/a&gt;, and &lt;a href="https://github.com/tommcdo/vim-exchange" rel="noopener noreferrer"&gt;vim-exchange&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another way is to create your own operator - which is what this article is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create your own Vim operator
&lt;/h2&gt;

&lt;p&gt;A custom Vim operator is a mapping that sets &lt;code&gt;'operatorfunc'&lt;/code&gt; to your function and returns &lt;code&gt;g@&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I learn better from examples, so let's jump straight to one. Let's create a new operator, &lt;code&gt;gz&lt;/code&gt;, that reverses text. Pass it 'hello' and you get 'olleh'. &lt;/p&gt;

&lt;p&gt;Here's the full code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; Reverse&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; abort
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt;# &lt;span class="s1"&gt;'line'&lt;/span&gt;
    normal&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="s1"&gt;'[V'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;"ry
  &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt;# &lt;span class="s1"&gt;'block'&lt;/span&gt;
    &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"normal! `[\&amp;lt;C-V&amp;gt;`]\"ry"&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    normal&lt;span class="p"&gt;!&lt;/span&gt; `&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;v&lt;/span&gt;`&lt;span class="p"&gt;]&lt;/span&gt;"ry
  &lt;span class="k"&gt;endif&lt;/span&gt;

  &lt;span class="k"&gt;let&lt;/span&gt; @&lt;span class="k"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;substitute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;@&lt;span class="k"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'\n$'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'\zs'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  normal&lt;span class="p"&gt;!&lt;/span&gt; gv"rp
&lt;span class="k"&gt;endfunction&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:SetupReverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;operatorfunc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;Reverse
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'g@'&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;

nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;expr&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gz  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SetupReverse&lt;span class="p"&gt;()&lt;/span&gt;
xnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;expr&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gz  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SetupReverse&lt;span class="p"&gt;()&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;expr&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gzz &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SetupReverse&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spoiler alert: the magic ingredient to create a new operator is &lt;code&gt;g@&lt;/code&gt; (&lt;code&gt;:h g@&lt;/code&gt;). I'll go over this in just a little bit. The code above is composed of 3 parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The transformer function (&lt;code&gt;Reverse&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The operator function (&lt;code&gt;SetupReverse&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The key mappings (the &lt;code&gt;noremap&lt;/code&gt; expressions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start with the last part, the mappings.&lt;/p&gt;

&lt;h3&gt;
  
  
  The key mappings
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;expr&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gz  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SetupReverse&lt;span class="p"&gt;()&lt;/span&gt;
xnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;expr&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gz  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SetupReverse&lt;span class="p"&gt;()&lt;/span&gt;
nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;expr&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gzz &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SetupReverse&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nnoremap&lt;/code&gt; maps &lt;code&gt;gz&lt;/code&gt; to &lt;code&gt;SetupReverse&lt;/code&gt; in normal mode. This  allows you to press &lt;code&gt;gz&lt;/code&gt; + motion/text object like any operator. &lt;code&gt;xnoremap&lt;/code&gt; maps &lt;code&gt;gz&lt;/code&gt; to the same function in visual mode (&lt;code&gt;v&lt;/code&gt;, &lt;code&gt;V&lt;/code&gt;, &lt;code&gt;&amp;lt;C-V&amp;gt;&lt;/code&gt;). This lets you to first highlight a text then press &lt;code&gt;gz&lt;/code&gt; to reverse them. This is also how any native Vim operator behaves.&lt;/p&gt;

&lt;p&gt;The last &lt;code&gt;nnoremap&lt;/code&gt; maps &lt;code&gt;gzz&lt;/code&gt; to &lt;code&gt;SetupReverse&lt;/code&gt; &lt;em&gt;concatenated&lt;/em&gt; with &lt;code&gt;_&lt;/code&gt;. Why &lt;code&gt;_&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Recall Vim has the convention that doubling an operator key makes it act on the current line: &lt;code&gt;dd&lt;/code&gt;, &lt;code&gt;yy&lt;/code&gt;, &lt;code&gt;cc&lt;/code&gt;, &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;gUU&lt;/code&gt;, &lt;code&gt;guu&lt;/code&gt;. To follow that convention, our operator needs one extra mapping. &lt;code&gt;_&lt;/code&gt; is actually a motion and it means "this line, linewise" (&lt;code&gt;:h _&lt;/code&gt;). You technically don't need the mapping because &lt;code&gt;gz_&lt;/code&gt; already works, just like &lt;code&gt;d_&lt;/code&gt; is the same as &lt;code&gt;dd&lt;/code&gt; and &lt;code&gt;gu_&lt;/code&gt; the same as &lt;code&gt;guu&lt;/code&gt; - but it's nice to follow Vim convention. My muscle memory is itching to press &lt;code&gt;gzz&lt;/code&gt; to reverse the whole line.&lt;/p&gt;

&lt;p&gt;By the way, if you're one of those people who actually prefer &lt;code&gt;gugu&lt;/code&gt; instead of &lt;code&gt;guu&lt;/code&gt; and &lt;code&gt;gUgU&lt;/code&gt; instead of &lt;code&gt;gUU&lt;/code&gt;, feel free to add a map for &lt;code&gt;gzgz&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;expr&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gzgz &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SetupReverse&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;SID&amp;gt;&lt;/code&gt; means script-local. I won't go over it in detail here (&lt;code&gt;:h &amp;lt;SID&amp;gt;&lt;/code&gt;); all you need to know is that &lt;code&gt;SetupReverse&lt;/code&gt; is a script-local function (defined with &lt;code&gt;s:&lt;/code&gt;), and from a mapping we can't call &lt;code&gt;SetupReverse()&lt;/code&gt; directly, we need &lt;code&gt;&amp;lt;SID&amp;gt;SetupReverse()&lt;/code&gt;. &lt;code&gt;Reverse&lt;/code&gt;, on the other hand, is global, because Vim calls &lt;code&gt;operatorfunc&lt;/code&gt; (&lt;code&gt;:h 'operatorfunc'&lt;/code&gt;) from outside our script.&lt;/p&gt;

&lt;h3&gt;
  
  
  The operator function: set operatorfunc, return g@
&lt;/h3&gt;

&lt;p&gt;Ok, so we use 3 mappings to create our operator, but how does that work? I thought &lt;code&gt;nnoremap&lt;/code&gt; was for "basic" mappings, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;vs&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;source&lt;/span&gt; $HOME&lt;span class="sr"&gt;/.vim/&lt;/span&gt;vimrc&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;CR&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I press &lt;code&gt;&amp;lt;Leader&amp;gt;vs&lt;/code&gt; and Vim sources my vimrc. That's it. I don't pass it a motion or a text object. I don't press &lt;code&gt;&amp;lt;Leader&amp;gt;vs&lt;/code&gt; and then &lt;code&gt;$&lt;/code&gt;. I didn't know I could press a motion / text object after my mapping? Yet somehow this mapping lets me pass motions and text objects, like &lt;code&gt;gz$&lt;/code&gt; or &lt;code&gt;gziw&lt;/code&gt;, and makes &lt;code&gt;gz&lt;/code&gt; act like an operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;nnoremap &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;expr&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; gz  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;SID&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;SetupReverse&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're actually right. There is nothing magical about the mapping. &lt;code&gt;&amp;lt;expr&amp;gt;&lt;/code&gt; means "evaluate this expression and type whatever it returns". &lt;code&gt;SetupReverse()&lt;/code&gt; returns &lt;code&gt;'g@'&lt;/code&gt;, so pressing &lt;code&gt;gz&lt;/code&gt; is the same as typing &lt;code&gt;g@&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The secret sauce is in what &lt;code&gt;g@&lt;/code&gt; does, not in the mapping. Let's look inside &lt;code&gt;SetupReverse()&lt;/code&gt;. It does 2 things: sets &lt;code&gt;operatorfunc&lt;/code&gt; with a function (our &lt;code&gt;Reverse&lt;/code&gt; function) and returns &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 viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;s:SetupReverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; abort
  &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;operatorfunc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;Reverse
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'g@'&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What g@ does in Vim
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;g@&lt;/code&gt; is a built-in operator that &lt;em&gt;waits for a motion&lt;/em&gt;. You type a motion or text object (&lt;code&gt;iw&lt;/code&gt;), and Vim runs whatever function is assigned to &lt;code&gt;operatorfunc&lt;/code&gt; on that region.&lt;/p&gt;

&lt;p&gt;What happens when you press &lt;code&gt;gziw&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;gz&lt;/code&gt; calls &lt;code&gt;SetupReverse()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SetupReverse()&lt;/code&gt; sets &lt;code&gt;operatorfunc&lt;/code&gt; to &lt;code&gt;Reverse&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It returns &lt;code&gt;g@&lt;/code&gt;, which Vim types for you&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;g@&lt;/code&gt; enters operator-pending mode: it waits for a motion or text object&lt;/li&gt;
&lt;li&gt;You press &lt;code&gt;iw&lt;/code&gt; (hey, a text object!)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;g@&lt;/code&gt; calls &lt;code&gt;operatorfunc&lt;/code&gt; (&lt;code&gt;Reverse&lt;/code&gt;) &lt;em&gt;and&lt;/em&gt; passes it a type (more on this below)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Take a pause and digest that. This is where the magic happens!&lt;/p&gt;

&lt;p&gt;There is nothing magical about &lt;code&gt;nnoremap&lt;/code&gt;. When &lt;code&gt;g@&lt;/code&gt; gets one, Vim says, "Hey, here's a region. Now run &lt;code&gt;operatorfunc&lt;/code&gt; on it". This is how you make an operator in Vim.&lt;/p&gt;

&lt;h3&gt;
  
  
  The transformer function
&lt;/h3&gt;

&lt;p&gt;Let's see the function assigned to &lt;code&gt;operatorfunc&lt;/code&gt;. It looks complicated. Let's break it down!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; Reverse&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; abort
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt;# &lt;span class="s1"&gt;'line'&lt;/span&gt;
    normal&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="s1"&gt;'[V'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;"ry
  &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt;# &lt;span class="s1"&gt;'block'&lt;/span&gt;
    &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"normal! `[\&amp;lt;C-V&amp;gt;`]\"ry"&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    normal&lt;span class="p"&gt;!&lt;/span&gt; `&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;v&lt;/span&gt;`&lt;span class="p"&gt;]&lt;/span&gt;"ry
  &lt;span class="k"&gt;endif&lt;/span&gt;

  &lt;span class="k"&gt;let&lt;/span&gt; @&lt;span class="k"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;substitute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;@&lt;span class="k"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'\n$'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'\zs'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  normal&lt;span class="p"&gt;!&lt;/span&gt; gv"rp
&lt;span class="k"&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pay attention to what &lt;code&gt;Reverse()&lt;/code&gt;'s argument is &lt;em&gt;not&lt;/em&gt;. It's not text. I'd expect &lt;code&gt;gziw&lt;/code&gt; on "class" to mean "reverse the word 'class' I'm passing you", and &lt;code&gt;gzz&lt;/code&gt; on "learn = 'vim'" to mean "reverse this line, pls". But &lt;code&gt;Reverse&lt;/code&gt; doesn't receive text. It receives a &lt;code&gt;type&lt;/code&gt;. What the heck is type? And how does it know which text to transform? Where's the text??&lt;/p&gt;

&lt;h4&gt;
  
  
  The three region types: char, line, and block
&lt;/h4&gt;

&lt;p&gt;In Vim there are 3 region types: &lt;code&gt;'char'&lt;/code&gt;, &lt;code&gt;'line'&lt;/code&gt;, and &lt;code&gt;'block'&lt;/code&gt;. Vim picks one based on &lt;em&gt;how the region was produced&lt;/em&gt;, i.e. which motion or text object you passed. Every motion in &lt;code&gt;:h motion.txt&lt;/code&gt; is either characterwise or linewise:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Motions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;char&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;w&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;e&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;^&lt;/code&gt;, &lt;code&gt;h&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt;, &lt;code&gt;f&lt;/code&gt;/&lt;code&gt;t&lt;/code&gt;, &lt;code&gt;%&lt;/code&gt;, &lt;code&gt;`&lt;/code&gt;mark, &lt;code&gt;iw&lt;/code&gt;, &lt;code&gt;aw&lt;/code&gt;, &lt;code&gt;i"&lt;/code&gt;, &lt;code&gt;i(&lt;/code&gt;, &lt;code&gt;it&lt;/code&gt;, &lt;code&gt;/pattern&lt;/code&gt; …&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;line&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;j&lt;/code&gt;, &lt;code&gt;k&lt;/code&gt;, &lt;code&gt;_&lt;/code&gt;, &lt;code&gt;G&lt;/code&gt;, &lt;code&gt;gg&lt;/code&gt;, &lt;code&gt;'&lt;/code&gt;mark, &lt;code&gt;ip&lt;/code&gt;, &lt;code&gt;ap&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;H&lt;/code&gt;/&lt;code&gt;L&lt;/code&gt;/&lt;code&gt;M&lt;/code&gt; …&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In general, motions that move up/down or cover whole lines are linewise; anything that lands on a specific column is characterwise. You can force a type with the visual mode keys: &lt;code&gt;gzvj&lt;/code&gt; forces &lt;code&gt;j&lt;/code&gt; to be characterwise, &lt;code&gt;gzV$&lt;/code&gt; forces &lt;code&gt;$&lt;/code&gt; to be linewise, &lt;code&gt;gz&amp;lt;C-V&amp;gt;iw&lt;/code&gt; forces blockwise (&lt;code&gt;:h o_v&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The 3 types mirror the 3 visual modes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Visual mode&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;char&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;V&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;line&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;C-V&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;block&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Want to see it yourself? Add an echo inside &lt;code&gt;Reverse&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; Reverse&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; abort
  &lt;span class="k"&gt;echomsg&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't have to memorize which type each motion translates to. Just know that &lt;code&gt;gziw&lt;/code&gt; → &lt;code&gt;char&lt;/code&gt;, &lt;code&gt;gzj&lt;/code&gt; → &lt;code&gt;line&lt;/code&gt;, &lt;code&gt;&amp;lt;C-V&amp;gt;jjgz&lt;/code&gt; → &lt;code&gt;block&lt;/code&gt;, and &lt;code&gt;gzz&lt;/code&gt; (AKA &lt;code&gt;gz_&lt;/code&gt;) is always &lt;code&gt;line&lt;/code&gt; because &lt;code&gt;_&lt;/code&gt; is a linewise motion.&lt;/p&gt;

&lt;p&gt;Wait, so &lt;code&gt;Reverse&lt;/code&gt; only gets the type, not the text? How does it know what text to transform?&lt;/p&gt;

&lt;p&gt;Yup. We have to go through some hoops to get the text. But &lt;code&gt;type&lt;/code&gt; is what we need to do the job.&lt;/p&gt;

&lt;h4&gt;
  
  
  Reselecting the region with '[ and ']
&lt;/h4&gt;

&lt;p&gt;Using this text again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;learn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;vim&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's say you did &lt;code&gt;gzz&lt;/code&gt; (or equivalently, &lt;code&gt;gz_&lt;/code&gt;). That's a &lt;code&gt;line&lt;/code&gt; type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt;# &lt;span class="s1"&gt;'line'&lt;/span&gt;
  normal&lt;span class="p"&gt;!&lt;/span&gt; &lt;span class="s1"&gt;'[V'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;"ry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vim runs &lt;code&gt;normal! '[V']"ry&lt;/code&gt;. What the heck is that? &lt;/p&gt;

&lt;p&gt;&lt;code&gt;normal!&lt;/code&gt; runs normal-mode keys (the &lt;code&gt;!&lt;/code&gt; ignores your mappings). &lt;code&gt;'[&lt;/code&gt; jumps to the first line of the &lt;em&gt;text you just operated on&lt;/em&gt; (&lt;code&gt;:h '[&lt;/code&gt;). &lt;code&gt;V&lt;/code&gt; starts linewise visual mode. &lt;code&gt;']&lt;/code&gt; jumps to the last line of the text you just operated on (&lt;code&gt;:h ']&lt;/code&gt;). Stop right there. &lt;code&gt;'[V']&lt;/code&gt; re-highlights the entire region you just operated on (&lt;code&gt;learn = 'vim'&lt;/code&gt;, in linewise visual mode). That's it.&lt;/p&gt;

&lt;p&gt;Try it yourself. Find a random line in your file and run a line operation on it (&lt;code&gt;gUU&lt;/code&gt;, &lt;code&gt;gU2j&lt;/code&gt;, &lt;code&gt;y10j&lt;/code&gt;). Then press &lt;code&gt;'[&lt;/code&gt; (or its backtick variation, &lt;code&gt;`[&lt;/code&gt;, which goes to the exact character). Where is your cursor? Now press &lt;code&gt;V&lt;/code&gt;, then &lt;code&gt;']&lt;/code&gt;. Where does that take you? Vim just re-selected the whole text you operated on! &lt;/p&gt;

&lt;p&gt;Now the final part: &lt;code&gt;"ry&lt;/code&gt;. &lt;code&gt;"r&lt;/code&gt; means "whatever I'm about to do, use register &lt;code&gt;r&lt;/code&gt;", and &lt;code&gt;y&lt;/code&gt; yanks. We just yanked the region into register &lt;code&gt;r&lt;/code&gt; (any register works; nothing is special about &lt;code&gt;r&lt;/code&gt;).&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; @&lt;span class="k"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;substitute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;@&lt;span class="k"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'\n$'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'\zs'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the transformation. &lt;code&gt;@r&lt;/code&gt; is the content of register &lt;code&gt;r&lt;/code&gt;. A linewise yank ends in a newline, so &lt;code&gt;substitute(@r, '\n$', '', '')&lt;/code&gt; strips it first (otherwise the newline would get reversed to the front, and you'd paste an empty line above your text). &lt;code&gt;split(..., '\zs')&lt;/code&gt; splits the string into characters (&lt;code&gt;\zs&lt;/code&gt; is a zero-width match, so it works on texts), &lt;code&gt;reverse()&lt;/code&gt; reverses the list, and &lt;code&gt;join()&lt;/code&gt; puts it back into a string. The result is assigned to &lt;code&gt;@r&lt;/code&gt;. Register &lt;code&gt;r&lt;/code&gt; now holds the reversed text.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;normal&lt;span class="p"&gt;!&lt;/span&gt; gv"rp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;gv&lt;/code&gt; re-selects the previous visual area in the same mode. Since we just did &lt;code&gt;'[V']&lt;/code&gt;, that's the line &lt;code&gt;learn = 'vim'&lt;/code&gt;. &lt;code&gt;"rp&lt;/code&gt; pastes register &lt;code&gt;r&lt;/code&gt; over it. Pasting over a visual selection replaces it.&lt;/p&gt;

&lt;p&gt;And that, my friend, is how you create your own operator in Vim.&lt;/p&gt;

&lt;p&gt;What about the other 2 branches?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;  &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="nv"&gt;a:type&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt;# &lt;span class="s1"&gt;'block'&lt;/span&gt;
    &lt;span class="nb"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"normal! `[\&amp;lt;C-V&amp;gt;`]\"ry"&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    normal&lt;span class="p"&gt;!&lt;/span&gt; `&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;v&lt;/span&gt;`&lt;span class="p"&gt;]&lt;/span&gt;"ry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same concept. The &lt;code&gt;char&lt;/code&gt; branch re-highlights with &lt;code&gt;`[&lt;/code&gt; and &lt;code&gt;`]&lt;/code&gt; (exact characters, not whole lines) in &lt;code&gt;v&lt;/code&gt; mode and the &lt;code&gt;block&lt;/code&gt; branch does it in &lt;code&gt;&amp;lt;C-V&amp;gt;&lt;/code&gt; mode. The latter is rare (usually invoked with &lt;code&gt;&amp;lt;C-V&amp;gt;&lt;/code&gt; first), and our one-line transformation doesn't know about block shapes, so it will scramble a block. Making it block-aware is a good exercise (hint: &lt;code&gt;getreginfo()&lt;/code&gt; and &lt;code&gt;setreg()&lt;/code&gt; let you transform the register line by line while keeping its type).&lt;/p&gt;

&lt;h2&gt;
  
  
  The bare minimum: g@ and operatorfunc
&lt;/h2&gt;

&lt;p&gt;You technically don't even need &lt;code&gt;nnoremap&lt;/code&gt; and &lt;code&gt;SetupReverse&lt;/code&gt; for the operator to work because &lt;code&gt;g@&lt;/code&gt; does most of the work for you. Try this. Assign &lt;code&gt;operatorfunc&lt;/code&gt; to the transformer function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nb"&gt;operatorfunc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;Reverse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you are ready to invoke the &lt;code&gt;Reverse&lt;/code&gt; function. Press &lt;code&gt;g@iw&lt;/code&gt;, it will reverse the inner word. Press &lt;code&gt;g@$&lt;/code&gt;, it will reverse the texts to the end of the line. Press &lt;code&gt;g@_&lt;/code&gt;, it will reverse the current line. &lt;code&gt;g@&lt;/code&gt; invokes whatever function is assigned to &lt;code&gt;operatorfunc&lt;/code&gt;. That's really all you need!&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary: how a custom Vim operator works
&lt;/h2&gt;

&lt;p&gt;To create a Vim operator, pick a key (here, &lt;code&gt;gz&lt;/code&gt;) and map it to a function that does 2 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set &lt;code&gt;operatorfunc&lt;/code&gt; to the transformer function&lt;/li&gt;
&lt;li&gt;Return &lt;code&gt;g@&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Creating an operator in Vim is no magic. It's just a bunch of Vim operations encapsulated in functions.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;g@&lt;/code&gt; goes into operator-pending mode and waits for a motion or text object. It then calls the transformer with the region's type: &lt;code&gt;char&lt;/code&gt;, &lt;code&gt;line&lt;/code&gt;, or &lt;code&gt;block&lt;/code&gt;. Depending on the type, the transformer re-selects the region in the matching visual mode, yanks it, transforms it, and pastes it back.&lt;/p&gt;

&lt;p&gt;The code I showed here works, but it is still pretty rough. It 'pollutes' your registers: whatever you had in register &lt;code&gt;r&lt;/code&gt; is now replaced with the operated-on text, and the visual &lt;code&gt;p&lt;/code&gt; overwrites the unnamed register too. It also pollutes your marks and jumps: &lt;code&gt;'&amp;lt;&lt;/code&gt;, &lt;code&gt;'&amp;gt;&lt;/code&gt; (what &lt;code&gt;gv&lt;/code&gt; uses) and the jumplist now point at whatever we just highlighted. A good operator saves those states in temporary variables, does its transformation, then restores them so Vim "forgets" the operation ever happened.&lt;/p&gt;

&lt;p&gt;I wrote a plugin, &lt;a href="https://github.com/iggredible/vim-operatorify" rel="noopener noreferrer"&gt;vim-operatorify&lt;/a&gt; that lets you to create an operator easily.  Check out my plugin to see &lt;a href="https://github.com/iggredible/vim-operatorify/blob/main/autoload/Operatorify.vim" rel="noopener noreferrer"&gt;how to handle some rough edges&lt;/a&gt;. Pay attention to how I created temp variables (&lt;code&gt;save&lt;/code&gt;) and restored them after the transformation was done in the &lt;code&gt;finally&lt;/code&gt; block.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes a custom Vim operator feel native
&lt;/h2&gt;

&lt;p&gt;A good operator should feel native.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It uses Vim's own API: &lt;code&gt;g@&lt;/code&gt; and &lt;code&gt;'operatorfunc'&lt;/code&gt;, not a reimplementation of operator semantics.&lt;/li&gt;
&lt;li&gt;It composes with the full motion grammar, including text objects from plugins you install next year.&lt;/li&gt;
&lt;li&gt;Follows the double-letter-convention for linewise effect. &lt;code&gt;gzz&lt;/code&gt; is implemented as &lt;code&gt;g@_&lt;/code&gt;, just like &lt;code&gt;dd&lt;/code&gt;, &lt;code&gt;yy&lt;/code&gt;, &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;guu&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Works on visual mode too.&lt;/li&gt;
&lt;li&gt;Dot-repeat works. &lt;code&gt;g@&lt;/code&gt; gives you &lt;code&gt;.&lt;/code&gt; for free. &lt;/li&gt;
&lt;li&gt;Counts work. &lt;code&gt;gz3j&lt;/code&gt; reverses four lines.&lt;/li&gt;
&lt;li&gt;Vim's conventional home for extra operator is to use &lt;code&gt;g*&lt;/code&gt; (make sure &lt;code&gt;gz&lt;/code&gt; isn't taken; check with &lt;code&gt;:h map-which-keys&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Now that you know how to make an operator, create your own!&lt;/p&gt;

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

</description>
      <category>vim</category>
      <category>neovim</category>
      <category>vimscript</category>
      <category>tutorial</category>
    </item>
    <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 javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;e&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;e&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;e&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;e&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 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 json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;one:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;two:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;three:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;four:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;def:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;abc:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;jkl:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;ghi:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;four:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;one:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;three:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;two:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;abc:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;def:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;ghi:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;jkl:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;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>
  </channel>
</rss>
