How can I create an "actions" function and table of actions?

Hi there! Welcome to the Forum.
The actions.at() doesn’t work, because it references the at method of the state element itself, not the dictionary (see the typst doc). The at function of the state expects a location in the document or something like that (label etc.), so that’s what the error is about. Here is:

// Create a dictionary to store actions for each assignee.  
// The key will be the assignee and the value will be array of actions
// Due to scoping constraints, use the "state" function
#let actions = state("actions", (:))

// Define a helper function to add an action to the global dictionary
#let _add_action(actions, assignee, action) = {
  if not assignee in actions {
    actions.insert(assignee, (action,))
  }
  else {
  actions.at(assignee).push(action)
  }
  return actions
}

// Define an action for use in the body text
#let action(body, assignee: "", side: left) = {
    // Add action to the global state to be able to render a table later
    actions.update(x => _add_action(x, assignee, body))
    // Display the action text inline as usual
    body
    // Mark the presence of an action in a sidenote with the assignee
    // margin-note(side: side)[#strong("Action:") #assignee]
}

Here's an example of text with an #action(assignee: "Ben")[action for Ben to do]

#action(assignee: "Ben")[new action for Ben to do].

The current content of actions: 

#context actions.get()

#action(assignee: "Steven")[a new person with some action].

#action(assignee: "Steven")[steven action].

The current content of actions: 

#context actions.get()

Note that I commented the “margin-note” out, because you didn’t provide the function, so it wouldn’t compile otherwise.
I mainly changed the update function to “actions.update(x => _add_action(x, assignee, body))”. I also changed the helper function so it adds the actions to the array in the dictionary entry if it is present and add a dictionary entry otherwise. The x in the “actions.update” is the old value of the state and the content behind the “=>” is the new value of the state. The helper function _add_action now changes the x (which is the first parameter of the function) and returns the new value.

If there are any questions left or I misunderstood something, don’t hesitate to ask again :slight_smile:. If this answer solves your problem, please mark it as the solution.

PS: when initializing the state, you can use “state(“actions”, (:))” to initialze an empty dictionary.

2 Likes