List of Favorite OS X Web Developer Apps

The following tools are either open source, shareware or freeware. For shareware, I will post freeware alternatives.DEVELOPMENT* JetBrains RubyMine (for Ruby and Rails development)

* Charles Proxy
* PHP xdebug with remote_enable = true

* SourceTree (if you use git)
* Cornerstone (if you use svn)

* iTerm2
* Zshell with Oh My Zsh
* BetterSnapTool
* Mou (Markdown Editor)
* Tabs Outliner extension for Chrome

* LittleSnitch
* Skitch
* Dropbox
* SuperDupr! or Time Machine
* RescueTime
* Solarized Theme (for shell, TextMate, etc.)

Remote repository hosting

A dedicated IDE or Editor. Pimping Your IDE will be in another post. Here are my most used editors/workflows (not in any specific order. Usually the right one for the job.)

MacVim with solarized (light) BG but I’m constantly tweaking the colorscheme. Font is one of Anonymous, Source Code Pro, Consolas, Inconsolata, all patched for powerline (optional.)

I use NeoBundle to manage my vim packages. Here are my current bundles:

" After install, exec ~/.vim/bundle/vimproc, (n,g)make -f your_machines_makefile</pre>
NeoBundle 'Shougo/vimproc'
NeoBundle 'Shougo/vimshell'
NeoBundle 'kien/ctrlp.vim.git'
NeoBundle 'honza/writer.vim'
NeoBundle 'vim-ruby/vim-ruby'
NeoBundle 'plasticboy/vim-markdown'
NeoBundle 'juvenn/mustache.vim'
NeoBundle 'tpope/vim-rails'
NeoBundle 'tpope/vim-fugitive'
NeoBundle 'tpope/vim-unimpaired'
NeoBundle 'tpope/vim-abolish'
NeoBundle 'tpope/vim-surround'
NeoBundle 'tpope/vim-bundler'
NeoBundle 'tpope/vim-surround'
NeoBundle 'tpope/vim-characterize'
NeoBundle 'tpope/vim-haml'
NeoBundle 'tpope/vim-rake'
NeoBundle 'Lokaltog/vim-easymotion'
NeoBundle 'jeetsukumaran/vim-buffergator'
NeoBundle 'tilljoel/vim-automatic-ctags'
NeoBundle 'git://'
NeoBundle 'altercation/vim-colors-solarized'
NeoBundle 'vim-scripts/Vim-R-plugin'
NeoBundle 'vim-scripts/R-MacOSX'
NeoBundle 'vim-scripts/vim-mou'
NeoBundle 'vim-scripts/ShowMarks'
NeoBundle 'vim-scripts/dbext.vim'
NeoBundle 'vim-scripts/Txtfmt-The-Vim-Highlighter'
NeoBundle 'vim-scripts/mru.vim'
NeoBundle 'vim-scripts/YankRing.vim'
NeoBundle 'majutsushi/tagbar'
NeoBundle 'mileszs/ack.vim'
NeoBundle 'ervandew/screen'
NeoBundle 'L9'
NeoBundle 'Gundo'
NeoBundle 'mattn/zencoding-vim'
NeoBundle 'scrooloose/nerdtree'
NeoBundle 'scrooloose/nerdcommenter'
NeoBundle 'jistr/vim-nerdtree-tabs'
NeoBundle 'nathanaelkane/vim-indent-guides'
NeoBundle 'git://'
NeoBundle 'git://'
NeoBundle ''

Tmux + vim

Send and Receive POST Requests with PHP

This can be used to build an API or generally have different sites and scripts communicate externally.

function postback($url, $params, $optional_headers=null, $decode=true) {
$params['handshake'] = HANDSHAKE;
 $params['url'] = $url;
 $params['remote_ip'] = $_SERVER['REMOTE_ADDR'];
 $data = http_build_query($params);

$options = Array('http' => Array(
 'method' => "POST",
 'header'=> "Accept-language: en\r\n".
 "Content-type: application/x-www-form-urlencoded\r\n",
 "Content-Length: " . strlen($data) . "\r\n",
 'content' => $data));

if ($optional_headers !== null) {
 $params['http']['header'] .= $optional_headers;

$ctx = stream_context_create($options);
$fp = fopen($url, 'r', false, $ctx);
 if (!$fp) throw new Exception("Problem with URL '$url' {$php_errormsg}");

$response = stream_get_contents($fp);
 if ($response === false) throw new Exception("Problem reading data from $url, $php_errormsg");

 if ($decode) $response = json_decode(rawurldecode($response), TRUE);

// Invalid query?
 if (!isset($response['handshake']) || ($response['handshake'] !== HANDSHAKE))
 return NULL;

return $response;


Bulk Upload Images as Simple Products in Magento

The client has thousands of images, each of which is a (simple) product they want in Magento. Each image is named the associated product’s SKU number with a JPG extension. I began by using a recorded Batch script in Photoshop to resize all the images to reduce filesize and make the image more web-friendly.

The following Ruby script generates a Magento Product CSV file from JPG images in a directory. It is pasted as-is.

#!/bin/env ruby

require 'rubygems'
require 'csv'
require 'htmlentities'
require 'uri'

def main
    #Dir.glob("media/products/#{catname}/*").each_with_index do |imgpath, i|

    # Magento 1.7 CSV product headers
    csv_headers = '"store"	"websites"	"attribute_set"	"type"	"category_ids"	"sku"	"has_options"	"name"	"meta_title"	"meta_description"	"image"	"small_image"	"thumbnail"	"url_key"	"url_path"	"custom_design"	"page_layout"	"options_container"	"image_label"	"small_image_label"	"thumbnail_label"	"country_of_manufacture"	"msrp_enabled"	"msrp_display_actual_price_type"	"gift_message_available"	"price"	"special_price"	"weight"	"msrp"	"status"	"visibility"	"Featured"	"Deal"	"Hot"	"enable_googlecheckout"	"tax_class_id"	"is_recurring"	"description"	"short_description"	"meta_keyword"	"custom_layout_update"	"news_from_date"	"news_to_date"	"special_from_date"	"special_to_date"	"custom_design_from"	"custom_design_to"	"qty"	"min_qty"	"use_config_min_qty"	"is_qty_decimal"	"backorders"	"use_config_backorders"	"min_sale_qty"	"use_config_min_sale_qty"	"max_sale_qty"	"use_config_max_sale_qty"	"is_in_stock"	"low_stock_date"	"notify_stock_qty"	"use_config_notify_stock_qty"	"manage_stock"	"use_config_manage_stock"	"stock_status_changed_auto"	"use_config_qty_increments"	"qty_increments"	"use_config_enable_qty_inc"	"enable_qty_increments"	"is_decimal_divided"	"stock_status_changed_automatically"	"use_config_enable_qty_increments"	"product_name"	"store_id"	"product_type_id"	"product_status_changed"	"product_changed_websites"'

    path = "output.csv"
    open(path, 'w') { |f| f.puts csv_headers } 

    Dir.glob("*.JPG").each_with_index do |imgpath, i|
        image_name = File.basename(imgpath)
        image_url = "/#{image_name}"
        sku = image_name[0,image_name.size-4]
        name = sku
        desc_short = sku
        desc = sku
        csv = '"default"	"base"	"Default"	"simple"	"2"	"SKU"	"0"	"NAME"	"META_TITLE"	"META_DESC"	"IMAGE"	"IMAGE"	"IMAGE"	"url-key-SKU"	"url-key-SKU"	""	"No layout updates"	"Block after Info Column"	""	""	""	" "	"Use config"	"Use config"	"No"	"1.0000"	"China"	"1.0000"	""	"Enabled"	"Catalog, Search"	"0"	"0"	"0"	"Yes"	"None"	"No"	"LONG_DESC"	"SHORT_DESC"	"META_KEYWORDS"	""	""	""	""	""	""	""	"10000.0000"	"0.0000"	"1"	"0"	"0"	"1"	"1.0000"	"1"	"0.0000"	"1"	"1"	""	""	"1"	"0"	"1"	"0"	"1"	"0.0000"	"1"	"0"	"0"	"0"	"1"	"NAME"	"0"	"simple"	""	""'
        csv.gsub!('SKU', sku)
        csv.gsub!('NAME', name)
        csv.gsub!('LONG_DESC', desc)
        csv.gsub!('SHORT_DESC', desc_short)
        csv.gsub!('META_TITLE', sku)
        csv.gsub!('META_DESC', sku)
        csv.gsub!('META_KEYWORDS', sku)
        csv.gsub!('IMAGE', "#{image_url}")
        open(path, 'a') { |f| f.puts csv } 

    p "Finished."



#require 'yaml'
#require 'hpricot'
#require 'tempfile'
#require 'mechanize'
#require 'open-uri'
#require 'highline/import'
#HighLine.track_eof = false

class Importer
  def initialize
    CSV.foreach('/Users/bluish/Desktop/export_ish.csv') do |row|
      p row.inspect
    return'/Users/bluish/Desktop/export_ish.csv', 'wb') do |csv|
      p 'injecting csv'
      csv << ['123', '', '456'] 

class String
  def decode

  def encode
def saveImage(remote_url, thumb_url, dir='./media/import')
  require 'open-uri'
        base = File.basename(remote_url)
        img = "#{dir}/#{base}"
        unless File.exist? img
          p img
          open(img, 'wb') do |file|
            file << open(remote_url).read
        thumb =  "#{dir}/thumb-#{base}"
        unless File.exist? thumb
          p thumb
          open(thumb, 'wb') do |file|
            file << open(thumb_url).read
        p "GOT MEDIA"

       p "FAILED to grab #{remote_url}"
       p "or #{thumb_url}"
       p 'Possible 404? continuing...'


Add Items to Category Programmatically in Magento

The code on the bottom will take the following array:

$categories = array(
#   "nickname" => category_id,
    "Eyeliner" => 107,
    "Lipstick" => 108,
    "General" => 18,
#   etc.

The $lineItems array contains a line of category+sku-items in the format “CategoryNick SKU1 SKU2 SKU3.” CategoryNick is matched against the $categories array above to figure out the Magento category ID. If the product is already in the category, it doesn’t do anything. The product will retain the categories it is already associated with rather than dropping the existing category associations.

$lineItems = Array();
$lineItems[] =     "Eyeliner 7897";
$lineItems[] =     "Eyeliner 7898 7772 7771 7770";
$lineItems[] =     "Lipstick 7909-15 7909-16 7939 7941 7984";
$lineItems[] =     "General 7940"; 

This is the full code. It should be placed in a /filename.php file and visited at /filename.php – Make a backup of your database before using this (and daily!) Don’t keep executable PHP files hanging around after use. If you need to, make sure the permissions are 600 or 700 and NOT world-writable or rename to .phps so they aren’t executable by web

define('MAGENTO', realpath(dirname(__FILE__)));
require_once MAGENTO . '/app/Mage.php';

# assign duct tape to all categories
function FindBySku($sku) {
    return Mage::getModel('catalog/product')->loadByAttribute('sku', $sku);

function AddToCategory($product, $newcat, $save=false) {
    $cats = $product->getCategoryIds();

    # Don't double categories
    if (in_array($newcat, $cats)) return;

    $cats[] = $newcat;

    if ($save) return $product->Save();

# 3 categories nicknamed and linked to respective Magento IDs
$categories = array(
    "Eyeliner" => 107,
    "Lipstick" => 108,
    "General" => 18,

# Add 5 items to the Eyeliner category (107), 5 to Lipstick and 1 to General.
$lineItems = Array();
$lineItems[] =     "Eyeliner 7897";
$lineItems[] =     "Eyeliner 7898 7772 7771 7770";
$lineItems[] =     "Lipstick 7909-15 7909-16 7939 7941 7984";
$lineItems[] =     "General 7940"; 

foreach($lineItems as $line) {
    $pieces = explode(' ', $line);
    $cat = $pieces[0];

    #$skus = implode(' ', $pieces);
    #$skus = substr($skus, strpos($skus, ' ')+1, strlen($skus) - strlen($cat));
    # $cat is the category NickName and $skus is a space-delimited list of SKU #s

    $skus = array_slice($pieces, 1);
    # $cat is the category NickName and $skus is an array of SKU numbers

    if (array_key_exists($cat, $categories) && $categories[$cat] != 0) {
        $cat_id = $categories[$cat];
        echo "Adding to category $cat (id = $cat_id)\n";
        echo '\tAdding ' . sizeof($skus) . " SKUs\n";
        #$item_skus = explode(" ", $skus);
        $i = 0;

        foreach($skus as $sku) {
            $product = FindBySku($sku);
            if (!$product) {
                echo "** ERROR: NO PRODUCT FOUND SKU=$sku\n";
            AddToCategory($product, $cat_id, true);
            echo "\tadded $sku to $cat ";

        echo "\nTOTAL $i/" . sizeof($skus) . " items to $cat\n\n";
    } else {
        echo "** ERROR: CANNOT FIND CATEGORY '$cat'\n\n";


Using Rsync to Copy Remote Files to Local Machine on OS X / Linux

The following is used to copy files from a remote server to your local machine using Rsync to keep both synchronized. This is useful for things like backing up important directories on your web server to your external hard drive or elsewhere.

Rsync can incrementally synchronize files between two locations whether local or remote. This means only the updated files on your remote server are updated on your local machine.

From here on in I assume you’re using OS X but this should work on Linux as well. Press CMD+Space to open a Terminal (I use TotalTerminal.) At the command prompt, just use the following:

rsync -a -e "ssh" --rsync-path="sudo rsync -vau " .
rsync -a -e "ssh" --rsync-path="sudo rsync -vau " .
rsync -a -e "ssh" --rsync-path="sudo rsync -vau " .

This will copy /home, /var, and /etc from your remote machine to the current directory.

Installing Alan Storm’s LayoutViewer in Magento (works with 1.7!)

I use the debug toolbar but nothing beats Alan Storm’s configviewer and layoutviewer. Unfortunately the only archive of this on Alan’s site is missing a module config file to activate it. Below is a simple shell script to download, install and activate the LayoutViewer in any version of Magento. I can confirm it works flawlessly in Magento 1.7. If you’d like to manually install this module, read the “manual installation” section below.




# If in root, go to app/code/local
if [ -f "index.php" ]; then
    cd app/code/local;

echo "Using curl to download Magento LayoutViewer"
curl -so - $VIEWER_HTTP_DOWNLOAD | tar xvzf -

echo "Writing app/etc/modules/ config file"
cat <<'ConfigFile'
<?php xml version="1.0"?>
) > ../../etc/modules/Alanstormdotcom_Layoutviewer.xml

echo "Done. Visit any page with ?showLayout=page"

Save this to a file and run “sh” in your Magento root.

Manual Installation

Download the MagentoLayoutViewer and extract the Alanstormdotcom folder to [magento-root]/app/code/local/

Create a new config file in app/etc/modules/ named Alanstormdotcom_Layoutviewer.xml  and paste in it the following:

<?php xml version="1.0"?>

Done. See usage below.

Module Usage

Visit any URL with ?showLayout=page (or handle or package) to retrieve the layouts XML

The module also accepts a showLayoutFormat=text argument if you’d like plain text instead of XML.

Example: http://my-store.cxm/product/123?showLayout=page&showLayoutFormat=text

This vs That — Be Tech Agnostic

Linux (Ubuntu) vs Windows 8 vs OS X
iOS vs Android vs Windows Mobile vs Whatever …

I’m not a “frontend developer.” That’s not my job. I’m a “backend” developer” and I only code PHP and MySQL on OS X. <-- Move away from this mentality and be more accepting of other technologies. Investors and businessmen don't care so much what's under the hood, and neither should you.

Don't limit yourself to a single OS or platform. Dabble in open source and use Linux*, OS X and Windows. Learn WordPress, Joomla, Drupal and Magento. Learn Django, Rails, Symfony and Ruby, Python and PHP. If you're wondering where to start, it's not the tools that matter, but how you use them. In IT, you'll always find a layer of abstraction above where you are right now. There's always a right tool for the job. Taking a top down approach, see the goal and work backwards on how to achieve it. It's true that if you know one programming language, you know them all, and even if you aren't as efficient with one language compared to another, those are "problems" that get streamlined early on.

Don't tie yourself down to an OS. Use whatever works for you. I don't have a "main" workstation. I have a Macbook Pro when I'm on the go and usually at home. I have Ubuntu and Windows on a desktop and Android on my phone. I am a developer. An engineer. I can code for all of these platforms and there's no reason to coerce yourself into one niche.

Zoom out and take note of the technologies and skills you've accumulated under your belt. These are all labels (i.e., a “wordpress developer” is or at least should be a PHP developer) Yes there are bad programmers and good programmers, but the difference isn’t in the code anymore. Working in IT means always being able to adapt to changes in trends. Make your work your sandbox. Don’t bullshit anyone, but don’t deny what you’re capable of either. Create.

See yourself as a problem solver and tackle challenges accordingly. Use your developer skillset to keep the wheels in motion. What makes programming worthwhile? Why reinvent the wheel when you can move the damn thing forward a millimeter or two?

Quake Live Tips

Quake Live is a free, manly game to play. QL is a version of Quake 3 that runs as a browser plugin for Firefox, Safari, and IE. It features a skill-matched game finder, a friend’s system, and other modern features. Think a Lite, browser-based version of Steam. Quake 3 came out in 1999, and people have been playing it on a regular basis since. That’s about 11 years ahead of you if you’re new (doesn’t mean you can’t become excellent fast.)

The following Quake Live tips apply to those games: Quake 3, Quake World, Death Match Classic, Warsow, etc.

Quake Live Tips – The Basics

The point of the game is to control the map, not to get the most frags. Kills happen because other players are trying to take over your territory.

Don’t chase your opponent. Chasing is predictable, and will almost always get you killed if you don’t know what you’re doing.

Pay attention to your opponent. What items are they picking up? Their usual routes (surprisingly predictable,) etc.

Pay attention to what your opponent does when their health is low. They will either become very aggressive and erratic, or change their route and generally keep their distance from you.

Learn to strafe jump. It’s not as easy as in Counter-Strike <1.1, but it’s a skill that you can carry into other shooters (listed above), and is a core part of the game. Quake Live makes this easy with a movement practice mode and video tutorials.

Use a low sensitivity. Mine is 1.5. It’s more accurate, and you quickly learn how much force to give the mouse to flick the crosshair if you need to. You don’t need to do 180s and 360s. Once you become good, you will know where opponents are likely to come from, and have the crosshair always in that general direction.

Use ASDW to move, and bind every weapon nearby. I use R for rocket, Q for rail, E for lightening, F for shotgun, etc.

Learn the maps. Duels are a great way to learn maps. You can also learn a map by deciding on a specific item route to follow, and then following it until you’ve memorized it. Then memorizing another route, and so on. For example, rocket to RA to rail to MG to shotgun to rocket to RA ….

Use the right gun for the job. QL/Q3 has the most balanced arsenal in a shooter. Every gun including the machine gun and gauntlet are useable and very powerful. In some situations a machine gun is better than a rocket, such as when the opponent is very far away.

Quake Live Tips – Beyond Basics

Learn the amount of seconds each item takes to spawn. Then learn to countdown internally exactly when that item will respawn. This isn’t as hard as it sounds. Begin by only focusing on big items such as Red Armor (RA), Mega Health (MG), etc. You have to control the map (items), and also be able to spot what your opponent has, and both require that you know when items were taken, and/or when they will respawn. You can make the timer count up or down via

Control important items. Focus on controlling at least RA, MG, rocket and rail.

Try to predict what your opponent has equipped. There’s a good chance your opponent will have equipped whatever items were in the immediate vicinity. If they’re walking out from near the lightening gun (LG), they probably have the LG out. This is especially true in pubs and when you know your opponent just spawned or did not pick up a better gun. If there’s a common route, like from rocket to RA, and you know the RA had spawned recently, your opponent likely has RA with rockets a’blazin’

Fire at spawn points. QL has a very low invincibility time when you respawn, and you can die again right away. Memorize the spawn points in each map, and shoot at them when you expect a respawn. If you frag someone, and you know there’s a spawn point behind you, turn around and begin shooting. If they respawn at that point, they’ll be welcomed back with a rocket or balls of plasma.

Watch demos (replays.) Get the Firefox demo player and hop over to ESReality.

You have to actually play the game. Playing is how you get good. I put this tip at the end because people who don’t read up to this point, who will close this page and go play, don’t need the tip. People who read through this entire page are more likely to also be the type of person looking for a shortcut to becoming pro at QL – there are no shortcuts. You have to play the game, and enjoy every loss. Experience comes from playing.

Quake Live Links

Quake Live – Official Site

List of command variables

Learning to Program on Your Own

Learning how to code is like learning anything else – You have to do it. The hardest part is figuring out where to begin, and then you need some mechanism to show you that you’re making progress. The latter is important because it motivates you to keep going.

First, have a goal. I initially wanted to make AOL “punters” (apps that kicked other users offline) and malware. I found them interesting. Do you want to program games? websites? Facebook Apps? Apps for OS X?

Once you have the goal, do research on how those apps are made, particularly on the language used, APIs/libraries used, and so on.

When starting, you will be learning a lot of concepts that you will see no use for. If-then statements, variables, etc. You might understand the basic idea of what a variable is, but might wonder – why would I ever use this instead of putting the value in directly? At this stage, it’s important that you remain persistant and just go through the examples/exercises in your book (or those provided by your tutor). I noticed that most people will struggle through the first set of concepts, and then lose interest and quit after seeing that they aren’t doing anything interesting. One day, you’ll be doing something and everything will fall into place. An A-Ha moment.

You’re learning a bunch of stuff that doesn’t really connect with each other. How does printing “Hello World” to the screen eventually become a 3D game? How do I go from a console app to a window app? How does knowing what a variable or constant is translate to a web development project?

It’s a plateau — and I want to stress that this applies to almost anything, not just programming. You begin by learning a lot of stuff, very slowly making progress, and over time you begin to see that you kinda “know” what’s happening behind the scenes of the apps you’re using. After that, learning because easier and quicker. Getting to that level requires persistance.

My Turning Point – Stop Asking “What Should I Code?”

When I first began coding, I had the mentality that I had to “learn how to program” before “making app X” – This is logical but the way I structured in my head was important in impeding my progress. I divided learning how to program and making app X into two separate goals. It was a problem because it migrated me away from the goal of “making app X.” I began asking the wrong question – what should I code to learn how to program?

Instead, I should have been asking – what should I learn next, to reach my goal of making app X? I broke down app X into individual tasks, and then began learning how to do each one. For example, let’s say my goal is to program a game.

If I ask “what should I code to learn how to program?” I will spend a lot of time learning things I might not need anytime soon (or ever), I will get nowhere near reaching my goal, and will become unmotivated and quit before getting there. Instead, I would break down the game into individual tasks (this requires research) and work on learning each one.

Let’s see, I need to figure out how to make a window/draw things on screen. That becomes my new short term goal. I dig deeper and learn that I need to learn the Windows API. I learn that the Windows API is how one draws to the screen. But the Windows API is another thing I need to learn, so that becomes the immediate short term goal. Digging deeper, I realize that the Windows API is just a bunch of functions with some conventions that I need to memorize.

Now my goal is somewhat clearer. I begin reading about the Windows API, making different small apps to make sure I understand what I’m reading. Eventually I am able to draw a window and controls. Great. I still don’t have a game. What’s next? I need to draw graphics. I dig into how it’s done and learn that the Windows API provides a set of functions graphics. I’m familiar with the Win API and so I just begin learning the graphics lib. I make a few dozen apps drawing basic circles, loading bitmap images, etc. Now my goal of making a game is starting to take shape in my head. I can mentally structure how the game will be, minus a few concepts I might not have learned yet.


JS, Angular, PHP, Ruby, Magento, Wordpress, vim, shell …. ~