Packages / auto-spacing

VoiceCode has a flexible "auto spacing" system. By "auto spacing" we mean determining whether or not to add a space before, after, or in-between commands or words.

Background

In VoiceCode it is important to keep in mind that everything you say is parsed and sorted to determine which command(s) should process the text. Even if you just say some random words that are not "commands" - those words will be caught by a fallback command.

For instance, when you say "hello there", VoiceCode parses the phrase as follows:

{
  command: "core:literal", 
  arguments: ["hello", "there"]
}

By default, the "core:literal" command will join each of its arguments with a space, and then type them onto the screen. In a way, that could be considered "auto spacing", however that is not the type of "auto spacing" we are discussing here. Auto spacing has to do with spaces between commands.


Take the following two commands as examples:

cram <text> will insert camelCasedText

snake <text> will insert snake_cased_text

Without auto spacing if you said "cram hello there snake my friend", it should type out helloTheremy_friend.

In order to get more intuitive results, we could tell VoiceCode that we want a space inserted between those commands. To achieve this, we can set up auto spacing rules on any commands by adding a parameter called autoSpacing.

Options for autoSpacing

autoSpacing takes a string value, or a function that returns a string. Within the string it defines the spacing before the command and after the command, with a space between the two words.

The possible values of each option are:

  • normal
  • soft
  • always
  • never

So for a command that should have normal spacing before and after you would set it like:

autoSpacing: 'normal normal'

Whenever VoiceCode processes a command, it looks at the auto spacing rules for that command and the surrounding commands to determine where to add spaces. The precedence is as follows (order does not matter):

  • normal + normal → space
  • normal + soft → space
  • soft + soft → no space
  • always + * → space
  • never + * → no space
  • never + always → no space (this is a tiebreaker)
  • everything else → no space

So as another example, if we had a command that never wanted a space before but always after, we could define it as follows:

autoSpacing: 'never always'

Dynamic Rules

The basic settings above generally handle most cases, but there are other cases where the decision whether or not to add a space needs to rely on context. For these cases, we can define a callback function that returns a decision. This callback function is called with the same context as the "action" function of each command - which means it has full access to the Actions API so it can find any information it needs such as the current application, current window name, contents of the clipboard, etc.

So if you wanted the "snake" command to have regular auto spacing in most applications, but no spacing in your text editor for coding you could set its parameters as follows:

autoSpacing: function(input) {
  if (this.currentApplication() === "My Editor") {
    return "never never"
  }
  return "normal normal"
}

Notice you also have access to the input which is the arguments to the command (in this case whatever you spoke after the command's speakable name). So you can get as fancy as you like with these rules.

Multi-Phrase Auto Spacing

The above examples apply to commands when they are spoken within the same phrase. We can also set similar settings for commands that span multiple phrases. For example if I said "cram hello there" <pause> "snake my friend", then the two commands would be processed as separate phrases, and often we want auto spacing to behave differently across multiple phrases then we do when you say it all fluidly as a single phrase.

For this we use another parameter multiPhraseAutoSpacing, which takes all the exact same arguments / options. For example:

multiPhraseAutoSpacing: 'normal normal'

Overwriting Defaults

Sometimes different people want the defaults to be different for certain commands. To change the defaults simply do something like:

Commands.update('some-package:some-command', {
  autoSpacing: 'never never'
  multiPhraseAutoSpacing: 'never never'
})

Or to just remove the default settings from a certain command

Commands.update('some-package:some-command', {
  autoSpacing: null
  multiPhraseAutoSpacing: null
})

Canceling Auto-Spacing State

It would be a quite annoying if you were typing with VoiceCode, then you manually clicked the mouse or pressed some keyboard keys and VoiceCode tried to auto-space based on the previous context which is now invalid. Instead it should cancel the old context so it can start fresh. To achieve this, VoiceCode monitors certain events so it can reset its state. Currently it resets auto spacing context in the following scenarios:

  • foreground application changes
  • user clicks the mouse
  • arrow keys are pressed or any text is typed

If you need to reset auto-spacing state from custom code, do

HistoryController.cancelAutoSpacing()

More Examples

Many of the built-in commands have much more complex rules for determining auto spacing, so if you are interested - it would be a good idea to look through existing packages and see how the commands are implemented.

results matching ""

    No results matching ""