awhitebox


Uploading Files to CloudApp from Alfred

Update: If you like, you can save yourself most of the configuration trouble and download the shortcut’s folder directly. I’ve put that up on github. The CloudApp icon is redistributed with permission.

This one takes advantage of the new feature in Alfred 0.9, Result Actions (Requires Powerpack). Actions can be performed on files that are selected using File Navigation or File Search. Basically they are like any other terminal shortcuts but with the ‘action’ checkbox checked, which tells Alfred to pass in the full file path as {query} when used in that context.

I used Aaron Russell’s cloudapp api wrapper gem, which made it really easy to create this script which basically adds an action to upload files selected in Alfred to CloudApp. I also use rb-appscript for the Growl notification AppleScript. You will need to install both of these gems to be able to use this script:

$ sudo gem install cloudapp_api rb-appscript

You may or may not need to use sudo depending on your setup.

Either paste the script shown below in a file somewhere or download it from this link.

Make sure you edit the script to set your CloudApp email address and password.

As usual, create a new shortcut in the ‘Terminal/Shell’ section in Alfred Preferences.

Alfred Preferences Screenshot

You can use whatever you want for the Title and Description. In this particular case, I didn’t really care about the Keyword as I don’t intend to use this shortcut directly.

In Command, point to the script you created/downloaded while passing the {query} in which Alfred will pass the file path:

~/bin/cloudapp_upload "{query}"

In addition, you can pass in one or two option to further customise the script’s behaviour:

Make sure you check both ‘Quotes’ and ‘Spaces’. After saving, tick both ‘Silent’ and ‘Action’.

That should be it. Now, if you navigate to a file (Fire up Alfred and start typing / or ~), or if you locate a file using find, hit CTRL to select the file and display the actions list, and you should see your brand new action at the bottom. Select it, patiently wait for the script to upload the file, and done! The URL of the file will also be copied to the clipboard straight away.

Alfred Preferences Screenshot

Here’s the script:

#!/usr/local/bin/ruby

require 'cloudapp_api'
require 'appscript'

# Set your CloudApp credentials:
EMAIL = 'your_email@example.com'
PASSWORD = 'yourpassword'

file = ARGV[0]
privacy = ARGV[1] == '-p' || ARGV[2] == '-p'
mute = ARGV[1] == '-m' || ARGV[2] == '-m'

exit if file.nil?

# Authenticate to CloudApp
client = CloudApp::Client.new
client.authenticate EMAIL, PASSWORD

# Upload file
drop = client.upload file, :private => privacy

# Create a Growl notification
include Appscript
growl = app("GrowlHelperApp")
notifications = ["CloudAppUpload"]
growl.register(
  :as_application => "CloudAppUpload",
  :all_notifications => notifications,
  :default_notifications => notifications
)
growl.notify(
  :with_name => "CloudAppUpload",
  :title => "CloudApp Upload Succeeded",
  :description => "The file '#{drop.name}' has been sucessfully uploaded to Cloudapp: #{drop.url}",
  :application_name => "CloudAppUpload",
  :icon_of_application => "Alfred"
)
# Play sound
exec 'afplay /System/Library/Sounds/Glass.aiff' unless mute

# Copy file URL to clipboard
IO.popen('pbcopy', 'r+') do |clipboard|
  clipboard.puts "#{drop.url}"
end

You can respond to this article by replying on twitter or sending me an email.


Partial Templates in Lithium

Update: I’ve put the helper explained below in a lithium plugin so that it can be easily reused instead of copying the helper across all of your webapps. Installation is super easy and is explained in the plugin’s README.

When building web applications with a MVC framework, we are bound to end up with views that share common form field. For example, both ‘New Post’ and ‘Edit Post’ will both have ‘Post title’, ‘Post content’ and so forth.

Most frameworks already have solutions for that. I know that Rails uses partial templates – most commonly known as partials. Put simply, partials are templates that can be rendered and re-rendered by views.

Lithium already has something very similar, dubbed “Elements”. So it’s already exceptionally trivial to render a template from within a lithium view.

Consider the following example view, views/posts/add.html.php:

<?=$this->form->create($post)?>
  <?=$this->form->field('title', array('type' => 'text'))?>
  <?=$this->form->field('content', array('type' => 'textarea'))?>
  <?=$this->form->submit('Add Post')?>
<?=$this->form->end()?>

We would probably have at least one other view, views/posts/edit.html.php with the content of which would look very similar to the above.

Say, as an example, both views share a common chunk, that is the two lines where field is called. We can then, move those two lines to a separate file views/elements/fields.html.php, and render it directly from within the views:

<?=$this->form->create($post)?>
  <?=$this->view()->render(array('element' => 'fields'))?>
  <?=$this->form->submit('Add Post')?>
<?=$this->form->end()?>

Works like a charm, but slightly ugly for my taste! And it seemed to me that there was a cleaner way to render these templates, and that is to use a helper.

Creating a helper in Lithium is quite easy. We simply extend the \lithium\template\Helper class:

<?php

// Partial.php

namespace app\extensions\helper;

class Partial extends \lithium\template\Helper {
  public function __call($method, $args) {
    $params = empty($args)? array() : $args[0];
    return $this->_context->view()->render(array('element'=> "{$method}_partial"), $params);
  }
}
?>

Placing the class file above in our app’s extensions\helper should do the trick. Now, we simply call the partial helper from the view to render the partial:

<?=$this->form->create($post)?>
  <?=$this->partial->fields()?>
  <?=$this->form->submit('Add Post')?>
<?=$this->form->end()?>

Good! You can also pass in arbitrary variables to the partial templates as an array (e.g. using compact()):

<?=$this->partial->fields(compact('foo', 'bar'))?>

The renderer will extract that array to make the variables $foo and $bar available for the fields.html.php template to use.

More on templates and helpers in Lithium can be found here.

You can respond to this article by replying on twitter or sending me an email.


Quick world time lookup using Alfred and Growl

I’ve been an avid Alfred user since its early days. It’s just one of these pieces of software that you get attached to and want to use for everything. Alfred is a fast, lightweight and friendly app launcher. But it’s also much more than that. Terminal shortcuts, custom searches and clipboard snippets are probably my top used features in addition to the app launching and file browser. I’d recommend checking it out if you haven’t already. The powerpack is worth every single penny.

Anna’s article about setting up a custom search to quickly navigate to a Worldtime Buddy reminded me of something I do quite often when I want to quickly tell the current time is it in any city around the world. Especially handy if you work with a team whose members are scattered all over the world. I often just ask Google. For example, searching for “time in sydney” gives you the current time in Sydney, along with the search results. Which, at that point, is basically just jargon.

In Alfred you can simply use ‘google time in sydney’ which would open a new tab in your browser and basically do the above. But I wanted something even quicker and does not involve opening a new browser tab that I’d be closing 3 seconds after.

Enter timeinplace, a small and simple script that hits that search page, grabs that line of text and displays it in a Growl notification.

Here’s how.

Download the script and place it somewhere convenient. I often put my own scripts in ~/bin/ which I’ve already added to my $PATH.

You will need to make that script executable

chmod +x timeinplace

And you will also need to install the nokogiri and rb-appscript gems if you don’t have them already.

gem install nokogiri rb-appscript

Now open Alfred Preferences, and navigate to the ‘Terminal/Shell’ section. Use the ‘+’ button under the shortcuts list to add a new shortcut.

Alfred Preferences Screenshot

Use whatever you like for ‘Title’, ‘Description’ and ‘Keyword’. The latter is what you will be using to run the script, so I recommend something short and easy. I use ‘time’ so I can type in ‘time in city’ like I’m used to.

For ‘Command’ put in timeinplace"{query}", make sure ‘Quotes’ is checked and save the shortcut. Don’t forget to check the ‘Silent’ checkbox next to your shortcut in the list. This will tell Alfred not to execute the script in a visible terminal window.

Tip: If you are having trouble getting the script to work in Silent mode, try using the absolute path to the script in ‘Command’ instead. i.e. ~/bin/timeinplace "{query}" in my case.

That’s it. Fire Alfred and type in ‘time in melbourne’, a second or two to wait, and…

Alfred Preferences Screenshot

For those who only wanted to take a look, here’s the script

#!/usr/local/bin/ruby

require 'open-uri'
require 'cgi'
require 'nokogiri'
require 'appscript'
include Appscript

query = ARGV[0]
exit if query.nil?

begin
  url = "http://www.google.com/search?q=time+#{CGI.escape(query)}"
  res = Nokogiri::HTML(open(url)).at("li.tpo").text
  description, title = res.split(' - ')
rescue
  title = "Cannot find time"
  description = "Cannot find timne for '#{query}'"
end

growl = app("GrowlHelperApp")
notifications = ["TimeInPlace"]
growl.register(
  :as_application => "TimeInPlace",
  :all_notifications => notifications,
  :default_notifications => notifications
)
growl.notify(
  :with_name => "TimeInPlace",
  :title => title,
  :description => description,
  :application_name => "TimeInPlace",
  :icon_of_application => "Alfred"
)

Enjoy.

Update: Slightly refactored the script to use the appscript library instead of the ugly applescript wrapped in an uglier system().

You can respond to this article by replying on twitter or sending me an email.


Soft Launching

“Just launch it already!” is, more or less, the response I got every time I talked about my plans for awhitebox. So as you can see, I’m yielding and finally letting it loose. Expect a long write-up soon.

People who know me wouldn’t hold their breaths though ;-)

Laugh-Out-Loud Cats #1248

– Laugh-Out-Loud Cats #1248 (by-nc-nd) by Ape Lad.