TypedHandlerDelegate not called each character
I have a problem where `TypedHandlerDelegate` is called only for the first character in a word.
Reading through the other topics in this forum, one person recommended extending `TypedActionHandlerBase` which does work, but the extension point is scheduled for removal.
The deprecation warning says to use `TypedHandlerDelegate`, but the two are not equivalent. `TypedActionHandlerBase` is called for every character except enter, and TypedHandleDelegate only for the first character
Is there a way to get every character typed in `TypeHandlerDelegate`, or is there another extension point to use?
A minimal Example:
class EndWordIndenter : TypedHandlerDelegate() {
private val logger = Logger.getLogger(this.className)
override fun newTypingStarted(c: Char, editor: Editor, context: DataContext) {
logger.info("newTypingStarted('$c')")
}
override fun beforeCharTyped(c: Char, project: Project, editor: Editor, file: PsiFile, fileType: FileType): Result {
logger.info("beforeCharTyped('$c')")
return Result.CONTINUE
}
override fun charTyped(c: Char, project: Project, editor: Editor, file: PsiFile): Result {
logger.info("charTyped('$c')")
return Result.CONTINUE
}
}
Typing kill ownr endm
Logs:
newTypingStarted('k')
beforeCharTyped('k')
charTyped('k')
newTypingStarted(' ')
beforeCharTyped(' ')
charTyped(' ')
newTypingStarted('o')
beforeCharTyped('o')
charTyped('o')
newTypingStarted('e')
beforeCharTyped('e')
charTyped('e')
newTypingStarted('e')
beforeCharTyped('e')
charTyped('e')
With TypedActionHandlerBase
class TypedActionEndWordIndenter(handler: TypedActionHandler) : TypedActionHandlerBase(handler) {
private val logger = Logger.getLogger(this.className)
override fun execute(editor: Editor, c: Char, context: DataContext) {
super.myOriginalHandler?.execute(editor, c, context)
logger.info("Character '$c' typed")
}
}
Typing the same code: kill ownr endm
Logs:
Character 'k' typed
Character 'i' typed
Character 'l' typed
Character 'l' typed
Character ' ' typed
Character 'o' typed
Character 'w' typed
Character 'n' typed
Character 'r' typed
Character 'e' typed
Character 'n' typed
Character 'd' typed
Character 'm' typed
Running both extension points at the same time yields:
TypedHandlerDelegate - newTypingStarted('k')
TypedHandlerDelegate - beforeCharTyped('k')
TypedHandlerDelegate - charTyped('k')
TypedActionHandler - Character 'k' typed
TypedActionHandler - Character 'i' typed
TypedActionHandler - Character 'l' typed
TypedActionHandler - Character 'l' typed
TypedHandlerDelegate - newTypingStarted(' ')
TypedHandlerDelegate - beforeCharTyped(' ')
TypedHandlerDelegate - charTyped(' ')
TypedActionHandler - Character ' ' typed
TypedHandlerDelegate - newTypingStarted('o')
TypedHandlerDelegate - beforeCharTyped('o')
TypedHandlerDelegate - charTyped('o')
TypedActionHandler - Character 'o' typed
TypedActionHandler - Character 'w' typed
TypedActionHandler - Character 'n' typed
TypedActionHandler - Character 'r' typed
TypedHandlerDelegate - newTypingStarted('e')
TypedHandlerDelegate - beforeCharTyped('e')
TypedHandlerDelegate - charTyped('e')
TypedActionHandler - Character 'e' typed
TypedActionHandler - Character 'n' typed
TypedActionHandler - Character 'd' typed
TypedActionHandler - Character 'm' typed
UPDATE: Added checkAutoPopup
and it still does not work. That method is called even less often, even with a popup.
override fun checkAutoPopup(charTyped: Char, project: Project, editor: Editor, file: PsiFile): Result {
logger.info("checkAutoPopup('$charTyped')")
return Result.CONTINUE
}
Please sign in to leave a comment.
Hi Dan,
It should be called for each character. Maybe another handler stops your handler?
Try adding
order="first"
in your extension registration. If it doesn't help, try to debug to find out if there actually is a stopping handler, and if it is registered as first too and has an ID, you can push yours before it withorder="first,before xyz"
.So I registered my TypedHandlerDelegate as first, but CompletionAutoPopup was called first, so I added
order="first, before completionAutoPopup".
But it made no difference.That had my handler called first, but it still was not receiving every letter when typing.
It does NOT work when the completion popup window is visible. I have to press escape, to clear autocomplete, and then I can type the final character and then each method is called on the character.
I overwrote
checkAutoPopup,
but it does not get called when popup is up either.TypedActionHandler works perfectly, but will be removed in the future according to the docs.
Hi,
The completion popup was a missing part to reproduce it.
Could you please describe your use case?
The reason I would like to check the character typed is because I want to detect when the final letter of certain commands are typed and reformat the code in between the start and end keywords.
An example would be typing the
i
inendi
So on typing
i
, I want the code betweendoif
andendi
to indent to become:There may be a better extension point all together to support this, but I am not aware of one. I was not able to use words for the brace matching.
Hi Dan,
Indeed, this solution seems hacky and there is a better API for this case. You can take a look at the Formatter docs, especially this section: https://plugins.jetbrains.com/docs/intellij/code-formatting.html#building-the-block-tree
Implementing it properly will auto indent your code while pressing enter.