views:

361

answers:

2

I need to write a Ruby method that takes a word, runs it through OS 10.5’s Dictionary.app’s thesaurus function, and returns alternative words.

If the Ruby method ends up calling the command-line, that’s fine; I just need to be able to do it programmatically from Ruby.

After looking through Ruby OSA, I realize that the Dictionary is accessible through some Dictionary Service [http://discussions.apple.com/thread.jspa?threadID=1561332], but I don’t really get it.

Anyone see a simple solution?

I was also up for making an Automator workflow and calling it from the command line, but I wasn’t able to properly feed the "Get Definition" function a word from the shell for some reason (it kept saying that it couldn’t find the word, but when looking manually it worked).

+4  A: 

Unfortunately the only programmatic interface to this (Dictionary Services) doesn't support setting a dictionary.

However, it does consult the dictionary preferences to use the first dictionary specified, so you could potentially, in very ugly fashion, reset the preferences so the thesaurus is the only dictionary available.

This is really disgusting and likely to break if breathed upon, but it should work:

/* compile with:

   gcc -o thesaurus -framework CoreServices -framework Foundation thesaurus.m
*/

#import <Foundation/Foundation.h>
#include <CoreServices/CoreServices.h>

int main(int argc, char *argv[]) {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
  NSMutableDictionary *dictionaryPrefs =
    [[userDefaults persistentDomainForName:@"com.apple.DictionaryServices"] mutableCopy];

  NSArray *activeDictionaries = [dictionaryPrefs objectForKey:@"DCSActiveDictionaries"];

  [dictionaryPrefs setObject:
    [NSArray arrayWithObject:@"/Library/Dictionaries/Oxford American Writer's Thesaurus.dictionary"]
                      forKey:@"DCSActiveDictionaries"];
  [userDefaults setPersistentDomain:dictionaryPrefs forName:@"com.apple.DictionaryServices"];

  NSString *word = [NSString stringWithUTF8String:argv[1]];
  puts([(NSString *)DCSCopyTextDefinition(NULL, (CFStringRef)word,
                                          CFRangeMake(0, [word length])) UTF8String]);

  [dictionaryPrefs setObject:activeDictionaries forKey: @"DCSActiveDictionaries"];
  [userDefaults setPersistentDomain:dictionaryPrefs forName:@"com.apple.DictionaryServices"];
}

And use it as:

% ./thesaurus string
noun 
1 twine, cord, yarn, thread, strand.
2 chain, group, firm, company.
3 series, succession, chain, sequence, run, streak.
4 line, train, procession, queue, file, column, convoy, cavalcade.
[...]
Nicholas Riley
+1, well done! Way to beat me to the punch!
rampion
A: 

Wow, Stack Overflow is awesome!

Thanks Nicholas!

EdwardOG