Nothing
#| include: false knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE )
One-page reference for the automerge package. See full documentation with ?function_name.
# From R-universe install.packages("automerge", repos = "https://posit-dev.r-universe.dev") # From GitHub pak::pak("posit-dev/automerge-r")
library(automerge) # Create doc <- am_create() # New document doc <- am_create("fd3ca50687f13477f1f9ea2b216b958a") # With custom actor ID # Load/Save bytes <- am_save(doc) # Save to bytes doc <- am_load(bytes) # Load from bytes # Actor ID actor <- am_get_actor(doc) # Get actor ID (raw bytes) actor_hex <- am_get_actor_hex(doc) # Get actor ID as hex string am_set_actor(doc, actor_hex) # Set actor ID (raw, hex, or NULL) # Fork/Merge doc2 <- am_fork(doc) # Create independent copy am_merge(doc, doc2) # Merge doc2 into doc1 # Transactions am_commit(doc, "message") # Commit changes am_rollback(doc) # Cancel pending changes # Cleanup am_close(doc) # Explicitly free resources (optional)
# S3 operators doc[["key"]] <- "value" # Set value value <- doc[["key"]] # Get value doc$key <- value # Alternative syntax value <- doc$key # Alternative syntax # Functional API am_delete(doc, AM_ROOT, "key") # Delete key am_put(doc, AM_ROOT, "key", value) # Set value value <- am_get(doc, AM_ROOT, "key") # Get value # Introspection keys <- names(doc) # Get all keys keys <- am_keys(doc, AM_ROOT) # Functional version values <- am_values(doc, AM_ROOT) # Get all values n <- length(doc) # Number of keys n <- am_length(doc, AM_ROOT) # Functional version
# Automatic recursive conversion (recommended) am_put( doc, AM_ROOT, "user", list( name = "Alice", age = 30L, address = list(city = "NYC", zip = 10001L) ) ) # Path-based access (simple for deep structures) am_put_path(doc, c("user", "address", "city"), "Boston") city <- am_get_path(doc, c("user", "address", "city")) am_delete_path(doc, c("user", "address")) # Manual access user_obj <- am_get(doc, AM_ROOT, "user") am_put(doc, user_obj, "name", "Bob") name <- am_get(doc, user_obj, "name")
# Create list am_put(doc, AM_ROOT, "items", AM_OBJ_TYPE_LIST) items <- am_get(doc, AM_ROOT, "items") # Operations (1-based indexing) am_insert(doc, items, 1, "first") # Insert at index 1 am_put(doc, items, 1, "FIRST") # Replace at index 1 am_put(doc, items, "end", "append") # Append to end value <- am_get(doc, items, 1) # Get index 1 am_delete(doc, items, 1) # Delete index 1 # Introspection n <- am_length(doc, items) # List length
# Text objects use 0-based inter-character positions # For the text "Hello": # H e l l o # 0 1 2 3 4 5 <- positions (0-based, between characters) # Create text object am_put(doc, AM_ROOT, "content", am_text("Hello")) text_obj <- am_get(doc, AM_ROOT, "content") # Operations am_text_splice(text_obj, 5, 0, " World") # Insert at position 5 content <- am_text_content(text_obj) # Get full text # Update text (ideal for collaborative editing) old_text <- am_text_content(text_obj) am_text_update(text_obj, old_text, "Hello Universe") # Computes and applies diff # Cursors (stable positions) cursor <- am_cursor(text_obj, 5) # Create cursor at position 5 pos <- am_cursor_position(cursor) # Get current position # Marks (formatting) am_mark(text_obj, 0, 5, "bold", TRUE, expand = "none") marks <- am_marks(text_obj) # Get all marks marks_at <- am_marks_at(text_obj, 2) # Marks at position 2
# NULL am_put(doc, AM_ROOT, "null", NULL) # Boolean am_put(doc, AM_ROOT, "bool", TRUE) # Integer am_put(doc, AM_ROOT, "int", 42L) # Double am_put(doc, AM_ROOT, "float", 3.14) # String am_put(doc, AM_ROOT, "str", "text") # Raw bytes am_put(doc, AM_ROOT, "bytes", raw(10)) # Timestamp am_put(doc, AM_ROOT, "time", Sys.time()) # Counter am_put(doc, AM_ROOT, "score", am_counter(0)) am_counter_increment(doc, AM_ROOT, "score", 10) value <- am_get(doc, AM_ROOT, "score") # Unsigned 64-bit integer (for cross-platform interop) am_put(doc, AM_ROOT, "id", am_uint64(12345)) # Explicit type constructors am_put(doc, AM_ROOT, "items", am_list()) # Empty list am_put(doc, AM_ROOT, "config", am_map()) # Empty map am_put(doc, AM_ROOT, "notes", am_text()) # Text object
# Bidirectional sync (auto-converge) # Documents are modified in place rounds <- am_sync(doc1, doc2) cat("Converged in", rounds, "rounds\n") # One-way merge am_merge(doc1, doc2) # Merge doc2 into doc1
# Create sync state sync_state <- am_sync_state_new() # Encode/decode messages msg <- am_sync_encode(doc, sync_state) am_sync_decode(doc, sync_state, msg) # Manual sync loop repeat { msg1 <- am_sync_encode(doc1, sync1) if (is.null(msg1)) { break } am_sync_decode(doc2, sync2, msg1) msg2 <- am_sync_encode(doc2, sync2) if (is.null(msg2)) { break } am_sync_decode(doc1, sync1, msg2) }
# Get heads heads <- am_get_heads(doc) # Get changes changes <- am_get_changes(doc, NULL) # All changes changes <- am_get_changes(doc, heads) # Since specific heads # Apply changes am_apply_changes(doc, changes) # Full history history <- am_get_history(doc)
# R → Automerge doc <- as_automerge(list(name = "Alice", age = 30L)) # Automerge → R r_list <- from_automerge(doc) r_list <- as.list(doc) # S3 method for documents text_str <- as.character(text_obj) # S3 method for text objects
doc <- am_create() |> am_put(AM_ROOT, "name", "Alice") |> am_put(AM_ROOT, "age", 30L) |> am_commit("Initial data")
# Save to file writeBin(am_save(doc), "document.automerge") # Load from file doc <- am_load(readBin("document.automerge", "raw", 1e6))
AM_ROOT # Root object (NULL) AM_OBJ_TYPE_LIST # "list" AM_OBJ_TYPE_MAP # "map" AM_OBJ_TYPE_TEXT # "text" AM_MARK_EXPAND_NONE # "none" (mark doesn't expand at boundaries) AM_MARK_EXPAND_BEFORE # "before" (expands when text inserted before start) AM_MARK_EXPAND_AFTER # "after" (expands when text inserted after end) AM_MARK_EXPAND_BOTH # "both" (expands at both boundaries)
# Function help ?am_create ?am_put ?am_sync # Package help ?automerge help(package = "automerge") # Vignettes vignette("automerge", "automerge") vignette("crdt-concepts", "automerge") vignette("sync-protocol", "automerge") vignette(package = "automerge") # List all
Note: This is a quick reference. See full vignettes for detailed examples and explanations.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.