Skip to main content

Parser

Parse, normalize, and validate key binding strings.

import {
  parseKeyBind,
  normalizeKeyBind,
  validateKeyBind,
  keyboardEventToDescriptor,
  KEY_ALIASES,
  MODIFIER_KEYS,
} from '@gentleduck/vim/parser'
import {
  parseKeyBind,
  normalizeKeyBind,
  validateKeyBind,
  keyboardEventToDescriptor,
  KEY_ALIASES,
  MODIFIER_KEYS,
} from '@gentleduck/vim/parser'

Types

ParsedKeyBind

The structured result of parsing a key binding string.

interface ParsedKeyBind {
  /** The non-modifier key, lowercased (e.g. 's', 'space', 'enter') */
  key: string
  ctrl: boolean
  shift: boolean
  alt: boolean
  meta: boolean
  /** Sorted array of active modifier names */
  modifiers: Array<'ctrl' | 'alt' | 'meta' | 'shift'>
}
interface ParsedKeyBind {
  /** The non-modifier key, lowercased (e.g. 's', 'space', 'enter') */
  key: string
  ctrl: boolean
  shift: boolean
  alt: boolean
  meta: boolean
  /** Sorted array of active modifier names */
  modifiers: Array<'ctrl' | 'alt' | 'meta' | 'shift'>
}

ValidationResult

interface ValidationResult {
  valid: boolean
  warnings: string[]
  errors: string[]
}
interface ValidationResult {
  valid: boolean
  warnings: string[]
  errors: string[]
}

Functions

parseKeyBind(binding, platform?)

Parses a key binding string into its structured components. Resolves the Mod key based on the current or specified platform.

function parseKeyBind(binding: string, platform?: Platform): ParsedKeyBind
function parseKeyBind(binding: string, platform?: Platform): ParsedKeyBind

Throws if the binding is empty, has multiple non-modifier keys, or has no non-modifier key.

Examples:

parseKeyBind('ctrl+shift+s')
// { key: 's', ctrl: true, shift: true, alt: false, meta: false, modifiers: ['ctrl', 'shift'] }
 
parseKeyBind('Mod+S', 'mac')
// { key: 's', ctrl: false, shift: false, alt: false, meta: true, modifiers: ['meta'] }
 
parseKeyBind('space')
// { key: 'space', ctrl: false, shift: false, alt: false, meta: false, modifiers: [] }
parseKeyBind('ctrl+shift+s')
// { key: 's', ctrl: true, shift: true, alt: false, meta: false, modifiers: ['ctrl', 'shift'] }
 
parseKeyBind('Mod+S', 'mac')
// { key: 's', ctrl: false, shift: false, alt: false, meta: true, modifiers: ['meta'] }
 
parseKeyBind('space')
// { key: 'space', ctrl: false, shift: false, alt: false, meta: false, modifiers: [] }

normalizeKeyBind(binding, platform?)

Returns the canonical string form of a binding: modifiers in alphabetical order, all lowercase, joined by +.

function normalizeKeyBind(binding: string, platform?: Platform): string
function normalizeKeyBind(binding: string, platform?: Platform): string

Examples:

normalizeKeyBind('Shift+Mod+s', 'mac') // 'meta+shift+s'
normalizeKeyBind('Ctrl+K')             // 'ctrl+k'
normalizeKeyBind('Command+Alt+Z')      // 'alt+meta+z' (on any platform, since Command is an alias for meta)
normalizeKeyBind('Shift+Mod+s', 'mac') // 'meta+shift+s'
normalizeKeyBind('Ctrl+K')             // 'ctrl+k'
normalizeKeyBind('Command+Alt+Z')      // 'alt+meta+z' (on any platform, since Command is an alias for meta)

validateKeyBind(binding)

Validates a key binding string without throwing. Returns errors and warnings.

function validateKeyBind(binding: string): ValidationResult
function validateKeyBind(binding: string): ValidationResult

Examples:

validateKeyBind('ctrl+k')
// { valid: true, warnings: [], errors: [] }
 
validateKeyBind('ctrl+k+j')
// { valid: false, warnings: [], errors: ['Multiple non-modifier keys found'] }
 
validateKeyBind('shift+shift+a')
// { valid: false, warnings: [], errors: ["Duplicate modifier: 'shift'"] }
 
validateKeyBind('alt+n')
// { valid: true, warnings: ['Alt+letter combinations may not work on macOS due to special characters'], errors: [] }
validateKeyBind('ctrl+k')
// { valid: true, warnings: [], errors: [] }
 
validateKeyBind('ctrl+k+j')
// { valid: false, warnings: [], errors: ['Multiple non-modifier keys found'] }
 
validateKeyBind('shift+shift+a')
// { valid: false, warnings: [], errors: ["Duplicate modifier: 'shift'"] }
 
validateKeyBind('alt+n')
// { valid: true, warnings: ['Alt+letter combinations may not work on macOS due to special characters'], errors: [] }

keyboardEventToDescriptor(event)

Builds a canonical key descriptor string from a KeyboardEvent. Returns null for pure modifier key presses.

function keyboardEventToDescriptor(e: KeyboardEvent): string | null
function keyboardEventToDescriptor(e: KeyboardEvent): string | null

Example:

document.addEventListener('keydown', (e) => {
  const desc = keyboardEventToDescriptor(e)
  if (desc) console.log('Key descriptor:', desc) // e.g. 'ctrl+k'
})
document.addEventListener('keydown', (e) => {
  const desc = keyboardEventToDescriptor(e)
  if (desc) console.log('Key descriptor:', desc) // e.g. 'ctrl+k'
})

Constants

KEY_ALIASES

A record mapping raw key names to their canonical forms.

const KEY_ALIASES: Record<string, string> = {
  ' ': 'space',
  escape: 'esc',
  control: 'ctrl',
  cmd: 'meta',
  command: 'meta',
  opt: 'alt',
  option: 'alt',
}
const KEY_ALIASES: Record<string, string> = {
  ' ': 'space',
  escape: 'esc',
  control: 'ctrl',
  cmd: 'meta',
  command: 'meta',
  opt: 'alt',
  option: 'alt',
}

MODIFIER_KEYS

The set of recognized modifier key names.

const MODIFIER_KEYS: ReadonlySet<string> = new Set(['ctrl', 'alt', 'meta', 'shift'])
const MODIFIER_KEYS: ReadonlySet<string> = new Set(['ctrl', 'alt', 'meta', 'shift'])