@@ -151,16 +151,6 @@ let cachedKeymap = [];
151151/** @type {Set<EditorView> } */
152152const commandViews = new Set ( ) ;
153153
154- /**
155- * Commands are often registered in bursts (a plugin adding several at once),
156- * so the keymap is rebuilt lazily on the next read instead of per command.
157- */
158- let keymapDirty = true ;
159-
160- /** @type {Set<EditorView> } views waiting for the updated keymap */
161- const pendingKeymapViews = new Set ( ) ;
162- let keymapRefreshScheduled = false ;
163-
164154const CODEMIRROR_COMMAND_ENTRIES = Object . entries ( cmCommands ) . filter (
165155 ( [ name , value ] ) =>
166156 typeof value === "function" && CODEMIRROR_COMMAND_NAMES . has ( name ) ,
@@ -174,6 +164,7 @@ registerCoreCommands();
174164registerLspCommands ( ) ;
175165registerLintCommands ( ) ;
176166registerCommandsFromKeyBindings ( ) ;
167+ rebuildKeymap ( ) ;
177168
178169function registerCoreCommands ( ) {
179170 addCommand ( {
@@ -1523,34 +1514,19 @@ function buildResolvedKeyBindingsSnapshot() {
15231514 ) ;
15241515}
15251516
1526- /**
1527- * Resolve a command's effective description and key from the bindings.
1528- * @returns {string|null } the key source
1529- */
1530- function syncCommandBinding ( command , name ) {
1531- const bindingInfo = resolveBindingInfo ( name ) ;
1532- command . description = bindingInfo ?. description || command . defaultDescription ;
1533- command . key =
1534- bindingInfo && Object . prototype . hasOwnProperty . call ( bindingInfo , "key" )
1535- ? bindingInfo . key
1536- : ( command . defaultKey ?? null ) ;
1537- return command . key ;
1538- }
1539-
1540- function invalidateKeymap ( ) {
1541- keymapDirty = true ;
1542- }
1543-
1544- function ensureKeymap ( ) {
1545- if ( keymapDirty ) rebuildKeymap ( ) ;
1546- }
1547-
15481517function rebuildKeymap ( ) {
15491518 cachedResolvedKeyBindings = buildResolvedKeyBindingsSnapshot ( ) ;
15501519 const candidates = [ ] ;
15511520 let order = 0 ;
15521521 commandMap . forEach ( ( command , name ) => {
1553- const keySource = syncCommandBinding ( command , name ) ;
1522+ const bindingInfo = resolveBindingInfo ( name ) ;
1523+ command . description =
1524+ bindingInfo ?. description || command . defaultDescription ;
1525+ const keySource =
1526+ bindingInfo && Object . prototype . hasOwnProperty . call ( bindingInfo , "key" )
1527+ ? bindingInfo . key
1528+ : ( command . defaultKey ?? null ) ;
1529+ command . key = keySource ;
15541530 const combos = parseKeyString ( keySource ) ;
15551531 combos . forEach ( ( combo ) => {
15561532 const cmKey = toCodeMirrorKey ( combo ) ;
@@ -1575,15 +1551,9 @@ function rebuildKeymap() {
15751551 const conflicts = [ ] ;
15761552 for ( const candidate of candidates ) {
15771553 const canonicalKey = canonicalizeKeyBinding ( candidate . key ) ;
1578- // First conflicting claim in insertion order, without copying the map
1579- // for every candidate.
1580- let claimed = null ;
1581- for ( const entry of claimedKeys ) {
1582- if ( keyBindingsConflict ( entry [ 0 ] , canonicalKey ) ) {
1583- claimed = entry ;
1584- break ;
1585- }
1586- }
1554+ const claimed = Array . from ( claimedKeys . entries ( ) ) . find ( ( [ key ] ) =>
1555+ keyBindingsConflict ( key , canonicalKey ) ,
1556+ ) ;
15871557 if ( claimed ) {
15881558 const [ claimedKey , owner ] = claimed ;
15891559 const appCommandShadowsCodeMirrorDefault =
@@ -1626,7 +1596,6 @@ function rebuildKeymap() {
16261596 cachedKeyBindingConflicts = conflicts ;
16271597 cachedKeymap = bindings ;
16281598 resolvedKeyBindingsVersion += 1 ;
1629- keymapDirty = false ;
16301599 return bindings ;
16311600}
16321601
@@ -1674,7 +1643,6 @@ export function executeCommand(name, view, args) {
16741643}
16751644
16761645export function getRegisteredCommands ( ) {
1677- ensureKeymap ( ) ;
16781646 return Array . from ( commandMap . values ( ) ) . map ( ( command ) => ( {
16791647 name : command . name ,
16801648 description : command . description || command . defaultDescription ,
@@ -1683,27 +1651,22 @@ export function getRegisteredCommands() {
16831651}
16841652
16851653export function getResolvedKeyBindings ( ) {
1686- ensureKeymap ( ) ;
16871654 return cachedResolvedKeyBindings ;
16881655}
16891656
16901657export function getEffectiveKeyBindings ( ) {
1691- ensureKeymap ( ) ;
16921658 return cachedEffectiveKeyBindings ;
16931659}
16941660
16951661export function getKeyBindingConflicts ( ) {
1696- ensureKeymap ( ) ;
16971662 return cachedKeyBindingConflicts . map ( ( conflict ) => ( { ...conflict } ) ) ;
16981663}
16991664
17001665export function getResolvedKeyBindingsVersion ( ) {
1701- ensureKeymap ( ) ;
17021666 return resolvedKeyBindingsVersion ;
17031667}
17041668
17051669export function getCommandKeymapExtension ( ) {
1706- ensureKeymap ( ) ;
17071670 return commandKeymapCompartment . of ( keymap . of ( cachedKeymap ) ) ;
17081671}
17091672
@@ -1791,11 +1754,9 @@ export function registerExternalCommand(descriptor = {}) {
17911754 const stored = commandMap . get ( name ) ;
17921755 if ( stored ) {
17931756 stored . key = normalized . key ?? stored . key ;
1794- // The returned command reflects its final binding right away.
1795- syncCommandBinding ( stored , name ) ;
17961757 }
17971758
1798- invalidateKeymap ( ) ;
1759+ rebuildKeymap ( ) ;
17991760 return stored ;
18001761}
18011762
@@ -1804,34 +1765,13 @@ export function removeExternalCommand(name) {
18041765 const exists = commandMap . has ( name ) ;
18051766 if ( ! exists ) return false ;
18061767 commandMap . delete ( name ) ;
1807- invalidateKeymap ( ) ;
1768+ rebuildKeymap ( ) ;
18081769 return true ;
18091770}
18101771
1811- /**
1812- * Apply the current keymap to a view. Calls made in the same task are applied
1813- * together in a microtask, which always runs before the next key event.
1814- */
18151772export function refreshCommandKeymap ( view ) {
18161773 const resolvedView = resolveView ( view ) ;
1817- if ( ! resolvedView ) return ;
1818- pendingKeymapViews . add ( resolvedView ) ;
1819- if ( keymapRefreshScheduled ) return ;
1820- keymapRefreshScheduled = true ;
1821- Promise . resolve ( ) . then ( flushKeymapRefresh ) ;
1822- }
1823-
1824- function flushKeymapRefresh ( ) {
1825- keymapRefreshScheduled = false ;
1826- const views = Array . from ( pendingKeymapViews ) ;
1827- pendingKeymapViews . clear ( ) ;
1828- for ( const view of views ) {
1829- try {
1830- applyCommandKeymap ( view ) ;
1831- } catch ( error ) {
1832- console . error ( "Failed to apply command keymap" , error ) ;
1833- }
1834- }
1774+ applyCommandKeymap ( resolvedView ) ;
18351775}
18361776
18371777function normalizeExternalCommand ( descriptor ) {
@@ -1887,9 +1827,8 @@ function normalizeExternalKey(bindKey) {
18871827 return combos . length ? combos . join ( "|" ) : null ;
18881828}
18891829
1890- function applyCommandKeymap ( view , bindings ) {
1830+ function applyCommandKeymap ( view , bindings = cachedKeymap ) {
18911831 if ( ! view ) return ;
1892- ensureKeymap ( ) ;
18931832 commandViews . add ( view ) ;
18941833 view . dispatch ( {
18951834 effects : commandKeymapCompartment . reconfigure (
0 commit comments