diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..926ccaa
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+doc/tags
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..19194b9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,162 @@
+
+# DelayTrain
+_Train yourself to stop repeating keys... gently_
+
+[How does it work?](#how-does-it-work) • [Installation](#installation)
+• [Configuration](#configuration) • [Commands](#commands)
+• [Contributing](#contributing)
+
+TODO: quick demo gif ~/Videos/delaytrain.gif
+
+
+## "Stop using arrow keys!" "Stop using hjkl!"
+
+If you're familiar with the (neo)vim community you've probably heard this a
+million times. The whole point of vim is to seamlessly navigate where you
+need to go without constantly repeating keypresses. Why press `j` ten times
+when you can press `10j`, or `}`, or search.
+
+But if you've been using vim for a while this may be a harder habit to break.
+You try to stop relying on this type of navigation but you only catch
+yourself after the fact. You might chastize yourself and move on but the
+habit stays there.
+
+Most recommendations involve disabling these keys altogether, but this only
+increases frustration. Sometimes your next position is directly above and
+the quickest option is to press `k`. This might help in the long run but
+it's incredibly annoying and hard to stick with.
+
+That's where DelayTrain comes in.
+
+DelayTrain will still let you use these keybindings, but it only punishes
+you when you _keep_ hitting them. If you need to navigate directly below,
+you can still do that. But if you need to navigate 5 lines below using
+repeated keypresses, DelayTrain will gently remind you that there might
+be a better way by stopping the keypress from working for a certain
+amount of time.
+
+And DelayTrain doesn't just work for hjkl. Mappings are included to
+prevent repeated arrow key presses and you can configure delaytrain to
+prevent anything else like `w` or `b`.
+
+## How does it work?
+
+DelayTrain takes two configurable values, `delay_ms` and `grace_period`.
+
+When you first hit a configured keypress (like `j`), the `delay_ms` timer
+starts. You are given a `grace_period` of repeated keypresses within the
+`delay_ms` timer before the key stops working. Once the `delay_ms` timer
+ends, everything is reset.
+
+### Examples
+
+We'll use a few tables to show how this works. Assume the follwing:
+
+* `delay_ms = 1000`
+* `grace_period = 2`
+
+By default the `grace_period` is 1, but setting it to 2 allows you to
+press the key twice before it stops working.
+
+| Keypress | Time | Grace Period | Does it work? |
+| ---------- | ----------- | ------------ | ------------- |
+| `j` | 0ms | 1 | Yes |
+| `j` | 200ms | 2 | Yes |
+| `j` | 500ms | 3 | No |
+| `j` | 1000ms | 1 | Yes |
+
+Each keypress starts a dedicated `delay_ms` timer and has a dedicated
+`grace_period`. So if you're trying to navigate down and to the left,
+this still works.
+
+| Keypress | Time | Grace Period | Does it work? |
+| ---------- | ----------- | ------------ | ------------- |
+| `j' | 0ms | 1 | Yes |
+| `j' | 200ms | 2 | Yes |
+| `h' | 500ms | 1 | Yes |
+| `j' | 700ms | 3 | No |
+| `h' | 1000ms | 2 | Yes |
+| `j' | 1200ms | 1 | Yes |
+| `h' | 1400ms | 3 | No |
+| `h' | 1500ms | 1 | Yes |
+
+
+## Installation
+
+Install with [vim-plug](https://github.com/junegunn/vim-plug):
+
+```vim
+Plug '[TODO GITHUB NAME]/delaytrain.nvim'
+```
+
+or with [packer](https://github.com/wbthomason/packer.nvim):
+
+```lua
+ -- Delay repeat execution of certain keys
+ use '[TODO GITHUB NAME]/delaytrain.nvim'
+```
+
+For the default setup (see defaults below), you can simply place the following
+into your `init.lua`:
+
+```lua
+require('delaytrain').setup()
+```
+
+## Configuration
+
+You can configure all DelayTrain settings through the `setup()` function. The
+default DelayTrain mappings are included below:
+
+```lua
+ require('delaytrain').setup {
+ delay_ms = 1000, -- How long repeated usage of a key should be prevented
+ grace_period = 1, -- How many repeated keypresses are allowed
+ keys = { -- Which keys (in which modes) should be delayed
+ ['nv'] = {'h', 'j', 'k', 'l'},
+ ['nvi'] = {'', '', '', ''},
+ },
+ }
+```
+
+### Mappings
+
+The keys option allows you to delay different keypresses in different modes.
+This takes the following KV pair:
+
+```lua
+ ['list_of_applicable_modes'] = {'keys', 'you', 'want', 'delayed'},
+```
+
+Modes can be added based on their short-names (ex: normal is 'n', insert is
+'i') and multiple modes can be added to a single keymap.
+
+This option ties into a call to `vim.keymap.set()`, so mode short-names and
+key names should match what is possible in that function.
+
+### Options
+
+Global options can be modified to change delay/grace period settings on the
+fly:
+
+* `g:delaytrain_delay_ms`
+* `g:delaytrain_grace_period`
+
+## Commands
+
+The following commands allow you to turn DelayTrain on and off without
+calling `setup()` again:
+
+* `:DelayTrainEnable`
+* `:DelayTrainDisable`
+* `:DelayTrainToggle`
+
+By default, DelayTrain is turned on when the `setup()` function is called.
+
+## Contributing
+
+This has been tested on my personal and work machines using nvim-nightly and
+[Neovide](https://github.com/neovide/neovide). This is a REALLY SMALL plugin
+so while there shouldn't be a lot of issues it's entirely possible I missed
+something. I'm also brand new to plugin development so if you notice anything
+off please feel free to open up an issue or send me a PR!
diff --git a/doc/delaytrain.txt b/doc/delaytrain.txt
new file mode 100644
index 0000000..6b19edd
--- /dev/null
+++ b/doc/delaytrain.txt
@@ -0,0 +1,118 @@
+*delaytrain.txt* DelayTrain
+*delaytrain.nvim*
+
+Author: James Ford
+Version: 1.0.0
+Homepage: <>
+
+=============================================================================
+INTRODUCTION *delaytrain*
+
+When learning how to use Vim keybindings, sometimes it's helpful to avoid
+repetitive keypresses. For example, repetitive use of hjkl or arrow keys can
+often be replaced with a numeric prefix, or an even better key to navigate
+exactly where you want to go.
+
+To help train your muscle memory, most people suggest un-mapping these keys
+to avoid using them completely. But there are certain cases where hjkl may
+be necessary and another key combination would be overkill.
+
+DelayTrain helps train this muscle memory by preventing a keypress from
+being used after a certain amount of repeated usage inside a timeframe,
+rather than disabling the key completely. This way you can still go about
+your work with a gentle reminder that there might be a better way to do
+what you want.
+
+==============================================================================
+USAGE *delaytrain-usage*
+
+Most people will be training with hjkl and arrow keys, so for a default setup
+you can simply run:
+>
+ require('delaytrain').setup()
+<
+
+==============================================================================
+CONFIGURATION *delaytrain-configuration*
+
+For more granular configuration and additional keymaps, you can pass the
+following configuration (default settings included):
+>
+ require('delaytrain').setup {
+ delay_ms = 1000, -- How long repeated usage of a key should be prevented
+ grace_period = 1, -- How many repeated keypresses are allowed
+ keys = { -- Which keys (in which modes) should be delayed
+ ['nv'] = {'h', 'j', 'k', 'l'},
+ ['nvi'] = {'', '', '', ''},
+ },
+ }
+<
+Keep in mind that the `delay_ms` timer starts on the FIRST keypress and not the
+final `grace_period` keypress. For example (with default settings) if you hit j,
+the timer starts immediately. If you hit j again after 500ms, the key will not
+work. If you wait ANOTHER 500ms and hit j again, it will work. Likewise, if
+you hit j, wait 1000ms, and hit j again, both keypresses will work.
+
+With an increased `grace_period`, you can hit a key `grace_period` amount of times
+inside `delay_ms` before it stops working.
+
+`grace_period` and `delay_ms` only affect the current key being pressed. With
+the default settings, if you hit j and then hit k after 500ms, both keypresses
+will work. If you wait another 200ms and hit j again, the keypress will not
+work.
+
+------------------------------------------------------------------------------
+MAPPINGS *delaytrain-mappings*
+
+The keys option allows you to delay different keypresses in different modes.
+This takes the following KV pair:
+>
+ ['list_of_applicable_modes'] = {'keys', 'you', 'want', 'delayed'},
+<
+Modes can be added based on their short-names (ex: normal is 'n', insert is
+'i') and multiple modes can be added to a single keymap.
+
+This option ties into a call to |vim.keymap.set()|, so mode short-names and
+key names should match what is possible in that function.
+
+
+------------------------------------------------------------------------------
+OPTIONS *delaytrain-options*
+
+Global options can be modified to change delay/grace period settings on the
+fly.
+
+------------------------------------------------------------------------------
+g:delaytrain_delay_ms~ *g:delaytrain_delay_ms*
+
+How long repeated usage of a key should be prevented. Keep in mind that the
+timer starts on the FIRST keypress and delays repeated usage of a key based on
+`grace_period` in this timeframe.
+
+ Type: |Number|
+ Default value: `1000`
+
+------------------------------------------------------------------------------
+g:delaytrain_grace_period~ *g:delaytrain_grace_period*
+
+How many repeated keypresses are allowed inside the `delay_ms` timeframe. By
+default this is 1, so you can press a key 1 time inside `delay_ms` before it's
+disabled. Setting this value to 0 will completely disable the key.
+
+ Type: |Number|
+ Default value: `1`
+
+==============================================================================
+COMMANDS *delaytrain-commands*
+
+:DelayTrainEnable *:DelayTrainEnable*
+ Enable DelayTrain by setting defined keymaps
+
+:DelayTrainDisable *:DelayTrainDisable*
+ Disable DelayTrain by deleting defined keymaps
+
+:DelayTrainToggle *:DelayTrainToggle*
+ Toggle DelayTrain by setting/deleting keymaps
+
+------------------------------------------------------------------------------
+vim:tw=78:ts=8:ft=help:norl:
diff --git a/lua/delaytrain/init.lua b/lua/delaytrain/init.lua
new file mode 100644
index 0000000..7dfe316
--- /dev/null
+++ b/lua/delaytrain/init.lua
@@ -0,0 +1,96 @@
+local M = {}
+
+vim.g.delaytrain_delay_ms = 1000
+vim.g.delaytrain_grace_period = 1
+
+-- Map of keys to their individual current grace period
+-- This keeps track of how many times a key has been pressed
+local current_grace_period_intervals = {}
+
+local keymaps = {
+ ['nv'] = {'h', 'j', 'k', 'l'},
+ ['nvi'] = {'', '', '', ''},
+}
+
+local is_enabled = false
+
+function M.try_delay_keypress(key)
+ current_interval = current_grace_period_intervals[key]
+
+ -- Start a timer on the first keypress to reset the interval
+ if current_interval == 0 then
+ vim.loop.new_timer():start(vim.g.delaytrain_delay_ms, 0, function()
+ current_grace_period_intervals[key] = 0
+ end)
+ end
+
+ -- Pass the key through only if we haven't reached the grace period
+ if current_interval < vim.g.delaytrain_grace_period then
+ current_grace_period_intervals[key] = current_interval + 1
+
+ vim.api.nvim_feedkeys(
+ vim.api.nvim_replace_termcodes(key, true, false, true),
+ 'n',
+ false
+ )
+ end
+end
+
+function M.setup(opts)
+ if opts then
+ if opts.delay_ms then
+ vim.g.delaytrain_delay_ms = opts.delay_ms
+ end
+
+ if opts.grace_period then
+ vim.g.delaytrain_grace_period = opts.grace_period
+ end
+
+ if opts.keys then
+ keymaps = opts.keys
+ end
+ end
+
+ M.enable()
+end
+
+function M.enable()
+ is_enabled = true
+
+ for modes, keys in pairs(keymaps) do
+ mode_array = {}
+ for mode in modes:gmatch"." do
+ table.insert(mode_array, mode)
+ end
+ for _, key in ipairs(keys) do
+ -- Set the current grace period for the given key
+ current_grace_period_intervals[key] = 0
+
+ vim.keymap.set(mode_array, key, function() M.try_delay_keypress(key) end, {expr = true})
+ end
+ end
+end
+
+function M.disable()
+ is_enabled = false
+
+ for modes, keys in pairs(keymaps) do
+ mode_array = {}
+ for mode in modes:gmatch"." do
+ table.insert(mode_array, mode)
+ end
+ for _, key in ipairs(keys) do
+ vim.keymap.del(mode_array, key)
+ end
+ end
+end
+
+function M.toggle()
+ if is_enabled then
+ M.disable()
+ else
+ M.enable()
+ end
+end
+
+return M
diff --git a/plugin/delaytrain.lua b/plugin/delaytrain.lua
new file mode 100644
index 0000000..51b72d4
--- /dev/null
+++ b/plugin/delaytrain.lua
@@ -0,0 +1,11 @@
+vim.api.nvim_create_user_command("DelayTrainEnable", function()
+ require("delaytrain").enable()
+end, { desc = "Enable DelayTrain by setting defined keymaps" })
+
+vim.api.nvim_create_user_command("DelayTrainDisable", function()
+ require("delaytrain").disable()
+end, { desc = "Disable DelayTrain by deleting defined keymaps" })
+
+vim.api.nvim_create_user_command("DelayTrainToggle", function()
+ require("delaytrain").toggle()
+end, { desc = "Toggle DelayTrain by setting/deleting keymaps" })