Nothing
## -----------------------------------------------------------------------------
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
eval = FALSE
)
## -----------------------------------------------------------------------------
# # 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
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.