@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,262 @@
1
+ /// <reference path="../../types/fresh.d.ts" />
2
+
3
+ /**
4
+ * Git Grep TypeScript Plugin for Fresh Editor
5
+ *
6
+ * Demonstrates async process spawning with native Promises:
7
+ * - Uses editor.spawnProcess() for async git operations
8
+ * - Parses git grep output and displays results
9
+ * - Shows file opening with line/column positioning
10
+ * - Registers multiple commands on plugin load
11
+ *
12
+ * This is a significant improvement over the Lua version because:
13
+ * - Native async/await instead of callback-based pattern
14
+ * - Cleaner error handling with try/catch
15
+ * - Type safety from TypeScript
16
+ * - Better state management with closures
17
+ */
18
+
19
+ // Store search results for navigation
20
+ interface GrepMatch {
21
+ file: string;
22
+ line: number;
23
+ text: string;
24
+ }
25
+
26
+ let searchResults: GrepMatch[] = [];
27
+ let currentResultIndex = 0;
28
+
29
+ // Parse git grep output into structured results
30
+ function parseGitGrepOutput(output: string): GrepMatch[] {
31
+ const matches: GrepMatch[] = [];
32
+ const lines = output.split("\n").filter((line) => line.trim());
33
+
34
+ for (const line of lines) {
35
+ // git grep output format: file:line:text
36
+ const match = line.match(/^([^:]+):(\d+):(.*)$/);
37
+ if (match) {
38
+ matches.push({
39
+ file: match[1],
40
+ line: parseInt(match[2], 10),
41
+ text: match[3].trim(),
42
+ });
43
+ }
44
+ }
45
+
46
+ return matches;
47
+ }
48
+
49
+ // Action: Search for pattern in repository
50
+ globalThis.git_grep_search = async function (): Promise<void> {
51
+ // For now, search for a hardcoded pattern
52
+ // In a full implementation, this would use a prompt
53
+ const pattern = "TODO";
54
+
55
+ editor.setStatus(`Searching for "${pattern}"...`);
56
+
57
+ try {
58
+ const result = await editor.spawnProcess("git", [
59
+ "grep",
60
+ "-n", // Show line numbers
61
+ "-I", // Skip binary files
62
+ pattern,
63
+ ]);
64
+
65
+ if (result.exit_code === 0 && result.stdout.trim()) {
66
+ searchResults = parseGitGrepOutput(result.stdout);
67
+ currentResultIndex = 0;
68
+
69
+ if (searchResults.length > 0) {
70
+ editor.setStatus(
71
+ `Found ${searchResults.length} matches for "${pattern}"`
72
+ );
73
+ editor.debug(`Git grep results: ${JSON.stringify(searchResults)}`);
74
+
75
+ // Jump to first result
76
+ const first = searchResults[0];
77
+ editor.openFile(first.file, first.line, 1);
78
+ editor.setStatus(
79
+ `[1/${searchResults.length}] ${first.file}:${first.line}: ${first.text}`
80
+ );
81
+ }
82
+ } else if (result.exit_code === 1) {
83
+ // git grep returns 1 when no matches found
84
+ editor.setStatus(`No matches found for "${pattern}"`);
85
+ searchResults = [];
86
+ } else {
87
+ editor.setStatus(`Git grep error: ${result.stderr || "Unknown error"}`);
88
+ editor.debug(`Git grep failed with exit code ${result.exit_code}`);
89
+ }
90
+ } catch (error) {
91
+ editor.setStatus(`Git grep failed: ${error}`);
92
+ editor.debug(`Git grep exception: ${error}`);
93
+ }
94
+ };
95
+
96
+ // Action: Go to next search result
97
+ globalThis.git_grep_next = function (): void {
98
+ if (searchResults.length === 0) {
99
+ editor.setStatus("No search results. Run git_grep_search first.");
100
+ return;
101
+ }
102
+
103
+ currentResultIndex = (currentResultIndex + 1) % searchResults.length;
104
+ const result = searchResults[currentResultIndex];
105
+
106
+ editor.openFile(result.file, result.line, 1);
107
+ editor.setStatus(
108
+ `[${currentResultIndex + 1}/${searchResults.length}] ${result.file}:${result.line}: ${result.text}`
109
+ );
110
+ };
111
+
112
+ // Action: Go to previous search result
113
+ globalThis.git_grep_prev = function (): void {
114
+ if (searchResults.length === 0) {
115
+ editor.setStatus("No search results. Run git_grep_search first.");
116
+ return;
117
+ }
118
+
119
+ currentResultIndex =
120
+ (currentResultIndex - 1 + searchResults.length) % searchResults.length;
121
+ const result = searchResults[currentResultIndex];
122
+
123
+ editor.openFile(result.file, result.line, 1);
124
+ editor.setStatus(
125
+ `[${currentResultIndex + 1}/${searchResults.length}] ${result.file}:${result.line}: ${result.text}`
126
+ );
127
+ };
128
+
129
+ // Action: Show current git status
130
+ globalThis.git_status = async function (): Promise<void> {
131
+ editor.setStatus("Getting git status...");
132
+
133
+ try {
134
+ const result = await editor.spawnProcess("git", ["status", "--short"]);
135
+
136
+ if (result.exit_code === 0) {
137
+ const lines = result.stdout.trim().split("\n").filter((l) => l);
138
+ if (lines.length === 0) {
139
+ editor.setStatus("Git: Clean working directory");
140
+ } else {
141
+ editor.setStatus(`Git: ${lines.length} changed file(s)`);
142
+ editor.debug(`Git status:\n${result.stdout}`);
143
+ }
144
+ } else {
145
+ editor.setStatus(`Not a git repository or git error`);
146
+ }
147
+ } catch (error) {
148
+ editor.setStatus(`Git status failed: ${error}`);
149
+ }
150
+ };
151
+
152
+ // Action: Show current branch
153
+ globalThis.git_branch = async function (): Promise<void> {
154
+ try {
155
+ const result = await editor.spawnProcess("git", [
156
+ "rev-parse",
157
+ "--abbrev-ref",
158
+ "HEAD",
159
+ ]);
160
+
161
+ if (result.exit_code === 0) {
162
+ const branch = result.stdout.trim();
163
+ editor.setStatus(`Git branch: ${branch}`);
164
+ } else {
165
+ editor.setStatus("Not a git repository");
166
+ }
167
+ } catch (error) {
168
+ editor.setStatus(`Git branch failed: ${error}`);
169
+ }
170
+ };
171
+
172
+ // Action: Show recent commits
173
+ globalThis.git_log = async function (): Promise<void> {
174
+ editor.setStatus("Fetching recent commits...");
175
+
176
+ try {
177
+ const result = await editor.spawnProcess("git", [
178
+ "log",
179
+ "--oneline",
180
+ "-10", // Last 10 commits
181
+ ]);
182
+
183
+ if (result.exit_code === 0) {
184
+ const lines = result.stdout.trim().split("\n");
185
+ editor.setStatus(`Git: ${lines.length} recent commits`);
186
+ editor.debug(`Recent commits:\n${result.stdout}`);
187
+
188
+ // Show first commit in status
189
+ if (lines.length > 0) {
190
+ editor.setStatus(`Latest: ${lines[0]}`);
191
+ }
192
+ } else {
193
+ editor.setStatus("Git log failed");
194
+ }
195
+ } catch (error) {
196
+ editor.setStatus(`Git log failed: ${error}`);
197
+ }
198
+ };
199
+
200
+ // Register commands on plugin load
201
+ editor.registerCommand(
202
+ "Git Grep: Search TODOs",
203
+ "Search for TODO comments in the repository",
204
+ "git_grep_search",
205
+ "normal"
206
+ );
207
+
208
+ editor.registerCommand(
209
+ "Git Grep: Next Result",
210
+ "Jump to next search result",
211
+ "git_grep_next",
212
+ "normal"
213
+ );
214
+
215
+ editor.registerCommand(
216
+ "Git Grep: Previous Result",
217
+ "Jump to previous search result",
218
+ "git_grep_prev",
219
+ "normal"
220
+ );
221
+
222
+ editor.registerCommand(
223
+ "Git: Show Status",
224
+ "Display git status summary",
225
+ "git_status",
226
+ "" // Available in all contexts
227
+ );
228
+
229
+ editor.registerCommand(
230
+ "Git: Show Branch",
231
+ "Display current git branch",
232
+ "git_branch",
233
+ ""
234
+ );
235
+
236
+ editor.registerCommand(
237
+ "Git: Recent Commits",
238
+ "Show recent commit history",
239
+ "git_log",
240
+ ""
241
+ );
242
+
243
+ // Plugin initialized
244
+ editor.setStatus("Git Grep plugin loaded - 6 commands registered");
245
+ editor.debug("Git Grep TypeScript plugin initialized");
246
+
247
+ // Automatically show git branch on load
248
+ (async () => {
249
+ try {
250
+ const result = await editor.spawnProcess("git", [
251
+ "rev-parse",
252
+ "--abbrev-ref",
253
+ "HEAD",
254
+ ]);
255
+ if (result.exit_code === 0) {
256
+ const branch = result.stdout.trim();
257
+ editor.setStatus(`Git Grep plugin ready | Branch: ${branch}`);
258
+ }
259
+ } catch {
260
+ // Silently fail if not in a git repo
261
+ }
262
+ })();
@@ -0,0 +1,93 @@
1
+ /// <reference path="../../types/fresh.d.ts" />
2
+
3
+ /**
4
+ * Hello World TypeScript Plugin for Fresh Editor
5
+ *
6
+ * This is a simple example plugin that demonstrates:
7
+ * - Querying editor state (buffer info, cursor position)
8
+ * - Sending commands (status messages, text insertion)
9
+ * - Using async/await for plugin actions
10
+ */
11
+
12
+ // Global action: Display buffer information
13
+ globalThis.show_buffer_info = function (): void {
14
+ const bufferId = editor.getActiveBufferId();
15
+ const path = editor.getBufferPath(bufferId);
16
+ const length = editor.getBufferLength(bufferId);
17
+ const modified = editor.isBufferModified(bufferId);
18
+ const cursorPos = editor.getCursorPosition();
19
+
20
+ const status = `Buffer ${bufferId}: ${path || "[untitled]"} | ${length} bytes | ${
21
+ modified ? "modified" : "saved"
22
+ } | cursor@${cursorPos}`;
23
+
24
+ editor.setStatus(status);
25
+ editor.debug(`Buffer info: ${status}`);
26
+ };
27
+
28
+ // Global action: Insert timestamp at cursor
29
+ globalThis.insert_timestamp = function (): void {
30
+ const bufferId = editor.getActiveBufferId();
31
+ const cursorPos = editor.getCursorPosition();
32
+ const timestamp = new Date().toISOString();
33
+
34
+ const success = editor.insertText(bufferId, cursorPos, timestamp);
35
+ if (success) {
36
+ editor.setStatus(`Inserted timestamp: ${timestamp}`);
37
+ } else {
38
+ editor.setStatus("Failed to insert timestamp");
39
+ }
40
+ };
41
+
42
+ // Global action: Highlight current line (demo overlay)
43
+ globalThis.highlight_region = function (): void {
44
+ const bufferId = editor.getActiveBufferId();
45
+ const cursorPos = editor.getCursorPosition();
46
+
47
+ // Highlight 10 characters around cursor
48
+ const start = Math.max(0, cursorPos - 5);
49
+ const end = cursorPos + 5;
50
+
51
+ // Use namespace "demo" for batch operations
52
+ const success = editor.addOverlay(
53
+ bufferId,
54
+ "demo", // namespace
55
+ start,
56
+ end,
57
+ 255, // Red
58
+ 255, // Green
59
+ 0, // Blue (yellow highlight)
60
+ false // No underline
61
+ );
62
+
63
+ if (success) {
64
+ editor.setStatus(`Highlighted region ${start}-${end}`);
65
+ }
66
+ };
67
+
68
+ // Global action: Remove highlight
69
+ globalThis.clear_highlight = function (): void {
70
+ const bufferId = editor.getActiveBufferId();
71
+ // Clear all overlays in the "demo" namespace
72
+ const success = editor.clearNamespace(bufferId, "demo");
73
+ if (success) {
74
+ editor.setStatus("Cleared highlight");
75
+ }
76
+ };
77
+
78
+ // Global async action: Demonstrate async/await
79
+ globalThis.async_demo = async function (): Promise<void> {
80
+ editor.setStatus("Starting async operation...");
81
+
82
+ // Simulate some async work
83
+ await Promise.resolve();
84
+
85
+ const bufferId = editor.getActiveBufferId();
86
+ const length = editor.getBufferLength(bufferId);
87
+
88
+ editor.setStatus(`Async operation complete! Buffer has ${length} bytes`);
89
+ };
90
+
91
+ // Log that plugin loaded
92
+ editor.debug("Hello World plugin loaded!");
93
+ editor.setStatus("Hello World plugin ready");
@@ -0,0 +1,116 @@
1
+ // Virtual Buffer Demo Plugin
2
+ // Demonstrates the virtual buffer API for creating diagnostic panels, search results, etc.
3
+
4
+ // Register a command to show a demo virtual buffer
5
+ editor.registerCommand(
6
+ "Virtual Buffer Demo",
7
+ "Show a demo virtual buffer with sample diagnostics",
8
+ "show_virtual_buffer_demo",
9
+ "normal"
10
+ );
11
+
12
+ // Define a custom mode for the demo buffer
13
+ editor.defineMode(
14
+ "demo-list", // mode name
15
+ null, // no parent mode
16
+ [
17
+ ["Return", "demo_goto_item"],
18
+ ["n", "demo_next_item"],
19
+ ["p", "demo_prev_item"],
20
+ ["q", "demo_close_buffer"],
21
+ ],
22
+ true // read-only
23
+ );
24
+
25
+ // Register actions for the mode
26
+ globalThis.demo_goto_item = () => {
27
+ const bufferId = editor.getActiveBufferId();
28
+ const props = editor.getTextPropertiesAtCursor(bufferId);
29
+
30
+ if (props.length > 0) {
31
+ const location = props[0].location as { file: string; line: number; column: number } | undefined;
32
+ if (location) {
33
+ editor.openFile(location.file, location.line, location.column || 0);
34
+ editor.setStatus(`Jumped to ${location.file}:${location.line}`);
35
+ } else {
36
+ editor.setStatus("No location info for this item");
37
+ }
38
+ } else {
39
+ editor.setStatus("No properties at cursor position");
40
+ }
41
+ };
42
+
43
+ globalThis.demo_next_item = () => {
44
+ editor.setStatus("Next item (not implemented in demo)");
45
+ };
46
+
47
+ globalThis.demo_prev_item = () => {
48
+ editor.setStatus("Previous item (not implemented in demo)");
49
+ };
50
+
51
+ globalThis.demo_close_buffer = () => {
52
+ editor.setStatus("Close buffer (not implemented in demo)");
53
+ };
54
+
55
+ // Main action: show the virtual buffer
56
+ globalThis.show_virtual_buffer_demo = async () => {
57
+ editor.setStatus("Creating virtual buffer demo...");
58
+
59
+ // Create sample diagnostic entries
60
+ const entries = [
61
+ {
62
+ text: "[ERROR] src/main.rs:42:10 - undefined variable 'foo'\n",
63
+ properties: {
64
+ severity: "error",
65
+ location: { file: "src/main.rs", line: 42, column: 10 },
66
+ message: "undefined variable 'foo'",
67
+ },
68
+ },
69
+ {
70
+ text: "[WARNING] src/lib.rs:100:5 - unused variable 'bar'\n",
71
+ properties: {
72
+ severity: "warning",
73
+ location: { file: "src/lib.rs", line: 100, column: 5 },
74
+ message: "unused variable 'bar'",
75
+ },
76
+ },
77
+ {
78
+ text: "[INFO] src/utils.rs:25:1 - consider using 'if let' instead of 'match'\n",
79
+ properties: {
80
+ severity: "info",
81
+ location: { file: "src/utils.rs", line: 25, column: 1 },
82
+ message: "consider using 'if let' instead of 'match'",
83
+ },
84
+ },
85
+ {
86
+ text: "[HINT] src/config.rs:8:20 - type annotation unnecessary\n",
87
+ properties: {
88
+ severity: "hint",
89
+ location: { file: "src/config.rs", line: 8, column: 20 },
90
+ message: "type annotation unnecessary",
91
+ },
92
+ },
93
+ ];
94
+
95
+ // Create the virtual buffer in a horizontal split
96
+ try {
97
+ const bufferId = await editor.createVirtualBufferInSplit({
98
+ name: "*Demo Diagnostics*",
99
+ mode: "demo-list",
100
+ read_only: true,
101
+ entries: entries,
102
+ ratio: 0.7, // Original pane takes 70%, demo buffer takes 30%
103
+ panel_id: "demo-diagnostics",
104
+ show_line_numbers: false,
105
+ show_cursors: true,
106
+ });
107
+
108
+ editor.setStatus(`Created demo virtual buffer (ID: ${bufferId}) with ${entries.length} items - Press RET to jump to location`);
109
+ } catch (error) {
110
+ const errorMessage = error instanceof Error ? error.message : String(error);
111
+ editor.setStatus(`Failed to create virtual buffer: ${errorMessage}`);
112
+ }
113
+ };
114
+
115
+ // Log that the plugin loaded
116
+ editor.debug("Virtual buffer demo plugin loaded");