@involvex/fresh-editor 0.1.76 → 0.1.78

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.
Files changed (90) hide show
  1. package/bin/CHANGELOG.md +1017 -0
  2. package/bin/LICENSE +117 -0
  3. package/bin/README.md +248 -0
  4. package/bin/fresh.exe +0 -0
  5. package/bin/plugins/README.md +71 -0
  6. package/bin/plugins/audit_mode.i18n.json +821 -0
  7. package/bin/plugins/audit_mode.ts +1810 -0
  8. package/bin/plugins/buffer_modified.i18n.json +67 -0
  9. package/bin/plugins/buffer_modified.ts +281 -0
  10. package/bin/plugins/calculator.i18n.json +93 -0
  11. package/bin/plugins/calculator.ts +770 -0
  12. package/bin/plugins/clangd-lsp.ts +168 -0
  13. package/bin/plugins/clangd_support.i18n.json +223 -0
  14. package/bin/plugins/clangd_support.md +20 -0
  15. package/bin/plugins/clangd_support.ts +325 -0
  16. package/bin/plugins/color_highlighter.i18n.json +145 -0
  17. package/bin/plugins/color_highlighter.ts +304 -0
  18. package/bin/plugins/config-schema.json +768 -0
  19. package/bin/plugins/csharp-lsp.ts +147 -0
  20. package/bin/plugins/csharp_support.i18n.json +80 -0
  21. package/bin/plugins/csharp_support.ts +170 -0
  22. package/bin/plugins/css-lsp.ts +143 -0
  23. package/bin/plugins/diagnostics_panel.i18n.json +236 -0
  24. package/bin/plugins/diagnostics_panel.ts +642 -0
  25. package/bin/plugins/examples/README.md +85 -0
  26. package/bin/plugins/examples/async_demo.ts +165 -0
  27. package/bin/plugins/examples/bookmarks.ts +329 -0
  28. package/bin/plugins/examples/buffer_query_demo.ts +110 -0
  29. package/bin/plugins/examples/git_grep.ts +262 -0
  30. package/bin/plugins/examples/hello_world.ts +93 -0
  31. package/bin/plugins/examples/virtual_buffer_demo.ts +116 -0
  32. package/bin/plugins/find_references.i18n.json +275 -0
  33. package/bin/plugins/find_references.ts +359 -0
  34. package/bin/plugins/git_blame.i18n.json +496 -0
  35. package/bin/plugins/git_blame.ts +707 -0
  36. package/bin/plugins/git_find_file.i18n.json +314 -0
  37. package/bin/plugins/git_find_file.ts +300 -0
  38. package/bin/plugins/git_grep.i18n.json +171 -0
  39. package/bin/plugins/git_grep.ts +191 -0
  40. package/bin/plugins/git_gutter.i18n.json +93 -0
  41. package/bin/plugins/git_gutter.ts +477 -0
  42. package/bin/plugins/git_log.i18n.json +481 -0
  43. package/bin/plugins/git_log.ts +1285 -0
  44. package/bin/plugins/go-lsp.ts +143 -0
  45. package/bin/plugins/html-lsp.ts +145 -0
  46. package/bin/plugins/json-lsp.ts +145 -0
  47. package/bin/plugins/lib/fresh.d.ts +1321 -0
  48. package/bin/plugins/lib/index.ts +24 -0
  49. package/bin/plugins/lib/navigation-controller.ts +214 -0
  50. package/bin/plugins/lib/panel-manager.ts +220 -0
  51. package/bin/plugins/lib/types.ts +72 -0
  52. package/bin/plugins/lib/virtual-buffer-factory.ts +130 -0
  53. package/bin/plugins/live_grep.i18n.json +171 -0
  54. package/bin/plugins/live_grep.ts +422 -0
  55. package/bin/plugins/markdown_compose.i18n.json +223 -0
  56. package/bin/plugins/markdown_compose.ts +630 -0
  57. package/bin/plugins/merge_conflict.i18n.json +821 -0
  58. package/bin/plugins/merge_conflict.ts +1810 -0
  59. package/bin/plugins/path_complete.i18n.json +80 -0
  60. package/bin/plugins/path_complete.ts +165 -0
  61. package/bin/plugins/python-lsp.ts +162 -0
  62. package/bin/plugins/rust-lsp.ts +166 -0
  63. package/bin/plugins/search_replace.i18n.json +405 -0
  64. package/bin/plugins/search_replace.ts +484 -0
  65. package/bin/plugins/test_i18n.i18n.json +67 -0
  66. package/bin/plugins/test_i18n.ts +18 -0
  67. package/bin/plugins/theme_editor.i18n.json +3746 -0
  68. package/bin/plugins/theme_editor.ts +2063 -0
  69. package/bin/plugins/todo_highlighter.i18n.json +184 -0
  70. package/bin/plugins/todo_highlighter.ts +206 -0
  71. package/bin/plugins/typescript-lsp.ts +167 -0
  72. package/bin/plugins/vi_mode.i18n.json +1549 -0
  73. package/bin/plugins/vi_mode.ts +2747 -0
  74. package/bin/plugins/welcome.i18n.json +236 -0
  75. package/bin/plugins/welcome.ts +76 -0
  76. package/bin/themes/dark.json +102 -0
  77. package/bin/themes/dracula.json +62 -0
  78. package/bin/themes/high-contrast.json +102 -0
  79. package/bin/themes/light.json +102 -0
  80. package/bin/themes/nord.json +62 -0
  81. package/bin/themes/nostalgia.json +102 -0
  82. package/bin/themes/solarized-dark.json +62 -0
  83. package/binary-install.js +1 -1
  84. package/dist/bin/fresh.js +9 -0
  85. package/dist/binary-install.js +149 -0
  86. package/dist/binary.js +30 -0
  87. package/dist/fresh-6yhknp07.exe +0 -0
  88. package/dist/install.js +158 -0
  89. package/dist/run-fresh.js +43 -0
  90. package/package.json +7 -2
@@ -0,0 +1,85 @@
1
+ # Example Plugins
2
+
3
+ This directory contains example plugins demonstrating the editor's plugin system. These are educational examples showing specific API features.
4
+
5
+ For the complete API reference, see **[docs/plugin-api.md](../../docs/plugin-api.md)**.
6
+
7
+ ## Available Examples
8
+
9
+ ### hello_world.ts
10
+
11
+ A simple "Hello World" plugin that demonstrates:
12
+ - Registering a custom command
13
+ - Setting status messages
14
+ - Basic plugin structure
15
+
16
+ ### async_demo.ts
17
+
18
+ Demonstrates async process spawning:
19
+ - Running external commands with `spawnProcess`
20
+ - Processing stdout/stderr
21
+ - Handling exit codes
22
+
23
+ ### buffer_query_demo.ts
24
+
25
+ Demonstrates buffer queries:
26
+ - Getting buffer metadata with `getBufferInfo`
27
+ - Listing all open buffers
28
+ - Querying cursor and viewport information
29
+
30
+ ### virtual_buffer_demo.ts
31
+
32
+ Demonstrates virtual buffer creation:
33
+ - Creating virtual buffers with `createVirtualBufferInSplit`
34
+ - Using text properties for embedded metadata
35
+ - Defining custom modes with keybindings
36
+ - Handling "go to" navigation from results
37
+
38
+ ### bookmarks.ts
39
+
40
+ A complete bookmark management example:
41
+ - Managing persistent state across sessions
42
+ - Creating navigation commands
43
+ - Using overlays for visual markers
44
+
45
+ ### git_grep.ts
46
+
47
+ Git grep implementation demonstrating:
48
+ - Spawning async git processes
49
+ - Parsing structured output
50
+ - Opening files at specific line:column positions
51
+ - Interactive search with prompt API
52
+
53
+ ## Writing Your Own Plugin
54
+
55
+ 1. Create a `.ts` file in the plugins directory
56
+ 2. Use the `editor` global object to access the API
57
+ 3. Register commands with `editor.registerCommand()`
58
+ 4. The plugin will be automatically loaded when the editor starts
59
+
60
+ Example template:
61
+
62
+ ```typescript
63
+ /// <reference path="../types/fresh.d.ts" />
64
+
65
+ // Define the command handler
66
+ globalThis.my_command = function(): void {
67
+ editor.setStatus("My command executed!");
68
+ };
69
+
70
+ // Register the command
71
+ editor.registerCommand(
72
+ "My Custom Command",
73
+ "Does something cool",
74
+ "my_command",
75
+ "normal"
76
+ );
77
+
78
+ // Initialization message
79
+ editor.debug("My custom plugin loaded");
80
+ ```
81
+
82
+ ## Further Reading
83
+
84
+ - **Getting Started:** [docs/PLUGIN_DEVELOPMENT.md](../../docs/PLUGIN_DEVELOPMENT.md)
85
+ - **API Reference:** [docs/plugin-api.md](../../docs/plugin-api.md)
@@ -0,0 +1,165 @@
1
+ /// <reference path="../../types/fresh.d.ts" />
2
+
3
+ /**
4
+ * Async Process Demo Plugin
5
+ * Demonstrates spawning external processes asynchronously with async/await
6
+ */
7
+
8
+ // Git status
9
+ globalThis.async_git_status = async function(): Promise<void> {
10
+ editor.setStatus("Running git status...");
11
+
12
+ try {
13
+ const result = await editor.spawnProcess("git", ["status", "--short"]);
14
+ if (result.exit_code === 0) {
15
+ if (result.stdout === "" || result.stdout === "\n") {
16
+ editor.setStatus("Git: Working tree clean");
17
+ } else {
18
+ const count = result.stdout.split("\n").filter(line => line.trim()).length;
19
+ editor.setStatus(`Git: ${count} files changed`);
20
+ }
21
+ } else {
22
+ editor.setStatus(`Git status failed: ${result.stderr}`);
23
+ }
24
+ } catch (e) {
25
+ editor.setStatus(`Git status error: ${e}`);
26
+ }
27
+ };
28
+
29
+ editor.registerCommand(
30
+ "Async Demo: Git Status",
31
+ "Run git status and show output",
32
+ "async_git_status",
33
+ "normal"
34
+ );
35
+
36
+ // Current directory
37
+ globalThis.async_pwd = async function(): Promise<void> {
38
+ try {
39
+ const result = await editor.spawnProcess("pwd");
40
+ if (result.exit_code === 0) {
41
+ const dir = result.stdout.trim();
42
+ editor.setStatus(`Current directory: ${dir}`);
43
+ } else {
44
+ editor.setStatus("pwd failed");
45
+ }
46
+ } catch (e) {
47
+ editor.setStatus(`pwd error: ${e}`);
48
+ }
49
+ };
50
+
51
+ editor.registerCommand(
52
+ "Async Demo: Current Directory",
53
+ "Show current directory using pwd",
54
+ "async_pwd",
55
+ "normal"
56
+ );
57
+
58
+ // List files
59
+ globalThis.async_ls = async function(): Promise<void> {
60
+ editor.setStatus("Listing files...");
61
+
62
+ try {
63
+ const result = await editor.spawnProcess("ls", ["-1"]);
64
+ if (result.exit_code === 0) {
65
+ const count = result.stdout.split("\n").filter(line => line.trim()).length;
66
+ editor.setStatus(`Found ${count} files/directories`);
67
+ } else {
68
+ editor.setStatus("ls failed");
69
+ }
70
+ } catch (e) {
71
+ editor.setStatus(`ls error: ${e}`);
72
+ }
73
+ };
74
+
75
+ editor.registerCommand(
76
+ "Async Demo: List Files",
77
+ "List files in current directory",
78
+ "async_ls",
79
+ "normal"
80
+ );
81
+
82
+ // Git branch
83
+ globalThis.async_git_branch = async function(): Promise<void> {
84
+ try {
85
+ const result = await editor.spawnProcess("git", ["branch", "--show-current"]);
86
+ if (result.exit_code === 0) {
87
+ const branch = result.stdout.trim();
88
+ if (branch !== "") {
89
+ editor.setStatus(`Git branch: ${branch}`);
90
+ } else {
91
+ editor.setStatus("Not on any branch (detached HEAD)");
92
+ }
93
+ } else {
94
+ editor.setStatus("Not a git repository");
95
+ }
96
+ } catch (e) {
97
+ editor.setStatus(`Git branch error: ${e}`);
98
+ }
99
+ };
100
+
101
+ editor.registerCommand(
102
+ "Async Demo: Git Branch",
103
+ "Show current git branch",
104
+ "async_git_branch",
105
+ "normal"
106
+ );
107
+
108
+ // Echo test
109
+ globalThis.async_echo = async function(): Promise<void> {
110
+ try {
111
+ const result = await editor.spawnProcess("echo", ["Hello from async process!"]);
112
+ editor.setStatus(`Echo output: ${result.stdout.trim()}`);
113
+ } catch (e) {
114
+ editor.setStatus(`Echo error: ${e}`);
115
+ }
116
+ };
117
+
118
+ editor.registerCommand(
119
+ "Async Demo: Echo Test",
120
+ "Test with simple echo command",
121
+ "async_echo",
122
+ "normal"
123
+ );
124
+
125
+ // With working directory
126
+ globalThis.async_with_cwd = async function(): Promise<void> {
127
+ try {
128
+ const result = await editor.spawnProcess("pwd", [], "/tmp");
129
+ const dir = result.stdout.trim();
130
+ editor.setStatus(`Working dir was: ${dir}`);
131
+ } catch (e) {
132
+ editor.setStatus(`pwd error: ${e}`);
133
+ }
134
+ };
135
+
136
+ editor.registerCommand(
137
+ "Async Demo: With Working Dir",
138
+ "Run command in /tmp directory",
139
+ "async_with_cwd",
140
+ "normal"
141
+ );
142
+
143
+ // Error handling
144
+ globalThis.async_error = async function(): Promise<void> {
145
+ try {
146
+ const result = await editor.spawnProcess("this_command_does_not_exist");
147
+ if (result.exit_code !== 0) {
148
+ editor.setStatus(`Command failed (as expected): exit ${result.exit_code}`);
149
+ } else {
150
+ editor.setStatus("Unexpected success");
151
+ }
152
+ } catch (e) {
153
+ editor.setStatus(`Command failed with error: ${e}`);
154
+ }
155
+ };
156
+
157
+ editor.registerCommand(
158
+ "Async Demo: Error Handling",
159
+ "Demonstrate error handling with non-existent command",
160
+ "async_error",
161
+ "normal"
162
+ );
163
+
164
+ editor.setStatus("Async Demo plugin loaded! Try the 'Async Demo' commands.");
165
+ editor.debug("Async Demo plugin initialized with native async/await support");
@@ -0,0 +1,329 @@
1
+ /// <reference path="../../types/fresh.d.ts" />
2
+
3
+ /**
4
+ * Bookmarks Plugin for Fresh Editor (TypeScript)
5
+ *
6
+ * Demonstrates the new TypeScript plugin ops:
7
+ * - editor.registerCommand() - Register plugin commands
8
+ * - editor.openFile() - Open file at specific location
9
+ * - editor.getActiveSplitId() - Get current split ID
10
+ * - editor.openFileInSplit() - Open file in specific split
11
+ *
12
+ * Features:
13
+ * - Add bookmarks at current cursor position
14
+ * - List all bookmarks
15
+ * - Jump to bookmarks
16
+ * - Remove bookmarks
17
+ * - Split-aware navigation
18
+ */
19
+
20
+ // Bookmark storage
21
+ interface Bookmark {
22
+ id: number;
23
+ name: string;
24
+ path: string;
25
+ line: number;
26
+ column: number;
27
+ splitId: number;
28
+ }
29
+
30
+ const bookmarks: Map<number, Bookmark> = new Map();
31
+ let nextBookmarkId = 1;
32
+
33
+ // Helper: Get current location info
34
+ function getCurrentLocation(): {
35
+ path: string;
36
+ position: number;
37
+ splitId: number;
38
+ } {
39
+ const bufferId = editor.getActiveBufferId();
40
+ const path = editor.getBufferPath(bufferId);
41
+ const position = editor.getCursorPosition();
42
+ const splitId = editor.getActiveSplitId();
43
+
44
+ return { path, position, splitId };
45
+ }
46
+
47
+ // Helper: Get actual line number using the API
48
+ function getCurrentLineCol(): { line: number; column: number } {
49
+ // Use the actual getCursorLine API for accurate line number
50
+ const lineNumber = editor.getCursorLine();
51
+
52
+ // Get cursor position within the line by reading buffer content
53
+ const bufferId = editor.getActiveBufferId();
54
+ const cursorPos = editor.getCursorPosition();
55
+ const bufferInfo = editor.getBufferInfo(bufferId);
56
+
57
+ // Calculate column by finding start of current line
58
+ let column = 1;
59
+ if (bufferInfo && cursorPos > 0) {
60
+ // Read a small chunk before cursor to find line start
61
+ const readStart = Math.max(0, cursorPos - 1000);
62
+ const textBefore = editor.getBufferText(bufferId, readStart, cursorPos);
63
+ const lastNewline = textBefore.lastIndexOf("\n");
64
+ if (lastNewline !== -1) {
65
+ column = cursorPos - (readStart + lastNewline);
66
+ } else {
67
+ // No newline found, column is position from readStart
68
+ column = cursorPos - readStart + 1;
69
+ }
70
+ }
71
+
72
+ return { line: lineNumber, column };
73
+ }
74
+
75
+ // Action: Add bookmark at current position
76
+ globalThis.bookmark_add = function (): void {
77
+ const { path, position, splitId } = getCurrentLocation();
78
+ const { line, column } = getCurrentLineCol();
79
+
80
+ if (!path) {
81
+ editor.setStatus("Cannot bookmark: buffer has no file path");
82
+ return;
83
+ }
84
+
85
+ const id = nextBookmarkId++;
86
+ const name = `Bookmark ${id}`;
87
+
88
+ const bookmark: Bookmark = {
89
+ id,
90
+ name,
91
+ path,
92
+ line,
93
+ column,
94
+ splitId,
95
+ };
96
+
97
+ bookmarks.set(id, bookmark);
98
+
99
+ // Add visual indicator with bookmark namespace
100
+ const bufferId = editor.getActiveBufferId();
101
+ editor.addOverlay(
102
+ bufferId,
103
+ "bookmark", // namespace for all bookmarks
104
+ position,
105
+ position + 1,
106
+ 0, // Red
107
+ 128, // Green (teal color)
108
+ 255, // Blue
109
+ true // Underline
110
+ );
111
+
112
+ editor.setStatus(`Added ${name} at ${path}:${line}:${column}`);
113
+ editor.debug(`Bookmark ${id} created: ${JSON.stringify(bookmark)}`);
114
+ };
115
+
116
+ // Action: List all bookmarks
117
+ globalThis.bookmark_list = function (): void {
118
+ if (bookmarks.size === 0) {
119
+ editor.setStatus("No bookmarks");
120
+ return;
121
+ }
122
+
123
+ const list: string[] = [];
124
+ bookmarks.forEach((bm, id) => {
125
+ list.push(`[${id}] ${bm.path}:${bm.line}:${bm.column}`);
126
+ });
127
+
128
+ editor.setStatus(`Bookmarks: ${list.join(" | ")}`);
129
+ editor.debug(`All bookmarks: ${JSON.stringify([...bookmarks.values()])}`);
130
+ };
131
+
132
+ // Action: Jump to bookmark by ID
133
+ globalThis.bookmark_goto = function (): void {
134
+ if (bookmarks.size === 0) {
135
+ editor.setStatus("No bookmarks to jump to");
136
+ return;
137
+ }
138
+
139
+ // Jump to the first bookmark (simplified)
140
+ const firstBookmark = bookmarks.values().next().value;
141
+ if (firstBookmark) {
142
+ const success = editor.openFile(
143
+ firstBookmark.path,
144
+ firstBookmark.line,
145
+ firstBookmark.column
146
+ );
147
+
148
+ if (success) {
149
+ editor.setStatus(
150
+ `Jumped to ${firstBookmark.name}: ${firstBookmark.path}:${firstBookmark.line}`
151
+ );
152
+ } else {
153
+ editor.setStatus(`Failed to open ${firstBookmark.path}`);
154
+ }
155
+ }
156
+ };
157
+
158
+ // Action: Jump to bookmark in same split (split-aware)
159
+ globalThis.bookmark_goto_split = function (): void {
160
+ if (bookmarks.size === 0) {
161
+ editor.setStatus("No bookmarks");
162
+ return;
163
+ }
164
+
165
+ const currentSplit = editor.getActiveSplitId();
166
+ const firstBookmark = bookmarks.values().next().value;
167
+
168
+ if (firstBookmark) {
169
+ // Open in the current split, not the bookmark's original split
170
+ const success = editor.openFileInSplit(
171
+ currentSplit,
172
+ firstBookmark.path,
173
+ firstBookmark.line,
174
+ firstBookmark.column
175
+ );
176
+
177
+ if (success) {
178
+ editor.setStatus(
179
+ `Opened ${firstBookmark.name} in split ${currentSplit}`
180
+ );
181
+ } else {
182
+ editor.setStatus(`Failed to open in split ${currentSplit}`);
183
+ }
184
+ }
185
+ };
186
+
187
+ // Action: Remove all bookmarks
188
+ globalThis.bookmark_clear = function (): void {
189
+ const bufferId = editor.getActiveBufferId();
190
+
191
+ // Remove all bookmark overlays using namespace
192
+ editor.clearNamespace(bufferId, "bookmark");
193
+
194
+ const count = bookmarks.size;
195
+ bookmarks.clear();
196
+
197
+ editor.setStatus(`Cleared ${count} bookmark(s)`);
198
+ };
199
+
200
+ // Action: Show current split info
201
+ globalThis.show_split_info = function (): void {
202
+ const splitId = editor.getActiveSplitId();
203
+ const bufferId = editor.getActiveBufferId();
204
+ const path = editor.getBufferPath(bufferId);
205
+
206
+ editor.setStatus(`Split ${splitId} | Buffer ${bufferId} | ${path || "[untitled]"}`);
207
+ };
208
+
209
+ // Interactive bookmark selection using prompt API
210
+ let bookmarkSuggestionIds: number[] = [];
211
+
212
+ globalThis.bookmark_select = function (): void {
213
+ if (bookmarks.size === 0) {
214
+ editor.setStatus("No bookmarks to select");
215
+ return;
216
+ }
217
+
218
+ // Create suggestions from bookmarks
219
+ const suggestions: PromptSuggestion[] = [];
220
+ bookmarkSuggestionIds = [];
221
+
222
+ bookmarks.forEach((bm) => {
223
+ const filename = bm.path.split("/").pop() || bm.path;
224
+ suggestions.push({
225
+ text: `${bm.name}: ${bm.path}:${bm.line}:${bm.column}`,
226
+ description: `${filename} at line ${bm.line}`,
227
+ value: String(bm.id),
228
+ disabled: false,
229
+ });
230
+ bookmarkSuggestionIds.push(bm.id);
231
+ });
232
+
233
+ editor.startPrompt("Select bookmark: ", "bookmark-select");
234
+ editor.setPromptSuggestions(suggestions);
235
+ editor.setStatus(`${bookmarks.size} bookmark(s) available`);
236
+ };
237
+
238
+ // Handle bookmark selection confirmation
239
+ globalThis.onBookmarkSelectConfirmed = function (args: {
240
+ prompt_type: string;
241
+ selected_index: number | null;
242
+ input: string;
243
+ }): boolean {
244
+ if (args.prompt_type !== "bookmark-select") {
245
+ return true;
246
+ }
247
+
248
+ if (args.selected_index !== null && bookmarkSuggestionIds[args.selected_index] !== undefined) {
249
+ const bookmarkId = bookmarkSuggestionIds[args.selected_index];
250
+ const bookmark = bookmarks.get(bookmarkId);
251
+
252
+ if (bookmark) {
253
+ editor.openFile(bookmark.path, bookmark.line, bookmark.column);
254
+ editor.setStatus(`Jumped to ${bookmark.name}: ${bookmark.path}:${bookmark.line}`);
255
+ }
256
+ } else {
257
+ editor.setStatus("No bookmark selected");
258
+ }
259
+
260
+ return true;
261
+ };
262
+
263
+ // Handle bookmark selection cancellation
264
+ globalThis.onBookmarkSelectCancelled = function (args: { prompt_type: string }): boolean {
265
+ if (args.prompt_type !== "bookmark-select") {
266
+ return true;
267
+ }
268
+
269
+ editor.setStatus("Bookmark selection cancelled");
270
+ return true;
271
+ };
272
+
273
+ // Register bookmark event handlers
274
+ editor.on("prompt_confirmed", "onBookmarkSelectConfirmed");
275
+ editor.on("prompt_cancelled", "onBookmarkSelectCancelled");
276
+
277
+ // Register commands on plugin load
278
+ editor.registerCommand(
279
+ "Add Bookmark",
280
+ "Add a bookmark at the current cursor position",
281
+ "bookmark_add",
282
+ "normal"
283
+ );
284
+
285
+ editor.registerCommand(
286
+ "List Bookmarks",
287
+ "Show all bookmarks",
288
+ "bookmark_list",
289
+ "normal"
290
+ );
291
+
292
+ editor.registerCommand(
293
+ "Go to Bookmark",
294
+ "Jump to the first bookmark",
295
+ "bookmark_goto",
296
+ "normal"
297
+ );
298
+
299
+ editor.registerCommand(
300
+ "Go to Bookmark (Current Split)",
301
+ "Jump to bookmark in current split",
302
+ "bookmark_goto_split",
303
+ "normal"
304
+ );
305
+
306
+ editor.registerCommand(
307
+ "Clear Bookmarks",
308
+ "Remove all bookmarks",
309
+ "bookmark_clear",
310
+ "normal"
311
+ );
312
+
313
+ editor.registerCommand(
314
+ "Show Split Info",
315
+ "Display current split and buffer information",
316
+ "show_split_info",
317
+ "" // Available in all contexts
318
+ );
319
+
320
+ editor.registerCommand(
321
+ "Select Bookmark",
322
+ "Interactively select and jump to a bookmark",
323
+ "bookmark_select",
324
+ "normal"
325
+ );
326
+
327
+ // Plugin initialized
328
+ editor.setStatus("Bookmarks plugin loaded - 7 commands registered");
329
+ editor.debug("Bookmarks plugin initialized with command registration and prompt API support");
@@ -0,0 +1,110 @@
1
+ /// <reference path="../../types/fresh.d.ts" />
2
+
3
+ /**
4
+ * Buffer Query Demo Plugin
5
+ * Demonstrates the buffer query APIs in Phase 2
6
+ */
7
+
8
+ // Show buffer info
9
+ globalThis.show_buffer_info_demo = function(): void {
10
+ const bufferId = editor.getActiveBufferId();
11
+ const info = editor.getBufferInfo(bufferId);
12
+
13
+ if (info) {
14
+ const msg = `Buffer ${info.id}: ${info.path || "[No Name]"} (${
15
+ info.modified ? "modified" : "saved"
16
+ }, ${info.length} bytes)`;
17
+ editor.setStatus(msg);
18
+ } else {
19
+ editor.setStatus("No buffer info available");
20
+ }
21
+ };
22
+
23
+ editor.registerCommand(
24
+ "Query Demo: Show Buffer Info",
25
+ "Display information about the current buffer",
26
+ "show_buffer_info_demo",
27
+ "normal"
28
+ );
29
+
30
+ // Show cursor position with selection info
31
+ globalThis.show_cursor_info_demo = function(): void {
32
+ const cursor = editor.getPrimaryCursor();
33
+
34
+ if (cursor) {
35
+ let msg: string;
36
+ if (cursor.selection) {
37
+ msg = `Cursor at ${cursor.position}, selection: ${cursor.selection.start}-${cursor.selection.end} (${
38
+ cursor.selection.end - cursor.selection.start
39
+ } chars)`;
40
+ } else {
41
+ msg = `Cursor at byte position ${cursor.position} (no selection)`;
42
+ }
43
+ editor.setStatus(msg);
44
+ } else {
45
+ editor.setStatus("No cursor info available");
46
+ }
47
+ };
48
+
49
+ editor.registerCommand(
50
+ "Query Demo: Show Cursor Position",
51
+ "Display cursor position and selection info",
52
+ "show_cursor_info_demo",
53
+ "normal"
54
+ );
55
+
56
+ // Count all cursors (multi-cursor support)
57
+ globalThis.count_cursors_demo = function(): void {
58
+ const cursors = editor.getAllCursors();
59
+ editor.setStatus(`Active cursors: ${cursors.length}`);
60
+ };
61
+
62
+ editor.registerCommand(
63
+ "Query Demo: Count All Cursors",
64
+ "Display the number of active cursors",
65
+ "count_cursors_demo",
66
+ "normal"
67
+ );
68
+
69
+ // List all buffers
70
+ globalThis.list_all_buffers_demo = function(): void {
71
+ const buffers = editor.listBuffers();
72
+ let modifiedCount = 0;
73
+
74
+ for (const buf of buffers) {
75
+ if (buf.modified) {
76
+ modifiedCount++;
77
+ }
78
+ }
79
+
80
+ editor.setStatus(`Open buffers: ${buffers.length} (${modifiedCount} modified)`);
81
+ };
82
+
83
+ editor.registerCommand(
84
+ "Query Demo: List All Buffers",
85
+ "Show count of open buffers",
86
+ "list_all_buffers_demo",
87
+ "normal"
88
+ );
89
+
90
+ // Show viewport info
91
+ globalThis.show_viewport_demo = function(): void {
92
+ const vp = editor.getViewport();
93
+
94
+ if (vp) {
95
+ const msg = `Viewport: ${vp.width}x${vp.height}, top_byte=${vp.top_byte}, left_col=${vp.left_column}`;
96
+ editor.setStatus(msg);
97
+ } else {
98
+ editor.setStatus("No viewport info available");
99
+ }
100
+ };
101
+
102
+ editor.registerCommand(
103
+ "Query Demo: Show Viewport Info",
104
+ "Display viewport dimensions and scroll position",
105
+ "show_viewport_demo",
106
+ "normal"
107
+ );
108
+
109
+ editor.setStatus("Buffer Query Demo plugin loaded! Try the 'Query Demo' commands.");
110
+ editor.debug("Buffer Query Demo plugin initialized (TypeScript version)");