Programmatic Changes¶
You can modify the document programmatically by dispatching transactions with change specifications.
Inserting text¶
Insert text at the beginning of the document:
Button(onClick = {
session.insertAt(DocPos.ZERO, "// Inserted header\n")
}) { Text("Insert at top") }
Appending text¶
Append text at the end of the document:
Button(onClick = {
session.insertAt(session.state.doc.endPos, "\n// Appended footer")
}) { Text("Append at end") }
Replacing a range¶
Replace the first line with new content:
Button(onClick = {
val firstLineEnd = session.state.doc.line(LineNumber(1)).to
session.dispatch(
transactionSpec {
replace(
DocPos.ZERO,
firstLineEnd,
"// Replaced first line"
)
}
)
Deleting text¶
Omit insert to delete a range:
// Delete characters 0..5
view.dispatch(TransactionSpec(
changes = ChangeSpec.Single(from = 0, to = 5)
))
Multiple changes¶
Use ChangeSpec.Multi to apply several changes at once. Positions refer to the original document — the system handles offsetting:
view.dispatch(TransactionSpec(
changes = ChangeSpec.Multi(listOf(
ChangeSpec.Single(from = 0, insert = InsertContent.StringContent("// header\n")),
ChangeSpec.Single(from = 20, to = 25, insert = InsertContent.StringContent("new"))
))
))
Replacing the selection¶
state.replaceSelection() builds a TransactionSpec that replaces every selection range with the given text:
Per-range changes¶
state.changeByRange applies a function to each selection range independently, correctly handling multi-cursor edits:
val spec = state.changeByRange { range ->
ChangeByRangeResult(
changes = ChangeSpec.Single(
range.from, range.to,
insert = InsertContent.StringContent(
state.sliceDoc(range.from, range.to).uppercase()
)
),
range = EditorSelection.range(
range.from,
range.from + (range.to - range.from)
)
)
}
view.dispatch(spec)
Composing and inverting changes¶
ChangeSet values support composition and inversion:
// Build a ChangeSet
val changes = state.changes(
ChangeSpec.Single(from = 0, to = 5, insert = InsertContent.StringContent("Hi"))
)
// Apply to get a new document
val newDoc = changes.apply(state.doc)
// Create an undo operation
val undo = changes.invert(state.doc)
// Compose two sequential change sets
val combined = first.compose(second)
Mapping positions¶
When changes modify the document, use mapPos to translate positions from the old document to the new one:
val newPos = changes.mapPos(oldPos)
// Control which side of an insertion to stick to
val newPos = changes.mapPos(oldPos, assoc = 1) // after insertion
Related API¶
TransactionSpec— transaction specificationChangeSpec— change specificationChangeSet— immutable change setEditorSession.dispatch— apply transactions
Based on the CodeMirror Changes example.