> ## Documentation Index
> Fetch the complete documentation index at: https://klyx.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Editor & Workspace Tabs

> Open files, create workspace tabs, and handle editor actions

Extensions can interact with Klyx's editor through file openers and workspace tabs. The `FileOpenerRegistry` lets you handle custom file types, while the `Tabs` service manages open workspace tabs.

## FileOpenerRegistry

Register custom file openers to handle opening files with specific extensions. Registration uses Kotlin context receivers.

```kotlin theme={null}
private val openers: FileOpenerRegistry by plugin()

// Inside a KlyxPlugin method:
val registration: FileOpenerRegistration = openers.register(MyFileOpener())
```

### Register an opener

```kotlin theme={null}
class SvgOpener : FileOpener {
    override val id = "myext.svg_opener"
    override val priority = 50

    override suspend fun open(request: FileOpenRequest): WorkspaceTab? {
        if (request.extension != "svg") return null
        return WorkspaceTab.Custom(
            title = request.fileName,
            id = request.uri.toString(),
        ) { SvgViewer(request.uri) }
    }
}
```

Return `null` to let other openers try. Higher `priority` values are consulted first.

### FileOpenRequest

```kotlin theme={null}
data class FileOpenRequest(
    val uri: Uri,           // File URI
    val fileName: String,   // Display name
    val extension: String,  // File extension without dot
    val mimeType: String?,  // MIME type if available
    val projectUri: Uri? = null  // Project URI if inside a project
)
```

### FileOpener interface

| Property   | Type     | Description                                        |
| ---------- | -------- | -------------------------------------------------- |
| `id`       | `String` | Unique opener identifier (reverse-DNS recommended) |
| `priority` | `Int`    | Higher values are tried first (default: 0)         |

| Method          | Returns         | Description                                 |
| --------------- | --------------- | ------------------------------------------- |
| `open(request)` | `WorkspaceTab?` | Return a tab to display, or null to decline |

### FileOpenerRegistration

| Method         | Description                          |
| -------------- | ------------------------------------ |
| `unregister()` | Removes the opener from the registry |

### FileOpenerRegistry methods

| Method             | Returns                  | Description                                                         |
| ------------------ | ------------------------ | ------------------------------------------------------------------- |
| `register(opener)` | `FileOpenerRegistration` | Register an opener (requires `KlyxPlugin` context)                  |
| `unregister(id)`   |                          | Remove an opener by ID                                              |
| `openers()`        | `List<FileOpener>`       | All registered openers, ordered by descending priority              |
| `open(request)`    | `WorkspaceTab?`          | Consult all openers in priority order, return first non-null result |

## WorkspaceTab

A `WorkspaceTab` represents an open tab in Klyx's workspace area.

```kotlin theme={null}
sealed class WorkspaceTab {
    abstract val title: String
    open val id: String  // Defaults to a generated UUID

    data class TextFile(...)
    data class ImageFile(...)
    data object Welcome
    data class Custom(...)
}
```

### TextFile

```kotlin theme={null}
WorkspaceTab.TextFile(
    file = kxFile,                           // KxFile to display
    projectUri = null,                      // Optional project URI
    hasUnsavedChanges = false,               // Flag for dirty state
    title = kxFile.name,                     // Override the tab title
    id = kxFile.uri.toString()               // Override the tab ID
)
```

### ImageFile

```kotlin theme={null}
WorkspaceTab.ImageFile(
    uri = imageUri,                          // URI of the image
    projectUri = null,                       // Optional project URI
    title = "image.png",                     // Display title
    id = imageUri.toString()                 // Optional custom ID
)
```

### Welcome

```kotlin theme={null}
WorkspaceTab.Welcome  // The default welcome screen
```

### Custom

```kotlin theme={null}
WorkspaceTab.Custom(
    title = request.fileName,
    id = request.uri.toString(),
    content = { MyCustomViewer() },
    onClose = { /* optional suspend cleanup */ },
    pluginId = null                          // Optional owning plugin ID
)
```

| Type                     | Description                        |
| ------------------------ | ---------------------------------- |
| `WorkspaceTab.TextFile`  | Text file with syntax highlighting |
| `WorkspaceTab.ImageFile` | Image viewer                       |
| `WorkspaceTab.Welcome`   | The default welcome screen         |
| `WorkspaceTab.Custom`    | Any custom composable content      |

## Tabs service

Manage open workspace tabs with the `Tabs` service.

```kotlin theme={null}
private val tabs: Tabs by plugin()
```

| Property  | Returns              | Description              |
| --------- | -------------------- | ------------------------ |
| `current` | `WorkspaceTab?`      | The currently active tab |
| `opened`  | `List<WorkspaceTab>` | All open tabs            |

| Method       | Description                                       |
| ------------ | ------------------------------------------------- |
| `open(tab)`  | Opens a new tab or switches to it if already open |
| `close(id)`  | Closes the tab with the specified ID              |
| `select(id)` | Switches to the tab with the specified ID         |
| `get(id)`    | Retrieves a tab by ID (operator `tabs[id]`)       |

```kotlin theme={null}
tabs.open(WorkspaceTab.Custom(title = "My Panel", id = "myext.panel") { MyPanel() })
tabs.close("myext.panel")
tabs.select("myext.panel")
val tab: WorkspaceTab? = tabs["myext.panel"]
```

## EditorAction

`EditorAction` represents actions that can be performed on editor content. This is primarily used internally but can be extended.

| Action                                   | Description                     |
| ---------------------------------------- | ------------------------------- |
| `EditorAction.Save(file)`                | Save the file                   |
| `EditorAction.SaveAs(oldTabId, newFile)` | Save the file to a new location |
