The #nosyntax movement

Part I
======

_DESTRUENS_

what’s syntax highlighting after all?
————————————-

I’m a long time `vi` fan, but more than it I like `nano`, which is in turn
surpassed by the glorious `MS-DOS` `edit`. The reason is simple, they just
work: “no-fluff, just stuff”, as they say.

On the other hand what I’ve been told and taught[^1] over the years was that my
editor is my toolbox, it should be the extension of my arm, the center of my
life as a programmer.

Now’s the right place and time to say no to all this nonsense, in Melville’s
own words:

> I tell you, the sperm whale will stand no nonsense.[^2]

Let’s face it, we don’t challenge these common beliefs as we ought. We’ll
maybe discover that the impositions we suffer about syntax and tools are
something that can be overcome by progress.

[^1]: E.g. in “The Pragmatic Programmer” by A. Hunt and D. Thomas –
http://pragprog.com/book/tpp/the-pragmatic-programmer
[^2]: http://www.online-literature.com/melville/mobydick/46/

are colors that great deal?
—————————

I’ll skip at once the whole color blindness problem to concentrate on something
that I feel being much more important. Has been noted elsewhere that colors in
software are broken[^3]. Although I want to remark here that is not enough,
bluntly said colors are YAGNI[^4].

[^3]:
https://medium.com/@MrJamesFisher/your-syntax-highlighter-is-wrong-6f83add748c9
[^4]: to be clear, I’m not against colors in general, but I have very strong
feelings about how they’re used to discriminate parts of other’s code

should somebody else decide for you what’s important?
—————————————————–

Everybody seems concerned on telling you what to do, what’s right, what’s
wrong, and even who’s right and wrong in saying who can talk about right and
wrong.

All just to tell you that you are right anyway (the secret here is that you are
already abiding to their views, hence you are right). I know this is a bit of
a broad concept, but you know, you need to start small.

All in all I think we, the developers, should start to put our brains to good
use and refute the kool-aid of mainstream development practices.

Therefore I’ll end Part I issuing the following statement:

*** I don’t want anymore an unknown theme author to dictate the visual
hierarchy of my code ***

Part II
=======

_CONSTRUENS_

readable code
————-

TBH, I’m really tempted to leave this title as is, no explanation. Mary
Poppins would surely agree[^5].

The one thing that I found really heartening is that having no syntax colors
gives you freedom. The feeling is similar to having less stuff in your pockets.

Try it for 5 minutes straight and let your eyes start processing spaces,
sentences and shapes. Set them free from preordered “parsing”. Spot by
instinct places where the shapes alone act as code smells.

Don’t forget that similar techniques were adopted in the ‘70, for example the
SmallTalk community used to write their programs in variable-width fonts[^6].
Say that to one of your colleagues and check out their response[^7].

[^5]: https://www.youtube.com/watch?v=E6ADGIHIKnI
[^6]: http://typophile.com/node/13090#comment-75514
[^7]: another example on how the current generation is biased:
https://groups.google.com/forum/#!topic/mailing.postfix.users/6Kkel3J_nv4 (via
@steveklabnik)

short code
———-

Needless to say, migrating to this style will have a number of benefits on your
coding and on how you perceive code in general. You’ll be forced to write
smaller methods with cleaner syntax that will truly enable literate
programming[^8].

Don’t be fooled though. It won’t be easy, especially at first, your old habits
will try to survive, you’ll often find yourself longing for the old colors.
More on that in the next sections.

[^8]: https://en.wikipedia.org/wiki/Literate_programming

y-spacing
———

If you ever felt that vertical spacing deserves more attention than it
receives, be reassured, you’re not alone.

Start a #nosyntax life today, and rejoice by looking your code get in shape on
both the axes. “30-days money back guaranteed” because I already know you’re
gonna love it <3 <3 <3

b/w is always cool but…
———————–

As I said before I’m not against colors in general (I would be a stupid, or a
troll). It may seem trivial but I think it’s worth pointing it out: you’re not
confined to black and white, there are plenty of colors out there, new patterns
could emerge. Just think of how cool would be to have a different color for
each file type or role (e.g. light-blue views, grass-green models, warm-orange
controller, etc.)

get priorities right
——————–

You are in control. Really. Get used to it.

No editor color scheme will be able to hide bugs and comments from your sight.
No tool producer will have the chance to influence your thoughts anymore.

_tools for tools’ sake_

No, thanks.

better judging your language’s syntax
————————————-

This the final note of Part II. This the final alert.

The real measure of the goodness of your programming language will surface. A
good language will shine in its full clarity and expressiveness. The bad ones
will be unbearable. The really bad ones will hurt your eyes at once.

Conclusion
==========

don’t haste
———–

I know that all this seems weird and even difficult, habits are a powerful
weapon. Having been through it myself I’ll give just this piece of advice:
take your time.

For example you can switch to monochrome scale for a while. Plan ahead the
switch to full #nosyntax style and you’ll do great!

get your own pace, but don’t stop
———————————

There’s no manifest, even if everyone now has a manifesto[^9]. As said you’ll
need to find your own pace, but please don’t stop. This is a movement, it is
not meant to be stopped.

[^9]: http://www.reactivemanifesto.org

_Trolly_ Yours,
Elia

Enter ju-jist, the gist runner

Neo: Ju jitsu? I’m gonna learn Ju jitsu?

Forewords

In the last article we explored the internals of D3.js, the data visualization library.
In doing that we ended up with a number of files in a gist.

This morning I thought it’d be nice to put up the thing into one of those JavaScript fiddle sites, I looked up a bunch of them: CodePen, JSFiddle, JS Bin but none of them allowed for arbitrary extensions or loading a code from a Gist1.

I had to build my own.

The Plan

  1. load and run gists by visiting URLs in this form: http://ju-jist.herokuapp.com/USER/GIST_ID/FILE_NAME
  2. eventually add a home page that will build the right url from the GIST_ID defaulting to index.html as file name

Section 1: Rack Proxy

The first thing I did is to preparing a simple proxy rack application that would extract the gist id and
file name from the URL:

parts = %r{^/(?<user>[^/]+)/?(?<gist_id>w+)/(?<file>.*)(?:$|?(?<query>.*$))}.match(env['PATH_INFO'])
gist_id = parts[:gist_id]
file = parts[:file]
user = parts[:user]

Note here how handy are actually named Regexp groups (introduced in Ruby 1.9).

Then let’s be ol’ school and use open-uri to fetch urls:

contents = open("https://gist.githubusercontent.com/#{user}/#{gist_id}/raw/#{file}")

Pass it over to Rack:

[200, {}, [contents.read]]

And wrap everything in a rack app:

# config.ru
def call(env)
  parts = %r{^/(?<user>[^/]+)/?(?<gist_id>w+)/(?<file>.*)(?:$|?(?<query>.*$))}.match(env['PATH_INFO'])
  gist_id = parts[:gist_id]
  file = parts[:file]
  user = parts[:user]
  contents = open("https://gist.githubusercontent.com/#{user}/#{gist_id}/raw/#{file}")
  [200, {}, [contents.read]]
end

run self

Section 2: The URL builder

Next I prepared a simple form:

<!-- inside index.html -->
<form>
  <input type="text" id="user_and_gist_id">
  <input type="submit" value="open">
</form>

And then I used Opal and Native with some vanilla DOM to build the URL and
redirect the user.

# gist-runner.rb
$doc  = $$[:document]
input = $doc.querySelector('input#user_and_gist_id')
form  = $doc.querySelector('form')

form[:onsubmit] = -> submit {
  Native(submit).preventDefault
  user_and_gist_id = input[:value]
  $$[:location][:href] = "/#{user_and_gist_id}/index.html"
}

And let Rack serve static files:

use Rack::Static, urls: %w[/gist-runner.rb /favicon.ico], index: 'index.html'
run self

Conclusion

Ju-Jist is up and running, you can see the code from the last article gist live on ju-jist.

The code is available on GitHub.


  1. Actually JSFiddle has some docs for loading Gists, but I wasn’t able to make it work. CodePen and others allow for external resources, but GitHub blocks the sourcing of raw contents from Gists

Learning D3.js basics with Ruby (and Opal)

I always wanted to learn D3.js, problem is JavaScript is too awesome and that kept turning me off… till now!

Let’s take a random tutorial that we will attempt to translate into Ruby, for example this: http://bl.ocks.org/mbostock/3883245.

A couple of thing we need to bear in mind are these: D3 is not object-oriented and it’s a pretty complex library. We’re expecting some problems.

To have something to compare it to we may note, for example, that JQuery is basically a class ($) that exposes methods that returns other instances of the same class. That makes things easy enough when we try to use it from an OO language like Ruby.

Part I — The Setup

Following the tutorial, let’s setup the HTML page:

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<style>
/* …uninteresting CSS from the tutorial here… */
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>

<!-- OUR ADDITIONS HERE -->
<script src="http://cdn.opalrb.org/opal/current/opal.js"></script>
<script src="http://cdn.opalrb.org/opal/current/native.js"></script>
<script src="http://cdn.opalrb.org/opal/current/opal-parser.js"></script>

<script type="text/ruby" src="./app.rb"></script>

</body>
</html>

As you probably have noted we added a couple of libraries from the Opal CDN.

First we added opal.js, that is the runtime and core library that are necessary to run code compiled with Opal.

Then there’s native.js that we’ll use to interact with native objects (more details in this other post).

And last we have opal-parser.js and app.rb (that is declared as type="text/ruby"). The parser will look for all script tags marked as text/ruby and will load, parse and run them.

In additon we’re also providing a data.tsv file as described in the tutorial.

Part II — Code Ungarbling

About the process of translating

The approach I used to translate this code is quite simple, I copy/pasted all the JavaScript from the tutorial into app.rb and commented it out. Then I translated one line (or sentence) at a time tackling errors as they came.

Using Native

The first thing we need to do is to wrap the d3 global object with Native, so that is ready for Ruby consumption.

d3 = Native(`window.d3`)

Now let’s look at the first chunk of code

original code:

var parseDate = d3.time.format("%d-%b-%y").parse;

var x = d3.time.scale()
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

converted code

d3 = Native(window.d3)
time  = d3[:time]
scale = d3[:scale]
svg   = d3[:svg]

date_parser = time.format("%d-%b-%y")

x = time.scale.range([0, width])
y = scale.linear.range([height, 0])

x_axis = svg.axis.scale(x).orient(:bottom)
y_axis = svg.axis.scale(y).orient(:left)

By trying to run this code we discover early on that somehow Native is failing to deliver calls via method missing.

The reason is that bridged classes are a kind of their own and turns out that D3 tends to return augmented anonymous functions and arrays. Now both Array and Proc are bridged classes. That means that they are the same as their JS counterparts: Array and Function.

Native will have no effect on bridged classes (no wrapping) and therefore all calls to properties added by D3 will end in calls on undefined.

To solve this we’ll manually expose the methods on those classes, the final code looks like this:

module Native::Exposer
  def expose(*methods)
    methods.each do |name|
      define_method name do |*args,&block|
        args << block if block_given?
        `return #{self}[#{name}].apply(#{self},#{args.to_n})`
      end
    end
  end
end

Proc.extend Native::Exposer
Array.extend Native::Exposer

Proc.expose :range, :axis, :scale, :orient, :line, :x, :y, :parse, :domain
Array.expose :append, :attr, :call, :style, :text, :datum

The complete code can be found in this gist.

UPDATE: see the code in action on Ju-Jist, and read about building ju-jist in this article

A better solution

Let’s hope that in the future the Opal team (me included) will add method missing stubs1 to all bridged classes (instead of just adding them BasicObject).

Conclusion

We probably didn’t learn very much about how to use D3.js, but we discovered a bit of its internals, exposing an interesting style of JavaScript.


  1. (which is the underlying mechanism that powers method_missing support in Opal) 

Mocking Rails, for SPEED

DISCLAIMER: This article is by no means related to the recent quarrel about TDD’s death (be it presumed or actual), nor to this article or these hangouts.

:trollface:

Now that we’re clear let us get to the real title:

How I test Rails stuff without loading Rails and learned to use mkdir

Chapter 1: mkdir1

this chapter is quite brief and straightforward…

Starting from Rails 3 every folder you create under app will be used for autoloading, this means that you can group files by concern2 instead of grouping them by MVC role, or you maybe want to add new “roles”.

For example the app I’m currently working on contains looks like this:

app/
├── admin
├── assets
├── authentication
├── authorization
├── controllers
├── forms
├── helpers
├── journaling
├── mailers
├── models
├── proposals
├── utils
└── views

The journaling folder contains journal.rb (a simple Ruby class) and journal_entry (an ActiveRecord model).

Chapter 2: Rails not required

Talking about that Journal, it doesn’t really need Rails to be used, it’s ok with any JournalEntry-ish object that exposes this API:

class FauxJournalEntryClass < Struct.new(:difference, :user, :model_type, :model_id, :action)
  def save!
    @persisted = true
  end

  def persisted?
    @persisted
  end
end

So it can be used and tested without loading rails, that gives opportunity to have the corresponding spec to give us really fast feedback. Enter a lighter version of our spec_helper:

# spec/spec_helper.rb
RSpec.configure do |config|
  # yada, yada, rspec default config from `rspec --init`
end

along with a speedy spec:

require 'light_spec_helper'
require File.expand_path('../../app/journal/journal', __FILE__)

describe Journal do
  # examples here...
end

and have the normal spec_helper to load the light one:

# spec/spec_helper.rb
require 'light_spec_helper'
# stuff coming from `rails generate rspec:install`...

Chapter 3: Mocking Rails

…without making fun of it

With time i often found myself in the need to add a logger, to check current environment or to know the app’s root from this kind of plain classes.

In a Rails app the obvious choices are Rails.logger, Rails.env and Rails.root. In addition I really can’t stand that File.expand_path and light_spec_helper, they’re just ugly.

My solution was to:

  • have a faux Rails constant that quacks like Rails in all those handy methods
  • add the most probable load paths into the light spec_helper
  • rename the the rails-ready spec_helper to rails_helper and keep the light helper as the default one

Here’s how it looks:

# spec/spec_helper.rb
require 'bundler/setup'
require 'pathname'

unless defined? Rails
  module Rails
    def self.root
      Pathname.new(File.expand_path("#{__dir__}/.."))
    end

    def self.env
      'test'
    end

    def self.logger
      @logger ||= begin
        require 'logger'
        Logger.new(root.join("log/#{env}.log"))
      end
    end

    def self.cache
      nil
    end

    def self.fake?
      true
    end

    def self.implode!
      class << self
        %i[fake? cache logger env root implode!].each do |m|
          remove_method m
        end
      end
    end
  end
end

$:.unshift *Dir[File.expand_path("#{Rails.root}/{app/*,lib}")]

RSpec.configure do |config|
  # yada, yada, rspec default config from `rspec --init`
end

Notice anything of interest?
I bet you already guessed what Rails.implode! does…

Here’s the shiny new rails_helper:

ENV["RAILS_ENV"] ||= 'test'
require 'spec_helper'
Rails.implode! if Rails.respond_to? :implode!

require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join('spec/support/**/*.rb')].each do |f|
  f = Pathname(f).relative_path_from(Rails.root.join('spec'))
  require f
end

ActiveRecord::Migration.maintain_test_schema! # rails 4.1 only

RSpec.configure do |config|
  # stuff coming from `rails generate rspec:install`...
end

Conclusion

The introduction of Spring in Rails 4 has actually made all this stuff useless, running RSpec through it makes it blazingly fast.

Sorry if I wasted your time and I didn’t even make you smile.


  1. I don’t actually use mkdir, I know how to use my editor 
  2. Not those concerns 

Preview emails for any user with Rails 4.1

Last night I was preparing a weekly email to remind my dear TimeSampler users about the work they have done in their previous week.

I started by adding a couple of previews one for the user that has actual stuff done (see an example below):

Weekly email for user with registered bursts

Setup a mailer (you can skip this)

The first thing you need to preview an email is to have a Mailer (yuk!), here’s a simple one:

# app/mailers/user_notifier

class UserNotifier < ActionMailer::Base
  default from: 'weekly-report@timesampler.com', reply_to: 'elia+timesampler-weekly-report@schito.me'
  helper DayHelper

  def weekly_report user
    @user         = user
    @project_days = project_days
    @days         = project_days.group_by(&:day).to_a.sort
    @end_time     = end_time
    @start_time   = start_time

    mail to: user.email, subject: "TimeSampler: Weekly activity report · week #{start_time.cweek}"
  end
end

And its view:

/ app/views/user_notifier
= render 'style'

%h1 TimeSampler: Weekly activity report · week #{@start_time.cweek}

%p
  Hi #{@user.some_name}!

- if @project_days.any?
  %p
    Here's what you've done during the past week (#{link_to "from #{@start_time} to #{@end_time}", journal_path}):
  .days
    - @days.sort.reverse.each do |(day, project_days)|
      = render 'day', day: day, project_days: project_days
- else
  = render 'blank_slate'

= render 'footer'

Setup a previewer

Then we need to add our previewer. Problem is that the default location for the previewers is test/mailers/previews
and as you may have guessed already we have no test dir in this app, instead we’ll put our
ActionMailer::Preview classes inside app/mailer_previews.

To do that let’s add the following line to config/environments/development:

Rails.application.configure do
  # …
  config.action_mailer.preview_path = "#{Rails.root}/app/mailer_previews"
end

Your previewer could be something like this:

class UserNotifierPreview < ActionMailer::Preview
  def weekly_report_empty
    UserNotifier.weekly_report(andrea)
  end

  def weekly_report_full
    UserNotifier.weekly_report(elia)
  end

  # …s
end

And have beautyful previews for your emails. For example, this is how the blankslate TimeSampler mail looks like:

blank slate mail preview

POWER PREVIEWING !!1!

Now what if you want to preview emails for arbitrary users without having to manually update the code?

No problem, luckly it’s Ruby! After a bit of inspection inside actionmailer and railties I found the right hook…

WARNING: rails hackery ahead

Rails asks the previewer if an email_exists? before trying to display it, so we’ll hook into that method and
auto-define a previewer instance method for each user in out system (please don’t try this with more than a hundred users).

Here teh codez:

class UserNotifierPreview < ActionMailer::Preview
  def self.email_exists?(*)
    User.all.each do |user|
      next if user.email.blank?
      email = user.email.gsub(/W/, '_')
      method_name = "weekly_report_#{email}"
      user_id = user.id

      define_method method_name do
        UserNotifier.weekly_report(User.find(user_id))
      end
    end

    super
  end

  # …
end

Of course it’s advisable to be careful and probably reduce the set of users you’re gonna prepare a preview method for.
In my case the development database is quite manageable and hence User.all is fine.

Final Pro-tip

You find cumbersome to dig the sources of the gems in your bundle even
if you setup the $EDITOR var in your bash and are a regular client of bundle open <my-gem>?

Then you can give a try to the Bundler bundle for TextMate2 which will give you an
incredible speed boost while perusing the gems in your current Gemfile.lock.

To get some more info on my TextMate2 setup you can read:

Read next: Pimp my TextMate2 — Ruby edition

opening gems from the current bundle

Using native JavaScript objects from Opal

Question: can I call JS functions from Opal?
Answer: totally!

Opal standard lib (stdlib) includes a native module, let’s see how it works and wrap window:

require 'native'

window = Native(`window`) # equivalent to Native::Object.new(`window`)

Now what if we want to access one of its properties?

window[:location][:href]                         # => "http://dev.mikamai.com/"
window[:location][:href] = "http://mikamai.com/" # will bring you to mikamai.com

And what about methods?

window.alert('hey there!')

So let’s do something more interesting:

class << window
  # A cross-browser window close method (works in IE!)
  def close!
    %x{
      return (#@native.open('', '_self', '') && #@native.close()) ||
             (#@native.opener = null && #@native.close()) ||
             (#@native.opener = '' && #@native.close());
    }
  end

  # let's assign href directly
  def href= url
    self[:location][:href] = url
  end
end

That’s all for now, bye!

window.close!

Pimp my TextMate2 — Ruby edition

Here at Mikamai It’s no secret I’m a happy TextMate user and early TM2 adopter. I’m always there if either an editor war is catching fire or if someone needs help setting up his editor.

Above all I still find that TextMate is the best choice for a Ruby developer, even if SublimeText, emacs and vim seem more fashionable these days. Even if I’m saving the full list of reasons for another post I’ll tell just this one: TextMate relies on Ruby for a big part of its implementation that has always been opensource*.

Of course I’m talking about bundles, if you’re not convinced look at the code used to align assignments (⌥⌘]) from the source bundle (which is responsible for actions common to any programming language).

Just to be clear I would still use SublimeText if I were to program from Linux or (ugh!) Windows.

That said I want to gather here some of the stuff that makes using TextMate2 for Ruby and Rails development so awesome.

* Of course I know about redcar (which seems quite dead, but I didn’t tried it recently) and other TM clones err enhancements like Chocolat

ALERT: shameless self promotion follows

The Bundles and Settings parade

1. Effortless opening of Bundled Gems ⌥⌘O

This I do all the time, opening the source of bundled gems. Please behold and don’t be horrified. Especially in Ruby-land the source of gems is the best source of documentation, and as explained by Glenn Vanderburg) there’s probably a good reason for that. Also the README and specs are included most of the time and reading other’s code is a healthy activity.

Needless to say that the best place to read source code is your editor.

⌥⌘O will present the complete list of gems from your Gemfile.lock, start typing the first letters of a gem and use arrow if you don’t want to touch the mouse (or trackpad).

opening gems from the current bundle

Source: https://github.com/elia/bundler.tmbundle

2. Beautiful Markdown rendering

No README.md reading activity would be on par with a the GFM rendered version without code blocks highlighting.

This bundle almost looks like GFM while typing, press ⌃⌥⌘P (the standard TM key equivalent for preview) to get it rendered to the HTML window.

Redcarpet Markdown Bundle in action

Bonus Install the Scott Web Theme from Preferences → Bundles for a nice looking preview

Source: https://github.com/streeter/markdown-redcarpet.tmbundle

3. Restart Pow! in a single stroke ⌃⌥⌘R

Restarts the current app detecting a tmp/ directory in current project or in a parent dir.

Falls back to /tmp

Source: https://github.com/elia/pow-server.tmbundle

4. Open the terminal in your current project folder

Works with both Terminal and iTerm, just press ⌃⌥⌘T from a project.

Source: https://github.com/elia/avian-missing.tmbundle

5. Trailing whitespace fix, cross-tab completion and more…

Command Description
⌃⎋ Cross tab completion
⌃⌥⌘T Open Project directory in Terminal
⌃⌥⌘L Keep current file as reference

Source: https://github.com/elia/avian-missing.tmbundle

Installing the whole thing

Download the latest version of TextMate2 here: https://api.textmate.org/downloads/release

mkdir -p ~/Library/Application Support/Avian/Bundles
cd ~/Library/Application Support/Avian/Bundles

git clone https://github.com/elia/avian-missing.tmbundle
git clone https://github.com/elia/bundler.tmbundle
git clone https://github.com/streeter/markdown-redcarpet.tmbundle

# Activate the system ruby (if you're using a Ruby version manager):
type rvm &> /dev/null && rvm use system # for RVM
export RBENV_VERSION="system"           # for rbenv

# Install the required gems
sudo gem install redcarpet -v 2.3.0
sudo gem install pygments.rb

# Trailing whitespace
defaults write com.macromates.TextMate.preview environmentVariables -array-add 
    '{ "enabled" = YES; "name" = "TM_STRIP_WHITESPACE_ON_SAVE"; "value" = "true"; }' # enable trailing whitespace removal and EOF fix

echo <<-INI >> ~/.tm_properties
[ "*.y{,a}ml" ]
# Disable trailing whitespace fix for YAML 
# files that can be broken by this feat.
TM_STRIP_WHITESPACE_ON_SAVE = false
INI

The following will set the tabs/file-browser/html-windows to my current taste, I don’t pretend it matches everyone prefs but can still be useful for cherry-picking.

# File browser fixes and general UI fixes
defaults write com.macromates.TextMate.preview fileBrowserStyle SourceList       # lighblue file browser background
defaults write com.macromates.TextMate.preview fileBrowserPlacement left         # keep it on the left
defaults write com.macromates.TextMate.preview tabsAboveDocument -bool YES       # no tabs above the file browser
defaults write com.macromates.TextMate.preview allowExpandingLinks -bool YES     # make symlinks expandable
defaults write com.macromates.TextMate.preview htmlOutputPlacement right         # place the html output to the right
defaults write com.macromates.TextMate.preview disableTabBarCollapsing -bool YES # keep the tab-bar alway visible
defaults write com.macromates.TextMate.preview scrollPastEnd -bool YES           # give me some air after the file ends