Create shortcut for your project Mingle with Alfred

A few days ago, I post a blog(Create shortcut for your project Mingle with Chrome OmniBox) about that we can access specific Mingle story card directly from Chrome “OmniBox”. The shortcut is created by registering Mingle search as custom search in Chrome.

Today I found applying the same trick to launch apps, we can have one step further. In Mac OS, almost all the launcher apps support custom search, such as Aflred, QuickSilver, Launcher. Even in Windows, we also have Launchy. For Linux, I believe there should be similar stuff. So the trick is environment independent.

To add custom search query in different launch app is quite different, but should be straightforward.
I’ll take Alfred as example:

  1. Open Alfred Preference

    Alfred Preferences
  2. Register Mingle as custom search

    Alfred Preferences

The url for custom search can be get with the same approach described in previous post. Alfred uses {query} as placeholder, so you should replace the %s with {query} when coping the url from chrome to Alfred.

Using RVMed Ruby in Mac Automator Workflow

HINT This content is obsoleted on OSX 10.9 Mavericks

Embed Ruby into Automator Workflow

Automator workflow has the ability to execute ruby code, but it is not that obvious if you doesn’t know it.

To embed ruby code into workflow, you need to create a “Run Shell Script” action first, then choose “/usr/bin/ruby” as the shell. Then the script in the text box will be parsed and executed as ruby code.

Ruby In Automator

So, from now on, you know how to embed ruby into automator workflow.

Use RVM ruby instead of System Ruby

By default, Automator will load system ruby at /usr/bin/ruby, which is ruby v1.8.7 without bundler support. For most ruby developers, they must have installed some kind of ruby version manager, such as RVM or rbenv. As to me, I uses RVM. So I wish I could use RVMed versions of Ruby rather than the system ruby, could be ruby 1.9.3 or even ruby 2.0 with bundler support.

To use the RVMed ruby, I tried several approaches by hacking different configurations or files. And at last, I made it doing this:

RVM provides a ruby executable file at ~/.rvm/bin/ruby. On the other hand, /usr/bin/ruby is actually a symbol link that pointed to ‘/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby’.

So what we need to do is to replace the the symbol link with a new one pointed to ~/.rvm/bin/ruby.

Replace system ruby with RVMed ruby
1
2
3
4
sudo mv /usr/bin/ruby /usr/bin/system_ruby
sudo ln -s /Users/timnew/.rvm/bin/ruby /usr/bin/ruby

(You might need to replace the /Users/timnew/.rvm/bin/ruby with the path to your ruby executable file)

After doing this, done, you have the RVMed ruby in your Automator Workflow.

You can try to excute the following code in Workflow to verify it:

Test Ruby Version
1
puts RUBY_VERSION

If you do it correct, then you should see ‘1.9.3’ or any other version of ruby you have configured.

Adjust files encoding in Finder context menu "GB1312 to UTF-8 with 1-click"

One of the most annoying thing of Mac is that encoding, espeically you’re living in a non-Mac world.

Mac uses UTF-8 as the default encoding for text files. But Windows uses local encoding, so it changes according to your OS language. For Chinese users, Windows uses GB2312 as the default encoding.

So usually the movie subtitle files, the song lyrics files, the plain text novel files, the code contains Chinese, which you downloaded form web sites or recieved from others usually cannot be read because of the wrong encoding.

So I really wish to have an item in my finder’s context menu that I can adjust the encoding of selected files with 1-click.

Luckily, with the help of Ruby, Automator workflow and Mac OSX service, it isn’t that hard.

So basically, OSX loads all the workflow files saved in ~/Library/Services/, which is displayed as Context Menu in finder.

To build the service, work through the following steps:

1. To create a new service, just pick Service in Automator’s ‘create new document’ dialog.

2. Set service input as “files and folders from any application”.

3. Run Ruby Script to transcode the files

Add a “Run Shell Script” action to execute the following ruby code, which is used to transcode the files passed to service. (For more detail about how to embed Ruby in workflow, check out Using RVMed Ruby in Mac Automator Workflow )

Make sure the input is passed as arugments to the ruby script.

Transcode the files
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
old_files = []
ARGV.each do |name|
next until File.file? name
backup_name = name + '.old'
File.rename name, backup_name
source = File.open backup_name, 'r:GB2312:UTF-8'
dest = File.open name, 'w'
while line = source.gets
dest.puts line
end
puts name
old_files << backup_name
end
ENV['Transcode_Backup_Files'] = old_files.join('|')

4. Display a growl message when processing is done

5. Prompt user whether to keep the backup files

I use a Ask for confirmation action to ask whether user want to keep the backup files.
The workflow will abort if user clicks “No”, make sure you updated the text on the buttons, and texts are put on right button.

6. Add script to remove backup files

Add another “Run Shell Script” aciton to execute another piece of ruby code.

Remove backup files
1
2
3
4
5
6
7
8
9
if ENV['Transcode_Backup_Files']
ENV['Transcode_Backup_Files'].split('|').each do |file|
File.delete file
end
ENV.delete 'Transcode_Backup_Files'
end

7. Display notification to tell user that backup files has been deleted

TIP: The transcode ruby script requires Ruby 1.9+, but Mac OS X default provides Ruby 1.8.3, which doesn’t support encoding. To interprets workflow embedded code with ruby 1.9+, please refers to Using RVMed Ruby in Mac Automator Workflow

Install specific version of tool with HomeBrew

HomeBrew is a convenient package manager for Mac user. For some reason I prefer Home Brew to Mac Ports.
Brew has a younger package repository since it has shorter history comparing to MacPorts. Younger repository means less options. And sometime it is hard for you to install the old-fashioned tool with brew.

Brew uses git to manage its formula repository, so you can list with git.
Typically, the repo is located at /usr/local. But since this path can be changed, so it is safer to reference this path via brew.
Brew call the repo path as prefix, so you can reference the path with brew --prefix
You can use the following shell command to enter the brew repo.

1
cd $(brew --prefix)

Since brew load formula from local, so before we install the app with brew, we need to ensure the repo is updated. We can use the following command to update the brew repo:

1
2
3
4
5
# Update brew
brew update
# update with git
cd $(brew --prefix) && git pull --rebase

To install specific version of the app, we need to checkout the specific version of the formula, we can get the versions and related git revision by brew versions command, and checkout specific version, then install the app:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
brew versions postgresql
# Output:
# 9.1.3 git checkout e088818 /usr/local/Library/Formula/postgresql.rb
# 9.1.2 git checkout dfcc838 /usr/local/Library/Formula/postgresql.rb
# 9.1.1 git checkout 4ef8fb0 /usr/local/Library/Formula/postgresql.rb
# 9.0.4 git checkout 2accac4 /usr/local/Library/Formula/postgresql.rb
# 9.0.3 git checkout b782d9d /usr/local/Library/Formula/postgresql.rb
# 9.0.2 git checkout 2c3b88a /usr/local/Library/Formula/postgresql.rb
# 9.0.1 git checkout b7fab6c /usr/local/Library/Formula/postgresql.rb
# 9.0.0 git checkout 1168d8f /usr/local/Library/Formula/postgresql.rb
# 8.4.4 git checkout c32bea0 /usr/local/Library/Formula/postgresql.rb
# 8.4.3 git checkout 9b2ef7c /usr/local/Library/Formula/postgresql.rb
# 8.4.1 git checkout 0495cf5 /usr/local/Library/Formula/postgresql.rb
# 8.4.0 git checkout a82e823 /usr/local/Library/Formula/postgresql.rb
git checkout a82e823 /usr/local/Library/Formula/postgresql.rb
brew install postgresql

If we cannot find the specific version that we want (Such as Postgres 8.3.11). don’t be disappointed, we can try to search the version repository.
Some of the old-fashioned tool which is not included in brew’s master repo might be provided in version repository.

Begin from Brew 0.9 provide the multiple repository support, user can use brew tap command to register alternative repositories besides the master repo. There are quite a some interesting alternative repos, such as versions and games.
These official alternative repos can be found on github

The formulas in alternative repositories cannot be used directly, but luckily the official ones are included in the search result.

1
2
3
4
5
brew search postgresql
# Output:
# postgresql
# homebrew/versions/postgresql8 homebrew/versions/postgresql9

In the search result, we can see there are 2 formulas are displayed with a path rather than just the formula name, which means these formulas are in a alternative repo.
The path to the formula follows the convention: <github username>/<repository name without "homebrew-">/<formula name>.
So homebrew/versions/postgresql8 means the file is located at https://raw.github.com/Homebrew/homebrew-versions/master/postgresql8.rb

To install it, we can install it directly or tap the repo first:

1
2
3
4
5
6
7
8
# Install directly
brew install homebrew/versions/postgresql8
# Tap
brew tap homebrew/versions
brew install postgres8

How to launch Mac OS Terminal as Interactive Shell rather than Log-in Shell

As described in previous post, Mac OS launch its terminal as Log-In shell rather than Interactive Shell, which is different to default behavior of Unix and Linux. As a result, Terminal will load “bash_profile” as its profile rather than the normal “bashrc”.

This unique behavior might cause some problem when you try to port CLI tool from Unix or Linux.
Because basically, the ported app infers that the bash_profile should be loaded only once, and only when user just logged in. But in Mac OS, this inference is wrong, which can cause some weird problem.

This default behavior sometimes is annoying, and in fact, this Mac OS Terminal’s “unique” behavior can be configured. And even more, you can use other shell program, such as ksh, rather than the default bash.

Mac user can customize this behavior in Terminal’s Preferences dialog of Terminal app.
Terminal Preferences Dialog

If you choose the command to launch bash, the launched shell will become a interactive shell, which will load .bashrc file rather than .bash_profile file.

Bash Profile on Mac OS X

In Linux and Unix world, there are 2 common used shell profiles: ~/.bashrc and ~/.bash_profile. These two profiles are usually used to initialize user bash environment, but there still are some slightly differences between them two.
According to bash manual, .bashrc is “interactive-shell startup file”, and .bash_profile is “login-shell startup file”.

What’s the difference between interactive-shell and login-shell

Basically, the login-shell means the shell opened when user log in via console. It could be the shell opened on local computer after you entered correct user name and password, or the shell opened when you ssh to a remote host.
So according to the bash_profile will be loaded only once, that’s right after you logged into a computer, either locally or remotely.

And, on the other hand, the interactive-shell could be more widely used, be seen more often. It is the shell opened after you logged in, such as the shell opened from KDE or Gnome.

Mac Terminal’s Pitfall

According to the manual, the Terminal App on Mac is the typical “interactive-shell”, so theoretically Terminal should load “.bashrc” to initialize the shell environment. But the fact is Terminal doesn’t load the “.bashrc”, instead it load “.bash_profile” for initialization.
So in a word, Mac’s Terminal doesn’t follow the routine strictly. We need to be aware it.

And not all the shell are interactive! If the shell is not interactive, the Terminal App won’t load the profile file to initialize the environment.
A typical non-interactive shell in the shell that TextMate used to run command script, which means in TextMate’s shell, these environment variables, path and even alias you used in you daily life might not be available for TextMate’s command.
And also the most hurt one, the rvm function also won’t be available in TextMate’s command shell, which means if you call rake or rails in TextMate’s command script, you are very possibly got error because it cannot find proper gem or other resources.
So you should always remember to source and run the “.bash_profile” file or setup these values once again.