mac-helper 0.4.0 → 0.6.0
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/lib/chrome.d.ts +16 -4
- package/lib/chrome.js +42 -12
- package/lib/finder.d.ts +6 -0
- package/lib/finder.js +32 -0
- package/lib/iterm.js +8 -6
- package/package.json +17 -15
- package/src/chrome.ts +32 -11
- package/src/finder.ts +35 -0
- package/src/iterm.ts +10 -8
package/lib/chrome.d.ts
CHANGED
|
@@ -2,7 +2,19 @@ export type ActiveTab = {
|
|
|
2
2
|
url: string;
|
|
3
3
|
title: string;
|
|
4
4
|
};
|
|
5
|
-
export declare
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
export declare enum BrowserAppName {
|
|
6
|
+
Chrome = "Google Chrome",
|
|
7
|
+
Brave = "Brave Browser"
|
|
8
|
+
}
|
|
9
|
+
export declare class ChromiumBrowserHelper {
|
|
10
|
+
appName: string;
|
|
11
|
+
constructor(appName: string);
|
|
12
|
+
isRunning: () => Promise<boolean>;
|
|
13
|
+
isFrontmost: () => Promise<boolean>;
|
|
14
|
+
getActiveTab: () => Promise<ActiveTab | undefined>;
|
|
15
|
+
}
|
|
16
|
+
export declare const Chrome: ChromiumBrowserHelper;
|
|
17
|
+
export declare const Brave: ChromiumBrowserHelper;
|
|
18
|
+
export declare function isChromiumAppRunning(appName?: string): Promise<boolean>;
|
|
19
|
+
export declare function getChromiumActiveTab(appName?: string): Promise<ActiveTab | undefined>;
|
|
20
|
+
export declare function getChromiumIsFrontmost(appName?: string): Promise<boolean>;
|
package/lib/chrome.js
CHANGED
|
@@ -1,16 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Chrome = void 0;
|
|
4
|
-
exports.
|
|
3
|
+
exports.Brave = exports.Chrome = exports.ChromiumBrowserHelper = exports.BrowserAppName = void 0;
|
|
4
|
+
exports.isChromiumAppRunning = isChromiumAppRunning;
|
|
5
|
+
exports.getChromiumActiveTab = getChromiumActiveTab;
|
|
6
|
+
exports.getChromiumIsFrontmost = getChromiumIsFrontmost;
|
|
5
7
|
const run_1 = require("@jxa/run");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
const app_1 = require("./app");
|
|
9
|
+
var BrowserAppName;
|
|
10
|
+
(function (BrowserAppName) {
|
|
11
|
+
BrowserAppName["Chrome"] = "Google Chrome";
|
|
12
|
+
BrowserAppName["Brave"] = "Brave Browser";
|
|
13
|
+
})(BrowserAppName || (exports.BrowserAppName = BrowserAppName = {}));
|
|
14
|
+
class ChromiumBrowserHelper {
|
|
15
|
+
appName;
|
|
16
|
+
constructor(appName) {
|
|
17
|
+
this.appName = appName;
|
|
18
|
+
}
|
|
19
|
+
isRunning = () => isChromiumAppRunning(this.appName);
|
|
20
|
+
isFrontmost = () => getChromiumIsFrontmost(this.appName);
|
|
21
|
+
getActiveTab = () => getChromiumActiveTab(this.appName);
|
|
22
|
+
}
|
|
23
|
+
exports.ChromiumBrowserHelper = ChromiumBrowserHelper;
|
|
24
|
+
exports.Chrome = new ChromiumBrowserHelper(BrowserAppName.Chrome);
|
|
25
|
+
exports.Brave = new ChromiumBrowserHelper(BrowserAppName.Brave);
|
|
26
|
+
/* #region implements */
|
|
27
|
+
function isChromiumAppRunning(appName = BrowserAppName.Chrome) {
|
|
28
|
+
return (0, app_1.isAppRunning)(appName);
|
|
29
|
+
}
|
|
30
|
+
async function getChromiumActiveTab(appName = BrowserAppName.Chrome) {
|
|
31
|
+
if (!(await isChromiumAppRunning(appName)))
|
|
32
|
+
return;
|
|
33
|
+
return await (0, run_1.run)((appName) => {
|
|
34
|
+
const app = Application(appName);
|
|
14
35
|
app.includeStandardAdditions = true;
|
|
15
36
|
const win = (app.windows() || []).find((w) => !w.minimized());
|
|
16
37
|
const tab = win?.activeTab();
|
|
@@ -18,6 +39,15 @@ async function getChromeActiveTab() {
|
|
|
18
39
|
url: tab?.url(),
|
|
19
40
|
title: tab?.title(),
|
|
20
41
|
};
|
|
21
|
-
});
|
|
42
|
+
}, appName);
|
|
43
|
+
}
|
|
44
|
+
async function getChromiumIsFrontmost(appName = BrowserAppName.Chrome) {
|
|
45
|
+
if (!isChromiumAppRunning(appName))
|
|
46
|
+
return false;
|
|
47
|
+
return await (0, run_1.run)((appName) => {
|
|
48
|
+
const app = Application(appName);
|
|
49
|
+
app.includeStandardAdditions = true;
|
|
50
|
+
return app.frontmost();
|
|
51
|
+
}, appName);
|
|
22
52
|
}
|
|
23
|
-
|
|
53
|
+
/* #endregion */
|
package/lib/finder.d.ts
CHANGED
|
@@ -20,3 +20,9 @@ export type QSpaceFileItem = {
|
|
|
20
20
|
name: () => string;
|
|
21
21
|
urlstr: () => string;
|
|
22
22
|
};
|
|
23
|
+
export declare function isRepresentPF(file: string): boolean;
|
|
24
|
+
export declare function isRepresentQS(file: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* 处理 $PF $QS, ignore case
|
|
27
|
+
*/
|
|
28
|
+
export declare function normalizeInputFileList(fileList: string[]): Promise<string[]>;
|
package/lib/finder.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.QSpace = exports.Finder = exports.PathFinder = void 0;
|
|
7
|
+
exports.isRepresentPF = isRepresentPF;
|
|
8
|
+
exports.isRepresentQS = isRepresentQS;
|
|
9
|
+
exports.normalizeInputFileList = normalizeInputFileList;
|
|
10
|
+
const node_os_1 = require("node:os");
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
4
12
|
const node_url_1 = require("node:url");
|
|
5
13
|
const run_1 = require("@jxa/run");
|
|
14
|
+
const es_toolkit_1 = require("es-toolkit");
|
|
15
|
+
const promise_map_1 = __importDefault(require("promise.map"));
|
|
6
16
|
const app_1 = require("./app");
|
|
7
17
|
/**
|
|
8
18
|
* `App` named epxorts
|
|
@@ -97,6 +107,28 @@ async function QSpace_allSelected() {
|
|
|
97
107
|
return urls.map((u) => (0, node_url_1.fileURLToPath)(u));
|
|
98
108
|
}
|
|
99
109
|
/* #endregion */
|
|
110
|
+
/* #region Top Level Helper */
|
|
111
|
+
function isRepresentPF(file) {
|
|
112
|
+
return /^\$?pf$/i.test(file);
|
|
113
|
+
}
|
|
114
|
+
function isRepresentQS(file) {
|
|
115
|
+
return /^\$?qs$/i.test(file);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* 处理 $PF $QS, ignore case
|
|
119
|
+
*/
|
|
120
|
+
async function normalizeInputFileList(fileList) {
|
|
121
|
+
return (0, es_toolkit_1.uniq)((await (0, promise_map_1.default)(fileList, async (f) => {
|
|
122
|
+
if (process.platform === 'darwin') {
|
|
123
|
+
if (isRepresentPF(f))
|
|
124
|
+
return await exports.PathFinder.allSelected();
|
|
125
|
+
if (isRepresentQS(f))
|
|
126
|
+
return await exports.QSpace.allSelected();
|
|
127
|
+
}
|
|
128
|
+
return node_path_1.default.resolve(f);
|
|
129
|
+
}, (0, node_os_1.availableParallelism)())).flat());
|
|
130
|
+
}
|
|
131
|
+
/* #endregion */
|
|
100
132
|
// ;(async () => {
|
|
101
133
|
// console.log(await getQSpaceSelected())
|
|
102
134
|
// })()
|
package/lib/iterm.js
CHANGED
|
@@ -4,14 +4,14 @@ exports.iTerm = void 0;
|
|
|
4
4
|
exports.runInIterm = runInIterm;
|
|
5
5
|
const run_1 = require("@jxa/run");
|
|
6
6
|
async function runInIterm(command, reuse = true) {
|
|
7
|
-
await (0, run_1.run)((command, reuse) => {
|
|
7
|
+
const result = await (0, run_1.run)((command, reuse) => {
|
|
8
8
|
const app = Application('iTerm');
|
|
9
9
|
app.includeStandardAdditions = true;
|
|
10
10
|
app.activate();
|
|
11
11
|
let usingSession;
|
|
12
12
|
// reuse when possible
|
|
13
13
|
if (reuse) {
|
|
14
|
-
const session = app.currentWindow()
|
|
14
|
+
const session = app.currentWindow()?.currentSession();
|
|
15
15
|
const isIdle = session?.isAtShellPrompt();
|
|
16
16
|
if (isIdle) {
|
|
17
17
|
usingSession = session;
|
|
@@ -20,13 +20,15 @@ async function runInIterm(command, reuse = true) {
|
|
|
20
20
|
// create new tab when necessary
|
|
21
21
|
if (!usingSession) {
|
|
22
22
|
const tab = app.createTabWithDefaultProfile(app.currentWindow);
|
|
23
|
-
usingSession = tab
|
|
24
|
-
}
|
|
25
|
-
if (!usingSession) {
|
|
26
|
-
return;
|
|
23
|
+
usingSession = tab?.currentSession(); // TODO: iterm2 updated, this code no longer works
|
|
27
24
|
}
|
|
25
|
+
if (!usingSession)
|
|
26
|
+
return 'no-session';
|
|
28
27
|
app.write(usingSession, { text: command });
|
|
29
28
|
}, command, reuse);
|
|
29
|
+
if (result === 'no-session') {
|
|
30
|
+
console.error('No iTerm session found');
|
|
31
|
+
}
|
|
30
32
|
}
|
|
31
33
|
exports.iTerm = {
|
|
32
34
|
run: runInIterm,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mac-helper",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"packageManager": "pnpm@10.
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264",
|
|
5
5
|
"description": "useful helper for macOS",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mac",
|
|
@@ -34,32 +34,34 @@
|
|
|
34
34
|
"test-cover": "vitest run --globals --coverage --testTimeout=30000",
|
|
35
35
|
"dev": "tsc -w --incremental",
|
|
36
36
|
"typecheck": "tsc --noEmit",
|
|
37
|
-
"build": "rm -rf lib; rm
|
|
37
|
+
"build": "rm -rf lib; rm *.tsbuildinfo; tsc",
|
|
38
38
|
"prepublishOnly": "pnpm test && pnpm build"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@jxa/run": "^1.4.0"
|
|
41
|
+
"@jxa/run": "^1.4.0",
|
|
42
|
+
"es-toolkit": "^1.44.0",
|
|
43
|
+
"promise.map": "^1.1.3"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
46
|
"@jxa/global-type": "^1.4.0",
|
|
45
47
|
"@jxa/sdef-to-dts": "^1.4.0",
|
|
46
48
|
"@jxa/types": "^1.4.0",
|
|
47
|
-
"@magicdawn/eslint-config": "^1.
|
|
49
|
+
"@magicdawn/eslint-config": "^1.6.1",
|
|
48
50
|
"@magicdawn/prettier-config": "^0.1.0",
|
|
49
51
|
"@types/fs-extra": "^11.0.4",
|
|
50
|
-
"@types/node": "^
|
|
51
|
-
"@vitest/coverage-v8": "^
|
|
52
|
-
"delay": "^
|
|
53
|
-
"eslint": "^9.
|
|
54
|
-
"eslint-config-prettier": "^10.1.
|
|
55
|
-
"fs-extra": "^11.3.
|
|
52
|
+
"@types/node": "^25.2.0",
|
|
53
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
54
|
+
"delay": "^7.0.0",
|
|
55
|
+
"eslint": "^9.39.2",
|
|
56
|
+
"eslint-config-prettier": "^10.1.8",
|
|
57
|
+
"fs-extra": "^11.3.3",
|
|
56
58
|
"husky": "^9.1.7",
|
|
57
59
|
"jxa-common-used": "^0.0.3",
|
|
58
|
-
"lint-staged": "^16.
|
|
59
|
-
"prettier": "^3.
|
|
60
|
+
"lint-staged": "^16.2.7",
|
|
61
|
+
"prettier": "^3.8.1",
|
|
60
62
|
"should": "^13.2.3",
|
|
61
|
-
"typescript": "^5.
|
|
62
|
-
"vitest": "^
|
|
63
|
+
"typescript": "^5.9.3",
|
|
64
|
+
"vitest": "^4.0.18"
|
|
63
65
|
},
|
|
64
66
|
"pnpm": {
|
|
65
67
|
"onlyBuiltDependencies": [
|
package/src/chrome.ts
CHANGED
|
@@ -1,26 +1,47 @@
|
|
|
1
1
|
import { run } from '@jxa/run'
|
|
2
2
|
import type { GoogleChrome } from 'jxa-common-used'
|
|
3
|
+
import { isAppRunning } from './app'
|
|
3
4
|
|
|
4
5
|
export type ActiveTab = { url: string; title: string }
|
|
5
6
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
7
|
+
export enum BrowserAppName {
|
|
8
|
+
Chrome = 'Google Chrome',
|
|
9
|
+
Brave = 'Brave Browser',
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
export class ChromiumBrowserHelper {
|
|
13
|
+
constructor(public appName: string) {}
|
|
14
|
+
isRunning = (): Promise<boolean> => isChromiumAppRunning(this.appName)
|
|
15
|
+
isFrontmost = (): Promise<boolean> => getChromiumIsFrontmost(this.appName)
|
|
16
|
+
getActiveTab = (): Promise<ActiveTab | undefined> => getChromiumActiveTab(this.appName)
|
|
17
|
+
}
|
|
16
18
|
|
|
19
|
+
export const Chrome = new ChromiumBrowserHelper(BrowserAppName.Chrome)
|
|
20
|
+
export const Brave = new ChromiumBrowserHelper(BrowserAppName.Brave)
|
|
21
|
+
|
|
22
|
+
/* #region implements */
|
|
23
|
+
export function isChromiumAppRunning(appName: string = BrowserAppName.Chrome): Promise<boolean> {
|
|
24
|
+
return isAppRunning(appName)
|
|
25
|
+
}
|
|
26
|
+
export async function getChromiumActiveTab(appName: string = BrowserAppName.Chrome): Promise<ActiveTab | undefined> {
|
|
27
|
+
if (!(await isChromiumAppRunning(appName))) return
|
|
28
|
+
return await run((appName: string) => {
|
|
29
|
+
const app = Application<GoogleChrome>(appName)
|
|
30
|
+
app.includeStandardAdditions = true
|
|
17
31
|
const win = (app.windows() || []).find((w) => !w.minimized())
|
|
18
32
|
const tab = win?.activeTab()
|
|
19
33
|
return {
|
|
20
34
|
url: tab?.url(),
|
|
21
35
|
title: tab?.title(),
|
|
22
36
|
}
|
|
23
|
-
})
|
|
37
|
+
}, appName)
|
|
24
38
|
}
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
export async function getChromiumIsFrontmost(appName: string = BrowserAppName.Chrome): Promise<boolean> {
|
|
40
|
+
if (!isChromiumAppRunning(appName)) return false
|
|
41
|
+
return await run((appName: string) => {
|
|
42
|
+
const app = Application<GoogleChrome>(appName)
|
|
43
|
+
app.includeStandardAdditions = true
|
|
44
|
+
return app.frontmost()
|
|
45
|
+
}, appName)
|
|
46
|
+
}
|
|
47
|
+
/* #endregion */
|
package/src/finder.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { availableParallelism } from 'node:os'
|
|
2
|
+
import path from 'node:path'
|
|
1
3
|
import { fileURLToPath } from 'node:url'
|
|
2
4
|
import { run as jxaRun } from '@jxa/run'
|
|
5
|
+
import { uniq } from 'es-toolkit'
|
|
6
|
+
import pmap from 'promise.map'
|
|
3
7
|
import { isAppRunning } from './app'
|
|
4
8
|
import type { PathFinder as PathFinderType } from 'jxa-common-used'
|
|
5
9
|
|
|
@@ -118,6 +122,37 @@ async function QSpace_allSelected() {
|
|
|
118
122
|
}
|
|
119
123
|
/* #endregion */
|
|
120
124
|
|
|
125
|
+
/* #region Top Level Helper */
|
|
126
|
+
export function isRepresentPF(file: string) {
|
|
127
|
+
return /^\$?pf$/i.test(file)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function isRepresentQS(file: string) {
|
|
131
|
+
return /^\$?qs$/i.test(file)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 处理 $PF $QS, ignore case
|
|
136
|
+
*/
|
|
137
|
+
export async function normalizeInputFileList(fileList: string[]) {
|
|
138
|
+
return uniq(
|
|
139
|
+
(
|
|
140
|
+
await pmap(
|
|
141
|
+
fileList,
|
|
142
|
+
async (f) => {
|
|
143
|
+
if (process.platform === 'darwin') {
|
|
144
|
+
if (isRepresentPF(f)) return await PathFinder.allSelected()
|
|
145
|
+
if (isRepresentQS(f)) return await QSpace.allSelected()
|
|
146
|
+
}
|
|
147
|
+
return path.resolve(f)
|
|
148
|
+
},
|
|
149
|
+
availableParallelism(),
|
|
150
|
+
)
|
|
151
|
+
).flat(),
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
/* #endregion */
|
|
155
|
+
|
|
121
156
|
// ;(async () => {
|
|
122
157
|
// console.log(await getQSpaceSelected())
|
|
123
158
|
// })()
|
package/src/iterm.ts
CHANGED
|
@@ -2,8 +2,9 @@ import { run } from '@jxa/run'
|
|
|
2
2
|
import type { iTerm2 } from 'jxa-common-used'
|
|
3
3
|
|
|
4
4
|
export async function runInIterm(command: string, reuse = true) {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
type RunResult = 'no-session' | undefined
|
|
6
|
+
const result: RunResult = await run(
|
|
7
|
+
(command, reuse): RunResult => {
|
|
7
8
|
const app = Application<iTerm2>('iTerm')
|
|
8
9
|
app.includeStandardAdditions = true
|
|
9
10
|
app.activate()
|
|
@@ -12,7 +13,7 @@ export async function runInIterm(command: string, reuse = true) {
|
|
|
12
13
|
|
|
13
14
|
// reuse when possible
|
|
14
15
|
if (reuse) {
|
|
15
|
-
const session: iTerm2.Session = app.currentWindow()
|
|
16
|
+
const session: iTerm2.Session | undefined = app.currentWindow()?.currentSession()
|
|
16
17
|
const isIdle = session?.isAtShellPrompt()
|
|
17
18
|
if (isIdle) {
|
|
18
19
|
usingSession = session
|
|
@@ -22,18 +23,19 @@ export async function runInIterm(command: string, reuse = true) {
|
|
|
22
23
|
// create new tab when necessary
|
|
23
24
|
if (!usingSession) {
|
|
24
25
|
const tab = app.createTabWithDefaultProfile(app.currentWindow)
|
|
25
|
-
usingSession = tab
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!usingSession) {
|
|
29
|
-
return
|
|
26
|
+
usingSession = tab?.currentSession() // TODO: iterm2 updated, this code no longer works
|
|
30
27
|
}
|
|
31
28
|
|
|
29
|
+
if (!usingSession) return 'no-session'
|
|
32
30
|
app.write(usingSession, { text: command })
|
|
33
31
|
},
|
|
34
32
|
command,
|
|
35
33
|
reuse,
|
|
36
34
|
)
|
|
35
|
+
|
|
36
|
+
if (result === 'no-session') {
|
|
37
|
+
console.error('No iTerm session found')
|
|
38
|
+
}
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
export const iTerm = {
|