Skip to content

contacts

This directory manages contact integration for Talon voice dictation. It allows you to dynamically load a list of contacts and resolve spoken names, nicknames, and emails to make entering contact information hands-free and efficient.

The implementation details and user documentation are split across two files: * contacts.py implements the logic to watch, parse, merge, and register contact data into Talon lists and captures. * README.md details the formats for the contact sources, lists usage examples, and provides a utility snippet for exporting contacts from external sources like Google Contacts.


How It Works

The contacts system works by watching user-defined contact files, processing their contents into memory, and presenting them to Talon via native lists and semantic captures.

1. File Tracking and Merging

The module automatically watches two files in your private user settings directory:

  • contacts.csv: A simpler format containing flat mappings of names to emails.
  • contacts.json: A richer structured format that supports full names, nicknames, and customized phonetic pronunciations.

When either file changes, contacts.py triggers automatic reloading:

  • CSV Loading: Parses names and emails and saves them as basic Contact entities.
  • JSON Loading: Deserializes more intricate payloads. It uses a "pronunciation: written_name" parser syntax, allowing you to explicitly dictate how a contact's name is spoken (e.g. "Jah Nee: Jonny").
  • Merging: Data is merged on the unique email address. If a contact exists in both, JSON definitions take precedence, but if the JSON definition is missing a full name, the CSV name is used as a fallback.

2. Resolving Pronunciations and Names

Once loaded, the module builds inverse mapping tables (e.g., from spoken pronunciation to written name/email).

  • It handles first-name extraction automatically by splitting full names.
  • It parses pronunciation components. If a full name has a pronunciation with the same number of words as the written name, it will map those sub-parts automatically (e.g. mapping the spoken first name to the written first name).
  • In the case of name collisions (like two different contacts named "John"), JSON entries take priority, and earlier occurrences take precedence. You can use nicknames and custom pronunciations (e.g., "John S: John") to avoid conflicts.

3. Voice Captures and Output Formats

The parsed maps are exposed via three Talon lists:

  • user.contact_names
  • user.contact_emails
  • user.contact_full_names

Using these lists, contacts.py registers the unified capture <user.prose_contact>. Instead of triggering actions directly, this capture is consumed by general text rules (such as <user.text> or <user.prose>) to seamlessly insert contact fields as you speak.

Available spoken suffixes and structures include:

  • First names and nicknames: "John name" -> John
  • Full names: "John full name" -> John Doe
  • Emails: "John email address" -> john.doe@example.com
  • LDAP/Usernames: "John username" -> john.doe
  • Possessive forms: "John full names" -> John Doe's
  • Snippets: "hi John" -> hi John

For comprehensive configuration examples and an automation script to export Gmail contacts to the compatible CSV format, refer to README.md.