Skip to content

Compose Keymaps and Profiles

This chapter activates one personal keymap, observes a direct binding, semantic remap, and mask, verifies contextual precedence, and recovers from a profile that attempts to remove protected editor access.

Before You Begin

If you enter this chapter directly, first complete Prepare the User Guide Exercises.

Complete Use Familiar Interaction. Keep the isolated tutorial init.rkt and settings/interface.rkt from the previous chapters.

Add a Personal Keymap

Create ~/odra-guide/config/odra/settings/keys.rkt by pasting this complete chapter-owned file:

#lang racket/base

(require odra/keymaps)

(provide odra-interaction-profile)

(define source
  (odra-provenance "personal" "settings/keys.rkt" ""))

(define (key character modifiers)
  (odra-key-stroke 1 (char->integer character) modifiers))

(define (control character)
  (key character #x01))

(define (plain character)
  (key character 0))

(define personal-map
  (odra-keymap
   3 1 "personal-discovery" 0 0 'user-global 10
   0 0 0 0 'fallthrough
   (list
    (keymap-bind
     (key-sequence (control #\c) (plain #\i))
     "describe-keymap-state"
     source)
    (keymap-mask
     (key-sequence (control #\x) (control #\s))
     source))
   (list
    (keymap-remap
     "cursor-line-start"
     "cursor-line-first-non-whitespace"
     source))
   '()
   source))

(define factory (factory-interaction-profile))

(define odra-interaction-profile
  (compose-interaction-profile
   2 1 "personal-direct"
   (list (odra-interaction-profile-maps factory)
         (list personal-map))
   "insert-text"))

Update init.rkt to require and export both settings modules:

#lang racket/base

(require "settings/interface.rkt"
         "settings/keys.rkt")

(provide odra-status-bar-configuration
         odra-gutter-configuration
         odra-interaction-profile)

Run M-x reload-personal-commands. The complete command registry and profile relationship is checked before publication.

Observe Binding, Remap, and Mask

Press C-c i. The new binding runs describe-keymap-state. Its row identifies the active personal-direct profile and personal-discovery map.

In an indented source line, press C-a. The inherited physical binding first resolves cursor-line-start; the personal semantic remap redirects it to cursor-line-first-non-whitespace.

Run describe-key and capture C-x C-s. The personal map masks the lower factory binding, so the result records the masked disposition rather than silently exposing another command. Save through M-x save-buffer while this tutorial profile is active.

Verify Contextual Precedence

Open M-x and type ordinary query text. The command navigator's contextual map owns filtering, movement, acceptance, and cancellation above the personal global map. Open a fixed prompt or Darek and observe that its current component commands likewise retain local meaning.

Contextual owners activate and retire their maps with the interaction. A personal profile should bind semantic editor commands, not reproduce prompt responses or component-local navigation.

Reject an Unsafe Profile

Replace the C-x C-s mask with a mask for protected M-x:

(keymap-mask
 (key-sequence (key #\x #x02))
 source)

Run M-x reload-personal-commands. The candidate is rejected before publication because M-x and C-g are protected recovery routes. The prior personal generation remains active, so M-x still opens command navigation.

Run M-x describe-keymap-conflicts to inspect the protected-binding rejection. Restore the C-x C-s example or remove the mask, increment the profile and map revisions, and reload successfully.

Recover from Keymap Problems

Previous: Use Familiar Interaction · User Guide · Next: Write and Reload a Personal Command