searching address book (was Re: [TxMt] create email from document)

Grant Hollingworth grant at antiflux.org
Wed Nov 8 03:53:41 UTC 2006


* Brett Terpstra <brett at circlesixdesign.com> [2006-11-07 20:24]:
>It's not currently set up to match a full name, just a first, last,  
>or partial.  I could change the algorithm to do a full match, but it  
>wasn't intuitive to the way I was thinking this would be used.  What  
>were your thoughts?

I've attached yet another version of this.  It now uses lbdb if found, else contacts, else osascript.  lbdb can also search Mutt alias files, LDAP, and much more.  Both lbdb and contacts can handle a full name, if you select it first.

I'm grabbing the path from bash_init.sh, which isn't the fastest method (starting a whole shell just to get a variable)... but it works.
-------------- next part --------------
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>beforeRunningCommand</key>
	<string>nop</string>
	<key>bundleUUID</key>
	<string>B7BC3FFD-6E4B-11D9-91AF-000D93589AF6</string>
	<key>command</key>
	<string>#!/usr/bin/env ruby -wKU

SUPPORT = ENV['TM_SUPPORT_PATH']
DIALOG = SUPPORT + '/bin/tm_dialog'
ENV['PATH'] = %x{sh -c '. "$BASH_ENV"; echo $PATH'}
require SUPPORT + '/lib/escape'
require SUPPORT + '/lib/plist'
require SUPPORT + '/lib/exit_codes'
search_text = STDIN.read

def found?(executable)
  ENV['PATH'].split(/:/).find do |dir|
    File.executable?(File.join(dir, executable))
  end
end

COMMANDS = [
  ['lbdbq', 
    proc do
      %x{lbdbq "#{search_text}" | tail -n +2}.map do |line|
        line.split(/\t/)[0..1].map {|f| f.strip}.reverse
      end
    end
  ],
  ['contacts',
    proc do
      %x{contacts -HSs -f "%n:%e" "#{search_text}"}.map do |line|
        line.chomp.split(/:/)
      end
    end
  ],
  ['osascript',
    proc do
      %x{osascript <<END
tell application "Address Book"
  set matchList to {}
  repeat with oneID in (get id of every person whose name contains "#{search_text}")
    set oneID to contents of oneID
    set dataList to (get every email of person id oneID)
    repeat with oneValue in dataList
      copy (name of person id oneID & tab & value of oneValue) to end of matchList
    end repeat
  end repeat
end tell

set AppleScript's text item delimiters to ASCII character 10
return items of matchList as string
END
}.map {|line| line.chomp.split(/\t/)}
    end
  ],
]

matches = COMMANDS.find {|command| found? command.first }.last.call

names = matches.map do |name, email|
	{'title' => "#{name} (#{email})", 'email' => "#{name} <#{email}>"} if email
end.compact
TextMate.exit_show_tool_tip "No matches found" if names.empty?
TextMate.exit_replace_text names[0]['email'] if names.length == 1

plist = { 'menuItems' => names }.to_plist
res = PropertyList::load(`#{e_sh DIALOG} -up #{e_sh plist}`)
TextMate.exit_discard unless res.has_key? 'selectedMenuItem'

print res['selectedMenuItem']['email']</string>
	<key>fallbackInput</key>
	<string>word</string>
	<key>input</key>
	<string>selection</string>
	<key>keyEquivalent</key>
	<string>^@A</string>
	<key>name</key>
	<string>Find Email Address in Address Book</string>
	<key>output</key>
	<string>replaceSelectedText</string>
	<key>uuid</key>
	<string>575C4CAF-71B1-4F92-886B-8D89E0D0EFDD</string>
</dict>
</plist>


More information about the textmate mailing list