Welcome to khard’s documentation!

Command line usage

The following subsections give an overview of khard’s main features. You may get general help and all available actions as well as detailed information on all available options for the specific commands with the --help options:

khard --help
khard command --help

Beware, that the order of the command line parameters matters.

Show contacts

After you have created a new address book and you have synced it to your local machine, you can list all available contacts with the following command:

khard list

or if you have more than one address book and you want to filter the output:

khard list -a addressbook1,addressbook2

The resulting contact table only contains the first phone number and email address. If you want to view all contact details you can pick one from the list:

khard show

or search for it:

khard show [--strict-search] name of contact

or select the contact by it’s uid, which you can find at the contacts table:

khard show -u ID

The parameters -a and -u from the examples above are always optional. They can be given on all subcommands that select one or more contacts. If you don’t use them or your input produces unambiguous results, you may pick the contacts from a list instead.

The search parameter searches in all data fields. Therefore you aren’t limited to the contact’s name but you also could for example search for a part of a phone number, email address or post address. However if you explicitly want to narrow your search to the name field, you may use the --strict-search parameter instead.

Create contact

Add new contact with the following command:

khard new [-a "address book name"]

The template for the new contact opens in the text editor, which you can set in the config file. It follows the yaml syntax.

Alternatively you can create the contact from stdin:

echo "
First name : John
Last name  : Smith
Email :
    work : john.smith@example.org
Phone :
    home : xxx 555 1234
Categories :
    - cat1
    - cat2
    - cat3
" | khard new

or create from input template file:

khard new -i contact.yaml

You may get an empty contact template with the following command:

khard template

Assuming the user had configured the three supported private object “Jabber”, “Skype”, and “Twitter” in their config, the template would look like this.

Per default khard creates vcards of version 3.0. If your other contact applications support vcards of the more recent version 4.0, you may change this with the option --vcard-version. Example:

khard new --vcard-version=4.0

For a more permanent solution you may set the preferred_version parameter in the vcard section of the khard config file (see the example config file for more details). But beware, that khard cannot convert already existing contacts from version 3.0 to 4.0. Therefore this setting is not applicable to the modify action.

Edit contacts

Use the following to modify the contact after successful creation:

khard edit [-a addr_name] [-u uid|search terms [search terms ...]]

If you want to edit the contact elsewhere, you can export the filled contact template:

khard show --format=yaml -o contact.yaml [-a addr_name] [-u uid|search terms [search terms ...]]

Edit the yaml file and re-import either through stdin:

cat contact.yaml | khard edit [-a addr_name] [-u uid|search terms [search terms ...]]

or file name:

khard edit -i contact.yaml [-a addr_name] [-u uid|search terms [search terms ...]]

If you want to merge contacts use the following to select a first and then a second contact:

khard merge [-a source_abook] [-u uid|search terms [search terms ...]] [-A target_abook] [-U target_uid|-t target_search_terms]

You will be launched into your merge_editor (see khard.conf) where you can merge all changes from the first selected contact onto the second. Once you are finished, the first contact is deleted and the second one updated.

Copy or move contact:

khard copy [-a source_abook] [-u uid|search terms [search terms ...]] [-A target_abook]
khard move [-a source_abook] [-u uid|search terms [search terms ...]] [-A target_abook]

Remove contact:

khard remove [-a addr_name] [-u uid|search terms [search terms ...]]

Scripting and integration with other programs

Khard can be used together with email or SIP clients or a synchronisation program like vdirsyncer.

mutt

Khard may be used as an external address book for the email client mutt. To accomplish that, add the following to your mutt config file (mostly ~/.mutt/muttrc):

set query_command= "khard email --parsable %s"
bind editor <Tab> complete-query
bind editor ^T    complete

Then you can complete email addresses by pressing the Tab-key in mutt’s new mail dialog. If your address books contain hundreds or even thousands of contacts and the query process is very slow, you may try the --search-in-source-files option to speed up the search:

set query_command= "khard email --parsable --search-in-source-files %s"

If you want to complete multi-word search strings like “john smith” then you may try out the following instead:

set query_command = "echo %s | xargs khard email --parsable --"

To add email addresses to khard’s address book, you may also add the following lines to your muttrc file:

macro index,pager A \
  "<pipe-message>khard add-email<return>" \
  "add the sender email address to khard"

Then navigate to an email message in mutt’s index view and press “A” to start the address import dialog.

Alot

Add the following lines to your alot config file:

[accounts]
    [[youraccount]]
        [[[abook]]]
            type = shellcommand
            command = khard email --parsable
            regexp = '^(?P<email>[^@]+@[^\t]+)\t+(?P<name>[^\t]+)'
            ignorecase = True

Twinkle

For those who also use the SIP client twinkle to take phone calls, khard can be used to query incoming numbers. The plugin tries to find the incoming caller id and speaks it together with the phone’s ring tone. But it is more or less a proof of concept - feel free to extend.

The plugin needs the following programs:

sudo aptitude install ffmpeg espeak sox mpc

sox and ffmpeg are used to cut and convert the new ring tone and espeak speaks the caller id. mpc is a client for the music player daemon (mpd). It’s required to stop music during an incoming call. Skip the last, if you don’t use mpd. Don’t forget to set the “stop_music”-parameter in the config.py file to False, too.

After the installation, copy the scripts and sounds folders to your twinkle config folder:

cp -R misc/twinkle/* ~/.twinkle/

Next convert the sound samples to wave:

ffmpeg -i incoming_call.ogg incoming_call.wav
ffmpeg -i outgoing_call.ogg outgoing_call.wav
ffmpeg -i ringtone_segment.ogg ringtone_segment.wav

Then edit your twinkle config file (mostly ~/.twinkle/twinkle.cfg) like this:

# RING TONES
# We need a default ring tone. Otherwise the phone would not ring at all, if
# something with the custom ring tone creation goes wrong.
ringtone_file=/home/USERNAME/.twinkle/sounds/incoming_call.wav
ringback_file=/home/USERNAME/.twinkle/sounds/outgoing_call.wav

# SCRIPTS
script_incoming_call=/home/USERNAME/.twinkle/scripts/incoming_call.py
script_in_call_answered=
script_in_call_failed=/home/USERNAME/.twinkle/scripts/incoming_call_failed.py
script_outgoing_call=
script_out_call_answered=
script_out_call_failed=
script_local_release=/home/USERNAME/.twinkle/scripts/incoming_call_ended.py
script_remote_release=/home/USERNAME/.twinkle/scripts/incoming_call_ended.py

Zsh

The file misc/zsh/_khard contains a khard cli completion function for the zsh and misc/zsh/_email-khard completes email addresses.

Install by copying to a directory where zsh searches for completion functions (the $fpath array). If you, for example, put all completion functions into the folder ~/.zsh/completions you must add the following to your zsh main config file:

fpath=( $HOME/.zsh/completions $fpath )
autoload -U compinit
compinit

sdiff

Use the wrapper script misc/sdiff/sdiff_khard_wrapper.sh if you want to use sdiff as your contact merging tool. Just make the script executable and set it as your merge editor in khard’s config file:

merge_editor = /path/to/sdiff_khard_wrapper.sh

Davcontroller

Khard also contains a helper script called davcontroller. It’s designed to create and remove address books and calendars at the server. I have created davcontroller cause my previously used CalDAV server (Darwin calendarserver) offered no simple way to create new address books and calendars. But davcontroller should be considered as a hacky solution and it’s only tested against the Darwin calendarserver. So if your CalDAV server offers a way to create new address books and calendars I recommend to prefer that method over davcontroller.

If you nonetheless want to try davcontroller, you have to install the CalDAVClientLibrary first. Unfortunately that library isn’t compatible to python3 so you have to create an extra python2 virtual environment and install in there:

# create python2 virtual environment
virtualenv -p python2 ~/.virtualenvs/davcontroller
# get library from svn repository
sudo aptitude install subversion
svn checkout http://svn.calendarserver.org/repository/calendarserver/CalDAVClientLibrary/trunk CalDAVClientLibrary
cd CalDAVClientLibrary
# install library
~/.virtualenvs/davcontroller/bin/python setup.py install
# start davcontroller script
~/.virtualenvs/davcontroller/bin/python /path/to/khard-x.x.x/misc/davcontroller/davcontroller.py

This small script helps to create and remove new address books and calendars at the carddav and caldav server.

List available resources:

davcontroller -H example.com -p 11111 -u USERNAME -P PASSWORD list

Possible actions are: list, new-addressbook, new-calendar and remove. After creating or removing you must adapt your vdirsyncer config.

Contributing

Thank you for considering contributing to khard!

Benchmarking, profiling and performance

When benchmarking code it is important to reduce other load on the system (music player, web browser for example). One can use the python timeit module or a command line utility like hyperfine:

python -m timeit -s 'from khard.khard import main' 'main(["list"])'
hyperfine 'python -m khard list'

For profiling the cProfile python module works well. With the help of gprof2dot one can generate quite useful graphs:

python -m cProfile -o output.file -m khard list
gprof2dot -f pstats --show-samples output.file | dot -T png > graph.png
xdg-open graph.png

API Reference

This page contains auto-generated API reference documentation 1.

khard

Submodules
khard.actions

Names and aliases for the subcommands on the command line

Module Contents
class khard.actions.Actions

A class to manage the names and aliases of the command line subcommands.

action_map :Dict[str, List[str]]
classmethod get_action(cls, alias: str)

Find the name of the action for the supplied alias. If no action is asociated with the given alias, None is returned.

Parameters

alias – the alias to look up

Rturns

the name of the corresponding action or None

classmethod get_aliases(cls, action: str)

Find all aliases for the given action. If there is no such action, None is returned.

Parameters

action – the action name to look up

Returns

the list of aliases corresponding to the action or None

classmethod get_actions(cls)

Find the names of all defined actions.

Returns

all action names

classmethod get_all(cls)

Find the names of all defined actions and their aliases.

Returns

the names of all actions and aliases

khard.address_book

A simple class to load and manage the vcard files from disk.

Module Contents
khard.address_book.logger
khard.address_book.Query
exception khard.address_book.AddressBookParseError(filename: str, abook: str, reason: Exception)

Bases: Exception

Indicate an error while parsing data from an address book backend.

__str__(self)
exception khard.address_book.AddressBookNameError

Bases: Exception

Indicate an error with an address book name.

class khard.address_book.AddressBook(name: str)

The base class of all address book implementations.

__str__(self)
__eq__(self, other: object)
__ne__(self, other: object)
static _compare_uids(uid1: str, uid2: str)

Calculate the minimum length of initial substrings of uid1 and uid2 for them to be different.

Parameters
  • uid1 – first uid to compare

  • uid2 – second uid to compare

Returns

the length of the shortes unequal initial substrings

_search_all(self, query)

Search in all fields for contacts matching query.

Parameters

query – the query to search for

Yields

all found contacts

_search_names(self, query)

Search in the name filed for contacts matching query.

Parameters

query – the query to search for

Yields

all found contacts

_search_uid(self, query)

Search for contacts with a matching uid.

Parameters

query – the query to search for

Yields

all found contacts

search(self, query: Optional[List[str]], method: str = 'all')

Search this address book for contacts matching the query.

The method can be one of “all”, “name” and “uid”. The backend for this address book migth be load()ed if needed.

Parameters
  • query – the query to search for

  • method – the type of fileds to use when seaching

Returns

all found contacts

get_short_uid_dict(self, query: Optional[str] = None)

Create a dictionary of shortend UIDs for all contacts.

All arguments are only used if the address book is not yet initialized and will just be handed to self.load().

Parameters

query – see self.load()

Returns

the contacts mapped by the shortes unique prefix of their UID

get_short_uid(self, uid: str)

Get the shortend UID for the given UID.

Parameters

uid – the full UID to shorten

Returns

the shortend uid or the empty string

abstract load(self, query: Query = None)

Load the vCards from the backing store.

If a query is given loading is limited to entries which match the query. If the query is None all entries will be loaded.

Parameters

query – the query to limit loading to matching entries

Returns

the number of loaded contacts and the number of errors

class khard.address_book.VdirAddressBook(name: str, path: str, private_objects: Optional[List[str]] = None, localize_dates: bool = True, skip: bool = False)

Bases: khard.address_book.AddressBook

An AddressBook implementation based on a vdir.

This address book can load contacts from vcard files that reside in one direcotry on disk.

load(self, query: Query = None, search_in_source_files: bool = False)

Load all vcard files in this address book from disk.

If a search string is given only files which contents match that will be loaded.

Parameters
  • query – a regular expression to limit the results

  • search_in_source_files – apply search regexp directly on the .vcf files to speed up parsing (less accurate)

Throws

AddressBookParseError

class khard.address_book.AddressBookCollection(name: str, abooks: List[VdirAddressBook])

Bases: khard.address_book.AddressBook

A collection of several address books.

This represents a temporary merege of the contact collections provided by the underlying adress books. On load all contacts from all subadressbooks are copied into a dict in this address book. This allow this class to use all other methods from the parent AddressBook class.

load(self, query: Query = None)

Load the wrapped address books with the given parameters

All parameters will be handed to VdirAddressBook.load.

Parameters

query – a regular expression to limit the results

Throws

AddressBookParseError

__getitem__(self, key: Union[int, str])

Get one of the backing address books by name or index

Parameters

key – the name of the address book to get or its index

Returns

the matching address book

Throws

KeyError

__iter__(self)
Returns

an iterator over the underlying address books

__len__(self)
khard.carddav_object

Classes and logic to handle vCards in khard.

This module explicitly supports the vCard specifications version 3.0 and 4.0 which can be found here: - version 3.0: https://tools.ietf.org/html/rfc2426 - version 4.0: https://tools.ietf.org/html/rfc6350

Module Contents
khard.carddav_object.logger
khard.carddav_object.Query
khard.carddav_object.convert_to_vcard(name: str, value: Union[str, List[str]], allowed_object_type: ObjectType) → Union[str, List[str]]

converts user input into vcard compatible data structures

Parameters
  • name – object name, only required for error messages

  • value – user input

  • allowed_object_type – set the accepted return type for vcard attribute

Returns

cleaned user input, ready for vcard or a ValueError

khard.carddav_object.multi_property_key(item: Union[str, Dict]) → List

key function to pass to sorted(), allowing sorting of dicts with lists and strings. Dicts will be sorted by their label, after other types.

Parameters

item (a dict with a single entry or any sortable type) – member of the list being sorted

Returns

a list with two members. The first is int(isinstance(item, dict). The second is either the key from the dict or the unchanged item if it is not a dict.

Return type

list(int, type(item)) or list(int, str)

class khard.carddav_object.VCardWrapper(vcard: vobject.vCard, version: Optional[str] = None)

Wrapper class around a vobject.vCard object.

This class can wrap a single vCard and presents its data in a manner suitable for khard. Additionally some details of the vCard specifications in RFC 2426 (version 3.0) and RFC 6350 (version 4.0) that are not enforced by the vobject library are enforced here.

_default_version = 3.0
_supported_versions = ['3.0', '4.0']
phone_types_v3 = ['bbs', 'car', 'cell', 'fax', 'home', 'isdn', 'msg', 'modem', 'pager', 'pcs', 'video', 'voice', 'work']
email_types_v3 = ['home', 'internet', 'work', 'x400']
address_types_v3 = ['dom', 'intl', 'home', 'parcel', 'postal', 'work']
phone_types_v4 = ['text', 'voice', 'fax', 'cell', 'video', 'pager', 'textphone', 'home', 'work']
email_types_v4 = ['home', 'internet', 'work']
address_types_v4 = ['home', 'work']
__str__(self)
_get_string_field(self, field: str)

Get a string field from the underlying vCard.

Parameters

field – the field value to get

Returns

the field value or the empty string

_get_multi_property(self, name: str)

Get a vCard property that can exist more than once.

It does not matter what the individual vcard properties store as their value. This function returnes them untouched inside an agregating list.

If the property is part of a group containing exactly two items, with exactly one ABLABEL. the property will be prefixed with that ABLABEL.

Parameters

name – the name of the property (should be UPPER case)

Returns

the values from all occurences of the named property

_delete_vcard_object(self, name: str)

Delete all fields with the given name from the underlying vCard.

If a field that will be deleted is in a group with an X-ABLABEL field, that X-ABLABEL field will also be deleted. These fields are commonly added by the Apple address book to attach custom labels to some fields.

Parameters

name – the name of the fields to delete

static _parse_type_value(types: List[str], supported_types: List[str])

Parse type value of phone numbers, email and post addresses.

Parameters
  • types – list of type values

  • supported_types – all allowed standard types

Returns

tuple of standard and custom types and pref integer

_get_types_for_vcard_object(self, object: vobject.base.ContentLine, default_type: str)

get list of types for phone number, email or post address

Parameters
  • object – vcard class object

  • default_type – use if the object contains no type

Returns

list of type labels

property version(self)
property uid(self)
_update_revision(self)

Generate a new REV field for the vCard, replace any existing

All vCards should only always have one revision, this is a requirement for version 4 but also makes sense for all other versions.

Return type

NoneType

property birthday(self)

Return the birthday as a datetime object or a string depending on weather it is of type text or not. If no birthday is present in the vcard None is returned.

Returns

contacts birthday or None if not available

property anniversary(self)
Returns

contacts anniversary or None if not available

_get_ablabel(self, item: vobject.base.ContentLine)

Get an ABLABEL for a specified item in the vCard. Will return the ABLABEL only if the item is part of a group with exactly two items, exactly one of which is an ABLABEL.

Parameters

item – the item to be labelled

Returns

the ABLABEL in the circumstances above or an empty string

_get_new_group(self, group_type: str = '')
Get an unused group name for adding new groups. Uses the form item123

or itemgroup_type123 if a grouptype is specified.

Parameters

group_type – (Optional) a string to add between “item” and the number

Returns

the name of the first unused group of the specified form

_add_labelled_object(self, obj_type: str, user_input, name_groups: bool = False, allowed_object_type: ObjectType = ObjectType.string)
Add an object to the VCARD. If user_input is a dict, the object will

be added to a group with an ABLABEL created from the key of the dict.

Parameters
  • obj_type – type of object to add to the VCARD.

  • user_input (str or list(str) or dict(str) or dict(list(str))) – Contents of the object to add. If a dict

  • name_groups – (Optional) If True, use the obj_type in the group name for labelled objects.

  • allowed_object_type – (Optional) set the accepted return type for vcard attribute

_prepare_birthday_value(self, date: Union[str, datetime.datetime])

Prepare a value to be stored in a BDAY or ANNIVERSARY attribute.

Parameters

date (datetime.datetime or str) – the date like value to be stored

Returns

the object to set as the .value for the attribute and weather it should be stored as plain text

Return type

tuple(str,bool)

property formatted_name(self)
_get_names_part(self, part: str)

Get some part of the “N” entry in the vCard as a list

Parameters

part – the name to get e.g. “prefix” or “given”

Returns

a list of entries for this name part

_get_name_prefixes(self)
_get_first_names(self)
_get_additional_names(self)
_get_last_names(self)
_get_name_suffixes(self)
get_first_name_last_name(self)

Compute the full name of the contact by joining first, additional and last names together

get_last_name_first_name(self)

Compute the full name of the contact by joining the last names and then after a comma the first and additional names together

_add_name(self, prefix: Union[str, List[str]], first_name: Union[str, List[str]], additional_name: Union[str, List[str]], last_name: Union[str, List[str]], suffix: Union[str, List[str]])

Add an N entry to the vCard. No old entries are affected.

Parameters
  • prefix

  • first_name

  • additional_name

  • last_name

  • suffix

property organisations(self)
Returns

list of organisations, sorted alphabetically

_add_organisation(self, organisation: Union[str, List[str]])

Add one ORG entry to the underlying vcard

Parameters

organisation – the value to add

property titles(self)
_add_title(self, title)
property roles(self)
_add_role(self, role)
property nicknames(self)
_add_nickname(self, nickname)
property notes(self)
_add_note(self, note)
property webpages(self)
_add_webpage(self, webpage)
property categories(self)
_add_category(self, categories: List[str])

Add categories to the vCard

Parameters

categories

property phone_numbers(self)
Returns

dict of type and phone number list

_add_phone_number(self, type, number)
property emails(self)
Returns

dict of type and email address list

add_email(self, type, address)
property post_addresses(self)
Returns

dict of type and post address list

get_formatted_post_addresses(self)
_add_post_address(self, type, box, extended, street, code, city, region, country)
class khard.carddav_object.YAMLEditable(vcard: vobject.vCard, supported_private_objects: Optional[List[str]] = None, version: Optional[str] = None, localize_dates: bool = False)

Bases: khard.carddav_object.VCardWrapper

Conversion of vcards to YAML and updateing the vcard from YAML

_get_private_objects(self)
_add_private_object(self, key: str, value)
get_formatted_anniversary(self)
get_formatted_birthday(self)
static _format_date_object(date: Union[None, str, datetime.datetime], localize: bool)
static _filter_invalid_tags(contents: str)
static _parse_yaml(input: str)

Parse a YAML document into a dictinary and validate the data to some degree.

Parameters

input (str) – the YAML document to parse

Returns

the parsed datastructure

Return type

dict

static _set_string_list(setter: Callable[[Union[str, List]], None], key: str, data: Dict)

Prepocess a string or list and set each value with the given setter

Parameters
  • setter – the setter method to add a value to a card

  • key

  • data

_set_date(self, target: str, key: str, data: Dict)
update(self, input: str)

Update this vcard with some yaml input

Parameters

input – a yaml string to parse and then use to update self

to_yaml(self)

Convert this contact to a YAML string

The conversion follows the implicit schema that is given by the internal YAML template of khard.

Returns

a YAML representation of this contact

class khard.carddav_object.CarddavObject(vcard: vobject.vCard, address_book: address_book.VdirAddressBook, filename: str, supported_private_objects: Optional[List[str]] = None, vcard_version: Optional[str] = None, localize_dates: bool = False)

Bases: khard.carddav_object.YAMLEditable

classmethod new(cls, address_book: address_book.VdirAddressBook, supported_private_objects: Optional[List[str]] = None, version: Optional[str] = None, localize_dates: bool = False)

Create a new CarddavObject from scratch

classmethod from_file(cls, address_book: address_book.VdirAddressBook, filename: str, query: Query, supported_private_objects: Optional[List[str]] = None, localize_dates: bool = False)

Load a CarddavObject object from a .vcf file if the plain file matches the query.

Parameters
  • address_book – the address book where this contact is stored

  • filename – the file name of the .vcf file

  • query – the query to search in the source file or None to load the file unconditionally

  • supported_private_objects – the list of private property names that will be loaded from the actual vcard and represented in this pobject

  • localize_dates – should the formatted output of anniversary and birthday be localized or should the isoformat be used instead

Returns

the loaded CarddavObject or None if the file didn’t match

classmethod from_yaml(cls, address_book: address_book.VdirAddressBook, yaml: str, supported_private_objects: Optional[List[str]] = None, version: Optional[str] = None, localize_dates: bool = False)

Use this if you want to create a new contact from user input.

classmethod clone_with_yaml_update(cls, contact: CarddavObject, yaml: str, localize_dates: bool = False)

Use this if you want to clone an existing contact and replace its data with new user input in one step.

static match(string: str, query: Query)

Check if the given string matches against the query. The query is a list of lists of strings. The inner lists are AND joined and the outer lists are OR joined.

Parameters
  • string – the string which to check

  • query

__eq__(self, other: object)
__ne__(self, other: object)
print_vcard(self, show_address_book: bool = True, show_uid: bool = True)
write_to_file(self, overwrite: bool = False)
delete_vcard_file(self)
khard.cli

Command line parsing and configuration logic for khard

Module Contents
khard.cli.logger
khard.cli.field_argument(orignal: str) → List[str]

Ensure the fields specified for ls -F are proper field names. Nested attribute names are not checked.

Parameters

orignal – the value from the command line

Returns

the orignal value split at “,” if the fields are spelled correctly

Throws

argparse.ArgumentTypeError

khard.cli.create_parsers() → Tuple[argparse.ArgumentParser, argparse.ArgumentParser]

Create two argument parsers.

The first parser is manly used to find the config file which can than be used to set some default values on the second parser. The second parser can parse the remainder of the command line with the subcommand and all further options and arguments.

Returns

the two parsers for the first and the second parsing pass

Return type

(argparse.ArgumentParser, argparse.ArgumentParser)

khard.cli.parse_args(argv: List[str]) → Tuple[argparse.Namespace, Config]

Parse the command line arguments and return the namespace that was creates by argparse.ArgumentParser.parse_args().

Parameters

argv – the command line arguments

Returns

the namespace parsed from the command line

khard.cli.merge_args_into_config(args: argparse.Namespace, config: Config) → Config

Merge the parsed arguments from argparse into the config object.

Parameters
  • args – the parsed command line arguments

  • config – the parsed config file

Returns

the merged config object

khard.cli.init(argv: List[str]) → Tuple[argparse.Namespace, Config]

Initialize khard by parsing the command line and reading the config file

Parameters

argv – the command line arguments

Returns

the parsed command line and the fully initialized config

khard.config

Loading and validation of the configuration file

Module Contents
khard.config.logger
exception khard.config.ConfigError

Bases: Exception

Errors during config file parsing

khard.config.validate_command(value: List[str]) → List[str]

Special validator to check shell commands

The input must either be a list of strings or a string that shlex.split can parse into such.

Parameters

value – the config value to validate

Returns

the command after validation

Raises

validate.ValidateError

khard.config.validate_action(value: str) → str

Check that the given value is a valid action.

Parameters

value – the config value to check

Returns

the same value

Raises

validate.ValidateError

khard.config.validate_private_objects(value: List[str]) → List[str]

Check that the private objects are reasonable

Parameters

value – the config value to check

Returns

the list of private objects

Raises

validate.ValidateError

class khard.config.Config(config_file: Optional[str] = None)

Parse and validate the config file with configobj.

supported_vcard_versions = ['3.0', '4.0']
classmethod _load_config_file(cls, config_file: Optional[str])

Find and load the config file.

Parameters

config_file – the path to the config file to load

Returns

the loaded config file

static _validate(config: configobj.ConfigObj)
_set_attributes(self)

Set the attributes from the internal config instance on self.

init_address_books(self)

Initialize the internal address book collection.

This method should only be called after merging in the command line options as they can hold some options that are relevant for the loading of the address books.

get_address_books(self, names: Iterable[str], queries: Dict)

Load all address books with the given names.

Parameters
  • names – the address books to load

  • queries (dict) – a mapping of address book names to search queries

Returns

the loaded address books

merge(self, other: Union[configobj.ConfigObj, Dict])

Merge the config with some other dict or ConfigObj

Parameters

other – the other dict or ConfigObj to merge into self

Returns

None

merge_args(self, args: Namespace)

Merge options from a flat argparse object.

Parameters

args (argparse.Namespace) – the parsed arguments to incorperate

khard.formatter

Formatting and sorting of contacts

Module Contents
class khard.formatter.Formatter(display: str, preferred_email: List[str], preferred_phone: List[str], show_nicknames: bool)

A formtter for CarddavObject.

It recieves some settings on initialisation which influence the formatting of the contact.

static format_labeled_field(field, preferred)

Format a labeled field from a vcard for display, the first entry under the preferred label will be returned

:param dict(str:list(str)) field: the labeled field :param list(str) preferred: the order of preferred labels :returns: the formatted field entry :rtype: str

get_special_field(self, vcard: CarddavObject, field: str)

Returns certain fields with specific formatting options (for support of some list command options).

static get_nested_field(vcard: CarddavObject, field: str)

Returns the value of a nested field from a string

get_nested_field(vcard,’emails.home.1’) is equivalent to vcard.emails[‘home’][1].

Parameters
  • vcard – the contact from which to get the field

  • field – a field specification

Returns

the nested field, or the empty string if it didn’t exist

khard.helpers

Some helper functions for khard

Module Contents
khard.helpers.pretty_print(table: List[List[str]], justify: str = 'L') → str

Converts a list of lists into a string formatted like a table with spaces separating fields and newlines separating rows

khard.helpers.list_to_string(input: Union[str, List], delimiter: str) → str

converts list to string recursively so that nested lists are supported

Parameters
  • input – a list of strings and lists of strings (and so on recursive)

  • delimiter – the deimiter to use when joining the items

Returns

the recursively joined list

khard.helpers.string_to_list(input: Union[str, List[str]], delimiter: str) → List[str]
khard.helpers.string_to_date(string: str) → datetime

Convert a date string into a date object.

Parameters

string – the date string to parse

Returns

the parsed datetime object

khard.helpers.get_random_uid() → str
khard.helpers.file_modification_date(filename: str) → datetime
khard.helpers.convert_to_yaml(name: str, value: Union[None, str, List], indentation: int, index_of_colon: int, show_multi_line_character: bool) → List[str]

converts a value list into yaml syntax

Parameters
  • name – name of object (example: phone)

  • value (str, list(str), list(list(str)), list(dict)) – object contents

  • indentation – indent all by number of spaces

  • index_of_colon – use to position : at the name string (-1 for no space)

  • show_multi_line_character – option to hide “|”

Returns

yaml formatted string array of name, value pair

khard.helpers.indent_multiline_string(input: Union[str, List], indentation: int, show_multi_line_character: bool) → str
khard.helpers.get_new_contact_template(supported_private_objects: Optional[List[str]] = None) → str
khard.khard

Main application logic of khard includeing command line handling

Module Contents
khard.khard.logger
khard.khard.config :Config
khard.khard.T
khard.khard.confirm(message: str) → bool

Ask the user for confirmation on the terminal.

Parameters

message – the question to print

Returns

the answer of the user

khard.khard.select(items: List[T], include_none: bool = False) → Optional[T]

Ask the user to select an item from a list.

The list should be displayed to the user before calling this function and should be indexed starting with 1. This function might exit if the user selects “q”.

Parameters
  • items – the list from which to select

  • include_none – weather to allow the selection of no item

Returns

None or the selected item

khard.khard.write_temp_file(text: str = '') → str

Create a new temporary file and write some initial text to it.

Parameters

text – the text to write to the temp file

Returns

the file name of the newly created temp file

khard.khard.edit(*filenames: str, merge: bool = False) → None

Edit the given files with the configured editor or merge editor

khard.khard.create_new_contact(address_book: VdirAddressBook) → None
khard.khard.modify_existing_contact(old_contact: CarddavObject) → None
khard.khard.merge_existing_contacts(source_contact: CarddavObject, target_contact: CarddavObject, delete_source_contact: bool) → None
khard.khard.copy_contact(contact: CarddavObject, target_address_book: VdirAddressBook, delete_source_contact: bool) → None
khard.khard.list_address_books(address_books: Union[AddressBookCollection, List[VdirAddressBook]]) → None
khard.khard.list_contacts(vcard_list: List[CarddavObject], fields: Iterable[str] = (), parsable: bool = False) → None
khard.khard.list_with_headers(the_list: List, *headers: str) → None
khard.khard.choose_address_book_from_list(header_string: str, address_books: Union[AddressBookCollection, List[VdirAddressBook]]) → Optional[VdirAddressBook]
khard.khard.choose_vcard_from_list(header_string: str, vcard_list: List[CarddavObject], include_none: bool = False) → Optional[CarddavObject]
khard.khard.get_contact_list_by_user_selection(address_books: Union[VdirAddressBook, AddressBookCollection], search: Optional[List[str]], strict_search: bool) → List[CarddavObject]

returns a list of CarddavObject objects :param address_books: selected address books :param search: filter contact list :param strict_search: if True, search only in full name field :returns: list of CarddavObject objects

khard.khard.get_contacts(address_book: Union[VdirAddressBook, AddressBookCollection], query: Optional[List[str]], method: str = 'all', reverse: bool = False, group: bool = False, sort: str = 'first_name') → List[CarddavObject]

Get a list of contacts from one or more address books.

Parameters
  • address_book – the address book to search

  • query – a search query to select contacts

  • method – the search method, one of “all”, “name” or “uid”

  • reverse – reverse the order of the returned contacts

  • group – group results by address book

  • sort – the field to use for sorting, one of “first_name”, “last_name”, “formatted_name”

Returns

contacts from the address_book that match the query

khard.khard.prepare_search_queries(args)

Prepare the search query string from the given command line args.

Each address book can get a search query string to filter vcards befor loading them. Depending on the question if the address book is used for source or target searches different regexes have to be combined into one search string.

Parameters

args (argparse.Namespace) – the parsed command line

Returns

a dict mapping abook names to their loading queries, if the query is None it means that all cards should be loaded

Return type

dict(str:list(list(str)) or None)

khard.khard.generate_contact_list(args: Namespace) → List[CarddavObject]

TODO: Docstring for generate_contact_list.

Parameters

args – the command line arguments

Returns

the contacts for further processing

khard.khard.new_subcommand(selected_address_books: AddressBookCollection, input_from_stdin_or_file: str, open_editor: bool) → None

Create a new contact.

Parameters
  • selected_address_books – a list of addressbooks that were selected on the command line

  • input_from_stdin_or_file – the data for the new contact as a yaml formatted string

  • open_editor – whether to open the new contact in the edior after creation

khard.khard.add_email_subcommand(text: str, abooks: AddressBookCollection) → None

Add a new email address to contacts, creating new contacts if necessary.

Parameters
  • text – the input text to search for the new email

  • abooks – the addressbooks that were selected on the command line

khard.khard.birthdays_subcommand(vcard_list: List[CarddavObject], parsable: bool) → None

Print birthday contact table.

Parameters
  • vcard_list – the vcards to search for matching entries which should be printed

  • parsable – machine readable output: columns devided by tabulator ( )

khard.khard.phone_subcommand(search_terms: List[str], vcard_list: List[CarddavObject], parsable: bool) → None

Print a phone application friendly contact table.

Parameters
  • search_terms – used as search term to filter the contacts before printing

  • vcard_list – the vcards to search for matching entries which should be printed

  • parsable – machine readable output: columns devided by tabulator ( )

khard.khard.post_address_subcommand(search_terms: List[str], vcard_list: List[CarddavObject], parsable: bool) → None

Print a contact table. with all postal / mailing addresses

Parameters
  • search_terms – used as search term to filter the contacts before printing

  • vcard_list – the vcards to search for matching entries which should be printed

  • parsable – machine readable output: columns devided by tabulator ( )

khard.khard.email_subcommand(search_terms: List[str], vcard_list: List[CarddavObject], parsable: bool, remove_first_line: bool) → None

Print a mail client friendly contacts table that is compatible with the default format used by mutt. Output format:

single line of text
email_address   name    type
email_address   name    type
[...]
Parameters
  • search_terms – used as search term to filter the contacts before printing

  • vcard_list – the vcards to search for matching entries which should be printed

  • parsable – machine readable output: columns devided by tabulator ( )

  • remove_first_line – remove first line (searching for ‘’ …)

khard.khard.list_subcommand(vcard_list: List[CarddavObject], parsable: bool, fields: List[str]) → None

Print a user friendly contacts table.

Parameters
  • vcard_list – the vcards to print

  • parsable – machine readable output: columns devided by tabulator ( )

  • fields – list of strings for field evaluation

khard.khard.modify_subcommand(selected_vcard: CarddavObject, input_from_stdin_or_file: str, open_editor: bool, source: bool = False) → None

Modify a contact in an external editor.

Parameters
  • selected_vcard – the contact to modify

  • input_from_stdin_or_file – new data from stdin (or a file) that should be incorperated into the contact, this should be a yaml formatted string

  • open_editor – whether to open the new contact in the edior after creation

  • source – edit the source file or a yaml version?

khard.khard.remove_subcommand(selected_vcard: CarddavObject, force: bool) → None

Remove a contact from the addressbook.

Parameters
  • selected_vcard – the contact to delete

  • force – delete without confirmation

khard.khard.merge_subcommand(vcard_list, selected_address_books, search_terms, target_uid) → None

Merge two contacts into one.

Parameters
  • vcard_list (list(carddav_object.CarddavObject)) – the vcards from which to choose contacts for mergeing

  • selected_address_books (AddressBookCollection) – the addressbooks to use to find the target contact

  • search_terms (str) – the search terms to find the target contact

  • target_uid (str) – the uid of the target contact or empty

khard.khard.copy_or_move_subcommand(action: str, vcard_list: List[CarddavObject], target_address_books: AddressBookCollection) → None

Copy or move a contact to a different address book.

Parameters
  • action – the string “copy” or “move” to indicate what to do

  • vcard_list – the contact list from which to select one for the action

  • target_address_books – the target address books

khard.khard.main(argv: List[str] = sys.argv[1:]) → None
khard.object_type

Helper module for validating typed vcard properties

Module Contents
class khard.object_type.ObjectType

Bases: enum.Enum

string = 1
list_with_strings = 2
string_or_list_with_strings = 3
khard.version
Module Contents
khard.version.version = 0.16.0
1

Created with sphinx-autoapi

Khard is developed on Github where you are welcome to post bug reports, feature requests or join the discussion in general.

Bug reports

If you want to report a bug keep in mind that the following things make it much easier for maintainers to help:

  • update to the latest version if possible and verify the bug there

  • report the version(s) that are affected

  • state the python version you are using

  • if there are stack tracebacks post them with your bug report

  • supply a minimal configuration (config file and vcards) to reproduce the error

Feature requests

Please stick to the following standards when you open pull requests:

  • Khard’s development tries to follow Vincent’s branching model so normal pull requests should be made against the develop branch. Only important bug fixes that affect the current release should be opened against master.

  • Write “good” commit messages, especially a proper subject line. This is also explained in the Git book.

  • Format your python code according to PEP 8. Tools like pylint also help in writing maintainable code.

  • Khard has a test suite, please provide tests for bugs that you fix and also for new code and new features that are introduced.

  • Please verify all tests pass before sending a pull request, they will be checked again by travis but it might be a lot faster to check locally first: build status

Development

In order to start coding you need to fetch the develop branch:

git clone https://github.com/scheibler/khard
cd khard
python setup.py build  # to generate the version.py file
python -m kard --help
# or
pip3 install --editable .
khard --help

Alternatively you can use the setup.py script directly. If you want to isolate khard from your system Python environment you can use a virtualenv to do so.

Manpages

The following man pages are available for khard:

khard

Synopsis

khard [-c CONFIG] [--debug] [--skip-unparsable] SUBCOMMAND …

khard -h | --help

khard -v | --version

Description

khard is an address book for the Unix command line. It can read, create, modify and delete carddav address book entries. khard only works with a local store of VCARD files. It is intended to be used in conjunction with other programs like an email client, text editor, vdir synchronizer or VOIP client.

Options

-c CONFIG, --config CONFIG

configuration file (default: ~/.config/khard/khard.conf)

--debug

output debugging information

-h, --help

show a help message and exit

--skip-unparsable

skip unparsable vcards when reading the address books

-v, --version

show program’s version number and exit

Subcommands

The functionality of khard is divided into several subcommands. All of these have their own help text which can be seen with khard SUBCOMMAND --help.

Listing subcommands

These subcommands list information of several contacts who match a search query.

list

list all (selected) contacts

birthdays

list birthdays (sorted by month and day)

email

list email addresses

phone

list phone numbers

postaddress

list postal addresses

filename

list filenames of all matching contacts

Detailed display

These subcommands display detailed information about one subcommand.

show

display detailed information about one contact, supported output formats are “pretty”, “yaml” and “vcard”

export

DEPRECATED, use show --format=yaml instead

Modifying subcommands

These subcommands are used to modify contacts.

edit

edit the data of a contact, supported formats for editing are “yaml” and “vcard”

new

create a new contact

add-email

Extract email address from the “From:” field of an email header and add to an existing contact or create a new one

merge

merge two contacts

copy

copy a contact to a different addressbook

move

move a contact to a different addressbook

remove

remove a contact

source

DEPRECATED, use edit --format=vcard instead

Other subcommands
addressbooks

list all address books

template

print an empty yaml template

Configuration

See khard.conf(5).

khard.conf

Summary

The config file for khard is a plain text file with an ini-like syntax. Many options have a corresponding command line option. The only mandatory section in the config file is the definition of the available address books.

Location

The file is looked up at $XDG_CONFIG_HOME/khard/khard.conf. If the environment variable $XDG_CONFIG_HOME is unset ~/.config/ is used in its stead.

The location can be changed with the environment variable $KHARD_CONFIG or the command line option -c (which takes precedence).

Syntax

The syntax of the config file is ini-style dialect. It is parsed with the configobj library. The precise definition of the corresponding ini syntax can be found at https://configobj.readthedocs.io/en/latest/configobj.html#the-config-file-format .

It supports sections marked with square brackets and nested sections with more square brackets. Each section contains several keys with values delimited by equal signs. The values are typed and type checked.

Options

The config file consists of these four sections:

adressbooks

This section contains several subsections, but at least one. Each subsection can have an arbitrary name which will be the name of an addressbook known to khard. Each of these subsections must have a path key with the path to the folder containing the vcard files for that addressbook.

general

This section allows one to configure some general features about khard. The following keys are available in this section:

  • debug: a boolean indication weather the logging level should be set to debug by default (same effect as the --debug option on the command line)

  • default_action: the default action/subcommand to use if the first non option argument does not match any of the available subcommands

  • editor: the text editor to use to edit address book entries, if not given $EDITOR will be used

  • merge_editor: a command used to merge two cards interactively, if not given, $MERGE_EDITOR will be used

contact table

This section is used to configure the behaviour of different output listings of khard. The following keys are available:

  • display: which part of the name to use in listings; this can be one of first_name, last_name or formatted_name

  • group_by_addressbook: weather or not to group contacts by address book in listings

  • localize_dates: weather to localize dates or to use ISO date formats

  • preferred_email_address_type: labels of email addresses to prefer

  • preferred_phone_number_type: labels of telephone numbers to prefer

  • reverse: weather to reverse the order of contact listings or not

  • show_nicknames: weather to show nick names

  • show_uids: weather to show uids

  • sort: field by which to sort contact listings

vcard
  • private_objects: a list of strings, these are the names of private vCard fields (starting with X-) that will be loaded and displayed by khard

  • search_in_source_files: weather to search in the vcard files before parsing them in order to speed up searches

  • skip_unparsable: weather to skip unparsable vcards, otherwise khard exits on the first unparsable card it encounters

  • preferred_version: the preferred vcard version to use for new cards

Example

This is the example config file:

# example configuration file for khard version > 0.14.0
# place it under ~/.config/khard/khard.conf
# This file is parsed by the configobj library.  The syntax is described at
# https://configobj.readthedocs.io/en/latest/configobj.html#the-config-file-format

[addressbooks]
[[family]]
path = ~/.contacts/family/
[[friends]]
path = ~/.contacts/friends/

[general]
debug = no
default_action = list
# These are either strings or comma seperated lists
editor = vim, -i, NONE
merge_editor = vimdiff

[contact table]
# display names by first or last name: first_name / last_name / formatted_name
display = first_name
# group by address book: yes / no
group_by_addressbook = no
# reverse table ordering: yes / no
reverse = no
# append nicknames to name column: yes / no
show_nicknames = no
# show uid table column: yes / no
show_uids = yes
# sort by first or last name: first_name / last_name / formatted_name
sort = last_name
# localize dates: yes / no
localize_dates = yes
# set a comma separated list of preferred phone number types in descending priority
# or nothing for non-filtered alphabetical order
preferred_phone_number_type = pref, cell, home
# set a comma separated list of preferred email address types in descending priority
# or nothing for non-filtered alphabetical order
preferred_email_address_type = pref, work, home

[vcard]
# extend contacts with your own private objects
# these objects are stored with a leading "X-" before the object name in the vcard files
# every object label may only contain letters, digits and the - character
# example:
#   private_objects = Jabber, Skype, Twitter
# default: ,  (the empty list)
private_objects = Jabber, Skype, Twitter
# preferred vcard version: 3.0 / 4.0
preferred_version = 3.0
# Look into source vcf files to speed up search queries: yes / no
search_in_source_files = no
# skip unparsable vcard files: yes / no
skip_unparsable = no

Indices and tables

Khard is an address book for the Unix command line. It can read, create, modify and delete carddav address book entries. Khard only works with a local store of VCARD files. It is intended to be used in conjunction with other programs like an email client, text editor, vdir synchronizer or VOIP client.

Installation

Packaging status

Khard is available as a native package for some *nix distributions so you should check your package manager first. If you want or need to install manually you can use the release from PyPi:

pip3 install khard

If you want to help the development or need more advanced installation instructions see Contributing.

Configuration

The configuration file of khard is stored in the XDG conform config directory. If the environment variable $XDG_CONFIG_HOME is set, it is $XDG_CONFIG_HOME/khard/khard.conf and it defaults to ~/.config/khard/khard.conf otherwise.

An example configuration is provided in the source tree. It looks like this:

# example configuration file for khard version > 0.14.0
# place it under ~/.config/khard/khard.conf
# This file is parsed by the configobj library.  The syntax is described at
# https://configobj.readthedocs.io/en/latest/configobj.html#the-config-file-format

[addressbooks]
[[family]]
path = ~/.contacts/family/
[[friends]]
path = ~/.contacts/friends/

[general]
debug = no
default_action = list
# These are either strings or comma seperated lists
editor = vim, -i, NONE
merge_editor = vimdiff

[contact table]
# display names by first or last name: first_name / last_name / formatted_name
display = first_name
# group by address book: yes / no
group_by_addressbook = no
# reverse table ordering: yes / no
reverse = no
# append nicknames to name column: yes / no
show_nicknames = no
# show uid table column: yes / no
show_uids = yes
# sort by first or last name: first_name / last_name / formatted_name
sort = last_name
# localize dates: yes / no
localize_dates = yes
# set a comma separated list of preferred phone number types in descending priority
# or nothing for non-filtered alphabetical order
preferred_phone_number_type = pref, cell, home
# set a comma separated list of preferred email address types in descending priority
# or nothing for non-filtered alphabetical order
preferred_email_address_type = pref, work, home

[vcard]
# extend contacts with your own private objects
# these objects are stored with a leading "X-" before the object name in the vcard files
# every object label may only contain letters, digits and the - character
# example:
#   private_objects = Jabber, Skype, Twitter
# default: ,  (the empty list)
private_objects = Jabber, Skype, Twitter
# preferred vcard version: 3.0 / 4.0
preferred_version = 3.0
# Look into source vcf files to speed up search queries: yes / no
search_in_source_files = no
# skip unparsable vcard files: yes / no
skip_unparsable = no