Skip to content

emo333/motioncoach-nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

motioncoach-nvim motioncoach

** ONLY BEGINNER LEVEL IS AVAILABLE Currently **

** Advanced Level coming soon! **

motioncoach-nvim is a Neovim plugin that watches your navigation and editing episodes and suggests more efficient Vim motions and techniques "WHEN YOU NEED THEM"

It is designed as a coach, not a tutor. Suggestions are:

  • contextual to user's live motions/commands
  • rate-limited by keystrokes and time frames
  • undo-aware
  • registers-aware
  • jumplist-aware
  • leveled (Beginner/Advanced)
  • All suggestions are delivered via NeoVim notification messages
motioncoach-DEMO.mp4

Coaching Levels

  • Selectable with Keymaps
  • Apply to Neovim session

Beginner Coaching (Level 1)

  • Count compression (10j, 5k)
  • Scroll suggestions (<C-d>, <C-u>)
  • Line landmarks (0, ^, $)
  • Large jump hints (gg, G)
  • Horizontal efficiency (w, b vs llll)

Advanced Coaching (Level 2)

Some Advanced Suggestions:

  • Key pattern analysis (via vim.on_key)
  • State-diff validation (cursor movement, operators, undo)
  • Text object suggestions:
    • ciw, di", ci(, dap, etc.
  • Register coaching:
    • "_d, "0p, "+y, "+p
  • Marks & jumplist coaching:
    • ma, 'a, `a
    • <C-o> / <C-i>
  • Yank history capture (local, in-memory)
  • Delimiter / surround coaching
  • Optional Treesitter textobject hints
  • Configurable plugin recommendations

Coaching Off (Level 0)

  • Coaching is disabled

Installation

lazy.nvim

{
  "emo333/motioncoach-nvim",
  config = function()
    require("motioncoach-nvim").setup({
      coachingLevel = 1, -- set to what you want to be your default
    })
  end
}

packer.nvim

use "emo333/motioncoach.nvim"

vim.pack (Neovim version 12+ only)

vim.pack.add({
  'https://github.com/emo333/motioncoach-nvim',
})
-- after add()
plugin1 = require('motioncoach-nvim')

Commands

:MotionCoachOff

:MotionCoachBeginner

:MotionCoachAdvanced

:MotionCoachLevel 0|1|2


Default Keymaps

  vim.keymap.set('n', '<leader>m', '[M]otion Coach -->')
  vim.keymap.set('n', '<leader>m0', function()
    require('motioncoach-nvim').set_level(0)
  end, { desc = 'MotionCoach Disable(0)' })
  vim.keymap.set('n', '<leader>m1', function()
    require('motioncoach-nvim').set_level(1)
  end, { desc = 'MotionCoach Beginner Level(1)' })
  vim.keymap.set('n', '<leader>m2', function()
    require('motioncoach-nvim').set_level(2)
  end, { desc = 'MotionCoach Advanced Level(2)' })

Configuration

motioncoach-nvim is configured via:

require("motioncoach-nvim").setup({
  -- options
})

Recommended Notification Configuration (Optional)

  • either add this to your snacks.nvim configuration or; add this as a plugin (eg. snacks.lua):
return {
  {
    "folke/snacks.nvim",
    config = function(_, opts)
      require("snacks").setup(opts)

      local original_notify = Snacks.notifier.notify
      ---@diagnostic disable-next-line: duplicate-set-field
      Snacks.notifier.notify = function(msg, level, notify_opts)
        notify_opts = notify_opts or {}

        -- Custom logic: If msg has "Motion" in it, set timeout to 3 seconds
        if msg:find("Motion") then
          notify_opts.timeout = 3000
        end

        return original_notify(msg, level, notify_opts)
      end
    end,
    opts = {
      notifier = {
        -- Set the maximum width for notifications before they wrap/expand
        width = { min = 40, max = 0.4 }, -- max can be a percentage of screen width
        -- Default is 3000ms (3 seconds)
        -- timeout = 5000, -- Increase this value (in milliseconds)
        -- Return true to keep the notification on screen
        keep = function(notif)
          local severity = vim.log.levels
          return notif.level == severity.ERROR or notif.level == severity.WARN
        end,
      },
      styles = {
        notification = {
          wo = {
            wrap = true, -- Enable line wrapping for long messages
          },
        },
      },
    },
  },
}

Privacy

By default, motioncoach-nvim:

❌ Does not capture command-line input (: / ?)

❌ Does not capture insert-mode keys

You can override these, if you desire, to get more Advance suggestions:

require("motioncoach-nvim").setup({
  captureCommandLineKeys = false,
  captureInsertModeKeys = false,
})

✅ Uses a small rolling ring buffer for key patterns

✅ Captures yank contents locally only

❌ Never writes anything to disk

❌ Never sends data

Yank History (Advanced Only)

motioncoach-nvim captures yank events via TextYankPost and stores them in a per-buffer yank ring.

  • This is used to suggest yank( or cut/delete )/register technique suggestions

  • Yank contents, captured for suggestions, never leave memory


Plugin Recommendations { WORK IN PROGRESS }

motioncoach.nvim can suggest plugins only after repeated evidence(within a Neovim session) and only in advanced mode.

  • Recommendations are:
    • Fully configurable

    • Evidence-based

    • Designed to evolve over time

Optional

  • Disable all plugin recommendations(Default):
require("motioncoach-nvim").setup({
  pluginRecommendations = {
    enabled = false,
  }
})
  • Disable a single recommendation:
require("motioncoach-nvim").setup({
  pluginRecommendations = {
    items = {
      surround = { enabled = false },
    }
  }
})

Provider Hook { FUTURE FEATURE}

For long-term evolution, you will be able to supply a provider function that decides recommendations dynamically:

require("motioncoach-nvim").setup({
  pluginRecommendations = {
    provider = function(evidenceCounters, context)
      if (evidenceCounters.surroundLikeEvidenceCount or 0) >= 6 then
        evidenceCounters.surroundLikeEvidenceCount = 0
        return "Plugin idea: consider mini.surround or nvim-surround."
      end
      return nil
    end
  }
})
  • The provider would run before built-in defaults.

About the Author (emo333)

  • I am not a professional programmer.
  • I have been programming most of my life; either as side duties inherent to work or as hobby at home.
  • Vim/NeoVim/Lua are all new to me ( started delving into these around November 2025 ).
  • I started this project based on my own desire to have something "inside" NeoVim to remind/assist/suggest/coach me learning Vim motions.
  • I used ai to assist me developing this. But just when I needed to get over a hump.

Contributions

Hell yeah! Bring em!


License

MIT(ch) <-- I crack me up ;)


About

motioncoach-nvim is a pure Lua Neovim plugin that watches your navigation and editing episodes and suggests more efficient Vim motions and techniques.

Topics

Resources

Stars

Watchers

Forks

Contributors

Languages