Compare commits
No commits in common. "searchpane" and "main" have entirely different histories.
searchpane
...
main
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "miller",
|
"name": "miller",
|
||||||
"version": "0.2.6",
|
"version": "0.2.5",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "miller",
|
"name": "miller",
|
||||||
"version": "0.2.6",
|
"version": "0.2.5",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lydell/node-pty": "^1.1.0",
|
"@lydell/node-pty": "^1.1.0",
|
||||||
|
|
@ -34,7 +34,6 @@
|
||||||
"@types/electron-squirrel-startup": "^1.0.2",
|
"@types/electron-squirrel-startup": "^1.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
||||||
"@typescript-eslint/parser": "^8.46.3",
|
"@typescript-eslint/parser": "^8.46.3",
|
||||||
"@vscode/ripgrep": "^1.18.0",
|
|
||||||
"@xterm/addon-fit": "^0.10.0",
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
"@xterm/xterm": "^5.5.0",
|
"@xterm/xterm": "^5.5.0",
|
||||||
"codemirror": "^6.0.2",
|
"codemirror": "^6.0.2",
|
||||||
|
|
@ -3861,195 +3860,6 @@
|
||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vscode/ripgrep": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep/-/ripgrep-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-ns5lWe44tSfbTMbVUsyB+I1819PVSw4AdpgK0RNkzfWfwy6+3IUNSxwSrfTno1/oWaS/hERNz+XLWVyga2aJBQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@vscode/ripgrep-darwin-arm64": "1.18.0",
|
|
||||||
"@vscode/ripgrep-darwin-x64": "1.18.0",
|
|
||||||
"@vscode/ripgrep-linux-arm": "1.18.0",
|
|
||||||
"@vscode/ripgrep-linux-arm64": "1.18.0",
|
|
||||||
"@vscode/ripgrep-linux-ia32": "1.18.0",
|
|
||||||
"@vscode/ripgrep-linux-ppc64": "1.18.0",
|
|
||||||
"@vscode/ripgrep-linux-riscv64": "1.18.0",
|
|
||||||
"@vscode/ripgrep-linux-s390x": "1.18.0",
|
|
||||||
"@vscode/ripgrep-linux-x64": "1.18.0",
|
|
||||||
"@vscode/ripgrep-win32-arm64": "1.18.0",
|
|
||||||
"@vscode/ripgrep-win32-ia32": "1.18.0",
|
|
||||||
"@vscode/ripgrep-win32-x64": "1.18.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-darwin-arm64": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-darwin-arm64/-/ripgrep-darwin-arm64-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-r3ktHSvbFycQNF6sl7sNDPocpsI7J+mEzh1IaZFkY0spm3k2Z9t8hPAeOK7+p0l6p6/swkQC14XWX01low+94Q==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-darwin-x64": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-darwin-x64/-/ripgrep-darwin-x64-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-25b4gWbL138dGuQU244ebCKKc0q05ULBMoFSz9oAEUHNeqK/lOJViDS7DRvbDazzAzSEdan391Znks/R5mkaTQ==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-linux-arm": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-linux-arm/-/ripgrep-linux-arm-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-GDAvufNDHu8zqLEmXstalQF0Wh6wQvdsBi/Vg3Yi3CK4a8XoFXqqXVEHEZ9xQz3t0NfoSEc9JbvK9DDS6FxyxQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-linux-arm64": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-linux-arm64/-/ripgrep-linux-arm64-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-lQ/5zTG++U0E3IhVgS4EPTTn/U4okncaRMM5GOFfOYZywS4nuD31GhkHbNYlDk5CuDC68+hYJ0/eQeyCKJDA+g==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-linux-ia32": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-linux-ia32/-/ripgrep-linux-ia32-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-YWLkSUtFd4Jh5EepIhA9RJSfv3uMAVMo+2rBIGHPBnvgLrZciIs2cDKei1/p6Wc/aCzUoHyMAg2R6tw4ZCBKGg==",
|
|
||||||
"cpu": [
|
|
||||||
"ia32"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-linux-ppc64": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-linux-ppc64/-/ripgrep-linux-ppc64-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-quXVY8fwQ8O/lvU1yrSqSl3jlUzysRSb+AfUfCL/tRtphxsKlFvPAejryZ6vg4Bgvn8XL74xb4qMCDmWgYrT5w==",
|
|
||||||
"cpu": [
|
|
||||||
"ppc64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-linux-riscv64": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-linux-riscv64/-/ripgrep-linux-riscv64-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-f5kBQBrWfQt8Q7OhSORuNDei5dkYagBj3y4jImSUXGMy8B/Ke7SltSRcUtjPv166FAFfHCAmWuZp3+cWnX2/Vw==",
|
|
||||||
"cpu": [
|
|
||||||
"riscv64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-linux-s390x": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-linux-s390x/-/ripgrep-linux-s390x-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-rTOcJFGGcl2c07RUOWUo4U1ndnemKhY6A9hnMB18uk7jSgJc0d/QLBGWMWpumdtoJtpizn/wIv5mXIisJukusQ==",
|
|
||||||
"cpu": [
|
|
||||||
"s390x"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-linux-x64": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-linux-x64/-/ripgrep-linux-x64-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-mQ3bVrUpnD2vs7QT0vX90Lt0cnUq467uFtEktIdsJJmW296RoSULRGqWgzG1AKxyBpNDD6l4ZO4qKf6SgyC23Q==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-win32-arm64": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-win32-arm64/-/ripgrep-win32-arm64-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-vfTIjq1OHnzUjxZcHVQAMbnggp8dpGf+0QKFOZHwWPqFwXxQC8eCWM+5NUdoJ6yrElCeMzoUTXoK/LdZaniB+Q==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-win32-ia32": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-win32-ia32/-/ripgrep-win32-ia32-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-//rfAE+BOw5AC2EMmepmiE36jUuevtQYNQqqlw1s3m9FlRxjxEut97RkRPHAu9BG4mSojatZx+kXZXNdyI9caQ==",
|
|
||||||
"cpu": [
|
|
||||||
"ia32"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/ripgrep-win32-x64": {
|
|
||||||
"version": "1.18.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/ripgrep-win32-x64/-/ripgrep-win32-x64-1.18.0.tgz",
|
|
||||||
"integrity": "sha512-KNPvtElldqILHdnAetujPaowkNbpqJy3ssIGGN6F6Kve9Qi+nNLI2DN01O83JjCEVQbCzl8Ov3QZ9Eov3BR8Dg==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"node_modules/@vscode/sudo-prompt": {
|
"node_modules/@vscode/sudo-prompt": {
|
||||||
"version": "9.3.1",
|
"version": "9.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@vscode/sudo-prompt/-/sudo-prompt-9.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vscode/sudo-prompt/-/sudo-prompt-9.3.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@
|
||||||
"@types/electron-squirrel-startup": "^1.0.2",
|
"@types/electron-squirrel-startup": "^1.0.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
"@typescript-eslint/eslint-plugin": "^8.46.3",
|
||||||
"@typescript-eslint/parser": "^8.46.3",
|
"@typescript-eslint/parser": "^8.46.3",
|
||||||
"@vscode/ripgrep": "^1.18.0",
|
|
||||||
"@xterm/addon-fit": "^0.10.0",
|
"@xterm/addon-fit": "^0.10.0",
|
||||||
"@xterm/xterm": "^5.5.0",
|
"@xterm/xterm": "^5.5.0",
|
||||||
"codemirror": "^6.0.2",
|
"codemirror": "^6.0.2",
|
||||||
|
|
|
||||||
|
|
@ -209,14 +209,6 @@ export class Editor extends Displayable {
|
||||||
return this.file.filePath.val + (this.file.isDirty() ? "*" : "");
|
return this.file.filePath.val + (this.file.isDirty() ? "*" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
jumpTo(line: number) {
|
|
||||||
const lineDoc = this.view.state.doc.line(line);
|
|
||||||
this.view.dispatch({
|
|
||||||
selection: { anchor: lineDoc.from, head: lineDoc.from },
|
|
||||||
});
|
|
||||||
this.view.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
if (this.deleteFn) {
|
if (this.deleteFn) {
|
||||||
this.file.removeEditor(this, this.deleteFn);
|
this.file.removeEditor(this, this.deleteFn);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import { Terminal } from "./terminal";
|
||||||
import { Displayable } from "./displayable";
|
import { Displayable } from "./displayable";
|
||||||
import { QuickOpen } from "./quickopen";
|
import { QuickOpen } from "./quickopen";
|
||||||
import { toggleSidebar } from "./renderer";
|
import { toggleSidebar } from "./renderer";
|
||||||
import { SearchPane } from "./searchPane";
|
|
||||||
|
|
||||||
const EditorWrapper = (
|
const EditorWrapper = (
|
||||||
editor: State<Displayable>,
|
editor: State<Displayable>,
|
||||||
|
|
@ -100,12 +99,6 @@ export function addTerminal() {
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addSearchPane() {
|
|
||||||
const pane = new SearchPane();
|
|
||||||
editors[currentTab.val].push(vanX.noreactive(pane));
|
|
||||||
pane.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
const TabHeader = (tab: State<Editor[]>, del: () => void, k: number) =>
|
const TabHeader = (tab: State<Editor[]>, del: () => void, k: number) =>
|
||||||
v.div(
|
v.div(
|
||||||
{
|
{
|
||||||
|
|
@ -153,11 +146,6 @@ function shortcutHandler(e: KeyboardEvent) {
|
||||||
if (e.type === "keydown") {
|
if (e.type === "keydown") {
|
||||||
toggleSidebar();
|
toggleSidebar();
|
||||||
}
|
}
|
||||||
} else if (e.key === "f" && e.altKey) {
|
|
||||||
if (e.type === "keydown") {
|
|
||||||
addSearchPane();
|
|
||||||
}
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
import van, { State } from "vanjs-core";
|
|
||||||
const v = van.tags;
|
|
||||||
|
|
||||||
import { Displayable } from "./displayable";
|
|
||||||
import { addEditor } from "./editorgrid";
|
|
||||||
import { OpenFile } from "./filestate";
|
|
||||||
import * as u from "./utils";
|
|
||||||
|
|
||||||
interface SearchMatch {
|
|
||||||
path: string;
|
|
||||||
line: number;
|
|
||||||
column: number;
|
|
||||||
text: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SearchPane extends Displayable {
|
|
||||||
query = van.state("");
|
|
||||||
results = van.state<SearchMatch[]>([]);
|
|
||||||
isSearching = van.state(false);
|
|
||||||
private unsubscribeResult?: () => void;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
async startSearch() {
|
|
||||||
const q = this.query.val;
|
|
||||||
if (!q) return;
|
|
||||||
|
|
||||||
if (this.unsubscribeResult) {
|
|
||||||
this.unsubscribeResult();
|
|
||||||
this.unsubscribeResult = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isSearching.val = true;
|
|
||||||
this.results.val = [];
|
|
||||||
|
|
||||||
const args = ["--json", q, "."];
|
|
||||||
|
|
||||||
try {
|
|
||||||
await window.electronAPI.startSearch(args);
|
|
||||||
|
|
||||||
this.unsubscribeResult = window.electronAPI.onSearchResult((result: any) => {
|
|
||||||
console.log("Message from ripgrep: ", result);
|
|
||||||
if (result.type === "match") {
|
|
||||||
const match: SearchMatch = {
|
|
||||||
path: result.data.path.text,
|
|
||||||
line: result.data.line_number,
|
|
||||||
column: result.data.column_number,
|
|
||||||
text: result.data.lines.text,
|
|
||||||
};
|
|
||||||
this.results.val = [...this.results.val, match];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.type === "summary") {
|
|
||||||
this.isSearching.val = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Search failed", err);
|
|
||||||
this.isSearching.val = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
focus() {
|
|
||||||
const input = document.getElementById("search-input") as HTMLInputElement;
|
|
||||||
input?.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
close(): boolean {
|
|
||||||
// TODO: stop ripgrep
|
|
||||||
if (this.unsubscribeResult) {
|
|
||||||
this.unsubscribeResult();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
title(): string {
|
|
||||||
return "Search";
|
|
||||||
}
|
|
||||||
|
|
||||||
get dom() {
|
|
||||||
return v.div(
|
|
||||||
{ class: "flex flex-col h-full" },
|
|
||||||
v.div(
|
|
||||||
{ class: "p-2 border-b dark:border-gray-700 flex gap-2" },
|
|
||||||
v.input(
|
|
||||||
{
|
|
||||||
id: "search-input",
|
|
||||||
class: "flex-1 p-1 border rounded dark:bg-gray-800 dark:text-white outline-none",
|
|
||||||
placeholder: "Search...",
|
|
||||||
value: this.query,
|
|
||||||
onkeydown: (e: KeyboardEvent) => {
|
|
||||||
if (e.key === "Enter") {
|
|
||||||
this.startSearch();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
oninput: (e: any) => (this.query.val = e.target.value),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
u.Button(() => this.startSearch(), "🔍"),
|
|
||||||
),
|
|
||||||
v.div(
|
|
||||||
{ class: "flex-1 overflow-y-auto p-2" },
|
|
||||||
() => this.isSearching.val
|
|
||||||
? v.p({ class: "text-center text-gray-500" }, "Searching...")
|
|
||||||
: v.div(
|
|
||||||
this.results.val.map((match) =>
|
|
||||||
v.div(
|
|
||||||
{
|
|
||||||
class: "p-2 mb-2 cursor-pointer hover:bg-blue-100 dark:hover:bg-blue-900 rounded border border-transparent hover:border-blue-300",
|
|
||||||
onclick: async () => {
|
|
||||||
// TODO: use absolute path!
|
|
||||||
const file = await OpenFile.openFile(match.path);
|
|
||||||
if (file) {
|
|
||||||
const editor = addEditor(file);
|
|
||||||
editor.jumpTo(match.line);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
v.div({ class: "text-xs text-gray-500 dark:text-gray-400" }, match.path),
|
|
||||||
v.div({ class: "text-sm font-mono" }, `${match.line}:${match.column} ${match.text}`),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -14,7 +14,6 @@ import path from "node:path";
|
||||||
import started from "electron-squirrel-startup";
|
import started from "electron-squirrel-startup";
|
||||||
import { setupLangServer } from "./langserver";
|
import { setupLangServer } from "./langserver";
|
||||||
import { setMenu } from "./menu";
|
import { setMenu } from "./menu";
|
||||||
import { searchService } from "./searchService";
|
|
||||||
/// <reference types="./forge-vite-env.d.ts" />
|
/// <reference types="./forge-vite-env.d.ts" />
|
||||||
|
|
||||||
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
||||||
|
|
@ -140,19 +139,6 @@ app.whenReady().then(() => {
|
||||||
return terminalManager.closeTerminal(id);
|
return terminalManager.closeTerminal(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle("search:start", async (event, args: string[]) => {
|
|
||||||
const senderWindow = BrowserWindow.fromWebContents(event.sender);
|
|
||||||
if (!senderWindow) return;
|
|
||||||
|
|
||||||
await searchService.startSearch(
|
|
||||||
senderWindow,
|
|
||||||
args,
|
|
||||||
(result) => {
|
|
||||||
senderWindow.webContents.send("search:result", result);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
createWindow();
|
createWindow();
|
||||||
if (process.platform === "darwin") {
|
if (process.platform === "darwin") {
|
||||||
app.on("activate", function () {
|
app.on("activate", function () {
|
||||||
|
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
import { ChildProcess, spawn } from "child_process";
|
|
||||||
import { rgPath } from "@vscode/ripgrep";
|
|
||||||
import { BrowserWindow } from "electron";
|
|
||||||
import { getCurrentWorkspaceRoot } from "./fileOperations";
|
|
||||||
|
|
||||||
export interface SearchResult {
|
|
||||||
type: "match" | "error" | "line" | "path" | "context";
|
|
||||||
data: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SearchService {
|
|
||||||
private currentProcess: ChildProcess = null;
|
|
||||||
|
|
||||||
async startSearch(
|
|
||||||
mainWindow: BrowserWindow,
|
|
||||||
args: string[],
|
|
||||||
onResult: (result: any) => void,
|
|
||||||
) {
|
|
||||||
this.stopSearch();
|
|
||||||
|
|
||||||
const cwd = getCurrentWorkspaceRoot();
|
|
||||||
console.log("Spawning ripgrep: ", rgPath, cwd, args);
|
|
||||||
|
|
||||||
this.currentProcess = spawn(rgPath, args, {cwd});
|
|
||||||
|
|
||||||
this.currentProcess.stdin.end();
|
|
||||||
|
|
||||||
this.currentProcess.stdout.on("data", (data: Buffer) => {
|
|
||||||
console.log("ripgrep data: ", data.toString());
|
|
||||||
const lines = data.toString().split("\n");
|
|
||||||
for (const line of lines) {
|
|
||||||
if (line.trim()) {
|
|
||||||
try {
|
|
||||||
const json = JSON.parse(line);
|
|
||||||
onResult(json);
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to parse ripgrep JSON line:", line, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.currentProcess.stderr.on("data", (data: Buffer) => {
|
|
||||||
const errorLine = data.toString().trim();
|
|
||||||
if (errorLine) {
|
|
||||||
console.error("ripgrep stderr:", errorLine);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.currentProcess.on("close", (code: number) => {
|
|
||||||
console.log(`ripgrep process exited with code ${code}`);
|
|
||||||
this.currentProcess = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.currentProcess.on("error", (err: any) => {
|
|
||||||
console.log("Ripgrep failed to start: ", err);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.currentProcess.on("exit", (code: number) => {
|
|
||||||
console.log("Ripgrep exited: ", code);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
stopSearch() {
|
|
||||||
if (this.currentProcess) {
|
|
||||||
this.currentProcess.kill();
|
|
||||||
this.currentProcess = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const searchService = new SearchService();
|
|
||||||
|
|
@ -85,18 +85,6 @@ contextBridge.exposeInMainWorld("electronAPI", {
|
||||||
closeTerminal: (id: string) =>
|
closeTerminal: (id: string) =>
|
||||||
ipcRenderer.invoke("terminal:close", id) as Promise<boolean>,
|
ipcRenderer.invoke("terminal:close", id) as Promise<boolean>,
|
||||||
|
|
||||||
// Search operations
|
|
||||||
startSearch: (args: string[]) =>
|
|
||||||
ipcRenderer.invoke("search:start", args) as Promise<void>,
|
|
||||||
|
|
||||||
onSearchResult: (callback: (result: any) => void) => {
|
|
||||||
const listener = (_ev: any, result: any) => {
|
|
||||||
callback(result);
|
|
||||||
};
|
|
||||||
ipcRenderer.on("search:result", listener);
|
|
||||||
return () => ipcRenderer.removeListener("search:result", listener);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Terminal events (subscribe/unsubscribe)
|
// Terminal events (subscribe/unsubscribe)
|
||||||
onTerminalData: (id: string, callback: (data: string) => void) => {
|
onTerminalData: (id: string, callback: (data: string) => void) => {
|
||||||
terminalDataCallbacks.set(id, callback);
|
terminalDataCallbacks.set(id, callback);
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,6 @@ declare global {
|
||||||
language?: string;
|
language?: string;
|
||||||
root?: string;
|
root?: string;
|
||||||
}) => Promise<any>;
|
}) => Promise<any>;
|
||||||
|
|
||||||
startSearch: (args: string[]) => Promise<any>;
|
|
||||||
onSearchResult: (callback: any) => any;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue