Skip to content

Commit 8489f00

Browse files
committed
feat: add TextMate document partitioner
1 parent f85de1e commit 8489f00

File tree

15 files changed

+1852
-54
lines changed

15 files changed

+1852
-54
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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+
```

org.eclipse.tm4e.ui.tests/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<extension
1616
point="org.eclipse.core.contenttype.contentTypes">
1717
<content-type
18+
base-type="org.eclipse.core.runtime.text"
1819
file-extensions="ts"
1920
id="org.eclipse.tm4e.ui.tests.testContentType"
2021
name="Test Content Type for TM4E (typescipt)"

0 commit comments

Comments
 (0)