Home

Awesome

unruly worker

a ridiculously fun alternative neovim keymap for the workman keyboard layout

default setup

unruly worker default layout cheatsheet

everything enabled

unruly worker everything layout cheatsheet unruly worker plugin cheatsheet

LAYOUT PHILOSOPHY

  1. When possible, commands are positioned according to the workman layout heatmap. So frequent use will not strain your hands.
  2. When possible, commands are arranged onto a semantic key. This makes it possible for the keymap to be remembered with mnemonic phrases.
  3. When possible, keys behavior, or behavior substitute, should stay in the same position as the original-keymap, so that there is no need for experienced vim users to unlearn there years of muscle memory.

FEATURES

REGISTER PRESELECTION?

With unruly_kopy and unruly_macro when you select a register, it stays selected until you change it. This means you don't select a register for a specific motion, instead you set the yank or macro register, and then all future yank/paste or record/play actions will use the selected register until you select a new register.

INSTALL AND SETUP

  1. Install with your favorite neovim package manager
  2. Add the following lua code to your vim config
-- Use this setup config if you want to follow the keymap above
local unruly_worker = require('unruly-worker')

-- to setup with the defaults you can simply put
-- unruly_worker.setup()

-- example setup with the default settings
unruly_worker.setup({
  -- you can use the skip_list = {} to stop unruly from creating certain mappings
  -- skip_list = { "z", "Z", "<C-z>"},  skip z related mappings
  skip_list = {},
  unruly_options = {
    -- set default unruly kopy register must be [a-z] [A-Z] 0 +
    kopy_reg = "+",
    -- set default unruly macro register must be [a-z] [A-Z]
    macro_reg = "q",
    -- set default unruly seek mode, must be unruly_worker.seek_mode.(buffer|loclist|quickfix)
    seek_mode = unruly_worker.seek_mode.buffer,
    -- set unruly mark mode to global or local
    mark_mode_is_global = false
  },
  -- boosters allow you to op-in to extra keymaps
  -- or opt-out of the default keymaps if you want that for some reason
  booster = {
    default                     = true,
    -- easy stuff are just additional opt in keymaps
    easy_swap                   = false,
    easy_search = false,
    easy_line                   = false,
    easy_spellcheck             = false,
    easy_incrament              = false,
    easy_hlsearch               = false,
    easy_focus                  = false,
    easy_window                 = false,
    easy_jumplist               = false,
    easy_scroll                 = false,
    easy_source                 = false,
    easy_lsp                    = false,
    easy_lsp_leader             = false,
    easy_diagnostic             = false,
    easy_diagnostic_leader      = false,
    -- unruly stuff change neovim's normal behavior
    unruly_seek                 = false,
    unruly_mark                 = false,
    unruly_macro                = false,
    unruly_kopy                 = false,
    unruly_quit                 = false,
    -- plugin stuff have external dependencies
    plugin_navigator            = false,
    plugin_comment              = false,
    plugin_luasnip              = false,
    plugin_textobject           = false,
    plugin_telescope_leader     = false,
    plugin_telescope_lsp_leader = false,
    plugin_telescope_easy_jump  = false,
    plugin_telescope_easy_paste = false,
    plugin_telescope_diagnostic_leader = false,
  },
})

nvim-cmp MAPPING SETUP (optional)

-- NOTE: its recommended that you require cmp before unruly_worker.external.nvim-cmp
local cmp = require("cmp")
local unruly_cmp = require('unruly-worker.external.nvim-cmp')
cmp.setup({
    mapping = unruly_cmp.create_insert_mapping(),
    -- optionally you can pass a config with a skip_list and mappings
    -- mapping = unruly_cmp.create_insert_mapping({
      -- skip_list = { "<Right>" }, -- opt out of the <Right> keymap
      -- you can add your own mappings here
      -- your mappings will allways overwrite the unruly_cmp default mappings
      -- mapping = {
      --   ["<C-u>"] = cmp.mapping.complete() -- use <c-u> to complete
      -- },
    -- }),
    -- rest of config...
})

cmp.setup.cmdline({ "/", "?" }, {
    -- you can also pass the optional config into create_cmdline_mapping
    mapping = unruly_cmp.create_cmdline_mapping(),
    -- rest of config...
})

cmp.setup.cmdline(":", {
    mapping = unruly_cmp.create_cmdline_mapping(),
    -- rest of config...
})
-- my personal nvim-cmp config file: https://github.com/slugbyte/config/blob/main/conf/config/nvim/lua/slugbyte/plugin/cmp-and-luasnip.lua

nvim-cmp insert mode

nvim-cmp cmdline mode

telescope.nvim MAPPING SETUP (optional)

-- NOTE: its recommended that you require telescope before unruly_worker.external.telescope
local telescope = require("telescope")
local telescope_action = require("telescope.action")
local unruly_telescope = require("unruly-worker.external.telescope")
telescope.setup({
    defaults = {
        mappings = unruly_telescope.create_mappings(),
        -- -- optionally you can pass a config with skip_list, insert_mapping, and normal_mapping
        -- mappings = unruly_telescope.create_mappings({
        --   skip_list = {"<Tab>"}, -- disable <tab> map
        --   -- insert_mapping will overwrite any default unruly_telescope insert mappings
        --   insert_mapping = {
        --     "<c-u>" = telescope_action.select_default(), -- <c-u> select default
        --   },
        --   -- normal_mapping will overwrite any default unruly_telescope normal mappings
        --   normal_mapping = {
        --     "<c-u>" = telescope_action.select_default(), -- <c-u> select default
        --   },
        -- }),
    },
    -- rest of config...
})
-- my personal telescope setup: https://github.com/slugbyte/config/blob/main/conf/config/nvim/lua/slugbyte/plugin/telescope.lua

telescope.nvim insert mode

telescope.nvim normal mode (optional)

includes everything in insert mode ^

nvim-treesitter-textobject MAPPING SETUP

local unruly_textobjects = require("unruly-worker.external.textobjects")
require("nvim-treesitter.configs").setup({
    textobjects = {
        select = {
            keymaps = unruly_textobjects.select_keymaps,
            -- rest of config...
        },
        move = {
            goto_next_start = unruly_textobjects.move_goto_next_start,
            goto_previous_start = unruly_textobjects.move_goto_previous_start,
            goto_next_end = unruly_textobjects.move_goto_next_end,
            goto_previous_end = unruly_textobjects.move_goto_previous_end,
            -- rest of config...
        },
    },
})

textobjects select and movement

UNRULY TMUX CONFIG SETUP (optional)

This project includes a tmux config file with tmux unruly-worker style keybindings, See the unruly tmux README for installation instructions and overview.

UNRULY KEYMAP OVERVIEW (default booster)

cursor movement

insert text

kopy

paste

delete

change

macros

marks and jumplist

visual mode

search

utility

current line alignment

window navigation

keys with no behavior

j J % ^ = * - _ + , . | ;

EASY BOOSTERS (disabled by default)

easy boosters don't dramatically alter anything, they are just additional keymaps that I didn't include in the basic setup, in order to keep it as vanilla as possible.

easy_swap

easy_focus

easy_window

easy_hlsearch

NOTE: this will auto enable the vim hlsearch option

easy_source

NOTE: this will disable the builtin matchit plugin

easy_scroll

easy_jumplist

easy_diagnostic

easy_diagnostic_leader

easy_lsp

easy_lsp_leader

easy_spellcheck

easy_line

easy_search

easy_incrament

# select the colomn of 0s and then <leader><leader>i
0 -(will become)-> 1
0 -(will become)-> 2
0 -(will become)-> 3
0 -(will become)-> 4
0 -(will become)-> 5

UNRULY BOOSTERS (disabled by default)

unruly boosters change the way that neovim typically works, they are probably not most vim users cup of tea

unruly_kopy

kopy and paste with the kopy_reg

kopy prompt

the kopy prompt does not limit register selection or track history

delete, change, substitute, and paste from register 0

unruly_mark

The unruly idea behind marks is that you only need two marks, for everything else just use telescope. Unruly marks can be in local buffer mode or global mode, by default it will be in local mode.

unruly_seek

unruly seek allows you to quickly navigate through quickfix list, loclist, and currently open buffers. Seek keymaps only target one type of seekable list at a time, by default the seek type will be buffers.

unruly_macro

unruly macros use the preselected register macro_reg (default: z)

unruly_quit

this is maby a bad idea, but I love it

PLUGIN BOOSTERS (disabled by default)

plugin boosters have other plugin dependencies

plugin_telescope_jump_easy

depends on telescope.nvim

plugin_telescope_leader

depends on telescope.nvim

plugin_telescope_lsp_leader

depends on telescope.nvim

plugin_telescope_diagnostic_leader

depends on telescope.nvim

plugin_comment

depends on any plugin that uses gc and gcc mappings to comment toggle, like Comment.nvim

plugin_navigator

depends on Navigator.nvim

plugin_textobject

depends on nvim-treesitter and nvim-treesitter-textobject

plugin_textobject will whatever s and S where previously (for example unruly_kopy's s)

plugin_luasnip

depends on LuaSnip powerful snipits

ABOUT

Being dyslexic has taught me its often easier for me to build a system for myself than it is to learn a system that works well for everyone else. This reinventing the wheel usually ends up being a bit of an accident. I usually start off trying to learn something the way it is, but when I struggle to grasp whats going on I inevitably decide to dig in and see how things work under the hood. My process for exploring the "under the hood of a thing" is kind of caveman style, I just poke and prod and modify and delete things until I have a feeling for what does what. By the time I'm done with all that I usually have my own opinions about what things should be like, and I decide its time to reinvent the wheel or at least swap out the tires. I think the creation of this keymap is a good example of how my learning style tends to unfold.

Unrelated to vim, I decided to learn the workman layout in an attempt to address issues I was having with typing causing pain. This decision forced me to consider how to remap a few vim keybinds, but one thing lead to another and eventually I had created an entirely new layout, the unruly-worker layout. The original process of creating this keymap lead to me spending about a year reading :help and scouring the internet for vim config gems. Which probably seems ridiculous for many people, but for me its just how I've had to do most things in life. The time felt well used because I had already spent a decade writing code and I don't plan to stop for many decades to come. Unlike my first 7 years struggling with vim, I can now remember the entire keymap well enough to experience the sensation of manipulating text without noticing that my hands, or keyboard keys, or even that vim itself has anything to do with it. I always felt vim was the right tool for job, unruly-worker is just a jig that makes the tool fit perfectly into my workflow.

Dyslexia may or may not have been what made it so hard for me to learn vim, but it has normalized the process of reinventing wheels as a way to learn for me. The unruly-worker layout, is a classic example of the type of outcomes that my somewhat accidental process of learning produces. unruly-worker is a tool that may not be useful for anyone else, but it makes a tool that is useful to many other people accessible to me.

HELP WANTED

Suggestions and Spellcheck are always appreciated :)

See the Contributing Guide

SELF-PROMO

If you like this project star the GitHub repository :)

ACKNOWLEDGMENTS

I referenced the source code in these projcects when trying to figure out how to use the nvim apis