m4xshen / hardtime.nvim

Establish good command workflow and quit bad habit
MIT License
1.35k stars 27 forks source link

Wrong hint message for `xi` #77

Closed nullromo closed 3 months ago

nullromo commented 7 months ago

Describe the bug In normal mode, pressing xi will trigger a notification with the following message: Use a instead of li. Well, I didn't use li so this message makes no sense.

Config options

{ disable_mouse = false, restriction_mode = 'hint' }

To Reproduce Steps to reproduce the behavior:

  1. Open a file.
  2. Press xi.
  3. Look at the message.

Expected behavior The message should reflect the keys that were actually pressed.

Additional context It looks to me like the source of this message is the following hint:

["[^fFtT]li"] = {
    message = function()
        return "Use a instead of li"
    end,
    length = 3,
}

However, I don't know how this could have triggered while using the x key.

Other side notes An actual hint in this case would be Use s instead of xi because s does the same function as xi. Maybe this should be added as a new hint... I should see if I can do this and submit a PR.

nullromo commented 7 months ago

I tried adding a custom hint like this

hints = {
    ['xi'] = {
        message = function()
            return 'Use s instead of xi'
        end,
        length = 2,
    },
},

but I can't get it to trigger. I tried with length = 1, length = 2, and length = 3.

Instead of getting my custom message, I just get the same old message. Additionally, I tried adding another hint:

hints = {
    ['xx'] = {
        message = function()
            return 'Do not use x multiple times consecutively'
        end,
        length = 2,
    },
},

but I cannot get this one to trigger either.

kang8 commented 7 months ago

This is because x same as dl. So pressing x is equivalent to pressing dl.

When you press xi, it is ultimately interpreted as xdli, which(dli) conforms to the ["[^fFtTlt]" rule, so it matches.

You can use follow script to listener every input key

vim.on_key(function(k)
  local mode = vim.fn.mode()
  if mode == 'i' or mode == 'c' or mode == 'R' then
    return
  end

  local key = vim.fn.keytrans(k)
  vim.notify('k is: ' .. k .. ' , key is: ' .. key, vim.log.levels.WARN, { title = 'test' })
end)
nullromo commented 7 months ago

It's weird that x actually "presses" dl rather than just doing the underlying operation. For example, the following hint is kind of amusing:

['dl'] = {
    message = function()
        return 'Use x instead of dl'
    end,
    length = 2,
},

Each time you press x, it tells you to use x instead 🙃

So I guess hardtime.nvim can't actually distinguish which keypresses are "real" user keypresses. When I try your test function, I get the following notifications:

2024-02-02T09:15:03 test WARNING WARN WARNING | test: k is: x , key is: x
2024-02-02T09:15:03 test WARNING WARN WARNING | test: k is: d , key is: d
2024-02-02T09:15:03 hardtime WARNING WARN WARNING | hardtime: Use x instead of dl
2024-02-02T09:15:03 test WARNING WARN WARNING | test: k is: l , key is: l

This just feels like a very strange behavior of neovim to me.

m4xshen commented 7 months ago

@nullromo hardtime.nvim uses vim.on_key function to listen to key input. This behavior is expected based on the docs (see :h vim.on_key)

    {fn} will receive the keys after mappings have been evaluated

I currently haven't found other way to listen to the raw key input.

nullromo commented 7 months ago

Thanks for the reply. Looks like this is a feature missing from neovim that may (eventually) be added: https://github.com/neovim/neovim/issues/15527.

In that case, feel free to close this issue as I feel it's a little too far out of the scope of hardtime at the moment.

m4xshen commented 3 months ago

Looks like this is a feature missing from neovim that may (eventually) be added: https://github.com/neovim/neovim/issues/15527.

@nullromo Thanks for providing this information. I just update the code to use the latest api and now this issue is resolved! Btw the api requires Neovim >= 0.10