Automatic insertion and handling of matching brackets, including intelligent behavior for strings, quotes, and nested structures with language-aware configuration.
Main extension and configuration for automatic bracket closing behavior.
/**
* Extension to enable bracket-closing behavior
*/
function closeBrackets(): Extension;
/**
* Configuration for bracket closing behavior
*/
interface CloseBracketConfig {
/**
* Opening brackets to close (default: ["(", "[", "{", "'", '"'])
*/
brackets?: string[];
/**
* Characters in front of which brackets are automatically closed
* (default: ")]}:;>", always closes in front of whitespace)
*/
before?: string;
/**
* Prefixes to recognize before opening quotes for string detection
*/
stringPrefixes?: string[];
}Usage Examples:
import { closeBrackets } from "@codemirror/autocomplete";
import { EditorView } from "@codemirror/view";
// Basic bracket closing
const view = new EditorView({
extensions: [
closeBrackets()
]
});
// Language-specific configuration via language data
import { javascript } from "@codemirror/lang-javascript";
const jsView = new EditorView({
extensions: [
javascript(),
closeBrackets(),
javascript.data.of({
closeBrackets: {
brackets: ["(", "[", "{", "'", '"', "`"],
before: ")]}:;>,",
stringPrefixes: ["r", "u", "b", "f"] // Python-style prefixes
}
})
]
});Functions for programmatically inserting brackets with proper closing behavior.
/**
* Insert a bracket with automatic closing behavior
* Returns transaction if custom behavior is needed, null for default insertion
*/
function insertBracket(state: EditorState, bracket: string): Transaction | null;Usage Examples:
import { insertBracket } from "@codemirror/autocomplete";
// Programmatic bracket insertion
const insertParentheses = (view: EditorView) => {
const transaction = insertBracket(view.state, "(");
if (transaction) {
view.dispatch(transaction);
return true;
}
return false; // Use default insertion
};
// Custom bracket insertion logic
const smartBracketInsertion = (view: EditorView, bracket: string) => {
const state = view.state;
const selection = state.selection.main;
// Check if we should use automatic closing
const transaction = insertBracket(state, bracket);
if (transaction) {
// Custom closing behavior was applied
view.dispatch(transaction);
} else {
// Fall back to normal insertion
view.dispatch({
changes: { from: selection.from, to: selection.to, insert: bracket },
selection: { anchor: selection.from + bracket.length }
});
}
};Commands for intelligent deletion of matching bracket pairs.
/**
* Delete matching bracket pairs when cursor is between them
*/
const deleteBracketPair: StateCommand;
/**
* Key bindings for bracket-related operations
*/
const closeBracketsKeymap: readonly KeyBinding[];Usage Examples:
import { deleteBracketPair, closeBracketsKeymap } from "@codemirror/autocomplete";
import { keymap } from "@codemirror/view";
// Use default bracket keymap (includes Backspace -> deleteBracketPair)
const view = new EditorView({
extensions: [
closeBrackets(),
keymap.of(closeBracketsKeymap)
]
});
// Custom bracket deletion command
const smartDelete = (view: EditorView) => {
// Try bracket pair deletion first
if (deleteBracketPair(view)) {
return true;
}
// Fall back to normal deletion
return false;
};Configuring bracket behavior for specific languages and contexts.
Usage Examples:
import { LanguageSupport } from "@codemirror/language";
// Custom language with bracket configuration
const customLanguage = new LanguageSupport(myLanguage, [
myLanguage.data.of({
closeBrackets: {
brackets: ["(", "[", "{", '"'],
before: ")]}\"',;>",
stringPrefixes: ["r", "f"] // Raw and format strings
}
})
]);
// Multiple bracket configurations for different contexts
const htmlWithJS = [
html(),
javascript(),
// HTML bracket config
html.data.of({
closeBrackets: { brackets: ["<", '"', "'"], before: ">\"' \t\n" }
}),
// JavaScript bracket config within script tags
javascript.data.of({
closeBrackets: { brackets: ["(", "[", "{", "'", '"', "`"] }
})
];Complex bracket handling scenarios including triple quotes, nested structures, and context-aware closing.
Usage Examples:
// Python-style triple quotes
const pythonBrackets = {
brackets: ["(", "[", "{", "'", '"', "'''", '"""'],
before: ")]}\"':;>,",
stringPrefixes: ["r", "u", "b", "f", "rf", "fr", "br", "rb"]
};
// Context-aware bracket insertion
const contextAwareBrackets = (view: EditorView) => {
const state = view.state;
const pos = state.selection.main.head;
// Check syntax context
const syntaxTree = syntaxTree(state);
const node = syntaxTree.resolveInner(pos);
if (node.name === "String") {
// Inside string - different bracket behavior
return insertBracket(state, '"');
} else if (node.name === "Comment") {
// Inside comment - no bracket closing
return null;
} else {
// Normal context
return insertBracket(state, "(");
}
};
// Custom bracket matching logic
const customBracketLogic = {
// Custom bracket pairs
brackets: ["(", "[", "{", "<", "|", "'", '"'],
// Custom closing logic
before: ")]}>\"|';:,",
// Template string prefixes
stringPrefixes: ["template", "html", "css", "sql"]
};Understanding how bracket closing works in different scenarios.
Behavior Examples:
// Scenario 1: Empty selection, space after cursor
// Typing "(" when cursor is before " hello"
// Result: "()" with cursor between brackets
// Scenario 2: Text selection
// Selecting "text" and typing "("
// Result: "(text)" with "text" still selected
// Scenario 3: Cursor before existing closing bracket
// Typing ")" when cursor is before existing ")"
// Result: cursor moves past the existing ")"
// Scenario 4: String context with prefixes
// In Python, typing '"' after 'f'
// Result: 'f""' with cursor between quotes
// Scenario 5: Triple quote handling
// Typing '"' when already have '""'
// Result: '"""' (triple quote string)Combining bracket closing with completion and other editor features.
Usage Examples:
import { autocompletion, closeBrackets, snippetCompletion } from "@codemirror/autocomplete";
// Bracket closing with completion system
const integratedView = new EditorView({
extensions: [
autocompletion({
// Completions that work well with bracket closing
override: [
completeFromList([
// Functions that benefit from bracket closing
{ label: "function", type: "keyword", commitCharacters: ["("] },
{ label: "if", type: "keyword", commitCharacters: ["("] },
{ label: "for", type: "keyword", commitCharacters: ["("] }
])
]
}),
closeBrackets()
]
});
// Snippets with bracket closing
const bracketAwareSnippets = [
snippetCompletion("function ${name}(${params}) {\n\t${}\n}", {
label: "func",
detail: "function with brackets",
type: "snippet"
}),
// Snippet that leverages bracket closing
snippetCompletion("if (${condition}", {
label: "if",
detail: "if statement (auto-closes)",
type: "snippet",
commitCharacters: [")"] // Closing paren will be handled automatically
})
];