|
| 1 | +# TM Partitioner (IDocumentPartitioner) |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +- Partitioning ID: `tm4e.partitioning` |
| 6 | +- Partition type naming: `tm4e:<scopeName>` derived from the active TextMate scope. |
| 7 | + - Examples: `tm4e:text.html.derivative`, `tm4e:text.html.basic`, `tm4e:source.js`, `tm4e:source.css`. |
| 8 | +- Base partition type: |
| 9 | + - Before a grammar is known, the synthetic base type `tm4e:base` is used. |
| 10 | + - After activation with a grammar, the base becomes `tm4e:<grammarScope>` (for example, HTML base `tm4e:text.html.derivative`). |
| 11 | +- Installed automatically by `org.eclipse.tm4e.ui` for any document that resolves a TextMate grammar. It is added as a secondary partitioning and does not replace an editor's default partitioner. |
| 12 | + |
| 13 | +## Partition Semantics |
| 14 | + |
| 15 | +- `computePartitioning(offset, length)` returns regions that cover the entire requested range contiguously. Gaps between known embedded regions are filled with the current base type. |
| 16 | +- `getPartition(offset)` clamps the offset to the valid range `[0, docLength-1]`. Negative offsets resolve to the first region; EOF resolves to the last region. |
| 17 | +- Regions implement `ITMPartitionRegion` (extends `ITypedRegion`) and carry language metadata: |
| 18 | + - `getBaseScope()` returns a normalized root scope such as `source.js` or `text.html`. |
| 19 | + - `getFullScope()` returns the full scope at that position and may include a specific variant, such as `text.html.derivative`. |
| 20 | + |
| 21 | +## How to Consume from Code |
| 22 | + |
| 23 | +Get partitions from the TM4E partitioner via `IDocumentExtension3`: |
| 24 | +```java |
| 25 | +var ext3 = (IDocumentExtension3) doc; |
| 26 | +var partitioner = ext3.getDocumentPartitioner(org.eclipse.tm4e.ui.text.TMPartitions.TM_PARTITIONING /* or "tm4e.partitioning" */); |
| 27 | +ITypedRegion[] regions = partitioner.computePartitioning(offset, length); |
| 28 | +``` |
| 29 | + |
| 30 | +### Example: Content Assist / Feature Code |
| 31 | + |
| 32 | +```java |
| 33 | +import org.eclipse.tm4e.ui.text.ITMPartitionRegion; |
| 34 | +import org.eclipse.tm4e.ui.text.ITMPartitioner; |
| 35 | +import org.eclipse.tm4e.ui.text.TMPartitions; |
| 36 | + |
| 37 | +// ... |
| 38 | + |
| 39 | +IDocument doc = viewer.getDocument(); |
| 40 | +if (doc instanceof IDocumentExtension3 ext3) { |
| 41 | + if (ext3.getDocumentPartitioner(TMPartitions.TM_PARTITIONING) instanceof ITMPartitioner tmPartitioner) { |
| 42 | + ITypedRegion r = tmPartitioner.getPartition(caretOffset); |
| 43 | + // Prefer matching by normalized language scope (handles embedded variants) |
| 44 | + switch(r.getBaseScope()) { |
| 45 | + case "source.js": // offer JavaScript proposals |
| 46 | + case "source.css": // offer CSS proposals |
| 47 | + } |
| 48 | + } |
| 49 | +} |
| 50 | +``` |
| 51 | + |
| 52 | +## Matching by Scope (Recommended) |
| 53 | + |
| 54 | +- Avoid switching on the raw partition type string. Embedded variants may include suffixes (for example, `tm4e:source.css.embedded.html`), so `"tm4e:source.css".equals(type)` will not match. |
| 55 | +- Instead, detect the language using the normalized TextMate scope name (as shown in the example above). This is stable for language families such as `source.css`, `source.js`, or `text.html`. |
| 56 | + |
| 57 | +## Mapping to Content Types (Alternative) |
| 58 | + |
| 59 | +- If your feature keys off `IContentType`, translate the partition at the caret offset: |
| 60 | + |
| 61 | +```java |
| 62 | +IContentType[] cts = org.eclipse.tm4e.ui.text.TMPartitions.getContentTypesForOffset(doc, caretOffset); |
| 63 | +``` |
| 64 | + |
| 65 | +## Generic Editor Contributions |
| 66 | + |
| 67 | +- Register your feature with the Generic Editor as usual (e.g., content assist, hovers). Inside your implementation, use the code above to query TM4E’s partitioning and branch behavior based on the normalized scope (recommended) or the partition type. |
| 68 | +- You do not need to install a partitioner yourself; `org.eclipse.tm4e.ui` installs it automatically when a grammar exists. |
| 69 | + |
| 70 | +Example plugin.xml (content assist): |
| 71 | + |
| 72 | +```xml |
| 73 | +<extension point="org.eclipse.ui.genericeditor.contentAssistProcessors"> |
| 74 | + <contentAssistProcessor |
| 75 | + class="com.example.MyTM4EAwareAssist" |
| 76 | + contentType="org.eclipse.core.runtime.text" |
| 77 | + targetId="org.eclipse.ui.genericeditor.GenericEditor"/> |
| 78 | + <!-- partitionType here refers to the editor's default partitioning; |
| 79 | + to use TM4E partitions, query tm4e.partitioning from your code. --> |
| 80 | + </extension> |
| 81 | +``` |
| 82 | + |
| 83 | +## Utilities |
| 84 | + |
| 85 | +- Check if a document has a TM4E partitioner installed: |
| 86 | + |
| 87 | +```java |
| 88 | +boolean installed = org.eclipse.tm4e.ui.text.TMPartitions.hasPartitioning(doc); |
| 89 | +``` |
| 90 | + |
| 91 | +- Convenience to fetch the TM4E partition at an offset (null if none): |
| 92 | + |
| 93 | +```java |
| 94 | +ITypedRegion part = org.eclipse.tm4e.ui.text.TMPartitions.getPartition(doc, caretOffset); |
| 95 | +``` |
0 commit comments