Skip to content

Proposal: .sheetsrc config file for custom key mappings #23

Description

@NSEvent

Problem

Sheets has vim-style modal editing but no way to customize key bindings. Vim users expect to carry over muscle memory from their .vimrc — for example, many people remap <C-c><C-c> to quit, or remap navigation keys for their keyboard layout.

This is especially relevant now that #22 proposes removing Ctrl-C as a quit key. Without a config file, there's no way for users to bind their own quit sequence.

Proposal: ~/.sheetsrc

A minimal RC file that supports key mapping, using familiar vim syntax.

Format

" Comments start with " or #
# This is also a comment

" Map a key sequence in normal mode
nmap <C-c><C-c> :q

" Map in insert mode
imap <C-c> <Esc>

" Map in select mode
smap <C-c> <Esc>

" Map in all modes
map <C-c> <Esc>

Supported mapping commands

Command Scope
nmap / nnoremap Normal mode
imap / inoremap Insert mode
smap Select mode
map / noremap All modes

Key notation

Uses vim-style <...> notation:

Notation Key
<C-x> Ctrl+x
<Esc> Escape
<CR> / <Enter> Enter
<Tab> Tab
<Space> Space
<BS> Backspace
a, q, etc. Literal characters

Multiple keys can be chained: <C-c><C-c> is a two-key sequence.

Supported actions

Action Effect
:q Quit
:w Write/save
:wq Write and quit
<Esc> Exit current mode → normal
<Nop> Do nothing (disable a key)

Multi-key sequence handling

When the user presses a key that is a prefix of a mapped sequence:

  1. Buffer the key and wait for the next keypress
  2. If the next key completes a mapping → execute the action
  3. If the next key doesn't match any mapping → flush the buffer and process both keys normally
  4. If no key comes within 1 second → flush the buffer (process the key normally)

This matches vim's timeoutlen behavior.

Scope / non-goals

This proposal intentionally keeps the scope small:

  • No set commands (e.g., set cellwidth=20) — that can come later
  • No recursive mapping — nmap and nnoremap behave identically for now
  • No <leader> key — users can just spell out their sequences
  • No runtime :map command — config is read once at startup

Implementation sketch

  • New file config.go: RC file parser, key notation normalizer, sequence matcher
  • types.go: Add config, pendingSeq, pendingSeqMsgs fields to model
  • model.go: Check bindings before normal key dispatch in Update(); extract key dispatch into processKeyMsg() so buffered keys can be replayed on flush

I have a working implementation of this and am happy to open a PR if the design looks good. Feedback on the format, scope, or naming is welcome.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions