# Profiles

Contents

- Description
  - Supported Profile Types
    - Language Profiles
  - Profile Selection
- Standard Directives
  - The Include Directive
  - The Assign Directive
  - The AssignDefault Directive
  - The IfVar Directive
  - The IfNotVar Directive
  - The BeginVariables Directive
  - The EndVariables Directive
  - The ListVariables Directive
  - The EndIf Directive
  - The Else Directive

## Description

A profile is an activatable group of settings which explicitly override the ones that were established via command line options, the configuration file (`brltty.conf`), the preferences file (`brltty.prefs`), etc when BRLTTY was invoked. Profiles must be placed in the `/etc/brltty/Profiles/` directory (see Local Customization for more details).

A profile must be encoded in UTF-8. Blank lines are ignored. If the first non-whitespace character of a line is `#` then that line is a comment and is ignored. The Standard Directives are supported. All other lines specify the settings that are to be overridden, and must be in the form:

    name value

Each type of profile has the following properties:

- A specific group of settings that it can override.
- Its own file extension.
- Its own selector within BRLTTY's Profiles submenu.
- Its own SET_*_PROFILE command for direct selection (see Profile Selection).

### Supported Profile Types

#### Language Profiles

A language profile must have the `.lpf` file extension. It can override the following settings:

- locale
- speech-driver
- speech-parameters
- text-table
- contraction-table

For example, a profile for the German language might look like this:

    locale de_DE.UTF-8
    speech-driver es
    speech-parameters voice=de,maxrate=300
    text-table de
    contraction-table de-g2

All of the speech driver parameters must be specified on a single line, and be separated from one another by a comma (`,`).

### Profile Selection

Each type of profile has a selector within BRLTTY's Profiles submenu. The selector for a given profile type allows for setting that type of profile either to `off` (which means "no profile") or to any of the files in the `/etc/brltty/Profiles/` directory which have the file extension for that type of profile. The file names are sorted alphabetically.

If you'd like to select a profile directly (rather than use the Profiles submenu) then you can define key bindings for the appropriate `SET_*_PROFILE` command. For example, if you'd like to directly select your language profile then you'd define bindings for the `SET_LANGUAGE_PROFILE` command. You may add your bindings either to the keyboard table that you're using or to the key table for your braille device. Except for a few examples below, exactly how to do this is beyond the scope of this document (see Key Tables for details).

One approach is to define a single binding which involves a routing key. For example:

    bind Key1+Key2+RoutingKey SET_LANGUAGE_PROFILE

Using this paradigm, the leftmost routing key means to use no language profile, and the next few routing keys select each of your language profiles in the same order as they appear within the Language selector of the Profiles submenu.

Another approach is to define a specific binding for each language profile. For example:

    bind Key1+Key2 SET_LANGUAGE_PROFILE+0
    bind Key1+Key3 SET_LANGUAGE_PROFILE+1
    bind Key2+Key3 SET_LANGUAGE_PROFILE+2
    bind Key1+Key2+Key3 SET_LANGUAGE_PROFILE+3

Using this paradigm, the binding for `+0` (Key1+Key2) means to use no language profile, and the bindings for `+1` (Key1+Key3), `+2` (Key2+Key3), etc select each of your language profiles in the same order as they appear within the Language selector of the Profiles submenu.

A practical approach, which would make it easy to remember the bindings, might be to use a keyboard table, and to use a simple key combination plus a meaningful letter for each language name. Let's say that your primary language is English, and that you also use French and German. In this case, your default settings (no profile) would be for English, and you'd create french.lpf for French and german.lpf for German. You could then define a set of bindings which use `e` for English, `f` for French, and `g` for German. For example:

    bind ShiftLeft+ShiftRight+!e SET_LANGUAGE_PROFILE+0
    bind ShiftLeft+ShiftRight+!f SET_LANGUAGE_PROFILE+1
    bind ShiftLeft+ShiftRight+!g SET_LANGUAGE_PROFILE+2

The `+1` binding would activate `french.lpf` and the `+2` binding would activate `german.lpf` because that's how the profile name list would be sorted. If, however, you choose to use the native language names then you'd have `deutsch.lpf` for German and `français.lpf` for French. In this case, you'd need a different set of bindings because `deutsch.lpf` (for German) sorts before `français.lpf` (for French):

    bind ShiftLeft+ShiftRight+!e SET_LANGUAGE_PROFILE+0
    bind ShiftLeft+ShiftRight+!d SET_LANGUAGE_PROFILE+1
    bind ShiftLeft+ShiftRight+!f SET_LANGUAGE_PROFILE+2

When adding the bindings to a key table, they should most likely be defined within the default context. The best way to ensure this is to add them at the very end of the appropriate key table or subtable, and to add the `context default` statement just before them. For example:

    context default
    bind Key1+RoutingKey SET_LANGUAGE_PROFILE

If you'd like your additional binding definitions to survive a BRLTTY reinstall then you should use a customized key table or subtable (see Local Customization) that includes the provided one, and then defines your additiional bindings. Let's say that you'd like to add your bindings to the `laptop` keyboard table (`laptop.ktb`). Create a file with the same name - `laptop.ktb` - in the `/etc/xdg/brltty/` directory, and, with an editor, make it look like this:

    include laptop.ktb
    context default
    bind Key1+Key2+RoutingKey SET_LANGUAGE_PROFILE

## Standard Directives

### The Include Directive

    include file # comment

Use this directive to include the content of another file. It is recursive, which means that an included file can itself include yet another file. Care must be taken to ensure that an "include loop" is not created.

file
  The file to be included. It may be either a relative or an absolute path. If relative, it is anchored at the directory containing the including file.

### The Assign Directive

    assign variable value

Use this directive to create or update a variable associated with the current nesting level (see The BeginVariables Directive) of the current include level (see The Include Directive). The variable is visible to the current and to lower include levels, but not to higher include levels.

variable
  The name of the variable. If the variable doesn't already exist at the current include level then it is created.
value
  The value that is to be assigned to the variable. If it's not supplied then a zero-length (null) value is assigned.

Examples:

    assign nullValue
    assign shortValue word
    assign longValue a\svalue\swith\sspaces
    assign IndirectValue \{variableName}

### The AssignDefault Directive

    assignDefault variable value

Use this directive to assign a default value to a variable associated with the current nesting level (see The BeginVariables Directive) of the current include level (see The Include Directive). It's functionally equivalent to:

    ifNotVar variable assign variable value

See The Assign Directive and The IfNotVar Directive for more details.

variable
  The name of the variable. If the variable doesn't already exist at the current include level then it is created. If it does already exist then it is not modified.
value
  The value that is to be assigned to the variable if it doesn't already exist. If it's not supplied then a zero-length (null) value is assigned.

Examples:

    assignDefault format plain\stext

### The IfVar Directive

    ifVar variable directive

Use this directive to only process one or more directives if a variable exists.

variable
  The name of the variable whose existence is to be tested.
directive
  The directive that is to be conditionally processed. It may contain spaces. This operand is optional. If it isn't supplied then this directive applies to all subsequent lines until The EndIf Directive or The Else Directive that is at the same conditional nesting level.

Examples:

    ifVar var1 ifVar var2 assign concatenation \{var1}\{var2}

### The IfNotVar Directive

    ifNotVar variable directive

Use this directive to only process one or more directives if a variable doesn't exist.

variable
  The name of the variable whose existence is to be tested.
directive
  The directive that is to be conditionally processed. It may contain spaces. This operand is optional. If it isn't supplied then this directive applies to all subsequent lines until The EndIf Directive or The Else Directive that is at the same conditional nesting level.

Examples:

    ifNotVar var1 assign var1 default\svalue

### The BeginVariables Directive

    beginVariables

Use this directive to open a new variable nesting level. The Assign Directive) will define variables at this new nesting level, and will hide variables with the same names in any previous nesting level. These variables will remain defined until The EndVariables Directive that is at the same variable nesting level.

Examples:

    assign x 1
    # \{x} evaluates to 1
    beginVariables
    # \{x} still evaluates to 1
    assign x 2
    # \{x} now evaluates to 2
    endVariables
    # \{x} evaluates to 1 again

### The EndVariables Directive

    endVariables

Use this directive to close the current variable nesting level. See The BeginVariables Directive for details.

### The ListVariables Directive

    listVariables

Use this directive to list all of the currently defiined variables. It can be helpful when debugging.

### The EndIf Directive

    endIf

Use this directive to terminate the current conditional nesting level.

Examples:

    ifVar x
       These lines will be processed if a variable named x exists.
    endIf

### The Else Directive

    else

Use this directive to negate the test associated with the current conditional nesting level.

Examples:

    assign x some\svalue
    ifVar x
       These lines will be processed.
    else
       These lines won't be processed.
    endIf