# How to implement NormalKey hook

**URL:** <https://discuss.kakoune.com/t/how-to-implement-normalkey-hook/1618>\
**Category:** Help\
**Created:** [March 7, 2021, 2:36pm UTC](https://discuss.kakoune.com/t/how-to-implement-normalkey-hook/1618 "2021-03-07T14:36:08Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dmerejkowsky](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/dmerejkowsky/32/696_2.png) [@dmerejkowsky](https://discuss.kakoune.com/u/dmerejkowsky)\
**Post date:** [March 7, 2021, 2:36pm UTC](https://discuss.kakoune.com/t/how-to-implement-normalkey-hook/1618/1 "2021-03-07T14:36:08Z")

</div>

So, I’m trying to fix [Add more key bindings to the `*spelling*` buffer · Issue #11 · dmerejkowsky/kak-spell · GitHub](https://github.com/dmerejkowsky/kak-spell/issues/11)

Here’s what I’ve got so far:

First, the `kak-spell` script generates a `*spelling*` scratch buffer containing one selection per line, like this:

```auto
1.3,1.5 kak
3.1,3.9 PyEnchant

```

Then it calls the following commands:

```auto
hook buffer -group kak-spell NormalKey <ret> kak-spell-jump
hook buffer -group kak-spell NormalKey a 'kak-spell-add-from-spelling-buffer en_US'

```

The idea is that can you press ‘enter’ while in the `*spelling*` buffer to jump to the error, and ‘a’ to add the word from the line into the personal dictionary.

The kak-spell-jump command works fine:

```auto
define-command kak-spell-jump -hidden %{
  execute-keys '
    <esc>
    :edit -existing *spelling* <ret>
    gi <a-E> <esc>
    :set-option global kak_spell_current_error %val{selection} <ret>
    ga
    :select %opt{kak_spell_current_error} <ret>
  '
}

```

But I did not manage to make `kak-spell-add-from-spelling-buffer` work.

I tried this:

```auto
define-command -hidden kak-spell-add-from-spelling-buffer -params 1 %{
  execute-keys '
    <esc>
    gi <a-w> l Gl
  '
  nop %sh{ kak-spell --lang $1 add $kak_selection }

```

But the problem is that the `a` command still gets executed, and I end up with this:

```auto
1
    .3,1.5 kak
3.1,3.9 PyEnchant

```

which breaks everything else because the buffer is no longer formatted properly.

I’ve tried using `-draft` with `-save-reg` but to no avail.

What am I doing wrong ?

---

<div class="post-metadata">

**Author:** ![dmerejkowsky](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/dmerejkowsky/32/696_2.png) [@dmerejkowsky](https://discuss.kakoune.com/u/dmerejkowsky)\
**Post date:** [March 7, 2021, 2:46pm UTC](https://discuss.kakoune.com/t/how-to-implement-normalkey-hook/1618/2 "2021-03-07T14:46:19Z")

</div>

_Update_: I’ve also tried using `-draft`

```auto
define-command -hidden kak-spell-add-from-spelling-buffer -params 1 %{
  execute-keys -draft '
    <esc>
    gi <a-w> l Gl
    :set-option global kak_spell_word_to_add %val{selection} <ret>
  '

  nop %sh{ kak-spell --lang $1 add $kak_opt_kak_spell_word_to_add }
  execute-keys '
    <esc>
    ga
    :kak-spell<ret>
    :kak-spell-list<ret>
  '
}

```

But for some reason I end up adding several words instead of just the one from the line under the cursor …

---

<div class="post-metadata">

**Author:** ![dmerejkowsky](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/dmerejkowsky/32/696_2.png) [@dmerejkowsky](https://discuss.kakoune.com/u/dmerejkowsky)\
**Post date:** [March 9, 2021, 11:21am UTC](https://discuss.kakoune.com/t/how-to-implement-normalkey-hook/1618/3 "2021-03-09T11:21:01Z")

</div>

_Update_: I got the answer by looking at `plug.kak` implementation.

Things that helped:

One, using `<map buffer normal>` instead of `<hook buffer NormalKey>`. That way I don’t need to “undo” what pressing “a” does.

Two, using this pattern:

```auto
  evaluate-commands -save-regs t %{
    execute-keys -save-regs '' "gi <a-w> l Gl"
    set-register t %val{selection}
    evaluate-commands %sh{
         word="${kak_reg_t%:*}"
         # Now we are ready to add $word with for lang $1"
    }
}

```

The trick is we need to keep the `$1` param of the command, execute some keys to select the word from the line, and access the selection from the `execute-keys` call.

Note that this destroys whatever was on the `t` register.

Please tell me if you see a better way to do this.

---

<div class="post-metadata">

**Author:** ![prion](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/prion/32/404_2.png) [@prion](https://discuss.kakoune.com/u/prion)\
**Post date:** [March 9, 2021, 9:27pm UTC](https://discuss.kakoune.com/t/how-to-implement-normalkey-hook/1618/4 "2021-03-09T21:27:55Z")

</div>

It seems like you’ve already figured some of this out yourself but I’m just going to go through point by point.

First the `execute-keys` command takes a list of strings and execute all keys in them. Commonly you might see something like.  
`execute-keys <esc> <lt> x s ^.* <ret>`  
this is a list of space seperated strings. Comparatively,  
`execute-keys "<esc> <lt> x s ^.* <ret>"`  
is a single string where the whitespace is interpreted as the space key, or `<space>`.

The idiomatic way to write your `kak-spell-jump` is

```auto
define-command kak-spell-jump -hidden %{
  edit -existing *spelling*
  execute-keys gi <a-E>
  set-option global kak_spell_current_error %val{selection}
  execute-keys ga
  select %opt{kak_spell_current_error}
}

```

where commands are written as statements rather than as key presses with `:` and `<ret>`. As you figured out when your hook executes after the `a` key you’re in insert mode and the exec keys inserts all those spaces in your strings into the buffer as if you typed them.

I believe your `-save-regs` is unnecessary in that command. You can simply go.

```auto
exec gi <a-w> l Gl
eval %sh{
    word="$kak_val_selection"
    #...
}

```

One more point. Normally when you execute a command in kakscript you want to write it as `: edit ... <ret>` or `s abc<ret>` with the space between a key that creates a prompt (`:` or `s`). Doing this means the prompt entry is not added to the history to pollute it.

---

<div class="post-metadata">

**Author:** ![dmerejkowsky](https://discuss.kakoune.com/user_avatar/discuss.kakoune.com/dmerejkowsky/32/696_2.png) [@dmerejkowsky](https://discuss.kakoune.com/u/dmerejkowsky)\
**Post date:** [March 9, 2021, 9:50pm UTC](https://discuss.kakoune.com/t/how-to-implement-normalkey-hook/1618/5 "2021-03-09T21:50:53Z")

</div>

Wow. This was really useful feedback! The thing is, this kind of advice is really hard to find - maybe we should write a 'kak script best practices" somewhere …

Anyway, thanks a bunch!
