@fresh-editor/fresh-editor 0.1.75 → 0.1.77

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 (40) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +8 -0
  3. package/package.json +1 -1
  4. package/plugins/audit_mode.ts +9 -4
  5. package/plugins/buffer_modified.ts +1 -1
  6. package/plugins/calculator.ts +1 -1
  7. package/plugins/check-types.sh +41 -0
  8. package/plugins/clangd_support.ts +1 -1
  9. package/plugins/color_highlighter.ts +4 -1
  10. package/plugins/config-schema.json +75 -3
  11. package/plugins/diagnostics_panel.i18n.json +52 -52
  12. package/plugins/diagnostics_panel.ts +168 -540
  13. package/plugins/find_references.ts +82 -324
  14. package/plugins/git_blame.i18n.json +260 -247
  15. package/plugins/git_blame.ts +4 -9
  16. package/plugins/git_explorer.ts +159 -0
  17. package/plugins/git_find_file.ts +42 -270
  18. package/plugins/git_grep.ts +50 -167
  19. package/plugins/git_gutter.ts +1 -1
  20. package/plugins/git_log.ts +4 -11
  21. package/plugins/lib/finder.ts +1499 -0
  22. package/plugins/lib/fresh.d.ts +118 -17
  23. package/plugins/lib/index.ts +23 -1
  24. package/plugins/lib/navigation-controller.ts +1 -1
  25. package/plugins/lib/panel-manager.ts +7 -13
  26. package/plugins/lib/results-panel.ts +914 -0
  27. package/plugins/lib/search-utils.ts +343 -0
  28. package/plugins/lib/types.ts +14 -0
  29. package/plugins/lib/virtual-buffer-factory.ts +3 -2
  30. package/plugins/live_grep.ts +56 -379
  31. package/plugins/markdown_compose.ts +1 -17
  32. package/plugins/merge_conflict.ts +16 -14
  33. package/plugins/odin-lsp.ts +135 -0
  34. package/plugins/path_complete.ts +1 -1
  35. package/plugins/search_replace.i18n.json +13 -13
  36. package/plugins/search_replace.ts +11 -9
  37. package/plugins/theme_editor.ts +15 -9
  38. package/plugins/todo_highlighter.ts +1 -0
  39. package/plugins/vi_mode.ts +9 -5
  40. package/plugins/welcome.ts +1 -1
@@ -1,13 +1,17 @@
1
- /// <reference path="../types/fresh.d.ts" />
2
- const editor = getEditor();
3
-
1
+ /// <reference path="./lib/fresh.d.ts" />
4
2
 
5
3
  /**
6
4
  * Git Grep Plugin
7
5
  *
8
- * Provides interactive git grep functionality with live search results.
6
+ * Provides interactive git grep functionality with live search results
7
+ * and preview panel. Uses the Finder abstraction for unified search UX.
9
8
  */
10
9
 
10
+ import { Finder, parseGrepOutput } from "./lib/finder.ts";
11
+
12
+ const editor = getEditor();
13
+
14
+ // Result type from git grep
11
15
  interface GrepMatch {
12
16
  file: string;
13
17
  line: number;
@@ -15,177 +19,56 @@ interface GrepMatch {
15
19
  content: string;
16
20
  }
17
21
 
18
- // State management
19
- let gitGrepResults: GrepMatch[] = [];
20
-
21
- // Parse git grep output line
22
- // Format: file:line:column:content
23
- function parseGitGrepLine(line: string): GrepMatch | null {
24
- const match = line.match(/^([^:]+):(\d+):(\d+):(.*)$/);
25
- if (match) {
26
- return {
27
- file: match[1],
28
- line: parseInt(match[2], 10),
29
- column: parseInt(match[3], 10),
30
- content: match[4].trimStart(),
31
- };
32
- }
33
- return null;
34
- }
35
-
36
- // Parse git grep output into suggestions
37
- function parseGitGrepOutput(stdout: string): {
38
- results: GrepMatch[];
39
- suggestions: PromptSuggestion[];
40
- } {
41
- const results: GrepMatch[] = [];
42
- const suggestions: PromptSuggestion[] = [];
43
-
44
- for (const line of stdout.split("\n")) {
45
- if (!line.trim()) continue;
46
- const match = parseGitGrepLine(line);
47
- if (match) {
48
- results.push(match);
49
- suggestions.push({
50
- text: `${match.file}:${match.line}:${match.column}`,
51
- description: match.content,
52
- value: `${match.file}:${match.line}:${match.column}`,
53
- disabled: false,
54
- });
55
-
56
- // Limit to 100 results for performance
57
- if (results.length >= 100) {
58
- break;
59
- }
60
- }
61
- }
62
-
63
- return { results, suggestions };
64
- }
65
-
66
- // Global function to start git grep
67
- globalThis.start_git_grep = function(): void {
68
- // Clear previous results
69
- gitGrepResults = [];
70
-
71
- // Start the prompt
72
- editor.startPrompt(editor.t("prompt.grep"), "git-grep");
73
- editor.setStatus(editor.t("status.type_to_search"));
74
- };
75
-
76
- // React to prompt input changes
77
- globalThis.onGitGrepPromptChanged = function(args: {
78
- prompt_type: string;
79
- input: string;
80
- }): boolean {
81
- if (args.prompt_type !== "git-grep") {
82
- return true; // Not our prompt
83
- }
84
-
85
- const query = args.input;
86
-
87
- // Don't search for empty queries
88
- if (!query || query.trim() === "") {
89
- editor.setPromptSuggestions([]);
90
- return true;
91
- }
92
-
93
- // Spawn git grep asynchronously
22
+ // Create the finder instance
23
+ const finder = new Finder<GrepMatch>(editor, {
24
+ id: "git-grep",
25
+ format: (match) => ({
26
+ label: `${match.file}:${match.line}`,
27
+ description:
28
+ match.content.length > 60
29
+ ? match.content.substring(0, 57).trim() + "..."
30
+ : match.content.trim(),
31
+ location: {
32
+ file: match.file,
33
+ line: match.line,
34
+ column: match.column,
35
+ },
36
+ }),
37
+ preview: true,
38
+ maxResults: 100,
39
+ });
40
+
41
+ // Search function using git grep
42
+ async function searchWithGitGrep(query: string): Promise<GrepMatch[]> {
94
43
  const cwd = editor.getCwd();
95
- editor.spawnProcess("git", ["grep", "-n", "--column", "-I", "--", query], cwd)
96
- .then((result) => {
97
- if (result.exit_code === 0) {
98
- // Parse results and update suggestions
99
- const { results, suggestions } = parseGitGrepOutput(result.stdout);
100
- gitGrepResults = results;
101
-
102
- // Update prompt with suggestions
103
- editor.setPromptSuggestions(suggestions);
104
-
105
- // Update status
106
- if (results.length > 0) {
107
- editor.setStatus(editor.t("status.found", { count: String(results.length) }));
108
- } else {
109
- editor.setStatus(editor.t("status.no_matches"));
110
- }
111
- } else if (result.exit_code === 1) {
112
- // No matches found (git grep returns 1)
113
- gitGrepResults = [];
114
- editor.setPromptSuggestions([]);
115
- editor.setStatus(editor.t("status.no_matches"));
116
- } else {
117
- // Error occurred
118
- editor.setStatus(editor.t("status.error", { error: result.stderr }));
119
- }
120
- })
121
- .catch((e) => {
122
- editor.setStatus(editor.t("status.error", { error: String(e) }));
123
- });
124
-
125
- return true;
126
- };
127
-
128
- // Handle prompt confirmation (user pressed Enter)
129
- globalThis.onGitGrepPromptConfirmed = function(args: {
130
- prompt_type: string;
131
- selected_index: number | null;
132
- input: string;
133
- }): boolean {
134
- if (args.prompt_type !== "git-grep") {
135
- return true; // Not our prompt
136
- }
137
-
138
- editor.debug(
139
- `prompt-confirmed: selected_index=${args.selected_index}, num_results=${gitGrepResults.length}`
44
+ const result = await editor.spawnProcess(
45
+ "git",
46
+ ["grep", "-n", "--column", "-I", "--", query],
47
+ cwd
140
48
  );
141
49
 
142
- // Check if user selected a suggestion
143
- if (args.selected_index !== null && gitGrepResults[args.selected_index]) {
144
- const selected = gitGrepResults[args.selected_index];
145
-
146
- editor.debug(`Opening file: ${selected.file}:${selected.line}:${selected.column}`);
147
-
148
- // Open the file at the specific location
149
- editor.openFile(selected.file, selected.line, selected.column);
150
- editor.setStatus(editor.t("status.opened", { location: `${selected.file}:${selected.line}:${selected.column}` }));
151
- } else {
152
- // No selection
153
- editor.debug("No file selected - selected_index is null or out of bounds");
154
- editor.setStatus(editor.t("status.no_selection"));
155
- }
156
-
157
- return true;
158
- };
159
-
160
- // Handle prompt cancellation (user pressed Escape)
161
- globalThis.onGitGrepPromptCancelled = function(args: {
162
- prompt_type: string;
163
- }): boolean {
164
- if (args.prompt_type !== "git-grep") {
165
- return true; // Not our prompt
50
+ if (result.exit_code === 0) {
51
+ return parseGrepOutput(result.stdout, 100) as GrepMatch[];
166
52
  }
53
+ return [];
54
+ }
167
55
 
168
- // Clear results
169
- gitGrepResults = [];
170
- editor.setStatus(editor.t("status.cancelled"));
171
-
172
- return true;
56
+ // Global function to start git grep
57
+ globalThis.start_git_grep = function (): void {
58
+ finder.prompt({
59
+ title: editor.t("prompt.grep"),
60
+ source: {
61
+ mode: "search",
62
+ search: searchWithGitGrep,
63
+ debounceMs: 150,
64
+ minQueryLength: 1,
65
+ },
66
+ });
173
67
  };
174
68
 
175
- // Register event handlers
176
- editor.on("prompt_changed", "onGitGrepPromptChanged");
177
- editor.on("prompt_confirmed", "onGitGrepPromptConfirmed");
178
- editor.on("prompt_cancelled", "onGitGrepPromptCancelled");
179
-
180
69
  // Register command
181
- editor.registerCommand(
182
- "%cmd.grep",
183
- "%cmd.grep_desc",
184
- "start_git_grep",
185
- "normal"
186
- );
70
+ editor.registerCommand("%cmd.grep", "%cmd.grep_desc", "start_git_grep", "normal");
187
71
 
188
72
  // Log that plugin loaded successfully
189
- editor.debug("Git Grep plugin loaded successfully (TypeScript)");
190
- editor.debug("Usage: Call start_git_grep() or use command palette 'Git Grep'");
73
+ editor.debug("Git Grep plugin loaded (using Finder abstraction)");
191
74
  editor.setStatus(editor.t("status.ready"));
@@ -1,4 +1,4 @@
1
- /// <reference path="../types/fresh.d.ts" />
1
+ /// <reference path="./lib/fresh.d.ts" />
2
2
  const editor = getEditor();
3
3
 
4
4
 
@@ -1,4 +1,4 @@
1
- /// <reference path="../types/fresh.d.ts" />
1
+ /// <reference path="./lib/fresh.d.ts" />
2
2
  const editor = getEditor();
3
3
 
4
4
 
@@ -932,16 +932,9 @@ globalThis.git_log_copy_hash = function(): void {
932
932
  return;
933
933
  }
934
934
 
935
- // Use spawn to copy to clipboard (works on most systems)
936
- // Try xclip first (Linux), then pbcopy (macOS), then xsel
937
- editor.spawnProcess("sh", ["-c", `echo -n "${commit.hash}" | xclip -selection clipboard 2>/dev/null || echo -n "${commit.hash}" | pbcopy 2>/dev/null || echo -n "${commit.hash}" | xsel --clipboard 2>/dev/null`])
938
- .then(() => {
939
- editor.setStatus(editor.t("status.hash_copied", { short: commit.shortHash, full: commit.hash }));
940
- })
941
- .catch(() => {
942
- // If all clipboard commands fail, just show the hash
943
- editor.setStatus(editor.t("status.hash_display", { hash: commit.hash }));
944
- });
935
+ // Copy hash to clipboard
936
+ editor.copyToClipboard(commit.hash);
937
+ editor.setStatus(editor.t("status.hash_copied", { short: commit.shortHash, full: commit.hash }));
945
938
  };
946
939
 
947
940
  // =============================================================================