Getting Started with Vim

I’m giving Vim a try for the next 30 days (well, 27 days now) as my only editor. I just switched over to a Macbook Air as my main development machine so I am not even going to install TextMate or any other editors besides MacVim. I’ve made a couple attempts in the past at getting into Vim, but I just found myself getting frustrated at how unproductive I was and I quickly switched back to TextMate.

I’m already a couple days in to the challenge and have really enjoyed learning about all the editor has to offer. Partially to keep myself accountable to the challenge and partially to help others who are trying to make the switch to Vim, I’m going to be sharing my experiences here along the way. I’ll be giving my perspective coming from TextMate to Vim but I will try to share any tips and tricks I learn along the way that I find are improving my productivity.  I’d also be happy to answer any questions people have, so feel free to ask away in the comments.

The First Few Days

I’m already a few days in to the challenge and have had my fair share of struggles figuring out how to do things that were already part of my workflow in TextMate. I’m getting fairly comfortable with the editor and I would say that I’m about 90% as productive as I was previously in TextMate and I still have a lot to learn.

Here are a few things things that have been important to my adoption of the editor.

Multiple Editing Modes

This was tough to get used to at first. Remembering to switch between insert, visual and normal mode was a bit of a pain and I found myself typing a lot of nonsense when I would forget to jump in or out of a certain mode, but I’m pretty much past that. I’m already enjoying a lot of the commands that are available in normal mode and I would probably miss them if I were to make the switch back at this point.

Working with Multiple Files

One of the biggest differences with MacVim and pretty much any GUI editor out there is that you don’t have a file tree to look through and open files. Opening files with the default command (:e) is a bit of a pain, especially in large projects, but I realized that PeepOpen could bring back the awesome Go to File… command from TextMate (Command + T). This alone was a huge time saver.

If you haven’t heard of PeepOpen, you should check it out. If you are a MacVim or TextMate user, it is an awesome add on that can help you a lot when working with multiple files.

Learning My First Few Commands

To get my feet wet with Vim I tried out the built-in vimtutor that comes with the editor. It was a great introduction and easily worth the 45 minutes or so it took to get through it. Even if you aren’t using Vim on a regular basis, I would highly recommend it to anyone who has to do any editing of files over an SSH connection just so you have the basics of Vim under your belt for those few occasions that you actually have to use it.

To start vimtutor, just go to your Terminal and type vimtutor. That’s all there is to it! It’s really just a big text document that walks you through the Vim commands, but it’s very well done and covers all the basics you need to get started.

Next Steps

I’m still trying to work my way to some more advanced features, but am hoping to get through the Smash Into Vim screencasts from PeepCode in the next couple weeks. I am starting to get the hang of finding and replacing in Vim, but it takes me a while yet so I want to practice up on my regular expressions and understand all the possibilities of the vimgrep command. I also haven’t done any remote editing but am excited to try working with files over SSH.

What I Miss

Although there are a lot of things I like more about MacVim, there are a few things that I really miss.

  • Bundles – not a dealbreaker, but it would be nice to have some of my old bundles for PHP/CodeIgniter and Ruby/Rails.
  • Git Integration – I loved the Git bundle for TM and used it for all of my commits.
  • Find in Project – I used this command all the time, and it will take me a while to get used to finding and replacing in Vim.

I’m guessing all of these issues are not shortcomings of the editor, but only my lack of knowledge about it.

My CodeIgniter Base Model (My_Model)

A friend of mine, Doug Linsmyer, introduced me to Shawn McCool’s basic CRUD model that he uses in CodeIgniter development and I immediately started using it in my CI projects.  However, I couldn’t handle how much repeated code there was in my models so, with some help from my friends on Forrst, I turned it into a base model that I can use for all of my models.  Now all I have to do to create a new model with my CRUD methods is extend them with MY_Model and declare a couple variables.

Setup

In order to get up and running with the base model just:

  1. Download it and drop it into your application/core folder.
  2. Extend your models with MY_Model.
  3. Set the primary_table name.

That’s all that is required, but there are a couple more options.  Here’s a full example:

class Company_model extends MY_Model {

    var $primary_table = 'companies';

    var $validate_field_existence = TRUE;

    var $fields = array(
        'id',
        'name',
        'address',
        'city',
        'state',
        'zipcode',
        'phone',
        'is_active',
        'date_created',
        'date_modified'
    );

    var $required_fields = array(
        'name',
        'address',
        'city',
        'state',
        'zipcode',
        'phone'
    );
}

There are 5 options you can declare:

  • primary_table (required): The name of the table the model should execute queries on.
  • fields: An array of the fields in the database that the model has access to. If you don’t specify the fields here they will be pulled dynamically from the database and the query will be cached.
  • required_fields: An array of fields that must be submitted any time a record is created or updated.
  • models: Set an array of models to be loaded.  This can also be set in a constructor, but it makes things a little easier.
  • validate_field_existence: Validates that the fields you are trying to modify actually exist in the database.  Only use this method for debugging, it is not fit for production code because of the number of queries it has to run

Usage

All of the commands accept an array of parameters where the column name is the key.  When adding and updating a record you simply pass an array of fields you want to change with the values you want them set to:

$options = array(
    'name' => $this->input->post('company_name'),
    'address' => $this->input->post('company_address'),
    'city' => $this->input->post('company_city'),
    'state' => $this->input->post('company_state'),
    'zipcode' => $this->input->post('company_zip'),
    'phone' => $this->input->post('company_phone'),
    'is_active' => $this->input->post('company_is_active')
);
$company = $this->company_model->add($options);

When selecting records you can use any field in the database as a filter:

$options = array(
    'name' => $this->input->post('search_name'),
    'zipcode' => $this->input->post('search_zipcode')
);
$company = $this->company_model->get($options);

That’s about all there is to it. The code is up on GitHub so please feel free to contribute and make this better. I know Jamie Rumbelow and Phil Sturgeon have a base model that provides some similar functionality with some additional methods, but I haven’t really used it much yet. This approach has worked well for me in my projects so I thought I would share it here, but I’m sure it can be drastically improved.

Smooth CSS Transitions On Inset Box Shadows

**UPDATE: **It appears that Firefox 5 and Chrome 12.0 have eliminated the issue of the jumping shadow transition. Safari still has the issue and I haven’t testing with IE or Opera.

If you’ve ever tried to use a CSS transitions on an inset box shadow the result probably wasn’t what you expected. If you are transitioning from no box shadow to an inset box shadow, the transition takes place outside of the element and then jumps inside after the transition is complete. It’s hard to describe, so take a look at the demo to see it in action.

The Solution

If you set an invisible inset box shadow on the element to begin with, the transition have the desired effect. You can set an invisible box shadow by using rgba and setting alpha to 0, or by setting the box-shadow’s color to transparent.

.box { box-shadow: 0 0 0 transparent inset; }
.box { box-shadow: 0 0 0 rgba(0, 0, 0, 0) inset; }

Note: It makes no different whether you use rgba or transparent. I always go with transparent just because that seems more logical when reading it back than rgba.

Other Notes

You might think that if you set the transparent box shadow to a specific color that it would transition from that color to the desired color, but in my tests it hasn’t made a difference. Whether I am transitioning from red (rgba(255, 0, 0, 0)) to blue (rgba(0, 0, 255, 1)) or just transparent to blue I get the same effect.

One other important note is that the spread of your transparent box shadow makes a difference. If you set it to 0 you will get an effect where the shadow “grows” inward from the edge of the element. However, if you set the spread to the same value that you are transitioning to you will only see the shadow just fade in. Again, hard to describe so please take a look at the demo.

Resize Images the Right Way With Photoshop’s Image Processor

This may be old news for some, but batch resizing a mix of portrait and landscape images has always been a pain for me.  I used to:

  1. put all of my landscape images in one folder and my portrait images in another
  2. create a set of actions for each image orientation
  3. run a batch with the respective actions I just created on each folder

I was about to start going through this exact process to resize a set of images when I stopped and decided that I was going to find a better way to handle this.  I’m obviously not the first person to run into this issue so I figured there had to be an answer out there somewhere.  After searching for a while, I discovered Photoshop’s Image Processor tool.  I can’t believe I’ve gotten by this long without it.

The Image Processor can be found by going to:

File > Scripts > Image Processor...

The Photoshop Image Processor settings screen

Most of the settings are self-explanatory, but the “Resize to fit” option is the big time saver for me.  As you can see, I have the maximum height of my images to be 1000px and the maximum width to 1500px.  It makes sure that the dimensions fall within the boundaries of these dimensions so it is basically saying, “make the height of my portrait images 1000px” and “make the width of my landscape images 1500px.”

Hopefully this helps someone else who was running into the same issue and if you have any other questions, feel free to email me or ask a question in the comments.