# `Masu.Issho`
[🔗](https://github.com/hattoriai/masu/blob/v0.7.0/lib/masu/issho.ex#L2)

Masu's grids in [Issho](https://hex.pm/packages/issho)'s rooms: agents
read and change a grid as a person does, and the people who have it
open see where they are and what they change.

A grid is named as a document is, `"room/grid"` (`"notebook:42/tasks"`):
its `issho` `:document`, whose room is the part before the first
`"/"`. A place in a grid is `Masu.Issho.Place`. Its rows stay
the grid's own: its source reads them, and its writes save them, the
grid's way (`Masu.Sheet`). Issho carries who is there and where.

## The grids an agent may use

Your app says which grid a name is, for whom, with a function of the
name and the agent's `Issho.Tool.Context`, which gives the grid's
attributes (those of `data_grid/1`, and `scope`, for its writes):

    config :masu, Masu.Issho, grids: {MyApp.Grids, :for_agent}

    def for_agent("project:" <> rest, ctx) do
      [project_id, "tasks"] = String.split(rest, "/")
      scope = MyApp.Accounts.scope_for(ctx.opts[:on_behalf_of])
      {:ok, Keyword.put(tasks(scope, project_id), :scope, scope)}
    end

    def for_agent(_grid, _ctx), do: {:error, "There is no such grid."}

The agent is in the room (the room's policy lets it join), and each
write asks the policy too (`:write`), before the grid's own rules.

## Tools

`tools/0`: read a grid (in an order, filtered, searched), point at
cells, edit cells, add rows and delete rows. Give them to an agent
with Issho's (`Issho.Tools.room/0`), over MCP (`Issho.MCP`) or your
app's own model (`Issho.Tools`).

`config :masu, Masu.Issho, pace: 120, travel: true`: `pace`, the
milliseconds an agent stays on each cell it edits, typing, so the
people see it (0 for none); `travel`, whether it goes to each cell and
selects ranges as a drag does, as a person would (false: it is there at
once). Only where it goes is sent: each browser draws the way there.

An agent that a person paused or stopped (`Issho.Work`) changes the
grid no more: `select_cells`, `edit_cells`, `add_rows` and
`delete_rows` say who paused it and what to do, as Issho's tools do;
`read_grid` still reads. An edit of many cells, one by one, stops at
the cell it is on.

## Comments

Issho's comments (`Issho.Components.comments/1`) go on a cell or a
range of a grid as on any place, and their marks are drawn on the
cells. `label/2` says such a place in words, for the `:place` slot.

# `label`

```elixir
@spec label(map() | nil, keyword()) :: String.t() | nil
```

A place of a grid in words, for people: `"City of Acme"` for a cell,
`"Name to City of Acme"` for a range in a row, `"City of 3 rows"` for a
range of rows. `nil` for no place, or a place of another grid, so that
the words of whoever asks stay theirs. For the `:place` slot of Issho's
comments:

    <.comments id="comments" room="orders:42">
      <:place :let={%{place: place, default: default}}>
        {Masu.Issho.label(place, grid: "orders:42/orders", columns: @labels, row: &order_name/1) ||
          default}
      </:place>
    </.comments>

A place is in the grid's terms (`Masu.Issho.Place`), not a row's
number, as each person has their own order: name a row by its content.

Options:

  * `:grid`, the grid's document: a place of another document gives
    `nil`. Any grid's place, without it.
  * `:columns`, the columns' labels by key, as a map or a list of
    pairs (`%{"city" => "City"}`); a key that is not there is itself.
  * `:row`, a function of a row's id that gives its name (`"Acme"`),
    or `nil` for `"row 7"`.

# `place`

```elixir
@spec place(String.t(), {term(), String.t()} | {[term()], [String.t()]}) :: map()
```

The place of a cell, or of a range of rows and keys, in a grid of a room.

# `tools`

```elixir
@spec tools() :: [module()]
```

Masu's tools for agents.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
