Fine-tuning NSTextField auto completion

1k views Asked by At

I'm using NSControlTextEditingDelegate to auto complete what's typed in a NSSearchField with custom suggestions I generate. complete: message is sent to field editor when text is changed.

Now I'd like to fine-tune the behavior of auto-completion and have it working exactly as Google search text field works in Safari:

  1. When two or more words (separated by spaces) are typed in NSTextField, location for NSRange passed in control:textView:textView:completions:forPartialWordRange: indexOfSelectedItem: starts after the last space typed.

    This means that if user types "San Fran" and Google APIs returns "San Francisco", choosing it from auto-complete list NSTextField value is replaced with "San San Francisco".

    A possible workaround consist in rebuilding NSArray containing completion and returning only the suffix of the actual suggestions, depending on charRange.location. This looks crappy (because auto-completion list now shows only part of the completion string), so I want to have NSTextField ignore spaces when requesting auto-completion.

  2. Choosing an auto completion from list, default NSSearchField action is not sent. At the moment user need to choose an auto completion and then press enter to trigger search.

1

There are 1 answers

1
Zoë Peterson On BEST ANSWER

You can do this using a custom field editor rather than relying entirely on the delegate callbacks.

1) Override rangeForUserCompletion and adjust the returned value so it includes the text past the whitespace.

2) Override insertCompletion:forPartialWordRange:movement:isFinal and if isFinal is checked, do your accept processing.

Step (1) above will fix the range. If you're also setting the index in completionsForPartialWordRange to fill the edit (or leaving it at the default 0), the spacebar, along with '/' and '.' will accept the currently selected line, even if what the user wanted was to just keep typing. To work around that, in insertCompletion:forPartialWordRange:movement:isFinal, if isFinal is true, check [NSApp currentEvent] for those characters, and if they're found, skip out without processing it or calling super.