@fresh-editor/fresh-editor 0.1.86 → 0.1.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +4 -0
- package/package.json +1 -1
- package/plugins/README.md +1 -0
- package/plugins/audit_mode.ts +38 -34
- package/plugins/calculator.ts +6 -6
- package/plugins/examples/virtual_buffer_demo.ts +4 -4
- package/plugins/git_blame.ts +3 -3
- package/plugins/git_explorer.ts +3 -2
- package/plugins/git_log.ts +10 -10
- package/plugins/java-lsp.ts +65 -0
- package/plugins/latex-lsp.ts +65 -0
- package/plugins/lib/finder.ts +32 -32
- package/plugins/lib/fresh.d.ts +430 -18
- package/plugins/lib/panel-manager.ts +7 -7
- package/plugins/lib/search-utils.ts +13 -13
- package/plugins/lib/virtual-buffer-factory.ts +16 -14
- package/plugins/markdown_compose.ts +4 -4
- package/plugins/marksman-lsp.ts +65 -0
- package/plugins/merge_conflict.ts +21 -21
- package/plugins/search_replace.ts +6 -6
- package/plugins/templ-lsp.ts +65 -0
- package/plugins/theme_editor.ts +6 -5
- package/plugins/vi_mode.ts +2 -2
- package/plugins/zig-lsp.ts +65 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Release Notes
|
|
2
2
|
|
|
3
|
+
## 0.1.87
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **Language Support**: Added LSP configurations and syntax highlighting for Zig, Java, LaTeX, Markdown, and Templ.
|
|
8
|
+
* **Git File Highlighting**: Syntax highlighting for git-related files (.gitignore, .gitattributes, .gitmodules).
|
|
9
|
+
* **Plugin Type Safety**: TypeScript type definitions for plugin API with compile-time validation.
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **Hover Popup**: Fixed scrolling to bottom, dismiss on click outside, block clicks inside popup.
|
|
14
|
+
* **Settings UI**: Fixed overwriting manual config.json edits when saving from Settings UI (#806).
|
|
15
|
+
* **Windows Terminal**: Fixed truecolor detection and 256-color grayscale conversion overflow.
|
|
16
|
+
* **Composite Buffers**: Fixed mouse click sync, deserialization errors, and cursor positioning.
|
|
17
|
+
* **Plugin Stability**: Plugin thread panics now propagate to main thread for proper error handling.
|
|
18
|
+
* **Review Diff Plugin**: Fixed side-by-side diff commands not appearing in command palette.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
3
22
|
## 0.1.86
|
|
4
23
|
|
|
5
24
|
### Features
|
package/README.md
CHANGED
|
@@ -241,6 +241,10 @@ Thanks for contributing!
|
|
|
241
241
|
|
|
242
242
|
7. **LSP**: Ensure LSP interactions follow the correct lifecycle (e.g., `didOpen` must always precede other requests to avoid server-side errors). Use the appropriate existing helpers for this pattern.
|
|
243
243
|
|
|
244
|
+
8. **Regenerate plugin types**: After modifying the plugin API, run `cargo test -p fresh-plugin-runtime write_fresh_dts_file -- --ignored`
|
|
245
|
+
|
|
246
|
+
9. **Type check plugins**: Run `crates/fresh-editor/plugins/check-types.sh` (requires `tsc`)
|
|
247
|
+
|
|
244
248
|
**Tip**: You can use tmux + send-keys + render-pane to script ad-hoc tests on the UI, for example when trying to reproduce an issue.
|
|
245
249
|
|
|
246
250
|
## Privacy
|
package/package.json
CHANGED
package/plugins/README.md
CHANGED
package/plugins/audit_mode.ts
CHANGED
|
@@ -551,7 +551,7 @@ async function renderReviewStream(): Promise<{ entries: TextPropertyEntry[], hig
|
|
|
551
551
|
* Updates the buffer UI (text and highlights) based on current state.hunks
|
|
552
552
|
*/
|
|
553
553
|
async function updateReviewUI() {
|
|
554
|
-
if (state.reviewBufferId
|
|
554
|
+
if (state.reviewBufferId != null) {
|
|
555
555
|
const { entries, highlights } = await renderReviewStream();
|
|
556
556
|
editor.setVirtualBufferContent(state.reviewBufferId, entries);
|
|
557
557
|
|
|
@@ -677,12 +677,12 @@ globalThis.on_viewport_changed = (data: any) => {
|
|
|
677
677
|
|
|
678
678
|
const { oldSplitId, newSplitId, oldLineByteOffsets, newLineByteOffsets } = activeSideBySideState;
|
|
679
679
|
|
|
680
|
-
if (data.
|
|
680
|
+
if (data.splitId === oldSplitId && newLineByteOffsets.length > 0) {
|
|
681
681
|
// OLD pane scrolled - find which line it's on and sync NEW pane to same line
|
|
682
682
|
const lineNum = findLineForByte(oldLineByteOffsets, data.top_byte);
|
|
683
683
|
const targetByte = newLineByteOffsets[Math.min(lineNum, newLineByteOffsets.length - 1)];
|
|
684
684
|
(editor as any).setSplitScroll(newSplitId, targetByte);
|
|
685
|
-
} else if (data.
|
|
685
|
+
} else if (data.splitId === newSplitId && oldLineByteOffsets.length > 0) {
|
|
686
686
|
// NEW pane scrolled - find which line it's on and sync OLD pane to same line
|
|
687
687
|
const lineNum = findLineForByte(newLineByteOffsets, data.top_byte);
|
|
688
688
|
const targetByte = oldLineByteOffsets[Math.min(lineNum, oldLineByteOffsets.length - 1)];
|
|
@@ -1100,7 +1100,7 @@ globalThis.review_drill_down = async () => {
|
|
|
1100
1100
|
}));
|
|
1101
1101
|
|
|
1102
1102
|
// Create source buffers (hidden from tabs, used by composite)
|
|
1103
|
-
const
|
|
1103
|
+
const oldResult = await editor.createVirtualBuffer({
|
|
1104
1104
|
name: `*OLD:${h.file}*`,
|
|
1105
1105
|
mode: "normal",
|
|
1106
1106
|
readOnly: true,
|
|
@@ -1109,8 +1109,9 @@ globalThis.review_drill_down = async () => {
|
|
|
1109
1109
|
editingDisabled: true,
|
|
1110
1110
|
hiddenFromTabs: true
|
|
1111
1111
|
});
|
|
1112
|
+
const oldBufferId = oldResult.bufferId;
|
|
1112
1113
|
|
|
1113
|
-
const
|
|
1114
|
+
const newResult = await editor.createVirtualBuffer({
|
|
1114
1115
|
name: `*NEW:${h.file}*`,
|
|
1115
1116
|
mode: "normal",
|
|
1116
1117
|
readOnly: true,
|
|
@@ -1119,6 +1120,7 @@ globalThis.review_drill_down = async () => {
|
|
|
1119
1120
|
editingDisabled: true,
|
|
1120
1121
|
hiddenFromTabs: true
|
|
1121
1122
|
});
|
|
1123
|
+
const newBufferId = newResult.bufferId;
|
|
1122
1124
|
|
|
1123
1125
|
// Convert hunks to composite buffer format (parse counts from git diff)
|
|
1124
1126
|
const compositeHunks: TsCompositeHunk[] = fileHunks.map(fh => {
|
|
@@ -1130,10 +1132,10 @@ globalThis.review_drill_down = async () => {
|
|
|
1130
1132
|
else if (line.startsWith(' ')) { oldCount++; newCount++; }
|
|
1131
1133
|
}
|
|
1132
1134
|
return {
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1135
|
+
oldStart: fh.oldRange.start - 1, // Convert to 0-indexed
|
|
1136
|
+
oldCount: oldCount || 1,
|
|
1137
|
+
newStart: fh.range.start - 1, // Convert to 0-indexed
|
|
1138
|
+
newCount: newCount || 1
|
|
1137
1139
|
};
|
|
1138
1140
|
});
|
|
1139
1141
|
|
|
@@ -1142,27 +1144,27 @@ globalThis.review_drill_down = async () => {
|
|
|
1142
1144
|
name: `*Diff: ${h.file}*`,
|
|
1143
1145
|
mode: "diff-view",
|
|
1144
1146
|
layout: {
|
|
1145
|
-
|
|
1147
|
+
type: "side-by-side",
|
|
1146
1148
|
ratios: [0.5, 0.5],
|
|
1147
|
-
|
|
1149
|
+
showSeparator: true
|
|
1148
1150
|
},
|
|
1149
1151
|
sources: [
|
|
1150
1152
|
{
|
|
1151
|
-
|
|
1153
|
+
bufferId: oldBufferId,
|
|
1152
1154
|
label: "OLD (HEAD)",
|
|
1153
1155
|
editable: false,
|
|
1154
1156
|
style: {
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
+
removeBg: [80, 40, 40],
|
|
1158
|
+
gutterStyle: "diff-markers"
|
|
1157
1159
|
}
|
|
1158
1160
|
},
|
|
1159
1161
|
{
|
|
1160
|
-
|
|
1162
|
+
bufferId: newBufferId,
|
|
1161
1163
|
label: "NEW (Working)",
|
|
1162
1164
|
editable: false,
|
|
1163
1165
|
style: {
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
+
addBg: [40, 80, 40],
|
|
1167
|
+
gutterStyle: "diff-markers"
|
|
1166
1168
|
}
|
|
1167
1169
|
}
|
|
1168
1170
|
],
|
|
@@ -1518,7 +1520,7 @@ globalThis.on_review_buffer_activated = (data: any) => {
|
|
|
1518
1520
|
};
|
|
1519
1521
|
|
|
1520
1522
|
globalThis.on_review_buffer_closed = (data: any) => {
|
|
1521
|
-
if (data.buffer_id === state.reviewBufferId) stop_review_diff();
|
|
1523
|
+
if (data.buffer_id === state.reviewBufferId) globalThis.stop_review_diff();
|
|
1522
1524
|
};
|
|
1523
1525
|
|
|
1524
1526
|
// Side-by-side diff for current file using composite buffers
|
|
@@ -1663,7 +1665,7 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1663
1665
|
}));
|
|
1664
1666
|
|
|
1665
1667
|
// Create source buffers (hidden from tabs, used by composite)
|
|
1666
|
-
const
|
|
1668
|
+
const oldResult = await editor.createVirtualBuffer({
|
|
1667
1669
|
name: `*OLD:${filePath}*`,
|
|
1668
1670
|
mode: "normal",
|
|
1669
1671
|
readOnly: true,
|
|
@@ -1672,8 +1674,9 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1672
1674
|
editingDisabled: true,
|
|
1673
1675
|
hiddenFromTabs: true
|
|
1674
1676
|
});
|
|
1677
|
+
const oldBufferId = oldResult.bufferId;
|
|
1675
1678
|
|
|
1676
|
-
const
|
|
1679
|
+
const newResult = await editor.createVirtualBuffer({
|
|
1677
1680
|
name: `*NEW:${filePath}*`,
|
|
1678
1681
|
mode: "normal",
|
|
1679
1682
|
readOnly: true,
|
|
@@ -1682,13 +1685,14 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1682
1685
|
editingDisabled: true,
|
|
1683
1686
|
hiddenFromTabs: true
|
|
1684
1687
|
});
|
|
1688
|
+
const newBufferId = newResult.bufferId;
|
|
1685
1689
|
|
|
1686
1690
|
// Convert hunks to composite buffer format
|
|
1687
1691
|
const compositeHunks: TsCompositeHunk[] = fileHunks.map(h => ({
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
+
oldStart: h.oldRange.start - 1, // Convert to 0-indexed
|
|
1693
|
+
oldCount: h.oldRange.end - h.oldRange.start + 1,
|
|
1694
|
+
newStart: h.range.start - 1, // Convert to 0-indexed
|
|
1695
|
+
newCount: h.range.end - h.range.start + 1
|
|
1692
1696
|
}));
|
|
1693
1697
|
|
|
1694
1698
|
// Create composite buffer with side-by-side layout
|
|
@@ -1696,27 +1700,27 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1696
1700
|
name: `*Diff: ${filePath}*`,
|
|
1697
1701
|
mode: "diff-view",
|
|
1698
1702
|
layout: {
|
|
1699
|
-
|
|
1703
|
+
type: "side-by-side",
|
|
1700
1704
|
ratios: [0.5, 0.5],
|
|
1701
|
-
|
|
1705
|
+
showSeparator: true
|
|
1702
1706
|
},
|
|
1703
1707
|
sources: [
|
|
1704
1708
|
{
|
|
1705
|
-
|
|
1709
|
+
bufferId: oldBufferId,
|
|
1706
1710
|
label: "OLD (HEAD)",
|
|
1707
1711
|
editable: false,
|
|
1708
1712
|
style: {
|
|
1709
|
-
|
|
1710
|
-
|
|
1713
|
+
removeBg: [80, 40, 40],
|
|
1714
|
+
gutterStyle: "diff-markers"
|
|
1711
1715
|
}
|
|
1712
1716
|
},
|
|
1713
1717
|
{
|
|
1714
|
-
|
|
1718
|
+
bufferId: newBufferId,
|
|
1715
1719
|
label: "NEW (Working)",
|
|
1716
1720
|
editable: false,
|
|
1717
1721
|
style: {
|
|
1718
|
-
|
|
1719
|
-
|
|
1722
|
+
addBg: [40, 80, 40],
|
|
1723
|
+
gutterStyle: "diff-markers"
|
|
1720
1724
|
}
|
|
1721
1725
|
}
|
|
1722
1726
|
],
|
|
@@ -1746,10 +1750,10 @@ globalThis.side_by_side_diff_current_file = async () => {
|
|
|
1746
1750
|
};
|
|
1747
1751
|
|
|
1748
1752
|
// Register Modes and Commands
|
|
1749
|
-
editor.registerCommand("%cmd.review_diff", "%cmd.review_diff_desc", "start_review_diff",
|
|
1753
|
+
editor.registerCommand("%cmd.review_diff", "%cmd.review_diff_desc", "start_review_diff", null);
|
|
1750
1754
|
editor.registerCommand("%cmd.stop_review_diff", "%cmd.stop_review_diff_desc", "stop_review_diff", "review-mode");
|
|
1751
1755
|
editor.registerCommand("%cmd.refresh_review_diff", "%cmd.refresh_review_diff_desc", "review_refresh", "review-mode");
|
|
1752
|
-
editor.registerCommand("%cmd.side_by_side_diff", "%cmd.side_by_side_diff_desc", "side_by_side_diff_current_file",
|
|
1756
|
+
editor.registerCommand("%cmd.side_by_side_diff", "%cmd.side_by_side_diff_desc", "side_by_side_diff_current_file", null);
|
|
1753
1757
|
|
|
1754
1758
|
// Review Comment Commands
|
|
1755
1759
|
editor.registerCommand("%cmd.add_comment", "%cmd.add_comment_desc", "review_add_comment", "review-mode");
|
package/plugins/calculator.ts
CHANGED
|
@@ -711,16 +711,16 @@ globalThis.calculator_open = async function (): Promise<void> {
|
|
|
711
711
|
|
|
712
712
|
const entries = renderCalculator();
|
|
713
713
|
|
|
714
|
-
|
|
714
|
+
const result = await editor.createVirtualBuffer({
|
|
715
715
|
name: "*Calculator*",
|
|
716
716
|
mode: "calculator",
|
|
717
|
-
|
|
717
|
+
readOnly: true,
|
|
718
718
|
entries,
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
719
|
+
showLineNumbers: false,
|
|
720
|
+
showCursors: false,
|
|
721
|
+
editingDisabled: true,
|
|
722
722
|
});
|
|
723
|
-
|
|
723
|
+
state.bufferId = result.bufferId;
|
|
724
724
|
state.splitId = editor.getActiveSplitId();
|
|
725
725
|
|
|
726
726
|
editor.setStatus(editor.t("status.opened"));
|
|
@@ -97,12 +97,12 @@ globalThis.show_virtual_buffer_demo = async () => {
|
|
|
97
97
|
const bufferId = await editor.createVirtualBufferInSplit({
|
|
98
98
|
name: "*Demo Diagnostics*",
|
|
99
99
|
mode: "demo-list",
|
|
100
|
-
|
|
100
|
+
readOnly: true,
|
|
101
101
|
entries: entries,
|
|
102
102
|
ratio: 0.7, // Original pane takes 70%, demo buffer takes 30%
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
panelId: "demo-diagnostics",
|
|
104
|
+
showLineNumbers: false,
|
|
105
|
+
showCursors: true,
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
editor.setStatus(`Created demo virtual buffer (ID: ${bufferId}) with ${entries.length} items - Press RET to jump to location`);
|
package/plugins/git_blame.ts
CHANGED
|
@@ -478,7 +478,7 @@ globalThis.show_git_blame = async function(): Promise<void> {
|
|
|
478
478
|
}
|
|
479
479
|
|
|
480
480
|
// Create virtual buffer with the file content
|
|
481
|
-
const
|
|
481
|
+
const result = await editor.createVirtualBufferInExistingSplit({
|
|
482
482
|
name: bufferName,
|
|
483
483
|
mode: "git-blame",
|
|
484
484
|
readOnly: true,
|
|
@@ -489,9 +489,9 @@ globalThis.show_git_blame = async function(): Promise<void> {
|
|
|
489
489
|
editingDisabled: true,
|
|
490
490
|
});
|
|
491
491
|
|
|
492
|
-
if (
|
|
492
|
+
if (result !== null) {
|
|
493
493
|
blameState.isOpen = true;
|
|
494
|
-
blameState.bufferId = bufferId;
|
|
494
|
+
blameState.bufferId = result.bufferId;
|
|
495
495
|
|
|
496
496
|
// Add virtual lines for blame headers (persistent state model)
|
|
497
497
|
addBlameHeaders();
|
package/plugins/git_explorer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/// <reference path="
|
|
1
|
+
/// <reference path="./lib/fresh.d.ts" />
|
|
2
2
|
const editor = getEditor();
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -133,8 +133,9 @@ async function refreshGitExplorerDecorations() {
|
|
|
133
133
|
} else {
|
|
134
134
|
editor.setFileExplorerDecorations(NAMESPACE, decorations);
|
|
135
135
|
}
|
|
136
|
-
} catch (
|
|
136
|
+
} catch (err) {
|
|
137
137
|
editor.clearFileExplorerDecorations(NAMESPACE);
|
|
138
|
+
throw err;
|
|
138
139
|
} finally {
|
|
139
140
|
refreshInFlight = false;
|
|
140
141
|
}
|
package/plugins/git_log.ts
CHANGED
|
@@ -763,7 +763,7 @@ globalThis.show_git_log = async function(): Promise<void> {
|
|
|
763
763
|
gitLogState.cachedContent = entriesToContent(entries);
|
|
764
764
|
|
|
765
765
|
// Create virtual buffer in the current split (replacing current buffer)
|
|
766
|
-
const
|
|
766
|
+
const result = await editor.createVirtualBufferInExistingSplit({
|
|
767
767
|
name: "*Git Log*",
|
|
768
768
|
mode: "git-log",
|
|
769
769
|
readOnly: true,
|
|
@@ -774,9 +774,9 @@ globalThis.show_git_log = async function(): Promise<void> {
|
|
|
774
774
|
editingDisabled: true,
|
|
775
775
|
});
|
|
776
776
|
|
|
777
|
-
if (
|
|
777
|
+
if (result !== null) {
|
|
778
778
|
gitLogState.isOpen = true;
|
|
779
|
-
gitLogState.bufferId = bufferId;
|
|
779
|
+
gitLogState.bufferId = result.bufferId;
|
|
780
780
|
|
|
781
781
|
// Apply syntax highlighting
|
|
782
782
|
applyGitLogHighlighting();
|
|
@@ -897,7 +897,7 @@ globalThis.git_log_show_commit = async function(): Promise<void> {
|
|
|
897
897
|
commitDetailState.cachedContent = entriesToContent(entries);
|
|
898
898
|
|
|
899
899
|
// Create virtual buffer in the current split (replacing git log view)
|
|
900
|
-
const
|
|
900
|
+
const result = await editor.createVirtualBufferInExistingSplit({
|
|
901
901
|
name: `*Commit: ${commit.shortHash}*`,
|
|
902
902
|
mode: "git-commit-detail",
|
|
903
903
|
readOnly: true,
|
|
@@ -908,9 +908,9 @@ globalThis.git_log_show_commit = async function(): Promise<void> {
|
|
|
908
908
|
editingDisabled: true,
|
|
909
909
|
});
|
|
910
910
|
|
|
911
|
-
if (
|
|
911
|
+
if (result !== null) {
|
|
912
912
|
commitDetailState.isOpen = true;
|
|
913
|
-
commitDetailState.bufferId = bufferId;
|
|
913
|
+
commitDetailState.bufferId = result.bufferId;
|
|
914
914
|
commitDetailState.splitId = gitLogState.splitId;
|
|
915
915
|
commitDetailState.commit = commit;
|
|
916
916
|
|
|
@@ -1210,7 +1210,7 @@ globalThis.git_commit_detail_open_file = async function(): Promise<void> {
|
|
|
1210
1210
|
}
|
|
1211
1211
|
|
|
1212
1212
|
// Create a read-only virtual buffer with the file content
|
|
1213
|
-
const
|
|
1213
|
+
const result = await editor.createVirtualBufferInExistingSplit({
|
|
1214
1214
|
name: `${file} @ ${commit.shortHash}`,
|
|
1215
1215
|
mode: "git-file-view",
|
|
1216
1216
|
readOnly: true,
|
|
@@ -1221,16 +1221,16 @@ globalThis.git_commit_detail_open_file = async function(): Promise<void> {
|
|
|
1221
1221
|
editingDisabled: true,
|
|
1222
1222
|
});
|
|
1223
1223
|
|
|
1224
|
-
if (
|
|
1224
|
+
if (result !== null) {
|
|
1225
1225
|
// Track file view state so we can navigate back
|
|
1226
1226
|
fileViewState.isOpen = true;
|
|
1227
|
-
fileViewState.bufferId = bufferId;
|
|
1227
|
+
fileViewState.bufferId = result.bufferId;
|
|
1228
1228
|
fileViewState.splitId = commitDetailState.splitId;
|
|
1229
1229
|
fileViewState.filePath = file;
|
|
1230
1230
|
fileViewState.commitHash = commit.hash;
|
|
1231
1231
|
|
|
1232
1232
|
// Apply syntax highlighting based on file type
|
|
1233
|
-
applyFileViewHighlighting(bufferId, content, file);
|
|
1233
|
+
applyFileViewHighlighting(result.bufferId, content, file);
|
|
1234
1234
|
|
|
1235
1235
|
const targetLine = line || 1;
|
|
1236
1236
|
editor.setStatus(editor.t("status.file_view_ready", { file, hash: commit.shortHash, line: String(targetLine) }));
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/// <reference path="./lib/fresh.d.ts" />
|
|
2
|
+
// Provides installation help when jdtls (Java LSP) is not found
|
|
3
|
+
const editor = getEditor();
|
|
4
|
+
|
|
5
|
+
interface LspServerErrorData {
|
|
6
|
+
language: string;
|
|
7
|
+
server_command: string;
|
|
8
|
+
error_type: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface LspStatusClickedData {
|
|
13
|
+
language: string;
|
|
14
|
+
has_error: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ActionPopupResultData {
|
|
18
|
+
popup_id: string;
|
|
19
|
+
action_id: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const INSTALL_URL = "https://github.com/eclipse-jdtls/eclipse.jdt.ls#installation";
|
|
23
|
+
let javaLspError: { serverCommand: string; message: string } | null = null;
|
|
24
|
+
|
|
25
|
+
globalThis.on_java_lsp_server_error = function (data: LspServerErrorData): void {
|
|
26
|
+
if (data.language !== "java") return;
|
|
27
|
+
javaLspError = { serverCommand: data.server_command, message: data.message };
|
|
28
|
+
if (data.error_type === "not_found") {
|
|
29
|
+
editor.setStatus(`Java LSP '${data.server_command}' not found. Click status bar for help.`);
|
|
30
|
+
} else {
|
|
31
|
+
editor.setStatus(`Java LSP error: ${data.message}`);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
editor.on("lsp_server_error", "on_java_lsp_server_error");
|
|
35
|
+
|
|
36
|
+
globalThis.on_java_lsp_status_clicked = function (data: LspStatusClickedData): void {
|
|
37
|
+
if (data.language !== "java" || !javaLspError) return;
|
|
38
|
+
editor.showActionPopup({
|
|
39
|
+
id: "java-lsp-help",
|
|
40
|
+
title: "Java Language Server Not Found",
|
|
41
|
+
message: `Install jdtls for code completion and diagnostics. Visit ${INSTALL_URL}`,
|
|
42
|
+
actions: [
|
|
43
|
+
{ id: "copy_url", label: "Copy install URL" },
|
|
44
|
+
{ id: "disable", label: "Disable Java LSP" },
|
|
45
|
+
{ id: "dismiss", label: "Dismiss (ESC)" },
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
editor.on("lsp_status_clicked", "on_java_lsp_status_clicked");
|
|
50
|
+
|
|
51
|
+
globalThis.on_java_lsp_action_result = function (data: ActionPopupResultData): void {
|
|
52
|
+
if (data.popup_id !== "java-lsp-help") return;
|
|
53
|
+
switch (data.action_id) {
|
|
54
|
+
case "copy_url":
|
|
55
|
+
editor.setClipboard(INSTALL_URL);
|
|
56
|
+
editor.setStatus("Copied: " + INSTALL_URL);
|
|
57
|
+
break;
|
|
58
|
+
case "disable":
|
|
59
|
+
editor.disableLspForLanguage("java");
|
|
60
|
+
editor.setStatus("Java LSP disabled");
|
|
61
|
+
javaLspError = null;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
editor.on("action_popup_result", "on_java_lsp_action_result");
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/// <reference path="./lib/fresh.d.ts" />
|
|
2
|
+
// Provides installation help when texlab (LaTeX LSP) is not found
|
|
3
|
+
const editor = getEditor();
|
|
4
|
+
|
|
5
|
+
interface LspServerErrorData {
|
|
6
|
+
language: string;
|
|
7
|
+
server_command: string;
|
|
8
|
+
error_type: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface LspStatusClickedData {
|
|
13
|
+
language: string;
|
|
14
|
+
has_error: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ActionPopupResultData {
|
|
18
|
+
popup_id: string;
|
|
19
|
+
action_id: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const INSTALL_URL = "https://github.com/latex-lsp/texlab#installation";
|
|
23
|
+
let latexLspError: { serverCommand: string; message: string } | null = null;
|
|
24
|
+
|
|
25
|
+
globalThis.on_latex_lsp_server_error = function (data: LspServerErrorData): void {
|
|
26
|
+
if (data.language !== "latex") return;
|
|
27
|
+
latexLspError = { serverCommand: data.server_command, message: data.message };
|
|
28
|
+
if (data.error_type === "not_found") {
|
|
29
|
+
editor.setStatus(`LaTeX LSP '${data.server_command}' not found. Click status bar for help.`);
|
|
30
|
+
} else {
|
|
31
|
+
editor.setStatus(`LaTeX LSP error: ${data.message}`);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
editor.on("lsp_server_error", "on_latex_lsp_server_error");
|
|
35
|
+
|
|
36
|
+
globalThis.on_latex_lsp_status_clicked = function (data: LspStatusClickedData): void {
|
|
37
|
+
if (data.language !== "latex" || !latexLspError) return;
|
|
38
|
+
editor.showActionPopup({
|
|
39
|
+
id: "latex-lsp-help",
|
|
40
|
+
title: "LaTeX Language Server Not Found",
|
|
41
|
+
message: `Install texlab for code completion and diagnostics. Visit ${INSTALL_URL}`,
|
|
42
|
+
actions: [
|
|
43
|
+
{ id: "copy_url", label: "Copy install URL" },
|
|
44
|
+
{ id: "disable", label: "Disable LaTeX LSP" },
|
|
45
|
+
{ id: "dismiss", label: "Dismiss (ESC)" },
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
editor.on("lsp_status_clicked", "on_latex_lsp_status_clicked");
|
|
50
|
+
|
|
51
|
+
globalThis.on_latex_lsp_action_result = function (data: ActionPopupResultData): void {
|
|
52
|
+
if (data.popup_id !== "latex-lsp-help") return;
|
|
53
|
+
switch (data.action_id) {
|
|
54
|
+
case "copy_url":
|
|
55
|
+
editor.setClipboard(INSTALL_URL);
|
|
56
|
+
editor.setStatus("Copied: " + INSTALL_URL);
|
|
57
|
+
break;
|
|
58
|
+
case "disable":
|
|
59
|
+
editor.disableLspForLanguage("latex");
|
|
60
|
+
editor.setStatus("LaTeX LSP disabled");
|
|
61
|
+
latexLspError = null;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
editor.on("action_popup_result", "on_latex_lsp_action_result");
|