Wednesday, August 29, 2012

Create Reminder in AppleScript with Intelligent Date Time Parsing

Although you can make a new reminder object in Mountain Lion's Reminders application directly with Apple Script you lose the cool built-in parsing that extracts the date/time settings.

For example we want to simply write "Bowling with Bob 6PM on Friday" and have Reminders parse out the date and time to create a reminder(name="Bowling with Bob", datetime="2012-09-01 18:00:00")

Here is the script, note that I have it in Alfred-friendly form since I use the Alfred app launcher:

on alfred_script(q)
try
  tell application "Reminders"
    activate
    activate -- Single activate doesn't always work, esp if Reminders is closed.
    show list "Reminders"
   
    tell application "System Events" to keystroke "n" using command down
    tell application "System Events" to keystroke q
    tell application "System Events" to key code 36 -- enter
  end tell
 
on error a number b
  display dialog a
end try
end alfred_script

-- how to call:
--alfred_script("Bowling with Bob 6PM on Friday")

Tuesday, April 5, 2011

Fixing iChat GoogleTalk (gchat) connection issues.

iChat kept dropping my two Google chat accounts so I did some of my own Googling for a fix:

Create a script to reconnect iChat.


I created a file '~/dev/ichat-reconnect.sh':


#!/usr/bin/osascript


if appIsRunning("iChat") then
 tell application "iChat"
        if status is offline then
            log in
        end if
        set originalStatus to the status message
    end tell
end if


on appIsRunning(appName)
 tell application "System Events" to (name of processes) contains appName
end appIsRunning


Create a LaunchAgent


LaunchAgents are the OSX equivalent of cron jobs.

In the folder ~/Library/LaunchAgents/ I created a file 'com.ichat.reconnect.plist':


<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>label</key>
    <string>com.ichat.reconnect</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/gcoller/dev/ichat-reconnect.sh</string>
    </array>
    <key>OnDemand</key>
    <false/>
    <key>Nice</key>
    <integer>1</integer>
    <key>StartInterval</key>
    <integer>5</integer>
    <key>StandardErrorPath</key>
    <string>/tmp/AlTest1.err</string>
    <key>StandardOutPath</key>
    <string>/tmp/AlTest1.out</string>
  </dict>
</plist>


Basically it means run my ichat-reconnect.sh script every 5 seconds.

Tell launch agent about your file


Issue the command:

launchctl load com.ichat.reconnect.plist

To get it started. It will start automatically on reboots.

Thursday, March 17, 2011

Intellij IDEA: Key command for right-click context menu

Ever wanted that right-click menu without having to touch the mouse when using IDEA?

Note: This is for OS X, probably is available for Windows.

Turns out to be easy enough:
1) Open KeyMap in Settings
2) Find "Show Context Menu" in the "Other" folder
3) Assign it a key (I used F13 since it is easy to find and available)

Wednesday, January 5, 2011

Groovy to Scala: Closures

Defining a closure that takes two variables and returns a String.

Groovy:
{ x, y -> ...}

Scala:
(x:Stirng, y:String):String => { ... }

Note, Scala requires types for values x and y.

Groovy to Scala: Regular Expressions

Coming to Scala from Groovy/Java. Scala seems to have a bit more overhead in learning basic concepts so I'm planing on keeping my notes here in a series of short posts. This is not meant by any means to be comprehensive but just a "hello world" for each topic that I wish I had.

Regular Expressions:

Defining: Just add a ".r" after a normal string:

val regEx = "apple*".r

Using: Use in a typical Scala match statement:

val name = ....
name match {
  case regEx => // do your processing here
  case entry => // like default, possibly throw an error
}

Grouping:

val zipMatch = "(\\d+)-(\\d+)"
val zip = "12345-1234"
zip match {
  case regEx(num1, num2) => // num1 == 12345, num2 == 1234
  case entry => // do nothing
}

Friday, July 25, 2008

Stephen King's N







Amazon S3 Fast downloads to EC2 using Curl

Our company is building an application that depends heavily on Amazon's Cloud Web Services: Simple Storage Service, Elastic Compute Cloud, and Simple Queue Service. We are using Java for a lot of the business logic and Groovy for the 'glue code', interacting with frameworks, etc.

Anyway, I've spent some time tuning downloads and found out that I can get an order of magnitude faster download time if I shell out to 'curl' than if I use jets3t or the lower-level HttpClient. Note this speed-up only occurs when moving an S3 object to an EC2 instance, not when moving it outside the cloud (to my laptop for instance).

For some reason uploads using jets3t are very fast and we are guessing at this point that HttpClient (which jets3t depends upon) is causing the slowdown because it either can't (or hasn't been configured properly to) deal with the extra-large packet sizes that AWS allows within its cloud.

Being a developer on a schedule I punted and shelled out to curl using a signed-url that jets3t provides for my S3 Object get.

Here is the pseudo-code in Groovy (would be trivial to convert to plain Java) for the shell-out:


S3Service s3service = ... // Inject an instance of JetS3t S3Service
File file = ... // File representing download location on disk
S3Bucket bucket // Bucket object (could just be a string)

Date date = s3service.getCurrentTimeWithOffset()
long secondsSinceEpoch = (date.time / 1000) + 60L
def url = new URL(S3Service.createSignedUrl('GET', bucket.name, key, null, null, s3service.AWSCredentials, secondsSinceEpoch, false, false))

def cmd = ['curl']
// I break up large downloads so here is an optional byte range.
cmd += ['--range', "${low}-${hi}"]
cmd += ['--show-error']
cmd += ['--connect-timeout', '30']
cmd += ['--retry', '5']
cmd += ['--output', file.absolutePath]
cmd += [url]

Process p = cmd.execute()

p.waitFor()
if (p.exitValue() != 0) {
throw new IllegalStateException("Curl process exited with error code ${p.exitValue()}")
}
LOG.info("${file.name} download completed")


One final note: this will capture a curl process error but not many of the errors that you could experience when working with S3. For example if the key did not exist, the curl process would succeed but the downloaded file would contain the Amazon error response xml instead of the intended file. So it is your responsibility to first do a s3service.getObjectDetails(..) to make sure the object exists, then you must check the downloaded content length (and possibly content type) to ensure that you received your object and not an error.