Quick Fixes With Vim And The Command Line

Vim allows you to perform external commands with the !(bang) operator. The most common use I see is when someone opens a file requiring sudo permissions. They don’t find out until they’ve made their changes and try to save.

Instead of losing the work and re-opening the file under sudo permissions you can save it with :w !sudo tee %. Nathan Long provides an explanation of what’s happening here on Stack Overflow.


I’ve been having issues with a local Ruby on Rails app for the past few days. It doesn’t have the records I expect it to. I’ve run the seed files and they are still missing.

I discovered the reason was that the slugs had been modified. Two months ago I refactored the seed files when I added data to them.

Original

content = Content.find_or_initialize_by(slug: 'easy-reading-title')
content.name = "Easy Reading Title"
content.save!

Refactored

assessment_generator = GenerateContent.new(
slug: 'brand-easy-reading-title',
title: "Easy Reading Title"
)

By refactoring procedural code to objects I could easily use macros to convert a spreadsheet into a seed file.

I’ve reduced this code for demonstrations but left my error in place. The slug changed to something it wasn’t supposed to. At first glance, my problem seems pretty large. I have to compare the current files to what they were months ago. They are completely different in structure and source lines of code.

For 30+ files the process is

  1. Open a file for editing.
  2. Open the file to it’s state two months ago in version control.
  3. Identify the original slug.
  4. Update the current files slug.

Using Vim and the External Command operator I can do this with efficiency. While having the current file open in vim I can type the following: /slug:<enter>:read !git show 0abbdaa37057d:% | grep -o "slug: '.*'" | sed 's/$/,/'<enter>==kdd:w<enter>

  • /slug: Find the first line containing ‘slug’ and put the cursor there.
  • :read !git show 0abbdaa37057d:% | grep -o “slug: ‘.*'” | sed ‘s/$/,/’
    • read: Write the input to current file.
    • !: Perform external command.
    • git show 0abbdaa37057d:%: Show the current file (%) at the state of commit 0abbdaa37057d.
    • |: Pipe operator, take the output from the git statement and input it into the grep.
    • grep -o “slug: ‘.*'”: Find a line containing ‘slug:’ with anything between two quotations. The -o flag tells grep to only return what matches in the pattern. This means instead of getting the entire line, we will just get the slug.
    • |: Pipe operator, take the output from grep and put it into sed.
    • sed ‘s/$/,/’: Append the line with a comma.

At this point we should have the incorrect slug followed by the correct slug.

slug: 'brand-easy-reading-title',
slug: 'easy-reading-title',

  • ==: Correctly indent the new ‘slug’ line.
  • k: Move the cursor up to the incorrect ‘slug’ line.
  • dd: Delete the incorrect ‘slug’ line.
  • :w: Save the changes.

To recap, we add the correct slug by retrieving from git, filtering it with grep, and correct syntax with sed. Then delete the old slug line.

Now that I have my macro I can perform it on all my seed files.

  • vim $(find db/seeds -type f): Open all my seed files in vim.
  • Copy my macro into a register ‘m’.
  • :argdo normal @m: In vim, perform the macro on every file.

Knowing Vim enables you to spend time on greater problems because it’s so easy to solve repetitive problems like this one. Having experience with the command line empowers the use of Vim in greater ways.